@tonyclaw/llm-inspector 1.14.6 → 1.14.7
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/.output/nitro.json +1 -1
- package/.output/public/assets/index-Cmi8TfeU.js +105 -0
- package/.output/public/assets/{index-BFNoWwFI.css → index-DXUNTCVh.css} +1 -1
- package/.output/public/assets/{main-Dp5657Eq.js → main-BV7uNIIz.js} +1 -1
- package/.output/server/_libs/radix-ui__react-tooltip.mjs +1 -1
- package/.output/server/_ssr/{index-D2yS8VvO.mjs → index-BvHLASu8.mjs} +72 -17
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-DCfjmmJu.mjs → router-lUOA8pi6.mjs} +2 -2
- package/.output/server/{_tanstack-start-manifest_v-DupqJc5d.mjs → _tanstack-start-manifest_v-XNH7fVPN.mjs} +1 -1
- package/.output/server/index.mjs +27 -27
- package/package.json +1 -1
- package/src/components/providers/ImportWizardDialog.tsx +6 -0
- package/src/components/providers/ProvidersPanel.tsx +39 -11
- package/src/components/ui/confirm-dialog.tsx +51 -0
- package/.output/public/assets/index-LH-YtFEM.js +0 -105
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
|
|
2
|
-
import { C as CapturedLogSchema, a as parseRequest, s as stripClaudeCodeBillingHeader, R as RuntimeConfigSchema, c as createPendingProviderTestResults, P as ProviderTestResultsSchema, b as createFailedProviderTestResults, d as ProviderConfigSchema, p as parseOpenAIResponse, I as InspectorResponseSchema } from "./router-
|
|
2
|
+
import { C as CapturedLogSchema, a as parseRequest, s as stripClaudeCodeBillingHeader, R as RuntimeConfigSchema, c as createPendingProviderTestResults, P as ProviderTestResultsSchema, b as createFailedProviderTestResults, d as ProviderConfigSchema, p as parseOpenAIResponse, I as InspectorResponseSchema } from "./router-lUOA8pi6.mjs";
|
|
3
3
|
import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
|
|
4
4
|
import { u as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
|
|
5
5
|
import { J as JSZip } from "../_libs/jszip.mjs";
|
|
@@ -14,8 +14,8 @@ import { D as Download, L as LayoutGrid, a as List, G as GitCompareArrows, X, S
|
|
|
14
14
|
import { M as Markdown } from "../_libs/react-markdown.mjs";
|
|
15
15
|
import { a as array, b as string, u as union, d as object, l as literal, n as number, c as boolean, _ as _enum } from "../_libs/zod.mjs";
|
|
16
16
|
import { R as Root2$1, L as List$1, T as Trigger$2, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
|
|
17
|
-
import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
|
|
18
17
|
import { P as Provider, R as Root3, T as Trigger$3, a as Portal$2, C as Content2$1, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.mjs";
|
|
18
|
+
import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
|
|
19
19
|
import { R as Root$1 } from "../_libs/radix-ui__react-separator.mjs";
|
|
20
20
|
import { R as Root$2, C as CollapsibleTrigger$1, a as CollapsibleContent$1 } from "../_libs/radix-ui__react-collapsible.mjs";
|
|
21
21
|
import { R as Root$3, V as Viewport$1, C as Corner, S as ScrollAreaScrollbar, a as ScrollAreaThumb } from "../_libs/radix-ui__react-scroll-area.mjs";
|
|
@@ -276,7 +276,7 @@ async function exportLogsAsZip(logs) {
|
|
|
276
276
|
document.body.removeChild(anchor);
|
|
277
277
|
URL.revokeObjectURL(url);
|
|
278
278
|
}
|
|
279
|
-
const version = "1.14.
|
|
279
|
+
const version = "1.14.7";
|
|
280
280
|
const packageJson = {
|
|
281
281
|
version
|
|
282
282
|
};
|
|
@@ -3015,6 +3015,10 @@ function ImportWizardDialog({
|
|
|
3015
3015
|
return;
|
|
3016
3016
|
}
|
|
3017
3017
|
const result = parsed.data;
|
|
3018
|
+
setProviders(
|
|
3019
|
+
(prev) => prev.map((p, i) => selected.has(i) ? { ...p, alreadyExists: true } : p)
|
|
3020
|
+
);
|
|
3021
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
3018
3022
|
if (result.errors !== void 0 && result.errors.length > 0 && result.message !== void 0) {
|
|
3019
3023
|
setImportResult(result.message);
|
|
3020
3024
|
} else {
|
|
@@ -3109,6 +3113,35 @@ function ImportWizardDialog({
|
|
|
3109
3113
|
] })
|
|
3110
3114
|
] }) });
|
|
3111
3115
|
}
|
|
3116
|
+
function ConfirmDialog({
|
|
3117
|
+
open,
|
|
3118
|
+
onOpenChange,
|
|
3119
|
+
title,
|
|
3120
|
+
description,
|
|
3121
|
+
confirmLabel = "Confirm",
|
|
3122
|
+
variant = "default",
|
|
3123
|
+
onConfirm
|
|
3124
|
+
}) {
|
|
3125
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { children: [
|
|
3126
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { children: title }) }),
|
|
3127
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground", children: description }),
|
|
3128
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [
|
|
3129
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "outline", size: "sm", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
3130
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3131
|
+
Button,
|
|
3132
|
+
{
|
|
3133
|
+
variant,
|
|
3134
|
+
size: "sm",
|
|
3135
|
+
onClick: () => {
|
|
3136
|
+
onConfirm();
|
|
3137
|
+
onOpenChange(false);
|
|
3138
|
+
},
|
|
3139
|
+
children: confirmLabel
|
|
3140
|
+
}
|
|
3141
|
+
)
|
|
3142
|
+
] })
|
|
3143
|
+
] }) });
|
|
3144
|
+
}
|
|
3112
3145
|
function maskApiKey(apiKey) {
|
|
3113
3146
|
if (apiKey.length <= 8) return "••••••••";
|
|
3114
3147
|
return apiKey.slice(0, 4) + "••••••••" + apiKey.slice(-4);
|
|
@@ -3900,6 +3933,8 @@ function ProvidersPanel({
|
|
|
3900
3933
|
const [configPathCopied, setConfigPathCopied] = reactExports.useState(false);
|
|
3901
3934
|
const [highlightedProviderId, setHighlightedProviderId] = reactExports.useState(null);
|
|
3902
3935
|
const [showImportWizard, setShowImportWizard] = reactExports.useState(false);
|
|
3936
|
+
const [confirmOpen, setConfirmOpen] = reactExports.useState(false);
|
|
3937
|
+
const [deletingProviderId, setDeletingProviderId] = reactExports.useState(null);
|
|
3903
3938
|
const [sourceFilter, setSourceFilter] = reactExports.useState("all");
|
|
3904
3939
|
const listScrollRef = reactExports.useRef(null);
|
|
3905
3940
|
const highlightTimeoutRef = reactExports.useRef(null);
|
|
@@ -4088,7 +4123,12 @@ function ProvidersPanel({
|
|
|
4088
4123
|
})();
|
|
4089
4124
|
}
|
|
4090
4125
|
function handleDeleteProvider(providerId) {
|
|
4091
|
-
|
|
4126
|
+
setDeletingProviderId(providerId);
|
|
4127
|
+
setConfirmOpen(true);
|
|
4128
|
+
}
|
|
4129
|
+
function executeDelete() {
|
|
4130
|
+
const providerId = deletingProviderId;
|
|
4131
|
+
if (providerId === null) return;
|
|
4092
4132
|
void (async () => {
|
|
4093
4133
|
let res;
|
|
4094
4134
|
try {
|
|
@@ -4218,19 +4258,22 @@ function ProvidersPanel({
|
|
|
4218
4258
|
style: { display: "none" }
|
|
4219
4259
|
}
|
|
4220
4260
|
),
|
|
4221
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4261
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
4262
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
4263
|
+
Button,
|
|
4264
|
+
{
|
|
4265
|
+
variant: "outline",
|
|
4266
|
+
size: "sm",
|
|
4267
|
+
onClick: () => setShowImportWizard(true),
|
|
4268
|
+
className: "gap-1",
|
|
4269
|
+
children: [
|
|
4270
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Scan, { className: "size-3" }),
|
|
4271
|
+
"Scan"
|
|
4272
|
+
]
|
|
4273
|
+
}
|
|
4274
|
+
) }),
|
|
4275
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Detect and import provider configs from Claude Code and OpenCode" })
|
|
4276
|
+
] }) }),
|
|
4234
4277
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { onClick: () => setShowForm(true), size: "sm", className: "gap-1", children: [
|
|
4235
4278
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4" }),
|
|
4236
4279
|
"Add Provider"
|
|
@@ -4305,6 +4348,18 @@ function ProvidersPanel({
|
|
|
4305
4348
|
}
|
|
4306
4349
|
}
|
|
4307
4350
|
}
|
|
4351
|
+
),
|
|
4352
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4353
|
+
ConfirmDialog,
|
|
4354
|
+
{
|
|
4355
|
+
open: confirmOpen,
|
|
4356
|
+
onOpenChange: setConfirmOpen,
|
|
4357
|
+
title: "Delete Provider",
|
|
4358
|
+
description: "Are you sure you want to delete this provider? This action cannot be undone.",
|
|
4359
|
+
confirmLabel: "Delete",
|
|
4360
|
+
variant: "destructive",
|
|
4361
|
+
onConfirm: executeDelete
|
|
4362
|
+
}
|
|
4308
4363
|
)
|
|
4309
4364
|
] });
|
|
4310
4365
|
}
|
|
@@ -198,7 +198,7 @@ function getResponse() {
|
|
|
198
198
|
return event.res;
|
|
199
199
|
}
|
|
200
200
|
async function getStartManifest(matchedRoutes) {
|
|
201
|
-
const { tsrStartManifest } = await import("../_tanstack-start-manifest_v-
|
|
201
|
+
const { tsrStartManifest } = await import("../_tanstack-start-manifest_v-XNH7fVPN.mjs");
|
|
202
202
|
const startManifest = tsrStartManifest();
|
|
203
203
|
const rootRoute = startManifest.routes[rootRouteId] = startManifest.routes[rootRouteId] || {};
|
|
204
204
|
rootRoute.assets = rootRoute.assets || [];
|
|
@@ -767,7 +767,7 @@ let entriesPromise;
|
|
|
767
767
|
let baseManifestPromise;
|
|
768
768
|
let cachedFinalManifestPromise;
|
|
769
769
|
async function loadEntries() {
|
|
770
|
-
const routerEntry = await import("./router-
|
|
770
|
+
const routerEntry = await import("./router-lUOA8pi6.mjs").then((n) => n.r);
|
|
771
771
|
const startEntry = await import("./start-HYkvq4Ni.mjs");
|
|
772
772
|
return { startEntry, routerEntry };
|
|
773
773
|
}
|
|
@@ -45,7 +45,7 @@ import "../_libs/debounce-fn.mjs";
|
|
|
45
45
|
import "../_libs/mimic-function.mjs";
|
|
46
46
|
import "../_libs/semver.mjs";
|
|
47
47
|
import "../_libs/uint8array-extras.mjs";
|
|
48
|
-
const appCss = "/assets/index-
|
|
48
|
+
const appCss = "/assets/index-DXUNTCVh.css";
|
|
49
49
|
const Route$k = createRootRoute({
|
|
50
50
|
head: () => ({
|
|
51
51
|
meta: [
|
|
@@ -69,7 +69,7 @@ function RootDocument({ children }) {
|
|
|
69
69
|
] })
|
|
70
70
|
] });
|
|
71
71
|
}
|
|
72
|
-
const $$splitComponentImporter = () => import("./index-
|
|
72
|
+
const $$splitComponentImporter = () => import("./index-BvHLASu8.mjs");
|
|
73
73
|
const Route$j = createFileRoute("/")({
|
|
74
74
|
component: lazyRouteComponent($$splitComponentImporter, "component")
|
|
75
75
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/__root.tsx", "children": ["/", "/api/config", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/sessions", "/proxy/$"], "preloads": ["/assets/main-
|
|
1
|
+
const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/__root.tsx", "children": ["/", "/api/config", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/sessions", "/proxy/$"], "preloads": ["/assets/main-BV7uNIIz.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-Cmi8TfeU.js"] }, "/api/config": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/config.ts", "children": ["/api/config/paths"] }, "/api/health": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/health.ts" }, "/api/logs": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.ts", "children": ["/api/logs/$id", "/api/logs/stream"] }, "/api/mcp": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/mcp.ts" }, "/api/models": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/models.ts" }, "/api/providers": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.ts", "children": ["/api/providers/$providerId", "/api/providers/export", "/api/providers/import", "/api/providers/scan"] }, "/api/sessions": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/sessions.ts" }, "/proxy/$": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/proxy/$.ts" }, "/api/config/paths": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/config.paths.ts" }, "/api/logs/$id": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.ts", "children": ["/api/logs/$id/chunks", "/api/logs/$id/replay"] }, "/api/logs/stream": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.stream.ts" }, "/api/providers/$providerId": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.$providerId.ts", "children": ["/api/providers/$providerId/test"] }, "/api/providers/export": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.export.ts" }, "/api/providers/import": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.import.ts" }, "/api/providers/scan": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.scan.ts" }, "/api/logs/$id/chunks": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.chunks.ts" }, "/api/logs/$id/replay": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.replay.ts" }, "/api/providers/$providerId/test": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.$providerId.test.ts", "children": ["/api/providers/$providerId/test/log"] }, "/api/providers/$providerId/test/log": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.$providerId.test.log.ts" } }, "clientEntry": "/assets/main-BV7uNIIz.js" });
|
|
2
2
|
export {
|
|
3
3
|
tsrStartManifest
|
|
4
4
|
};
|
package/.output/server/index.mjs
CHANGED
|
@@ -35,54 +35,54 @@ const headers = ((m) => function headersRouteRule(event) {
|
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
37
|
const assets = {
|
|
38
|
-
"/assets/minimax-BPMzvuL-.jpeg": {
|
|
39
|
-
"type": "image/jpeg",
|
|
40
|
-
"etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
|
|
41
|
-
"mtime": "2026-06-11T06:43:41.004Z",
|
|
42
|
-
"size": 6918,
|
|
43
|
-
"path": "../public/assets/minimax-BPMzvuL-.jpeg"
|
|
44
|
-
},
|
|
45
38
|
"/assets/alibaba-TTwafVwX.svg": {
|
|
46
39
|
"type": "image/svg+xml",
|
|
47
40
|
"etag": '"171b-6dyV5K8QjiaY35sN9qNprh9zDIs"',
|
|
48
|
-
"mtime": "2026-06-
|
|
41
|
+
"mtime": "2026-06-11T07:46:13.437Z",
|
|
49
42
|
"size": 5915,
|
|
50
43
|
"path": "../public/assets/alibaba-TTwafVwX.svg"
|
|
51
44
|
},
|
|
45
|
+
"/assets/minimax-BPMzvuL-.jpeg": {
|
|
46
|
+
"type": "image/jpeg",
|
|
47
|
+
"etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
|
|
48
|
+
"mtime": "2026-06-11T07:46:13.439Z",
|
|
49
|
+
"size": 6918,
|
|
50
|
+
"path": "../public/assets/minimax-BPMzvuL-.jpeg"
|
|
51
|
+
},
|
|
52
52
|
"/assets/zhipuai-BPNAnxo-.svg": {
|
|
53
53
|
"type": "image/svg+xml",
|
|
54
54
|
"etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
|
|
55
|
-
"mtime": "2026-06-
|
|
55
|
+
"mtime": "2026-06-11T07:46:13.439Z",
|
|
56
56
|
"size": 11256,
|
|
57
57
|
"path": "../public/assets/zhipuai-BPNAnxo-.svg"
|
|
58
58
|
},
|
|
59
|
-
"/assets/main-Dp5657Eq.js": {
|
|
60
|
-
"type": "text/javascript; charset=utf-8",
|
|
61
|
-
"etag": '"50599-OPDsrJIp7Frbq0SCr8D0WjaPodo"',
|
|
62
|
-
"mtime": "2026-06-11T06:43:41.005Z",
|
|
63
|
-
"size": 329113,
|
|
64
|
-
"path": "../public/assets/main-Dp5657Eq.js"
|
|
65
|
-
},
|
|
66
59
|
"/assets/qwen-CONDcHqt.png": {
|
|
67
60
|
"type": "image/png",
|
|
68
61
|
"etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
|
|
69
|
-
"mtime": "2026-06-
|
|
62
|
+
"mtime": "2026-06-11T07:46:13.439Z",
|
|
70
63
|
"size": 357059,
|
|
71
64
|
"path": "../public/assets/qwen-CONDcHqt.png"
|
|
72
65
|
},
|
|
73
|
-
"/assets/
|
|
66
|
+
"/assets/main-BV7uNIIz.js": {
|
|
67
|
+
"type": "text/javascript; charset=utf-8",
|
|
68
|
+
"etag": '"50599-Hw6XWHNqYOzGgMQUjQUlo6V5ZGQ"',
|
|
69
|
+
"mtime": "2026-06-11T07:46:13.439Z",
|
|
70
|
+
"size": 329113,
|
|
71
|
+
"path": "../public/assets/main-BV7uNIIz.js"
|
|
72
|
+
},
|
|
73
|
+
"/assets/index-DXUNTCVh.css": {
|
|
74
74
|
"type": "text/css; charset=utf-8",
|
|
75
|
-
"etag": '"
|
|
76
|
-
"mtime": "2026-06-
|
|
77
|
-
"size":
|
|
78
|
-
"path": "../public/assets/index-
|
|
75
|
+
"etag": '"145d7-BpJnON+Y0T31X0nkA2icHh97eLY"',
|
|
76
|
+
"mtime": "2026-06-11T07:46:13.439Z",
|
|
77
|
+
"size": 83415,
|
|
78
|
+
"path": "../public/assets/index-DXUNTCVh.css"
|
|
79
79
|
},
|
|
80
|
-
"/assets/index-
|
|
80
|
+
"/assets/index-Cmi8TfeU.js": {
|
|
81
81
|
"type": "text/javascript; charset=utf-8",
|
|
82
|
-
"etag": '"
|
|
83
|
-
"mtime": "2026-06-
|
|
84
|
-
"size":
|
|
85
|
-
"path": "../public/assets/index-
|
|
82
|
+
"etag": '"94069-2UhstwPg+t7SdSjBWTNqX+kv980"',
|
|
83
|
+
"mtime": "2026-06-11T07:46:13.440Z",
|
|
84
|
+
"size": 606313,
|
|
85
|
+
"path": "../public/assets/index-Cmi8TfeU.js"
|
|
86
86
|
}
|
|
87
87
|
};
|
|
88
88
|
function readAsset(id) {
|
package/package.json
CHANGED
|
@@ -180,6 +180,12 @@ export function ImportWizardDialog({
|
|
|
180
180
|
return;
|
|
181
181
|
}
|
|
182
182
|
const result = parsed.data;
|
|
183
|
+
// Mark imported providers as already existing so they can't be re-selected
|
|
184
|
+
setProviders((prev) =>
|
|
185
|
+
prev.map((p, i) => (selected.has(i) ? { ...p, alreadyExists: true } : p)),
|
|
186
|
+
);
|
|
187
|
+
setSelected(new Set());
|
|
188
|
+
|
|
183
189
|
if (
|
|
184
190
|
result.errors !== undefined &&
|
|
185
191
|
result.errors.length > 0 &&
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { type JSX, useState, useEffect, useCallback, useMemo, useRef } from "react";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { Button } from "../ui/button";
|
|
4
|
+
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../ui/tooltip";
|
|
4
5
|
import { Plus, AlertCircle, Copy, Check, Download, Upload, Scan } from "lucide-react";
|
|
5
6
|
import { ImportWizardDialog } from "./ImportWizardDialog";
|
|
7
|
+
import { ConfirmDialog } from "../ui/confirm-dialog";
|
|
6
8
|
import { ProviderCard } from "./ProviderCard";
|
|
7
9
|
import { ProviderForm } from "./ProviderForm";
|
|
8
10
|
import { parseJsonResponse, readApiError } from "../../lib/apiClient";
|
|
@@ -87,6 +89,8 @@ export function ProvidersPanel({
|
|
|
87
89
|
const [configPathCopied, setConfigPathCopied] = useState(false);
|
|
88
90
|
const [highlightedProviderId, setHighlightedProviderId] = useState<string | null>(null);
|
|
89
91
|
const [showImportWizard, setShowImportWizard] = useState(false);
|
|
92
|
+
const [confirmOpen, setConfirmOpen] = useState(false);
|
|
93
|
+
const [deletingProviderId, setDeletingProviderId] = useState<string | null>(null);
|
|
90
94
|
const [sourceFilter, setSourceFilter] = useState<"all" | "personal" | "company">("all");
|
|
91
95
|
const listScrollRef = useRef<HTMLDivElement>(null);
|
|
92
96
|
const highlightTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
@@ -309,8 +313,13 @@ export function ProvidersPanel({
|
|
|
309
313
|
}
|
|
310
314
|
|
|
311
315
|
function handleDeleteProvider(providerId: string): void {
|
|
312
|
-
|
|
313
|
-
|
|
316
|
+
setDeletingProviderId(providerId);
|
|
317
|
+
setConfirmOpen(true);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function executeDelete(): void {
|
|
321
|
+
const providerId = deletingProviderId;
|
|
322
|
+
if (providerId === null) return;
|
|
314
323
|
void (async () => {
|
|
315
324
|
let res: Response;
|
|
316
325
|
try {
|
|
@@ -450,15 +459,24 @@ export function ProvidersPanel({
|
|
|
450
459
|
onChange={handleFileChange}
|
|
451
460
|
style={{ display: "none" }}
|
|
452
461
|
/>
|
|
453
|
-
<
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
+
<TooltipProvider>
|
|
463
|
+
<Tooltip>
|
|
464
|
+
<TooltipTrigger asChild>
|
|
465
|
+
<Button
|
|
466
|
+
variant="outline"
|
|
467
|
+
size="sm"
|
|
468
|
+
onClick={() => setShowImportWizard(true)}
|
|
469
|
+
className="gap-1"
|
|
470
|
+
>
|
|
471
|
+
<Scan className="size-3" />
|
|
472
|
+
Scan
|
|
473
|
+
</Button>
|
|
474
|
+
</TooltipTrigger>
|
|
475
|
+
<TooltipContent>
|
|
476
|
+
Detect and import provider configs from Claude Code and OpenCode
|
|
477
|
+
</TooltipContent>
|
|
478
|
+
</Tooltip>
|
|
479
|
+
</TooltipProvider>
|
|
462
480
|
<Button onClick={() => setShowForm(true)} size="sm" className="gap-1">
|
|
463
481
|
<Plus className="size-4" />
|
|
464
482
|
Add Provider
|
|
@@ -554,6 +572,16 @@ export function ProvidersPanel({
|
|
|
554
572
|
}
|
|
555
573
|
}}
|
|
556
574
|
/>
|
|
575
|
+
|
|
576
|
+
<ConfirmDialog
|
|
577
|
+
open={confirmOpen}
|
|
578
|
+
onOpenChange={setConfirmOpen}
|
|
579
|
+
title="Delete Provider"
|
|
580
|
+
description="Are you sure you want to delete this provider? This action cannot be undone."
|
|
581
|
+
confirmLabel="Delete"
|
|
582
|
+
variant="destructive"
|
|
583
|
+
onConfirm={executeDelete}
|
|
584
|
+
/>
|
|
557
585
|
</div>
|
|
558
586
|
);
|
|
559
587
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type JSX } from "react";
|
|
2
|
+
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../ui/dialog";
|
|
3
|
+
import { Button } from "../ui/button";
|
|
4
|
+
|
|
5
|
+
export type ConfirmDialogVariant = "default" | "destructive";
|
|
6
|
+
|
|
7
|
+
export type ConfirmDialogProps = {
|
|
8
|
+
open: boolean;
|
|
9
|
+
onOpenChange: (open: boolean) => void;
|
|
10
|
+
title: string;
|
|
11
|
+
description: string;
|
|
12
|
+
confirmLabel?: string;
|
|
13
|
+
variant?: ConfirmDialogVariant;
|
|
14
|
+
onConfirm: () => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function ConfirmDialog({
|
|
18
|
+
open,
|
|
19
|
+
onOpenChange,
|
|
20
|
+
title,
|
|
21
|
+
description,
|
|
22
|
+
confirmLabel = "Confirm",
|
|
23
|
+
variant = "default",
|
|
24
|
+
onConfirm,
|
|
25
|
+
}: ConfirmDialogProps): JSX.Element {
|
|
26
|
+
return (
|
|
27
|
+
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
28
|
+
<DialogContent>
|
|
29
|
+
<DialogHeader>
|
|
30
|
+
<DialogTitle>{title}</DialogTitle>
|
|
31
|
+
</DialogHeader>
|
|
32
|
+
<p className="text-sm text-muted-foreground">{description}</p>
|
|
33
|
+
<div className="flex justify-end gap-2 pt-2">
|
|
34
|
+
<Button variant="outline" size="sm" onClick={() => onOpenChange(false)}>
|
|
35
|
+
Cancel
|
|
36
|
+
</Button>
|
|
37
|
+
<Button
|
|
38
|
+
variant={variant}
|
|
39
|
+
size="sm"
|
|
40
|
+
onClick={() => {
|
|
41
|
+
onConfirm();
|
|
42
|
+
onOpenChange(false);
|
|
43
|
+
}}
|
|
44
|
+
>
|
|
45
|
+
{confirmLabel}
|
|
46
|
+
</Button>
|
|
47
|
+
</div>
|
|
48
|
+
</DialogContent>
|
|
49
|
+
</Dialog>
|
|
50
|
+
);
|
|
51
|
+
}
|