@tonyclaw/llm-inspector 1.6.3 → 1.7.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/.output/cli.js +4 -68
- package/.output/nitro.json +3 -3
- package/.output/public/assets/{index-s4lwsWvq.js → index-Bf_WGooQ.js} +18 -18
- package/.output/public/assets/{main-Cp8AM0Pa.js → main-CpIX1ZHy.js} +1 -1
- package/.output/server/_chunks/ssr-renderer.mjs +4 -0
- package/.output/server/_libs/h3-v2.mjs +5 -5
- package/.output/server/_libs/h3.mjs +5 -5
- package/.output/server/_libs/lucide-react.mjs +115 -76
- package/.output/server/_libs/react-dom.mjs +2074 -1228
- package/.output/server/_libs/readable-stream.mjs +3 -3
- package/.output/server/_libs/srvx.mjs +443 -47
- package/.output/server/_libs/util-deprecate.mjs +2 -2
- package/.output/server/_ssr/{index-ByCLZu7J.mjs → index-BZkxgx8f.mjs} +70 -13
- package/.output/server/_ssr/index.mjs +9 -2
- package/.output/server/_ssr/{router-Bq_mxeNz.mjs → router-D7g2K6y6.mjs} +109 -34
- package/.output/server/{_tanstack-start-manifest_v-C4E0e9my.mjs → _tanstack-start-manifest_v-b6u6g-Cr.mjs} +1 -1
- package/.output/server/index.mjs +31 -29
- package/package.json +1 -1
- package/src/cli.ts +4 -87
- package/src/components/providers/ProviderCard.tsx +82 -7
- package/src/components/providers/ProvidersPanel.tsx +40 -7
|
@@ -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-D7g2K6y6.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,7 +7,7 @@ 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, U as User, F as FileTerminal, i as Radio, E as ExternalLink, j as EyeOff, k as Eye, l as RotateCw, m as Pencil, T as Trash2, n as TriangleAlert, o as Minus, p as CircleCheckBig, q as
|
|
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, U as User, F as FileTerminal, i as Radio, E as ExternalLink, j as EyeOff, k as Eye, l as RotateCw, m as Pencil, T as Trash2, n as TriangleAlert, o as Minus, p as CircleCheckBig, q as CircleStop, r as CircleQuestionMark, s as Server, t as Gauge, u as Lock, v as Wifi, w as WifiOff, x as ChevronsUp, y as ChevronsDown, z as Terminal, B as Brain } from "../_libs/lucide-react.mjs";
|
|
11
11
|
import { M as Markdown } from "../_libs/react-markdown.mjs";
|
|
12
12
|
import { a as array, s as string, u as union, o as object, l as literal, b as boolean, n as number } 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";
|
|
@@ -27,6 +27,10 @@ import "../_libs/seroval-plugins.mjs";
|
|
|
27
27
|
import "node:stream/web";
|
|
28
28
|
import "node:stream";
|
|
29
29
|
import "../_libs/react-dom.mjs";
|
|
30
|
+
import "util";
|
|
31
|
+
import "crypto";
|
|
32
|
+
import "async_hooks";
|
|
33
|
+
import "stream";
|
|
30
34
|
import "../_libs/isbot.mjs";
|
|
31
35
|
import "node:fs";
|
|
32
36
|
import "node:path";
|
|
@@ -52,11 +56,9 @@ import "../_libs/debounce-fn.mjs";
|
|
|
52
56
|
import "../_libs/mimic-function.mjs";
|
|
53
57
|
import "../_libs/semver.mjs";
|
|
54
58
|
import "../_libs/uint8array-extras.mjs";
|
|
55
|
-
import "crypto";
|
|
56
59
|
import "node:child_process";
|
|
57
60
|
import "../_libs/tanstack__virtual-core.mjs";
|
|
58
61
|
import "../_libs/readable-stream.mjs";
|
|
59
|
-
import "stream";
|
|
60
62
|
import "../_libs/process-nextick-args.mjs";
|
|
61
63
|
import "../_libs/isarray.mjs";
|
|
62
64
|
import "events";
|
|
@@ -64,7 +66,6 @@ import "../_libs/safe-buffer.mjs";
|
|
|
64
66
|
import "buffer";
|
|
65
67
|
import "../_libs/core-util-is.mjs";
|
|
66
68
|
import "../_libs/inherits.mjs";
|
|
67
|
-
import "util";
|
|
68
69
|
import "../_libs/util-deprecate.mjs";
|
|
69
70
|
import "node:string_decoder";
|
|
70
71
|
import "../_libs/lie.mjs";
|
|
@@ -2115,7 +2116,33 @@ function maskApiKey(apiKey) {
|
|
|
2115
2116
|
function hasSuccessField(result) {
|
|
2116
2117
|
return Object.prototype.hasOwnProperty.call(result, "success");
|
|
2117
2118
|
}
|
|
2118
|
-
function
|
|
2119
|
+
function getErrorIcon(type) {
|
|
2120
|
+
const iconProps = { className: "size-3", strokeWidth: 2 };
|
|
2121
|
+
switch (type) {
|
|
2122
|
+
case "timeout":
|
|
2123
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { ...iconProps });
|
|
2124
|
+
case "network_unreachable":
|
|
2125
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(WifiOff, { ...iconProps });
|
|
2126
|
+
case "connection_refused":
|
|
2127
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Wifi, { ...iconProps });
|
|
2128
|
+
case "auth_failed":
|
|
2129
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Lock, { ...iconProps });
|
|
2130
|
+
case "rate_limited":
|
|
2131
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Gauge, { ...iconProps });
|
|
2132
|
+
case "server_error":
|
|
2133
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Server, { ...iconProps });
|
|
2134
|
+
case "invalid_response":
|
|
2135
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleQuestionMark, { ...iconProps });
|
|
2136
|
+
case "unknown":
|
|
2137
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { ...iconProps });
|
|
2138
|
+
default:
|
|
2139
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { ...iconProps });
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
function TestStatus({
|
|
2143
|
+
result,
|
|
2144
|
+
isTesting
|
|
2145
|
+
}) {
|
|
2119
2146
|
if (!hasSuccessField(result)) {
|
|
2120
2147
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
2121
2148
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Minus, { className: "size-3" }),
|
|
@@ -2128,9 +2155,23 @@ function TestStatus({ result }) {
|
|
|
2128
2155
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Connected" })
|
|
2129
2156
|
] });
|
|
2130
2157
|
}
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2158
|
+
const error = result.error;
|
|
2159
|
+
const errorMessage = error?.message ?? "Connection failed";
|
|
2160
|
+
const errorHint = error?.hint;
|
|
2161
|
+
const errorType = error?.type ?? "unknown";
|
|
2162
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1 min-w-0", children: [
|
|
2163
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2164
|
+
"div",
|
|
2165
|
+
{
|
|
2166
|
+
className: "flex items-center gap-1 text-xs text-red-600 min-w-0",
|
|
2167
|
+
title: error?.details ?? errorMessage,
|
|
2168
|
+
children: [
|
|
2169
|
+
getErrorIcon(errorType),
|
|
2170
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: errorMessage })
|
|
2171
|
+
]
|
|
2172
|
+
}
|
|
2173
|
+
),
|
|
2174
|
+
errorHint !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground pl-4 truncate", title: errorHint, children: errorHint })
|
|
2134
2175
|
] });
|
|
2135
2176
|
}
|
|
2136
2177
|
function ProviderCard({
|
|
@@ -2182,7 +2223,7 @@ function ProviderCard({
|
|
|
2182
2223
|
" ",
|
|
2183
2224
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: provider.anthropicBaseUrl })
|
|
2184
2225
|
] }),
|
|
2185
|
-
testResults && /* @__PURE__ */ jsxRuntimeExports.jsx(TestStatus, { result: testResults.anthropic.nonStreaming })
|
|
2226
|
+
testResults && /* @__PURE__ */ jsxRuntimeExports.jsx(TestStatus, { result: testResults.anthropic.nonStreaming, isTesting })
|
|
2186
2227
|
] }),
|
|
2187
2228
|
provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2188
2229
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-muted-foreground min-w-0 flex-1", children: [
|
|
@@ -2190,7 +2231,7 @@ function ProviderCard({
|
|
|
2190
2231
|
" ",
|
|
2191
2232
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: provider.openaiBaseUrl })
|
|
2192
2233
|
] }),
|
|
2193
|
-
testResults && /* @__PURE__ */ jsxRuntimeExports.jsx(TestStatus, { result: testResults.openai.nonStreaming })
|
|
2234
|
+
testResults && /* @__PURE__ */ jsxRuntimeExports.jsx(TestStatus, { result: testResults.openai.nonStreaming, isTesting })
|
|
2194
2235
|
] }),
|
|
2195
2236
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2 pt-1 border-t", children: [
|
|
2196
2237
|
onTest !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
@@ -2506,10 +2547,18 @@ function ProvidersPanel() {
|
|
|
2506
2547
|
}, []);
|
|
2507
2548
|
function handleAddProvider(data) {
|
|
2508
2549
|
void (async () => {
|
|
2550
|
+
const payload = {
|
|
2551
|
+
name: data.name,
|
|
2552
|
+
apiKey: data.apiKey,
|
|
2553
|
+
model: data.model,
|
|
2554
|
+
format: data.format,
|
|
2555
|
+
anthropicBaseUrl: data.format === "anthropic" ? data.baseUrl : void 0,
|
|
2556
|
+
openaiBaseUrl: data.format === "openai" ? data.baseUrl : void 0
|
|
2557
|
+
};
|
|
2509
2558
|
const res = await fetch("/api/providers", {
|
|
2510
2559
|
method: "POST",
|
|
2511
2560
|
headers: { "Content-Type": "application/json" },
|
|
2512
|
-
body: JSON.stringify(
|
|
2561
|
+
body: JSON.stringify(payload)
|
|
2513
2562
|
});
|
|
2514
2563
|
if (!res.ok) {
|
|
2515
2564
|
const err = await res.json();
|
|
@@ -2525,10 +2574,18 @@ function ProvidersPanel() {
|
|
|
2525
2574
|
function handleUpdateProvider(data) {
|
|
2526
2575
|
if (!editingProvider) return;
|
|
2527
2576
|
void (async () => {
|
|
2577
|
+
const payload = {
|
|
2578
|
+
name: data.name,
|
|
2579
|
+
apiKey: data.apiKey,
|
|
2580
|
+
model: data.model,
|
|
2581
|
+
format: data.format,
|
|
2582
|
+
anthropicBaseUrl: data.format === "anthropic" ? data.baseUrl : void 0,
|
|
2583
|
+
openaiBaseUrl: data.format === "openai" ? data.baseUrl : void 0
|
|
2584
|
+
};
|
|
2528
2585
|
const res = await fetch(`/api/providers/${editingProvider.id}`, {
|
|
2529
2586
|
method: "PUT",
|
|
2530
2587
|
headers: { "Content-Type": "application/json" },
|
|
2531
|
-
body: JSON.stringify(
|
|
2588
|
+
body: JSON.stringify(payload)
|
|
2532
2589
|
});
|
|
2533
2590
|
if (!res.ok) {
|
|
2534
2591
|
const err = await res.json();
|
|
@@ -12,8 +12,15 @@ import "node:stream/web";
|
|
|
12
12
|
import "node:stream";
|
|
13
13
|
import "../_libs/rou3.mjs";
|
|
14
14
|
import "../_libs/srvx.mjs";
|
|
15
|
+
import "node:http";
|
|
16
|
+
import "node:https";
|
|
17
|
+
import "node:http2";
|
|
15
18
|
import "../_libs/tiny-warning.mjs";
|
|
16
19
|
import "../_libs/react-dom.mjs";
|
|
20
|
+
import "util";
|
|
21
|
+
import "crypto";
|
|
22
|
+
import "async_hooks";
|
|
23
|
+
import "stream";
|
|
17
24
|
import "../_libs/isbot.mjs";
|
|
18
25
|
function StartServer(props) {
|
|
19
26
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(RouterProvider, { router: props.router });
|
|
@@ -190,7 +197,7 @@ function getResponse() {
|
|
|
190
197
|
return event.res;
|
|
191
198
|
}
|
|
192
199
|
async function getStartManifest(matchedRoutes) {
|
|
193
|
-
const { tsrStartManifest } = await import("../_tanstack-start-manifest_v-
|
|
200
|
+
const { tsrStartManifest } = await import("../_tanstack-start-manifest_v-b6u6g-Cr.mjs");
|
|
194
201
|
const startManifest = tsrStartManifest();
|
|
195
202
|
const rootRoute = startManifest.routes[rootRouteId] = startManifest.routes[rootRouteId] || {};
|
|
196
203
|
rootRoute.assets = rootRoute.assets || [];
|
|
@@ -759,7 +766,7 @@ let entriesPromise;
|
|
|
759
766
|
let baseManifestPromise;
|
|
760
767
|
let cachedFinalManifestPromise;
|
|
761
768
|
async function loadEntries() {
|
|
762
|
-
const routerEntry = await import("./router-
|
|
769
|
+
const routerEntry = await import("./router-D7g2K6y6.mjs").then((n) => n.r);
|
|
763
770
|
const startEntry = await import("./start-HYkvq4Ni.mjs");
|
|
764
771
|
return { startEntry, routerEntry };
|
|
765
772
|
}
|
|
@@ -18,6 +18,9 @@ import "../_libs/seroval-plugins.mjs";
|
|
|
18
18
|
import "node:stream/web";
|
|
19
19
|
import "node:stream";
|
|
20
20
|
import "../_libs/react-dom.mjs";
|
|
21
|
+
import "util";
|
|
22
|
+
import "async_hooks";
|
|
23
|
+
import "stream";
|
|
21
24
|
import "../_libs/isbot.mjs";
|
|
22
25
|
import "node:process";
|
|
23
26
|
import "node:crypto";
|
|
@@ -62,7 +65,7 @@ function RootDocument({ children }) {
|
|
|
62
65
|
] })
|
|
63
66
|
] });
|
|
64
67
|
}
|
|
65
|
-
const $$splitComponentImporter = () => import("./index-
|
|
68
|
+
const $$splitComponentImporter = () => import("./index-BZkxgx8f.mjs");
|
|
66
69
|
const Route$d = createFileRoute("/")({
|
|
67
70
|
component: lazyRouteComponent($$splitComponentImporter, "component")
|
|
68
71
|
});
|
|
@@ -2071,6 +2074,77 @@ const Route$3 = createFileRoute("/api/config/paths")({
|
|
|
2071
2074
|
}
|
|
2072
2075
|
}
|
|
2073
2076
|
});
|
|
2077
|
+
const ERROR_HINTS = {
|
|
2078
|
+
timeout: "The request took too long. Check your network connection or try again.",
|
|
2079
|
+
network_unreachable: "Cannot reach the server. Verify the base URL and check your firewall settings.",
|
|
2080
|
+
connection_refused: "Connection was refused. Make sure the provider server is running and the URL is correct.",
|
|
2081
|
+
auth_failed: "Authentication failed. Check your API key is correct and has not expired.",
|
|
2082
|
+
rate_limited: "Too many requests. Wait a moment and try again, or check your API quota.",
|
|
2083
|
+
server_error: "The provider server encountered an error. Check their status page and try again later.",
|
|
2084
|
+
invalid_response: "Received an unexpected response. The provider may be experiencing issues.",
|
|
2085
|
+
unknown: "An unexpected error occurred. Check the details and try again."
|
|
2086
|
+
};
|
|
2087
|
+
const MAX_ERROR_DETAILS_LENGTH = 200;
|
|
2088
|
+
function classifyError(error, responseStatus) {
|
|
2089
|
+
const errorStr = String(error);
|
|
2090
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
2091
|
+
return { type: "timeout", details: "Request was aborted due to timeout" };
|
|
2092
|
+
}
|
|
2093
|
+
if (errorStr.includes("timeout") || errorStr.includes("timed out") || errorStr.includes("Timeout")) {
|
|
2094
|
+
return { type: "timeout", details: truncateErrorDetails(errorStr) };
|
|
2095
|
+
}
|
|
2096
|
+
if (errorStr.includes("ECONNREFUSED") || errorStr.includes("connection refused")) {
|
|
2097
|
+
return { type: "connection_refused", details: truncateErrorDetails(errorStr) };
|
|
2098
|
+
}
|
|
2099
|
+
if (errorStr.includes("ENOTFOUND") || errorStr.includes("getaddrinfo") || errorStr.includes("DNS") || errorStr.includes("network") || errorStr.includes("fetch failed")) {
|
|
2100
|
+
return { type: "network_unreachable", details: truncateErrorDetails(errorStr) };
|
|
2101
|
+
}
|
|
2102
|
+
if (responseStatus !== void 0) {
|
|
2103
|
+
if (responseStatus === 401 || responseStatus === 403) {
|
|
2104
|
+
return { type: "auth_failed", details: `HTTP ${responseStatus}` };
|
|
2105
|
+
}
|
|
2106
|
+
if (responseStatus === 429) {
|
|
2107
|
+
return { type: "rate_limited", details: `HTTP ${responseStatus}` };
|
|
2108
|
+
}
|
|
2109
|
+
if (responseStatus >= 500 && responseStatus < 600) {
|
|
2110
|
+
return { type: "server_error", details: `HTTP ${responseStatus}` };
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
return { type: "unknown", details: truncateErrorDetails(errorStr) };
|
|
2114
|
+
}
|
|
2115
|
+
function truncateErrorDetails(details) {
|
|
2116
|
+
if (details.length <= MAX_ERROR_DETAILS_LENGTH) {
|
|
2117
|
+
return details;
|
|
2118
|
+
}
|
|
2119
|
+
return details.slice(0, MAX_ERROR_DETAILS_LENGTH) + "...";
|
|
2120
|
+
}
|
|
2121
|
+
function createErrorResult(error, latencyMs, streaming, responseStatus) {
|
|
2122
|
+
const { type, details } = classifyError(error, responseStatus);
|
|
2123
|
+
return {
|
|
2124
|
+
success: false,
|
|
2125
|
+
error: {
|
|
2126
|
+
message: getErrorMessage(type),
|
|
2127
|
+
type,
|
|
2128
|
+
details,
|
|
2129
|
+
hint: ERROR_HINTS[type]
|
|
2130
|
+
},
|
|
2131
|
+
latencyMs,
|
|
2132
|
+
streaming
|
|
2133
|
+
};
|
|
2134
|
+
}
|
|
2135
|
+
function getErrorMessage(type) {
|
|
2136
|
+
const messages = {
|
|
2137
|
+
timeout: "Request timed out",
|
|
2138
|
+
network_unreachable: "Cannot reach host",
|
|
2139
|
+
connection_refused: "Connection refused",
|
|
2140
|
+
auth_failed: "Authentication failed",
|
|
2141
|
+
rate_limited: "Rate limited",
|
|
2142
|
+
server_error: "Provider server error",
|
|
2143
|
+
invalid_response: "Invalid response",
|
|
2144
|
+
unknown: "Unknown error"
|
|
2145
|
+
};
|
|
2146
|
+
return messages[type];
|
|
2147
|
+
}
|
|
2074
2148
|
const AnthropicResponseSchema = object({
|
|
2075
2149
|
id: string().optional(),
|
|
2076
2150
|
type: string().optional(),
|
|
@@ -2103,6 +2177,7 @@ const OpenAIResponseSchema = object({
|
|
|
2103
2177
|
})
|
|
2104
2178
|
)
|
|
2105
2179
|
});
|
|
2180
|
+
const TEST_TIMEOUT_MS = 3e4;
|
|
2106
2181
|
async function testEndpoint(baseUrl, apiKey, path2, model, isOpenAI) {
|
|
2107
2182
|
const startTime = Date.now();
|
|
2108
2183
|
const body = JSON.stringify({
|
|
@@ -2110,6 +2185,8 @@ async function testEndpoint(baseUrl, apiKey, path2, model, isOpenAI) {
|
|
|
2110
2185
|
messages: [{ role: "user", content: "say hello and briefly introduce yourself" }],
|
|
2111
2186
|
max_tokens: 1024
|
|
2112
2187
|
});
|
|
2188
|
+
const controller = new AbortController();
|
|
2189
|
+
const timeoutId = setTimeout(() => controller.abort(), TEST_TIMEOUT_MS);
|
|
2113
2190
|
try {
|
|
2114
2191
|
const url = `${baseUrl}${path2}`;
|
|
2115
2192
|
const response = await fetch(url, {
|
|
@@ -2118,17 +2195,20 @@ async function testEndpoint(baseUrl, apiKey, path2, model, isOpenAI) {
|
|
|
2118
2195
|
"Content-Type": "application/json",
|
|
2119
2196
|
Authorization: `Bearer ${apiKey}`
|
|
2120
2197
|
},
|
|
2121
|
-
body
|
|
2198
|
+
body,
|
|
2199
|
+
signal: controller.signal
|
|
2122
2200
|
});
|
|
2201
|
+
clearTimeout(timeoutId);
|
|
2123
2202
|
const latencyMs = Date.now() - startTime;
|
|
2124
|
-
const responseText = await response.text();
|
|
2125
2203
|
if (!response.ok) {
|
|
2126
|
-
return
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2204
|
+
return createErrorResult(
|
|
2205
|
+
`HTTP ${response.status}: ${response.statusText}`,
|
|
2206
|
+
latencyMs,
|
|
2207
|
+
false,
|
|
2208
|
+
response.status
|
|
2209
|
+
);
|
|
2131
2210
|
}
|
|
2211
|
+
const responseText = await response.text();
|
|
2132
2212
|
try {
|
|
2133
2213
|
if (isOpenAI) {
|
|
2134
2214
|
const json = OpenAIResponseSchema.parse(JSON.parse(responseText));
|
|
@@ -2178,11 +2258,8 @@ async function testEndpoint(baseUrl, apiKey, path2, model, isOpenAI) {
|
|
|
2178
2258
|
};
|
|
2179
2259
|
}
|
|
2180
2260
|
} catch (err) {
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
error: String(err),
|
|
2184
|
-
latencyMs: Date.now() - startTime
|
|
2185
|
-
};
|
|
2261
|
+
clearTimeout(timeoutId);
|
|
2262
|
+
return createErrorResult(err, Date.now() - startTime, false);
|
|
2186
2263
|
}
|
|
2187
2264
|
}
|
|
2188
2265
|
async function testStreamingEndpoint(baseUrl, apiKey, path2, model, isOpenAI) {
|
|
@@ -2193,6 +2270,8 @@ async function testStreamingEndpoint(baseUrl, apiKey, path2, model, isOpenAI) {
|
|
|
2193
2270
|
max_tokens: 256,
|
|
2194
2271
|
stream: true
|
|
2195
2272
|
});
|
|
2273
|
+
const controller = new AbortController();
|
|
2274
|
+
const timeoutId = setTimeout(() => controller.abort(), TEST_TIMEOUT_MS);
|
|
2196
2275
|
try {
|
|
2197
2276
|
const url = `${baseUrl}${path2}`;
|
|
2198
2277
|
const response = await fetch(url, {
|
|
@@ -2201,24 +2280,29 @@ async function testStreamingEndpoint(baseUrl, apiKey, path2, model, isOpenAI) {
|
|
|
2201
2280
|
"Content-Type": "application/json",
|
|
2202
2281
|
Authorization: `Bearer ${apiKey}`
|
|
2203
2282
|
},
|
|
2204
|
-
body
|
|
2283
|
+
body,
|
|
2284
|
+
signal: controller.signal
|
|
2205
2285
|
});
|
|
2286
|
+
clearTimeout(timeoutId);
|
|
2206
2287
|
const latencyMs = Date.now() - startTime;
|
|
2207
2288
|
if (!response.ok) {
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
success: false,
|
|
2211
|
-
error: `HTTP ${response.status}: ${responseText.slice(0, 200)}`,
|
|
2289
|
+
return createErrorResult(
|
|
2290
|
+
`HTTP ${response.status}: ${response.statusText}`,
|
|
2212
2291
|
latencyMs,
|
|
2213
|
-
|
|
2214
|
-
|
|
2292
|
+
true,
|
|
2293
|
+
response.status
|
|
2294
|
+
);
|
|
2215
2295
|
}
|
|
2216
2296
|
const chunks = [];
|
|
2217
2297
|
const reader = response.body?.getReader();
|
|
2218
2298
|
if (!reader) {
|
|
2219
2299
|
return {
|
|
2220
2300
|
success: false,
|
|
2221
|
-
error:
|
|
2301
|
+
error: {
|
|
2302
|
+
message: "No response body",
|
|
2303
|
+
type: "invalid_response",
|
|
2304
|
+
hint: ERROR_HINTS.invalid_response
|
|
2305
|
+
},
|
|
2222
2306
|
latencyMs,
|
|
2223
2307
|
streaming: true
|
|
2224
2308
|
};
|
|
@@ -2231,12 +2315,7 @@ async function testStreamingEndpoint(baseUrl, apiKey, path2, model, isOpenAI) {
|
|
|
2231
2315
|
chunks.push(decoder.decode(value, { stream: true }));
|
|
2232
2316
|
}
|
|
2233
2317
|
} catch (readErr) {
|
|
2234
|
-
return {
|
|
2235
|
-
success: false,
|
|
2236
|
-
error: `Stream read error: ${readErr}`,
|
|
2237
|
-
latencyMs,
|
|
2238
|
-
streaming: true
|
|
2239
|
-
};
|
|
2318
|
+
return createErrorResult(`Stream read error: ${readErr}`, latencyMs, true);
|
|
2240
2319
|
}
|
|
2241
2320
|
const fullResponse = chunks.join("");
|
|
2242
2321
|
const mockLog = {
|
|
@@ -2317,12 +2396,8 @@ async function testStreamingEndpoint(baseUrl, apiKey, path2, model, isOpenAI) {
|
|
|
2317
2396
|
};
|
|
2318
2397
|
}
|
|
2319
2398
|
} catch (err) {
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
error: String(err),
|
|
2323
|
-
latencyMs: Date.now() - startTime,
|
|
2324
|
-
streaming: true
|
|
2325
|
-
};
|
|
2399
|
+
clearTimeout(timeoutId);
|
|
2400
|
+
return createErrorResult(err, Date.now() - startTime, true);
|
|
2326
2401
|
}
|
|
2327
2402
|
}
|
|
2328
2403
|
function createTestLogEntry(providerName, path2, body, upstreamUrl, result, isTest) {
|
|
@@ -2343,7 +2418,7 @@ function createTestLogEntry(providerName, path2, body, upstreamUrl, result, isTe
|
|
|
2343
2418
|
userAgent: "provider-test",
|
|
2344
2419
|
origin: null,
|
|
2345
2420
|
upstreamUrl,
|
|
2346
|
-
error: result.success ? null : result.error,
|
|
2421
|
+
error: result.success ? null : result.error?.message ?? String(result.error),
|
|
2347
2422
|
isTest: true,
|
|
2348
2423
|
providerName
|
|
2349
2424
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/__root.tsx", "children": ["/", "/api/health", "/api/logs", "/api/models", "/api/providers", "/api/sessions", "/proxy/$", "/api/config/paths"], "preloads": ["/assets/main-
|
|
1
|
+
const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/__root.tsx", "children": ["/", "/api/health", "/api/logs", "/api/models", "/api/providers", "/api/sessions", "/proxy/$", "/api/config/paths"], "preloads": ["/assets/main-CpIX1ZHy.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-Bf_WGooQ.js"] }, "/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/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/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/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" } }, "clientEntry": "/assets/main-CpIX1ZHy.js" });
|
|
2
2
|
export {
|
|
3
3
|
tsrStartManifest
|
|
4
4
|
};
|
package/.output/server/index.mjs
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
globalThis.__nitro_main__ = import.meta.url;
|
|
2
|
-
import {
|
|
2
|
+
import { N as NodeResponse, s as serve } from "./_libs/srvx.mjs";
|
|
3
3
|
import { d as defineHandler, H as HTTPError, t as toEventHandler, a as defineLazyEventHandler, b as H3Core } from "./_libs/h3.mjs";
|
|
4
4
|
import { d as decodePath, w as withLeadingSlash, a as withoutTrailingSlash, j as joinURL } from "./_libs/ufo.mjs";
|
|
5
5
|
import { promises } from "node:fs";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { dirname, resolve } from "node:path";
|
|
8
|
+
import "node:http";
|
|
9
|
+
import "node:stream";
|
|
10
|
+
import "node:https";
|
|
11
|
+
import "node:http2";
|
|
8
12
|
import "./_libs/rou3.mjs";
|
|
9
13
|
function lazyService(loader) {
|
|
10
14
|
let promise, mod;
|
|
@@ -26,7 +30,7 @@ const services = {
|
|
|
26
30
|
globalThis.__nitro_vite_envs__ = services;
|
|
27
31
|
const errorHandler$1 = (error, event) => {
|
|
28
32
|
const res = defaultHandler(error, event);
|
|
29
|
-
return new
|
|
33
|
+
return new NodeResponse(typeof res.body === "string" ? res.body : JSON.stringify(res.body, null, 2), res);
|
|
30
34
|
};
|
|
31
35
|
function defaultHandler(error, event, opts) {
|
|
32
36
|
const isSensitive = error.unhandled;
|
|
@@ -93,54 +97,54 @@ const headers = ((m) => function headersRouteRule(event) {
|
|
|
93
97
|
}
|
|
94
98
|
});
|
|
95
99
|
const assets = {
|
|
100
|
+
"/assets/alibaba-TTwafVwX.svg": {
|
|
101
|
+
"type": "image/svg+xml",
|
|
102
|
+
"etag": '"171b-6dyV5K8QjiaY35sN9qNprh9zDIs"',
|
|
103
|
+
"mtime": "2026-06-03T09:17:40.502Z",
|
|
104
|
+
"size": 5915,
|
|
105
|
+
"path": "../public/assets/alibaba-TTwafVwX.svg"
|
|
106
|
+
},
|
|
96
107
|
"/assets/index-B3RwBPLW.css": {
|
|
97
108
|
"type": "text/css; charset=utf-8",
|
|
98
109
|
"etag": '"10c74-aXacU4DRFVsUwcC5jHnjoPRSlTA"',
|
|
99
|
-
"mtime": "2026-06-
|
|
110
|
+
"mtime": "2026-06-03T09:17:40.504Z",
|
|
100
111
|
"size": 68724,
|
|
101
112
|
"path": "../public/assets/index-B3RwBPLW.css"
|
|
102
113
|
},
|
|
103
|
-
"/assets/
|
|
104
|
-
"type": "
|
|
105
|
-
"etag": '"
|
|
106
|
-
"mtime": "2026-06-
|
|
107
|
-
"size":
|
|
108
|
-
"path": "../public/assets/
|
|
114
|
+
"/assets/main-CpIX1ZHy.js": {
|
|
115
|
+
"type": "text/javascript; charset=utf-8",
|
|
116
|
+
"etag": '"4db57-PIyiLXQGvlFJuizUFXRhGOYXJwY"',
|
|
117
|
+
"mtime": "2026-06-03T09:17:40.504Z",
|
|
118
|
+
"size": 318295,
|
|
119
|
+
"path": "../public/assets/main-CpIX1ZHy.js"
|
|
109
120
|
},
|
|
110
121
|
"/assets/minimax-BPMzvuL-.jpeg": {
|
|
111
122
|
"type": "image/jpeg",
|
|
112
123
|
"etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
|
|
113
|
-
"mtime": "2026-06-
|
|
124
|
+
"mtime": "2026-06-03T09:17:40.501Z",
|
|
114
125
|
"size": 6918,
|
|
115
126
|
"path": "../public/assets/minimax-BPMzvuL-.jpeg"
|
|
116
127
|
},
|
|
117
128
|
"/assets/zhipuai-BPNAnxo-.svg": {
|
|
118
129
|
"type": "image/svg+xml",
|
|
119
130
|
"etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
|
|
120
|
-
"mtime": "2026-06-
|
|
131
|
+
"mtime": "2026-06-03T09:17:40.502Z",
|
|
121
132
|
"size": 11256,
|
|
122
133
|
"path": "../public/assets/zhipuai-BPNAnxo-.svg"
|
|
123
134
|
},
|
|
124
|
-
"/assets/main-Cp8AM0Pa.js": {
|
|
125
|
-
"type": "text/javascript; charset=utf-8",
|
|
126
|
-
"etag": '"4db57-FpqlPRLq9OHoaAFCL2NIXtZbW5c"',
|
|
127
|
-
"mtime": "2026-06-03T08:06:11.052Z",
|
|
128
|
-
"size": 318295,
|
|
129
|
-
"path": "../public/assets/main-Cp8AM0Pa.js"
|
|
130
|
-
},
|
|
131
135
|
"/assets/qwen-CONDcHqt.png": {
|
|
132
136
|
"type": "image/png",
|
|
133
137
|
"etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
|
|
134
|
-
"mtime": "2026-06-
|
|
138
|
+
"mtime": "2026-06-03T09:17:40.502Z",
|
|
135
139
|
"size": 357059,
|
|
136
140
|
"path": "../public/assets/qwen-CONDcHqt.png"
|
|
137
141
|
},
|
|
138
|
-
"/assets/index-
|
|
142
|
+
"/assets/index-Bf_WGooQ.js": {
|
|
139
143
|
"type": "text/javascript; charset=utf-8",
|
|
140
|
-
"etag": '"
|
|
141
|
-
"mtime": "2026-06-
|
|
142
|
-
"size":
|
|
143
|
-
"path": "../public/assets/index-
|
|
144
|
+
"etag": '"831df-gmdpd1CCnM4IdaxHIs9uyMgWFaY"',
|
|
145
|
+
"mtime": "2026-06-03T09:17:40.504Z",
|
|
146
|
+
"size": 537055,
|
|
147
|
+
"path": "../public/assets/index-Bf_WGooQ.js"
|
|
144
148
|
}
|
|
145
149
|
};
|
|
146
150
|
function readAsset(id) {
|
|
@@ -375,7 +379,6 @@ const host = process.env.NITRO_HOST || process.env.HOST;
|
|
|
375
379
|
const cert = process.env.NITRO_SSL_CERT;
|
|
376
380
|
const key = process.env.NITRO_SSL_KEY;
|
|
377
381
|
const nitroApp = useNitroApp();
|
|
378
|
-
let _fetch = nitroApp.fetch;
|
|
379
382
|
serve({
|
|
380
383
|
port,
|
|
381
384
|
hostname: host,
|
|
@@ -383,11 +386,10 @@ serve({
|
|
|
383
386
|
cert,
|
|
384
387
|
key
|
|
385
388
|
} : void 0,
|
|
386
|
-
fetch:
|
|
387
|
-
bun: { websocket: void 0 }
|
|
389
|
+
fetch: nitroApp.fetch
|
|
388
390
|
});
|
|
389
391
|
trapUnhandledErrors();
|
|
390
|
-
const
|
|
392
|
+
const nodeServer = {};
|
|
391
393
|
export {
|
|
392
|
-
|
|
394
|
+
nodeServer as default
|
|
393
395
|
};
|
package/package.json
CHANGED