@chenpu17/cc-gw 0.7.6 → 0.7.13

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.
Files changed (29) hide show
  1. package/package.json +1 -1
  2. package/src/server/dist/index.js +158 -70
  3. package/src/web/dist/assets/About-tjjzyak_.js +6 -0
  4. package/src/web/dist/assets/{ApiKeys-DU4MstBL.js → ApiKeys-Bm7WEjdm.js} +1 -1
  5. package/src/web/dist/assets/Dashboard-Bu8kskJg.js +16 -0
  6. package/src/web/dist/assets/{Events-CWHxopwa.js → Events-c_HL4-Bg.js} +1 -1
  7. package/src/web/dist/assets/{Help-DXyYkQj7.js → Help-DCobUSDC.js} +1 -1
  8. package/src/web/dist/assets/{Login-DNlwRCtC.js → Login-oDFHiIDQ.js} +1 -1
  9. package/src/web/dist/assets/Logs-aLo11Oa9.js +6 -0
  10. package/src/web/dist/assets/{ModelManagement-Csx-5GKf.js → ModelManagement-6vVyuoeq.js} +1 -1
  11. package/src/web/dist/assets/{PageHeader-BeW-Othf.js → PageHeader-Bk56T-yb.js} +1 -1
  12. package/src/web/dist/assets/{PageSection-DW84HFxm.js → PageSection-Dq0ilNBn.js} +1 -1
  13. package/src/web/dist/assets/{Settings-DrGMG3PK.js → Settings-BmcSRQUG.js} +1 -1
  14. package/src/web/dist/assets/{card-DO6ly30k.js → card-D5d6AfHr.js} +1 -1
  15. package/src/web/dist/assets/{copy-CSLiPZ3j.js → copy-BLEqa17V.js} +1 -1
  16. package/src/web/dist/assets/{dialog-BTot8EYU.js → dialog-DeP8kdI-.js} +1 -1
  17. package/src/web/dist/assets/{index-D_Dbqo2u.js → index-CeV0AE1d.js} +2 -2
  18. package/src/web/dist/assets/{index-CJAz7pOx.js → index-lin6BsX0.js} +1 -1
  19. package/src/web/dist/assets/{info-XoeNrG0H.js → info-B9sQLv7T.js} +1 -1
  20. package/src/web/dist/assets/{input-Ckx5qHOQ.js → input-DcSN-8OE.js} +1 -1
  21. package/src/web/dist/assets/{label-D2cIIMBu.js → label-C2a8bqtE.js} +1 -1
  22. package/src/web/dist/assets/{refresh-cw-C-S3w6yD.js → refresh-cw-DkrQh2bG.js} +1 -1
  23. package/src/web/dist/assets/{select-CMGw70tW.js → select-H2zEksk5.js} +1 -1
  24. package/src/web/dist/assets/{switch-BYGfNhav.js → switch-B3CHLKV_.js} +1 -1
  25. package/src/web/dist/assets/{useApiQuery-ByGFZwHE.js → useApiQuery-B_olnrT7.js} +1 -1
  26. package/src/web/dist/index.html +1 -1
  27. package/src/web/dist/assets/About-B0d_J5xQ.js +0 -6
  28. package/src/web/dist/assets/Dashboard-DrjpMpn5.js +0 -16
  29. package/src/web/dist/assets/Logs-CzXUpOMo.js +0 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chenpu17/cc-gw",
3
- "version": "0.7.6",
3
+ "version": "0.7.13",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -13779,16 +13779,31 @@ async function registerMessagesRoute(app) {
13779
13779
  }
