@tonyclaw/llm-inspector 1.7.7 → 1.7.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.output/nitro.json +1 -1
- package/.output/public/assets/index-CB8ZIeEk.js +97 -0
- package/.output/public/assets/{main-DYXtPYU8.js → main-BrU8NdGQ.js} +1 -1
- package/.output/server/_libs/lucide-react.mjs +98 -91
- package/.output/server/_libs/zod.mjs +1 -0
- package/.output/server/_ssr/{index-DbpsE3Y4.mjs → index-CAIDMqNv.mjs} +167 -21
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-CZSteFqT.mjs → router-CsCLdrXq.mjs} +241 -43
- package/.output/server/_tanstack-start-manifest_v-BF6ge6dS.mjs +4 -0
- package/.output/server/index.mjs +23 -23
- package/package.json +1 -1
- package/src/components/providers/ProvidersPanel.tsx +176 -14
- package/src/components/proxy-viewer/ConversationGroup.tsx +3 -3
- package/src/components/proxy-viewer/LogEntry.tsx +6 -3
- package/src/components/proxy-viewer/LogEntryHeader.tsx +3 -2
- package/src/proxy/formats/anthropic/stream.ts +3 -2
- package/src/proxy/formats/openai/stream.ts +3 -2
- package/src/proxy/handler.ts +5 -0
- package/src/proxy/providers.ts +98 -0
- package/src/routes/api/providers.export.ts +26 -0
- package/src/routes/api/providers.import.ts +47 -0
- package/.output/public/assets/index-Drusqil7.js +0 -97
- package/.output/server/_tanstack-start-manifest_v-DgsS3z4y.mjs +0 -4
|
@@ -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, p as parseOpenAIResponse, I as InspectorResponseSchema } from "./router-
|
|
2
|
+
import { C as CapturedLogSchema, a as parseRequest, p as parseOpenAIResponse, I as InspectorResponseSchema } from "./router-CsCLdrXq.mjs";
|
|
3
3
|
import { u as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
|
|
4
4
|
import { J as JSZip } from "../_libs/jszip.mjs";
|
|
5
5
|
import { c as clsx } from "../_libs/clsx.mjs";
|
|
@@ -7,9 +7,9 @@ import { t as twMerge } from "../_libs/tailwind-merge.mjs";
|
|
|
7
7
|
import { c as cva } from "../_libs/class-variance-authority.mjs";
|
|
8
8
|
import { R as Root, T as Trigger$1, C as Content, a as Close, b as Title, P as Portal$1, O as Overlay } from "../_libs/radix-ui__react-dialog.mjs";
|
|
9
9
|
import { R as Root2, T as Trigger, I as Icon, V as Value, P as Portal, C as Content2, a as Viewport, b as Item, c as ItemIndicator, d as ItemText, S as ScrollUpButton, e as ScrollDownButton } from "../_libs/radix-ui__react-select.mjs";
|
|
10
|
-
import { D as Download, L as LayoutGrid, a as List, S as Settings, C as ChevronDown, b as Check, R as RotateCcw, X, P as Plus, c as Copy, d as CircleAlert, e as ChevronUp, f as ChevronRight, g as Clock, M as MessageSquare, Z as Zap, h as LoaderCircle, W as Wrench, G as Globe,
|
|
10
|
+
import { D as Download, L as LayoutGrid, a as List, S as Settings, C as ChevronDown, b as Check, R as RotateCcw, X, U as Upload, P as Plus, c as Copy, d as CircleAlert, e as ChevronUp, f as ChevronRight, g as Clock, M as MessageSquare, Z as Zap, h as LoaderCircle, W as Wrench, G as Globe, i as User, F as FileTerminal, j as Radio, E as ExternalLink, k as EyeOff, l as Eye, m as RotateCw, n as Pencil, T as Trash2, o as TriangleAlert, p as Minus, q as CircleCheckBig, r as CircleStop, s as CircleQuestionMark, t as Server, u as Gauge, v as Lock, w as Wifi, x as WifiOff, y as ChevronsUp, z as ChevronsDown, A as Terminal, B as Brain } from "../_libs/lucide-react.mjs";
|
|
11
11
|
import { M as Markdown } from "../_libs/react-markdown.mjs";
|
|
12
|
-
import { a as array, s as string, u as union, o as object, l as literal,
|
|
12
|
+
import { a as array, s as string, u as union, o as object, l as literal, n as number, b as boolean } from "../_libs/zod.mjs";
|
|
13
13
|
import { R as Root2$1, L as List$1, T as Trigger$2, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
|
|
14
14
|
import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
|
|
15
15
|
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";
|
|
@@ -946,7 +946,7 @@ const STATUS_BADGE_CLASSES = {
|
|
|
946
946
|
server_error: "",
|
|
947
947
|
pending: "bg-muted text-muted-foreground border-border"
|
|
948
948
|
};
|
|
949
|
-
|
|
949
|
+
const LogEntryHeader = reactExports.memo(function LogEntryHeader2({
|
|
950
950
|
log,
|
|
951
951
|
parsedRequest,
|
|
952
952
|
expanded,
|
|
@@ -1098,7 +1098,7 @@ function LogEntryHeader({
|
|
|
1098
1098
|
]
|
|
1099
1099
|
}
|
|
1100
1100
|
);
|
|
1101
|
-
}
|
|
1101
|
+
});
|
|
1102
1102
|
function Dialog({
|
|
1103
1103
|
...props
|
|
1104
1104
|
}) {
|
|
@@ -1832,7 +1832,10 @@ function CopyButton({
|
|
|
1832
1832
|
}
|
|
1833
1833
|
);
|
|
1834
1834
|
}
|
|
1835
|
-
|
|
1835
|
+
const LogEntry = reactExports.memo(function LogEntry2({
|
|
1836
|
+
log,
|
|
1837
|
+
viewMode = "simple"
|
|
1838
|
+
}) {
|
|
1836
1839
|
const [expanded, setExpanded] = reactExports.useState(false);
|
|
1837
1840
|
const [requestCopied, setRequestCopied] = reactExports.useState(false);
|
|
1838
1841
|
const [responseCopied, setResponseCopied] = reactExports.useState(false);
|
|
@@ -1953,7 +1956,7 @@ function LogEntry({ log, viewMode = "simple" }) {
|
|
|
1953
1956
|
] }),
|
|
1954
1957
|
/* @__PURE__ */ jsxRuntimeExports.jsx(ReplayDialog, { log, open: replayOpen, onOpenChange: setReplayOpen })
|
|
1955
1958
|
] });
|
|
1956
|
-
}
|
|
1959
|
+
});
|
|
1957
1960
|
function computeStats(logs) {
|
|
1958
1961
|
let totalInput = 0;
|
|
1959
1962
|
let totalOutput = 0;
|
|
@@ -1963,7 +1966,7 @@ function computeStats(logs) {
|
|
|
1963
1966
|
}
|
|
1964
1967
|
return { totalInputTokens: totalInput, totalOutputTokens: totalOutput };
|
|
1965
1968
|
}
|
|
1966
|
-
|
|
1969
|
+
const ConversationGroup = reactExports.memo(function ConversationGroup2({
|
|
1967
1970
|
group,
|
|
1968
1971
|
viewMode = "simple"
|
|
1969
1972
|
}) {
|
|
@@ -1988,7 +1991,7 @@ function ConversationGroup({
|
|
|
1988
1991
|
),
|
|
1989
1992
|
expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pl-4 border-l-2 border-muted ml-3", children: group.logs.map((log) => /* @__PURE__ */ jsxRuntimeExports.jsx(LogEntry, { log, viewMode }, log.id)) })
|
|
1990
1993
|
] });
|
|
1991
|
-
}
|
|
1994
|
+
});
|
|
1992
1995
|
function Select({
|
|
1993
1996
|
...props
|
|
1994
1997
|
}) {
|
|
@@ -2562,11 +2565,21 @@ function ProvidersPanel({
|
|
|
2562
2565
|
const TEST_TIMEOUT_SECONDS = 30;
|
|
2563
2566
|
const runTest = reactExports.useCallback(
|
|
2564
2567
|
async (providerId) => {
|
|
2568
|
+
const resetResults = {
|
|
2569
|
+
anthropic: { nonStreaming: { notConfigured: true }, streaming: { notConfigured: true } },
|
|
2570
|
+
openai: { nonStreaming: { notConfigured: true }, streaming: { notConfigured: true } }
|
|
2571
|
+
};
|
|
2572
|
+
if (onTestResultsChange) {
|
|
2573
|
+
onTestResultsChange(providerId, resetResults);
|
|
2574
|
+
} else {
|
|
2575
|
+
setInternalTestResults((prev) => ({ ...prev, [providerId]: resetResults }));
|
|
2576
|
+
}
|
|
2565
2577
|
if (onTestingProvidersChange) {
|
|
2566
2578
|
onTestingProvidersChange(providerId, true);
|
|
2567
2579
|
} else {
|
|
2568
2580
|
setInternalTestingProviders((prev) => new Set(prev).add(providerId));
|
|
2569
2581
|
}
|
|
2582
|
+
const controller = new AbortController();
|
|
2570
2583
|
let remaining = TEST_TIMEOUT_SECONDS;
|
|
2571
2584
|
setTestingTimeLeft(providerId, remaining);
|
|
2572
2585
|
const intervalId = setInterval(() => {
|
|
@@ -2574,10 +2587,14 @@ function ProvidersPanel({
|
|
|
2574
2587
|
setTestingTimeLeft(providerId, remaining);
|
|
2575
2588
|
if (remaining <= 0) {
|
|
2576
2589
|
clearInterval(intervalId);
|
|
2590
|
+
controller.abort();
|
|
2577
2591
|
}
|
|
2578
2592
|
}, 1e3);
|
|
2579
2593
|
try {
|
|
2580
|
-
const res = await fetch(`/api/providers/${providerId}/test`, {
|
|
2594
|
+
const res = await fetch(`/api/providers/${providerId}/test`, {
|
|
2595
|
+
method: "POST",
|
|
2596
|
+
signal: controller.signal
|
|
2597
|
+
});
|
|
2581
2598
|
if (res.ok) {
|
|
2582
2599
|
const results = await res.json();
|
|
2583
2600
|
if (onTestResultsChange) {
|
|
@@ -2585,18 +2602,68 @@ function ProvidersPanel({
|
|
|
2585
2602
|
} else {
|
|
2586
2603
|
setInternalTestResults((prev) => ({ ...prev, [providerId]: results }));
|
|
2587
2604
|
}
|
|
2605
|
+
} else {
|
|
2606
|
+
const errorResult = {
|
|
2607
|
+
anthropic: {
|
|
2608
|
+
nonStreaming: {
|
|
2609
|
+
success: false,
|
|
2610
|
+
error: { message: `HTTP ${res.status}: ${res.statusText}`, type: "server_error" }
|
|
2611
|
+
},
|
|
2612
|
+
streaming: { notConfigured: true }
|
|
2613
|
+
},
|
|
2614
|
+
openai: {
|
|
2615
|
+
nonStreaming: {
|
|
2616
|
+
success: false,
|
|
2617
|
+
error: { message: `HTTP ${res.status}: ${res.statusText}`, type: "server_error" }
|
|
2618
|
+
},
|
|
2619
|
+
streaming: { notConfigured: true }
|
|
2620
|
+
}
|
|
2621
|
+
};
|
|
2622
|
+
if (onTestResultsChange) {
|
|
2623
|
+
onTestResultsChange(providerId, errorResult);
|
|
2624
|
+
} else {
|
|
2625
|
+
setInternalTestResults((prev) => ({ ...prev, [providerId]: errorResult }));
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
} catch (err) {
|
|
2629
|
+
const isAbort = err instanceof Error && err.name === "AbortError";
|
|
2630
|
+
if (isAbort) {
|
|
2631
|
+
const timeoutResult = {
|
|
2632
|
+
anthropic: {
|
|
2633
|
+
nonStreaming: {
|
|
2634
|
+
success: false,
|
|
2635
|
+
error: { message: "Request timed out", type: "timeout" }
|
|
2636
|
+
},
|
|
2637
|
+
streaming: { notConfigured: true }
|
|
2638
|
+
},
|
|
2639
|
+
openai: {
|
|
2640
|
+
nonStreaming: {
|
|
2641
|
+
success: false,
|
|
2642
|
+
error: { message: "Request timed out", type: "timeout" }
|
|
2643
|
+
},
|
|
2644
|
+
streaming: { notConfigured: true }
|
|
2645
|
+
}
|
|
2646
|
+
};
|
|
2647
|
+
if (onTestResultsChange) {
|
|
2648
|
+
onTestResultsChange(providerId, timeoutResult);
|
|
2649
|
+
} else {
|
|
2650
|
+
setInternalTestResults((prev) => ({ ...prev, [providerId]: timeoutResult }));
|
|
2651
|
+
}
|
|
2588
2652
|
}
|
|
2589
2653
|
} finally {
|
|
2590
2654
|
clearInterval(intervalId);
|
|
2591
2655
|
setTestingTimeLeft(providerId, void 0);
|
|
2592
|
-
|
|
2593
|
-
onTestingProvidersChange
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2656
|
+
try {
|
|
2657
|
+
if (onTestingProvidersChange) {
|
|
2658
|
+
onTestingProvidersChange(providerId, false);
|
|
2659
|
+
} else {
|
|
2660
|
+
setInternalTestingProviders((prev) => {
|
|
2661
|
+
const next = new Set(prev);
|
|
2662
|
+
next.delete(providerId);
|
|
2663
|
+
return next;
|
|
2664
|
+
});
|
|
2665
|
+
}
|
|
2666
|
+
} catch {
|
|
2600
2667
|
}
|
|
2601
2668
|
}
|
|
2602
2669
|
},
|
|
@@ -2669,6 +2736,65 @@ function ProvidersPanel({
|
|
|
2669
2736
|
await fetchProviders();
|
|
2670
2737
|
})();
|
|
2671
2738
|
}
|
|
2739
|
+
const fileInputRef = reactExports.useRef(null);
|
|
2740
|
+
function handleExport(includeKeys) {
|
|
2741
|
+
const url = `/api/providers/export${""}`;
|
|
2742
|
+
void (async () => {
|
|
2743
|
+
try {
|
|
2744
|
+
const res = await fetch(url);
|
|
2745
|
+
if (!res.ok) {
|
|
2746
|
+
setError("Failed to export providers");
|
|
2747
|
+
return;
|
|
2748
|
+
}
|
|
2749
|
+
const blob = await res.blob();
|
|
2750
|
+
const downloadUrl = URL.createObjectURL(blob);
|
|
2751
|
+
const a = document.createElement("a");
|
|
2752
|
+
a.href = downloadUrl;
|
|
2753
|
+
a.download = res.headers.get("Content-Disposition")?.match(/filename="(.+)"/)?.[1] ?? "providers.json";
|
|
2754
|
+
document.body.appendChild(a);
|
|
2755
|
+
a.click();
|
|
2756
|
+
document.body.removeChild(a);
|
|
2757
|
+
URL.revokeObjectURL(downloadUrl);
|
|
2758
|
+
} catch {
|
|
2759
|
+
setError("Failed to export providers");
|
|
2760
|
+
}
|
|
2761
|
+
})();
|
|
2762
|
+
}
|
|
2763
|
+
function handleImportClick() {
|
|
2764
|
+
fileInputRef.current?.click();
|
|
2765
|
+
}
|
|
2766
|
+
function handleFileChange(e) {
|
|
2767
|
+
const file = e.target.files?.[0];
|
|
2768
|
+
if (!file) return;
|
|
2769
|
+
void (async () => {
|
|
2770
|
+
try {
|
|
2771
|
+
const text = await file.text();
|
|
2772
|
+
const res = await fetch("/api/providers/import", {
|
|
2773
|
+
method: "POST",
|
|
2774
|
+
headers: { "Content-Type": "application/json" },
|
|
2775
|
+
body: JSON.stringify(text)
|
|
2776
|
+
});
|
|
2777
|
+
const ImportResponseSchema = object({
|
|
2778
|
+
success: boolean().optional(),
|
|
2779
|
+
imported: number().optional(),
|
|
2780
|
+
message: string().optional(),
|
|
2781
|
+
errors: array(string()).optional()
|
|
2782
|
+
});
|
|
2783
|
+
const data = ImportResponseSchema.parse(await res.json());
|
|
2784
|
+
if (res.ok && data.imported !== void 0 && data.imported > 0) {
|
|
2785
|
+
await fetchProviders();
|
|
2786
|
+
setError(null);
|
|
2787
|
+
} else if (data.errors && data.errors.length > 0) {
|
|
2788
|
+
setError(data.errors.join("; "));
|
|
2789
|
+
} else {
|
|
2790
|
+
setError(data.message ?? "Import failed");
|
|
2791
|
+
}
|
|
2792
|
+
} catch {
|
|
2793
|
+
setError("Failed to import providers");
|
|
2794
|
+
}
|
|
2795
|
+
e.target.value = "";
|
|
2796
|
+
})();
|
|
2797
|
+
}
|
|
2672
2798
|
if (isLoading && providers.length === 0) {
|
|
2673
2799
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground", children: "Loading providers..." }) });
|
|
2674
2800
|
}
|
|
@@ -2691,9 +2817,29 @@ function ProvidersPanel({
|
|
|
2691
2817
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
|
|
2692
2818
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2693
2819
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-medium", children: "Providers" }),
|
|
2694
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2695
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
2696
|
-
|
|
2820
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2821
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { variant: "outline", size: "sm", onClick: () => handleExport(), className: "gap-1", children: [
|
|
2822
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3" }),
|
|
2823
|
+
"Export"
|
|
2824
|
+
] }),
|
|
2825
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { variant: "outline", size: "sm", onClick: handleImportClick, className: "gap-1", children: [
|
|
2826
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "size-3" }),
|
|
2827
|
+
"Import"
|
|
2828
|
+
] }),
|
|
2829
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2830
|
+
"input",
|
|
2831
|
+
{
|
|
2832
|
+
type: "file",
|
|
2833
|
+
ref: fileInputRef,
|
|
2834
|
+
accept: ".json",
|
|
2835
|
+
onChange: handleFileChange,
|
|
2836
|
+
style: { display: "none" }
|
|
2837
|
+
}
|
|
2838
|
+
),
|
|
2839
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { onClick: () => setShowForm(true), size: "sm", className: "gap-1", children: [
|
|
2840
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4" }),
|
|
2841
|
+
"Add Provider"
|
|
2842
|
+
] })
|
|
2697
2843
|
] })
|
|
2698
2844
|
] }),
|
|
2699
2845
|
configPath !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground bg-muted/30 rounded-md px-3 py-2", children: [
|
|
@@ -197,7 +197,7 @@ function getResponse() {
|
|
|
197
197
|
return event.res;
|
|
198
198
|
}
|
|
199
199
|
async function getStartManifest(matchedRoutes) {
|
|
200
|
-
const { tsrStartManifest } = await import("../_tanstack-start-manifest_v-
|
|
200
|
+
const { tsrStartManifest } = await import("../_tanstack-start-manifest_v-BF6ge6dS.mjs");
|
|
201
201
|
const startManifest = tsrStartManifest();
|
|
202
202
|
const rootRoute = startManifest.routes[rootRouteId] = startManifest.routes[rootRouteId] || {};
|
|
203
203
|
rootRoute.assets = rootRoute.assets || [];
|
|
@@ -766,7 +766,7 @@ let entriesPromise;
|
|
|
766
766
|
let baseManifestPromise;
|
|
767
767
|
let cachedFinalManifestPromise;
|
|
768
768
|
async function loadEntries() {
|
|
769
|
-
const routerEntry = await import("./router-
|
|
769
|
+
const routerEntry = await import("./router-CsCLdrXq.mjs").then((n) => n.r);
|
|
770
770
|
const startEntry = await import("./start-HYkvq4Ni.mjs");
|
|
771
771
|
return { startEntry, routerEntry };
|
|
772
772
|
}
|