@qredence/fleet 0.5.11 → 0.6.1
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/web/client/assets/action-swap-roll-COzQ86wm.js +1 -0
- package/dist/web/client/assets/agent-activity-svETLf_5.js +1 -0
- package/dist/web/client/assets/agent-disclosure-DAMuuGcM.js +1 -0
- package/dist/web/client/assets/analytics-stub-B6zGMuSV.js +1 -0
- package/dist/web/client/assets/{artifacts-panel-CQmFEF_H.js → artifacts-panel-HVjqBMyx.js} +1 -1
- package/dist/web/client/assets/button-C5wFDY5_.js +1 -0
- package/dist/web/client/assets/card-DA3Vnqay.js +1 -0
- package/dist/web/client/assets/{chat-yh02zgA7.js → chat-BhYseKd6.js} +7 -7
- package/dist/web/client/assets/{chat-command-palette-CmHTS3rs.js → chat-command-palette-LILDO_vG.js} +1 -1
- package/dist/web/client/assets/{citations-C_tPOJE_.js → citations-BPv8HIpf.js} +2 -2
- package/dist/web/client/assets/command-PhicLCoO.js +1 -0
- package/dist/web/client/assets/dialog-pBGUjAQ7.js +1 -0
- package/dist/web/client/assets/fleet-message-queue-fbYYwMj0.js +1 -0
- package/dist/web/client/assets/{fleet-pi-tool-renderer-BEDIO3al.js → fleet-pi-tool-renderer-BRgNnmaJ.js} +28 -28
- package/dist/web/client/assets/fleet-reasoning-panel-CjA2dwUJ.js +1 -0
- package/dist/web/client/assets/{fork-picker-dialog-ByBOGVsa.js → fork-picker-dialog-B7NNpVmW.js} +1 -1
- package/dist/web/client/assets/globals-CuIiqOTg.css +2 -0
- package/dist/web/client/assets/horizontal-resize-Cp3iHMH7.js +1 -0
- package/dist/web/client/assets/index-CSGplyr_.js +12 -0
- package/dist/web/client/assets/{input-0wwjWjKq.js → input-PcdubeKn.js} +1 -1
- package/dist/web/client/assets/input-group-C2HJEZvl.js +1 -0
- package/dist/web/client/assets/ipython-tool-CyuMOxz1.js +3 -0
- package/dist/web/client/assets/{markdown-code-CuQcR3UO.js → markdown-code-xNyjdZ4g.js} +1 -1
- package/dist/web/client/assets/{markdown-DInPmRUG.js → markdown-lvexwooo.js} +2 -2
- package/dist/web/client/assets/{model-selector-list-DsKTuAgS.js → model-selector-list-CoXX358G.js} +1 -1
- package/dist/web/client/assets/{notify-DgMKgZZW.js → notify-DxL0VD7Z.js} +1 -1
- package/dist/web/client/assets/openui-renderer-TLNe5e_Q.js +378 -0
- package/dist/web/client/assets/pencil-DcUwsKLn.js +1 -0
- package/dist/web/client/assets/prompt-input-fwP8TsgQ.js +1 -0
- package/dist/web/client/assets/{prompt-suggestions-Cc--lSNR.js → prompt-suggestions-BlGXmWS7.js} +1 -1
- package/dist/web/client/assets/provider-catalog-DYMFdbKc.js +1 -0
- package/dist/web/client/assets/provider-label-B4q5mI65.js +1 -0
- package/dist/web/client/assets/{repl-panel-DsPX04Xr.js → repl-panel-C5om8MGU.js} +1 -1
- package/dist/web/client/assets/{right-panel-registry-DewpBWHM.js → right-panel-registry-BBlxLxnx.js} +2 -2
- package/dist/web/client/assets/routes-XGsAIqBJ.js +16 -0
- package/dist/web/client/assets/settings-dialog-BSBasR3o.js +2 -0
- package/dist/web/client/assets/{subagent-chat-panel-DkVUumrP.js → subagent-chat-panel-oeLDPDAK.js} +1 -1
- package/dist/web/client/assets/{subagent-transcript-D8wmQxXe.js → subagent-transcript-DaVHjNUH.js} +1 -1
- package/dist/web/client/assets/{subagents-panel-BMp2Ego0.js → subagents-panel-D_aVgSCi.js} +1 -1
- package/dist/web/client/assets/surfaces-BhAXz9So.js +1 -0
- package/dist/web/client/assets/{switch-9rTeg6J6.js → switch-WhXeJNNY.js} +1 -1
- package/dist/web/client/assets/{toast-Bt9p2OL4.js → toast-D3c9XeGe.js} +1 -1
- package/dist/web/client/assets/{tool-result-DfnPN0FQ.js → tool-result-Cki8WUNc.js} +3 -3
- package/dist/web/client/assets/virtualized-turn-list-CdMa-ydT.js +6 -0
- package/dist/web/client/assets/workspace-panel-77bDbprs.js +1 -0
- package/dist/web/client/bundle-budget.json +6 -6
- package/dist/web/launcher.mjs +10 -1
- package/dist/web/server/{_tanstack-start-manifest_v-po4woX6g-AUGCOEZ2.js → _tanstack-start-manifest_v-0L7fqnH4-KMVGUFE4.js} +25 -24
- package/dist/web/server/{agent-activity-CS2rbF_C-A3R26CYH.js → agent-activity-BuEE6iVw-CDZLK4D2.js} +4 -4
- package/dist/web/server/{artifacts-panel-8GGUCtOd-X5TNKTY2.js → artifacts-panel-D3ySO--V-XSL53CXL.js} +18 -18
- package/dist/web/server/{chat-command-palette-Dgl5tqWn-72LLEWUD.js → chat-command-palette-kAbXhWVg-TJWXH2WW.js} +9 -9
- package/dist/web/server/{chunk-O4OTWWPF.js → chunk-2DDWXTVG.js} +5 -5
- package/dist/web/server/{chunk-MIW4LJTV.js → chunk-2JHTYWD5.js} +15 -23
- package/dist/web/server/{chunk-7MDZVLIY.js → chunk-3TIMGWWI.js} +1 -2
- package/dist/web/server/{chunk-AGFRJQZ7.js → chunk-4WBFCB4O.js} +257 -257
- package/dist/web/server/{chunk-P6UMR32I.js → chunk-5UCAJBAH.js} +4 -4
- package/dist/web/server/{chunk-BXWAUTTH.js → chunk-D27LRYVT.js} +42 -42
- package/dist/web/server/{chunk-YXXRP3NS.js → chunk-DLUZFOG3.js} +5 -5
- package/dist/web/server/{chunk-K3BXQG3N.js → chunk-EBG3XFGQ.js} +60 -60
- package/dist/web/server/{chunk-2ATMSG7U.js → chunk-EJEPDVK6.js} +3 -3
- package/dist/web/server/{chunk-IJPCV6DH.js → chunk-FYDQK6UX.js} +1 -1
- package/dist/web/server/{chunk-WKV2Z4KO.js → chunk-HF7DG7PC.js} +74 -74
- package/dist/web/server/{chunk-WYL2DW5R.js → chunk-JTCCQZLN.js} +2 -2
- package/dist/web/server/{chunk-UAPNEWCA.js → chunk-KP2PNDGL.js} +6 -6
- package/dist/web/server/chunk-M5RSPNYN.js +22 -0
- package/dist/web/server/{chunk-7SR6WDM2.js → chunk-MNBGB2SP.js} +2 -2
- package/dist/web/server/{chunk-HSJMLO36.js → chunk-MNPHMZU7.js} +3 -3
- package/dist/web/server/{chunk-JQDLJ7KI.js → chunk-NGCQJ33Y.js} +1134 -1134
- package/dist/web/server/{chunk-7SD2ZSEA.js → chunk-NIDBN7BQ.js} +1 -1
- package/dist/web/server/{chunk-ZJFA4F5X.js → chunk-NIZBFVJF.js} +2 -2
- package/dist/web/server/{chunk-P7H2OPKF.js → chunk-NJ4QEZHK.js} +11 -4
- package/dist/web/server/{chunk-WM4PUT6M.js → chunk-NNKJTKOQ.js} +234 -234
- package/dist/web/server/{chunk-N6NOTURM.js → chunk-NWDI3OWB.js} +4 -4
- package/dist/web/server/{chunk-ABBWBBSS.js → chunk-O3HDELZ2.js} +74826 -74825
- package/dist/web/server/{chunk-GGT2ZKDB.js → chunk-PLYZ7P2Y.js} +11 -155
- package/dist/web/server/chunk-PTCKOR23.js +39 -0
- package/dist/web/server/{chunk-RNOJACWQ.js → chunk-QFRCJWQQ.js} +7 -7
- package/dist/web/server/{chunk-NXJ32VFR.js → chunk-QIULBRTU.js} +13 -13
- package/dist/web/server/{chunk-XKKXXG6N.js → chunk-RIP3PBWT.js} +3 -3
- package/dist/web/server/{chunk-YKVGQBZA.js → chunk-S5LFXXDY.js} +625 -622
- package/dist/web/server/{chunk-XLNCWZMZ.js → chunk-UCUFC553.js} +3 -1
- package/dist/web/server/{chunk-KOUEJ3NU.js → chunk-UL2725KQ.js} +3 -3
- package/dist/web/server/{chunk-HFQTI7AX.js → chunk-VPKX7QRU.js} +3 -3
- package/dist/web/server/{chunk-LZ4Q5KUJ.js → chunk-WNCAL4HN.js} +133 -133
- package/dist/web/server/{chunk-C5X6G26O.js → chunk-XIB6XNUX.js} +436 -436
- package/dist/web/server/{chunk-JUROEEWM.js → chunk-YGYOBX7G.js} +82 -4
- package/dist/web/server/{chunk-WILCIZYU.js → chunk-ZIFSJ3HQ.js} +626 -626
- package/dist/web/server/fleet-message-queue-D_w8lSeY-T3HB7HVQ.js +152 -0
- package/dist/web/server/{fleet-pi-tool-renderer-umKunT3K-O4GBH35V.js → fleet-pi-tool-renderer-qwc-qZFq-4U556N5Q.js} +12 -12
- package/dist/web/server/{fleet-reasoning-panel-BxC2COxi-GPLMQSTT.js → fleet-reasoning-panel-DG_vuvv0-NCZWEEIT.js} +26 -26
- package/dist/web/server/{fleet-subagent-list-CpSYzCIq-JDH2LHSS.js → fleet-subagent-list-BGb0PjhF-2X67FMUV.js} +1 -1
- package/dist/web/server/{fleet-tool-timeline-IB36_PB2-XJENTO6I.js → fleet-tool-timeline-D6yM4ZMz-ZSFVRRRI.js} +1 -1
- package/dist/web/server/{fork-picker-dialog-DlINz9UQ-UWIXFDJX.js → fork-picker-dialog-Ds6Tgtu3-DIBWN7MV.js} +5 -5
- package/dist/web/server/{model-selector-list-OYnzNbyu-HBGCNF2L.js → model-selector-list-DxeGZoD2-P6S6FSJH.js} +9 -9
- package/dist/web/server/{openui-renderer-Cj7kfqyL-EKJ6JTTQ.js → openui-renderer-MKFv6LlH-MDRSVFEY.js} +11 -11
- package/dist/web/server/{prompt-suggestions-D4AEEY7K-RZSP7PWV.js → prompt-suggestions-BOItmGnD-YQA7RHLG.js} +2 -2
- package/dist/web/server/{repl-panel-D5KsoJik-BQKO53JO.js → repl-panel-CuyF8wt5-CHDT2Q3N.js} +2 -2
- package/dist/web/server/{router-Ci1wxI7I-E2AYMNON.js → router-Dg72SESP-PCWKLFRG.js} +1239 -470
- package/dist/web/server/{routes-CRpm9-Sa-IYK6MUJO.js → routes-BGrVtPYF-SURPAJN6.js} +5781 -5588
- package/dist/web/server/server.js +2 -2
- package/dist/web/server/{settings-dialog-BvkgNflv-GPJ6COQO.js → settings-dialog-CK0FJlTg-HZRBAXDZ.js} +1577 -1264
- package/dist/web/server/{subagent-chat-panel-CMuvW9Sd-M5TEEGQW.js → subagent-chat-panel-gzamnTgK-PQ2TLLJF.js} +21 -21
- package/dist/web/server/{subagents-panel-DgfB6_Yy-4INEPE3Y.js → subagents-panel-Berjd7HJ-EI5ZKC6V.js} +20 -20
- package/dist/web/server/{workspace-panel-bpwj-Veu-Q2CEJMN4.js → workspace-panel-CBBa_3UO-B4PPFPMA.js} +46 -21
- package/package.json +1 -1
- package/dist/web/client/assets/action-swap-roll-BB8DFMuf.js +0 -1
- package/dist/web/client/assets/agent-activity-CwMDU7aP.js +0 -1
- package/dist/web/client/assets/agent-disclosure-B8SnhQXL.js +0 -1
- package/dist/web/client/assets/analytics-stub-Cas1He0w.js +0 -1
- package/dist/web/client/assets/button-BR2WWrFo.js +0 -1
- package/dist/web/client/assets/card-BKl76a3R.js +0 -1
- package/dist/web/client/assets/command-DPfiaYUL.js +0 -1
- package/dist/web/client/assets/dialog-BEZuZhzk.js +0 -1
- package/dist/web/client/assets/fleet-message-queue-DUz6Hfrf.js +0 -1
- package/dist/web/client/assets/fleet-reasoning-panel-CbkO7u-v.js +0 -1
- package/dist/web/client/assets/globals-B_I1Eq1u.css +0 -2
- package/dist/web/client/assets/horizontal-resize-qK6eRhIG.js +0 -1
- package/dist/web/client/assets/index-C1zOjrMK.js +0 -12
- package/dist/web/client/assets/input-group-BFDsCVS9.js +0 -1
- package/dist/web/client/assets/ipython-tool-ldJ9F1Cw.js +0 -3
- package/dist/web/client/assets/openui-renderer-J3dhPpL4.js +0 -378
- package/dist/web/client/assets/prompt-input-qPIXZ-Rb.js +0 -1
- package/dist/web/client/assets/provider-catalog-D8G66gwc.js +0 -1
- package/dist/web/client/assets/provider-label-Dpr7djG9.js +0 -1
- package/dist/web/client/assets/routes-vNkVToAF.js +0 -16
- package/dist/web/client/assets/settings-dialog-B-v4me3Y.js +0 -1
- package/dist/web/client/assets/surfaces-DI-U-_2a.js +0 -1
- package/dist/web/client/assets/virtualized-turn-list-DMJENRY0.js +0 -6
- package/dist/web/client/assets/workspace-panel-G6yMpKJ8.js +0 -1
- package/dist/web/server/chunk-QK4CHLVV.js +0 -17
- package/dist/web/server/fleet-message-queue-j0DCU5Xy-5HKBHMPV.js +0 -75
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
HIT_AREA_EXPAND_CLASS,
|
|
13
13
|
HIT_AREA_EXPAND_DENSE_CLASS,
|
|
14
14
|
PROVIDER_METADATA,
|
|
15
|
-
Pencil,
|
|
16
15
|
ProviderBrandIcon,
|
|
17
16
|
Settings,
|
|
18
17
|
Spinner,
|
|
@@ -25,7 +24,7 @@ import {
|
|
|
25
24
|
useHoverInteractionSharedState,
|
|
26
25
|
useHoverReferenceInteraction,
|
|
27
26
|
usePopupHandleStore
|
|
28
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-2JHTYWD5.js";
|
|
29
28
|
import {
|
|
30
29
|
UI_PREFERENCES_KEY,
|
|
31
30
|
isModelPatternEnabled,
|
|
@@ -36,6 +35,9 @@ import {
|
|
|
36
35
|
import {
|
|
37
36
|
MessageSquare
|
|
38
37
|
} from "./chunk-GL6HWDJB.js";
|
|
38
|
+
import {
|
|
39
|
+
Pencil
|
|
40
|
+
} from "./chunk-M5RSPNYN.js";
|
|
39
41
|
import {
|
|
40
42
|
Keyboard,
|
|
41
43
|
Monitor,
|
|
@@ -54,11 +56,11 @@ import {
|
|
|
54
56
|
} from "./chunk-OKL5ZRVB.js";
|
|
55
57
|
import {
|
|
56
58
|
notify
|
|
57
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-JTCCQZLN.js";
|
|
58
60
|
import {
|
|
59
61
|
FloatingPortalLite,
|
|
60
62
|
Info
|
|
61
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-UL2725KQ.js";
|
|
62
64
|
import "./chunk-UCA4WN66.js";
|
|
63
65
|
import {
|
|
64
66
|
Eye
|
|
@@ -80,8 +82,9 @@ import {
|
|
|
80
82
|
InputGroup,
|
|
81
83
|
InputGroupAddon,
|
|
82
84
|
InputGroupButton,
|
|
83
|
-
InputGroupInput
|
|
84
|
-
|
|
85
|
+
InputGroupInput,
|
|
86
|
+
Textarea
|
|
87
|
+
} from "./chunk-NJ4QEZHK.js";
|
|
85
88
|
import {
|
|
86
89
|
Search
|
|
87
90
|
} from "./chunk-JIULUYHT.js";
|
|
@@ -102,7 +105,7 @@ import {
|
|
|
102
105
|
FieldGroup,
|
|
103
106
|
FieldLabel,
|
|
104
107
|
Switch
|
|
105
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-KP2PNDGL.js";
|
|
106
109
|
import {
|
|
107
110
|
Select,
|
|
108
111
|
clamp,
|
|
@@ -114,7 +117,7 @@ import {
|
|
|
114
117
|
useDirection,
|
|
115
118
|
usePositioner,
|
|
116
119
|
useRender
|
|
117
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-NNKJTKOQ.js";
|
|
118
121
|
import {
|
|
119
122
|
isCustomProviderId,
|
|
120
123
|
isNamedOccInstanceId,
|
|
@@ -123,7 +126,7 @@ import {
|
|
|
123
126
|
import "./chunk-WWJF4RO2.js";
|
|
124
127
|
import {
|
|
125
128
|
Input
|
|
126
|
-
} from "./chunk-
|
|
129
|
+
} from "./chunk-5UCAJBAH.js";
|
|
127
130
|
import {
|
|
128
131
|
Dialog,
|
|
129
132
|
DialogBackdrop,
|
|
@@ -157,7 +160,7 @@ import {
|
|
|
157
160
|
usePopupRootStore,
|
|
158
161
|
useSurface,
|
|
159
162
|
useTriggerDataForwarding
|
|
160
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-4WBFCB4O.js";
|
|
161
164
|
import {
|
|
162
165
|
Button,
|
|
163
166
|
POPUP_COLLISION_AVOIDANCE,
|
|
@@ -178,7 +181,7 @@ import {
|
|
|
178
181
|
ownerDocument,
|
|
179
182
|
useTimeout,
|
|
180
183
|
webkit
|
|
181
|
-
} from "./chunk-
|
|
184
|
+
} from "./chunk-WNCAL4HN.js";
|
|
182
185
|
import {
|
|
183
186
|
Check
|
|
184
187
|
} from "./chunk-4QD4PCVP.js";
|
|
@@ -186,7 +189,7 @@ import "./chunk-S3PQ6HKH.js";
|
|
|
186
189
|
import {
|
|
187
190
|
useBaseUiId,
|
|
188
191
|
useValueAsRef
|
|
189
|
-
} from "./chunk-
|
|
192
|
+
} from "./chunk-MNBGB2SP.js";
|
|
190
193
|
import {
|
|
191
194
|
X
|
|
192
195
|
} from "./chunk-JBLHIEVG.js";
|
|
@@ -209,8 +212,10 @@ import {
|
|
|
209
212
|
useOpenChangeComplete,
|
|
210
213
|
useRenderElement,
|
|
211
214
|
useStableCallback
|
|
212
|
-
} from "./chunk-
|
|
213
|
-
import
|
|
215
|
+
} from "./chunk-XIB6XNUX.js";
|
|
216
|
+
import {
|
|
217
|
+
Plug
|
|
218
|
+
} from "./chunk-AHTO6GDS.js";
|
|
214
219
|
import "./chunk-EAJTWMK5.js";
|
|
215
220
|
import "./chunk-HFQZLPU2.js";
|
|
216
221
|
import {
|
|
@@ -223,7 +228,7 @@ import "./chunk-JDCCC7A7.js";
|
|
|
223
228
|
import "./chunk-L547YHC4.js";
|
|
224
229
|
import "./chunk-MLKGABMK.js";
|
|
225
230
|
|
|
226
|
-
// web/app/dist/server/assets/settings-dialog-
|
|
231
|
+
// web/app/dist/server/assets/settings-dialog-CK0FJlTg.js
|
|
227
232
|
import * as React$1 from "react";
|
|
228
233
|
import { useCallback as useCallback2, useEffect as useEffect2, useId, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
229
234
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -717,6 +722,46 @@ function useFocus(context, props = {}) {
|
|
|
717
722
|
trigger: reference
|
|
718
723
|
} : {}, [enabled, reference]);
|
|
719
724
|
}
|
|
725
|
+
function Breadcrumb({ className, ...props }) {
|
|
726
|
+
return /* @__PURE__ */ jsx("nav", {
|
|
727
|
+
"aria-label": "breadcrumb",
|
|
728
|
+
"data-slot": "breadcrumb",
|
|
729
|
+
className: cn(className),
|
|
730
|
+
...props
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
function BreadcrumbList({ className, ...props }) {
|
|
734
|
+
return /* @__PURE__ */ jsx("ol", {
|
|
735
|
+
"data-slot": "breadcrumb-list",
|
|
736
|
+
className: cn("flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground", className),
|
|
737
|
+
...props
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
function BreadcrumbItem({ className, ...props }) {
|
|
741
|
+
return /* @__PURE__ */ jsx("li", {
|
|
742
|
+
"data-slot": "breadcrumb-item",
|
|
743
|
+
className: cn("inline-flex items-center gap-1", className),
|
|
744
|
+
...props
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
function BreadcrumbPage({ className, ...props }) {
|
|
748
|
+
return /* @__PURE__ */ jsx("span", {
|
|
749
|
+
"data-slot": "breadcrumb-page",
|
|
750
|
+
"aria-current": "page",
|
|
751
|
+
className: cn("font-normal text-foreground", className),
|
|
752
|
+
...props
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
function BreadcrumbSeparator({ children, className, ...props }) {
|
|
756
|
+
return /* @__PURE__ */ jsx("li", {
|
|
757
|
+
"data-slot": "breadcrumb-separator",
|
|
758
|
+
role: "presentation",
|
|
759
|
+
"aria-hidden": "true",
|
|
760
|
+
className: cn("[&>svg]:size-3.5", className),
|
|
761
|
+
...props,
|
|
762
|
+
children: children ?? /* @__PURE__ */ jsx(ChevronRight, {})
|
|
763
|
+
});
|
|
764
|
+
}
|
|
720
765
|
var ScrollAreaRootContext = /* @__PURE__ */ React$1.createContext(void 0);
|
|
721
766
|
function useScrollAreaRootContext() {
|
|
722
767
|
const context = React$1.useContext(ScrollAreaRootContext);
|
|
@@ -1409,46 +1454,6 @@ function ScrollBar({ className, orientation = "vertical", ...props }) {
|
|
|
1409
1454
|
})
|
|
1410
1455
|
});
|
|
1411
1456
|
}
|
|
1412
|
-
function Breadcrumb({ className, ...props }) {
|
|
1413
|
-
return /* @__PURE__ */ jsx("nav", {
|
|
1414
|
-
"aria-label": "breadcrumb",
|
|
1415
|
-
"data-slot": "breadcrumb",
|
|
1416
|
-
className: cn(className),
|
|
1417
|
-
...props
|
|
1418
|
-
});
|
|
1419
|
-
}
|
|
1420
|
-
function BreadcrumbList({ className, ...props }) {
|
|
1421
|
-
return /* @__PURE__ */ jsx("ol", {
|
|
1422
|
-
"data-slot": "breadcrumb-list",
|
|
1423
|
-
className: cn("flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground", className),
|
|
1424
|
-
...props
|
|
1425
|
-
});
|
|
1426
|
-
}
|
|
1427
|
-
function BreadcrumbItem({ className, ...props }) {
|
|
1428
|
-
return /* @__PURE__ */ jsx("li", {
|
|
1429
|
-
"data-slot": "breadcrumb-item",
|
|
1430
|
-
className: cn("inline-flex items-center gap-1", className),
|
|
1431
|
-
...props
|
|
1432
|
-
});
|
|
1433
|
-
}
|
|
1434
|
-
function BreadcrumbPage({ className, ...props }) {
|
|
1435
|
-
return /* @__PURE__ */ jsx("span", {
|
|
1436
|
-
"data-slot": "breadcrumb-page",
|
|
1437
|
-
"aria-current": "page",
|
|
1438
|
-
className: cn("font-normal text-foreground", className),
|
|
1439
|
-
...props
|
|
1440
|
-
});
|
|
1441
|
-
}
|
|
1442
|
-
function BreadcrumbSeparator({ children, className, ...props }) {
|
|
1443
|
-
return /* @__PURE__ */ jsx("li", {
|
|
1444
|
-
"data-slot": "breadcrumb-separator",
|
|
1445
|
-
role: "presentation",
|
|
1446
|
-
"aria-hidden": "true",
|
|
1447
|
-
className: cn("[&>svg]:size-3.5", className),
|
|
1448
|
-
...props,
|
|
1449
|
-
children: children ?? /* @__PURE__ */ jsx(ChevronRight, {})
|
|
1450
|
-
});
|
|
1451
|
-
}
|
|
1452
1457
|
var MOBILE_BREAKPOINT = 768;
|
|
1453
1458
|
function useIsMobile() {
|
|
1454
1459
|
const [isMobile, setIsMobile] = React$1.useState(void 0);
|
|
@@ -2248,40 +2253,42 @@ function SidebarMenuButton({ render, isActive = false, variant = "default", size
|
|
|
2248
2253
|
...tooltip
|
|
2249
2254
|
})] });
|
|
2250
2255
|
}
|
|
2251
|
-
|
|
2252
|
-
{
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
{
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2256
|
+
function RowSurface({ className, interactive, padding, tone, ...props }) {
|
|
2257
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2258
|
+
className: cn(fleetPiRowSurface({
|
|
2259
|
+
interactive,
|
|
2260
|
+
padding,
|
|
2261
|
+
tone
|
|
2262
|
+
}), className),
|
|
2263
|
+
...props
|
|
2264
|
+
});
|
|
2265
|
+
}
|
|
2266
|
+
function ItemRow({ icon, title, subtitle, trailing, className, interactive = true, tone = "default" }) {
|
|
2267
|
+
return /* @__PURE__ */ jsxs(RowSurface, {
|
|
2268
|
+
tone,
|
|
2269
|
+
padding: "md",
|
|
2270
|
+
interactive,
|
|
2271
|
+
className: cn("items-center gap-3", className),
|
|
2272
|
+
children: [
|
|
2273
|
+
icon ? /* @__PURE__ */ jsx("div", {
|
|
2274
|
+
className: "flex size-8 shrink-0 items-center justify-center rounded-md border border-border/40 bg-background/60 text-foreground/70",
|
|
2275
|
+
children: icon
|
|
2276
|
+
}) : null,
|
|
2277
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2278
|
+
className: "min-w-0 flex-1",
|
|
2279
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2280
|
+
className: "truncate text-sm font-medium text-foreground",
|
|
2281
|
+
children: title
|
|
2282
|
+
}), subtitle ? /* @__PURE__ */ jsx("div", {
|
|
2283
|
+
className: "mt-0.5 truncate text-xs text-muted-foreground",
|
|
2284
|
+
children: subtitle
|
|
2285
|
+
}) : null]
|
|
2286
|
+
}),
|
|
2287
|
+
trailing ? /* @__PURE__ */ jsx("div", {
|
|
2288
|
+
className: "flex shrink-0 items-center gap-1.5",
|
|
2289
|
+
children: trailing
|
|
2290
|
+
}) : null
|
|
2291
|
+
]
|
|
2285
2292
|
});
|
|
2286
2293
|
}
|
|
2287
2294
|
function SettingsPane({ actions, children, description, title }) {
|
|
@@ -2331,444 +2338,62 @@ function SettingsCommitActions({ dirty, disabled: disabled2, onRevert, onSave, s
|
|
|
2331
2338
|
}) : /* @__PURE__ */ jsx(Save, { "data-icon": "inline-start" }), "Commit"]
|
|
2332
2339
|
})] });
|
|
2333
2340
|
}
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
const invalid = isFieldInvalid(value, attemptedSave, required);
|
|
2340
|
-
return /* @__PURE__ */ jsxs(Field, {
|
|
2341
|
-
"data-invalid": invalid || void 0,
|
|
2342
|
-
children: [/* @__PURE__ */ jsx(FieldLabel, {
|
|
2343
|
-
htmlFor: controlId,
|
|
2344
|
-
children: label
|
|
2345
|
-
}), /* @__PURE__ */ jsxs(InputGroup, { children: [
|
|
2346
|
-
/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
2347
|
-
align: "inline-start",
|
|
2348
|
-
children: /* @__PURE__ */ jsx(Lock, {})
|
|
2349
|
-
}),
|
|
2350
|
-
/* @__PURE__ */ jsx(InputGroupInput, {
|
|
2351
|
-
id: controlId,
|
|
2352
|
-
type: showPassword ? "text" : "password",
|
|
2353
|
-
placeholder,
|
|
2354
|
-
value,
|
|
2355
|
-
onChange: (event) => onChange(event.target.value),
|
|
2356
|
-
"aria-label": label,
|
|
2357
|
-
"aria-invalid": invalid || void 0
|
|
2358
|
-
}),
|
|
2359
|
-
/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
2360
|
-
align: "inline-end",
|
|
2361
|
-
children: /* @__PURE__ */ jsx(InputGroupButton, {
|
|
2362
|
-
size: "icon-xs",
|
|
2363
|
-
className: cn(HIT_AREA_EXPAND_CLASS, "transition-[background-color,transform] duration-150 active:scale-[0.96]"),
|
|
2364
|
-
"aria-label": showPassword ? "Hide value" : "Show value",
|
|
2365
|
-
onClick: onToggleVisibility,
|
|
2366
|
-
children: showPassword ? /* @__PURE__ */ jsx(EyeOff, {}) : /* @__PURE__ */ jsx(Eye, {})
|
|
2367
|
-
})
|
|
2368
|
-
})
|
|
2369
|
-
] })]
|
|
2370
|
-
});
|
|
2371
|
-
}
|
|
2372
|
-
function TextCredentialField({ attemptedSave, icon: Icon, inputType = "text", label, onChange, placeholder, required = true, value }) {
|
|
2373
|
-
const controlId = useId();
|
|
2374
|
-
const invalid = isFieldInvalid(value, attemptedSave, required);
|
|
2375
|
-
return /* @__PURE__ */ jsxs(Field, {
|
|
2376
|
-
"data-invalid": invalid || void 0,
|
|
2377
|
-
children: [/* @__PURE__ */ jsx(FieldLabel, {
|
|
2378
|
-
htmlFor: controlId,
|
|
2379
|
-
children: label
|
|
2380
|
-
}), /* @__PURE__ */ jsxs(InputGroup, { children: [/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
2381
|
-
align: "inline-start",
|
|
2382
|
-
children: /* @__PURE__ */ jsx(Icon, {})
|
|
2383
|
-
}), /* @__PURE__ */ jsx(InputGroupInput, {
|
|
2384
|
-
id: controlId,
|
|
2385
|
-
type: inputType,
|
|
2386
|
-
placeholder,
|
|
2387
|
-
value,
|
|
2388
|
-
onChange: (event) => onChange(event.target.value),
|
|
2389
|
-
"aria-label": label,
|
|
2390
|
-
"aria-invalid": invalid || void 0
|
|
2391
|
-
})] })]
|
|
2341
|
+
var OAUTH_POLL_MS = 1500;
|
|
2342
|
+
var STALE_LOGIN_ERROR = "Unknown or expired OAuth login";
|
|
2343
|
+
function delay(ms) {
|
|
2344
|
+
return new Promise((resolve) => {
|
|
2345
|
+
setTimeout(resolve, ms);
|
|
2392
2346
|
});
|
|
2393
2347
|
}
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
];
|
|
2416
|
-
function ProviderCredentialFields({ attemptedSave, apiKey, api, baseUrl, modelId, models, displayName, isCustom, onApiKeyChange, onApiChange, onBaseUrlChange, onModelIdChange, onModelsChange, onDisplayNameChange, onTogglePassword, openAiChat, placeholder, showPassword }) {
|
|
2417
|
-
const showApiSelector = isCustom && onApiChange;
|
|
2418
|
-
const showMultiModels = isCustom && onModelsChange;
|
|
2419
|
-
return /* @__PURE__ */ jsxs(FieldGroup, {
|
|
2420
|
-
className: "gap-2",
|
|
2421
|
-
children: [
|
|
2422
|
-
(openAiChat || isCustom) && onDisplayNameChange ? /* @__PURE__ */ jsx(TextCredentialField, {
|
|
2423
|
-
attemptedSave,
|
|
2424
|
-
icon: Tag,
|
|
2425
|
-
label: "Provider name",
|
|
2426
|
-
placeholder: OPENAI_CHAT_NAME_PLACEHOLDER,
|
|
2427
|
-
value: displayName ?? "",
|
|
2428
|
-
onChange: onDisplayNameChange
|
|
2429
|
-
}) : null,
|
|
2430
|
-
showApiSelector ? /* @__PURE__ */ jsx(ApiSelector, {
|
|
2431
|
-
value: api ?? "openai-completions",
|
|
2432
|
-
onChange: onApiChange
|
|
2433
|
-
}) : null,
|
|
2434
|
-
/* @__PURE__ */ jsx(SecretCredentialField, {
|
|
2435
|
-
attemptedSave,
|
|
2436
|
-
label: "API key",
|
|
2437
|
-
placeholder,
|
|
2438
|
-
value: apiKey,
|
|
2439
|
-
showPassword,
|
|
2440
|
-
onChange: onApiKeyChange,
|
|
2441
|
-
onToggleVisibility: onTogglePassword
|
|
2442
|
-
}),
|
|
2443
|
-
openAiChat || isCustom ? /* @__PURE__ */ jsx(TextCredentialField, {
|
|
2444
|
-
attemptedSave,
|
|
2445
|
-
icon: Globe,
|
|
2446
|
-
inputType: "url",
|
|
2447
|
-
label: "Base URL",
|
|
2448
|
-
placeholder: OPENAI_CHAT_BASE_URL_PLACEHOLDER,
|
|
2449
|
-
value: baseUrl,
|
|
2450
|
-
onChange: onBaseUrlChange
|
|
2451
|
-
}) : null,
|
|
2452
|
-
showMultiModels ? /* @__PURE__ */ jsx(TextCredentialField, {
|
|
2453
|
-
attemptedSave,
|
|
2454
|
-
icon: Layers,
|
|
2455
|
-
label: "Model ids",
|
|
2456
|
-
placeholder: CUSTOM_MODELS_PLACEHOLDER,
|
|
2457
|
-
value: models ?? "",
|
|
2458
|
-
onChange: onModelsChange
|
|
2459
|
-
}) : null,
|
|
2460
|
-
openAiChat && !showMultiModels ? /* @__PURE__ */ jsx(TextCredentialField, {
|
|
2461
|
-
attemptedSave,
|
|
2462
|
-
icon: Box,
|
|
2463
|
-
label: "Model name",
|
|
2464
|
-
placeholder: OPENAI_CHAT_MODEL_PLACEHOLDER,
|
|
2465
|
-
value: modelId,
|
|
2466
|
-
onChange: onModelIdChange
|
|
2467
|
-
}) : null
|
|
2468
|
-
]
|
|
2469
|
-
});
|
|
2470
|
-
}
|
|
2471
|
-
function ApiSelector({ value, onChange }) {
|
|
2472
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
2473
|
-
className: "flex flex-col gap-1",
|
|
2474
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
2475
|
-
className: "text-xs font-medium text-muted-foreground",
|
|
2476
|
-
children: "API family"
|
|
2477
|
-
}), /* @__PURE__ */ jsx(Select, {
|
|
2478
|
-
"aria-label": "API family",
|
|
2479
|
-
value,
|
|
2480
|
-
options: CUSTOM_PROVIDER_API_OPTIONS,
|
|
2481
|
-
placeholder: "Select API family",
|
|
2482
|
-
onValueChange: (next) => onChange(next)
|
|
2483
|
-
})]
|
|
2484
|
-
});
|
|
2485
|
-
}
|
|
2486
|
-
function isOAuthProvider(provider) {
|
|
2487
|
-
return provider.authType === "oauth";
|
|
2488
|
-
}
|
|
2489
|
-
function supportsOAuth(provider) {
|
|
2490
|
-
return provider.supportsOAuth === true;
|
|
2491
|
-
}
|
|
2492
|
-
var CUSTOM_PROVIDER_PICKER_ROW = {
|
|
2493
|
-
id: "custom",
|
|
2494
|
-
name: "Custom provider",
|
|
2495
|
-
isConfigured: false,
|
|
2496
|
-
envVarName: "CUSTOM_PROVIDER_API_KEY",
|
|
2497
|
-
displayName: "Custom provider"
|
|
2498
|
-
};
|
|
2499
|
-
function parseCustomProviderModels(raw) {
|
|
2500
|
-
return raw.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
2501
|
-
}
|
|
2502
|
-
function useProviderCredentialsController({ onRemoveProvider, onUpdateProvider, providers }) {
|
|
2503
|
-
const [editingProvider, setEditingProvider] = useState2(null);
|
|
2504
|
-
const [editingIsNewOccInstance, setEditingIsNewOccInstance] = useState2(false);
|
|
2505
|
-
const [apiKey, setApiKey] = useState2("");
|
|
2506
|
-
const [baseUrl, setBaseUrl] = useState2("");
|
|
2507
|
-
const [modelId, setModelId] = useState2("");
|
|
2508
|
-
const [models, setModels] = useState2("");
|
|
2509
|
-
const [api, setApi] = useState2("openai-completions");
|
|
2510
|
-
const [displayName, setDisplayName] = useState2("");
|
|
2511
|
-
const [showPassword, setShowPassword] = useState2(false);
|
|
2512
|
-
const [attemptedSave, setAttemptedSave] = useState2(false);
|
|
2513
|
-
const [searchQuery, setSearchQuery] = useState2("");
|
|
2514
|
-
const [addPickerOpen, setAddPickerOpen] = useState2(false);
|
|
2515
|
-
const [addPickerQuery, setAddPickerQuery] = useState2("");
|
|
2516
|
-
const [confirmRemoveProvider, setConfirmRemoveProvider] = useState2(null);
|
|
2517
|
-
const credentialProviders = useMemo2(() => {
|
|
2518
|
-
return [...providers.filter((provider) => provider.id !== CUSTOM_PROVIDER_PICKER_ROW.id), CUSTOM_PROVIDER_PICKER_ROW];
|
|
2519
|
-
}, [providers]);
|
|
2520
|
-
const activeProviders = useMemo2(() => credentialProviders.filter((provider) => provider.isConfigured), [credentialProviders]);
|
|
2521
|
-
const unconfiguredProviders = useMemo2(() => credentialProviders.filter((provider) => !provider.isConfigured || provider.id === "openai-chat-completions" && provider.providerFamily === void 0), [credentialProviders]);
|
|
2522
|
-
const filteredActiveProviders = useMemo2(() => {
|
|
2523
|
-
const query = searchQuery.trim().toLowerCase();
|
|
2524
|
-
if (!query) return activeProviders;
|
|
2525
|
-
return activeProviders.filter((provider) => providerMatchesQuery(provider, query));
|
|
2526
|
-
}, [activeProviders, searchQuery]);
|
|
2527
|
-
const filteredPickerAvailable = useMemo2(() => {
|
|
2528
|
-
const query = addPickerQuery.trim().toLowerCase();
|
|
2529
|
-
return unconfiguredProviders.filter((provider) => providerMatchesQuery(provider, query));
|
|
2530
|
-
}, [addPickerQuery, unconfiguredProviders]);
|
|
2531
|
-
const filteredPickerConfigured = useMemo2(() => {
|
|
2532
|
-
const query = addPickerQuery.trim().toLowerCase();
|
|
2533
|
-
return activeProviders.filter((provider) => providerMatchesQuery(provider, query));
|
|
2534
|
-
}, [activeProviders, addPickerQuery]);
|
|
2535
|
-
const pickerHasResults = filteredPickerAvailable.length > 0 || filteredPickerConfigured.length > 0;
|
|
2536
|
-
const editingUnconfiguredProvider = editingProvider && !activeProviders.some((provider) => provider.id === editingProvider) ? credentialProviders.find((entry) => entry.id === editingProvider) ?? null : null;
|
|
2537
|
-
const resetEditor = () => {
|
|
2538
|
-
setApiKey("");
|
|
2539
|
-
setBaseUrl("");
|
|
2540
|
-
setModelId("");
|
|
2541
|
-
setModels("");
|
|
2542
|
-
setApi("openai-completions");
|
|
2543
|
-
setDisplayName("");
|
|
2544
|
-
setShowPassword(false);
|
|
2545
|
-
setAttemptedSave(false);
|
|
2546
|
-
};
|
|
2547
|
-
const closeEditor = () => {
|
|
2548
|
-
setEditingProvider(null);
|
|
2549
|
-
setEditingIsNewOccInstance(false);
|
|
2550
|
-
resetEditor();
|
|
2551
|
-
};
|
|
2552
|
-
const openEditor = (providerId, opts) => {
|
|
2553
|
-
setAddPickerOpen(false);
|
|
2554
|
-
setAddPickerQuery("");
|
|
2555
|
-
setEditingProvider(providerId);
|
|
2556
|
-
setEditingIsNewOccInstance(opts?.newOccInstance === true);
|
|
2557
|
-
resetEditor();
|
|
2558
|
-
const existing = providers.find((provider) => provider.id === providerId);
|
|
2559
|
-
setBaseUrl(existing?.baseUrl ?? "");
|
|
2560
|
-
setDisplayName(existing?.displayName ?? (isCustomProviderId(providerId) ? existing?.name ?? "" : ""));
|
|
2561
|
-
setApi(existing?.api ?? "openai-completions");
|
|
2562
|
-
setModels((existing?.modelIds ?? []).join(", "));
|
|
2563
|
-
setModelId(existing?.modelIds?.[0] ?? "");
|
|
2564
|
-
};
|
|
2565
|
-
const openAddPicker = () => {
|
|
2566
|
-
closeEditor();
|
|
2567
|
-
setAddPickerQuery("");
|
|
2568
|
-
setAddPickerOpen(true);
|
|
2569
|
-
};
|
|
2570
|
-
const closeAddPicker = () => {
|
|
2571
|
-
setAddPickerOpen(false);
|
|
2572
|
-
setAddPickerQuery("");
|
|
2573
|
-
};
|
|
2574
|
-
const selectProviderFromPicker = (providerId) => {
|
|
2575
|
-
openEditor(providerId, { newOccInstance: isOccProviderId(providerId) });
|
|
2576
|
-
};
|
|
2577
|
-
const handleSave = async (providerId) => {
|
|
2578
|
-
if (!onUpdateProvider) return;
|
|
2579
|
-
setAttemptedSave(true);
|
|
2580
|
-
const isCustomEditor = providerId === "custom" || isCustomProviderId(providerId);
|
|
2581
|
-
const openAiChat = isOccProviderId(providerId);
|
|
2582
|
-
if (isCustomEditor) {
|
|
2583
|
-
const modelList = parseCustomProviderModels(models);
|
|
2584
|
-
if (!apiKey.trim() || !baseUrl.trim() || !displayName.trim()) return;
|
|
2585
|
-
if (modelList.length === 0) return;
|
|
2586
|
-
try {
|
|
2587
|
-
await onUpdateProvider({
|
|
2588
|
-
providerId,
|
|
2589
|
-
apiKey: apiKey.trim(),
|
|
2590
|
-
baseUrl: baseUrl.trim(),
|
|
2591
|
-
displayName: displayName.trim(),
|
|
2592
|
-
api,
|
|
2593
|
-
models: modelList,
|
|
2594
|
-
...providerId === "custom" ? { createOccInstance: true } : {}
|
|
2595
|
-
});
|
|
2596
|
-
notify.success("Provider credentials applied to your active sessions.");
|
|
2597
|
-
closeEditor();
|
|
2598
|
-
closeAddPicker();
|
|
2599
|
-
} catch (error) {
|
|
2600
|
-
notify.error(error instanceof Error ? error.message : "Failed to update provider");
|
|
2601
|
-
}
|
|
2602
|
-
return;
|
|
2603
|
-
}
|
|
2604
|
-
const isNamedOcc = openAiChat && isNamedOccInstanceId(providerId);
|
|
2605
|
-
const isOccLike = openAiChat && (isNamedOcc || editingIsNewOccInstance);
|
|
2606
|
-
if (!apiKey.trim()) return;
|
|
2607
|
-
if (openAiChat && (!baseUrl.trim() || !modelId.trim())) return;
|
|
2608
|
-
if (isOccLike && !displayName.trim()) return;
|
|
2348
|
+
function useOAuthLoginFlow({ onConfigured, onOAuthLogin, providerId }) {
|
|
2349
|
+
const [login, setLogin] = useState2(null);
|
|
2350
|
+
const [busy, setBusy] = useState2(false);
|
|
2351
|
+
const [promptAnswer, setPromptAnswer] = useState2("");
|
|
2352
|
+
const loginIdRef = useRef2(null);
|
|
2353
|
+
const generationRef = useRef2(0);
|
|
2354
|
+
const startingRef = useRef2(false);
|
|
2355
|
+
const onOAuthLoginRef = useRef2(onOAuthLogin);
|
|
2356
|
+
const onConfiguredRef = useRef2(onConfigured);
|
|
2357
|
+
const providerIdRef = useRef2(providerId);
|
|
2358
|
+
useEffect2(() => {
|
|
2359
|
+
onOAuthLoginRef.current = onOAuthLogin;
|
|
2360
|
+
onConfiguredRef.current = onConfigured;
|
|
2361
|
+
providerIdRef.current = providerId;
|
|
2362
|
+
}, [
|
|
2363
|
+
onConfigured,
|
|
2364
|
+
onOAuthLogin,
|
|
2365
|
+
providerId
|
|
2366
|
+
]);
|
|
2367
|
+
const cancelLoginId = useCallback2(async (loginId) => {
|
|
2368
|
+
if (!loginId || !onOAuthLoginRef.current) return;
|
|
2609
2369
|
try {
|
|
2610
|
-
await
|
|
2611
|
-
providerId,
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
baseUrl: baseUrl.trim(),
|
|
2615
|
-
modelId: modelId.trim(),
|
|
2616
|
-
...isOccLike ? { displayName: displayName.trim() } : {},
|
|
2617
|
-
...editingIsNewOccInstance ? { createOccInstance: true } : {}
|
|
2618
|
-
} : {}
|
|
2370
|
+
await onOAuthLoginRef.current({
|
|
2371
|
+
providerId: providerIdRef.current,
|
|
2372
|
+
loginId,
|
|
2373
|
+
cancel: true
|
|
2619
2374
|
});
|
|
2620
|
-
|
|
2621
|
-
closeEditor();
|
|
2622
|
-
closeAddPicker();
|
|
2623
|
-
} catch (error) {
|
|
2624
|
-
notify.error(error instanceof Error ? error.message : "Failed to update provider");
|
|
2375
|
+
} catch {
|
|
2625
2376
|
}
|
|
2626
|
-
};
|
|
2627
|
-
const
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
canSave: useMemo2(() => {
|
|
2647
|
-
if (apiKey.trim().length === 0) return false;
|
|
2648
|
-
if (!editingProvider) return true;
|
|
2649
|
-
if (editingProvider === "custom" || isCustomProviderId(editingProvider)) {
|
|
2650
|
-
if (baseUrl.trim().length === 0) return false;
|
|
2651
|
-
if (parseCustomProviderModels(models).length === 0) return false;
|
|
2652
|
-
return displayName.trim().length > 0;
|
|
2653
|
-
}
|
|
2654
|
-
if (!isOccProviderId(editingProvider)) return true;
|
|
2655
|
-
if (baseUrl.trim().length === 0 || modelId.trim().length === 0) return false;
|
|
2656
|
-
if (isNamedOccInstanceId(editingProvider) || editingIsNewOccInstance) return displayName.trim().length > 0;
|
|
2657
|
-
return true;
|
|
2658
|
-
}, [
|
|
2659
|
-
apiKey,
|
|
2660
|
-
baseUrl,
|
|
2661
|
-
modelId,
|
|
2662
|
-
models,
|
|
2663
|
-
displayName,
|
|
2664
|
-
editingProvider,
|
|
2665
|
-
editingIsNewOccInstance
|
|
2666
|
-
]),
|
|
2667
|
-
closeAddPicker,
|
|
2668
|
-
closeEditor,
|
|
2669
|
-
confirmRemoveProvider,
|
|
2670
|
-
credentialProviders,
|
|
2671
|
-
displayName,
|
|
2672
|
-
editingIsNewOccInstance,
|
|
2673
|
-
editingProvider,
|
|
2674
|
-
editingUnconfiguredProvider,
|
|
2675
|
-
filteredActiveProviders,
|
|
2676
|
-
filteredPickerAvailable,
|
|
2677
|
-
filteredPickerConfigured,
|
|
2678
|
-
handleRemove,
|
|
2679
|
-
handleSave,
|
|
2680
|
-
modelId,
|
|
2681
|
-
models,
|
|
2682
|
-
openAddPicker,
|
|
2683
|
-
openEditor,
|
|
2684
|
-
pickerHasResults,
|
|
2685
|
-
resetEditor,
|
|
2686
|
-
searchQuery,
|
|
2687
|
-
selectProviderFromPicker,
|
|
2688
|
-
setAddPickerOpen,
|
|
2689
|
-
setAddPickerQuery,
|
|
2690
|
-
setApi,
|
|
2691
|
-
setApiKey,
|
|
2692
|
-
setAttemptedSave,
|
|
2693
|
-
setBaseUrl,
|
|
2694
|
-
setConfirmRemoveProvider,
|
|
2695
|
-
setDisplayName,
|
|
2696
|
-
setEditingIsNewOccInstance,
|
|
2697
|
-
setEditingProvider,
|
|
2698
|
-
setModelId,
|
|
2699
|
-
setModels,
|
|
2700
|
-
setSearchQuery,
|
|
2701
|
-
setShowPassword,
|
|
2702
|
-
showPassword,
|
|
2703
|
-
unconfiguredProviders
|
|
2704
|
-
};
|
|
2705
|
-
}
|
|
2706
|
-
function providerMatchesQuery(provider, query) {
|
|
2707
|
-
if (!query) return true;
|
|
2708
|
-
const keywords = supportsOAuth(provider) ? isOAuthProvider(provider) ? "oauth sign-in login" : "api key oauth sign-in login" : provider.id === "custom" || isCustomProviderId(provider.id) ? "custom provider endpoint openai anthropic google compatible" : isOccProviderId(provider.id) ? "api key base url model name chat completions" : "";
|
|
2709
|
-
return [
|
|
2710
|
-
provider.name,
|
|
2711
|
-
provider.envVarName,
|
|
2712
|
-
provider.id,
|
|
2713
|
-
keywords
|
|
2714
|
-
].join(" ").toLowerCase().includes(query);
|
|
2715
|
-
}
|
|
2716
|
-
var OAUTH_POLL_MS = 1500;
|
|
2717
|
-
var STALE_LOGIN_ERROR = "Unknown or expired OAuth login";
|
|
2718
|
-
function delay(ms) {
|
|
2719
|
-
return new Promise((resolve) => {
|
|
2720
|
-
setTimeout(resolve, ms);
|
|
2721
|
-
});
|
|
2722
|
-
}
|
|
2723
|
-
function useOAuthLoginFlow({ onConfigured, onOAuthLogin, providerId }) {
|
|
2724
|
-
const [login, setLogin] = useState2(null);
|
|
2725
|
-
const [busy, setBusy] = useState2(false);
|
|
2726
|
-
const [promptAnswer, setPromptAnswer] = useState2("");
|
|
2727
|
-
const loginIdRef = useRef2(null);
|
|
2728
|
-
const generationRef = useRef2(0);
|
|
2729
|
-
const startingRef = useRef2(false);
|
|
2730
|
-
const onOAuthLoginRef = useRef2(onOAuthLogin);
|
|
2731
|
-
const onConfiguredRef = useRef2(onConfigured);
|
|
2732
|
-
const providerIdRef = useRef2(providerId);
|
|
2733
|
-
useEffect2(() => {
|
|
2734
|
-
onOAuthLoginRef.current = onOAuthLogin;
|
|
2735
|
-
onConfiguredRef.current = onConfigured;
|
|
2736
|
-
providerIdRef.current = providerId;
|
|
2737
|
-
}, [
|
|
2738
|
-
onConfigured,
|
|
2739
|
-
onOAuthLogin,
|
|
2740
|
-
providerId
|
|
2741
|
-
]);
|
|
2742
|
-
const cancelLoginId = useCallback2(async (loginId) => {
|
|
2743
|
-
if (!loginId || !onOAuthLoginRef.current) return;
|
|
2744
|
-
try {
|
|
2745
|
-
await onOAuthLoginRef.current({
|
|
2746
|
-
providerId: providerIdRef.current,
|
|
2747
|
-
loginId,
|
|
2748
|
-
cancel: true
|
|
2749
|
-
});
|
|
2750
|
-
} catch {
|
|
2751
|
-
}
|
|
2752
|
-
}, []);
|
|
2753
|
-
const resetLocal = useCallback2(() => {
|
|
2754
|
-
loginIdRef.current = null;
|
|
2755
|
-
startingRef.current = false;
|
|
2756
|
-
setLogin(null);
|
|
2757
|
-
setPromptAnswer("");
|
|
2758
|
-
setBusy(false);
|
|
2759
|
-
}, []);
|
|
2760
|
-
useEffect2(() => {
|
|
2761
|
-
return () => {
|
|
2762
|
-
generationRef.current += 1;
|
|
2763
|
-
const loginId = loginIdRef.current;
|
|
2764
|
-
loginIdRef.current = null;
|
|
2765
|
-
cancelLoginId(loginId);
|
|
2766
|
-
};
|
|
2767
|
-
}, [cancelLoginId]);
|
|
2768
|
-
const applyResult = useCallback2((result, generation) => {
|
|
2769
|
-
if (generation !== generationRef.current) {
|
|
2770
|
-
if (result.status === "waiting" && result.loginId) cancelLoginId(result.loginId);
|
|
2771
|
-
return;
|
|
2377
|
+
}, []);
|
|
2378
|
+
const resetLocal = useCallback2(() => {
|
|
2379
|
+
loginIdRef.current = null;
|
|
2380
|
+
startingRef.current = false;
|
|
2381
|
+
setLogin(null);
|
|
2382
|
+
setPromptAnswer("");
|
|
2383
|
+
setBusy(false);
|
|
2384
|
+
}, []);
|
|
2385
|
+
useEffect2(() => {
|
|
2386
|
+
return () => {
|
|
2387
|
+
generationRef.current += 1;
|
|
2388
|
+
const loginId = loginIdRef.current;
|
|
2389
|
+
loginIdRef.current = null;
|
|
2390
|
+
cancelLoginId(loginId);
|
|
2391
|
+
};
|
|
2392
|
+
}, [cancelLoginId]);
|
|
2393
|
+
const applyResult = useCallback2((result, generation) => {
|
|
2394
|
+
if (generation !== generationRef.current) {
|
|
2395
|
+
if (result.status === "waiting" && result.loginId) cancelLoginId(result.loginId);
|
|
2396
|
+
return;
|
|
2772
2397
|
}
|
|
2773
2398
|
if (result.status === "success") {
|
|
2774
2399
|
loginIdRef.current = null;
|
|
@@ -2928,14 +2553,10 @@ function ProviderOAuthSignIn({ onConfigured, onOAuthLogin, provider }) {
|
|
|
2928
2553
|
}),
|
|
2929
2554
|
userCode ? /* @__PURE__ */ jsxs("p", {
|
|
2930
2555
|
className: "text-sm",
|
|
2931
|
-
children: [
|
|
2932
|
-
"
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
className: "font-mono text-foreground",
|
|
2936
|
-
children: userCode
|
|
2937
|
-
})
|
|
2938
|
-
]
|
|
2556
|
+
children: ["Enter this code: ", /* @__PURE__ */ jsx("span", {
|
|
2557
|
+
className: "font-mono text-foreground",
|
|
2558
|
+
children: userCode
|
|
2559
|
+
})]
|
|
2939
2560
|
}) : null,
|
|
2940
2561
|
instructions && !userCode ? /* @__PURE__ */ jsx("p", {
|
|
2941
2562
|
className: "text-xs text-pretty text-muted-foreground",
|
|
@@ -3023,554 +2644,336 @@ function ProviderOAuthSignIn({ onConfigured, onOAuthLogin, provider }) {
|
|
|
3023
2644
|
})]
|
|
3024
2645
|
});
|
|
3025
2646
|
}
|
|
3026
|
-
function
|
|
3027
|
-
|
|
3028
|
-
|
|
2647
|
+
function statusLabel(connection) {
|
|
2648
|
+
switch (connection.status) {
|
|
2649
|
+
case "connected":
|
|
2650
|
+
return "Connected";
|
|
2651
|
+
case "anonymous":
|
|
2652
|
+
return "Available without sign-in";
|
|
2653
|
+
case "needs_auth":
|
|
2654
|
+
return "Sign-in required";
|
|
2655
|
+
case "disabled":
|
|
2656
|
+
return "Disabled";
|
|
2657
|
+
default:
|
|
2658
|
+
return connection.status;
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
function connectionSubtitle(connection) {
|
|
2662
|
+
const details = connection.transport === "http" ? connection.url : connection.commandPreview;
|
|
2663
|
+
return [
|
|
2664
|
+
connection.source === "builtin" ? "Built-in" : "User",
|
|
2665
|
+
connection.transport === "http" ? "HTTP" : "stdio",
|
|
2666
|
+
statusLabel(connection),
|
|
2667
|
+
details
|
|
2668
|
+
].filter((part) => Boolean(part)).join(" \xB7 ");
|
|
2669
|
+
}
|
|
2670
|
+
function McpConnectionsSection({ connections, isLoading, isPending, onOAuth, onRemove, onUpsert }) {
|
|
2671
|
+
const [adding, setAdding] = useState2(false);
|
|
2672
|
+
const [transport, setTransport] = useState2("http");
|
|
2673
|
+
const [name, setName] = useState2("");
|
|
2674
|
+
const [url, setUrl] = useState2("");
|
|
2675
|
+
const [oauth, setOauth] = useState2(true);
|
|
2676
|
+
const [bearerTokenEnvVar, setBearerTokenEnvVar] = useState2("");
|
|
2677
|
+
const [command, setCommand] = useState2("");
|
|
2678
|
+
const [args, setArgs] = useState2("");
|
|
2679
|
+
const [cwd, setCwd] = useState2("");
|
|
2680
|
+
const [envLines, setEnvLines] = useState2("");
|
|
2681
|
+
const [confirmRemove, setConfirmRemove] = useState2(null);
|
|
2682
|
+
const resetAddForm = () => {
|
|
2683
|
+
setName("");
|
|
2684
|
+
setUrl("");
|
|
2685
|
+
setOauth(true);
|
|
2686
|
+
setBearerTokenEnvVar("");
|
|
2687
|
+
setCommand("");
|
|
2688
|
+
setArgs("");
|
|
2689
|
+
setCwd("");
|
|
2690
|
+
setEnvLines("");
|
|
2691
|
+
setTransport("http");
|
|
2692
|
+
setAdding(false);
|
|
2693
|
+
};
|
|
2694
|
+
const handleAdd = async () => {
|
|
2695
|
+
if (!onUpsert) return;
|
|
2696
|
+
const trimmedName = name.trim();
|
|
2697
|
+
try {
|
|
2698
|
+
if (transport === "http") await onUpsert({
|
|
2699
|
+
name: trimmedName,
|
|
2700
|
+
transport: "http",
|
|
2701
|
+
url: url.trim(),
|
|
2702
|
+
...oauth ? { oauth: true } : {},
|
|
2703
|
+
...bearerTokenEnvVar.trim() ? { bearerTokenEnvVar: bearerTokenEnvVar.trim() } : {},
|
|
2704
|
+
force: true
|
|
2705
|
+
});
|
|
2706
|
+
else {
|
|
2707
|
+
const parsedArgs = args.split(/\s+/).map((part) => part.trim()).filter(Boolean);
|
|
2708
|
+
const env = envLines.split("\n").map((line) => line.trim()).filter(Boolean).flatMap((line) => {
|
|
2709
|
+
const equals = line.indexOf("=");
|
|
2710
|
+
if (equals <= 0) return [];
|
|
2711
|
+
const child = line.slice(0, equals).trim();
|
|
2712
|
+
const source = line.slice(equals + 1).trim();
|
|
2713
|
+
if (!child || !source) return [];
|
|
2714
|
+
return [{
|
|
2715
|
+
child,
|
|
2716
|
+
source
|
|
2717
|
+
}];
|
|
2718
|
+
});
|
|
2719
|
+
await onUpsert({
|
|
2720
|
+
name: trimmedName,
|
|
2721
|
+
transport: "stdio",
|
|
2722
|
+
command: command.trim(),
|
|
2723
|
+
...parsedArgs.length > 0 ? { args: parsedArgs } : {},
|
|
2724
|
+
...cwd.trim() ? { cwd: cwd.trim() } : {},
|
|
2725
|
+
...env.length > 0 ? { env } : {},
|
|
2726
|
+
force: true
|
|
2727
|
+
});
|
|
2728
|
+
}
|
|
2729
|
+
notify.success("MCP connection saved");
|
|
2730
|
+
resetAddForm();
|
|
2731
|
+
} catch (error) {
|
|
2732
|
+
notify.error(error instanceof Error ? error.message : "Could not save MCP connection");
|
|
2733
|
+
}
|
|
2734
|
+
};
|
|
2735
|
+
const handleRemove = async (connectionName) => {
|
|
2736
|
+
if (!onRemove) return;
|
|
2737
|
+
try {
|
|
2738
|
+
await onRemove({ name: connectionName });
|
|
2739
|
+
notify.success(`Removed ${connectionName}`);
|
|
2740
|
+
setConfirmRemove(null);
|
|
2741
|
+
} catch (error) {
|
|
2742
|
+
notify.error(error instanceof Error ? error.message : "Could not remove MCP connection");
|
|
2743
|
+
}
|
|
2744
|
+
};
|
|
2745
|
+
const handleLogout = async (connectionName) => {
|
|
2746
|
+
if (!onOAuth) return;
|
|
2747
|
+
try {
|
|
2748
|
+
await onOAuth({
|
|
2749
|
+
name: connectionName,
|
|
2750
|
+
action: "logout"
|
|
2751
|
+
});
|
|
2752
|
+
notify.success(`Signed out of ${connectionName}`);
|
|
2753
|
+
} catch (error) {
|
|
2754
|
+
notify.error(error instanceof Error ? error.message : "Could not sign out");
|
|
2755
|
+
}
|
|
2756
|
+
};
|
|
2757
|
+
const oauthAdapter = useMemo2(() => {
|
|
2758
|
+
if (!onOAuth) return void 0;
|
|
2759
|
+
return (connection) => async (request) => {
|
|
2760
|
+
const starting = !request.loginId && !request.cancel;
|
|
2761
|
+
return await onOAuth({
|
|
2762
|
+
name: connection.name,
|
|
2763
|
+
action: starting && connection.status === "connected" ? "reconnect" : "login",
|
|
2764
|
+
loginId: request.loginId,
|
|
2765
|
+
promptAnswer: request.promptAnswer,
|
|
2766
|
+
cancel: request.cancel
|
|
2767
|
+
});
|
|
2768
|
+
};
|
|
2769
|
+
}, [onOAuth]);
|
|
2770
|
+
return /* @__PURE__ */ jsxs(SettingsPane, {
|
|
2771
|
+
title: "MCP",
|
|
2772
|
+
description: "Connect built-in and user MCP servers. Tokens stay on the server; this list only shows status and environment-variable names.",
|
|
2773
|
+
actions: /* @__PURE__ */ jsxs(Button, {
|
|
2774
|
+
type: "button",
|
|
2775
|
+
size: "sm",
|
|
2776
|
+
variant: "outline",
|
|
2777
|
+
disabled: isPending || adding,
|
|
2778
|
+
onClick: () => setAdding(true),
|
|
2779
|
+
children: [/* @__PURE__ */ jsx(Plus, { "data-icon": "inline-start" }), "Add server"]
|
|
2780
|
+
}),
|
|
3029
2781
|
children: [
|
|
3030
|
-
/* @__PURE__ */ jsxs("div", {
|
|
3031
|
-
className: "flex items-center gap-2",
|
|
3032
|
-
children: [/* @__PURE__ */ jsx(
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
2782
|
+
isLoading ? /* @__PURE__ */ jsxs("div", {
|
|
2783
|
+
className: "flex items-center gap-2 text-sm text-muted-foreground",
|
|
2784
|
+
children: [/* @__PURE__ */ jsx(Spinner, { className: "size-3.5" }), "Loading MCP connections\u2026"]
|
|
2785
|
+
}) : null,
|
|
2786
|
+
adding ? /* @__PURE__ */ jsxs("div", {
|
|
2787
|
+
className: "flex flex-col gap-3 rounded-xl border p-4",
|
|
2788
|
+
children: [
|
|
2789
|
+
/* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, { children: "Name" }), /* @__PURE__ */ jsx(Input, {
|
|
2790
|
+
value: name,
|
|
2791
|
+
onChange: (event) => setName(event.target.value),
|
|
2792
|
+
"aria-label": "MCP server name"
|
|
2793
|
+
})] }),
|
|
2794
|
+
/* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, { children: "Transport" }), /* @__PURE__ */ jsx(Select, {
|
|
2795
|
+
value: transport,
|
|
2796
|
+
onValueChange: (value) => setTransport(value),
|
|
2797
|
+
options: [{
|
|
2798
|
+
label: "HTTP",
|
|
2799
|
+
value: "http"
|
|
2800
|
+
}, {
|
|
2801
|
+
label: "stdio",
|
|
2802
|
+
value: "stdio"
|
|
2803
|
+
}]
|
|
2804
|
+
})] }),
|
|
2805
|
+
transport === "http" ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2806
|
+
/* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, { children: "URL" }), /* @__PURE__ */ jsx(Input, {
|
|
2807
|
+
value: url,
|
|
2808
|
+
onChange: (event) => setUrl(event.target.value),
|
|
2809
|
+
"aria-label": "MCP server URL"
|
|
2810
|
+
})] }),
|
|
2811
|
+
/* @__PURE__ */ jsxs(Field, {
|
|
2812
|
+
orientation: "horizontal",
|
|
2813
|
+
className: "items-center justify-between",
|
|
2814
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(FieldLabel, { children: "OAuth" }), /* @__PURE__ */ jsx(FieldDescription, { children: "Use the browser sign-in flow for this server." })] }), /* @__PURE__ */ jsx(Switch, {
|
|
2815
|
+
checked: oauth,
|
|
2816
|
+
onCheckedChange: (checked) => setOauth(checked),
|
|
2817
|
+
"aria-label": "Use OAuth"
|
|
2818
|
+
})]
|
|
2819
|
+
}),
|
|
2820
|
+
!oauth ? /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, { children: "Bearer token environment variable" }), /* @__PURE__ */ jsx(Input, {
|
|
2821
|
+
value: bearerTokenEnvVar,
|
|
2822
|
+
onChange: (event) => setBearerTokenEnvVar(event.target.value),
|
|
2823
|
+
"aria-label": "Bearer token environment variable",
|
|
2824
|
+
placeholder: "MCP_BEARER_TOKEN"
|
|
2825
|
+
})] }) : null
|
|
2826
|
+
] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2827
|
+
/* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, { children: "Command" }), /* @__PURE__ */ jsx(Input, {
|
|
2828
|
+
value: command,
|
|
2829
|
+
onChange: (event) => setCommand(event.target.value),
|
|
2830
|
+
"aria-label": "MCP command"
|
|
2831
|
+
})] }),
|
|
2832
|
+
/* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, { children: "Arguments" }), /* @__PURE__ */ jsx(Input, {
|
|
2833
|
+
value: args,
|
|
2834
|
+
onChange: (event) => setArgs(event.target.value),
|
|
2835
|
+
"aria-label": "MCP command arguments"
|
|
2836
|
+
})] }),
|
|
2837
|
+
/* @__PURE__ */ jsxs(Field, { children: [
|
|
2838
|
+
/* @__PURE__ */ jsx(FieldLabel, { children: "Working directory" }),
|
|
2839
|
+
/* @__PURE__ */ jsx(Input, {
|
|
2840
|
+
value: cwd,
|
|
2841
|
+
onChange: (event) => setCwd(event.target.value),
|
|
2842
|
+
"aria-label": "MCP working directory"
|
|
2843
|
+
}),
|
|
2844
|
+
/* @__PURE__ */ jsx(FieldDescription, { children: "Must stay inside the current workspace." })
|
|
2845
|
+
] }),
|
|
2846
|
+
/* @__PURE__ */ jsxs(Field, { children: [
|
|
2847
|
+
/* @__PURE__ */ jsx(FieldLabel, { children: "Environment mappings" }),
|
|
2848
|
+
/* @__PURE__ */ jsx(Textarea, {
|
|
2849
|
+
value: envLines,
|
|
2850
|
+
onChange: (event) => setEnvLines(event.target.value),
|
|
2851
|
+
"aria-label": "MCP environment mappings",
|
|
2852
|
+
placeholder: "CHILD=SOURCE"
|
|
2853
|
+
}),
|
|
2854
|
+
/* @__PURE__ */ jsx(FieldDescription, { children: "One CHILD=SOURCE pair per line. Only variable names are stored." })
|
|
2855
|
+
] })
|
|
2856
|
+
] }),
|
|
2857
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2858
|
+
className: "flex justify-end gap-2",
|
|
2859
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
2860
|
+
type: "button",
|
|
2861
|
+
size: "sm",
|
|
2862
|
+
variant: "ghost",
|
|
2863
|
+
onClick: resetAddForm,
|
|
2864
|
+
children: "Cancel"
|
|
2865
|
+
}), /* @__PURE__ */ jsxs(Button, {
|
|
2866
|
+
type: "button",
|
|
2867
|
+
size: "sm",
|
|
2868
|
+
disabled: isPending || !name.trim(),
|
|
2869
|
+
onClick: () => void handleAdd(),
|
|
2870
|
+
children: [isPending ? /* @__PURE__ */ jsx(Spinner, { "data-icon": "inline-start" }) : null, "Save"]
|
|
2871
|
+
})]
|
|
2872
|
+
})
|
|
2873
|
+
]
|
|
2874
|
+
}) : null,
|
|
2875
|
+
!isLoading && connections.length === 0 && !adding ? /* @__PURE__ */ jsx("p", {
|
|
2876
|
+
className: "text-sm text-muted-foreground",
|
|
2877
|
+
children: "No MCP connections yet."
|
|
2878
|
+
}) : null,
|
|
3060
2879
|
/* @__PURE__ */ jsx("div", {
|
|
3061
|
-
className: "
|
|
3062
|
-
children:
|
|
3063
|
-
className: "
|
|
3064
|
-
children:
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
2880
|
+
className: "flex flex-col gap-2",
|
|
2881
|
+
children: connections.map((connection) => /* @__PURE__ */ jsxs("div", {
|
|
2882
|
+
className: "flex flex-col gap-2",
|
|
2883
|
+
children: [
|
|
2884
|
+
/* @__PURE__ */ jsx(ItemRow, {
|
|
2885
|
+
icon: /* @__PURE__ */ jsx(Plug, { className: "size-4" }),
|
|
2886
|
+
title: connection.label,
|
|
2887
|
+
subtitle: connectionSubtitle(connection),
|
|
2888
|
+
trailing: /* @__PURE__ */ jsxs("div", {
|
|
2889
|
+
className: "flex items-center gap-1.5",
|
|
2890
|
+
children: [connection.usesOAuth && connection.status !== "needs_auth" ? /* @__PURE__ */ jsx(Button, {
|
|
2891
|
+
type: "button",
|
|
2892
|
+
size: "sm",
|
|
2893
|
+
variant: "ghost",
|
|
2894
|
+
disabled: isPending || !onOAuth,
|
|
2895
|
+
onClick: () => {
|
|
2896
|
+
handleLogout(connection.name);
|
|
2897
|
+
},
|
|
2898
|
+
children: "Sign out"
|
|
2899
|
+
}) : null, connection.source === "user" ? confirmRemove === connection.name ? /* @__PURE__ */ jsx(Button, {
|
|
2900
|
+
type: "button",
|
|
2901
|
+
size: "sm",
|
|
2902
|
+
variant: "destructive",
|
|
2903
|
+
disabled: isPending,
|
|
2904
|
+
onClick: () => {
|
|
2905
|
+
handleRemove(connection.name);
|
|
2906
|
+
},
|
|
2907
|
+
children: "Confirm remove"
|
|
2908
|
+
}) : /* @__PURE__ */ jsx(Button, {
|
|
2909
|
+
type: "button",
|
|
2910
|
+
size: "sm",
|
|
2911
|
+
variant: "ghost",
|
|
2912
|
+
disabled: isPending || !onRemove,
|
|
2913
|
+
"aria-label": `Remove ${connection.name}`,
|
|
2914
|
+
onClick: () => setConfirmRemove(connection.name),
|
|
2915
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "size-3.5" })
|
|
2916
|
+
}) : null]
|
|
2917
|
+
})
|
|
2918
|
+
}),
|
|
2919
|
+
connection.error ? /* @__PURE__ */ jsx(Alert, {
|
|
2920
|
+
className: "px-3 py-2",
|
|
2921
|
+
children: /* @__PURE__ */ jsx(AlertDescription, {
|
|
2922
|
+
className: "text-xs text-pretty",
|
|
2923
|
+
children: connection.error
|
|
2924
|
+
})
|
|
2925
|
+
}) : null,
|
|
2926
|
+
connection.usesOAuth && oauthAdapter ? /* @__PURE__ */ jsx(ProviderOAuthSignIn, {
|
|
2927
|
+
provider: {
|
|
2928
|
+
id: connection.name,
|
|
2929
|
+
name: connection.label,
|
|
2930
|
+
isConfigured: connection.status === "connected",
|
|
2931
|
+
envVarName: "",
|
|
2932
|
+
authType: "oauth",
|
|
2933
|
+
supportsOAuth: true
|
|
2934
|
+
},
|
|
2935
|
+
onOAuthLogin: oauthAdapter(connection)
|
|
2936
|
+
}) : null
|
|
2937
|
+
]
|
|
2938
|
+
}, `${connection.source}:${connection.name}`))
|
|
3086
2939
|
})
|
|
3087
2940
|
]
|
|
3088
2941
|
});
|
|
3089
2942
|
}
|
|
3090
|
-
function
|
|
3091
|
-
return
|
|
3092
|
-
className: "flex flex-col gap-3",
|
|
3093
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
3094
|
-
className: "flex items-center gap-2",
|
|
3095
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
3096
|
-
type: "button",
|
|
3097
|
-
variant: "ghost",
|
|
3098
|
-
size: "icon-sm",
|
|
3099
|
-
"aria-label": "Back to provider list",
|
|
3100
|
-
onClick: onBack,
|
|
3101
|
-
children: /* @__PURE__ */ jsx(ArrowLeft, {})
|
|
3102
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
3103
|
-
className: "min-w-0 flex-1",
|
|
3104
|
-
children: [/* @__PURE__ */ jsxs("p", {
|
|
3105
|
-
className: "text-sm font-medium",
|
|
3106
|
-
children: ["Configure ", provider.name]
|
|
3107
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
3108
|
-
className: "text-xs text-pretty text-muted-foreground",
|
|
3109
|
-
children: "OAuth sign-in. Credentials are stored in auth.json for this account."
|
|
3110
|
-
})]
|
|
3111
|
-
})]
|
|
3112
|
-
}), /* @__PURE__ */ jsx(ProviderOAuthSignIn, {
|
|
3113
|
-
provider,
|
|
3114
|
-
onConfigured,
|
|
3115
|
-
onOAuthLogin
|
|
3116
|
-
}, provider.id)]
|
|
3117
|
-
});
|
|
3118
|
-
}
|
|
3119
|
-
function AddProviderEditorPanel({ provider, api, apiKey, baseUrl, modelId, models, displayName, showPassword, attemptedSave, isPending, canSave, onApiKeyChange, onApiChange, onBaseUrlChange, onModelIdChange, onModelsChange, onDisplayNameChange, onTogglePassword, onBack, onCancel, onConfigured, onOAuthLogin, onSave }) {
|
|
3120
|
-
const isCustomTemplate = provider.id === "custom" || isCustomProviderId(provider.id);
|
|
3121
|
-
const meta = PROVIDER_METADATA[provider.id] ?? (isCustomTemplate ? PROVIDER_METADATA["custom"] : {
|
|
3122
|
-
placeholder: "Enter credentials\u2026",
|
|
3123
|
-
help: "Stored securely in your local environment overrides."
|
|
3124
|
-
});
|
|
3125
|
-
const openAiChat = isOccProviderId(provider.id) && !isCustomTemplate;
|
|
3126
|
-
const oauthAvailable = supportsOAuth(provider);
|
|
3127
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
3128
|
-
className: "flex flex-col gap-3",
|
|
3129
|
-
children: [
|
|
3130
|
-
/* @__PURE__ */ jsxs("div", {
|
|
3131
|
-
className: "flex items-center gap-2",
|
|
3132
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
3133
|
-
type: "button",
|
|
3134
|
-
variant: "ghost",
|
|
3135
|
-
size: "icon-sm",
|
|
3136
|
-
"aria-label": "Back to provider list",
|
|
3137
|
-
onClick: onBack,
|
|
3138
|
-
children: /* @__PURE__ */ jsx(ArrowLeft, {})
|
|
3139
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
3140
|
-
className: "min-w-0 flex-1",
|
|
3141
|
-
children: [/* @__PURE__ */ jsxs("p", {
|
|
3142
|
-
className: "text-sm font-medium",
|
|
3143
|
-
children: ["Configure ", provider.name]
|
|
3144
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
3145
|
-
className: "text-xs text-pretty text-muted-foreground",
|
|
3146
|
-
children: isCustomTemplate ? "Name this custom provider, pick its API family, then enter its API key, https base URL, and model ids." : openAiChat ? "Name this OpenAI-compatible provider, then enter its API key, base URL, and model name." : `Stored as ${provider.envVarName} for this account.`
|
|
3147
|
-
})]
|
|
3148
|
-
})]
|
|
3149
|
-
}),
|
|
3150
|
-
/* @__PURE__ */ jsx(ProviderCredentialFields, {
|
|
3151
|
-
attemptedSave,
|
|
3152
|
-
api,
|
|
3153
|
-
apiKey,
|
|
3154
|
-
baseUrl,
|
|
3155
|
-
modelId,
|
|
3156
|
-
models,
|
|
3157
|
-
displayName,
|
|
3158
|
-
isCustom: isCustomTemplate,
|
|
3159
|
-
openAiChat,
|
|
3160
|
-
placeholder: meta.placeholder,
|
|
3161
|
-
showPassword,
|
|
3162
|
-
onApiKeyChange,
|
|
3163
|
-
onApiChange,
|
|
3164
|
-
onBaseUrlChange,
|
|
3165
|
-
onModelIdChange,
|
|
3166
|
-
onModelsChange,
|
|
3167
|
-
onDisplayNameChange,
|
|
3168
|
-
onTogglePassword
|
|
3169
|
-
}),
|
|
3170
|
-
/* @__PURE__ */ jsxs(Alert, {
|
|
3171
|
-
className: "px-3 py-2",
|
|
3172
|
-
children: [/* @__PURE__ */ jsx(Info, {}), /* @__PURE__ */ jsx(AlertDescription, {
|
|
3173
|
-
className: "text-xs text-pretty",
|
|
3174
|
-
children: meta.help
|
|
3175
|
-
})]
|
|
3176
|
-
}),
|
|
3177
|
-
/* @__PURE__ */ jsxs("div", {
|
|
3178
|
-
className: "flex items-center justify-end gap-1.5",
|
|
3179
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
3180
|
-
type: "button",
|
|
3181
|
-
variant: "ghost",
|
|
3182
|
-
size: "sm",
|
|
3183
|
-
onClick: onCancel,
|
|
3184
|
-
children: "Cancel"
|
|
3185
|
-
}), /* @__PURE__ */ jsxs(Button, {
|
|
3186
|
-
type: "button",
|
|
3187
|
-
size: "sm",
|
|
3188
|
-
disabled: isPending || !canSave,
|
|
3189
|
-
onClick: onSave,
|
|
3190
|
-
children: [isPending ? /* @__PURE__ */ jsx(Spinner, { "data-icon": "inline-start" }) : null, "Save"]
|
|
3191
|
-
})]
|
|
3192
|
-
}),
|
|
3193
|
-
oauthAvailable ? /* @__PURE__ */ jsx(ProviderOAuthSignIn, {
|
|
3194
|
-
provider,
|
|
3195
|
-
onConfigured: onConfigured ?? onCancel,
|
|
3196
|
-
onOAuthLogin
|
|
3197
|
-
}, `${provider.id}-oauth`) : null
|
|
3198
|
-
]
|
|
3199
|
-
});
|
|
2943
|
+
function customModelKey(provider, model) {
|
|
2944
|
+
return `${provider}/${model}`;
|
|
3200
2945
|
}
|
|
3201
|
-
function
|
|
3202
|
-
return
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
className: "flex flex-col gap-2",
|
|
3209
|
-
children: [/* @__PURE__ */ jsxs(AlertDialogTitle, { children: [
|
|
3210
|
-
"Remove ",
|
|
3211
|
-
confirmRemoveProvider?.name ?? "provider",
|
|
3212
|
-
"?"
|
|
3213
|
-
] }), /* @__PURE__ */ jsx(AlertDialogDescription, { children: "This clears stored credentials for this provider from your workspace settings. Active sessions will stop using it immediately." })]
|
|
3214
|
-
}), /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [/* @__PURE__ */ jsx(AlertDialogCancel, {
|
|
3215
|
-
disabled: isPending,
|
|
3216
|
-
children: "Cancel"
|
|
3217
|
-
}), /* @__PURE__ */ jsxs(AlertDialogAction, {
|
|
3218
|
-
disabled: isPending || !confirmRemoveProvider,
|
|
3219
|
-
onClick: () => {
|
|
3220
|
-
if (confirmRemoveProvider) onConfirm(confirmRemoveProvider);
|
|
3221
|
-
},
|
|
3222
|
-
children: [isPending ? /* @__PURE__ */ jsx(Spinner, { "data-icon": "inline-start" }) : null, "Remove provider"]
|
|
3223
|
-
})] })] })
|
|
3224
|
-
});
|
|
2946
|
+
function isModelEnabled(model, patterns) {
|
|
2947
|
+
return isModelPatternEnabled({
|
|
2948
|
+
id: model.id,
|
|
2949
|
+
name: model.name,
|
|
2950
|
+
provider: model.provider,
|
|
2951
|
+
modelId: model.modelId
|
|
2952
|
+
}, patterns);
|
|
3225
2953
|
}
|
|
3226
|
-
function
|
|
3227
|
-
|
|
3228
|
-
const
|
|
3229
|
-
const
|
|
3230
|
-
const
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
provider: isCustomTemplate ? "custom" : provider.id,
|
|
3239
|
-
api: provider.api,
|
|
3240
|
-
className: "text-foreground/70"
|
|
3241
|
-
})
|
|
3242
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
3243
|
-
className: "min-w-0 flex-1",
|
|
3244
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
3245
|
-
className: "truncate text-sm font-medium",
|
|
3246
|
-
children: provider.name
|
|
3247
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
3248
|
-
className: "truncate text-xs text-muted-foreground",
|
|
3249
|
-
children: [oauthOnly ? "OAuth sign-in" : oauthAvailable ? "API key or OAuth" : isCustomTemplate ? "API family + key + https base URL + models" : openAiChat ? "API key + base URL + model name" : provider.envVarName, configured ? " \xB7 Update" : ""]
|
|
3250
|
-
})]
|
|
3251
|
-
})]
|
|
3252
|
-
});
|
|
2954
|
+
function nextEnabledModelPatterns({ currentPatterns, enabled, model, models }) {
|
|
2955
|
+
if (currentPatterns === void 0 && enabled) return void 0;
|
|
2956
|
+
const current = currentPatterns ?? [];
|
|
2957
|
+
const knownModelPatterns = new Set(models.map((item) => modelPatternFor(item)));
|
|
2958
|
+
const activeKnown = /* @__PURE__ */ new Set();
|
|
2959
|
+
for (const item of models) if (isModelEnabled(item, currentPatterns)) activeKnown.add(modelPatternFor(item));
|
|
2960
|
+
if (enabled) activeKnown.add(modelPatternFor(model));
|
|
2961
|
+
else activeKnown.delete(modelPatternFor(model));
|
|
2962
|
+
return [...current.filter((pattern) => {
|
|
2963
|
+
if (knownModelPatterns.has(pattern)) return false;
|
|
2964
|
+
return enabled || !modelMatchesPattern(model, pattern);
|
|
2965
|
+
}), ...activeKnown];
|
|
3253
2966
|
}
|
|
3254
|
-
function
|
|
3255
|
-
return
|
|
3256
|
-
className: cn(fleetPiRowSurface({
|
|
3257
|
-
interactive,
|
|
3258
|
-
padding,
|
|
3259
|
-
tone
|
|
3260
|
-
}), className),
|
|
3261
|
-
...props
|
|
3262
|
-
});
|
|
2967
|
+
function modelPatternFor(model) {
|
|
2968
|
+
return modelPattern(model.provider, model.modelId);
|
|
3263
2969
|
}
|
|
3264
|
-
function
|
|
3265
|
-
return
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
icon ? /* @__PURE__ */ jsx("div", {
|
|
3272
|
-
className: "flex size-8 shrink-0 items-center justify-center rounded-md border border-border/40 bg-background/60 text-foreground/70",
|
|
3273
|
-
children: icon
|
|
3274
|
-
}) : null,
|
|
3275
|
-
/* @__PURE__ */ jsxs("div", {
|
|
3276
|
-
className: "min-w-0 flex-1",
|
|
3277
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
3278
|
-
className: "truncate text-sm font-medium text-foreground",
|
|
3279
|
-
children: title
|
|
3280
|
-
}), subtitle ? /* @__PURE__ */ jsx("div", {
|
|
3281
|
-
className: "mt-0.5 truncate text-xs text-muted-foreground",
|
|
3282
|
-
children: subtitle
|
|
3283
|
-
}) : null]
|
|
3284
|
-
}),
|
|
3285
|
-
trailing ? /* @__PURE__ */ jsx("div", {
|
|
3286
|
-
className: "flex shrink-0 items-center gap-1.5",
|
|
3287
|
-
children: trailing
|
|
3288
|
-
}) : null
|
|
3289
|
-
]
|
|
3290
|
-
});
|
|
3291
|
-
}
|
|
3292
|
-
function ActiveProviderList({ providers, editingProvider, form, operation, actions, onEdit, onCancelEdit, onSave, onRemove, onOAuthLogin, onConfigured }) {
|
|
3293
|
-
const { api, apiKey, baseUrl, modelId, models, displayName, showPassword, attemptedSave, canSave } = form;
|
|
3294
|
-
const { isPending, canRemove } = operation;
|
|
3295
|
-
const { onApiKeyChange, onApiChange, onBaseUrlChange, onModelIdChange, onModelsChange, onDisplayNameChange, onTogglePassword } = actions;
|
|
3296
|
-
return /* @__PURE__ */ jsx("div", {
|
|
3297
|
-
className: "flex flex-col gap-1.5",
|
|
3298
|
-
children: providers.map((provider) => {
|
|
3299
|
-
const isEditing = editingProvider === provider.id;
|
|
3300
|
-
const isCustom = isCustomProviderId(provider.id);
|
|
3301
|
-
const meta = PROVIDER_METADATA[provider.id] ?? PROVIDER_METADATA[isCustom ? "custom" : "openai-chat-completions"];
|
|
3302
|
-
const openAiChat = isOccProviderId(provider.id);
|
|
3303
|
-
const oauthOnly = isOAuthProvider(provider);
|
|
3304
|
-
const oauthAvailable = supportsOAuth(provider);
|
|
3305
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
3306
|
-
className: "flex flex-col",
|
|
3307
|
-
children: [/* @__PURE__ */ jsx(ItemRow, {
|
|
3308
|
-
interactive: false,
|
|
3309
|
-
icon: /* @__PURE__ */ jsx(ProviderBrandIcon, {
|
|
3310
|
-
provider: provider.id,
|
|
3311
|
-
api: provider.api,
|
|
3312
|
-
className: "text-foreground/80"
|
|
3313
|
-
}),
|
|
3314
|
-
title: provider.name,
|
|
3315
|
-
subtitle: oauthOnly ? "OAuth sign-in" : oauthAvailable ? "API key or OAuth" : isCustom ? "Custom provider \xB7 API key + base URL + models" : openAiChat ? "OpenAI-compatible \xB7 API key + base URL + model name" : provider.envVarName,
|
|
3316
|
-
trailing: /* @__PURE__ */ jsxs("div", {
|
|
3317
|
-
className: "flex items-center gap-0.5",
|
|
3318
|
-
children: [/* @__PURE__ */ jsxs(Button, {
|
|
3319
|
-
type: "button",
|
|
3320
|
-
variant: "ghost",
|
|
3321
|
-
size: "sm",
|
|
3322
|
-
className: cn(HIT_AREA_EXPAND_DENSE_CLASS, "h-7 px-2 text-xs text-muted-foreground transition-[background-color,color,transform] duration-150 hover:text-destructive active:scale-[0.96]"),
|
|
3323
|
-
disabled: isPending || !canRemove,
|
|
3324
|
-
"aria-label": `Remove ${provider.name}`,
|
|
3325
|
-
onClick: () => onRemove(provider),
|
|
3326
|
-
children: [/* @__PURE__ */ jsx(Trash2, { "data-icon": "inline-start" }), "Remove"]
|
|
3327
|
-
}), /* @__PURE__ */ jsxs(Button, {
|
|
3328
|
-
type: "button",
|
|
3329
|
-
variant: "ghost",
|
|
3330
|
-
size: "sm",
|
|
3331
|
-
className: cn(HIT_AREA_EXPAND_DENSE_CLASS, "h-7 px-2 text-xs transition-[background-color,transform] duration-150 active:scale-[0.96]"),
|
|
3332
|
-
disabled: isPending,
|
|
3333
|
-
onClick: () => {
|
|
3334
|
-
if (isEditing) {
|
|
3335
|
-
onCancelEdit();
|
|
3336
|
-
return;
|
|
3337
|
-
}
|
|
3338
|
-
onEdit(provider.id);
|
|
3339
|
-
},
|
|
3340
|
-
children: [!isEditing ? /* @__PURE__ */ jsx(Pencil, { "data-icon": "inline-start" }) : null, isEditing ? "Cancel" : "Update"]
|
|
3341
|
-
})]
|
|
3342
|
-
})
|
|
3343
|
-
}), isEditing ? /* @__PURE__ */ jsx(RowSurface, {
|
|
3344
|
-
tone: "inset",
|
|
3345
|
-
padding: "md",
|
|
3346
|
-
className: "flex flex-col gap-2 border-t border-border/30",
|
|
3347
|
-
children: oauthOnly ? /* @__PURE__ */ jsx(ProviderOAuthSignIn, {
|
|
3348
|
-
provider,
|
|
3349
|
-
onConfigured,
|
|
3350
|
-
onOAuthLogin
|
|
3351
|
-
}, provider.id) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
3352
|
-
/* @__PURE__ */ jsx(ProviderCredentialFields, {
|
|
3353
|
-
attemptedSave,
|
|
3354
|
-
api: provider.api ?? api,
|
|
3355
|
-
apiKey,
|
|
3356
|
-
baseUrl,
|
|
3357
|
-
modelId,
|
|
3358
|
-
models,
|
|
3359
|
-
displayName,
|
|
3360
|
-
isCustom,
|
|
3361
|
-
openAiChat,
|
|
3362
|
-
placeholder: meta.placeholder,
|
|
3363
|
-
showPassword,
|
|
3364
|
-
onApiKeyChange,
|
|
3365
|
-
onApiChange,
|
|
3366
|
-
onBaseUrlChange,
|
|
3367
|
-
onModelIdChange,
|
|
3368
|
-
onModelsChange,
|
|
3369
|
-
onDisplayNameChange: isCustom || provider.providerFamily !== void 0 ? onDisplayNameChange : void 0,
|
|
3370
|
-
onTogglePassword
|
|
3371
|
-
}),
|
|
3372
|
-
/* @__PURE__ */ jsxs(Alert, {
|
|
3373
|
-
className: "px-3 py-2",
|
|
3374
|
-
children: [/* @__PURE__ */ jsx(Info, {}), /* @__PURE__ */ jsx(AlertDescription, {
|
|
3375
|
-
className: "text-xs text-pretty",
|
|
3376
|
-
children: meta.help
|
|
3377
|
-
})]
|
|
3378
|
-
}),
|
|
3379
|
-
/* @__PURE__ */ jsx("div", {
|
|
3380
|
-
className: "flex items-center justify-end",
|
|
3381
|
-
children: /* @__PURE__ */ jsxs(Button, {
|
|
3382
|
-
type: "button",
|
|
3383
|
-
size: "sm",
|
|
3384
|
-
disabled: isPending || !canSave,
|
|
3385
|
-
onClick: () => onSave(provider.id),
|
|
3386
|
-
children: [isPending ? /* @__PURE__ */ jsx(Spinner, { "data-icon": "inline-start" }) : null, "Save"]
|
|
3387
|
-
})
|
|
3388
|
-
}),
|
|
3389
|
-
oauthAvailable ? /* @__PURE__ */ jsx(ProviderOAuthSignIn, {
|
|
3390
|
-
provider,
|
|
3391
|
-
onConfigured,
|
|
3392
|
-
onOAuthLogin
|
|
3393
|
-
}, `${provider.id}-oauth`) : null
|
|
3394
|
-
] })
|
|
3395
|
-
}) : null]
|
|
3396
|
-
}, provider.id);
|
|
3397
|
-
})
|
|
3398
|
-
});
|
|
3399
|
-
}
|
|
3400
|
-
function ProviderCredentialsSection({ isLoading, isPending, onOAuthLogin, onRemoveProvider, onUpdateProvider, providers }) {
|
|
3401
|
-
const { activeProviders, addPickerOpen, addPickerQuery, api, apiKey, attemptedSave, baseUrl, canSave, closeAddPicker, closeEditor, confirmRemoveProvider, credentialProviders, displayName, editingProvider, editingUnconfiguredProvider, filteredActiveProviders, filteredPickerAvailable, filteredPickerConfigured, handleRemove, handleSave, modelId, models, openAddPicker, openEditor, pickerHasResults, searchQuery, selectProviderFromPicker, setAddPickerQuery, setApi, setApiKey, setBaseUrl, setConfirmRemoveProvider, setDisplayName, setModelId, setModels, setSearchQuery, setShowPassword, showPassword } = useProviderCredentialsController({
|
|
3402
|
-
onRemoveProvider,
|
|
3403
|
-
onUpdateProvider,
|
|
3404
|
-
providers
|
|
3405
|
-
});
|
|
3406
|
-
const form = {
|
|
3407
|
-
api,
|
|
3408
|
-
apiKey,
|
|
3409
|
-
baseUrl,
|
|
3410
|
-
modelId,
|
|
3411
|
-
models,
|
|
3412
|
-
displayName,
|
|
3413
|
-
showPassword,
|
|
3414
|
-
attemptedSave,
|
|
3415
|
-
canSave
|
|
3416
|
-
};
|
|
3417
|
-
const operation = {
|
|
3418
|
-
isPending,
|
|
3419
|
-
canRemove: Boolean(onRemoveProvider)
|
|
3420
|
-
};
|
|
3421
|
-
const actions = {
|
|
3422
|
-
onApiKeyChange: setApiKey,
|
|
3423
|
-
onApiChange: setApi,
|
|
3424
|
-
onBaseUrlChange: setBaseUrl,
|
|
3425
|
-
onModelIdChange: setModelId,
|
|
3426
|
-
onModelsChange: setModels,
|
|
3427
|
-
onDisplayNameChange: setDisplayName,
|
|
3428
|
-
onTogglePassword: () => setShowPassword((current) => !current)
|
|
3429
|
-
};
|
|
3430
|
-
return /* @__PURE__ */ jsxs(SettingsPane, {
|
|
3431
|
-
title: "Providers",
|
|
3432
|
-
description: "Locally, API keys are stored in `.env.local`. When deployed, they are stored encrypted in your account.",
|
|
3433
|
-
children: [addPickerOpen ? /* @__PURE__ */ jsx(AddProviderPickerPanel, {
|
|
3434
|
-
addPickerQuery,
|
|
3435
|
-
credentialProvidersLength: credentialProviders.length,
|
|
3436
|
-
filteredPickerAvailable,
|
|
3437
|
-
filteredPickerConfigured,
|
|
3438
|
-
pickerHasResults,
|
|
3439
|
-
onClose: closeAddPicker,
|
|
3440
|
-
onQueryChange: setAddPickerQuery,
|
|
3441
|
-
onSelect: selectProviderFromPicker
|
|
3442
|
-
}) : editingUnconfiguredProvider && isOAuthProvider(editingUnconfiguredProvider) ? /* @__PURE__ */ jsx(AddProviderOAuthPanel, {
|
|
3443
|
-
provider: editingUnconfiguredProvider,
|
|
3444
|
-
onBack: openAddPicker,
|
|
3445
|
-
onConfigured: closeEditor,
|
|
3446
|
-
onOAuthLogin
|
|
3447
|
-
}, editingUnconfiguredProvider.id) : editingUnconfiguredProvider ? /* @__PURE__ */ jsx(AddProviderEditorPanel, {
|
|
3448
|
-
provider: editingUnconfiguredProvider,
|
|
3449
|
-
api,
|
|
3450
|
-
apiKey,
|
|
3451
|
-
baseUrl,
|
|
3452
|
-
modelId,
|
|
3453
|
-
models,
|
|
3454
|
-
displayName,
|
|
3455
|
-
showPassword,
|
|
3456
|
-
attemptedSave,
|
|
3457
|
-
isPending,
|
|
3458
|
-
canSave,
|
|
3459
|
-
onApiKeyChange: setApiKey,
|
|
3460
|
-
onApiChange: setApi,
|
|
3461
|
-
onBaseUrlChange: setBaseUrl,
|
|
3462
|
-
onModelIdChange: setModelId,
|
|
3463
|
-
onModelsChange: setModels,
|
|
3464
|
-
onDisplayNameChange: setDisplayName,
|
|
3465
|
-
onTogglePassword: () => setShowPassword((current) => !current),
|
|
3466
|
-
onBack: openAddPicker,
|
|
3467
|
-
onCancel: closeEditor,
|
|
3468
|
-
onConfigured: closeEditor,
|
|
3469
|
-
onOAuthLogin,
|
|
3470
|
-
onSave: () => {
|
|
3471
|
-
if (editingProvider) handleSave(editingProvider);
|
|
3472
|
-
}
|
|
3473
|
-
}) : /* @__PURE__ */ jsxs("div", {
|
|
3474
|
-
className: "flex flex-col gap-3",
|
|
3475
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
3476
|
-
className: "flex items-center gap-2",
|
|
3477
|
-
children: [/* @__PURE__ */ jsxs(InputGroup, {
|
|
3478
|
-
className: "flex-1",
|
|
3479
|
-
children: [/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
3480
|
-
align: "inline-start",
|
|
3481
|
-
children: /* @__PURE__ */ jsx(Search, {})
|
|
3482
|
-
}), /* @__PURE__ */ jsx(InputGroupInput, {
|
|
3483
|
-
type: "text",
|
|
3484
|
-
placeholder: "Search credentials\u2026",
|
|
3485
|
-
value: searchQuery,
|
|
3486
|
-
onChange: (event) => setSearchQuery(event.target.value),
|
|
3487
|
-
"aria-label": "Search credentials",
|
|
3488
|
-
disabled: isLoading || activeProviders.length === 0
|
|
3489
|
-
})]
|
|
3490
|
-
}), /* @__PURE__ */ jsxs(Button, {
|
|
3491
|
-
type: "button",
|
|
3492
|
-
variant: "outline",
|
|
3493
|
-
size: "sm",
|
|
3494
|
-
disabled: isLoading || credentialProviders.length === 0,
|
|
3495
|
-
onClick: openAddPicker,
|
|
3496
|
-
children: [/* @__PURE__ */ jsx(Plus, { "data-icon": "inline-start" }), "Add provider"]
|
|
3497
|
-
})]
|
|
3498
|
-
}), isLoading ? /* @__PURE__ */ jsxs("div", {
|
|
3499
|
-
className: "flex items-center justify-center gap-2 py-6 text-xs text-muted-foreground",
|
|
3500
|
-
children: [/* @__PURE__ */ jsx(Spinner, { className: "size-3" }), /* @__PURE__ */ jsx("span", { children: "Loading\u2026" })]
|
|
3501
|
-
}) : activeProviders.length === 0 ? /* @__PURE__ */ jsxs("div", {
|
|
3502
|
-
className: "flex flex-col items-center gap-3 py-8",
|
|
3503
|
-
children: [/* @__PURE__ */ jsx("p", {
|
|
3504
|
-
className: "text-center text-xs text-pretty text-muted-foreground",
|
|
3505
|
-
children: "No providers configured"
|
|
3506
|
-
}), /* @__PURE__ */ jsxs(Button, {
|
|
3507
|
-
type: "button",
|
|
3508
|
-
variant: "outline",
|
|
3509
|
-
size: "sm",
|
|
3510
|
-
disabled: credentialProviders.length === 0,
|
|
3511
|
-
onClick: openAddPicker,
|
|
3512
|
-
children: [/* @__PURE__ */ jsx(Plus, { "data-icon": "inline-start" }), "Add provider"]
|
|
3513
|
-
})]
|
|
3514
|
-
}) : filteredActiveProviders.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
3515
|
-
className: "py-6 text-center text-xs text-pretty text-muted-foreground",
|
|
3516
|
-
children: "No matching providers found."
|
|
3517
|
-
}) : /* @__PURE__ */ jsx(ActiveProviderList, {
|
|
3518
|
-
providers: filteredActiveProviders,
|
|
3519
|
-
editingProvider,
|
|
3520
|
-
form,
|
|
3521
|
-
operation,
|
|
3522
|
-
actions,
|
|
3523
|
-
onEdit: openEditor,
|
|
3524
|
-
onCancelEdit: closeEditor,
|
|
3525
|
-
onSave: (providerId) => void handleSave(providerId),
|
|
3526
|
-
onRemove: setConfirmRemoveProvider,
|
|
3527
|
-
onOAuthLogin,
|
|
3528
|
-
onConfigured: closeEditor
|
|
3529
|
-
})]
|
|
3530
|
-
}), /* @__PURE__ */ jsx(RemoveProviderConfirmDialog, {
|
|
3531
|
-
confirmRemoveProvider,
|
|
3532
|
-
isPending,
|
|
3533
|
-
onClose: () => setConfirmRemoveProvider(null),
|
|
3534
|
-
onConfirm: (provider) => {
|
|
3535
|
-
handleRemove(provider);
|
|
3536
|
-
}
|
|
3537
|
-
})]
|
|
3538
|
-
});
|
|
3539
|
-
}
|
|
3540
|
-
function customModelKey(provider, model) {
|
|
3541
|
-
return `${provider}/${model}`;
|
|
3542
|
-
}
|
|
3543
|
-
function isModelEnabled(model, patterns) {
|
|
3544
|
-
return isModelPatternEnabled({
|
|
3545
|
-
id: model.id,
|
|
3546
|
-
name: model.name,
|
|
3547
|
-
provider: model.provider,
|
|
3548
|
-
modelId: model.modelId
|
|
3549
|
-
}, patterns);
|
|
3550
|
-
}
|
|
3551
|
-
function nextEnabledModelPatterns({ currentPatterns, enabled, model, models }) {
|
|
3552
|
-
if (currentPatterns === void 0 && enabled) return void 0;
|
|
3553
|
-
const current = currentPatterns ?? [];
|
|
3554
|
-
const knownModelPatterns = new Set(models.map((item) => modelPatternFor(item)));
|
|
3555
|
-
const activeKnown = /* @__PURE__ */ new Set();
|
|
3556
|
-
for (const item of models) if (isModelEnabled(item, currentPatterns)) activeKnown.add(modelPatternFor(item));
|
|
3557
|
-
if (enabled) activeKnown.add(modelPatternFor(model));
|
|
3558
|
-
else activeKnown.delete(modelPatternFor(model));
|
|
3559
|
-
return [...current.filter((pattern) => {
|
|
3560
|
-
if (knownModelPatterns.has(pattern)) return false;
|
|
3561
|
-
return enabled || !modelMatchesPattern(model, pattern);
|
|
3562
|
-
}), ...activeKnown];
|
|
3563
|
-
}
|
|
3564
|
-
function modelPatternFor(model) {
|
|
3565
|
-
return modelPattern(model.provider, model.modelId);
|
|
3566
|
-
}
|
|
3567
|
-
function searchableModelText(model) {
|
|
3568
|
-
return [
|
|
3569
|
-
model.name,
|
|
3570
|
-
model.modelId,
|
|
3571
|
-
model.provider,
|
|
3572
|
-
model.id
|
|
3573
|
-
].join(" ").toLowerCase();
|
|
2970
|
+
function searchableModelText(model) {
|
|
2971
|
+
return [
|
|
2972
|
+
model.name,
|
|
2973
|
+
model.modelId,
|
|
2974
|
+
model.provider,
|
|
2975
|
+
model.id
|
|
2976
|
+
].join(" ").toLowerCase();
|
|
3574
2977
|
}
|
|
3575
2978
|
function AddModelsDialog({ configuredProviderIds, discoverableProviderIds, discoveringProviderId, enabledModels, modelOptions, onAddModels, onDiscoverProvider, onOpenChange, open, providerLabel = formatProviderLabel }) {
|
|
3576
2979
|
const [filter, setFilter] = useState2("");
|
|
@@ -3742,18 +3145,14 @@ function AddModelsDialog({ configuredProviderIds, discoverableProviderIds, disco
|
|
|
3742
3145
|
size: "sm",
|
|
3743
3146
|
disabled: selectedKeys.size === 0,
|
|
3744
3147
|
onClick: confirmAdd,
|
|
3745
|
-
children: [
|
|
3746
|
-
"
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
")"
|
|
3754
|
-
]
|
|
3755
|
-
}) : null
|
|
3756
|
-
]
|
|
3148
|
+
children: ["Add ", selectedKeys.size > 0 ? /* @__PURE__ */ jsxs("span", {
|
|
3149
|
+
className: "tabular-nums",
|
|
3150
|
+
children: [
|
|
3151
|
+
"(",
|
|
3152
|
+
selectedKeys.size,
|
|
3153
|
+
")"
|
|
3154
|
+
]
|
|
3155
|
+
}) : null]
|
|
3757
3156
|
})]
|
|
3758
3157
|
})
|
|
3759
3158
|
]
|
|
@@ -3824,8 +3223,7 @@ function ModelDefaultsSection({ draft, discoveringProviderId, modelDirty, modelF
|
|
|
3824
3223
|
return /* @__PURE__ */ jsxs(SettingsPane, {
|
|
3825
3224
|
title: "LLM Models",
|
|
3826
3225
|
description: /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
3827
|
-
"Models available in chat. Discover from configured providers, add the ones you want, and remove any you do not need \u2014 changes save automatically.",
|
|
3828
|
-
" ",
|
|
3226
|
+
"Models available in chat. Discover from configured providers, add the ones you want, and remove any you do not need \u2014 changes save automatically. ",
|
|
3829
3227
|
/* @__PURE__ */ jsx("span", {
|
|
3830
3228
|
className: "tabular-nums",
|
|
3831
3229
|
children: listedModels.length
|
|
@@ -3838,8 +3236,7 @@ function ModelDefaultsSection({ draft, discoveringProviderId, modelDirty, modelF
|
|
|
3838
3236
|
className: "tabular-nums",
|
|
3839
3237
|
children: modelOptions.length
|
|
3840
3238
|
}),
|
|
3841
|
-
" "
|
|
3842
|
-
"discovered"
|
|
3239
|
+
" discovered"
|
|
3843
3240
|
] }) : null,
|
|
3844
3241
|
"."
|
|
3845
3242
|
] }),
|
|
@@ -3853,200 +3250,989 @@ function ModelDefaultsSection({ draft, discoveringProviderId, modelDirty, modelF
|
|
|
3853
3250
|
children: [
|
|
3854
3251
|
/* @__PURE__ */ jsxs("div", {
|
|
3855
3252
|
className: "flex items-center gap-2",
|
|
3856
|
-
children: [/* @__PURE__ */ jsxs(InputGroup, {
|
|
3857
|
-
className: "flex-1",
|
|
3858
|
-
children: [/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
3859
|
-
align: "inline-start",
|
|
3860
|
-
children: /* @__PURE__ */ jsx(Search, {})
|
|
3861
|
-
}), /* @__PURE__ */ jsx(InputGroupInput, {
|
|
3862
|
-
"aria-label": "Search listed models",
|
|
3863
|
-
value: modelFilter,
|
|
3864
|
-
onChange: (event) => onModelFilterChange(event.target.value),
|
|
3865
|
-
placeholder: "Search listed models\u2026",
|
|
3866
|
-
disabled: disabled2 || listedModels.length === 0
|
|
3867
|
-
})]
|
|
3868
|
-
}), /* @__PURE__ */ jsxs(Button, {
|
|
3253
|
+
children: [/* @__PURE__ */ jsxs(InputGroup, {
|
|
3254
|
+
className: "flex-1",
|
|
3255
|
+
children: [/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
3256
|
+
align: "inline-start",
|
|
3257
|
+
children: /* @__PURE__ */ jsx(Search, {})
|
|
3258
|
+
}), /* @__PURE__ */ jsx(InputGroupInput, {
|
|
3259
|
+
"aria-label": "Search listed models",
|
|
3260
|
+
value: modelFilter,
|
|
3261
|
+
onChange: (event) => onModelFilterChange(event.target.value),
|
|
3262
|
+
placeholder: "Search listed models\u2026",
|
|
3263
|
+
disabled: disabled2 || listedModels.length === 0
|
|
3264
|
+
})]
|
|
3265
|
+
}), /* @__PURE__ */ jsxs(Button, {
|
|
3266
|
+
type: "button",
|
|
3267
|
+
variant: "outline",
|
|
3268
|
+
size: "sm",
|
|
3269
|
+
disabled: disabled2,
|
|
3270
|
+
onClick: openAddDialog,
|
|
3271
|
+
children: [/* @__PURE__ */ jsx(Plus, { "data-icon": "inline-start" }), "Add models"]
|
|
3272
|
+
})]
|
|
3273
|
+
}),
|
|
3274
|
+
/* @__PURE__ */ jsx("div", {
|
|
3275
|
+
className: "flex flex-col gap-3",
|
|
3276
|
+
"data-testid": "runtime-models-list",
|
|
3277
|
+
children: emptyMessage ? /* @__PURE__ */ jsxs("div", {
|
|
3278
|
+
className: "flex flex-col items-center gap-3 py-8",
|
|
3279
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
3280
|
+
className: "px-1 text-center text-xs text-pretty text-muted-foreground",
|
|
3281
|
+
children: emptyMessage
|
|
3282
|
+
}), !normalizedFilter ? /* @__PURE__ */ jsxs(Button, {
|
|
3283
|
+
type: "button",
|
|
3284
|
+
variant: "outline",
|
|
3285
|
+
size: "sm",
|
|
3286
|
+
disabled: disabled2,
|
|
3287
|
+
onClick: openAddDialog,
|
|
3288
|
+
children: [/* @__PURE__ */ jsx(Plus, { "data-icon": "inline-start" }), "Add models"]
|
|
3289
|
+
}) : null]
|
|
3290
|
+
}) : groupedListed.map(([provider, models]) => /* @__PURE__ */ jsxs("div", {
|
|
3291
|
+
className: "flex flex-col gap-1.5",
|
|
3292
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
3293
|
+
className: "px-1 text-xs font-medium text-muted-foreground",
|
|
3294
|
+
children: providerLabel(provider)
|
|
3295
|
+
}), models.map((model) => /* @__PURE__ */ jsx(ItemRow, {
|
|
3296
|
+
icon: /* @__PURE__ */ jsx(ProviderBrandIcon, { provider: model.provider }),
|
|
3297
|
+
title: model.name,
|
|
3298
|
+
subtitle: `${providerLabel(model.provider)} \xB7 ${model.modelId}`,
|
|
3299
|
+
trailing: /* @__PURE__ */ jsxs("div", {
|
|
3300
|
+
className: "flex items-center",
|
|
3301
|
+
children: [isDefaultModel(model) ? /* @__PURE__ */ jsx("span", {
|
|
3302
|
+
className: "px-2 text-xs font-medium text-muted-foreground",
|
|
3303
|
+
children: "Default"
|
|
3304
|
+
}) : onSetDefaultModel ? /* @__PURE__ */ jsxs(Button, {
|
|
3305
|
+
type: "button",
|
|
3306
|
+
variant: "ghost",
|
|
3307
|
+
size: "sm",
|
|
3308
|
+
className: cn(HIT_AREA_EXPAND_DENSE_CLASS, "h-7 px-2 text-xs text-muted-foreground transition-[background-color,color,transform] duration-150 active:scale-[0.96]"),
|
|
3309
|
+
disabled: disabled2,
|
|
3310
|
+
"aria-label": `Set ${model.name} as default`,
|
|
3311
|
+
onClick: () => onSetDefaultModel(model),
|
|
3312
|
+
children: [/* @__PURE__ */ jsx(Star, { "data-icon": "inline-start" }), "Set default"]
|
|
3313
|
+
}) : null, /* @__PURE__ */ jsxs(Button, {
|
|
3314
|
+
type: "button",
|
|
3315
|
+
variant: "ghost",
|
|
3316
|
+
size: "sm",
|
|
3317
|
+
className: cn(HIT_AREA_EXPAND_DENSE_CLASS, "h-7 px-2 text-xs text-muted-foreground transition-[background-color,color,transform] duration-150 hover:text-destructive active:scale-[0.96]"),
|
|
3318
|
+
disabled: disabled2,
|
|
3319
|
+
"aria-label": `Remove ${model.name}`,
|
|
3320
|
+
onClick: () => onRemoveModel(model),
|
|
3321
|
+
children: [/* @__PURE__ */ jsx(Trash2, { "data-icon": "inline-start" }), "Remove"]
|
|
3322
|
+
})]
|
|
3323
|
+
})
|
|
3324
|
+
}, model.id))]
|
|
3325
|
+
}, provider))
|
|
3326
|
+
}),
|
|
3327
|
+
/* @__PURE__ */ jsx(AddModelsDialog, {
|
|
3328
|
+
open: addOpen,
|
|
3329
|
+
configuredProviderIds,
|
|
3330
|
+
discoverableProviderIds,
|
|
3331
|
+
discoveringProviderId,
|
|
3332
|
+
enabledModels: draft?.enabledModels,
|
|
3333
|
+
modelOptions,
|
|
3334
|
+
onAddModels,
|
|
3335
|
+
onDiscoverProvider,
|
|
3336
|
+
onOpenChange: setAddOpen,
|
|
3337
|
+
providerLabel
|
|
3338
|
+
})
|
|
3339
|
+
]
|
|
3340
|
+
});
|
|
3341
|
+
}
|
|
3342
|
+
var THEME_OPTIONS = [
|
|
3343
|
+
{
|
|
3344
|
+
value: "system",
|
|
3345
|
+
label: "System",
|
|
3346
|
+
icon: Monitor
|
|
3347
|
+
},
|
|
3348
|
+
{
|
|
3349
|
+
value: "light",
|
|
3350
|
+
label: "Light",
|
|
3351
|
+
icon: Sun
|
|
3352
|
+
},
|
|
3353
|
+
{
|
|
3354
|
+
value: "dark",
|
|
3355
|
+
label: "Dark",
|
|
3356
|
+
icon: Moon
|
|
3357
|
+
}
|
|
3358
|
+
];
|
|
3359
|
+
function PersonalizationSection({ onThemePreferenceChange, themePreference }) {
|
|
3360
|
+
return /* @__PURE__ */ jsxs(Field, {
|
|
3361
|
+
orientation: "horizontal",
|
|
3362
|
+
className: "items-center justify-between gap-6 rounded-xl border p-4",
|
|
3363
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
3364
|
+
className: "min-w-0",
|
|
3365
|
+
children: [/* @__PURE__ */ jsx(FieldLabel, { children: "Theme" }), /* @__PURE__ */ jsx(FieldDescription, { children: "Match the system theme or pick light or dark." })]
|
|
3366
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
3367
|
+
className: "shrink-0",
|
|
3368
|
+
children: /* @__PURE__ */ jsx(Select, {
|
|
3369
|
+
"aria-label": "Theme",
|
|
3370
|
+
className: "w-[160px]",
|
|
3371
|
+
onValueChange: (value) => onThemePreferenceChange(value),
|
|
3372
|
+
options: [...THEME_OPTIONS],
|
|
3373
|
+
value: themePreference
|
|
3374
|
+
})
|
|
3375
|
+
})]
|
|
3376
|
+
});
|
|
3377
|
+
}
|
|
3378
|
+
function isFieldInvalid(value, attemptedSave, required = true) {
|
|
3379
|
+
return attemptedSave && required && value.trim().length === 0;
|
|
3380
|
+
}
|
|
3381
|
+
function SecretCredentialField({ attemptedSave, label, onChange, onToggleVisibility, placeholder, required = true, showPassword, value }) {
|
|
3382
|
+
const controlId = useId();
|
|
3383
|
+
const invalid = isFieldInvalid(value, attemptedSave, required);
|
|
3384
|
+
return /* @__PURE__ */ jsxs(Field, {
|
|
3385
|
+
"data-invalid": invalid || void 0,
|
|
3386
|
+
children: [/* @__PURE__ */ jsx(FieldLabel, {
|
|
3387
|
+
htmlFor: controlId,
|
|
3388
|
+
children: label
|
|
3389
|
+
}), /* @__PURE__ */ jsxs(InputGroup, { children: [
|
|
3390
|
+
/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
3391
|
+
align: "inline-start",
|
|
3392
|
+
children: /* @__PURE__ */ jsx(Lock, {})
|
|
3393
|
+
}),
|
|
3394
|
+
/* @__PURE__ */ jsx(InputGroupInput, {
|
|
3395
|
+
id: controlId,
|
|
3396
|
+
type: showPassword ? "text" : "password",
|
|
3397
|
+
placeholder,
|
|
3398
|
+
value,
|
|
3399
|
+
onChange: (event) => onChange(event.target.value),
|
|
3400
|
+
"aria-label": label,
|
|
3401
|
+
"aria-invalid": invalid || void 0
|
|
3402
|
+
}),
|
|
3403
|
+
/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
3404
|
+
align: "inline-end",
|
|
3405
|
+
children: /* @__PURE__ */ jsx(InputGroupButton, {
|
|
3406
|
+
size: "icon-xs",
|
|
3407
|
+
className: cn(HIT_AREA_EXPAND_CLASS, "transition-[background-color,transform] duration-150 active:scale-[0.96]"),
|
|
3408
|
+
"aria-label": showPassword ? "Hide value" : "Show value",
|
|
3409
|
+
onClick: onToggleVisibility,
|
|
3410
|
+
children: showPassword ? /* @__PURE__ */ jsx(EyeOff, {}) : /* @__PURE__ */ jsx(Eye, {})
|
|
3411
|
+
})
|
|
3412
|
+
})
|
|
3413
|
+
] })]
|
|
3414
|
+
});
|
|
3415
|
+
}
|
|
3416
|
+
function TextCredentialField({ attemptedSave, icon: Icon, inputType = "text", label, onChange, placeholder, required = true, value }) {
|
|
3417
|
+
const controlId = useId();
|
|
3418
|
+
const invalid = isFieldInvalid(value, attemptedSave, required);
|
|
3419
|
+
return /* @__PURE__ */ jsxs(Field, {
|
|
3420
|
+
"data-invalid": invalid || void 0,
|
|
3421
|
+
children: [/* @__PURE__ */ jsx(FieldLabel, {
|
|
3422
|
+
htmlFor: controlId,
|
|
3423
|
+
children: label
|
|
3424
|
+
}), /* @__PURE__ */ jsxs(InputGroup, { children: [/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
3425
|
+
align: "inline-start",
|
|
3426
|
+
children: /* @__PURE__ */ jsx(Icon, {})
|
|
3427
|
+
}), /* @__PURE__ */ jsx(InputGroupInput, {
|
|
3428
|
+
id: controlId,
|
|
3429
|
+
type: inputType,
|
|
3430
|
+
placeholder,
|
|
3431
|
+
value,
|
|
3432
|
+
onChange: (event) => onChange(event.target.value),
|
|
3433
|
+
"aria-label": label,
|
|
3434
|
+
"aria-invalid": invalid || void 0
|
|
3435
|
+
})] })]
|
|
3436
|
+
});
|
|
3437
|
+
}
|
|
3438
|
+
var OPENAI_CHAT_BASE_URL_PLACEHOLDER = "https://opencode.ai/zen/v1";
|
|
3439
|
+
var OPENAI_CHAT_MODEL_PLACEHOLDER = "qwen35-122b-a10b";
|
|
3440
|
+
var OPENAI_CHAT_NAME_PLACEHOLDER = "e.g. OpenCode Zen, Nebius, Groq\u2026";
|
|
3441
|
+
var CUSTOM_MODELS_PLACEHOLDER = "model-a, model-b (comma-separated)";
|
|
3442
|
+
var CUSTOM_PROVIDER_API_OPTIONS = [
|
|
3443
|
+
{
|
|
3444
|
+
value: "openai-completions",
|
|
3445
|
+
label: "OpenAI Chat Completions"
|
|
3446
|
+
},
|
|
3447
|
+
{
|
|
3448
|
+
value: "openai-responses",
|
|
3449
|
+
label: "OpenAI Responses"
|
|
3450
|
+
},
|
|
3451
|
+
{
|
|
3452
|
+
value: "anthropic-messages",
|
|
3453
|
+
label: "Anthropic Messages"
|
|
3454
|
+
},
|
|
3455
|
+
{
|
|
3456
|
+
value: "google-genai",
|
|
3457
|
+
label: "Google Generative AI"
|
|
3458
|
+
}
|
|
3459
|
+
];
|
|
3460
|
+
function ProviderCredentialFields({ attemptedSave, apiKey, api, baseUrl, modelId, models, displayName, isCustom, onApiKeyChange, onApiChange, onBaseUrlChange, onModelIdChange, onModelsChange, onDisplayNameChange, onTogglePassword, openAiChat, placeholder, showPassword }) {
|
|
3461
|
+
const showApiSelector = isCustom && onApiChange;
|
|
3462
|
+
const showMultiModels = isCustom && onModelsChange;
|
|
3463
|
+
return /* @__PURE__ */ jsxs(FieldGroup, {
|
|
3464
|
+
className: "gap-2",
|
|
3465
|
+
children: [
|
|
3466
|
+
(openAiChat || isCustom) && onDisplayNameChange ? /* @__PURE__ */ jsx(TextCredentialField, {
|
|
3467
|
+
attemptedSave,
|
|
3468
|
+
icon: Tag,
|
|
3469
|
+
label: "Provider name",
|
|
3470
|
+
placeholder: OPENAI_CHAT_NAME_PLACEHOLDER,
|
|
3471
|
+
value: displayName ?? "",
|
|
3472
|
+
onChange: onDisplayNameChange
|
|
3473
|
+
}) : null,
|
|
3474
|
+
showApiSelector ? /* @__PURE__ */ jsx(ApiSelector, {
|
|
3475
|
+
value: api ?? "openai-completions",
|
|
3476
|
+
onChange: onApiChange
|
|
3477
|
+
}) : null,
|
|
3478
|
+
/* @__PURE__ */ jsx(SecretCredentialField, {
|
|
3479
|
+
attemptedSave,
|
|
3480
|
+
label: "API key",
|
|
3481
|
+
placeholder,
|
|
3482
|
+
value: apiKey,
|
|
3483
|
+
showPassword,
|
|
3484
|
+
onChange: onApiKeyChange,
|
|
3485
|
+
onToggleVisibility: onTogglePassword
|
|
3486
|
+
}),
|
|
3487
|
+
openAiChat || isCustom ? /* @__PURE__ */ jsx(TextCredentialField, {
|
|
3488
|
+
attemptedSave,
|
|
3489
|
+
icon: Globe,
|
|
3490
|
+
inputType: "url",
|
|
3491
|
+
label: "Base URL",
|
|
3492
|
+
placeholder: OPENAI_CHAT_BASE_URL_PLACEHOLDER,
|
|
3493
|
+
value: baseUrl,
|
|
3494
|
+
onChange: onBaseUrlChange
|
|
3495
|
+
}) : null,
|
|
3496
|
+
showMultiModels ? /* @__PURE__ */ jsx(TextCredentialField, {
|
|
3497
|
+
attemptedSave,
|
|
3498
|
+
icon: Layers,
|
|
3499
|
+
label: "Model ids",
|
|
3500
|
+
placeholder: CUSTOM_MODELS_PLACEHOLDER,
|
|
3501
|
+
value: models ?? "",
|
|
3502
|
+
onChange: onModelsChange
|
|
3503
|
+
}) : null,
|
|
3504
|
+
openAiChat && !showMultiModels ? /* @__PURE__ */ jsx(TextCredentialField, {
|
|
3505
|
+
attemptedSave,
|
|
3506
|
+
icon: Box,
|
|
3507
|
+
label: "Model name",
|
|
3508
|
+
placeholder: OPENAI_CHAT_MODEL_PLACEHOLDER,
|
|
3509
|
+
value: modelId,
|
|
3510
|
+
onChange: onModelIdChange
|
|
3511
|
+
}) : null
|
|
3512
|
+
]
|
|
3513
|
+
});
|
|
3514
|
+
}
|
|
3515
|
+
function ApiSelector({ value, onChange }) {
|
|
3516
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3517
|
+
className: "flex flex-col gap-1",
|
|
3518
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
3519
|
+
className: "text-xs font-medium text-muted-foreground",
|
|
3520
|
+
children: "API family"
|
|
3521
|
+
}), /* @__PURE__ */ jsx(Select, {
|
|
3522
|
+
"aria-label": "API family",
|
|
3523
|
+
value,
|
|
3524
|
+
options: CUSTOM_PROVIDER_API_OPTIONS,
|
|
3525
|
+
placeholder: "Select API family",
|
|
3526
|
+
onValueChange: (next) => onChange(next)
|
|
3527
|
+
})]
|
|
3528
|
+
});
|
|
3529
|
+
}
|
|
3530
|
+
function isOAuthProvider(provider) {
|
|
3531
|
+
return provider.authType === "oauth";
|
|
3532
|
+
}
|
|
3533
|
+
function supportsOAuth(provider) {
|
|
3534
|
+
return provider.supportsOAuth === true;
|
|
3535
|
+
}
|
|
3536
|
+
var CUSTOM_PROVIDER_PICKER_ROW = {
|
|
3537
|
+
id: "custom",
|
|
3538
|
+
name: "Custom provider",
|
|
3539
|
+
isConfigured: false,
|
|
3540
|
+
envVarName: "CUSTOM_PROVIDER_API_KEY",
|
|
3541
|
+
displayName: "Custom provider"
|
|
3542
|
+
};
|
|
3543
|
+
function parseCustomProviderModels(raw) {
|
|
3544
|
+
return raw.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
3545
|
+
}
|
|
3546
|
+
function useProviderCredentialsController({ onRemoveProvider, onUpdateProvider, providers }) {
|
|
3547
|
+
const [editingProvider, setEditingProvider] = useState2(null);
|
|
3548
|
+
const [editingIsNewOccInstance, setEditingIsNewOccInstance] = useState2(false);
|
|
3549
|
+
const [apiKey, setApiKey] = useState2("");
|
|
3550
|
+
const [baseUrl, setBaseUrl] = useState2("");
|
|
3551
|
+
const [modelId, setModelId] = useState2("");
|
|
3552
|
+
const [models, setModels] = useState2("");
|
|
3553
|
+
const [api, setApi] = useState2("openai-completions");
|
|
3554
|
+
const [displayName, setDisplayName] = useState2("");
|
|
3555
|
+
const [showPassword, setShowPassword] = useState2(false);
|
|
3556
|
+
const [attemptedSave, setAttemptedSave] = useState2(false);
|
|
3557
|
+
const [searchQuery, setSearchQuery] = useState2("");
|
|
3558
|
+
const [addPickerOpen, setAddPickerOpen] = useState2(false);
|
|
3559
|
+
const [addPickerQuery, setAddPickerQuery] = useState2("");
|
|
3560
|
+
const [confirmRemoveProvider, setConfirmRemoveProvider] = useState2(null);
|
|
3561
|
+
const credentialProviders = useMemo2(() => {
|
|
3562
|
+
return [...providers.filter((provider) => provider.id !== CUSTOM_PROVIDER_PICKER_ROW.id), CUSTOM_PROVIDER_PICKER_ROW];
|
|
3563
|
+
}, [providers]);
|
|
3564
|
+
const activeProviders = useMemo2(() => credentialProviders.filter((provider) => provider.isConfigured), [credentialProviders]);
|
|
3565
|
+
const unconfiguredProviders = useMemo2(() => credentialProviders.filter((provider) => !provider.isConfigured || provider.id === "openai-chat-completions" && provider.providerFamily === void 0), [credentialProviders]);
|
|
3566
|
+
const filteredActiveProviders = useMemo2(() => {
|
|
3567
|
+
const query = searchQuery.trim().toLowerCase();
|
|
3568
|
+
if (!query) return activeProviders;
|
|
3569
|
+
return activeProviders.filter((provider) => providerMatchesQuery(provider, query));
|
|
3570
|
+
}, [activeProviders, searchQuery]);
|
|
3571
|
+
const filteredPickerAvailable = useMemo2(() => {
|
|
3572
|
+
const query = addPickerQuery.trim().toLowerCase();
|
|
3573
|
+
return unconfiguredProviders.filter((provider) => providerMatchesQuery(provider, query));
|
|
3574
|
+
}, [addPickerQuery, unconfiguredProviders]);
|
|
3575
|
+
const filteredPickerConfigured = useMemo2(() => {
|
|
3576
|
+
const query = addPickerQuery.trim().toLowerCase();
|
|
3577
|
+
return activeProviders.filter((provider) => providerMatchesQuery(provider, query));
|
|
3578
|
+
}, [activeProviders, addPickerQuery]);
|
|
3579
|
+
const pickerHasResults = filteredPickerAvailable.length > 0 || filteredPickerConfigured.length > 0;
|
|
3580
|
+
const editingUnconfiguredProvider = editingProvider && !activeProviders.some((provider) => provider.id === editingProvider) ? credentialProviders.find((entry) => entry.id === editingProvider) ?? null : null;
|
|
3581
|
+
const resetEditor = () => {
|
|
3582
|
+
setApiKey("");
|
|
3583
|
+
setBaseUrl("");
|
|
3584
|
+
setModelId("");
|
|
3585
|
+
setModels("");
|
|
3586
|
+
setApi("openai-completions");
|
|
3587
|
+
setDisplayName("");
|
|
3588
|
+
setShowPassword(false);
|
|
3589
|
+
setAttemptedSave(false);
|
|
3590
|
+
};
|
|
3591
|
+
const closeEditor = () => {
|
|
3592
|
+
setEditingProvider(null);
|
|
3593
|
+
setEditingIsNewOccInstance(false);
|
|
3594
|
+
resetEditor();
|
|
3595
|
+
};
|
|
3596
|
+
const openEditor = (providerId, opts) => {
|
|
3597
|
+
setAddPickerOpen(false);
|
|
3598
|
+
setAddPickerQuery("");
|
|
3599
|
+
setEditingProvider(providerId);
|
|
3600
|
+
setEditingIsNewOccInstance(opts?.newOccInstance === true);
|
|
3601
|
+
resetEditor();
|
|
3602
|
+
const existing = providers.find((provider) => provider.id === providerId);
|
|
3603
|
+
setBaseUrl(existing?.baseUrl ?? "");
|
|
3604
|
+
setDisplayName(existing?.displayName ?? (isCustomProviderId(providerId) ? existing?.name ?? "" : ""));
|
|
3605
|
+
setApi(existing?.api ?? "openai-completions");
|
|
3606
|
+
setModels((existing?.modelIds ?? []).join(", "));
|
|
3607
|
+
setModelId(existing?.modelIds?.[0] ?? "");
|
|
3608
|
+
};
|
|
3609
|
+
const openAddPicker = () => {
|
|
3610
|
+
closeEditor();
|
|
3611
|
+
setAddPickerQuery("");
|
|
3612
|
+
setAddPickerOpen(true);
|
|
3613
|
+
};
|
|
3614
|
+
const closeAddPicker = () => {
|
|
3615
|
+
setAddPickerOpen(false);
|
|
3616
|
+
setAddPickerQuery("");
|
|
3617
|
+
};
|
|
3618
|
+
const selectProviderFromPicker = (providerId) => {
|
|
3619
|
+
openEditor(providerId, { newOccInstance: isOccProviderId(providerId) });
|
|
3620
|
+
};
|
|
3621
|
+
const handleSave = async (providerId) => {
|
|
3622
|
+
if (!onUpdateProvider) return;
|
|
3623
|
+
setAttemptedSave(true);
|
|
3624
|
+
const isCustomEditor = providerId === "custom" || isCustomProviderId(providerId);
|
|
3625
|
+
const openAiChat = isOccProviderId(providerId);
|
|
3626
|
+
if (isCustomEditor) {
|
|
3627
|
+
const modelList = parseCustomProviderModels(models);
|
|
3628
|
+
if (!apiKey.trim() || !baseUrl.trim() || !displayName.trim()) return;
|
|
3629
|
+
if (modelList.length === 0) return;
|
|
3630
|
+
try {
|
|
3631
|
+
await onUpdateProvider({
|
|
3632
|
+
providerId,
|
|
3633
|
+
apiKey: apiKey.trim(),
|
|
3634
|
+
baseUrl: baseUrl.trim(),
|
|
3635
|
+
displayName: displayName.trim(),
|
|
3636
|
+
api,
|
|
3637
|
+
models: modelList,
|
|
3638
|
+
...providerId === "custom" ? { createOccInstance: true } : {}
|
|
3639
|
+
});
|
|
3640
|
+
notify.success("Provider credentials applied to your active sessions.");
|
|
3641
|
+
closeEditor();
|
|
3642
|
+
closeAddPicker();
|
|
3643
|
+
} catch (error) {
|
|
3644
|
+
notify.error(error instanceof Error ? error.message : "Failed to update provider");
|
|
3645
|
+
}
|
|
3646
|
+
return;
|
|
3647
|
+
}
|
|
3648
|
+
const isNamedOcc = openAiChat && isNamedOccInstanceId(providerId);
|
|
3649
|
+
const isOccLike = openAiChat && (isNamedOcc || editingIsNewOccInstance);
|
|
3650
|
+
if (!apiKey.trim()) return;
|
|
3651
|
+
if (openAiChat && (!baseUrl.trim() || !modelId.trim())) return;
|
|
3652
|
+
if (isOccLike && !displayName.trim()) return;
|
|
3653
|
+
try {
|
|
3654
|
+
await onUpdateProvider({
|
|
3655
|
+
providerId,
|
|
3656
|
+
apiKey: apiKey.trim(),
|
|
3657
|
+
...openAiChat ? {
|
|
3658
|
+
baseUrl: baseUrl.trim(),
|
|
3659
|
+
modelId: modelId.trim(),
|
|
3660
|
+
...isOccLike ? { displayName: displayName.trim() } : {},
|
|
3661
|
+
...editingIsNewOccInstance ? { createOccInstance: true } : {}
|
|
3662
|
+
} : {}
|
|
3663
|
+
});
|
|
3664
|
+
notify.success("Provider credentials applied to your active sessions.");
|
|
3665
|
+
closeEditor();
|
|
3666
|
+
closeAddPicker();
|
|
3667
|
+
} catch (error) {
|
|
3668
|
+
notify.error(error instanceof Error ? error.message : "Failed to update provider");
|
|
3669
|
+
}
|
|
3670
|
+
};
|
|
3671
|
+
const handleRemove = async (provider) => {
|
|
3672
|
+
if (!onRemoveProvider) return;
|
|
3673
|
+
try {
|
|
3674
|
+
await onRemoveProvider({ providerId: provider.id });
|
|
3675
|
+
if (editingProvider === provider.id) closeEditor();
|
|
3676
|
+
notify.success(`${provider.name} removed from your configured providers.`);
|
|
3677
|
+
setConfirmRemoveProvider(null);
|
|
3678
|
+
} catch (error) {
|
|
3679
|
+
notify.error(error instanceof Error ? error.message : "Failed to remove provider");
|
|
3680
|
+
}
|
|
3681
|
+
};
|
|
3682
|
+
return {
|
|
3683
|
+
activeProviders,
|
|
3684
|
+
addPickerOpen,
|
|
3685
|
+
addPickerQuery,
|
|
3686
|
+
api,
|
|
3687
|
+
apiKey,
|
|
3688
|
+
attemptedSave,
|
|
3689
|
+
baseUrl,
|
|
3690
|
+
canSave: useMemo2(() => {
|
|
3691
|
+
if (apiKey.trim().length === 0) return false;
|
|
3692
|
+
if (!editingProvider) return true;
|
|
3693
|
+
if (editingProvider === "custom" || isCustomProviderId(editingProvider)) {
|
|
3694
|
+
if (baseUrl.trim().length === 0) return false;
|
|
3695
|
+
if (parseCustomProviderModels(models).length === 0) return false;
|
|
3696
|
+
return displayName.trim().length > 0;
|
|
3697
|
+
}
|
|
3698
|
+
if (!isOccProviderId(editingProvider)) return true;
|
|
3699
|
+
if (baseUrl.trim().length === 0 || modelId.trim().length === 0) return false;
|
|
3700
|
+
if (isNamedOccInstanceId(editingProvider) || editingIsNewOccInstance) return displayName.trim().length > 0;
|
|
3701
|
+
return true;
|
|
3702
|
+
}, [
|
|
3703
|
+
apiKey,
|
|
3704
|
+
baseUrl,
|
|
3705
|
+
modelId,
|
|
3706
|
+
models,
|
|
3707
|
+
displayName,
|
|
3708
|
+
editingProvider,
|
|
3709
|
+
editingIsNewOccInstance
|
|
3710
|
+
]),
|
|
3711
|
+
closeAddPicker,
|
|
3712
|
+
closeEditor,
|
|
3713
|
+
confirmRemoveProvider,
|
|
3714
|
+
credentialProviders,
|
|
3715
|
+
displayName,
|
|
3716
|
+
editingIsNewOccInstance,
|
|
3717
|
+
editingProvider,
|
|
3718
|
+
editingUnconfiguredProvider,
|
|
3719
|
+
filteredActiveProviders,
|
|
3720
|
+
filteredPickerAvailable,
|
|
3721
|
+
filteredPickerConfigured,
|
|
3722
|
+
handleRemove,
|
|
3723
|
+
handleSave,
|
|
3724
|
+
modelId,
|
|
3725
|
+
models,
|
|
3726
|
+
openAddPicker,
|
|
3727
|
+
openEditor,
|
|
3728
|
+
pickerHasResults,
|
|
3729
|
+
resetEditor,
|
|
3730
|
+
searchQuery,
|
|
3731
|
+
selectProviderFromPicker,
|
|
3732
|
+
setAddPickerOpen,
|
|
3733
|
+
setAddPickerQuery,
|
|
3734
|
+
setApi,
|
|
3735
|
+
setApiKey,
|
|
3736
|
+
setAttemptedSave,
|
|
3737
|
+
setBaseUrl,
|
|
3738
|
+
setConfirmRemoveProvider,
|
|
3739
|
+
setDisplayName,
|
|
3740
|
+
setEditingIsNewOccInstance,
|
|
3741
|
+
setEditingProvider,
|
|
3742
|
+
setModelId,
|
|
3743
|
+
setModels,
|
|
3744
|
+
setSearchQuery,
|
|
3745
|
+
setShowPassword,
|
|
3746
|
+
showPassword,
|
|
3747
|
+
unconfiguredProviders
|
|
3748
|
+
};
|
|
3749
|
+
}
|
|
3750
|
+
function providerMatchesQuery(provider, query) {
|
|
3751
|
+
if (!query) return true;
|
|
3752
|
+
const keywords = supportsOAuth(provider) ? isOAuthProvider(provider) ? "oauth sign-in login" : "api key oauth sign-in login" : provider.id === "custom" || isCustomProviderId(provider.id) ? "custom provider endpoint openai anthropic google compatible" : isOccProviderId(provider.id) ? "api key base url model name chat completions" : "";
|
|
3753
|
+
return [
|
|
3754
|
+
provider.name,
|
|
3755
|
+
provider.envVarName,
|
|
3756
|
+
provider.id,
|
|
3757
|
+
keywords
|
|
3758
|
+
].join(" ").toLowerCase().includes(query);
|
|
3759
|
+
}
|
|
3760
|
+
function AddProviderPickerPanel({ addPickerQuery, credentialProvidersLength, filteredPickerAvailable, filteredPickerConfigured, pickerHasResults, onClose, onQueryChange, onSelect }) {
|
|
3761
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3762
|
+
className: "flex flex-col gap-3",
|
|
3763
|
+
children: [
|
|
3764
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3765
|
+
className: "flex items-center gap-2",
|
|
3766
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
3869
3767
|
type: "button",
|
|
3870
|
-
variant: "
|
|
3871
|
-
size: "sm",
|
|
3872
|
-
|
|
3873
|
-
onClick:
|
|
3874
|
-
children:
|
|
3768
|
+
variant: "ghost",
|
|
3769
|
+
size: "icon-sm",
|
|
3770
|
+
"aria-label": "Back to providers",
|
|
3771
|
+
onClick: onClose,
|
|
3772
|
+
children: /* @__PURE__ */ jsx(ArrowLeft, {})
|
|
3773
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
3774
|
+
className: "min-w-0 flex-1",
|
|
3775
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
3776
|
+
className: "text-sm font-medium",
|
|
3777
|
+
children: "Add provider"
|
|
3778
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
3779
|
+
className: "text-xs text-pretty text-muted-foreground",
|
|
3780
|
+
children: "Choose a provider to store encrypted credentials for this account."
|
|
3781
|
+
})]
|
|
3875
3782
|
})]
|
|
3876
3783
|
}),
|
|
3784
|
+
/* @__PURE__ */ jsxs(InputGroup, { children: [/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
3785
|
+
align: "inline-start",
|
|
3786
|
+
children: /* @__PURE__ */ jsx(Search, {})
|
|
3787
|
+
}), /* @__PURE__ */ jsx(InputGroupInput, {
|
|
3788
|
+
type: "text",
|
|
3789
|
+
placeholder: "Search providers\u2026",
|
|
3790
|
+
value: addPickerQuery,
|
|
3791
|
+
onChange: (event) => onQueryChange(event.target.value),
|
|
3792
|
+
"aria-label": "Search providers to add"
|
|
3793
|
+
})] }),
|
|
3877
3794
|
/* @__PURE__ */ jsx("div", {
|
|
3878
|
-
className: "
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3795
|
+
className: "max-h-[min(24rem,50vh)] overflow-y-auto",
|
|
3796
|
+
children: !pickerHasResults ? /* @__PURE__ */ jsx("p", {
|
|
3797
|
+
className: "py-6 text-center text-xs text-pretty text-muted-foreground",
|
|
3798
|
+
children: credentialProvidersLength === 0 ? "No providers available." : "No matching providers found."
|
|
3799
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
3800
|
+
className: "flex flex-col gap-3",
|
|
3801
|
+
children: [filteredPickerAvailable.length > 0 ? /* @__PURE__ */ jsx("div", {
|
|
3802
|
+
className: "flex flex-col gap-1",
|
|
3803
|
+
children: filteredPickerAvailable.map((provider) => /* @__PURE__ */ jsx(ProviderPickerRow, {
|
|
3804
|
+
provider,
|
|
3805
|
+
configured: false,
|
|
3806
|
+
onSelect: () => onSelect(provider.id)
|
|
3807
|
+
}, provider.id))
|
|
3808
|
+
}) : null, filteredPickerConfigured.length > 0 ? /* @__PURE__ */ jsxs("div", {
|
|
3809
|
+
className: "flex flex-col gap-1",
|
|
3810
|
+
children: [filteredPickerAvailable.length > 0 ? /* @__PURE__ */ jsx("p", {
|
|
3811
|
+
className: "px-2 pt-1 text-[0.6875rem] font-medium tracking-wide text-muted-foreground uppercase",
|
|
3812
|
+
children: "Already configured"
|
|
3813
|
+
}) : null, filteredPickerConfigured.map((provider) => /* @__PURE__ */ jsx(ProviderPickerRow, {
|
|
3814
|
+
provider,
|
|
3815
|
+
configured: true,
|
|
3816
|
+
onSelect: () => onSelect(provider.id)
|
|
3817
|
+
}, provider.id))]
|
|
3892
3818
|
}) : null]
|
|
3893
|
-
})
|
|
3894
|
-
className: "flex flex-col gap-1.5",
|
|
3895
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
3896
|
-
className: "px-1 text-xs font-medium text-muted-foreground",
|
|
3897
|
-
children: providerLabel(provider)
|
|
3898
|
-
}), models.map((model) => /* @__PURE__ */ jsx(ItemRow, {
|
|
3899
|
-
icon: /* @__PURE__ */ jsx(ProviderBrandIcon, { provider: model.provider }),
|
|
3900
|
-
title: model.name,
|
|
3901
|
-
subtitle: `${providerLabel(model.provider)} \xB7 ${model.modelId}`,
|
|
3902
|
-
trailing: /* @__PURE__ */ jsxs("div", {
|
|
3903
|
-
className: "flex items-center",
|
|
3904
|
-
children: [isDefaultModel(model) ? /* @__PURE__ */ jsx("span", {
|
|
3905
|
-
className: "px-2 text-xs font-medium text-muted-foreground",
|
|
3906
|
-
children: "Default"
|
|
3907
|
-
}) : onSetDefaultModel ? /* @__PURE__ */ jsxs(Button, {
|
|
3908
|
-
type: "button",
|
|
3909
|
-
variant: "ghost",
|
|
3910
|
-
size: "sm",
|
|
3911
|
-
className: cn(HIT_AREA_EXPAND_DENSE_CLASS, "h-7 px-2 text-xs text-muted-foreground transition-[background-color,color,transform] duration-150 active:scale-[0.96]"),
|
|
3912
|
-
disabled: disabled2,
|
|
3913
|
-
"aria-label": `Set ${model.name} as default`,
|
|
3914
|
-
onClick: () => onSetDefaultModel(model),
|
|
3915
|
-
children: [/* @__PURE__ */ jsx(Star, { "data-icon": "inline-start" }), "Set default"]
|
|
3916
|
-
}) : null, /* @__PURE__ */ jsxs(Button, {
|
|
3917
|
-
type: "button",
|
|
3918
|
-
variant: "ghost",
|
|
3919
|
-
size: "sm",
|
|
3920
|
-
className: cn(HIT_AREA_EXPAND_DENSE_CLASS, "h-7 px-2 text-xs text-muted-foreground transition-[background-color,color,transform] duration-150 hover:text-destructive active:scale-[0.96]"),
|
|
3921
|
-
disabled: disabled2,
|
|
3922
|
-
"aria-label": `Remove ${model.name}`,
|
|
3923
|
-
onClick: () => onRemoveModel(model),
|
|
3924
|
-
children: [/* @__PURE__ */ jsx(Trash2, { "data-icon": "inline-start" }), "Remove"]
|
|
3925
|
-
})]
|
|
3926
|
-
})
|
|
3927
|
-
}, model.id))]
|
|
3928
|
-
}, provider))
|
|
3929
|
-
}),
|
|
3930
|
-
/* @__PURE__ */ jsx(AddModelsDialog, {
|
|
3931
|
-
open: addOpen,
|
|
3932
|
-
configuredProviderIds,
|
|
3933
|
-
discoverableProviderIds,
|
|
3934
|
-
discoveringProviderId,
|
|
3935
|
-
enabledModels: draft?.enabledModels,
|
|
3936
|
-
modelOptions,
|
|
3937
|
-
onAddModels,
|
|
3938
|
-
onDiscoverProvider,
|
|
3939
|
-
onOpenChange: setAddOpen,
|
|
3940
|
-
providerLabel
|
|
3819
|
+
})
|
|
3941
3820
|
})
|
|
3942
3821
|
]
|
|
3943
3822
|
});
|
|
3944
3823
|
}
|
|
3945
|
-
|
|
3946
|
-
{
|
|
3947
|
-
value: "auto",
|
|
3948
|
-
label: "Auto"
|
|
3949
|
-
},
|
|
3950
|
-
{
|
|
3951
|
-
value: "sse",
|
|
3952
|
-
label: "SSE"
|
|
3953
|
-
},
|
|
3954
|
-
{
|
|
3955
|
-
value: "websocket",
|
|
3956
|
-
label: "WebSocket"
|
|
3957
|
-
}
|
|
3958
|
-
];
|
|
3959
|
-
var DELIVERY_OPTIONS = [{
|
|
3960
|
-
value: "all",
|
|
3961
|
-
label: "All"
|
|
3962
|
-
}, {
|
|
3963
|
-
value: "one-at-a-time",
|
|
3964
|
-
label: "One at a time"
|
|
3965
|
-
}];
|
|
3966
|
-
function HarnessRuntimeSection({ draft, updateDraft }) {
|
|
3967
|
-
const disabled2 = !draft;
|
|
3824
|
+
function AddProviderOAuthPanel({ onBack, onConfigured, onOAuthLogin, provider }) {
|
|
3968
3825
|
return /* @__PURE__ */ jsxs("div", {
|
|
3969
|
-
className: "flex flex-col gap-
|
|
3826
|
+
className: "flex flex-col gap-3",
|
|
3827
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
3828
|
+
className: "flex items-center gap-2",
|
|
3829
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
3830
|
+
type: "button",
|
|
3831
|
+
variant: "ghost",
|
|
3832
|
+
size: "icon-sm",
|
|
3833
|
+
"aria-label": "Back to provider list",
|
|
3834
|
+
onClick: onBack,
|
|
3835
|
+
children: /* @__PURE__ */ jsx(ArrowLeft, {})
|
|
3836
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
3837
|
+
className: "min-w-0 flex-1",
|
|
3838
|
+
children: [/* @__PURE__ */ jsxs("p", {
|
|
3839
|
+
className: "text-sm font-medium",
|
|
3840
|
+
children: ["Configure ", provider.name]
|
|
3841
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
3842
|
+
className: "text-xs text-pretty text-muted-foreground",
|
|
3843
|
+
children: "OAuth sign-in. Credentials are stored in auth.json for this account."
|
|
3844
|
+
})]
|
|
3845
|
+
})]
|
|
3846
|
+
}), /* @__PURE__ */ jsx(ProviderOAuthSignIn, {
|
|
3847
|
+
provider,
|
|
3848
|
+
onConfigured,
|
|
3849
|
+
onOAuthLogin
|
|
3850
|
+
}, provider.id)]
|
|
3851
|
+
});
|
|
3852
|
+
}
|
|
3853
|
+
function AddProviderEditorPanel({ provider, api, apiKey, baseUrl, modelId, models, displayName, showPassword, attemptedSave, isPending, canSave, onApiKeyChange, onApiChange, onBaseUrlChange, onModelIdChange, onModelsChange, onDisplayNameChange, onTogglePassword, onBack, onCancel, onConfigured, onOAuthLogin, onSave }) {
|
|
3854
|
+
const isCustomTemplate = provider.id === "custom" || isCustomProviderId(provider.id);
|
|
3855
|
+
const meta = PROVIDER_METADATA[provider.id] ?? (isCustomTemplate ? PROVIDER_METADATA["custom"] : {
|
|
3856
|
+
placeholder: "Enter credentials\u2026",
|
|
3857
|
+
help: "Stored securely in your local environment overrides."
|
|
3858
|
+
});
|
|
3859
|
+
const openAiChat = isOccProviderId(provider.id) && !isCustomTemplate;
|
|
3860
|
+
const oauthAvailable = supportsOAuth(provider);
|
|
3861
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3862
|
+
className: "flex flex-col gap-3",
|
|
3970
3863
|
children: [
|
|
3971
|
-
/* @__PURE__ */
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
trailing: /* @__PURE__ */ jsx(Switch, {
|
|
3991
|
-
"aria-label": "Auto-retry",
|
|
3992
|
-
checked: draft?.retry.enabled ?? false,
|
|
3993
|
-
disabled: disabled2,
|
|
3994
|
-
onCheckedChange: (enabled) => updateDraft((current) => ({
|
|
3995
|
-
...current,
|
|
3996
|
-
retry: {
|
|
3997
|
-
...current.retry,
|
|
3998
|
-
enabled
|
|
3999
|
-
}
|
|
4000
|
-
}))
|
|
4001
|
-
})
|
|
3864
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3865
|
+
className: "flex items-center gap-2",
|
|
3866
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
3867
|
+
type: "button",
|
|
3868
|
+
variant: "ghost",
|
|
3869
|
+
size: "icon-sm",
|
|
3870
|
+
"aria-label": "Back to provider list",
|
|
3871
|
+
onClick: onBack,
|
|
3872
|
+
children: /* @__PURE__ */ jsx(ArrowLeft, {})
|
|
3873
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
3874
|
+
className: "min-w-0 flex-1",
|
|
3875
|
+
children: [/* @__PURE__ */ jsxs("p", {
|
|
3876
|
+
className: "text-sm font-medium",
|
|
3877
|
+
children: ["Configure ", provider.name]
|
|
3878
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
3879
|
+
className: "text-xs text-pretty text-muted-foreground",
|
|
3880
|
+
children: isCustomTemplate ? "Name this custom provider, pick its API family, then enter its API key, https base URL, and model ids." : openAiChat ? "Name this OpenAI-compatible provider, then enter its API key, base URL, and model name." : `Stored as ${provider.envVarName} for this account.`
|
|
3881
|
+
})]
|
|
3882
|
+
})]
|
|
4002
3883
|
}),
|
|
4003
|
-
/* @__PURE__ */ jsx(
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
3884
|
+
/* @__PURE__ */ jsx(ProviderCredentialFields, {
|
|
3885
|
+
attemptedSave,
|
|
3886
|
+
api,
|
|
3887
|
+
apiKey,
|
|
3888
|
+
baseUrl,
|
|
3889
|
+
modelId,
|
|
3890
|
+
models,
|
|
3891
|
+
displayName,
|
|
3892
|
+
isCustom: isCustomTemplate,
|
|
3893
|
+
openAiChat,
|
|
3894
|
+
placeholder: meta.placeholder,
|
|
3895
|
+
showPassword,
|
|
3896
|
+
onApiKeyChange,
|
|
3897
|
+
onApiChange,
|
|
3898
|
+
onBaseUrlChange,
|
|
3899
|
+
onModelIdChange,
|
|
3900
|
+
onModelsChange,
|
|
3901
|
+
onDisplayNameChange,
|
|
3902
|
+
onTogglePassword
|
|
4016
3903
|
}),
|
|
4017
|
-
/* @__PURE__ */
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
disabled: disabled2,
|
|
4024
|
-
onValueChange: (value) => updateDraft((current) => ({
|
|
4025
|
-
...current,
|
|
4026
|
-
steeringMode: value
|
|
4027
|
-
})),
|
|
4028
|
-
options: [...DELIVERY_OPTIONS],
|
|
4029
|
-
value: draft?.steeringMode ?? "all"
|
|
4030
|
-
})
|
|
3904
|
+
/* @__PURE__ */ jsxs(Alert, {
|
|
3905
|
+
className: "px-3 py-2",
|
|
3906
|
+
children: [/* @__PURE__ */ jsx(Info, {}), /* @__PURE__ */ jsx(AlertDescription, {
|
|
3907
|
+
className: "text-xs text-pretty",
|
|
3908
|
+
children: meta.help
|
|
3909
|
+
})]
|
|
4031
3910
|
}),
|
|
4032
|
-
/* @__PURE__ */
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
3911
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3912
|
+
className: "flex items-center justify-end gap-1.5",
|
|
3913
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
3914
|
+
type: "button",
|
|
3915
|
+
variant: "ghost",
|
|
3916
|
+
size: "sm",
|
|
3917
|
+
onClick: onCancel,
|
|
3918
|
+
children: "Cancel"
|
|
3919
|
+
}), /* @__PURE__ */ jsxs(Button, {
|
|
3920
|
+
type: "button",
|
|
3921
|
+
size: "sm",
|
|
3922
|
+
disabled: isPending || !canSave,
|
|
3923
|
+
onClick: onSave,
|
|
3924
|
+
children: [isPending ? /* @__PURE__ */ jsx(Spinner, { "data-icon": "inline-start" }) : null, "Save"]
|
|
3925
|
+
})]
|
|
3926
|
+
}),
|
|
3927
|
+
oauthAvailable ? /* @__PURE__ */ jsx(ProviderOAuthSignIn, {
|
|
3928
|
+
provider,
|
|
3929
|
+
onConfigured: onConfigured ?? onCancel,
|
|
3930
|
+
onOAuthLogin
|
|
3931
|
+
}, `${provider.id}-oauth`) : null
|
|
4047
3932
|
]
|
|
4048
3933
|
});
|
|
4049
3934
|
}
|
|
3935
|
+
function RemoveProviderConfirmDialog({ confirmRemoveProvider, isPending, onClose, onConfirm }) {
|
|
3936
|
+
return /* @__PURE__ */ jsx(AlertDialog, {
|
|
3937
|
+
open: confirmRemoveProvider !== null,
|
|
3938
|
+
onOpenChange: (open) => {
|
|
3939
|
+
if (!open) onClose();
|
|
3940
|
+
},
|
|
3941
|
+
children: /* @__PURE__ */ jsxs(AlertDialogContent, { children: [/* @__PURE__ */ jsxs("div", {
|
|
3942
|
+
className: "flex flex-col gap-2",
|
|
3943
|
+
children: [/* @__PURE__ */ jsxs(AlertDialogTitle, { children: [
|
|
3944
|
+
"Remove ",
|
|
3945
|
+
confirmRemoveProvider?.name ?? "provider",
|
|
3946
|
+
"?"
|
|
3947
|
+
] }), /* @__PURE__ */ jsx(AlertDialogDescription, { children: "This clears stored credentials for this provider from your workspace settings. Active sessions will stop using it immediately." })]
|
|
3948
|
+
}), /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [/* @__PURE__ */ jsx(AlertDialogCancel, {
|
|
3949
|
+
disabled: isPending,
|
|
3950
|
+
children: "Cancel"
|
|
3951
|
+
}), /* @__PURE__ */ jsxs(AlertDialogAction, {
|
|
3952
|
+
disabled: isPending || !confirmRemoveProvider,
|
|
3953
|
+
onClick: () => {
|
|
3954
|
+
if (confirmRemoveProvider) onConfirm(confirmRemoveProvider);
|
|
3955
|
+
},
|
|
3956
|
+
children: [isPending ? /* @__PURE__ */ jsx(Spinner, { "data-icon": "inline-start" }) : null, "Remove provider"]
|
|
3957
|
+
})] })] })
|
|
3958
|
+
});
|
|
3959
|
+
}
|
|
3960
|
+
function ProviderPickerRow({ configured, onSelect, provider }) {
|
|
3961
|
+
const openAiChat = isOccProviderId(provider.id);
|
|
3962
|
+
const isCustomTemplate = provider.id === "custom" || isCustomProviderId(provider.id);
|
|
3963
|
+
const oauthOnly = isOAuthProvider(provider);
|
|
3964
|
+
const oauthAvailable = supportsOAuth(provider);
|
|
3965
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
3966
|
+
type: "button",
|
|
3967
|
+
className: cn("flex w-full items-center gap-3 rounded-lg px-2 py-2 text-left transition-[background-color,transform] duration-150", "hover:bg-muted/60 focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none active:scale-[0.96]"),
|
|
3968
|
+
onClick: onSelect,
|
|
3969
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
3970
|
+
className: "flex size-8 shrink-0 items-center justify-center rounded-[4px] border border-border/40 bg-background/60",
|
|
3971
|
+
children: /* @__PURE__ */ jsx(ProviderBrandIcon, {
|
|
3972
|
+
provider: isCustomTemplate ? "custom" : provider.id,
|
|
3973
|
+
api: provider.api,
|
|
3974
|
+
className: "text-foreground/70"
|
|
3975
|
+
})
|
|
3976
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
3977
|
+
className: "min-w-0 flex-1",
|
|
3978
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
3979
|
+
className: "truncate text-sm font-medium",
|
|
3980
|
+
children: provider.name
|
|
3981
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
3982
|
+
className: "truncate text-xs text-muted-foreground",
|
|
3983
|
+
children: [oauthOnly ? "OAuth sign-in" : oauthAvailable ? "API key or OAuth" : isCustomTemplate ? "API family + key + https base URL + models" : openAiChat ? "API key + base URL + model name" : provider.envVarName, configured ? " \xB7 Update" : ""]
|
|
3984
|
+
})]
|
|
3985
|
+
})]
|
|
3986
|
+
});
|
|
3987
|
+
}
|
|
3988
|
+
function ActiveProviderList({ providers, editingProvider, form, operation, actions, onEdit, onCancelEdit, onSave, onRemove, onOAuthLogin, onConfigured }) {
|
|
3989
|
+
const { api, apiKey, baseUrl, modelId, models, displayName, showPassword, attemptedSave, canSave } = form;
|
|
3990
|
+
const { isPending, canRemove } = operation;
|
|
3991
|
+
const { onApiKeyChange, onApiChange, onBaseUrlChange, onModelIdChange, onModelsChange, onDisplayNameChange, onTogglePassword } = actions;
|
|
3992
|
+
return /* @__PURE__ */ jsx("div", {
|
|
3993
|
+
className: "flex flex-col gap-1.5",
|
|
3994
|
+
children: providers.map((provider) => {
|
|
3995
|
+
const isEditing = editingProvider === provider.id;
|
|
3996
|
+
const isCustom = isCustomProviderId(provider.id);
|
|
3997
|
+
const meta = PROVIDER_METADATA[provider.id] ?? PROVIDER_METADATA[isCustom ? "custom" : "openai-chat-completions"];
|
|
3998
|
+
const openAiChat = isOccProviderId(provider.id);
|
|
3999
|
+
const oauthOnly = isOAuthProvider(provider);
|
|
4000
|
+
const oauthAvailable = supportsOAuth(provider);
|
|
4001
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4002
|
+
className: "flex flex-col",
|
|
4003
|
+
children: [/* @__PURE__ */ jsx(ItemRow, {
|
|
4004
|
+
interactive: false,
|
|
4005
|
+
icon: /* @__PURE__ */ jsx(ProviderBrandIcon, {
|
|
4006
|
+
provider: provider.id,
|
|
4007
|
+
api: provider.api,
|
|
4008
|
+
className: "text-foreground/80"
|
|
4009
|
+
}),
|
|
4010
|
+
title: provider.name,
|
|
4011
|
+
subtitle: oauthOnly ? "OAuth sign-in" : oauthAvailable ? "API key or OAuth" : isCustom ? "Custom provider \xB7 API key + base URL + models" : openAiChat ? "OpenAI-compatible \xB7 API key + base URL + model name" : provider.envVarName,
|
|
4012
|
+
trailing: /* @__PURE__ */ jsxs("div", {
|
|
4013
|
+
className: "flex items-center gap-0.5",
|
|
4014
|
+
children: [/* @__PURE__ */ jsxs(Button, {
|
|
4015
|
+
type: "button",
|
|
4016
|
+
variant: "ghost",
|
|
4017
|
+
size: "sm",
|
|
4018
|
+
className: cn(HIT_AREA_EXPAND_DENSE_CLASS, "h-7 px-2 text-xs text-muted-foreground transition-[background-color,color,transform] duration-150 hover:text-destructive active:scale-[0.96]"),
|
|
4019
|
+
disabled: isPending || !canRemove,
|
|
4020
|
+
"aria-label": `Remove ${provider.name}`,
|
|
4021
|
+
onClick: () => onRemove(provider),
|
|
4022
|
+
children: [/* @__PURE__ */ jsx(Trash2, { "data-icon": "inline-start" }), "Remove"]
|
|
4023
|
+
}), /* @__PURE__ */ jsxs(Button, {
|
|
4024
|
+
type: "button",
|
|
4025
|
+
variant: "ghost",
|
|
4026
|
+
size: "sm",
|
|
4027
|
+
className: cn(HIT_AREA_EXPAND_DENSE_CLASS, "h-7 px-2 text-xs transition-[background-color,transform] duration-150 active:scale-[0.96]"),
|
|
4028
|
+
disabled: isPending,
|
|
4029
|
+
onClick: () => {
|
|
4030
|
+
if (isEditing) {
|
|
4031
|
+
onCancelEdit();
|
|
4032
|
+
return;
|
|
4033
|
+
}
|
|
4034
|
+
onEdit(provider.id);
|
|
4035
|
+
},
|
|
4036
|
+
children: [!isEditing ? /* @__PURE__ */ jsx(Pencil, { "data-icon": "inline-start" }) : null, isEditing ? "Cancel" : "Update"]
|
|
4037
|
+
})]
|
|
4038
|
+
})
|
|
4039
|
+
}), isEditing ? /* @__PURE__ */ jsx(RowSurface, {
|
|
4040
|
+
tone: "inset",
|
|
4041
|
+
padding: "md",
|
|
4042
|
+
className: "flex flex-col gap-2 border-t border-border/30",
|
|
4043
|
+
children: oauthOnly ? /* @__PURE__ */ jsx(ProviderOAuthSignIn, {
|
|
4044
|
+
provider,
|
|
4045
|
+
onConfigured,
|
|
4046
|
+
onOAuthLogin
|
|
4047
|
+
}, provider.id) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
4048
|
+
/* @__PURE__ */ jsx(ProviderCredentialFields, {
|
|
4049
|
+
attemptedSave,
|
|
4050
|
+
api: provider.api ?? api,
|
|
4051
|
+
apiKey,
|
|
4052
|
+
baseUrl,
|
|
4053
|
+
modelId,
|
|
4054
|
+
models,
|
|
4055
|
+
displayName,
|
|
4056
|
+
isCustom,
|
|
4057
|
+
openAiChat,
|
|
4058
|
+
placeholder: meta.placeholder,
|
|
4059
|
+
showPassword,
|
|
4060
|
+
onApiKeyChange,
|
|
4061
|
+
onApiChange,
|
|
4062
|
+
onBaseUrlChange,
|
|
4063
|
+
onModelIdChange,
|
|
4064
|
+
onModelsChange,
|
|
4065
|
+
onDisplayNameChange: isCustom || provider.providerFamily !== void 0 ? onDisplayNameChange : void 0,
|
|
4066
|
+
onTogglePassword
|
|
4067
|
+
}),
|
|
4068
|
+
/* @__PURE__ */ jsxs(Alert, {
|
|
4069
|
+
className: "px-3 py-2",
|
|
4070
|
+
children: [/* @__PURE__ */ jsx(Info, {}), /* @__PURE__ */ jsx(AlertDescription, {
|
|
4071
|
+
className: "text-xs text-pretty",
|
|
4072
|
+
children: meta.help
|
|
4073
|
+
})]
|
|
4074
|
+
}),
|
|
4075
|
+
/* @__PURE__ */ jsx("div", {
|
|
4076
|
+
className: "flex items-center justify-end",
|
|
4077
|
+
children: /* @__PURE__ */ jsxs(Button, {
|
|
4078
|
+
type: "button",
|
|
4079
|
+
size: "sm",
|
|
4080
|
+
disabled: isPending || !canSave,
|
|
4081
|
+
onClick: () => onSave(provider.id),
|
|
4082
|
+
children: [isPending ? /* @__PURE__ */ jsx(Spinner, { "data-icon": "inline-start" }) : null, "Save"]
|
|
4083
|
+
})
|
|
4084
|
+
}),
|
|
4085
|
+
oauthAvailable ? /* @__PURE__ */ jsx(ProviderOAuthSignIn, {
|
|
4086
|
+
provider,
|
|
4087
|
+
onConfigured,
|
|
4088
|
+
onOAuthLogin
|
|
4089
|
+
}, `${provider.id}-oauth`) : null
|
|
4090
|
+
] })
|
|
4091
|
+
}) : null]
|
|
4092
|
+
}, provider.id);
|
|
4093
|
+
})
|
|
4094
|
+
});
|
|
4095
|
+
}
|
|
4096
|
+
function ProviderCredentialsSection({ isLoading, isPending, onOAuthLogin, onRemoveProvider, onUpdateProvider, providers }) {
|
|
4097
|
+
const { activeProviders, addPickerOpen, addPickerQuery, api, apiKey, attemptedSave, baseUrl, canSave, closeAddPicker, closeEditor, confirmRemoveProvider, credentialProviders, displayName, editingProvider, editingUnconfiguredProvider, filteredActiveProviders, filteredPickerAvailable, filteredPickerConfigured, handleRemove, handleSave, modelId, models, openAddPicker, openEditor, pickerHasResults, searchQuery, selectProviderFromPicker, setAddPickerQuery, setApi, setApiKey, setBaseUrl, setConfirmRemoveProvider, setDisplayName, setModelId, setModels, setSearchQuery, setShowPassword, showPassword } = useProviderCredentialsController({
|
|
4098
|
+
onRemoveProvider,
|
|
4099
|
+
onUpdateProvider,
|
|
4100
|
+
providers
|
|
4101
|
+
});
|
|
4102
|
+
const form = {
|
|
4103
|
+
api,
|
|
4104
|
+
apiKey,
|
|
4105
|
+
baseUrl,
|
|
4106
|
+
modelId,
|
|
4107
|
+
models,
|
|
4108
|
+
displayName,
|
|
4109
|
+
showPassword,
|
|
4110
|
+
attemptedSave,
|
|
4111
|
+
canSave
|
|
4112
|
+
};
|
|
4113
|
+
const operation = {
|
|
4114
|
+
isPending,
|
|
4115
|
+
canRemove: Boolean(onRemoveProvider)
|
|
4116
|
+
};
|
|
4117
|
+
const actions = {
|
|
4118
|
+
onApiKeyChange: setApiKey,
|
|
4119
|
+
onApiChange: setApi,
|
|
4120
|
+
onBaseUrlChange: setBaseUrl,
|
|
4121
|
+
onModelIdChange: setModelId,
|
|
4122
|
+
onModelsChange: setModels,
|
|
4123
|
+
onDisplayNameChange: setDisplayName,
|
|
4124
|
+
onTogglePassword: () => setShowPassword((current) => !current)
|
|
4125
|
+
};
|
|
4126
|
+
return /* @__PURE__ */ jsxs(SettingsPane, {
|
|
4127
|
+
title: "Providers",
|
|
4128
|
+
description: "Locally, API keys are stored in `.env.local`. When deployed, they are stored encrypted in your account.",
|
|
4129
|
+
children: [addPickerOpen ? /* @__PURE__ */ jsx(AddProviderPickerPanel, {
|
|
4130
|
+
addPickerQuery,
|
|
4131
|
+
credentialProvidersLength: credentialProviders.length,
|
|
4132
|
+
filteredPickerAvailable,
|
|
4133
|
+
filteredPickerConfigured,
|
|
4134
|
+
pickerHasResults,
|
|
4135
|
+
onClose: closeAddPicker,
|
|
4136
|
+
onQueryChange: setAddPickerQuery,
|
|
4137
|
+
onSelect: selectProviderFromPicker
|
|
4138
|
+
}) : editingUnconfiguredProvider && isOAuthProvider(editingUnconfiguredProvider) ? /* @__PURE__ */ jsx(AddProviderOAuthPanel, {
|
|
4139
|
+
provider: editingUnconfiguredProvider,
|
|
4140
|
+
onBack: openAddPicker,
|
|
4141
|
+
onConfigured: closeEditor,
|
|
4142
|
+
onOAuthLogin
|
|
4143
|
+
}, editingUnconfiguredProvider.id) : editingUnconfiguredProvider ? /* @__PURE__ */ jsx(AddProviderEditorPanel, {
|
|
4144
|
+
provider: editingUnconfiguredProvider,
|
|
4145
|
+
api,
|
|
4146
|
+
apiKey,
|
|
4147
|
+
baseUrl,
|
|
4148
|
+
modelId,
|
|
4149
|
+
models,
|
|
4150
|
+
displayName,
|
|
4151
|
+
showPassword,
|
|
4152
|
+
attemptedSave,
|
|
4153
|
+
isPending,
|
|
4154
|
+
canSave,
|
|
4155
|
+
onApiKeyChange: setApiKey,
|
|
4156
|
+
onApiChange: setApi,
|
|
4157
|
+
onBaseUrlChange: setBaseUrl,
|
|
4158
|
+
onModelIdChange: setModelId,
|
|
4159
|
+
onModelsChange: setModels,
|
|
4160
|
+
onDisplayNameChange: setDisplayName,
|
|
4161
|
+
onTogglePassword: () => setShowPassword((current) => !current),
|
|
4162
|
+
onBack: openAddPicker,
|
|
4163
|
+
onCancel: closeEditor,
|
|
4164
|
+
onConfigured: closeEditor,
|
|
4165
|
+
onOAuthLogin,
|
|
4166
|
+
onSave: () => {
|
|
4167
|
+
if (editingProvider) handleSave(editingProvider);
|
|
4168
|
+
}
|
|
4169
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
4170
|
+
className: "flex flex-col gap-3",
|
|
4171
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
4172
|
+
className: "flex items-center gap-2",
|
|
4173
|
+
children: [/* @__PURE__ */ jsxs(InputGroup, {
|
|
4174
|
+
className: "flex-1",
|
|
4175
|
+
children: [/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
4176
|
+
align: "inline-start",
|
|
4177
|
+
children: /* @__PURE__ */ jsx(Search, {})
|
|
4178
|
+
}), /* @__PURE__ */ jsx(InputGroupInput, {
|
|
4179
|
+
type: "text",
|
|
4180
|
+
placeholder: "Search credentials\u2026",
|
|
4181
|
+
value: searchQuery,
|
|
4182
|
+
onChange: (event) => setSearchQuery(event.target.value),
|
|
4183
|
+
"aria-label": "Search credentials",
|
|
4184
|
+
disabled: isLoading || activeProviders.length === 0
|
|
4185
|
+
})]
|
|
4186
|
+
}), /* @__PURE__ */ jsxs(Button, {
|
|
4187
|
+
type: "button",
|
|
4188
|
+
variant: "outline",
|
|
4189
|
+
size: "sm",
|
|
4190
|
+
disabled: isLoading || credentialProviders.length === 0,
|
|
4191
|
+
onClick: openAddPicker,
|
|
4192
|
+
children: [/* @__PURE__ */ jsx(Plus, { "data-icon": "inline-start" }), "Add provider"]
|
|
4193
|
+
})]
|
|
4194
|
+
}), isLoading ? /* @__PURE__ */ jsxs("div", {
|
|
4195
|
+
className: "flex items-center justify-center gap-2 py-6 text-xs text-muted-foreground",
|
|
4196
|
+
children: [/* @__PURE__ */ jsx(Spinner, { className: "size-3" }), /* @__PURE__ */ jsx("span", { children: "Loading\u2026" })]
|
|
4197
|
+
}) : activeProviders.length === 0 ? /* @__PURE__ */ jsxs("div", {
|
|
4198
|
+
className: "flex flex-col items-center gap-3 py-8",
|
|
4199
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
4200
|
+
className: "text-center text-xs text-pretty text-muted-foreground",
|
|
4201
|
+
children: "No providers configured"
|
|
4202
|
+
}), /* @__PURE__ */ jsxs(Button, {
|
|
4203
|
+
type: "button",
|
|
4204
|
+
variant: "outline",
|
|
4205
|
+
size: "sm",
|
|
4206
|
+
disabled: credentialProviders.length === 0,
|
|
4207
|
+
onClick: openAddPicker,
|
|
4208
|
+
children: [/* @__PURE__ */ jsx(Plus, { "data-icon": "inline-start" }), "Add provider"]
|
|
4209
|
+
})]
|
|
4210
|
+
}) : filteredActiveProviders.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
4211
|
+
className: "py-6 text-center text-xs text-pretty text-muted-foreground",
|
|
4212
|
+
children: "No matching providers found."
|
|
4213
|
+
}) : /* @__PURE__ */ jsx(ActiveProviderList, {
|
|
4214
|
+
providers: filteredActiveProviders,
|
|
4215
|
+
editingProvider,
|
|
4216
|
+
form,
|
|
4217
|
+
operation,
|
|
4218
|
+
actions,
|
|
4219
|
+
onEdit: openEditor,
|
|
4220
|
+
onCancelEdit: closeEditor,
|
|
4221
|
+
onSave: (providerId) => void handleSave(providerId),
|
|
4222
|
+
onRemove: setConfirmRemoveProvider,
|
|
4223
|
+
onOAuthLogin,
|
|
4224
|
+
onConfigured: closeEditor
|
|
4225
|
+
})]
|
|
4226
|
+
}), /* @__PURE__ */ jsx(RemoveProviderConfirmDialog, {
|
|
4227
|
+
confirmRemoveProvider,
|
|
4228
|
+
isPending,
|
|
4229
|
+
onClose: () => setConfirmRemoveProvider(null),
|
|
4230
|
+
onConfirm: (provider) => {
|
|
4231
|
+
handleRemove(provider);
|
|
4232
|
+
}
|
|
4233
|
+
})]
|
|
4234
|
+
});
|
|
4235
|
+
}
|
|
4050
4236
|
var PROVENANCE_SOURCES = /* @__PURE__ */ new Set([
|
|
4051
4237
|
"auto",
|
|
4052
4238
|
"global",
|
|
@@ -4163,6 +4349,111 @@ function CatalogValueList({ addLabel, catalog, onChange, placeholder, values })
|
|
|
4163
4349
|
})] })]
|
|
4164
4350
|
});
|
|
4165
4351
|
}
|
|
4352
|
+
var TRANSPORT_OPTIONS = [
|
|
4353
|
+
{
|
|
4354
|
+
value: "auto",
|
|
4355
|
+
label: "Auto"
|
|
4356
|
+
},
|
|
4357
|
+
{
|
|
4358
|
+
value: "sse",
|
|
4359
|
+
label: "SSE"
|
|
4360
|
+
},
|
|
4361
|
+
{
|
|
4362
|
+
value: "websocket",
|
|
4363
|
+
label: "WebSocket"
|
|
4364
|
+
}
|
|
4365
|
+
];
|
|
4366
|
+
var DELIVERY_OPTIONS = [{
|
|
4367
|
+
value: "all",
|
|
4368
|
+
label: "All"
|
|
4369
|
+
}, {
|
|
4370
|
+
value: "one-at-a-time",
|
|
4371
|
+
label: "One at a time"
|
|
4372
|
+
}];
|
|
4373
|
+
function HarnessRuntimeSection({ draft, updateDraft }) {
|
|
4374
|
+
const disabled2 = !draft;
|
|
4375
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4376
|
+
className: "flex flex-col gap-2",
|
|
4377
|
+
children: [
|
|
4378
|
+
/* @__PURE__ */ jsx(ItemRow, {
|
|
4379
|
+
title: "Compaction",
|
|
4380
|
+
subtitle: "Summarize old turns when context fills up",
|
|
4381
|
+
trailing: /* @__PURE__ */ jsx(Switch, {
|
|
4382
|
+
"aria-label": "Compaction",
|
|
4383
|
+
checked: draft?.compaction.enabled ?? false,
|
|
4384
|
+
disabled: disabled2,
|
|
4385
|
+
onCheckedChange: (enabled) => updateDraft((current) => ({
|
|
4386
|
+
...current,
|
|
4387
|
+
compaction: {
|
|
4388
|
+
...current.compaction,
|
|
4389
|
+
enabled
|
|
4390
|
+
}
|
|
4391
|
+
}))
|
|
4392
|
+
})
|
|
4393
|
+
}),
|
|
4394
|
+
/* @__PURE__ */ jsx(ItemRow, {
|
|
4395
|
+
title: "Auto-retry",
|
|
4396
|
+
subtitle: "Retry failed provider requests",
|
|
4397
|
+
trailing: /* @__PURE__ */ jsx(Switch, {
|
|
4398
|
+
"aria-label": "Auto-retry",
|
|
4399
|
+
checked: draft?.retry.enabled ?? false,
|
|
4400
|
+
disabled: disabled2,
|
|
4401
|
+
onCheckedChange: (enabled) => updateDraft((current) => ({
|
|
4402
|
+
...current,
|
|
4403
|
+
retry: {
|
|
4404
|
+
...current.retry,
|
|
4405
|
+
enabled
|
|
4406
|
+
}
|
|
4407
|
+
}))
|
|
4408
|
+
})
|
|
4409
|
+
}),
|
|
4410
|
+
/* @__PURE__ */ jsx(ItemRow, {
|
|
4411
|
+
title: "Transport",
|
|
4412
|
+
trailing: /* @__PURE__ */ jsx(Select, {
|
|
4413
|
+
"aria-label": "Transport",
|
|
4414
|
+
className: "w-[160px]",
|
|
4415
|
+
disabled: disabled2,
|
|
4416
|
+
onValueChange: (value) => updateDraft((current) => ({
|
|
4417
|
+
...current,
|
|
4418
|
+
transport: value
|
|
4419
|
+
})),
|
|
4420
|
+
options: [...TRANSPORT_OPTIONS],
|
|
4421
|
+
value: draft?.transport ?? "auto"
|
|
4422
|
+
})
|
|
4423
|
+
}),
|
|
4424
|
+
/* @__PURE__ */ jsx(ItemRow, {
|
|
4425
|
+
title: "Steering",
|
|
4426
|
+
subtitle: "How queued steers are delivered mid-turn",
|
|
4427
|
+
trailing: /* @__PURE__ */ jsx(Select, {
|
|
4428
|
+
"aria-label": "Steering",
|
|
4429
|
+
className: "w-[160px]",
|
|
4430
|
+
disabled: disabled2,
|
|
4431
|
+
onValueChange: (value) => updateDraft((current) => ({
|
|
4432
|
+
...current,
|
|
4433
|
+
steeringMode: value
|
|
4434
|
+
})),
|
|
4435
|
+
options: [...DELIVERY_OPTIONS],
|
|
4436
|
+
value: draft?.steeringMode ?? "all"
|
|
4437
|
+
})
|
|
4438
|
+
}),
|
|
4439
|
+
/* @__PURE__ */ jsx(ItemRow, {
|
|
4440
|
+
title: "Follow-up",
|
|
4441
|
+
subtitle: "How queued follow-ups run after the turn",
|
|
4442
|
+
trailing: /* @__PURE__ */ jsx(Select, {
|
|
4443
|
+
"aria-label": "Follow-up",
|
|
4444
|
+
className: "w-[160px]",
|
|
4445
|
+
disabled: disabled2,
|
|
4446
|
+
onValueChange: (value) => updateDraft((current) => ({
|
|
4447
|
+
...current,
|
|
4448
|
+
followUpMode: value
|
|
4449
|
+
})),
|
|
4450
|
+
options: [...DELIVERY_OPTIONS],
|
|
4451
|
+
value: draft?.followUpMode ?? "all"
|
|
4452
|
+
})
|
|
4453
|
+
})
|
|
4454
|
+
]
|
|
4455
|
+
});
|
|
4456
|
+
}
|
|
4166
4457
|
function ResourcesSection({ draft, onEnableSkillCommandsChange, onExtensionsChange, onPackageRowsChange, onPromptsChange, onRevert, onSave, onSkillsChange, onThemesChange, packageError, packageRows, resourceDirty, resources, resourceSummary, saving, scope = "harness", settingsLoading, updateDraft }) {
|
|
4167
4458
|
const disabled2 = !draft || settingsLoading || !!packageError;
|
|
4168
4459
|
const catalogSubtitle = resourceSummary.total === 0 ? "Empty" : resourceSummary.reloadRequired > 0 ? `${resourceSummary.total} \xB7 ${resourceSummary.reloadRequired} reload` : `${resourceSummary.total}`;
|
|
@@ -4679,6 +4970,14 @@ var SETTINGS_SECTION_REGISTRY = {
|
|
|
4679
4970
|
icon: MessageSquare,
|
|
4680
4971
|
group: "workspace"
|
|
4681
4972
|
},
|
|
4973
|
+
mcp: {
|
|
4974
|
+
id: "mcp",
|
|
4975
|
+
order: 25,
|
|
4976
|
+
title: "MCP",
|
|
4977
|
+
ariaLabel: "MCP connection settings",
|
|
4978
|
+
icon: Plug,
|
|
4979
|
+
group: "workspace"
|
|
4980
|
+
},
|
|
4682
4981
|
sandbox: {
|
|
4683
4982
|
id: "sandbox",
|
|
4684
4983
|
order: 30,
|
|
@@ -4768,7 +5067,7 @@ function PreferenceRow({ children, description, label }) {
|
|
|
4768
5067
|
});
|
|
4769
5068
|
}
|
|
4770
5069
|
function useSettingsForm() {
|
|
4771
|
-
const { isLoadingProviders, isUpdatingProvider, modelCatalog, onDiscoverModels, onOAuthLogin, onRemoveProvider, onThemePreferenceChange, onUpdateProvider, providers = [], saveSettings, settings, settingsLoading, themePreference } = useSettingsActionsContext();
|
|
5070
|
+
const { isLoadingMcp, isLoadingProviders, isUpdatingMcp, isUpdatingProvider, mcpConnections = [], modelCatalog, onDiscoverModels, onMcpOAuth, onOAuthLogin, onRemoveMcp, onRemoveProvider, onThemePreferenceChange, onUpdateMcp, onUpdateProvider, providers = [], saveSettings, settings, settingsLoading, themePreference } = useSettingsActionsContext();
|
|
4772
5071
|
const { models, resources } = useChatPanelDataContext();
|
|
4773
5072
|
const [draft, setDraft] = useState2(null);
|
|
4774
5073
|
const [savingSection, setSavingSection] = useState2(null);
|
|
@@ -4832,11 +5131,17 @@ function useSettingsForm() {
|
|
|
4832
5131
|
return "close";
|
|
4833
5132
|
};
|
|
4834
5133
|
return {
|
|
5134
|
+
isLoadingMcp,
|
|
4835
5135
|
isLoadingProviders,
|
|
5136
|
+
isUpdatingMcp,
|
|
4836
5137
|
isUpdatingProvider,
|
|
4837
|
-
|
|
5138
|
+
mcpConnections,
|
|
5139
|
+
onMcpOAuth,
|
|
4838
5140
|
onOAuthLogin,
|
|
5141
|
+
onRemoveMcp,
|
|
4839
5142
|
onRemoveProvider,
|
|
5143
|
+
onThemePreferenceChange,
|
|
5144
|
+
onUpdateMcp,
|
|
4840
5145
|
onUpdateProvider,
|
|
4841
5146
|
providers,
|
|
4842
5147
|
resources,
|
|
@@ -4907,7 +5212,7 @@ function SettingsDialogSession({ initialTab, onOpenChange, open }) {
|
|
|
4907
5212
|
});
|
|
4908
5213
|
}
|
|
4909
5214
|
function SettingsDialogPaneContent({ activeTab, form, preferences, updatePreference }) {
|
|
4910
|
-
const { isLoadingProviders, isUpdatingProvider,
|
|
5215
|
+
const { isLoadingMcp, isLoadingProviders, isUpdatingMcp, isUpdatingProvider, mcpConnections, onMcpOAuth, onOAuthLogin, onRemoveMcp, onRemoveProvider, onThemePreferenceChange, onUpdateMcp, onUpdateProvider, providers, resources, settingsLoading, themePreference, draft, savingSection, packageRows, packageError, modelFilter, setModelFilter, resourceSummary, modelOptions, modelDirty, resourceDirty, revertResourceDraft, revertModelDraft, updateDraft, handlePackageRowsChange, addModels, removeModel, setDefaultModel, discoverProvider, discoveringProviderId, saveSection } = form;
|
|
4911
5216
|
const resourcesPane = (scope) => /* @__PURE__ */ jsx(ResourcesSection, {
|
|
4912
5217
|
scope,
|
|
4913
5218
|
draft,
|
|
@@ -5017,6 +5322,14 @@ function SettingsDialogPaneContent({ activeTab, form, preferences, updatePrefere
|
|
|
5017
5322
|
})
|
|
5018
5323
|
})]
|
|
5019
5324
|
}),
|
|
5325
|
+
mcp: () => /* @__PURE__ */ jsx(McpConnectionsSection, {
|
|
5326
|
+
connections: mcpConnections,
|
|
5327
|
+
isLoading: isLoadingMcp ?? false,
|
|
5328
|
+
isPending: isUpdatingMcp ?? false,
|
|
5329
|
+
onOAuth: onMcpOAuth,
|
|
5330
|
+
onRemove: onRemoveMcp,
|
|
5331
|
+
onUpsert: onUpdateMcp
|
|
5332
|
+
}),
|
|
5020
5333
|
sandbox: () => /* @__PURE__ */ jsx(SandboxProviderSection, {
|
|
5021
5334
|
isLoading: isLoadingProviders ?? false,
|
|
5022
5335
|
isPending: isUpdatingProvider ?? false,
|