13780
13780
  } else {
13781
13781
  const collected = {};
13782
- const skip = /* @__PURE__ */ new Set(["content-length", "host", "connection", "transfer-encoding"]);
13783
- const allowedPrefixes = ["x-stainless-", "anthropic-"];
13784
- const allowedHeaders = /* @__PURE__ */ new Set(["user-agent", "content-type", "accept"]);
13782
+ const excludedHeaders = /* @__PURE__ */ new Set([
13783
+ "host",
13784
+ "connection",
13785
+ "content-length",
13786
+ "transfer-encoding",
13787
+ "keep-alive",
13788
+ "upgrade",
13789
+ "proxy-connection",
13790
+ "proxy-authenticate",
13791
+ "proxy-authorization",
13792
+ "te",
13793
+ "trailer",
13794
+ "upgrade-insecure-requests",
13795
+ "authorization",
13796
+ "x-api-key",
13797
+ "content-type",
13798
+ "accept",
13799
+ "accept-encoding",
13800
+ "cookie",
13801
+ "referer"
13802
+ ]);
13785
13803
  const sourceHeaders = request.raw?.headers ?? request.headers;
13786
13804
  for (const [headerKey, headerValue] of Object.entries(sourceHeaders)) {
13787
13805
  const lower = headerKey.toLowerCase();
13788
- if (skip.has(lower))
13789
- continue;
13790
- const shouldForward = allowedHeaders.has(lower) || allowedPrefixes.some((prefix) => lower.startsWith(prefix));
13791
- if (!shouldForward)
13806
+ if (excludedHeaders.has(lower))
13792
13807
  continue;
13793
13808
  let value;
13794
13809
  if (typeof headerValue === "string") {
@@ -15069,12 +15084,32 @@ function filterForwardedAnthropicHeaders(headers) {
15069
15084
  if (!headers)
15070
15085
  return {};
15071
15086
  const result = {};
15072
- const allowContentHeaders = /* @__PURE__ */ new Set(["content-type", "accept", "user-agent"]);
15087
+ const excludedHeaders = /* @__PURE__ */ new Set([
15088
+ "host",
15089
+ "connection",
15090
+ "content-length",
15091
+ "transfer-encoding",
15092
+ "keep-alive",
15093
+ "upgrade",
15094
+ "proxy-connection",
15095
+ "proxy-authenticate",
15096
+ "proxy-authorization",
15097
+ "te",
15098
+ "trailer",
15099
+ "upgrade-insecure-requests",
15100
+ "authorization",
15101
+ "x-api-key",
15102
+ "content-type",
15103
+ "accept",
15104
+ "accept-encoding",
15105
+ "cookie",
15106
+ "referer"
15107
+ ]);
15073
15108
  for (const [key, value] of Object.entries(headers)) {
15074
15109
  if (!value)
15075
15110
  continue;
15076
15111
  const lower = key.toLowerCase();
15077
- if (lower.startsWith("anthropic-") || lower.startsWith("x-stainless-") || allowContentHeaders.has(lower)) {
15112
+ if (!excludedHeaders.has(lower)) {
15078
15113
  result[lower] = value;
15079
15114
  }
15080
15115
  }
@@ -15440,6 +15475,18 @@ async function registerOpenAiRoutes(app) {
15440
15475
  const rawHeaders = request.raw?.headers ?? request.headers;
15441
15476
  const forwarded = collectAnthropicForwardHeaders(rawHeaders);
15442
15477
  providerHeaders = filterForwardedAnthropicHeaders(forwarded);
15478
+ if (OPENAI_DEBUG) {
15479
+ debugLog("responses non-anthropic forwarded headers", providerHeaders);
15480
+ }
15481
+ request.log.info(
15482
+ {
15483
+ event: "responses.forward_headers",
15484
+ provider: target.providerId,
15485
+ model: target.modelId,
15486
+ headers: providerHeaders
15487
+ },
15488
+ "forwarding headers (responses, non-anthropic provider)"
15489
+ );
15443
15490
  providerBody = { ...payload };
15444
15491
  providerBody.model = target.modelId;
15445
15492
  if (Object.prototype.hasOwnProperty.call(payload, "stream")) {
@@ -16024,6 +16071,18 @@ async function registerOpenAiRoutes(app) {
16024
16071
  const rawHeaders = request.raw?.headers ?? request.headers;
16025
16072
  const forwarded = collectAnthropicForwardHeaders(rawHeaders);
16026
16073
  providerHeaders = filterForwardedAnthropicHeaders(forwarded);
16074
+ if (OPENAI_DEBUG) {
16075
+ debugLog("chat completions non-anthropic forwarded headers", providerHeaders);
16076
+ }
16077
+ request.log.info(
16078
+ {
16079
+ event: "chat.completions.forward_headers",
16080
+ provider: target.providerId,
16081
+ model: target.modelId,
16082
+ headers: providerHeaders
16083
+ },
16084
+ "forwarding headers (chat completions, non-anthropic provider)"
16085
+ );
16027
16086
  providerBody = buildProviderBody(normalized, {
16028
16087
  maxTokens: typeof payload.max_tokens === "number" ? payload.max_tokens : void 0,
16029
16088
  temperature: typeof payload.temperature === "number" ? payload.temperature : void 0,
@@ -16998,7 +17057,7 @@ async function registerAdminRoutes(app) {
16998
17057
  const model = typeof raw.model === "string" && raw.model.length > 0 ? raw.model : void 0;
16999
17058
  const statusParam = typeof raw.status === "string" ? raw.status : void 0;
17000
17059
  const status = statusParam === "success" || statusParam === "error" ? statusParam : void 0;
17001
- const endpoint = isEndpoint(raw.endpoint) ? raw.endpoint : void 0;
17060
+ const endpoint = typeof raw.endpoint === "string" && raw.endpoint.length > 0 ? raw.endpoint : void 0;
17002
17061
  const from = parseTimestamp(raw.from);
17003
17062
  const to = parseTimestamp(raw.to);
17004
17063
  const apiKeyIdsRaw = parseApiKeyIds(raw.apiKeys ?? raw.apiKeyIds ?? raw.apiKey);
@@ -17706,14 +17765,14 @@ async function registerAdminRoutes(app) {
17706
17765
  });
17707
17766
  app.get("/api/stats/overview", async (request) => {
17708
17767
  const query = request.query ?? {};
17709
- const endpoint = isEndpoint(query.endpoint) ? query.endpoint : void 0;
17768
+ const endpoint = typeof query.endpoint === "string" && query.endpoint.length > 0 ? query.endpoint : void 0;
17710
17769
  return getMetricsOverview(endpoint);
17711
17770
  });
17712
17771
  app.get("/api/stats/daily", async (request) => {
17713
17772
  const query = request.query ?? {};
17714
17773
  const daysRaw = Number(query.days ?? 7);
17715
17774
  const days = Number.isFinite(daysRaw) ? Math.max(1, Math.min(daysRaw, 30)) : 7;
17716
- const endpoint = isEndpoint(query.endpoint) ? query.endpoint : void 0;
17775
+ const endpoint = typeof query.endpoint === "string" && query.endpoint.length > 0 ? query.endpoint : void 0;
17717
17776
  return getDailyMetrics(days, endpoint);
17718
17777
  });
17719
17778
  app.get("/api/stats/model", async (request) => {
@@ -17722,14 +17781,14 @@ async function registerAdminRoutes(app) {
17722
17781
  const limitRaw = Number(query.limit ?? 10);
17723
17782
  const days = Number.isFinite(daysRaw) ? Math.max(1, Math.min(daysRaw, 90)) : 7;
17724
17783
  const limit = Number.isFinite(limitRaw) ? Math.max(1, Math.min(limitRaw, 50)) : 10;
17725
- const endpoint = isEndpoint(query.endpoint) ? query.endpoint : void 0;
17784
+ const endpoint = typeof query.endpoint === "string" && query.endpoint.length > 0 ? query.endpoint : void 0;
17726
17785
  return getModelUsageMetrics(days, limit, endpoint);
17727
17786
  });
17728
17787
  app.get("/api/stats/api-keys/overview", async (request) => {
17729
17788
  const query = request.query ?? {};
17730
17789
  const daysRaw = Number(query.days ?? 7);
17731
17790
  const rangeDays = Number.isFinite(daysRaw) ? Math.max(1, Math.min(daysRaw, 90)) : 7;
17732
- const endpoint = isEndpoint(query.endpoint) ? query.endpoint : void 0;
17791
+ const endpoint = typeof query.endpoint === "string" && query.endpoint.length > 0 ? query.endpoint : void 0;
17733
17792
  return getApiKeyOverviewMetrics(rangeDays, endpoint);
17734
17793
  });
17735
17794
  app.get("/api/stats/api-keys/usage", async (request) => {
@@ -17738,7 +17797,7 @@ async function registerAdminRoutes(app) {
17738
17797
  const limitRaw = Number(query.limit ?? 10);
17739
17798
  const days = Number.isFinite(daysRaw) ? Math.max(1, Math.min(daysRaw, 90)) : 7;
17740
17799
  const limit = Number.isFinite(limitRaw) ? Math.max(1, Math.min(limitRaw, 50)) : 10;
17741
- const endpoint = isEndpoint(query.endpoint) ? query.endpoint : void 0;
17800
+ const endpoint = typeof query.endpoint === "string" && query.endpoint.length > 0 ? query.endpoint : void 0;
17742
17801
  return getApiKeyUsageMetrics(days, limit, endpoint);
17743
17802
  });
17744
17803
  app.get("/api/keys", async () => {
@@ -18037,7 +18096,6 @@ async function registerAdminRoutes(app) {
18037
18096
  }
18038
18097
  });
18039
18098
  }
18040
- var isEndpoint = (value) => value === "anthropic" || value === "openai";
18041
18099
 
18042
18100
  // routes/events.ts
18043
18101
  async function registerEventsRoutes(app) {
@@ -18436,24 +18494,34 @@ async function handleAnthropicProtocol(request, reply, endpoint, endpointId, app
18436
18494
  const validationConfig = endpoint.routing?.validation ?? configSnapshot.endpointRouting?.anthropic?.validation;
18437
18495
  const validationMode = validationConfig?.mode ?? "off";
18438
18496
  const providerHeaders = {};
18439
- const headersToForward = [
18440
- "user-agent",
18441
- "anthropic-version",
18442
- "anthropic-beta",
18443
- "x-stainless-arch",
18444
- "x-stainless-async",
18445
- "x-stainless-lang",
18446
- "x-stainless-os",
18447
- "x-stainless-package-version",
18448
- "x-stainless-runtime",
18449
- "x-stainless-runtime-version"
18450
- ];
18451
- for (const key of headersToForward) {
18452
- const value = request.headers[key];
18453
- if (typeof value === "string" && value.length > 0) {
18454
- providerHeaders[key] = value;
18455
- } else if (Array.isArray(value) && value.length > 0 && typeof value[0] === "string") {
18456
- providerHeaders[key] = value[0];
18497
+ const excludedHeaders = /* @__PURE__ */ new Set([
18498
+ "host",
18499
+ "connection",
18500
+ "content-length",
18501
+ "transfer-encoding",
18502
+ "keep-alive",
18503
+ "upgrade",
18504
+ "proxy-connection",
18505
+ "proxy-authenticate",
18506
+ "proxy-authorization",
18507
+ "te",
18508
+ "trailer",
18509
+ "upgrade-insecure-requests",
18510
+ "authorization",
18511
+ "x-api-key",
18512
+ "content-type",
18513
+ "accept",
18514
+ "accept-encoding",
18515
+ "cookie",
18516
+ "referer"
18517
+ ]);
18518
+ for (const [key, rawValue] of Object.entries(request.headers)) {
18519
+ const lower = key.toLowerCase();
18520
+ if (excludedHeaders.has(lower))
18521
+ continue;
18522
+ const value = typeof rawValue === "string" ? rawValue : Array.isArray(rawValue) ? rawValue[0] : void 0;
18523
+ if (value && value.length > 0) {
18524
+ providerHeaders[lower] = value;
18457
18525
  }
18458
18526
  }
18459
18527
  const providedApiKey = extractApiKeyFromRequest2(request);
@@ -18906,24 +18974,34 @@ async function handleOpenAIChatProtocol(request, reply, endpoint, endpointId, ap
18906
18974
  querySuffix = request.querystring || null;
18907
18975
  }
18908
18976
  const providerHeaders = {};
18909
- const headersToForward = [
18910
- "user-agent",
18911
- "anthropic-version",
18912
- "anthropic-beta",
18913
- "x-stainless-arch",
18914
- "x-stainless-async",
18915
- "x-stainless-lang",
18916
- "x-stainless-os",
18917
- "x-stainless-package-version",
18918
- "x-stainless-runtime",
18919
- "x-stainless-runtime-version"
18920
- ];
18921
- for (const key of headersToForward) {
18922
- const value = request.headers[key];
18923
- if (typeof value === "string" && value.length > 0) {
18924
- providerHeaders[key] = value;
18925
- } else if (Array.isArray(value) && value.length > 0 && typeof value[0] === "string") {
18926
- providerHeaders[key] = value[0];
18977
+ const excludedHeaders = /* @__PURE__ */ new Set([
18978
+ "host",
18979
+ "connection",
18980
+ "content-length",
18981
+ "transfer-encoding",
18982
+ "keep-alive",
18983
+ "upgrade",
18984
+ "proxy-connection",
18985
+ "proxy-authenticate",
18986
+ "proxy-authorization",
18987
+ "te",
18988
+ "trailer",
18989
+ "upgrade-insecure-requests",
18990
+ "authorization",
18991
+ "x-api-key",
18992
+ "content-type",
18993
+ "accept",
18994
+ "accept-encoding",
18995
+ "cookie",
18996
+ "referer"
18997
+ ]);
18998
+ for (const [key, rawValue] of Object.entries(request.headers)) {
18999
+ const lower = key.toLowerCase();
19000
+ if (excludedHeaders.has(lower))
19001
+ continue;
19002
+ const value = typeof rawValue === "string" ? rawValue : Array.isArray(rawValue) ? rawValue[0] : void 0;
19003
+ if (value && value.length > 0) {
19004
+ providerHeaders[lower] = value;
18927
19005
  }
18928
19006
  }
18929
19007
  const providedApiKey = extractApiKeyFromRequest2(request);
@@ -19260,24 +19338,34 @@ async function handleOpenAIResponsesProtocol(request, reply, endpoint, endpointI
19260
19338
  querySuffix = request.querystring || null;
19261
19339
  }
19262
19340
  const providerHeaders = {};
19263
- const headersToForward = [
19264
- "user-agent",
19265
- "anthropic-version",
19266
- "anthropic-beta",
19267
- "x-stainless-arch",
19268
- "x-stainless-async",
19269
- "x-stainless-lang",
19270
- "x-stainless-os",
19271
- "x-stainless-package-version",
19272
- "x-stainless-runtime",
19273
- "x-stainless-runtime-version"
19274
- ];
19275
- for (const key of headersToForward) {
19276
- const value = request.headers[key];
19277
- if (typeof value === "string" && value.length > 0) {
19278
- providerHeaders[key] = value;
19279
- } else if (Array.isArray(value) && value.length > 0 && typeof value[0] === "string") {
19280
- providerHeaders[key] = value[0];
19341
+ const excludedHeaders = /* @__PURE__ */ new Set([
19342
+ "host",
19343
+ "connection",
19344
+ "content-length",
19345
+ "transfer-encoding",
19346
+ "keep-alive",
19347
+ "upgrade",
19348
+ "proxy-connection",
19349
+ "proxy-authenticate",
19350
+ "proxy-authorization",
19351
+ "te",
19352
+ "trailer",
19353
+ "upgrade-insecure-requests",
19354
+ "authorization",
19355
+ "x-api-key",
19356
+ "content-type",
19357
+ "accept",
19358
+ "accept-encoding",
19359
+ "cookie",
19360
+ "referer"
19361
+ ]);
19362
+ for (const [key, rawValue] of Object.entries(request.headers)) {
19363
+ const lower = key.toLowerCase();
19364
+ if (excludedHeaders.has(lower))
19365
+ continue;
19366
+ const value = typeof rawValue === "string" ? rawValue : Array.isArray(rawValue) ? rawValue[0] : void 0;
19367
+ if (value && value.length > 0) {
19368
+ providerHeaders[lower] = value;
19281
19369
  }
19282
19370
  }
19283
19371
  const providedApiKey = extractApiKeyFromRequest2(request);
@@ -0,0 +1,6 @@
1
+ import{c as j,u as g,b as v,r as i,j as e,e as d,a5 as N}from"./index-CeV0AE1d.js";import{u as y}from"./useApiQuery-B_olnrT7.js";import{P as E}from"./PageHeader-Bk56T-yb.js";import{P as n}from"./PageSection-Dq0ilNBn.js";import{C as m,a as p}from"./card-D5d6AfHr.js";import{I}from"./info-B9sQLv7T.js";import{R as T}from"./refresh-cw-DkrQh2bG.js";/**
2
+ * @license lucide-react v0.344.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const k=j("Sparkles",[["path",{d:"m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z",key:"17u4zn"}],["path",{d:"M5 3v4",key:"bklmnn"}],["path",{d:"M19 17v4",key:"iiml17"}],["path",{d:"M3 5h4",key:"nem4j1"}],["path",{d:"M17 19h4",key:"lbex7p"}]]),_="0.7.13",w={version:_},L={VITE_BUILD_TIME:"2025-12-15T03:50:43.077Z",VITE_NODE_VERSION:"v22.16.0"};function u({items:t}){return t.length===0?null:e.jsx("dl",{className:"grid gap-4 sm:grid-cols-2",children:t.map(a=>e.jsx(m,{children:e.jsxs(p,{className:"pt-4",children:[e.jsx("dt",{className:"text-xs font-medium uppercase tracking-wide text-muted-foreground",children:a.label}),e.jsx("dd",{className:"mt-1 text-sm font-semibold",children:a.value}),a.hint&&e.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:a.hint})]})},a.label))})}function D(){const{t}=g(),{pushToast:a}=v(),s=y(["status","gateway"],{url:"/api/status",method:"GET"},{staleTime:6e4});i.useEffect(()=>{s.isError&&s.error&&a({title:t("about.toast.statusError.title"),description:s.error.message,variant:"error"})},[s.isError,s.error,a,t]);const o=w.version,r=i.useMemo(()=>{const c=L,b=c.VITE_BUILD_TIME,f=c.VITE_NODE_VERSION;return{buildTime:b,nodeVersion:f}},[]),x=i.useMemo(()=>[{label:t("about.app.labels.name"),value:e.jsx("span",{className:"font-mono",children:"cc-gw"})},{label:t("about.app.labels.version"),value:e.jsxs("span",{className:"font-mono text-primary",children:["v",o]})},{label:t("about.app.labels.buildTime"),value:r.buildTime,hint:t("about.app.hint.buildTime")},{label:t("about.app.labels.node"),value:e.jsx("span",{className:"font-mono",children:r.nodeVersion})}],[o,r.buildTime,r.nodeVersion,t]),l=i.useMemo(()=>s.data?[{label:t("about.status.labels.host"),value:s.data.host??"127.0.0.1"},{label:t("about.status.labels.port"),value:s.data.port.toLocaleString()},{label:t("about.status.labels.providers"),value:s.data.providers.toLocaleString()},{label:t("about.status.labels.active"),value:(s.data.activeRequests??0).toLocaleString(),hint:t("about.status.hint.active")}]:[],[s.data,t]),h=()=>{a({title:t("about.toast.updatesPlanned"),variant:"info"})};return e.jsxs("div",{className:"space-y-6",children:[e.jsx(E,{icon:e.jsx(I,{className:"h-5 w-5","aria-hidden":"true"}),title:t("about.title"),description:t("about.description"),badge:`v${o}`,actions:e.jsxs(d,{onClick:h,children:[e.jsx(k,{className:"mr-2 h-4 w-4","aria-hidden":"true"}),t("about.support.actions.checkUpdates")]})}),e.jsxs("div",{className:"grid gap-6 lg:grid-cols-2",children:[e.jsx(n,{title:t("about.app.title"),description:t("about.app.subtitle"),children:e.jsx(u,{items:x})}),e.jsx(n,{title:t("about.status.title"),description:t("about.status.subtitle"),actions:e.jsxs(d,{variant:"outline",size:"sm",onClick:()=>s.refetch(),disabled:s.isFetching,children:[e.jsx(T,{className:`mr-2 h-4 w-4 ${s.isFetching?"animate-spin":""}`,"aria-hidden":"true"}),s.isFetching?t("common.actions.refreshing"):t("common.actions.refresh")]}),children:s.isLoading?e.jsxs("div",{className:"flex h-32 flex-col items-center justify-center gap-2 text-center",children:[e.jsx("div",{className:"h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:t("about.status.loading")})]}):l.length>0?e.jsx(u,{items:l}):e.jsxs("div",{className:"flex h-32 flex-col items-center justify-center gap-1 rounded-lg border border-dashed p-6 text-center",children:[e.jsx("p",{className:"text-sm font-medium",children:t("about.status.empty")}),e.jsx("p",{className:"text-xs text-muted-foreground",children:t("common.actions.refresh")})]})})]}),e.jsx(n,{title:t("about.support.title"),description:e.jsxs("span",{className:"space-y-1",children:[e.jsx("span",{className:"block text-sm font-medium text-primary",children:t("about.support.subtitle")}),e.jsx("span",{children:t("about.support.description")})]}),children:e.jsx(m,{children:e.jsxs(p,{className:"flex flex-col gap-4 pt-4",children:[e.jsxs("div",{className:"flex flex-wrap items-start gap-4",children:[e.jsx("div",{className:"flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10 text-primary",children:e.jsx(N,{className:"h-5 w-5","aria-hidden":"true"})}),e.jsx("p",{className:"flex-1 text-sm text-muted-foreground",children:t("about.support.tip")})]}),e.jsx("code",{className:"inline-flex self-start rounded-md bg-muted px-3 py-1.5 text-xs font-medium",children:"~/.cc-gw/config.json"})]})})})]})}export{D as default};
@@ -1,4 +1,4 @@
1
- import{c as D,r as c,j as e,a as $,u as Z,b as de,L as pe,e as o,K as me,v as ue,d as K}from"./index-D_Dbqo2u.js";import{E as ye}from"./index-CJAz7pOx.js";import{u as w}from"./useApiQuery-ByGFZwHE.js";import{P as xe,B as q}from"./PageHeader-BeW-Othf.js";import{P as z}from"./PageSection-DW84HFxm.js";import{c as he}from"./clipboard-CALi6bTW.js";import{I as ge}from"./input-Ckx5qHOQ.js";import{L as I}from"./label-D2cIIMBu.js";import{C as T,a as S}from"./card-DO6ly30k.js";import{P as fe,D as W,a as H,b as V,c as G,d as je,e as Q}from"./dialog-BTot8EYU.js";import{C as U}from"./copy-CSLiPZ3j.js";/**
1
+ import{c as D,r as c,j as e,a as $,u as Z,b as de,L as pe,e as o,K as me,v as ue,d as K}from"./index-CeV0AE1d.js";import{E as ye}from"./index-lin6BsX0.js";import{u as w}from"./useApiQuery-B_olnrT7.js";import{P as xe,B as q}from"./PageHeader-Bk56T-yb.js";import{P as z}from"./PageSection-Dq0ilNBn.js";import{c as he}from"./clipboard-CALi6bTW.js";import{I as ge}from"./input-DcSN-8OE.js";import{L as I}from"./label-C2a8bqtE.js";import{C as T,a as S}from"./card-D5d6AfHr.js";import{P as fe,D as W,a as H,b as V,c as G,d as je,e as Q}from"./dialog-DeP8kdI-.js";import{C as U}from"./copy-BLEqa17V.js";/**
2
2
  * @license lucide-react v0.344.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -0,0 +1,16 @@
1
+ import{c as O,r as d,j as e,a as f,u as I,b as ne,d as ie,t as le,L as ce,B as D,e as me}from"./index-CeV0AE1d.js";import{E as he}from"./index-lin6BsX0.js";import{P as ue,B as k}from"./PageHeader-Bk56T-yb.js";import{P as X}from"./PageSection-Dq0ilNBn.js";import{u as S}from"./useApiQuery-B_olnrT7.js";import{C as G,a as Q}from"./card-D5d6AfHr.js";import{S as xe,a as pe,b as be,c as ge,d as q}from"./select-H2zEksk5.js";/**
2
+ * @license lucide-react v0.344.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const $=O("Activity",[["path",{d:"M22 12h-4l-3 9L9 3l-3 9H2",key:"d5dnw9"}]]);/**
7
+ * @license lucide-react v0.344.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */const fe=O("Timer",[["line",{x1:"10",x2:"14",y1:"2",y2:"2",key:"14vaq8"}],["line",{x1:"12",x2:"15",y1:"14",y2:"11",key:"17fdiu"}],["circle",{cx:"12",cy:"14",r:"8",key:"1e1u0o"}]]);/**
12
+ * @license lucide-react v0.344.0 - ISC
13
+ *
14
+ * This source code is licensed under the ISC license.
15
+ * See the LICENSE file in the root directory of this source tree.
16
+ */const ye=O("TrendingUp",[["polyline",{points:"22 7 13.5 15.5 8.5 10.5 2 17",key:"126l90"}],["polyline",{points:"16 7 22 7 22 13",key:"kwv8wd"}]]),F=d.forwardRef(({className:t,...s},a)=>e.jsx("div",{className:"relative w-full overflow-auto rounded-lg",children:e.jsx("table",{ref:a,className:f("w-full caption-bottom text-sm border-collapse",t),...s})}));F.displayName="Table";const H=d.forwardRef(({className:t,...s},a)=>e.jsx("thead",{ref:a,className:f("bg-muted/40 [&_tr]:border-b [&_tr]:border-border/60",t),...s}));H.displayName="TableHeader";const _=d.forwardRef(({className:t,...s},a)=>e.jsx("tbody",{ref:a,className:f("[&_tr:last-child]:border-0",t),...s}));_.displayName="TableBody";const je=d.forwardRef(({className:t,...s},a)=>e.jsx("tfoot",{ref:a,className:f("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",t),...s}));je.displayName="TableFooter";const A=d.forwardRef(({className:t,...s},a)=>e.jsx("tr",{ref:a,className:f("border-b border-border/50 transition-all duration-150","hover:bg-primary/5 data-[state=selected]:bg-primary/10","group",t),...s}));A.displayName="TableRow";const h=d.forwardRef(({className:t,...s},a)=>e.jsx("th",{ref:a,className:f("h-11 px-4 text-left align-middle text-xs font-semibold uppercase tracking-wider text-muted-foreground/80","[&:has([role=checkbox])]:pr-0",t),...s}));h.displayName="TableHead";const u=d.forwardRef(({className:t,...s},a)=>e.jsx("td",{ref:a,className:f("px-4 py-3 align-middle text-sm","[&:has([role=checkbox])]:pr-0","group-hover:text-foreground transition-colors",t),...s}));u.displayName="TableCell";const ve=d.forwardRef(({className:t,...s},a)=>e.jsx("caption",{ref:a,className:f("mt-4 text-sm text-muted-foreground",t),...s}));ve.displayName="TableCaption";function P(t,s,a){return t==null?"-":`${t.toLocaleString(void 0,a)} ${s}`}function W(t){if(t==null)return"-";if(t<1024)return`${t} B`;const s=["KB","MB","GB","TB"];let a=t/1024,r=0;for(;a>=1024&&r<s.length-1;)a/=1024,r+=1;return`${a.toFixed(a>=100?0:a>=10?1:2)} ${s[r]}`}function Ae(){var U,V,K;const{t}=I(),{pushToast:s}=ne(),[a,r]=d.useState("all"),[i,y]=d.useState(!1),x=a==="all"?void 0:a,Y=S(["custom-endpoints"],{url:"/api/custom-endpoints",method:"GET"}),N=S(["stats","overview",a],{url:"/api/stats/overview",method:"GET",params:x?{endpoint:x}:void 0}),T=S(["stats","daily",14,a],{url:"/api/stats/daily",method:"GET",params:{days:14,...x?{endpoint:x}:{}}}),g=S(["stats","model",7,6,a],{url:"/api/stats/model",method:"GET",params:{days:7,limit:6,...x?{endpoint:x}:{}}}),E=S(["status"],{url:"/api/status",method:"GET"}),j=S(["db","info"],{url:"/api/db/info",method:"GET"}),z=j.refetch??(async()=>{}),C=S(["logs","recent",a],{url:"/api/logs",method:"GET",params:{limit:5,...x?{endpoint:x}:{}}},{refetchInterval:3e4});d.useEffect(()=>{N.isError&&N.error&&s({title:t("dashboard.toast.overviewError"),description:N.error.message,variant:"error"})},[N.isError,N.error,s,t]),d.useEffect(()=>{T.isError&&T.error&&s({title:t("dashboard.toast.dailyError"),description:T.error.message,variant:"error"})},[T.isError,T.error,s,t]),d.useEffect(()=>{g.isError&&g.error&&s({title:t("dashboard.toast.modelError"),description:g.error.message,variant:"error"})},[g.isError,g.error,s,t]),d.useEffect(()=>{E.isError&&E.error&&s({title:t("dashboard.toast.statusError"),description:E.error.message,variant:"error"})},[E.isError,E.error,s,t]),d.useEffect(()=>{j.isError&&j.error&&s({title:t("dashboard.toast.dbError"),description:j.error.message,variant:"error"})},[j.isError,j.error,s,t]);const Z=d.useCallback(async()=>{if(!i){y(!0);try{await ie.post("/api/db/compact"),await z(),s({title:t("dashboard.toast.compactSuccess.title"),description:t("dashboard.toast.compactSuccess.desc"),variant:"success"})}catch(n){const m=le(n);s({title:t("dashboard.toast.compactError.title"),description:m.message,variant:"error"})}finally{y(!1)}}},[i,s,z,t]);d.useEffect(()=>{C.isError&&C.error&&s({title:t("dashboard.toast.recentError"),description:C.error.message,variant:"error"})},[C.isError,C.error,s,t]);const o=N.data,v=T.data??[],l=g.data??[],L=E.data,R=j.data,ee=((U=C.data)==null?void 0:U.items)??[],te=R?W(R.totalBytes??R.sizeBytes):"-",ae=R?W(R.memoryRssBytes??0):"-",se=d.useMemo(()=>{const n=v.map(b=>b.date),m=t("dashboard.charts.barRequests"),c=t("dashboard.charts.lineInput"),B=t("dashboard.charts.lineOutput"),p=t("dashboard.charts.lineCacheRead"),J=t("dashboard.charts.lineCacheCreation");return{tooltip:{trigger:"axis"},legend:{data:[m,c,B,p,J]},grid:{left:60,right:40,top:60,bottom:60},xAxis:{type:"category",data:n},yAxis:{type:"value"},series:[{name:m,type:"bar",data:v.map(b=>b.requestCount),itemStyle:{color:"hsl(var(--primary))",borderRadius:[4,4,0,0]}},{name:c,type:"line",data:v.map(b=>b.inputTokens),smooth:!0,itemStyle:{color:"#10b981"},lineStyle:{width:2}},{name:B,type:"line",data:v.map(b=>b.outputTokens),smooth:!0,itemStyle:{color:"#f59e0b"},lineStyle:{width:2}},{name:p,type:"line",data:v.map(b=>b.cacheReadTokens),smooth:!0,itemStyle:{color:"#8b5cf6"},lineStyle:{width:2}},{name:J,type:"line",data:v.map(b=>b.cacheCreationTokens),smooth:!0,itemStyle:{color:"#ec4899"},lineStyle:{width:2}}]}},[v,t]),re=d.useMemo(()=>{const n=l.map(p=>`${p.provider}/${p.model}`),m=t("dashboard.charts.barRequests"),c=t("dashboard.charts.lineInput"),B=t("dashboard.charts.lineOutput");return{tooltip:{trigger:"axis"},legend:{data:[m,c,B]},grid:{left:80,right:60,top:60,bottom:100},xAxis:{type:"category",data:n,axisLabel:{rotate:30}},yAxis:[{type:"value",name:m},{type:"value",name:t("dashboard.charts.axisTokens"),position:"right"}],series:[{name:m,type:"bar",data:l.map(p=>p.requests),itemStyle:{color:"#6366f1",borderRadius:[4,4,0,0]}},{name:c,type:"line",yAxisIndex:1,smooth:!0,data:l.map(p=>p.inputTokens??0),itemStyle:{color:"#10b981"}},{name:B,type:"line",yAxisIndex:1,smooth:!0,data:l.map(p=>p.outputTokens??0),itemStyle:{color:"#f59e0b"}}]}},[l,t]),oe=d.useMemo(()=>{const n=l.map(c=>`${c.provider}/${c.model}`),m=t("dashboard.charts.ttftLabel");return{tooltip:{trigger:"axis"},grid:{left:80,right:50,top:60,bottom:100},xAxis:{type:"category",data:n,axisLabel:{rotate:30}},yAxis:{type:"value",name:t("dashboard.charts.ttftAxis")},series:[{name:m,type:"bar",data:l.map(c=>c.avgTtftMs??0),itemStyle:{color:"hsl(var(--primary))",borderRadius:[4,4,0,0]}}]}},[l,t]),de=d.useMemo(()=>{const n=l.map(c=>`${c.provider}/${c.model}`),m=t("dashboard.charts.tpotLabel");return{tooltip:{trigger:"axis"},grid:{left:80,right:50,top:60,bottom:100},xAxis:{type:"category",data:n,axisLabel:{rotate:30}},yAxis:{type:"value",name:t("dashboard.charts.tpotAxis")},series:[{name:m,type:"bar",data:l.map(c=>c.avgTpotMs??0),itemStyle:{color:"#f59e0b",borderRadius:[4,4,0,0]}}]}},[l,t]);return N.isPending||E.isPending||j.isPending?e.jsx(ce,{}):e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(ue,{icon:e.jsx(D,{className:"h-5 w-5","aria-hidden":"true"}),title:t("nav.dashboard"),description:t("dashboard.description"),actions:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-xs font-medium text-muted-foreground",children:t("dashboard.filters.endpoint")}),e.jsxs(xe,{value:a,onValueChange:r,children:[e.jsx(pe,{className:"w-[140px]",children:e.jsx(be,{})}),e.jsxs(ge,{children:[e.jsx(q,{value:"all",children:t("dashboard.filters.endpointAll")}),e.jsx(q,{value:"anthropic",children:t("dashboard.filters.endpointAnthropic")}),e.jsx(q,{value:"openai",children:t("dashboard.filters.endpointOpenAI")}),(K=(V=Y.data)==null?void 0:V.endpoints)==null?void 0:K.map(n=>e.jsx(q,{value:n.id,children:n.label||n.id},n.id))]})]})]})}),L&&e.jsx(G,{children:e.jsxs(Q,{className:"flex flex-wrap items-center gap-3 pt-4",children:[e.jsx(k,{variant:"default",className:"bg-emerald-500",children:t("dashboard.status.listening",{host:L.host??"0.0.0.0",port:L.port})}),e.jsx(k,{variant:"secondary",children:t("dashboard.status.providers",{value:L.providers.toLocaleString()})}),e.jsx(k,{variant:"secondary",children:t("dashboard.status.todayRequests",{value:((o==null?void 0:o.today.requests)??0).toLocaleString()})}),e.jsx(k,{variant:"outline",children:t("dashboard.status.active",{value:(L.activeRequests??0).toLocaleString()})}),e.jsx(k,{variant:"outline",children:t("dashboard.status.dbSize",{value:te})}),e.jsx(k,{variant:"outline",children:t("dashboard.status.memory",{value:ae})}),e.jsx(me,{variant:"outline",size:"sm",onClick:Z,disabled:i,children:t(i?"dashboard.actions.compacting":"dashboard.actions.compact")})]})}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2 xl:grid-cols-3",children:[e.jsx(w,{icon:e.jsx($,{className:"h-5 w-5"}),title:t("dashboard.cards.todayRequests"),value:(o==null?void 0:o.today.requests)??0,suffix:t("common.units.request"),color:"blue"}),e.jsx(w,{icon:e.jsx(ye,{className:"h-5 w-5"}),title:t("dashboard.cards.todayInput"),value:(o==null?void 0:o.today.inputTokens)??0,suffix:t("common.units.token"),color:"emerald"}),e.jsx(w,{icon:e.jsx($,{className:"h-5 w-5"}),title:t("dashboard.cards.todayCacheRead"),value:(o==null?void 0:o.today.cacheReadTokens)??0,suffix:t("common.units.token"),color:"violet"}),e.jsx(w,{icon:e.jsx($,{className:"h-5 w-5"}),title:t("dashboard.cards.todayCacheCreation"),value:(o==null?void 0:o.today.cacheCreationTokens)??0,suffix:t("common.units.token"),color:"rose"}),e.jsx(w,{icon:e.jsx(D,{className:"h-5 w-5"}),title:t("dashboard.cards.todayOutput"),value:(o==null?void 0:o.today.outputTokens)??0,suffix:t("common.units.token"),color:"amber"}),e.jsx(w,{icon:e.jsx(fe,{className:"h-5 w-5"}),title:t("dashboard.cards.avgLatency"),value:(o==null?void 0:o.today.avgLatencyMs)??0,suffix:t("common.units.ms"),color:"cyan"})]}),e.jsxs("div",{className:"grid gap-6 lg:grid-cols-2",children:[e.jsx(M,{title:t("dashboard.charts.requestsTitle"),description:t("dashboard.charts.requestsDesc"),loading:T.isPending,option:se,empty:!v.length,emptyText:t("dashboard.charts.empty")}),e.jsx(M,{title:t("dashboard.charts.modelTitle"),description:t("dashboard.charts.modelDesc"),loading:g.isPending,option:re,empty:!l.length,emptyText:t("dashboard.charts.empty")})]}),e.jsxs("div",{className:"grid gap-6 lg:grid-cols-2",children:[e.jsx(M,{title:t("dashboard.charts.ttftTitle"),description:t("dashboard.charts.ttftDesc"),loading:g.isPending,option:oe,empty:!l.some(n=>n.avgTtftMs!=null&&n.avgTtftMs>0),emptyText:t("dashboard.charts.ttftEmpty")}),e.jsx(M,{title:t("dashboard.charts.tpotTitle"),description:t("dashboard.charts.tpotDesc"),loading:g.isPending,option:de,empty:!l.some(n=>n.avgTpotMs!=null&&n.avgTpotMs>0),emptyText:t("dashboard.charts.tpotEmpty")})]}),e.jsx(Te,{models:l,loading:g.isPending}),e.jsx(Ee,{loading:C.isPending,records:ee})]})}const Ne={blue:{gradient:"bg-gradient-to-br from-blue-500/10 via-blue-500/5 to-transparent",iconBg:"bg-blue-500/15",iconColor:"text-blue-600 dark:text-blue-400"},emerald:{gradient:"bg-gradient-to-br from-emerald-500/10 via-emerald-500/5 to-transparent",iconBg:"bg-emerald-500/15",iconColor:"text-emerald-600 dark:text-emerald-400"},amber:{gradient:"bg-gradient-to-br from-amber-500/10 via-amber-500/5 to-transparent",iconBg:"bg-amber-500/15",iconColor:"text-amber-600 dark:text-amber-400"},violet:{gradient:"bg-gradient-to-br from-violet-500/10 via-violet-500/5 to-transparent",iconBg:"bg-violet-500/15",iconColor:"text-violet-600 dark:text-violet-400"},rose:{gradient:"bg-gradient-to-br from-rose-500/10 via-rose-500/5 to-transparent",iconBg:"bg-rose-500/15",iconColor:"text-rose-600 dark:text-rose-400"},cyan:{gradient:"bg-gradient-to-br from-cyan-500/10 via-cyan-500/5 to-transparent",iconBg:"bg-cyan-500/15",iconColor:"text-cyan-600 dark:text-cyan-400"}};function w({icon:t,title:s,value:a,suffix:r,color:i="blue"}){const y=Ne[i];return e.jsx(G,{variant:"interactive",className:f("overflow-hidden",y.gradient),children:e.jsxs(Q,{className:"pt-5",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("span",{className:"text-xs font-semibold uppercase tracking-wider text-muted-foreground",children:s}),t&&e.jsx("div",{className:f("flex h-10 w-10 items-center justify-center rounded-xl",y.iconBg,y.iconColor),children:t})]}),e.jsxs("p",{className:"text-3xl font-bold tracking-tight",children:[a.toLocaleString(),r&&e.jsx("span",{className:"ml-1.5 text-sm font-medium text-muted-foreground",children:r})]})]})})}function M({title:t,description:s,option:a,loading:r,empty:i,emptyText:y}){const{t:x}=I();return e.jsx(G,{children:e.jsxs(Q,{className:"space-y-4 pt-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-base font-semibold",children:t}),e.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:s})]}),r?e.jsx("div",{className:"flex h-[320px] items-center justify-center",children:e.jsx("span",{className:"text-sm text-muted-foreground",children:x("common.loadingShort")})}):i?e.jsxs("div",{className:"flex h-[320px] flex-col items-center justify-center rounded-lg border border-dashed",children:[e.jsx(D,{className:"mb-2 h-10 w-10 text-muted-foreground/50"}),e.jsx("span",{className:"text-sm text-muted-foreground",children:y??x("dashboard.charts.empty")})]}):e.jsx(he,{option:a,style:{height:320},notMerge:!0,lazyUpdate:!0})]})})}function Te({models:t,loading:s}){const{t:a}=I(),r=t.length>0;return e.jsx(X,{title:a("dashboard.modelTable.title"),description:a("dashboard.modelTable.description"),children:s?e.jsx("div",{className:"flex h-32 items-center justify-center",children:e.jsx("span",{className:"text-sm text-muted-foreground",children:a("common.loadingShort")})}):r?e.jsx("div",{className:"max-h-80 overflow-auto rounded-md border",children:e.jsxs(F,{children:[e.jsx(H,{children:e.jsxs(A,{children:[e.jsx(h,{children:a("dashboard.modelTable.columns.model")}),e.jsx(h,{className:"text-right",children:a("dashboard.modelTable.columns.requests")}),e.jsx(h,{className:"text-right",children:a("dashboard.modelTable.columns.latency")}),e.jsx(h,{className:"text-right",children:a("dashboard.modelTable.columns.ttft")}),e.jsx(h,{className:"text-right",children:a("dashboard.modelTable.columns.tpot")})]})}),e.jsx(_,{children:t.map(i=>e.jsxs(A,{children:[e.jsx(u,{children:e.jsxs("div",{className:"flex flex-col",children:[e.jsx("span",{className:"font-medium",children:i.provider}),e.jsx("span",{className:"text-xs text-muted-foreground",children:i.model})]})}),e.jsx(u,{className:"text-right font-medium",children:i.requests.toLocaleString()}),e.jsx(u,{className:"text-right",children:P(i.avgLatencyMs,a("common.units.ms"))}),e.jsx(u,{className:"text-right",children:P(i.avgTtftMs,a("common.units.ms"))}),e.jsx(u,{className:"text-right",children:P(i.avgTpotMs,a("common.units.msPerToken"),{maximumFractionDigits:2})})]},`${i.provider}/${i.model}`))})]})}):e.jsx("div",{className:"flex h-32 items-center justify-center rounded-lg border border-dashed",children:e.jsx("span",{className:"text-sm text-muted-foreground",children:a("dashboard.modelTable.empty")})})})}function Ee({records:t,loading:s}){const{t:a}=I();return e.jsx(X,{title:a("dashboard.recent.title"),description:a("dashboard.recent.subtitle",{count:5}),children:s?e.jsx("div",{className:"flex h-32 items-center justify-center",children:e.jsx("span",{className:"text-sm text-muted-foreground",children:a("dashboard.recent.loading")})}):t.length===0?e.jsx("div",{className:"flex h-32 items-center justify-center rounded-lg border border-dashed",children:e.jsx("span",{className:"text-sm text-muted-foreground",children:a("dashboard.recent.empty")})}):e.jsx("div",{className:"max-h-80 overflow-auto rounded-md border",children:e.jsxs(F,{children:[e.jsx(H,{children:e.jsxs(A,{children:[e.jsx(h,{children:a("dashboard.recent.columns.time")}),e.jsx(h,{children:a("dashboard.recent.columns.endpoint")}),e.jsx(h,{children:a("dashboard.recent.columns.provider")}),e.jsx(h,{children:a("dashboard.recent.columns.route")}),e.jsx(h,{className:"text-right",children:a("dashboard.recent.columns.latency")}),e.jsx(h,{children:a("dashboard.recent.columns.status")})]})}),e.jsx(_,{children:t.map(r=>e.jsxs(A,{children:[e.jsx(u,{className:"text-xs",children:new Date(r.timestamp).toLocaleString()}),e.jsx(u,{className:"text-xs text-muted-foreground",children:r.endpoint==="anthropic"?a("logs.table.endpointAnthropic"):r.endpoint==="openai"?a("logs.table.endpointOpenAI"):r.endpoint}),e.jsx(u,{className:"font-medium",children:r.provider}),e.jsx(u,{children:e.jsxs("div",{className:"flex items-center gap-1 text-xs text-muted-foreground",children:[e.jsx("span",{children:r.client_model??a("dashboard.recent.routePlaceholder")}),e.jsx("span",{children:"→"}),e.jsx("span",{className:"font-medium text-foreground",children:r.model})]})}),e.jsx(u,{className:"text-right font-medium",children:P(r.latency_ms,a("common.units.ms"))}),e.jsx(u,{children:e.jsx(k,{variant:r.error?"destructive":"default",children:(r.status_code??(r.error?500:200)).toString()})})]},r.id))})]})})})}export{Ae as default};
@@ -1,4 +1,4 @@
1
- import{c as N,u as E,b as L,r as i,j as e,e as h,C as R,a as $,g as I,h as T,t as P}from"./index-D_Dbqo2u.js";import{P as z,B as j}from"./PageHeader-BeW-Othf.js";import{I as F}from"./input-Ckx5qHOQ.js";import{C as w,a as C,b as V}from"./card-DO6ly30k.js";import{S as B,a as D,b as K,c as H,d as f}from"./select-CMGw70tW.js";import{R as J}from"./refresh-cw-C-S3w6yD.js";/**
1
+ import{c as N,u as E,b as L,r as i,j as e,e as h,C as R,a as $,g as I,h as T,t as P}from"./index-CeV0AE1d.js";import{P as z,B as j}from"./PageHeader-Bk56T-yb.js";import{I as F}from"./input-DcSN-8OE.js";import{C as w,a as C,b as V}from"./card-D5d6AfHr.js";import{S as B,a as D,b as K,c as H,d as f}from"./select-H2zEksk5.js";import{R as J}from"./refresh-cw-DkrQh2bG.js";/**
2
2
  * @license lucide-react v0.344.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as x,u,r as g,j as e,e as h}from"./index-D_Dbqo2u.js";import{P as N}from"./PageHeader-BeW-Othf.js";import{P as d}from"./PageSection-DW84HFxm.js";import{c as p}from"./clipboard-CALi6bTW.js";import{C as j,a as f}from"./card-DO6ly30k.js";import{I as v}from"./info-XoeNrG0H.js";/**
1
+ import{c as x,u,r as g,j as e,e as h}from"./index-CeV0AE1d.js";import{P as N}from"./PageHeader-Bk56T-yb.js";import{P as d}from"./PageSection-Dq0ilNBn.js";import{c as p}from"./clipboard-CALi6bTW.js";import{C as j,a as f}from"./card-D5d6AfHr.js";import{I as v}from"./info-B9sQLv7T.js";/**
2
2
  * @license lucide-react v0.344.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{u as C,ai as E,aj as F,ak as L,r as n,j as e,L as S,e as k}from"./index-D_Dbqo2u.js";import{I as j}from"./input-Ckx5qHOQ.js";import{L as b}from"./label-D2cIIMBu.js";import{C as v,a as w,b as P,c as T,d as A,e as D}from"./card-DO6ly30k.js";function H(){const{t:s}=C(),i=E(),u=F(),{authEnabled:l,isAuthenticated:m,loading:o,login:N,error:x}=L(),[t,f]=n.useState({username:"",password:""}),[p,d]=n.useState(null),[h,g]=n.useState(!1),c=n.useMemo(()=>{var r;const a=u.state;return((r=a==null?void 0:a.from)==null?void 0:r.pathname)??"/"},[u.state]);n.useEffect(()=>{if(!l&&!o){i(c,{replace:!0});return}l&&m&&!o&&i(c,{replace:!0})},[l,m,o,i,c]);const y=async a=>{if(a.preventDefault(),d(null),!t.username.trim()||!t.password){d(s("login.validation.required"));return}g(!0);try{await N(t.username.trim(),t.password),i(c,{replace:!0})}catch(r){d(r instanceof Error?r.message:s("login.validation.failed"))}finally{g(!1)}};return o?e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-background",children:e.jsx(v,{className:"w-full max-w-md",children:e.jsx(w,{className:"flex min-h-[320px] items-center justify-center",children:e.jsx(S,{})})})}):l?e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-background px-4",children:e.jsxs(v,{className:"w-full max-w-md",children:[e.jsxs(P,{className:"text-center",children:[e.jsx("div",{className:"mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-xl bg-primary text-lg font-bold text-primary-foreground",children:"GW"}),e.jsx(T,{className:"text-2xl",children:s("login.title")}),e.jsx(A,{className:"text-sm",children:s("login.description")})]}),e.jsx(w,{children:e.jsxs("form",{className:"space-y-4",onSubmit:y,children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(b,{htmlFor:"username",children:s("login.fields.username")}),e.jsx(j,{id:"username",value:t.username,autoComplete:"username",autoFocus:!0,onChange:a=>f(r=>({...r,username:a.target.value})),placeholder:s("login.fields.usernamePlaceholder")})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(b,{htmlFor:"password",children:s("login.fields.password")}),e.jsx(j,{id:"password",type:"password",value:t.password,autoComplete:"current-password",onChange:a=>f(r=>({...r,password:a.target.value})),placeholder:s("login.fields.passwordPlaceholder")})]}),(p||x)&&e.jsx("div",{className:"rounded-md border border-destructive/50 bg-destructive/10 px-4 py-3 text-sm text-destructive",children:p||x}),e.jsx(k,{type:"submit",className:"w-full",disabled:h,children:s(h?"common.actions.loading":"login.actions.submit")})]})}),e.jsx(D,{className:"justify-center",children:e.jsx("p",{className:"text-center text-xs text-muted-foreground",children:s("login.hint")})})]})}):null}export{H as default};
1
+ import{u as C,ai as E,aj as F,ak as L,r as n,j as e,L as S,e as k}from"./index-CeV0AE1d.js";import{I as j}from"./input-DcSN-8OE.js";import{L as b}from"./label-C2a8bqtE.js";import{C as v,a as w,b as P,c as T,d as A,e as D}from"./card-D5d6AfHr.js";function H(){const{t:s}=C(),i=E(),u=F(),{authEnabled:l,isAuthenticated:m,loading:o,login:N,error:x}=L(),[t,f]=n.useState({username:"",password:""}),[p,d]=n.useState(null),[h,g]=n.useState(!1),c=n.useMemo(()=>{var r;const a=u.state;return((r=a==null?void 0:a.from)==null?void 0:r.pathname)??"/"},[u.state]);n.useEffect(()=>{if(!l&&!o){i(c,{replace:!0});return}l&&m&&!o&&i(c,{replace:!0})},[l,m,o,i,c]);const y=async a=>{if(a.preventDefault(),d(null),!t.username.trim()||!t.password){d(s("login.validation.required"));return}g(!0);try{await N(t.username.trim(),t.password),i(c,{replace:!0})}catch(r){d(r instanceof Error?r.message:s("login.validation.failed"))}finally{g(!1)}};return o?e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-background",children:e.jsx(v,{className:"w-full max-w-md",children:e.jsx(w,{className:"flex min-h-[320px] items-center justify-center",children:e.jsx(S,{})})})}):l?e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-background px-4",children:e.jsxs(v,{className:"w-full max-w-md",children:[e.jsxs(P,{className:"text-center",children:[e.jsx("div",{className:"mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-xl bg-primary text-lg font-bold text-primary-foreground",children:"GW"}),e.jsx(T,{className:"text-2xl",children:s("login.title")}),e.jsx(A,{className:"text-sm",children:s("login.description")})]}),e.jsx(w,{children:e.jsxs("form",{className:"space-y-4",onSubmit:y,children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(b,{htmlFor:"username",children:s("login.fields.username")}),e.jsx(j,{id:"username",value:t.username,autoComplete:"username",autoFocus:!0,onChange:a=>f(r=>({...r,username:a.target.value})),placeholder:s("login.fields.usernamePlaceholder")})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(b,{htmlFor:"password",children:s("login.fields.password")}),e.jsx(j,{id:"password",type:"password",value:t.password,autoComplete:"current-password",onChange:a=>f(r=>({...r,password:a.target.value})),placeholder:s("login.fields.passwordPlaceholder")})]}),(p||x)&&e.jsx("div",{className:"rounded-md border border-destructive/50 bg-destructive/10 px-4 py-3 text-sm text-destructive",children:p||x}),e.jsx(k,{type:"submit",className:"w-full",disabled:h,children:s(h?"common.actions.loading":"login.actions.submit")})]})}),e.jsx(D,{className:"justify-center",children:e.jsx("p",{className:"text-center text-xs text-muted-foreground",children:s("login.hint")})})]})}):null}export{H as default};
@@ -0,0 +1,6 @@
1
+ import{c as be,u as U,b as me,r as n,d as we,t as ke,j as e,e as k,a as L,F as _e,f as Se,X as Ee,L as Te}from"./index-CeV0AE1d.js";import{u as F}from"./useApiQuery-B_olnrT7.js";import{P as Ce,B as xe}from"./PageHeader-Bk56T-yb.js";import{c as Le}from"./clipboard-CALi6bTW.js";import{I as Q}from"./input-DcSN-8OE.js";import{L as S}from"./label-C2a8bqtE.js";import{C as re,a as ne}from"./card-D5d6AfHr.js";import{S as M,a as z,b as O,c as q,d as w}from"./select-H2zEksk5.js";import{R as De}from"./refresh-cw-DkrQh2bG.js";/**
2
+ * @license lucide-react v0.344.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const Re=be("Download",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"7 10 12 15 17 10",key:"2ggqvy"}],["line",{x1:"12",x2:"12",y1:"15",y2:"3",key:"1vk2je"}]]),oe=[20,50,100];function de(s,r=!1){if(!s)return;const o=r?`${s}T23:59:59.999`:`${s}T00:00:00.000`,g=Date.parse(o);return Number.isFinite(g)?g:void 0}function ue(s){const r=new Date(s);return`${r.getFullYear()}-${`${r.getMonth()+1}`.padStart(2,"0")}-${`${r.getDate()}`.padStart(2,"0")} ${`${r.getHours()}`.padStart(2,"0")}:${`${r.getMinutes()}`.padStart(2,"0")}:${`${r.getSeconds()}`.padStart(2,"0")}`}function _(s){return s==null?"-":s.toLocaleString()}function E(s,r){const o=_(s);return o==="-"?"-":`${o} ${r}`}function Fe(s){return s?"true":"false"}function ce(s,r){if(!s||s.trim().length===0)return r;try{const o=JSON.parse(s);return JSON.stringify(o,null,2)}catch{return s}}function Qe(){var se,te,le,ae;const{t:s}=U(),{pushToast:r}=me(),[o,g]=n.useState("all"),[j,t]=n.useState("all"),[d,y]=n.useState(""),[m,v]=n.useState("all"),[l,h]=n.useState(""),[i,x]=n.useState(""),[c,p]=n.useState(1),[N,I]=n.useState(oe[0]),[K,H]=n.useState(null),[pe,V]=n.useState(!1),[D,W]=n.useState([]),[P,J]=n.useState(!1);n.useEffect(()=>{p(1)},[o,j,d,m,l,i,N,D]);const $=n.useMemo(()=>{const a={limit:N,offset:(c-1)*N};o!=="all"&&(a.provider=o),j!=="all"&&(a.endpoint=j),d.trim().length>0&&(a.model=d.trim()),m!=="all"&&(a.status=m);const u=de(l),A=de(i,!0);return u!==void 0&&(a.from=u),A!==void 0&&(a.to=A),D.length>0&&(a.apiKeys=D.join(",")),a},[o,j,d,m,l,i,c,N,D]),f=F(["logs",$],{url:"/api/logs",method:"GET",params:$}),T=F(["providers","all"],{url:"/api/providers",method:"GET"}),X=F(["api-keys"],{url:"/api/keys",method:"GET"}),he=F(["custom-endpoints"],{url:"/api/custom-endpoints",method:"GET"});n.useEffect(()=>{f.isError&&f.error&&r({title:s("logs.toast.listError.title"),description:s("logs.toast.listError.desc",{message:f.error.message}),variant:"error"})},[f.isError,f.error,r,s]),n.useEffect(()=>{T.isError&&T.error&&r({title:s("logs.toast.providerError.title"),description:s("logs.toast.providerError.desc",{message:T.error.message}),variant:"error"})},[T.isError,T.error,r,s]);const C=((se=f.data)==null?void 0:se.total)??0,b=C>0?Math.ceil(C/N):0,Y=((te=f.data)==null?void 0:te.items)??[];n.useEffect(()=>{b>0&&c>b&&p(b)},[b,c]);const B=T.data??[],Z=n.useMemo(()=>{const a=new Map;for(const u of B)u.id&&a.set(u.id,u.label??u.id);return a},[B]),G=X.data??[],ee=n.useMemo(()=>{const a=new Map;for(const u of G)a.set(u.id,u);return a},[G]),fe=()=>{g("all"),y(""),t("all"),v("all"),h(""),x(""),W([])},ge=n.useCallback(async()=>{if(!P){J(!0);try{const a=C>0?Math.min(C,5e3):1e3,u={...$,limit:a,offset:0},A=await we.post("/api/logs/export",u,{responseType:"blob"}),Ne=new Blob([A.data],{type:"application/zip"}),ve=new Date().toISOString().replace(/[:.]/g,"-"),ie=URL.createObjectURL(Ne),R=document.createElement("a");R.href=ie,R.download=`cc-gw-logs-${ve}.zip`,document.body.appendChild(R),R.click(),R.remove(),URL.revokeObjectURL(ie),r({title:s("logs.toast.exportSuccess.title"),description:s("logs.toast.exportSuccess.desc"),variant:"success"})}catch(a){const u=ke(a);r({title:s("logs.toast.exportError.title"),description:s("logs.toast.exportError.desc",{message:u.message}),variant:"error"})}finally{J(!1)}}},[P,r,$,s,C]),je=n.useCallback(a=>{H(a),V(!0)},[]),ye=n.useCallback(()=>{V(!1),H(null)},[]);return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(Ce,{icon:e.jsx(_e,{className:"h-5 w-5","aria-hidden":"true"}),title:s("logs.title"),description:s("logs.description"),actions:e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsxs(k,{onClick:ge,disabled:P,children:[e.jsx(Re,{className:"mr-2 h-4 w-4"}),s(P?"common.actions.loading":"logs.actions.export")]}),e.jsx("span",{className:"text-sm text-muted-foreground",children:s("logs.summary.total",{value:C.toLocaleString()})}),e.jsxs(k,{variant:"outline",size:"sm",onClick:()=>f.refetch(),disabled:f.isFetching,children:[e.jsx(De,{className:L("mr-2 h-4 w-4",f.isFetching&&"animate-spin")}),f.isFetching?s("common.actions.refreshing"):s("logs.actions.manualRefresh")]})]})}),e.jsx(re,{children:e.jsxs(ne,{className:"pt-4",children:[e.jsxs("div",{className:"mb-4 flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-medium",children:s("logs.filtersTitle")}),e.jsx("p",{className:"text-xs text-muted-foreground",children:s("logs.filtersDescription")})]}),e.jsx(k,{variant:"ghost",size:"sm",onClick:fe,children:s("common.actions.reset")})]}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(S,{children:s("logs.filters.provider")}),e.jsxs(M,{value:o,onValueChange:g,children:[e.jsx(z,{children:e.jsx(O,{})}),e.jsxs(q,{children:[e.jsx(w,{value:"all",children:s("logs.filters.providerAll")}),B.map(a=>e.jsx(w,{value:a.id,children:a.label??a.id},a.id))]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(S,{children:s("logs.filters.endpoint")}),e.jsxs(M,{value:j,onValueChange:t,children:[e.jsx(z,{children:e.jsx(O,{})}),e.jsxs(q,{children:[e.jsx(w,{value:"all",children:s("logs.filters.endpointAll")}),e.jsx(w,{value:"anthropic",children:s("logs.filters.endpointAnthropic")}),e.jsx(w,{value:"openai",children:s("logs.filters.endpointOpenAI")}),(ae=(le=he.data)==null?void 0:le.endpoints)==null?void 0:ae.map(a=>e.jsx(w,{value:a.id,children:a.label||a.id},a.id))]})]})]}),e.jsx($e,{className:"md:col-span-2",apiKeys:G,selected:D,disabled:X.isLoading,onChange:W}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(S,{children:s("logs.filters.modelId")}),e.jsx(Q,{value:d,onChange:a=>y(a.target.value),placeholder:s("logs.filters.modelPlaceholder")})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(S,{children:s("logs.filters.status")}),e.jsxs(M,{value:m,onValueChange:a=>v(a),children:[e.jsx(z,{children:e.jsx(O,{})}),e.jsxs(q,{children:[e.jsx(w,{value:"all",children:s("logs.filters.statusAll")}),e.jsx(w,{value:"success",children:s("logs.filters.statusSuccess")}),e.jsx(w,{value:"error",children:s("logs.filters.statusError")})]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(S,{children:s("logs.filters.startDate")}),e.jsx(Q,{type:"date",value:l,onChange:a=>h(a.target.value)})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(S,{children:s("logs.filters.endDate")}),e.jsx(Q,{type:"date",value:i,onChange:a=>x(a.target.value)})]})]})]})}),e.jsx(re,{children:e.jsxs(ne,{className:"p-0",children:[e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full min-w-[1200px] text-sm",children:[e.jsx("thead",{className:"border-b bg-muted/50",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-3 py-2 text-left text-xs font-medium",children:s("logs.table.columns.time")}),e.jsx("th",{className:"px-3 py-2 text-left text-xs font-medium",children:s("logs.table.columns.endpoint")}),e.jsx("th",{className:"px-3 py-2 text-left text-xs font-medium",children:s("logs.table.columns.provider")}),e.jsx("th",{className:"px-3 py-2 text-left text-xs font-medium",children:s("logs.table.columns.requestedModel")}),e.jsx("th",{className:"px-3 py-2 text-left text-xs font-medium",children:s("logs.table.columns.routedModel")}),e.jsx("th",{className:"px-3 py-2 text-left text-xs font-medium",children:s("logs.table.columns.apiKey")}),e.jsx("th",{className:"px-3 py-2 text-right text-xs font-medium",children:s("logs.table.columns.inputTokens")}),e.jsx("th",{className:"px-3 py-2 text-right text-xs font-medium",children:s("logs.table.columns.cacheReadTokens")}),e.jsx("th",{className:"px-3 py-2 text-right text-xs font-medium",children:s("logs.table.columns.cacheCreationTokens")}),e.jsx("th",{className:"px-3 py-2 text-right text-xs font-medium",children:s("logs.table.columns.outputTokens")}),e.jsx("th",{className:"px-3 py-2 text-right text-xs font-medium",children:s("logs.table.columns.latency")}),e.jsx("th",{className:"px-3 py-2 text-right text-xs font-medium",children:s("logs.table.columns.ttft")}),e.jsx("th",{className:"px-3 py-2 text-right text-xs font-medium",children:s("logs.table.columns.tpot")}),e.jsx("th",{className:"px-3 py-2 text-center text-xs font-medium",children:s("logs.table.columns.status")}),e.jsx("th",{className:"px-3 py-2 text-left text-xs font-medium",children:s("logs.table.columns.error")}),e.jsx("th",{className:"px-3 py-2 text-center text-xs font-medium",children:s("logs.table.columns.actions")})]})}),e.jsx("tbody",{className:"divide-y",children:f.isPending?e.jsx("tr",{children:e.jsx("td",{colSpan:16,className:"px-3 py-8 text-center text-sm text-muted-foreground",children:s("logs.table.loading")})}):Y.length===0?e.jsx("tr",{children:e.jsx("td",{colSpan:16,className:"px-3 py-8 text-center text-sm text-muted-foreground",children:s("logs.table.empty")})}):Y.map((a,u)=>e.jsx(Ke,{record:a,providerLabelMap:Z,apiKeyMap:ee,onSelect:je,isEven:u%2===0},a.id))})]})}),e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-4 border-t p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm text-muted-foreground",children:s("logs.table.pagination.perPage")}),e.jsxs(M,{value:N.toString(),onValueChange:a=>I(Number(a)),children:[e.jsx(z,{className:"w-[80px]",children:e.jsx(O,{})}),e.jsx(q,{children:oe.map(a=>e.jsx(w,{value:a.toString(),children:a},a))})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(k,{variant:"outline",size:"sm",onClick:()=>p(a=>Math.max(a-1,1)),disabled:c<=1,children:s("logs.table.pagination.previous")}),e.jsx("span",{className:"text-sm text-muted-foreground",children:s("logs.table.pagination.pageLabel",{page:b===0?0:c,total:b})}),e.jsx(k,{variant:"outline",size:"sm",onClick:()=>p(a=>b===0?a:Math.min(a+1,b)),disabled:b===0||c>=b,children:s("logs.table.pagination.next")})]})]})]})}),e.jsx(Pe,{open:pe,logId:K,onClose:ye,providerLabelMap:Z,apiKeyMap:ee})]})}function Ke({record:s,providerLabelMap:r,apiKeyMap:o,onSelect:g,isEven:j}){const{t}=U(),d=r.get(s.provider)??s.provider,y=s.endpoint||"-",m=!!s.error,v=s.status_code,l=s.client_model??t("logs.table.requestedModelFallback"),h=s.api_key_id!=null?o.get(s.api_key_id):void 0,i=s.api_key_id==null?t("logs.table.apiKeyUnknown"):h!=null&&h.isWildcard?t("apiKeys.wildcard"):h!=null&&h.name?h.name:s.api_key_name?s.api_key_name:t("logs.table.apiKeyUnknown");return e.jsxs("tr",{className:L("transition-colors",j?"bg-muted/30":"","hover:bg-muted/50"),children:[e.jsx("td",{className:"px-3 py-2 text-xs",children:ue(s.timestamp)}),e.jsx("td",{className:"px-3 py-2 text-xs",children:y}),e.jsx("td",{className:"px-3 py-2 text-xs",children:e.jsx("div",{className:"max-w-[100px] truncate",title:d,children:d})}),e.jsx("td",{className:"px-3 py-2 text-xs text-muted-foreground",children:e.jsx("div",{className:"max-w-[120px] truncate",title:l,children:l})}),e.jsx("td",{className:"px-3 py-2 text-xs",children:e.jsx("div",{className:"max-w-[120px] truncate",title:s.model,children:s.model})}),e.jsx("td",{className:"px-3 py-2 text-xs text-muted-foreground",children:e.jsx("div",{className:"max-w-[90px] truncate",title:i,children:i})}),e.jsx("td",{className:"px-3 py-2 text-right text-xs tabular-nums",children:_(s.input_tokens)}),e.jsx("td",{className:"px-3 py-2 text-right text-xs tabular-nums",children:_(s.cache_read_tokens)}),e.jsx("td",{className:"px-3 py-2 text-right text-xs tabular-nums",children:_(s.cache_creation_tokens)}),e.jsx("td",{className:"px-3 py-2 text-right text-xs tabular-nums",children:_(s.output_tokens)}),e.jsx("td",{className:"px-3 py-2 text-right text-xs tabular-nums",children:E(s.latency_ms,"ms")}),e.jsx("td",{className:"px-3 py-2 text-right text-xs tabular-nums",children:E(s.ttft_ms,"ms")}),e.jsx("td",{className:"px-3 py-2 text-right text-xs tabular-nums",children:E(s.tpot_ms,"ms/tk")}),e.jsx("td",{className:"px-3 py-2 text-center",children:e.jsx(xe,{variant:m?"destructive":"default",className:"text-xs",children:v??(m?500:200)})}),e.jsx("td",{className:"px-3 py-2 text-xs text-muted-foreground",children:e.jsx("div",{className:"max-w-[100px] truncate",title:s.error??"",children:s.error?s.error:"-"})}),e.jsx("td",{className:"px-3 py-2 text-center",children:e.jsx(k,{variant:"outline",size:"sm",onClick:()=>g(s.id),children:t("logs.actions.detail")})})]})}function Pe({open:s,logId:r,onClose:o,providerLabelMap:g,apiKeyMap:j}){var x,c;const{t}=U(),{pushToast:d}=me(),y=n.useRef(null),m=F(["log-detail",r],{url:`/api/logs/${r}`,method:"GET"},{enabled:s&&r!==null,staleTime:3e4});n.useEffect(()=>{m.isError&&m.error&&d({title:t("logs.detail.loadError"),description:m.error.message,variant:"error"})},[m.isError,m.error,d,t]),n.useEffect(()=>{if(!s)return;const p=N=>{N.key==="Escape"&&o()};return window.addEventListener("keydown",p),()=>window.removeEventListener("keydown",p)},[s,o]),n.useEffect(()=>{s&&y.current&&y.current.focus()},[s,r]);const v=n.useCallback(async(p,N,I)=>{if(!N){d({title:t("logs.detail.copy.empty",{label:p}),variant:"info"});return}try{await Le(N),d({title:t(I),variant:"success"})}catch(K){d({title:t("logs.detail.copy.failure"),description:K instanceof Error?K.message:t("logs.detail.copy.failureFallback"),variant:"error"})}},[d,t]);if(!s)return null;const l=m.data,h=l?g.get(l.provider)??l.provider:"",i=l&&l.api_key_id!=null?j.get(l.api_key_id):void 0;return typeof document>"u"?null:Se.createPortal(e.jsxs("div",{className:"fixed inset-0 z-50 flex",children:[e.jsx("div",{className:"flex-1 bg-background/80 backdrop-blur-sm",onClick:o}),e.jsxs("aside",{role:"dialog","aria-modal":"true",className:"flex h-full w-full max-w-xl flex-col border-l bg-card shadow-xl",children:[e.jsxs("header",{className:"flex items-center justify-between border-b px-6 py-4",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold",children:t("logs.detail.title")}),l&&e.jsx("p",{className:"text-xs text-muted-foreground",children:t("logs.detail.id",{id:l.id})})]}),e.jsxs(k,{ref:y,variant:"outline",size:"sm",onClick:o,children:[e.jsx(Ee,{className:"mr-2 h-4 w-4"}),t("common.actions.close")]})]}),e.jsx("div",{className:"flex-1 overflow-y-auto",children:m.isPending?e.jsx(Te,{}):l?e.jsxs("div",{className:"flex flex-col gap-6 px-6 py-5 text-sm",children:[e.jsxs("section",{className:"space-y-3",children:[e.jsx("h3",{className:"text-xs font-semibold uppercase tracking-wide text-muted-foreground",children:t("logs.detail.infoSection")}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 rounded-md bg-muted p-3 text-xs",children:[e.jsx("span",{className:"font-medium",children:t("logs.detail.summary.route",{from:l.client_model??t("logs.detail.info.noRequestedModel"),to:l.model})}),e.jsx("span",{className:"text-muted-foreground",children:t("logs.detail.summary.latency",{value:E(l.latency_ms,t("common.units.ms"))})}),l.ttft_ms!==null&&e.jsxs("span",{className:"text-muted-foreground",children:["TTFT: ",E(l.ttft_ms,t("common.units.ms"))]}),e.jsx(xe,{variant:l.error?"destructive":"default",children:(l.status_code??(l.error?500:200)).toString()})]}),e.jsxs("dl",{className:"grid grid-cols-2 gap-x-4 gap-y-3",children:[e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.time")}),e.jsx("dd",{className:"font-medium",children:ue(l.timestamp)})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.sessionId")}),e.jsx("dd",{className:"font-medium",children:l.session_id??"-"})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.endpoint")}),e.jsx("dd",{className:"font-medium",children:l.endpoint||"-"})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.provider")}),e.jsx("dd",{className:"font-medium",children:h})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.requestedModel")}),e.jsx("dd",{className:"font-medium",children:l.client_model??t("logs.detail.info.noRequestedModel")})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.model")}),e.jsx("dd",{className:"font-medium",children:l.model})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.stream")}),e.jsx("dd",{className:"font-medium",children:Fe(l.stream)})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.inputTokens")}),e.jsx("dd",{className:"font-medium",children:_(l.input_tokens)})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.cacheReadTokens")}),e.jsx("dd",{className:"font-medium",children:_(l.cache_read_tokens)})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.cacheCreationTokens")}),e.jsx("dd",{className:"font-medium",children:_(l.cache_creation_tokens)})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.outputTokens")}),e.jsx("dd",{className:"font-medium",children:_(l.output_tokens)})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.ttft")}),e.jsx("dd",{className:"font-medium",children:E(l.ttft_ms,t("common.units.ms"))})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.tpot")}),e.jsx("dd",{className:"font-medium",children:E(l.tpot_ms,t("common.units.msPerToken"))})]})]}),l.error&&e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-xs text-muted-foreground",children:t("logs.detail.info.error")}),e.jsx("p",{className:"rounded-md border border-destructive/50 bg-destructive/10 p-3 text-xs text-destructive",children:l.error})]})]}),e.jsxs("section",{className:"space-y-3",children:[e.jsx("h3",{className:"text-xs font-semibold uppercase tracking-wide text-muted-foreground",children:t("logs.detail.apiKey.title")}),e.jsxs("dl",{className:"grid gap-x-4 gap-y-3 text-sm sm:grid-cols-2",children:[e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.apiKey.name")}),e.jsx("dd",{className:"font-medium",children:l.api_key_id==null&&!l.api_key_name?t("logs.detail.apiKey.missing"):i!=null&&i.isWildcard?t("apiKeys.wildcard"):(i==null?void 0:i.name)??l.api_key_name??t("logs.detail.apiKey.missing")})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.apiKey.identifier")}),e.jsx("dd",{className:"font-medium",children:l.api_key_id??t("common.noData")})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.apiKey.masked")}),e.jsx("dd",{className:"font-medium",children:i!=null&&i.isWildcard?t("apiKeys.wildcard"):(i==null?void 0:i.maskedKey)??l.api_key_name??t("logs.detail.apiKey.maskedUnavailable")})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs text-muted-foreground",children:t("logs.detail.apiKey.lastUsed")}),e.jsx("dd",{className:"font-medium",children:i!=null&&i.lastUsedAt?new Date(i.lastUsedAt).toLocaleString():t("common.noData")})]})]}),e.jsxs("div",{className:"rounded-md border bg-muted p-3 text-xs",children:[e.jsx("p",{className:"font-medium",children:t("logs.detail.apiKey.rawMasked")}),e.jsx("p",{className:"mt-1 break-all font-mono",children:l.api_key_value_available?l.api_key_value_masked??t("logs.detail.apiKey.rawUnavailable"):t("logs.detail.apiKey.rawUnavailable")}),e.jsx("p",{className:"mt-2 text-[11px] text-muted-foreground",children:t("logs.detail.apiKey.rawMaskedHint")})]})]}),e.jsxs("section",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"text-xs font-semibold uppercase tracking-wide text-muted-foreground",children:t("logs.detail.payload.request")}),e.jsx(k,{variant:"outline",size:"sm",onClick:()=>{var p;return v(t("logs.detail.payload.request"),(p=l.payload)==null?void 0:p.prompt,"logs.detail.copy.requestSuccess")},children:t("common.actions.copy")})]}),e.jsx("pre",{className:"max-h-64 overflow-auto whitespace-pre-wrap rounded-md border bg-muted p-3 text-xs",children:ce((x=l.payload)==null?void 0:x.prompt,t("logs.detail.payload.emptyRequest"))})]}),e.jsxs("section",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"text-xs font-semibold uppercase tracking-wide text-muted-foreground",children:t("logs.detail.payload.response")}),e.jsx(k,{variant:"outline",size:"sm",onClick:()=>{var p;return v(t("logs.detail.payload.response"),(p=l.payload)==null?void 0:p.response,"logs.detail.copy.responseSuccess")},children:t("common.actions.copy")})]}),e.jsx("pre",{className:"max-h-64 overflow-auto whitespace-pre-wrap rounded-md border bg-muted p-3 text-xs",children:ce((c=l.payload)==null?void 0:c.response,t("logs.detail.payload.emptyResponse"))})]})]}):e.jsx("div",{className:"flex h-full items-center justify-center p-8 text-sm text-muted-foreground",children:t("logs.detail.loadError")})})]})]}),document.body)}function $e({apiKeys:s,selected:r,onChange:o,disabled:g,className:j}){const{t}=U(),[d,y]=n.useState(!1),m=n.useRef(null);n.useEffect(()=>{if(!d)return;const i=x=>{var c;(c=m.current)!=null&&c.contains(x.target)||y(!1)};return window.addEventListener("mousedown",i),()=>window.removeEventListener("mousedown",i)},[d]);const v=n.useMemo(()=>{if(r.length===0)return[];const i=new Map;for(const x of s)i.set(x.id,x);return r.map(x=>{const c=i.get(x);return c?c.isWildcard?t("apiKeys.wildcard"):c.name:null}).filter(x=>!!x)},[s,r,t]),l=r.length===0?t("logs.filters.apiKeyAll"):t("logs.filters.apiKeySelected",{count:r.length}),h=i=>{r.includes(i)?o(r.filter(x=>x!==i)):o([...r,i])};return e.jsxs("div",{className:L("relative space-y-2",j),ref:m,children:[e.jsx(S,{children:t("logs.filters.apiKey")}),e.jsxs("button",{type:"button",onClick:()=>y(i=>!i),disabled:g||s.length===0,title:t("logs.filters.apiKeyHint"),className:L("flex h-10 w-full items-center justify-between rounded-md border bg-background px-3 text-sm ring-offset-background focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",r.length>0&&"border-primary",d&&"ring-2 ring-ring ring-offset-2"),children:[e.jsxs("span",{className:"truncate",children:[l,v.length>0&&e.jsx("span",{className:"ml-1 text-xs text-muted-foreground",children:v.join(", ")})]}),e.jsx("svg",{className:L("h-4 w-4 opacity-50 transition-transform",d&&"rotate-180"),viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M5.23 7.21a.75.75 0 011.06.02L10 10.94l3.71-3.71a.75.75 0 111.06 1.06l-4.24 4.25a.75.75 0 01-1.06 0L5.21 8.29a.75.75 0 01.02-1.08z",clipRule:"evenodd"})})]}),d&&e.jsxs("div",{className:"absolute left-0 top-full z-30 mt-1 w-64 rounded-md border bg-popover p-2 shadow-lg",children:[e.jsxs("div",{className:"flex items-center justify-between rounded-md bg-muted px-3 py-2 text-xs",children:[e.jsx("span",{children:l}),e.jsx("button",{type:"button",onClick:()=>o([]),disabled:r.length===0,className:"text-primary hover:underline disabled:opacity-40",children:t("common.actions.reset")})]}),e.jsxs("div",{className:"max-h-56 overflow-y-auto py-2",children:[s.map(i=>{const x=i.isWildcard?t("apiKeys.wildcard"):i.name,c=r.includes(i.id);return e.jsxs("label",{className:L("flex cursor-pointer items-center gap-2 rounded-md px-3 py-2 text-sm transition hover:bg-muted",c&&"bg-primary/10 text-primary"),children:[e.jsx("input",{type:"checkbox",className:"h-4 w-4 rounded border",checked:c,onChange:()=>h(i.id)}),e.jsx("span",{className:"truncate",children:x})]},i.id)}),s.length===0&&e.jsx("p",{className:"px-2 py-2 text-xs text-muted-foreground",children:t("logs.filters.apiKeyAll")})]})]})]})}export{Qe as default};