@tonyclaw/agent-inspector 3.0.3 → 3.0.5
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/{CompareDrawer-CufpM7_P.js → CompareDrawer-Co-35_Xw.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-DPv1rBo7.js +106 -0
- package/.output/public/assets/{ReplayDialog-ClDmxv57.js → ReplayDialog-DghbvKdy.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-DcuIghmp.js → RequestAnatomy-CRXE5v8X.js} +1 -1
- package/.output/public/assets/{ResponseView-C7Tl47j3.js → ResponseView-CzxoQRjp.js} +2 -2
- package/.output/public/assets/{StreamingChunkSequence-DBK_R540.js → StreamingChunkSequence-DnFyF_Hr.js} +1 -1
- package/.output/public/assets/{_sessionId-D8Ke-EcI.js → _sessionId-DHRhWzKe.js} +1 -1
- package/.output/public/assets/index-D8cruW0P.css +1 -0
- package/.output/public/assets/index-DZyTpd2w.js +1 -0
- package/.output/public/assets/{index-CpWH7b2O.js → index-Dl1oki9E.js} +1 -1
- package/.output/public/assets/{json-viewer-BEifdKM_.js → json-viewer-B84f7oiG.js} +1 -1
- package/.output/public/assets/{main-DDfExS3_.js → main-DViDnJ9X.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +2 -2
- package/.output/server/{_sessionId-Di7z893V.mjs → _sessionId-C43vEAWe.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-ABv-8FMB.mjs → CompareDrawer-DOL6q0jD.mjs} +2 -2
- package/.output/server/_ssr/{ProxyViewerContainer-CGX-1aUr.mjs → ProxyViewerContainer-S9izw3ND.mjs} +572 -272
- package/.output/server/_ssr/{ReplayDialog-DD31ftzG.mjs → ReplayDialog-tqthwJh0.mjs} +3 -3
- package/.output/server/_ssr/{RequestAnatomy-54kNHAjH.mjs → RequestAnatomy-CgWDjFPR.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-CRnibtlX.mjs → ResponseView-Dk8Op622.mjs} +2 -2
- package/.output/server/_ssr/{StreamingChunkSequence-Cb5WGfMm.mjs → StreamingChunkSequence-AlS7PK8f.mjs} +2 -2
- package/.output/server/_ssr/{index-BJ-8DomR.mjs → index-BGwvMN2M.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-DB5188I7.mjs → json-viewer-CKHkh5U3.mjs} +2 -2
- package/.output/server/_ssr/{router-BKf70uDr.mjs → router-BJMaHkr1.mjs} +9 -9
- package/.output/server/{_tanstack-start-manifest_v-DUuf3Rgf.mjs → _tanstack-start-manifest_v-C_HvRzgP.mjs} +1 -1
- package/.output/server/index.mjs +66 -66
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +92 -25
- package/src/components/ProxyViewerContainer.tsx +154 -55
- package/src/components/providers/ProviderCard.tsx +413 -230
- package/src/components/proxy-viewer/ConversationGroup.tsx +1 -1
- package/src/components/proxy-viewer/ConversationHeader.tsx +4 -5
- package/src/lib/stopReason.ts +4 -0
- package/.output/public/assets/ProxyViewerContainer-Dppr2zGE.js +0 -106
- package/.output/public/assets/index-BskTYcAH.css +0 -1
- package/.output/public/assets/index-DRHfTEM5.js +0 -1
package/.output/server/_ssr/{ProxyViewerContainer-CGX-1aUr.mjs → ProxyViewerContainer-S9izw3ND.mjs}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
|
|
2
|
-
import { I as InspectorGroupsListResponseSchema, C as CapturedLogSchema, D as DEFAULT_CAPTURE_MODE, a as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, b as DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS, c as DEFAULT_TIME_DISPLAY_FORMAT, d as RuntimeConfigSchema, p as packageJson, P as ProviderConfigSchema, i as apiFormatForPath, n as DeleteInspectorGroupsResponseSchema, o as GroupEvidenceExportResultSchema, q as DeleteInspectorGroupResponseSchema, z as createPendingProviderTestResults, B as ProviderTestResultsSchema, E as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, F as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, l as AlertSummarySchema, m as AlertListResponseSchema, G as GroupEvidenceReadResponseSchema,
|
|
2
|
+
import { I as InspectorGroupsListResponseSchema, C as CapturedLogSchema, D as DEFAULT_CAPTURE_MODE, a as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, b as DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS, c as DEFAULT_TIME_DISPLAY_FORMAT, d as RuntimeConfigSchema, p as packageJson, P as ProviderConfigSchema, i as apiFormatForPath, n as DeleteInspectorGroupsResponseSchema, o as GroupEvidenceExportResultSchema, q as DeleteInspectorGroupResponseSchema, z as createPendingProviderTestResults, B as ProviderTestResultsSchema, E as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, F as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, l as AlertSummarySchema, m as AlertListResponseSchema, G as GroupEvidenceReadResponseSchema, t as maskApiKey, u as PATH_V1_MESSAGES, v as PATH_V1_CHAT_COMPLETIONS, w as PATH_V1_RESPONSES, r as providerHasContextMetadata, f as parseOpenAIResponse, g as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, h as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, H as resolveProviderContextWindow, j as getSessionPath, x as findProviderModelMetadata, y as previewUpstreamUrl, K as KnowledgeCandidateSchema, J as isPlainRecord, k as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-BJMaHkr1.mjs";
|
|
3
3
|
import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
|
|
4
4
|
import { J as JSZip } from "../_libs/jszip.mjs";
|
|
5
5
|
import { c as clsx } from "../_libs/clsx.mjs";
|
|
@@ -9,7 +9,7 @@ import { c as cva } from "../_libs/class-variance-authority.mjs";
|
|
|
9
9
|
import { u as useWindowVirtualizer, a as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
|
|
10
10
|
import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
|
|
11
11
|
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";
|
|
12
|
-
import { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, S as Search, U as Upload, D as Download, F as FileBraces,
|
|
12
|
+
import { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, R as RefreshCw, c as Trash2, S as Search, U as Upload, D as Download, F as FileBraces, P as Plus, A as ArrowLeft, d as ChevronUp, e as Copy, f as ChevronsLeft, g as ChevronLeft, h as ChevronRight, i as ChevronsRight, j as Clapperboard, k as Flag, l as Siren, m as Timer, G as Gauge, L as LoaderCircle, n as Layers, o as Settings, M as Monitor, p as Scan, q as CircleAlert, r as Terminal, s as ArrowUpRight, t as ArrowDownRight, u as Cpu, v as FolderOpen, B as Bell, w as Clock3, x as ShieldAlert, E as EyeOff, y as Eye, z as ExternalLink, H as Clock, J as RotateCw, K as Pencil, N as MessageSquare, Z as Zap, W as Wrench, O as Brain, Q as Minus, V as CircleCheckBig, Y as CircleQuestionMark, _ as Server, $ as Lock, a0 as Wifi, a1 as WifiOff, a2 as CircleX, a3 as ShieldCheck, a4 as Save, a5 as FileSearch, a6 as CloudUpload, a7 as OctagonAlert, a8 as Radio, a9 as Globe, aa as FileTerminal, ab as ChevronsUp, ac as ChevronsDown, ad as FileDiff, ae as History, af as RotateCcw, ag as GitCompareArrows, ah as ArrowUp, ai as ArrowDown, aj as Ellipsis, ak as CodeXml, al as Blocks, am as MousePointerClick, an as FileText, ao as Rows3, ap as Columns2 } from "../_libs/lucide-react.mjs";
|
|
13
13
|
import { u as union, d as object, a as array, l as literal, b as string, n as number, c as boolean, _ as _enum } from "../_libs/zod.mjs";
|
|
14
14
|
import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
|
|
15
15
|
import { R as Root2$1, L as List, T as Trigger$2, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
|
|
@@ -530,6 +530,8 @@ function normalizeAnthropicStopReason(value) {
|
|
|
530
530
|
case "end_turn":
|
|
531
531
|
case "tool_use":
|
|
532
532
|
return value;
|
|
533
|
+
case "max_tokens":
|
|
534
|
+
return "length";
|
|
533
535
|
default:
|
|
534
536
|
return null;
|
|
535
537
|
}
|
|
@@ -539,6 +541,8 @@ function normalizeOpenAIFinishReason(value) {
|
|
|
539
541
|
case "stop":
|
|
540
542
|
case "length":
|
|
541
543
|
return value;
|
|
544
|
+
case "max_tokens":
|
|
545
|
+
return "length";
|
|
542
546
|
default:
|
|
543
547
|
return null;
|
|
544
548
|
}
|
|
@@ -1650,7 +1654,7 @@ function ConversationHeader({
|
|
|
1650
1654
|
type: "button",
|
|
1651
1655
|
onClick: handleClearClick,
|
|
1652
1656
|
"aria-label": `Clear group (${totalCalls} request${totalCalls !== 1 ? "s" : ""})`,
|
|
1653
|
-
title: "Clear this group",
|
|
1657
|
+
title: "Clear this group from the current view",
|
|
1654
1658
|
className: HEADER_ACTION_BUTTON_CLASS$1,
|
|
1655
1659
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" })
|
|
1656
1660
|
}
|
|
@@ -1677,8 +1681,8 @@ function ConversationHeader({
|
|
|
1677
1681
|
{
|
|
1678
1682
|
open: confirmOpen,
|
|
1679
1683
|
onOpenChange: setConfirmOpen,
|
|
1680
|
-
title: "Clear this group?",
|
|
1681
|
-
description: `This will
|
|
1684
|
+
title: "Clear this group from the current view?",
|
|
1685
|
+
description: `This will hide ${totalCalls} request${totalCalls !== 1 ? "s" : ""} from the current view. Stored logs remain reloadable.`,
|
|
1682
1686
|
confirmLabel: "Clear",
|
|
1683
1687
|
variant: "destructive",
|
|
1684
1688
|
onConfirm: () => {
|
|
@@ -2302,27 +2306,27 @@ function useCopyFeedback(text) {
|
|
|
2302
2306
|
return { copied, copy };
|
|
2303
2307
|
}
|
|
2304
2308
|
const LazyCompareDrawer = reactExports.lazy(
|
|
2305
|
-
() => import("./CompareDrawer-
|
|
2309
|
+
() => import("./CompareDrawer-DOL6q0jD.mjs").then((m) => ({ default: m.CompareDrawer }))
|
|
2306
2310
|
);
|
|
2307
2311
|
const LazyReplayDialog = reactExports.lazy(
|
|
2308
|
-
() => import("./ReplayDialog-
|
|
2312
|
+
() => import("./ReplayDialog-tqthwJh0.mjs").then((m) => ({ default: m.ReplayDialog }))
|
|
2309
2313
|
);
|
|
2310
2314
|
const LazyRequestAnatomy = reactExports.lazy(
|
|
2311
|
-
() => import("./RequestAnatomy-
|
|
2315
|
+
() => import("./RequestAnatomy-CgWDjFPR.mjs").then((m) => ({ default: m.RequestAnatomy }))
|
|
2312
2316
|
);
|
|
2313
2317
|
const LazyResponseView = reactExports.lazy(
|
|
2314
|
-
() => import("./ResponseView-
|
|
2318
|
+
() => import("./ResponseView-Dk8Op622.mjs").then((m) => ({ default: m.ResponseView }))
|
|
2315
2319
|
);
|
|
2316
2320
|
const LazyStreamingChunkSequence = reactExports.lazy(
|
|
2317
|
-
() => import("./StreamingChunkSequence-
|
|
2321
|
+
() => import("./StreamingChunkSequence-AlS7PK8f.mjs").then((m) => ({
|
|
2318
2322
|
default: m.StreamingChunkSequence
|
|
2319
2323
|
}))
|
|
2320
2324
|
);
|
|
2321
2325
|
const LazyJsonViewer = reactExports.lazy(
|
|
2322
|
-
() => import("./json-viewer-
|
|
2326
|
+
() => import("./json-viewer-CKHkh5U3.mjs").then((m) => ({ default: m.JsonViewer }))
|
|
2323
2327
|
);
|
|
2324
2328
|
const LazyJsonViewerFromString = reactExports.lazy(
|
|
2325
|
-
() => import("./json-viewer-
|
|
2329
|
+
() => import("./json-viewer-CKHkh5U3.mjs").then((m) => ({ default: m.JsonViewerFromString }))
|
|
2326
2330
|
);
|
|
2327
2331
|
const HIGHLIGHT_DURATION_MS = 1200;
|
|
2328
2332
|
const MAX_HIGHLIGHT_ATTEMPTS = 12;
|
|
@@ -8327,6 +8331,153 @@ function ProviderEndpointSummary({
|
|
|
8327
8331
|
children
|
|
8328
8332
|
] });
|
|
8329
8333
|
}
|
|
8334
|
+
function providerHasEndpoint(value) {
|
|
8335
|
+
return value !== void 0 && value !== "";
|
|
8336
|
+
}
|
|
8337
|
+
function providerTestTargets(provider) {
|
|
8338
|
+
const targets = [];
|
|
8339
|
+
if (providerHasEndpoint(provider.anthropicBaseUrl)) {
|
|
8340
|
+
targets.push("Anthropic");
|
|
8341
|
+
}
|
|
8342
|
+
if (providerHasEndpoint(provider.openaiBaseUrl)) {
|
|
8343
|
+
targets.push("Chat");
|
|
8344
|
+
}
|
|
8345
|
+
if (providerHasEndpoint(provider.openaiResponsesBaseUrl)) {
|
|
8346
|
+
targets.push("Responses");
|
|
8347
|
+
}
|
|
8348
|
+
return targets;
|
|
8349
|
+
}
|
|
8350
|
+
function ProviderTestCoverage({ provider }) {
|
|
8351
|
+
const targets = providerTestTargets(provider);
|
|
8352
|
+
if (targets.length === 0) {
|
|
8353
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "Test requires at least one configured endpoint." });
|
|
8354
|
+
}
|
|
8355
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
8356
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Test covers" }),
|
|
8357
|
+
targets.map((target) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8358
|
+
"span",
|
|
8359
|
+
{
|
|
8360
|
+
className: "rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-foreground/80",
|
|
8361
|
+
children: target
|
|
8362
|
+
},
|
|
8363
|
+
target
|
|
8364
|
+
)),
|
|
8365
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "non-stream + stream" })
|
|
8366
|
+
] });
|
|
8367
|
+
}
|
|
8368
|
+
function configuredFormatResults(provider, testResults) {
|
|
8369
|
+
if (testResults === void 0) return [];
|
|
8370
|
+
const results = [];
|
|
8371
|
+
if (providerHasEndpoint(provider.anthropicBaseUrl)) {
|
|
8372
|
+
results.push(testResults.anthropic);
|
|
8373
|
+
}
|
|
8374
|
+
if (providerHasEndpoint(provider.openaiBaseUrl)) {
|
|
8375
|
+
results.push(testResults.openaiChat);
|
|
8376
|
+
}
|
|
8377
|
+
if (providerHasEndpoint(provider.openaiResponsesBaseUrl)) {
|
|
8378
|
+
results.push(testResults.openaiResponses);
|
|
8379
|
+
}
|
|
8380
|
+
return results;
|
|
8381
|
+
}
|
|
8382
|
+
function summarizeTestResults(provider, testResults) {
|
|
8383
|
+
const summary = { total: 0, passed: 0, failed: 0, testing: 0 };
|
|
8384
|
+
for (const results of configuredFormatResults(provider, testResults)) {
|
|
8385
|
+
for (const state of [results.nonStreaming, results.streaming]) {
|
|
8386
|
+
if (isNotConfiguredState(state)) continue;
|
|
8387
|
+
summary.total += 1;
|
|
8388
|
+
if (hasSuccessField(state)) {
|
|
8389
|
+
if (state.success) {
|
|
8390
|
+
summary.passed += 1;
|
|
8391
|
+
} else {
|
|
8392
|
+
summary.failed += 1;
|
|
8393
|
+
}
|
|
8394
|
+
} else {
|
|
8395
|
+
summary.testing += 1;
|
|
8396
|
+
}
|
|
8397
|
+
}
|
|
8398
|
+
}
|
|
8399
|
+
return summary;
|
|
8400
|
+
}
|
|
8401
|
+
function ProviderTestPill({
|
|
8402
|
+
provider,
|
|
8403
|
+
testResults,
|
|
8404
|
+
isTesting
|
|
8405
|
+
}) {
|
|
8406
|
+
const targets = providerTestTargets(provider);
|
|
8407
|
+
const summary = summarizeTestResults(provider, testResults);
|
|
8408
|
+
if (isTesting) {
|
|
8409
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1 rounded border border-cyan-300/25 bg-cyan-300/[0.08] px-2 py-1 text-xs text-cyan-100", children: [
|
|
8410
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RotateCw, { className: "size-3 animate-spin" }),
|
|
8411
|
+
"Testing"
|
|
8412
|
+
] });
|
|
8413
|
+
}
|
|
8414
|
+
if (targets.length === 0) {
|
|
8415
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded border border-border/70 bg-muted/20 px-2 py-1 text-xs text-muted-foreground", children: "No endpoint" });
|
|
8416
|
+
}
|
|
8417
|
+
if (testResults === void 0 || summary.total === 0) {
|
|
8418
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded border border-border/70 bg-muted/20 px-2 py-1 text-xs text-muted-foreground", children: "Not tested" });
|
|
8419
|
+
}
|
|
8420
|
+
if (summary.failed > 0) {
|
|
8421
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1 rounded border border-red-400/25 bg-red-500/[0.08] px-2 py-1 text-xs text-red-200", children: [
|
|
8422
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "size-3" }),
|
|
8423
|
+
summary.passed,
|
|
8424
|
+
"/",
|
|
8425
|
+
summary.total,
|
|
8426
|
+
" passed"
|
|
8427
|
+
] });
|
|
8428
|
+
}
|
|
8429
|
+
if (summary.testing > 0 || summary.passed < summary.total) {
|
|
8430
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "rounded border border-amber-300/25 bg-amber-400/[0.08] px-2 py-1 text-xs text-amber-100", children: [
|
|
8431
|
+
"Partial ",
|
|
8432
|
+
summary.passed,
|
|
8433
|
+
"/",
|
|
8434
|
+
summary.total
|
|
8435
|
+
] });
|
|
8436
|
+
}
|
|
8437
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1 rounded border border-cyan-300/25 bg-cyan-300/[0.08] px-2 py-1 text-xs text-cyan-100", children: [
|
|
8438
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "size-3" }),
|
|
8439
|
+
"OK ",
|
|
8440
|
+
summary.passed,
|
|
8441
|
+
"/",
|
|
8442
|
+
summary.total
|
|
8443
|
+
] });
|
|
8444
|
+
}
|
|
8445
|
+
function compactModelLabel(provider) {
|
|
8446
|
+
const models = provider.models ?? [];
|
|
8447
|
+
if (models.length === 0) return "No models configured";
|
|
8448
|
+
const visible = models.slice(0, 2).join(", ");
|
|
8449
|
+
const hiddenCount = models.length - 2;
|
|
8450
|
+
return hiddenCount > 0 ? `${visible} +${hiddenCount} more` : visible;
|
|
8451
|
+
}
|
|
8452
|
+
function ModelChip({ provider, model }) {
|
|
8453
|
+
const metadata = findProviderModelMetadata(provider, model);
|
|
8454
|
+
const sourceLink = getModelSourceLink(metadata?.sourceUrl);
|
|
8455
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground", children: [
|
|
8456
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: model }),
|
|
8457
|
+
metadata !== null && metadata.contextWindow !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-foreground/80", children: formatContextWindowTokens(metadata.contextWindow) }),
|
|
8458
|
+
sourceLink !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
8459
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8460
|
+
"a",
|
|
8461
|
+
{
|
|
8462
|
+
href: sourceLink.url,
|
|
8463
|
+
target: "_blank",
|
|
8464
|
+
rel: "noopener noreferrer",
|
|
8465
|
+
className: "inline-flex items-center gap-0.5 rounded border border-border/70 bg-background/70 px-1 font-mono text-[10px] leading-4 text-muted-foreground transition-colors hover:text-foreground",
|
|
8466
|
+
"aria-label": sourceLink.title,
|
|
8467
|
+
children: sourceLink.label
|
|
8468
|
+
}
|
|
8469
|
+
) }),
|
|
8470
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: sourceLink.title })
|
|
8471
|
+
] }) })
|
|
8472
|
+
] });
|
|
8473
|
+
}
|
|
8474
|
+
function modelResultsLabel(testResults) {
|
|
8475
|
+
const models = testResults?.models;
|
|
8476
|
+
if (models === void 0) return null;
|
|
8477
|
+
const count = Object.keys(models).length;
|
|
8478
|
+
if (count === 0) return null;
|
|
8479
|
+
return `${count} model${count === 1 ? "" : "s"} tested`;
|
|
8480
|
+
}
|
|
8330
8481
|
function getErrorIcon(type) {
|
|
8331
8482
|
const iconProps = { className: "size-3", strokeWidth: 2 };
|
|
8332
8483
|
switch (type) {
|
|
@@ -8513,6 +8664,7 @@ function ProviderCard({
|
|
|
8513
8664
|
}) {
|
|
8514
8665
|
const [showApiKey, setShowApiKey] = reactExports.useState(false);
|
|
8515
8666
|
const [copied, setCopied] = reactExports.useState(false);
|
|
8667
|
+
const [showDetails, setShowDetails] = reactExports.useState(false);
|
|
8516
8668
|
const [showModelResults, setShowModelResults] = reactExports.useState(false);
|
|
8517
8669
|
function handleCopy() {
|
|
8518
8670
|
void copyTextToClipboard(provider.apiKey).then((success) => {
|
|
@@ -8527,6 +8679,8 @@ function ProviderCard({
|
|
|
8527
8679
|
const hasContextMetadata = providerHasContextMetadata(provider);
|
|
8528
8680
|
const canRefreshMetadata = provider.modelMetadataUrl !== void 0 && provider.modelMetadataUrl.trim() !== "";
|
|
8529
8681
|
const metadataImportLabel = canRefreshMetadata ? "Refresh" : "Import defaults";
|
|
8682
|
+
const isTestingValue = isTesting ?? false;
|
|
8683
|
+
const testedModelsLabel = modelResultsLabel(testResults);
|
|
8530
8684
|
const providerSourceBadge = provider.source === "company" ? /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
8531
8685
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 rounded border border-cyan-300/20 bg-cyan-300/[0.08] px-1.5 py-0.5 text-xs text-cyan-100", children: "Company" }) }),
|
|
8532
8686
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Company-provided API key" })
|
|
@@ -8537,65 +8691,53 @@ function ProviderCard({
|
|
|
8537
8691
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8538
8692
|
"div",
|
|
8539
8693
|
{
|
|
8540
|
-
className: `
|
|
8694
|
+
className: `flex flex-col gap-3 rounded-[8px] border border-border bg-card p-4 shadow-sm transition-all duration-500 ${isHighlighted === true ? "ring-2 ring-primary shadow-md" : ""}`,
|
|
8541
8695
|
children: [
|
|
8542
8696
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
8543
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "
|
|
8544
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
8545
|
-
|
|
8546
|
-
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
] }) }),
|
|
8550
|
-
providerSourceBadge === null && provider.source === "personal" && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
8551
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs px-1.5 py-0.5 rounded bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400 shrink-0", children: "个人" }) }),
|
|
8552
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Your personal API key" })
|
|
8553
|
-
] }) })
|
|
8697
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 space-y-1", children: [
|
|
8698
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
8699
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate font-medium", children: provider.name }),
|
|
8700
|
+
providerSourceBadge
|
|
8701
|
+
] }),
|
|
8702
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "truncate text-xs text-muted-foreground", children: compactModelLabel(provider) })
|
|
8554
8703
|
] }),
|
|
8555
|
-
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8562
|
-
|
|
8563
|
-
|
|
8564
|
-
|
|
8565
|
-
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8704
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
8705
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8706
|
+
ProviderTestPill,
|
|
8707
|
+
{
|
|
8708
|
+
provider,
|
|
8709
|
+
testResults,
|
|
8710
|
+
isTesting: isTestingValue
|
|
8711
|
+
}
|
|
8712
|
+
),
|
|
8713
|
+
docsUrl !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8714
|
+
"a",
|
|
8715
|
+
{
|
|
8716
|
+
href: docsUrl,
|
|
8717
|
+
target: "_blank",
|
|
8718
|
+
rel: "noopener noreferrer",
|
|
8719
|
+
className: "flex items-center gap-1 text-xs text-muted-foreground transition-colors hover:text-foreground",
|
|
8720
|
+
title: "View API documentation",
|
|
8721
|
+
children: [
|
|
8722
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { className: "size-3" }),
|
|
8723
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sr-only", children: "Docs" })
|
|
8724
|
+
]
|
|
8725
|
+
}
|
|
8726
|
+
)
|
|
8727
|
+
] })
|
|
8728
|
+
] }),
|
|
8729
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2 text-xs text-muted-foreground sm:flex-row sm:items-center sm:justify-between", children: [
|
|
8730
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ProviderTestCoverage, { provider }),
|
|
8731
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
8732
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Key configured" }),
|
|
8733
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: provider.authHeader === "x-api-key" ? "x-api-key" : "Bearer" }),
|
|
8734
|
+
testedModelsLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: testedModelsLabel }),
|
|
8735
|
+
testResults?.testedAt !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
8736
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
|
|
8737
|
+
formatTimeAgo(testResults.testedAt)
|
|
8738
|
+
] })
|
|
8739
|
+
] })
|
|
8569
8740
|
] }),
|
|
8570
|
-
provider.models !== void 0 && provider.models.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-1", children: provider.models.map((m) => {
|
|
8571
|
-
const metadata = findProviderModelMetadata(provider, m);
|
|
8572
|
-
const sourceLink = getModelSourceLink(metadata?.sourceUrl);
|
|
8573
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8574
|
-
"span",
|
|
8575
|
-
{
|
|
8576
|
-
className: "inline-flex items-center gap-1 text-xs px-1.5 py-0.5 rounded bg-muted text-muted-foreground",
|
|
8577
|
-
children: [
|
|
8578
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: m }),
|
|
8579
|
-
metadata !== null && metadata.contextWindow !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-foreground/80", children: formatContextWindowTokens(metadata.contextWindow) }),
|
|
8580
|
-
sourceLink !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
8581
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8582
|
-
"a",
|
|
8583
|
-
{
|
|
8584
|
-
href: sourceLink.url,
|
|
8585
|
-
target: "_blank",
|
|
8586
|
-
rel: "noopener noreferrer",
|
|
8587
|
-
className: "inline-flex items-center gap-0.5 rounded border border-border/70 bg-background/70 px-1 font-mono text-[10px] leading-4 text-muted-foreground transition-colors hover:text-foreground",
|
|
8588
|
-
"aria-label": sourceLink.title,
|
|
8589
|
-
children: sourceLink.label
|
|
8590
|
-
}
|
|
8591
|
-
) }),
|
|
8592
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: sourceLink.title })
|
|
8593
|
-
] }) })
|
|
8594
|
-
]
|
|
8595
|
-
},
|
|
8596
|
-
m
|
|
8597
|
-
);
|
|
8598
|
-
}) }),
|
|
8599
8741
|
!hasContextMetadata && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 rounded-md border border-amber-500/25 bg-amber-500/6 px-2 py-1.5 text-xs text-muted-foreground", children: [
|
|
8600
8742
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Context window metadata missing" }),
|
|
8601
8743
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
@@ -8627,139 +8769,150 @@ function ProviderCard({
|
|
|
8627
8769
|
)
|
|
8628
8770
|
] })
|
|
8629
8771
|
] }),
|
|
8630
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "
|
|
8631
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
8632
|
-
|
|
8633
|
-
|
|
8772
|
+
showDetails && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3 border-t border-border/60 pt-3", children: [
|
|
8773
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8774
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "flex-1 truncate rounded bg-muted px-2 py-1 text-xs text-muted-foreground", children: showApiKey ? provider.apiKey : maskApiKey(provider.apiKey) }),
|
|
8775
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8776
|
+
"button",
|
|
8777
|
+
{
|
|
8778
|
+
type: "button",
|
|
8779
|
+
onClick: () => setShowApiKey((s) => !s),
|
|
8780
|
+
className: "p-1 text-muted-foreground transition-colors hover:text-foreground",
|
|
8781
|
+
"aria-label": showApiKey ? "Hide API key" : "Show API key",
|
|
8782
|
+
children: showApiKey ? /* @__PURE__ */ jsxRuntimeExports.jsx(EyeOff, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { className: "size-4" })
|
|
8783
|
+
}
|
|
8784
|
+
),
|
|
8785
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8786
|
+
"button",
|
|
8787
|
+
{
|
|
8788
|
+
type: "button",
|
|
8789
|
+
onClick: handleCopy,
|
|
8790
|
+
className: "p-1 text-muted-foreground transition-colors hover:text-foreground",
|
|
8791
|
+
"aria-label": "Copy API key",
|
|
8792
|
+
children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-4 text-cyan-300" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-4" })
|
|
8793
|
+
}
|
|
8794
|
+
)
|
|
8795
|
+
] }),
|
|
8796
|
+
provider.models !== void 0 && provider.models.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-1", children: provider.models.map((model) => /* @__PURE__ */ jsxRuntimeExports.jsx(ModelChip, { provider, model }, model)) }),
|
|
8797
|
+
providerHasEndpoint(provider.anthropicBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8798
|
+
ProviderEndpointSummary,
|
|
8634
8799
|
{
|
|
8635
|
-
|
|
8636
|
-
|
|
8637
|
-
|
|
8638
|
-
|
|
8639
|
-
children:
|
|
8800
|
+
label: "Anthropic",
|
|
8801
|
+
baseUrl: provider.anthropicBaseUrl,
|
|
8802
|
+
endpoint: PATH_V1_MESSAGES,
|
|
8803
|
+
providerName: provider.name,
|
|
8804
|
+
children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.anthropic })
|
|
8640
8805
|
}
|
|
8641
8806
|
),
|
|
8642
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8643
|
-
|
|
8807
|
+
providerHasEndpoint(provider.openaiBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8808
|
+
ProviderEndpointSummary,
|
|
8644
8809
|
{
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
children:
|
|
8650
|
-
}
|
|
8651
|
-
)
|
|
8652
|
-
] }),
|
|
8653
|
-
provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8654
|
-
ProviderEndpointSummary,
|
|
8655
|
-
{
|
|
8656
|
-
label: "Anthropic",
|
|
8657
|
-
baseUrl: provider.anthropicBaseUrl,
|
|
8658
|
-
endpoint: PATH_V1_MESSAGES,
|
|
8659
|
-
providerName: provider.name,
|
|
8660
|
-
children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.anthropic })
|
|
8661
|
-
}
|
|
8662
|
-
),
|
|
8663
|
-
provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8664
|
-
ProviderEndpointSummary,
|
|
8665
|
-
{
|
|
8666
|
-
label: "OpenAI Chat",
|
|
8667
|
-
baseUrl: provider.openaiBaseUrl,
|
|
8668
|
-
endpoint: PATH_V1_CHAT_COMPLETIONS,
|
|
8669
|
-
providerName: provider.name,
|
|
8670
|
-
children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openaiChat })
|
|
8671
|
-
}
|
|
8672
|
-
),
|
|
8673
|
-
provider.openaiResponsesBaseUrl !== void 0 && provider.openaiResponsesBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8674
|
-
ProviderEndpointSummary,
|
|
8675
|
-
{
|
|
8676
|
-
label: "OpenAI Responses",
|
|
8677
|
-
baseUrl: provider.openaiResponsesBaseUrl,
|
|
8678
|
-
endpoint: PATH_V1_RESPONSES,
|
|
8679
|
-
providerName: provider.name,
|
|
8680
|
-
children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openaiResponses })
|
|
8681
|
-
}
|
|
8682
|
-
),
|
|
8683
|
-
testResults?.testedAt !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-muted-foreground flex items-center gap-1", children: [
|
|
8684
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
|
|
8685
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
8686
|
-
"Tested ",
|
|
8687
|
-
formatTimeAgo(testResults.testedAt)
|
|
8688
|
-
] })
|
|
8689
|
-
] }),
|
|
8690
|
-
testResults?.models !== void 0 && Object.keys(testResults.models).length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-t pt-2", children: [
|
|
8691
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8692
|
-
"button",
|
|
8693
|
-
{
|
|
8694
|
-
type: "button",
|
|
8695
|
-
onClick: () => setShowModelResults((value) => !value),
|
|
8696
|
-
className: "text-xs text-muted-foreground hover:text-foreground transition-colors flex items-center gap-1",
|
|
8697
|
-
children: [
|
|
8698
|
-
showModelResults ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3" }),
|
|
8699
|
-
"Model Test Results (",
|
|
8700
|
-
Object.keys(testResults.models).length,
|
|
8701
|
-
")"
|
|
8702
|
-
]
|
|
8810
|
+
label: "Chat",
|
|
8811
|
+
baseUrl: provider.openaiBaseUrl,
|
|
8812
|
+
endpoint: PATH_V1_CHAT_COMPLETIONS,
|
|
8813
|
+
providerName: provider.name,
|
|
8814
|
+
children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openaiChat })
|
|
8703
8815
|
}
|
|
8704
8816
|
),
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "text-left py-1 px-2 font-medium text-muted-foreground", children: "Model" }),
|
|
8708
|
-
provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "text-left py-1 px-2 font-medium text-muted-foreground", children: "Anthropic" }),
|
|
8709
|
-
provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "text-left py-1 px-2 font-medium text-muted-foreground", children: "Chat" }),
|
|
8710
|
-
provider.openaiResponsesBaseUrl !== void 0 && provider.openaiResponsesBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "text-left py-1 px-2 font-medium text-muted-foreground", children: "Responses" })
|
|
8711
|
-
] }) }),
|
|
8712
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: Object.entries(testResults.models).map(([modelName, modelResult]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "border-b border-border/50 last:border-0", children: [
|
|
8713
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1 px-2 font-medium", children: modelName }),
|
|
8714
|
-
provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1 px-2 align-top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: modelResult.anthropic }) }),
|
|
8715
|
-
provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1 px-2 align-top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: modelResult.openaiChat }) }),
|
|
8716
|
-
provider.openaiResponsesBaseUrl !== void 0 && provider.openaiResponsesBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1 px-2 align-top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: modelResult.openaiResponses }) })
|
|
8717
|
-
] }, modelName)) })
|
|
8718
|
-
] }) })
|
|
8719
|
-
] }),
|
|
8720
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2 pt-1 border-t", children: [
|
|
8721
|
-
onTest !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8722
|
-
Button,
|
|
8817
|
+
providerHasEndpoint(provider.openaiResponsesBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8818
|
+
ProviderEndpointSummary,
|
|
8723
8819
|
{
|
|
8724
|
-
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
|
|
8728
|
-
|
|
8729
|
-
children: [
|
|
8730
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(RotateCw, { className: `size-3 ${isTesting ?? false ? "animate-spin" : ""}` }),
|
|
8731
|
-
isTesting ?? false ? testingTimeLeft !== void 0 ? `Testing (${testingTimeLeft}s)` : "Testing..." : "Test"
|
|
8732
|
-
]
|
|
8820
|
+
label: "Responses",
|
|
8821
|
+
baseUrl: provider.openaiResponsesBaseUrl,
|
|
8822
|
+
endpoint: PATH_V1_RESPONSES,
|
|
8823
|
+
providerName: provider.name,
|
|
8824
|
+
children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openaiResponses })
|
|
8733
8825
|
}
|
|
8734
8826
|
),
|
|
8827
|
+
testResults?.models !== void 0 && Object.keys(testResults.models).length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
8828
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8829
|
+
"button",
|
|
8830
|
+
{
|
|
8831
|
+
type: "button",
|
|
8832
|
+
onClick: () => setShowModelResults((value) => !value),
|
|
8833
|
+
className: "flex items-center gap-1 text-xs text-muted-foreground transition-colors hover:text-foreground",
|
|
8834
|
+
children: [
|
|
8835
|
+
showModelResults ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3" }),
|
|
8836
|
+
"Model Test Results (",
|
|
8837
|
+
Object.keys(testResults.models).length,
|
|
8838
|
+
")"
|
|
8839
|
+
]
|
|
8840
|
+
}
|
|
8841
|
+
),
|
|
8842
|
+
showModelResults && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 overflow-x-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("table", { className: "w-full border-collapse text-xs", children: [
|
|
8843
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("thead", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "border-b border-border", children: [
|
|
8844
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-2 py-1 text-left font-medium text-muted-foreground", children: "Model" }),
|
|
8845
|
+
providerHasEndpoint(provider.anthropicBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-2 py-1 text-left font-medium text-muted-foreground", children: "Anthropic" }),
|
|
8846
|
+
providerHasEndpoint(provider.openaiBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-2 py-1 text-left font-medium text-muted-foreground", children: "Chat" }),
|
|
8847
|
+
providerHasEndpoint(provider.openaiResponsesBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-2 py-1 text-left font-medium text-muted-foreground", children: "Responses" })
|
|
8848
|
+
] }) }),
|
|
8849
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: Object.entries(testResults.models).map(([modelName, modelResult]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "border-b border-border/50 last:border-0", children: [
|
|
8850
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-2 py-1 font-medium", children: modelName }),
|
|
8851
|
+
providerHasEndpoint(provider.anthropicBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-2 py-1 align-top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: modelResult.anthropic }) }),
|
|
8852
|
+
providerHasEndpoint(provider.openaiBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-2 py-1 align-top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: modelResult.openaiChat }) }),
|
|
8853
|
+
providerHasEndpoint(provider.openaiResponsesBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-2 py-1 align-top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: modelResult.openaiResponses }) })
|
|
8854
|
+
] }, modelName)) })
|
|
8855
|
+
] }) })
|
|
8856
|
+
] })
|
|
8857
|
+
] }),
|
|
8858
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2 border-t pt-1 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
8735
8859
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8736
|
-
|
|
8860
|
+
"button",
|
|
8737
8861
|
{
|
|
8738
|
-
|
|
8739
|
-
|
|
8740
|
-
|
|
8741
|
-
|
|
8742
|
-
disabled: isTesting ?? false,
|
|
8862
|
+
type: "button",
|
|
8863
|
+
onClick: () => setShowDetails((value) => !value),
|
|
8864
|
+
className: "inline-flex items-center gap-1 text-xs text-muted-foreground transition-colors hover:text-foreground",
|
|
8865
|
+
"aria-expanded": showDetails,
|
|
8743
8866
|
children: [
|
|
8744
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8745
|
-
"
|
|
8867
|
+
showDetails ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3" }),
|
|
8868
|
+
"Details"
|
|
8746
8869
|
]
|
|
8747
8870
|
}
|
|
8748
8871
|
),
|
|
8749
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
|
|
8755
|
-
|
|
8756
|
-
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
|
|
8761
|
-
|
|
8762
|
-
|
|
8872
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
8873
|
+
onTest !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8874
|
+
Button,
|
|
8875
|
+
{
|
|
8876
|
+
variant: "outline",
|
|
8877
|
+
size: "sm",
|
|
8878
|
+
onClick: () => onTest(provider.id),
|
|
8879
|
+
className: "text-xs h-7 gap-1",
|
|
8880
|
+
disabled: isTestingValue,
|
|
8881
|
+
children: [
|
|
8882
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RotateCw, { className: `size-3 ${isTestingValue ? "animate-spin" : ""}` }),
|
|
8883
|
+
isTestingValue ? testingTimeLeft !== void 0 ? `Testing (${testingTimeLeft}s)` : "Testing..." : "Test"
|
|
8884
|
+
]
|
|
8885
|
+
}
|
|
8886
|
+
),
|
|
8887
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8888
|
+
Button,
|
|
8889
|
+
{
|
|
8890
|
+
variant: "outline",
|
|
8891
|
+
size: "sm",
|
|
8892
|
+
onClick: () => onEdit(provider),
|
|
8893
|
+
className: "text-xs h-7 gap-1",
|
|
8894
|
+
disabled: isTestingValue,
|
|
8895
|
+
children: [
|
|
8896
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Pencil, { className: "size-3" }),
|
|
8897
|
+
"Edit"
|
|
8898
|
+
]
|
|
8899
|
+
}
|
|
8900
|
+
),
|
|
8901
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8902
|
+
Button,
|
|
8903
|
+
{
|
|
8904
|
+
variant: "outline",
|
|
8905
|
+
size: "sm",
|
|
8906
|
+
onClick: () => onDelete(provider.id),
|
|
8907
|
+
className: "text-xs h-7 gap-1 text-destructive hover:text-destructive",
|
|
8908
|
+
disabled: isTestingValue,
|
|
8909
|
+
children: [
|
|
8910
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3" }),
|
|
8911
|
+
"Delete"
|
|
8912
|
+
]
|
|
8913
|
+
}
|
|
8914
|
+
)
|
|
8915
|
+
] })
|
|
8763
8916
|
] })
|
|
8764
8917
|
]
|
|
8765
8918
|
}
|
|
@@ -13704,6 +13857,7 @@ function ProxyViewer({
|
|
|
13704
13857
|
onSessionChange,
|
|
13705
13858
|
onModelChange,
|
|
13706
13859
|
onClearAll,
|
|
13860
|
+
onReloadSession,
|
|
13707
13861
|
onClearGroup,
|
|
13708
13862
|
onNotify,
|
|
13709
13863
|
onImportLogs,
|
|
@@ -13829,6 +13983,8 @@ function ProxyViewer({
|
|
|
13829
13983
|
const comparisonPredecessors = reactExports.useMemo(() => buildValidPredecessors(groups), [groups]);
|
|
13830
13984
|
const exportActionVisibility = getExportActionVisibility(captureMode, logs.length);
|
|
13831
13985
|
const isPinnedSessionPage = pinnedSessionId !== void 0;
|
|
13986
|
+
const canClearCurrentView = logs.length > 0;
|
|
13987
|
+
const reloadSessionLabel = logs.length === 0 ? "Load" : "Reload";
|
|
13832
13988
|
const sessionInputValue = selectedSession === "__all__" ? "" : selectedSession;
|
|
13833
13989
|
const sessionSelectValue = selectedSession === "__all__" || sessions.includes(selectedSession) ? selectedSession : "__typed__";
|
|
13834
13990
|
const activeScopeLabel = hasSessionContext && sessionContextScope !== null ? truncateSessionId(sessionContextScope.label) : selectedSession === "__all__" ? "All sessions" : truncateSessionId(selectedSession);
|
|
@@ -13864,26 +14020,62 @@ function ProxyViewer({
|
|
|
13864
14020
|
[onSessionChange]
|
|
13865
14021
|
);
|
|
13866
14022
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-background min-h-screen w-full text-foreground", children: [
|
|
13867
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid min-h-screen w-full grid-cols-1 lg:grid-cols-[
|
|
13868
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("aside", { className: "bg-background/95 border-b border-white/[0.045] lg:sticky lg:top-0 lg:h-screen lg:overflow-y-auto lg:border-b-0 lg:border-
|
|
14023
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid min-h-screen w-full grid-cols-1 lg:grid-cols-[minmax(0,1fr)_340px] xl:grid-cols-[minmax(0,1fr)_360px]", children: [
|
|
14024
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("aside", { className: "bg-background/95 order-1 border-b border-white/[0.045] lg:sticky lg:top-0 lg:order-2 lg:h-screen lg:overflow-y-auto lg:border-b-0 lg:border-l lg:border-white/[0.055]", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4 p-4", children: [
|
|
13869
14025
|
/* @__PURE__ */ jsxRuntimeExports.jsx(BrandHeader, { compact: true, crabEntrancePhase }),
|
|
13870
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
13871
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
13872
|
-
|
|
13873
|
-
SidebarMetric,
|
|
13874
|
-
|
|
13875
|
-
|
|
13876
|
-
|
|
13877
|
-
|
|
13878
|
-
|
|
13879
|
-
|
|
13880
|
-
|
|
13881
|
-
|
|
13882
|
-
|
|
13883
|
-
|
|
13884
|
-
|
|
13885
|
-
|
|
13886
|
-
|
|
14026
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(SidebarPanel, { label: "Session", children: [
|
|
14027
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
14028
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SidebarMetric, { label: "Requests", value: logs.length }),
|
|
14029
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SidebarMetric, { label: "Sessions", value: sessions.length }),
|
|
14030
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14031
|
+
SidebarMetric,
|
|
14032
|
+
{
|
|
14033
|
+
label: "Input",
|
|
14034
|
+
value: formatTokens(hasSessionContext ? sessionContextTotalIn : totalIn)
|
|
14035
|
+
}
|
|
14036
|
+
),
|
|
14037
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14038
|
+
SidebarMetric,
|
|
14039
|
+
{
|
|
14040
|
+
label: "Output",
|
|
14041
|
+
value: formatTokens(hasSessionContext ? sessionContextTotalOut : totalOut)
|
|
14042
|
+
}
|
|
14043
|
+
)
|
|
14044
|
+
] }),
|
|
14045
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 grid grid-cols-2 gap-2", children: [
|
|
14046
|
+
onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
14047
|
+
"button",
|
|
14048
|
+
{
|
|
14049
|
+
type: "button",
|
|
14050
|
+
onClick: onReloadSession,
|
|
14051
|
+
disabled: isLoading,
|
|
14052
|
+
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 min-w-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
14053
|
+
title: "Load stored logs for this session",
|
|
14054
|
+
children: [
|
|
14055
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: cn("size-3.5", isLoading && "animate-spin") }),
|
|
14056
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: reloadSessionLabel })
|
|
14057
|
+
]
|
|
14058
|
+
}
|
|
14059
|
+
),
|
|
14060
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
14061
|
+
"button",
|
|
14062
|
+
{
|
|
14063
|
+
type: "button",
|
|
14064
|
+
onClick: onClearAll,
|
|
14065
|
+
disabled: !canClearCurrentView,
|
|
14066
|
+
className: cn(
|
|
14067
|
+
"bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 min-w-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
14068
|
+
onReloadSession === void 0 && "col-span-2"
|
|
14069
|
+
),
|
|
14070
|
+
title: "Clear the current view. Stored logs remain reloadable.",
|
|
14071
|
+
children: [
|
|
14072
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
|
|
14073
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear view" })
|
|
14074
|
+
]
|
|
14075
|
+
}
|
|
14076
|
+
)
|
|
14077
|
+
] })
|
|
14078
|
+
] }),
|
|
13887
14079
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SidebarPanel, { label: "Workspace", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-black/20 rounded-md px-3 py-2 shadow-[inset_0_1px_0_rgba(255,255,255,0.035)]", children: [
|
|
13888
14080
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13889
14081
|
"div",
|
|
@@ -13957,7 +14149,7 @@ function ProxyViewer({
|
|
|
13957
14149
|
] })
|
|
13958
14150
|
] }) })
|
|
13959
14151
|
] }) }),
|
|
13960
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "min-w-0", children: [
|
|
14152
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "order-2 min-w-0 lg:order-1", children: [
|
|
13961
14153
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-background/95 shadow-[0_12px_36px_rgba(0,0,0,0.18),inset_0_-1px_0_rgba(255,255,255,0.045)] sticky top-0 z-30 px-4 py-3 lg:px-5", children: [
|
|
13962
14154
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
13963
14155
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-[180px] flex-1", children: [
|
|
@@ -14022,16 +14214,31 @@ function ProxyViewer({
|
|
|
14022
14214
|
] })
|
|
14023
14215
|
}
|
|
14024
14216
|
),
|
|
14217
|
+
onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
14218
|
+
"button",
|
|
14219
|
+
{
|
|
14220
|
+
type: "button",
|
|
14221
|
+
onClick: onReloadSession,
|
|
14222
|
+
disabled: isLoading,
|
|
14223
|
+
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
14224
|
+
title: "Reload this session from stored logs",
|
|
14225
|
+
children: [
|
|
14226
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: cn("size-3.5", isLoading && "animate-spin") }),
|
|
14227
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: reloadSessionLabel })
|
|
14228
|
+
]
|
|
14229
|
+
}
|
|
14230
|
+
),
|
|
14025
14231
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
14026
14232
|
"button",
|
|
14027
14233
|
{
|
|
14028
14234
|
type: "button",
|
|
14029
14235
|
onClick: onClearAll,
|
|
14030
|
-
|
|
14031
|
-
|
|
14236
|
+
disabled: !canClearCurrentView,
|
|
14237
|
+
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
14238
|
+
title: "Clear the current view. Stored logs remain reloadable.",
|
|
14032
14239
|
children: [
|
|
14033
14240
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
|
|
14034
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear" })
|
|
14241
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear view" })
|
|
14035
14242
|
]
|
|
14036
14243
|
}
|
|
14037
14244
|
)
|
|
@@ -14044,24 +14251,45 @@ function ProxyViewer({
|
|
|
14044
14251
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-4 lg:px-5", children: [
|
|
14045
14252
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SessionOpeningSlate, { stats: slateStats }),
|
|
14046
14253
|
logs.length === 0 ? selectedSession !== "__all__" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_18px_52px_rgba(0,0,0,0.18)] mx-auto max-w-xl space-y-4 rounded-[8px] px-4 py-8", children: [
|
|
14047
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : "
|
|
14254
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : "No logs loaded for this session" }),
|
|
14048
14255
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "inline-block max-w-full rounded bg-muted px-3 py-1 font-mono text-xs break-all", children: truncateSessionId(selectedSession) }),
|
|
14049
14256
|
sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-left", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }) }),
|
|
14050
|
-
!isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("
|
|
14051
|
-
"
|
|
14052
|
-
" ",
|
|
14053
|
-
|
|
14054
|
-
|
|
14055
|
-
|
|
14056
|
-
|
|
14057
|
-
|
|
14058
|
-
|
|
14059
|
-
|
|
14060
|
-
|
|
14061
|
-
|
|
14257
|
+
!isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3 text-xs", children: [
|
|
14258
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Stored logs may still be available." }),
|
|
14259
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
|
|
14260
|
+
onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
14261
|
+
"button",
|
|
14262
|
+
{
|
|
14263
|
+
type: "button",
|
|
14264
|
+
onClick: onReloadSession,
|
|
14265
|
+
className: "bg-white/[0.045] hover:bg-white/[0.075] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground",
|
|
14266
|
+
children: [
|
|
14267
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3.5" }),
|
|
14268
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Load session" })
|
|
14269
|
+
]
|
|
14270
|
+
}
|
|
14271
|
+
),
|
|
14272
|
+
hideSessionFilter ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14273
|
+
"a",
|
|
14274
|
+
{
|
|
14275
|
+
href: "/",
|
|
14276
|
+
className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
|
|
14277
|
+
children: "Back to all sessions"
|
|
14278
|
+
}
|
|
14279
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14280
|
+
"button",
|
|
14281
|
+
{
|
|
14282
|
+
type: "button",
|
|
14283
|
+
onClick: () => onSessionChange("__all__"),
|
|
14284
|
+
className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
|
|
14285
|
+
children: "Show all sessions"
|
|
14286
|
+
}
|
|
14287
|
+
)
|
|
14288
|
+
] })
|
|
14062
14289
|
] })
|
|
14063
14290
|
] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_18px_52px_rgba(0,0,0,0.18)] mx-auto max-w-2xl space-y-4 rounded-[8px] px-4 py-8", children: [
|
|
14064
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "No
|
|
14291
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "No logs loaded in the current view." }),
|
|
14292
|
+
sessions.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mx-auto max-w-xl text-xs leading-relaxed text-muted-foreground", children: "Pick a session from the filter panel to load stored logs on demand." }),
|
|
14065
14293
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
|
|
14066
14294
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "ANTHROPIC_BASE_URL=http://localhost:9527/proxy <your-tool>" }),
|
|
14067
14295
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "OPENAI_BASE_URL=http://localhost:9527/proxy <your-tool>" })
|
|
@@ -14127,6 +14355,7 @@ const LogCursorPageSchema = object({
|
|
|
14127
14355
|
oldestLogId: number().int().positive().nullable(),
|
|
14128
14356
|
newestLogId: number().int().positive().nullable()
|
|
14129
14357
|
});
|
|
14358
|
+
const SessionsResponseSchema = array(string());
|
|
14130
14359
|
function buildSessionMembershipEvidence(groups, sessionId) {
|
|
14131
14360
|
const memberships = [];
|
|
14132
14361
|
for (const group of groups) {
|
|
@@ -14172,6 +14401,8 @@ const DEBOUNCE_MS = 100;
|
|
|
14172
14401
|
const HASH_SCROLL_ATTEMPTS = 12;
|
|
14173
14402
|
const HASH_HIGHLIGHT_MS = 1800;
|
|
14174
14403
|
const SESSION_PAGE_LIMIT = 100;
|
|
14404
|
+
const SESSION_RELOAD_PAGE_LIMIT = 500;
|
|
14405
|
+
const MAX_SESSION_RELOAD_PAGES = 200;
|
|
14175
14406
|
function buildLogsStreamUrl(sessionId) {
|
|
14176
14407
|
const params = new URLSearchParams();
|
|
14177
14408
|
if (sessionId !== void 0) {
|
|
@@ -14181,11 +14412,11 @@ function buildLogsStreamUrl(sessionId) {
|
|
|
14181
14412
|
const query = params.toString();
|
|
14182
14413
|
return query.length > 0 ? `/api/logs/stream?${query}` : "/api/logs/stream";
|
|
14183
14414
|
}
|
|
14184
|
-
function buildSessionLogsPageUrl(sessionId, request) {
|
|
14415
|
+
function buildSessionLogsPageUrl(sessionId, request, limit = SESSION_PAGE_LIMIT) {
|
|
14185
14416
|
const params = new URLSearchParams({
|
|
14186
14417
|
cursor: "1",
|
|
14187
14418
|
compact: "1",
|
|
14188
|
-
limit: String(
|
|
14419
|
+
limit: String(limit),
|
|
14189
14420
|
sessionId
|
|
14190
14421
|
});
|
|
14191
14422
|
switch (request.kind) {
|
|
@@ -14220,12 +14451,23 @@ function mergeLogsById(previousLogs, incomingLogs) {
|
|
|
14220
14451
|
}
|
|
14221
14452
|
return [...byId.values()].sort((left, right) => left.id - right.id);
|
|
14222
14453
|
}
|
|
14454
|
+
function mergeSessionIds(previousSessions, incomingSessions) {
|
|
14455
|
+
const sessions = /* @__PURE__ */ new Set();
|
|
14456
|
+
for (const session of previousSessions) {
|
|
14457
|
+
if (session !== "") sessions.add(session);
|
|
14458
|
+
}
|
|
14459
|
+
for (const session of incomingSessions) {
|
|
14460
|
+
if (session !== "") sessions.add(session);
|
|
14461
|
+
}
|
|
14462
|
+
return [...sessions].sort();
|
|
14463
|
+
}
|
|
14223
14464
|
function ProxyViewerContainer({
|
|
14224
14465
|
initialSessionId
|
|
14225
14466
|
} = {}) {
|
|
14226
14467
|
const [allLogs, setAllLogs] = reactExports.useState([]);
|
|
14227
14468
|
const [selectedSession, setSelectedSession] = reactExports.useState(initialSessionId ?? "__all__");
|
|
14228
14469
|
const [selectedModel, setSelectedModel] = reactExports.useState("__all__");
|
|
14470
|
+
const [knownSessions, setKnownSessions] = reactExports.useState([]);
|
|
14229
14471
|
const { notice, showToast, dismissToast } = useTransientToast();
|
|
14230
14472
|
const [streamInitialized, setStreamInitialized] = reactExports.useState(initialSessionId === void 0);
|
|
14231
14473
|
const [logPage, setLogPage] = reactExports.useState(null);
|
|
@@ -14249,8 +14491,17 @@ function ProxyViewerContainer({
|
|
|
14249
14491
|
() => filterLogs(allLogs, selectedSession, selectedModel),
|
|
14250
14492
|
[allLogs, selectedSession, selectedModel]
|
|
14251
14493
|
);
|
|
14252
|
-
const sessions = reactExports.useMemo(
|
|
14494
|
+
const sessions = reactExports.useMemo(
|
|
14495
|
+
() => mergeSessionIds(knownSessions, extractSessions(allLogs)),
|
|
14496
|
+
[allLogs, knownSessions]
|
|
14497
|
+
);
|
|
14253
14498
|
const models = reactExports.useMemo(() => extractModels(allLogs), [allLogs]);
|
|
14499
|
+
const refreshSessions = reactExports.useCallback(() => {
|
|
14500
|
+
void fetchJson("/api/sessions", SessionsResponseSchema).then((sessionIds) => {
|
|
14501
|
+
setKnownSessions((prev) => mergeSessionIds(prev, sessionIds));
|
|
14502
|
+
}).catch(() => {
|
|
14503
|
+
});
|
|
14504
|
+
}, []);
|
|
14254
14505
|
const flushUpdates = reactExports.useCallback(() => {
|
|
14255
14506
|
flushTimerRef.current = null;
|
|
14256
14507
|
const updates = pendingUpdatesRef.current;
|
|
@@ -14301,9 +14552,14 @@ function ProxyViewerContainer({
|
|
|
14301
14552
|
logIndexRef.current = buildLogIndex(nextLogs);
|
|
14302
14553
|
return nextLogs;
|
|
14303
14554
|
});
|
|
14555
|
+
setKnownSessions((prev) => mergeSessionIds(prev, extractSessions(update.logs)));
|
|
14304
14556
|
setStreamInitialized(true);
|
|
14305
14557
|
dismissToast();
|
|
14306
14558
|
} else if (update.type === "update") {
|
|
14559
|
+
setKnownSessions((prev) => {
|
|
14560
|
+
if (update.log.sessionId === null || update.log.sessionId === "") return prev;
|
|
14561
|
+
return mergeSessionIds(prev, [update.log.sessionId]);
|
|
14562
|
+
});
|
|
14307
14563
|
scheduleUpdate(update.log);
|
|
14308
14564
|
}
|
|
14309
14565
|
} catch {
|
|
@@ -14346,6 +14602,56 @@ function ProxyViewerContainer({
|
|
|
14346
14602
|
},
|
|
14347
14603
|
[dismissToast, initialSessionId, showErrorToast]
|
|
14348
14604
|
);
|
|
14605
|
+
const reloadSessionLogs = reactExports.useCallback(
|
|
14606
|
+
(sessionId) => {
|
|
14607
|
+
const requestId = sessionPageRequestIdRef.current + 1;
|
|
14608
|
+
sessionPageRequestIdRef.current = requestId;
|
|
14609
|
+
setSessionPageLoading(true);
|
|
14610
|
+
dismissToast();
|
|
14611
|
+
void (async () => {
|
|
14612
|
+
const collected = [];
|
|
14613
|
+
let page = await fetchJson(
|
|
14614
|
+
buildSessionLogsPageUrl(sessionId, { kind: "oldest" }, SESSION_RELOAD_PAGE_LIMIT),
|
|
14615
|
+
LogCursorPageSchema
|
|
14616
|
+
);
|
|
14617
|
+
collected.push(...page.logs);
|
|
14618
|
+
let loadedPages = 1;
|
|
14619
|
+
while (page.hasNewer && page.newestLogId !== null && loadedPages < MAX_SESSION_RELOAD_PAGES) {
|
|
14620
|
+
page = await fetchJson(
|
|
14621
|
+
buildSessionLogsPageUrl(
|
|
14622
|
+
sessionId,
|
|
14623
|
+
{ kind: "newer", afterLogId: page.newestLogId },
|
|
14624
|
+
SESSION_RELOAD_PAGE_LIMIT
|
|
14625
|
+
),
|
|
14626
|
+
LogCursorPageSchema
|
|
14627
|
+
);
|
|
14628
|
+
collected.push(...page.logs);
|
|
14629
|
+
loadedPages += 1;
|
|
14630
|
+
}
|
|
14631
|
+
if (sessionPageRequestIdRef.current !== requestId) return;
|
|
14632
|
+
setAllLogs((prev) => {
|
|
14633
|
+
const next = mergeLogsById(prev, collected);
|
|
14634
|
+
logIndexRef.current = buildLogIndex(next);
|
|
14635
|
+
return next;
|
|
14636
|
+
});
|
|
14637
|
+
setKnownSessions((prev) => mergeSessionIds(prev, [sessionId]));
|
|
14638
|
+
setSessionPageLoading(false);
|
|
14639
|
+
if (page.hasNewer) {
|
|
14640
|
+
showToast({
|
|
14641
|
+
message: `Loaded ${String(collected.length)} logs for this session. More history is available.`,
|
|
14642
|
+
tone: "success"
|
|
14643
|
+
});
|
|
14644
|
+
} else {
|
|
14645
|
+
dismissToast();
|
|
14646
|
+
}
|
|
14647
|
+
})().catch((err) => {
|
|
14648
|
+
if (sessionPageRequestIdRef.current !== requestId) return;
|
|
14649
|
+
setSessionPageLoading(false);
|
|
14650
|
+
showErrorToast(err instanceof Error ? err.message : "Failed to reload session logs");
|
|
14651
|
+
});
|
|
14652
|
+
},
|
|
14653
|
+
[dismissToast, showErrorToast, showToast]
|
|
14654
|
+
);
|
|
14349
14655
|
reactExports.useEffect(() => {
|
|
14350
14656
|
if (initialSessionId === void 0) {
|
|
14351
14657
|
setSessionMemberships([]);
|
|
@@ -14367,10 +14673,18 @@ function ProxyViewerContainer({
|
|
|
14367
14673
|
cancelled = true;
|
|
14368
14674
|
};
|
|
14369
14675
|
}, [initialSessionId]);
|
|
14676
|
+
reactExports.useEffect(() => {
|
|
14677
|
+
refreshSessions();
|
|
14678
|
+
}, [refreshSessions]);
|
|
14370
14679
|
reactExports.useEffect(() => {
|
|
14371
14680
|
if (initialSessionId === void 0) return;
|
|
14372
14681
|
loadSessionPage({ kind: "newest" });
|
|
14373
14682
|
}, [initialSessionId, loadSessionPage]);
|
|
14683
|
+
reactExports.useEffect(() => {
|
|
14684
|
+
if (initialSessionId !== void 0) return;
|
|
14685
|
+
if (selectedSession === "__all__") return;
|
|
14686
|
+
reloadSessionLogs(selectedSession);
|
|
14687
|
+
}, [initialSessionId, reloadSessionLogs, selectedSession]);
|
|
14374
14688
|
reactExports.useEffect(() => {
|
|
14375
14689
|
if (initialSessionId !== void 0) return void 0;
|
|
14376
14690
|
connectSSE();
|
|
@@ -14438,57 +14752,42 @@ function ProxyViewerContainer({
|
|
|
14438
14752
|
};
|
|
14439
14753
|
}, [logs.length]);
|
|
14440
14754
|
const handleClearAll = reactExports.useCallback(() => {
|
|
14441
|
-
|
|
14442
|
-
|
|
14443
|
-
|
|
14444
|
-
|
|
14445
|
-
|
|
14446
|
-
|
|
14447
|
-
|
|
14448
|
-
|
|
14449
|
-
|
|
14450
|
-
|
|
14451
|
-
});
|
|
14452
|
-
if (!res.ok) {
|
|
14453
|
-
showErrorToast("Failed to clear logs");
|
|
14454
|
-
return;
|
|
14455
|
-
}
|
|
14456
|
-
logIndexRef.current.clear();
|
|
14457
|
-
setAllLogs([]);
|
|
14458
|
-
dismissToast();
|
|
14459
|
-
} catch (err) {
|
|
14460
|
-
showErrorToast(err instanceof Error ? err.message : "Unknown error clearing logs");
|
|
14461
|
-
}
|
|
14462
|
-
})();
|
|
14463
|
-
}, [allLogs, dismissToast, initialSessionId, showErrorToast]);
|
|
14755
|
+
const clearedSessions = extractSessions(allLogs);
|
|
14756
|
+
logIndexRef.current.clear();
|
|
14757
|
+
setAllLogs([]);
|
|
14758
|
+
setLogPage(null);
|
|
14759
|
+
setKnownSessions((prev) => mergeSessionIds(prev, clearedSessions));
|
|
14760
|
+
showToast({
|
|
14761
|
+
message: "Cleared the current view. Stored logs are still reloadable.",
|
|
14762
|
+
tone: "success"
|
|
14763
|
+
});
|
|
14764
|
+
}, [allLogs, showToast]);
|
|
14464
14765
|
const handleClearGroup = reactExports.useCallback(
|
|
14465
14766
|
(ids) => {
|
|
14466
14767
|
if (ids.length === 0) return;
|
|
14467
|
-
|
|
14468
|
-
|
|
14469
|
-
|
|
14470
|
-
|
|
14471
|
-
|
|
14472
|
-
|
|
14473
|
-
|
|
14474
|
-
|
|
14475
|
-
|
|
14476
|
-
return;
|
|
14477
|
-
}
|
|
14478
|
-
const idSet = new Set(ids);
|
|
14479
|
-
setAllLogs((prev) => {
|
|
14480
|
-
const remaining = prev.filter((l) => !idSet.has(l.id));
|
|
14481
|
-
logIndexRef.current = buildLogIndex(remaining);
|
|
14482
|
-
return remaining;
|
|
14483
|
-
});
|
|
14484
|
-
dismissToast();
|
|
14485
|
-
} catch (err) {
|
|
14486
|
-
showErrorToast(err instanceof Error ? err.message : "Unknown error clearing group");
|
|
14487
|
-
}
|
|
14488
|
-
})();
|
|
14768
|
+
const idSet = new Set(ids);
|
|
14769
|
+
setAllLogs((prev) => {
|
|
14770
|
+
const removed = prev.filter((log) => idSet.has(log.id));
|
|
14771
|
+
const remaining = prev.filter((log) => !idSet.has(log.id));
|
|
14772
|
+
setKnownSessions((known) => mergeSessionIds(known, extractSessions(removed)));
|
|
14773
|
+
logIndexRef.current = buildLogIndex(remaining);
|
|
14774
|
+
return remaining;
|
|
14775
|
+
});
|
|
14776
|
+
showToast({ message: "Cleared this group from the current view.", tone: "success" });
|
|
14489
14777
|
},
|
|
14490
|
-
[
|
|
14778
|
+
[showToast]
|
|
14491
14779
|
);
|
|
14780
|
+
const handleReloadSession = reactExports.useCallback(() => {
|
|
14781
|
+
if (initialSessionId !== void 0) {
|
|
14782
|
+
loadSessionPage({ kind: "newest" });
|
|
14783
|
+
return;
|
|
14784
|
+
}
|
|
14785
|
+
if (selectedSession === "__all__") {
|
|
14786
|
+
refreshSessions();
|
|
14787
|
+
return;
|
|
14788
|
+
}
|
|
14789
|
+
reloadSessionLogs(selectedSession);
|
|
14790
|
+
}, [initialSessionId, loadSessionPage, refreshSessions, reloadSessionLogs, selectedSession]);
|
|
14492
14791
|
const handleImportLogs = reactExports.useCallback(
|
|
14493
14792
|
async (file) => {
|
|
14494
14793
|
const formData = new FormData();
|
|
@@ -14572,10 +14871,11 @@ function ProxyViewerContainer({
|
|
|
14572
14871
|
onSessionChange: setSelectedSession,
|
|
14573
14872
|
onModelChange: setSelectedModel,
|
|
14574
14873
|
onClearAll: handleClearAll,
|
|
14874
|
+
onReloadSession: initialSessionId !== void 0 || selectedSession !== "__all__" ? handleReloadSession : void 0,
|
|
14575
14875
|
onClearGroup: handleClearGroup,
|
|
14576
14876
|
onNotify: showToast,
|
|
14577
14877
|
onImportLogs: initialSessionId === void 0 ? handleImportLogs : void 0,
|
|
14578
|
-
isLoading: initialSessionId === void 0 ? !streamInitialized : sessionPageLoading,
|
|
14878
|
+
isLoading: initialSessionId === void 0 ? !streamInitialized || sessionPageLoading : sessionPageLoading,
|
|
14579
14879
|
pagination,
|
|
14580
14880
|
sessionMemberships,
|
|
14581
14881
|
viewMode,
|