dsh-token-total 1.0.4 → 1.0.6

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/lib/client.js CHANGED
@@ -29390,13 +29390,14 @@ window.__ModuleLoader__.load({
29390
29390
  this.code = code;
29391
29391
  }
29392
29392
  };
29393
- async function post(method, body) {
29393
+ async function post(method, body, signal) {
29394
29394
  let res;
29395
29395
  try {
29396
29396
  res = await fetch(`token-total/api/${method}`, {
29397
29397
  method: "POST",
29398
29398
  headers: { "content-type": "application/json" },
29399
- body: body === void 0 ? void 0 : JSON.stringify(body)
29399
+ body: body === void 0 ? void 0 : JSON.stringify(body),
29400
+ signal
29400
29401
  });
29401
29402
  } catch (err) {
29402
29403
  throw new UsageApiError("network", err instanceof Error ? err.message : String(err));
@@ -29425,15 +29426,19 @@ window.__ModuleLoader__.load({
29425
29426
  async function fetchSessionUsage(sessionId) {
29426
29427
  return post("session", { sessionId });
29427
29428
  }
29429
+ /** Log-owned requests and live route states for the per-session Usage view. */
29430
+ async function fetchSessionDetail(sessionId, signal) {
29431
+ return post("session-detail", { sessionId }, signal);
29432
+ }
29428
29433
  //#endregion
29429
29434
  //#region \0token-total-css:/home/runner/work/dsh-token-total/dsh-token-total/src/client/TokenTotalPanel.module.css?inline
29430
- const css$2 = "/**\n * Usage statistics panel styles — a DSH-native CSS Module. Every visual\n * value rides the DSH semantic tokens (--dsw-alias-* colors, --dsw-font-*\n * typography, --ds-* motion); no static palette values, no theme selectors.\n * The heatmap's 5 levels come from the brand accent via color-mix; model\n * colours are the fixed --dsw-chart-1..5 series (rank order by token\n * volume) plus the gray --dsw-chart-other step — the reasonix token-total\n * palette, with a lifted dark variant defined below.\n */\n\n/* The panel as a standalone main panel. It gets the same 960px content column\n the Plugins page gives it — the declarations below mirror the Plugins page's\n own `.page_768838850` so both entries render identically. Without the cap the charts\n would stretch to whatever the centre column happens to be.\n\n One deliberate difference from that page: its 28px top inset is NOT part of\n this container. A main panel starts at the window's top-left corner, so an\n inset painted by this scrolling container is a strip above the content that\n no window-drag region covers; `.backRow_768838850` below owns the inset instead, which\n is the shape the shipped page plugins use for the same reason\n (`ui-plugin-manager`'s `.pageHead_768838850`/`.detailTop_768838850` and `ui-schedule`'s page\n head). The rendered position is unchanged. */\n.page_768838850 {\n display: flex;\n flex-direction: column;\n align-items: center;\n box-sizing: border-box;\n height: 100%;\n overflow: auto;\n padding: 0 clamp(24px, 4vw, 48px) 48px;\n color: var(--dsw-alias-label-primary);\n}\n\n.page_768838850 > * {\n width: 100%;\n max-width: 960px;\n}\n\n/* The standalone panel's back control. Only the main panel renders this seat —\n the Plugins page entry already sits inside the page's own chrome, which\n draws its own crumb back to the bundle list. The spacing matches the gap the\n panel keeps between its own sections.\n\n The row also carries the panel's former 28px top inset: it starts at the\n window's top edge, so the whole strip above the back control drags the\n window (Electron app-regions are geometry, not stacking, so a strip owned by\n the scrolling container would subtract itself from the drag row beneath\n it). */\n.backRow_768838850 {\n display: flex;\n box-sizing: border-box;\n padding-top: 28px;\n margin-bottom: 18px;\n}\n\n.back_768838850 {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.panel_768838850 {\n display: flex;\n flex-direction: column;\n gap: 18px;\n min-width: 0;\n}\n\n/* ── toolbar ───────────────────────────────────────────────────────────── */\n\n.toolbar_768838850 {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 10px;\n}\n\n/* Each picker (time range) lives in a framed group. */\n.group_768838850 {\n display: inline-flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 2px;\n padding: 3px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 9px;\n background: var(--dsw-alias-bg-layer-1);\n}\n\n/* A range-preset chip: ghost Button inside the group, active state tinted\n with the brand accent (same blue as the section bars and the total card). */\n.segItem_768838850 {\n border-radius: 6px;\n}\n\n.segItem_768838850:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.segActive_768838850,\n.segActive_768838850:hover:not(:disabled) {\n background: color-mix(in srgb, var(--dsw-tone-1) 14%, transparent);\n color: var(--dsw-tone-1);\n font-weight: 600;\n}\n\n.customRange_768838850 {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.dateInput_768838850 {\n width: 150px;\n flex: 0 0 auto;\n}\n\n.customSep_768838850 {\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* Trailing toolbar edge: the \"as of\" stamp sits immediately left of the\n refresh action (it stamps the very data that button refreshes). */\n.toolbarEnd_768838850 {\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n gap: 10px;\n}\n\n.asOf_768838850 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n white-space: nowrap;\n}\n\n/* Keep the remaining toolbar action at the trailing edge. */\n.refresh_768838850 {\n flex: 0 0 auto;\n}\n\n/* ── states ────────────────────────────────────────────────────────────── */\n\n.errorBanner_768838850 {\n padding: 10px 14px;\n border: 1px solid var(--dsw-alias-state-warn-primary);\n border-radius: 8px;\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 12%, transparent);\n color: var(--dsw-alias-state-warn-label);\n font-size: 13px;\n}\n\n.loading_768838850 {\n padding: 24px;\n text-align: center;\n color: var(--dsw-alias-label-tertiary);\n font-size: 13px;\n}\n\n.empty_768838850 {\n padding: 24px;\n text-align: center;\n color: var(--dsw-alias-label-tertiary);\n font-size: 13px;\n border: 1px dashed var(--dsw-alias-border-l2);\n border-radius: 8px;\n}\n\n/* ── numeric cards ─────────────────────────────────────────────────────── */\n\n/* Six equal tracks: the overview row is one grid of six identical cards\n (long value or not), so no card crowds its neighbours. At the Plugins\n page's 960px content width that is six columns on one row. */\n.cards_768838850 {\n display: grid;\n grid-template-columns: repeat(6, minmax(0, 1fr));\n gap: 10px;\n}\n\n/* Below the width where six cards hold their own, the grid folds to three\n columns (two rows of three), then to two (three rows of two). */\n@media (max-width: 720px) {\n .cards_768838850 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n}\n\n@media (max-width: 430px) {\n .cards_768838850 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n}\n\n/* Each stat card wears one accent hue (tone 1..6 → --dsw-tone-1..6): a 3px\n accent bar on the left edge, the icon in a tinted badge, and a whisper of\n the hue washing the top-left corner — the overview row reads in colour\n instead of one gray register. --card-accent is set by the .cardToneN_768838850 map\n below; content sits above the wash via a z-index layer. */\n.card_768838850 {\n --card-accent: var(--dsw-alias-label-tertiary);\n position: relative;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 14px 14px 12px 18px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-1);\n box-shadow: 0 1px 2px var(--dsw-alias-bg-mask-2);\n min-width: 0;\n}\n\n.card_768838850::before {\n content: \"\";\n position: absolute;\n left: 0;\n top: 12px;\n bottom: 12px;\n width: 3px;\n border-radius: 0 3px 3px 0;\n background: var(--card-accent);\n}\n\n.card_768838850::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background: linear-gradient(135deg, color-mix(in srgb, var(--card-accent) 7%, transparent), transparent 60%);\n pointer-events: none;\n}\n\n/* Content must paint above the corner wash (the ::after pseudo is the last\n child, so it wins a same-layer paint order). */\n.card_768838850 > * {\n position: relative;\n z-index: 1;\n}\n\n.cardTone1_768838850 { --card-accent: var(--dsw-tone-1); }\n.cardTone2_768838850 { --card-accent: var(--dsw-tone-2); }\n.cardTone3_768838850 { --card-accent: var(--dsw-tone-3); }\n.cardTone4_768838850 { --card-accent: var(--dsw-tone-4); }\n.cardTone5_768838850 { --card-accent: var(--dsw-tone-5); }\n.cardTone6_768838850 { --card-accent: var(--dsw-tone-6); }\n\n.cardHead_768838850 {\n display: flex;\n align-items: center;\n gap: 7px;\n}\n\n/* Icon badge: the accent hue at 12% behind its own glyph. */\n.cardIcon_768838850 {\n box-sizing: border-box;\n width: 24px;\n height: 24px;\n padding: 5px;\n border-radius: 7px;\n color: var(--card-accent);\n background: color-mix(in srgb, var(--card-accent) 12%, transparent);\n flex: 0 0 auto;\n}\n\n.cardLabel_768838850 {\n color: var(--dsw-alias-label-secondary);\n font-size: 13px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Values never wrap: a wrapped number defeats FitText's measurement (the\n wrapped line is exactly as wide as its box) and reads as a layout break.\n Oversized text shrinks instead — see FitText in TokenTotalPanel.tsx_768838850. */\n.cardValue_768838850 {\n color: var(--dsw-alias-label-primary);\n font-weight: 600;\n line-height: 1.15;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.cardValueSm_768838850 {\n font-size: 14px;\n}\n\n.cardValueWrap_768838850 {\n word-break: break-word;\n}\n\n/* The \"most used model\" card value: the model name over the provider, the\n same two-line anatomy as the per-model list rows (modelName/modelProvider\n classes), instead of the raw \"provider/model\" ref. */\n.cardModelLines_768838850 {\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n\n/* A muted second line under a card value (the absolute cached-token volume\n under the hit-rate percentage). Same no-wrap rule as the value above. */\n.cardSub_768838850 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 1.2;\n white-space: nowrap;\n overflow: hidden;\n}\n\n/* ── sections / chart chrome ───────────────────────────────────────────── */\n\n.section_768838850 {\n display: flex;\n flex-direction: column;\n gap: 12px;\n min-width: 0;\n padding: 14px 16px 16px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-1);\n box-shadow: 0 1px 2px var(--dsw-alias-bg-mask-2);\n}\n\n.sectionHead_768838850 {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n/* Section titles carry the same brand accent bar as the stat cards' tone\n language, so every card heading is anchored the same way. */\n.sectionTitle_768838850 {\n margin: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 15px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n.sectionTitle_768838850::before {\n content: \"\";\n width: 3px;\n height: 13px;\n border-radius: 2px;\n background: var(--dsw-tone-1);\n flex: 0 0 auto;\n}\n\n/* Header meta cluster right of a section title (trend cap note + curve\n legend). Kept as one wrap-friendly row on a common baseline. */\n.headMeta_768838850 {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n font-size: 12px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.trendNote_768838850 {\n font-size: 13px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* Heatmap and the token trend share ONE row — one card each, left and right.\n Both columns stretch to a common height; the heatmap centres its SVG in the\n taller partner. Below 720px the pair folds to a single column. */\n.duo_768838850 {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n gap: 12px;\n align-items: stretch;\n}\n\n@media (max-width: 720px) {\n .duo_768838850 {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n.chartWrap_768838850 {\n position: relative;\n min-width: 0;\n}\n\n/* ── heatmap ───────────────────────────────────────────────────────────── */\n\n.heatWrap_768838850 {\n position: relative;\n /* hidden, not auto: the SVG now fills the container exactly, and an\n auto scrollbar would flash when a fixed tooltip passes over the wrap's\n right edge. */\n overflow: hidden;\n min-width: 0;\n /* In the duo row the heatmap card shares height with the trend card; the\n grid centres itself in whatever slack the partner leaves. */\n flex: 1 1 auto;\n display: flex;\n align-items: center;\n}\n\n.heatmap_768838850 {\n display: block;\n margin: 0 auto;\n /* The ~364 day cells are flat SVG rects (no per-cell filter), so there is no\n blur chain left to re-rasterize — but promoting the SVG onto its own\n compositing layer still keeps the whole grid off the scroll repaint path,\n which is what made scrolling this panel drop frames while idle was clean\n (#4). Cheap and invisible, so it stays. Note that the promotion is what\n does the work: `contain: paint` on its own measured no better than no\n mitigation at all. */\n transform: translateZ(0);\n}\n\n.heatLegend_768838850 {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 13px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* Axis labels drawn inside the heatmap SVG: the weekday column on the left and\n the month strip along the bottom. SVG <text> takes `fill`, not `color`. */\n.heatAxis_768838850 {\n fill: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n}\n\n.heatCell_768838850 {\n display: inline-block;\n border-radius: 2px;\n /* No width/height here: the SVG cells carry their size as geometry\n attributes (x/y/width/height), and a CSS width/height would override\n those on SVG2 rects — pinning every cell to a fixed px and widening the\n visual gap. The legend swatches carry the same size inline, so both\n always match the measured geom.size_768838850.\n No filter either: the reference chart paints each tile as a flat, matte\n rounded square, so a sheen/under-shadow would read as a smudge at this\n cell size rather than depth. */\n}\n\n/* The five heat levels ride a fixed emerald ramp sampled pixel-for-pixel from\n the reference chart (a GitHub-style green scale), with a darker variant for\n dark mode below — never the theme accent, which can read near-black against\n the base surface in dark mode. level0 (no data) is a neutral empty cell.\n The fills are fully opaque: the reference tiles are solid, and mixing toward\n transparent (the previous glass treatment) lightened every step and broke\n the sampled ramp. The cells are SVG <rect>s, so the color rides `fill`\n (background is a no-op on SVG geometry) — but the legend swatches are HTML,\n so both declarations stay in step. */\n.heatLevel0_768838850 {\n fill: var(--dsw-heat-0);\n background: var(--dsw-heat-0);\n}\n\n.heatLevel1_768838850 {\n fill: var(--dsw-heat-1);\n background: var(--dsw-heat-1);\n}\n\n.heatLevel2_768838850 {\n fill: var(--dsw-heat-2);\n background: var(--dsw-heat-2);\n}\n\n.heatLevel3_768838850 {\n fill: var(--dsw-heat-3);\n background: var(--dsw-heat-3);\n}\n\n.heatLevel4_768838850 {\n fill: var(--dsw-heat-4);\n background: var(--dsw-heat-4);\n}\n\n.heatLevel5_768838850 {\n fill: var(--dsw-heat-5);\n background: var(--dsw-heat-5);\n}\n\n/* ── daily trend ───────────────────────────────────────────────────────── */\n\n.chart_768838850 {\n display: block;\n}\n\n.grid_768838850 {\n stroke: var(--dsw-alias-border-l1);\n stroke-width: 1;\n}\n\n.axis_768838850 {\n fill: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n\n.axisRate_768838850 {\n fill: var(--dsw-alias-label-tertiary);\n}\n\n.bar_768838850 {\n transition: opacity 0.12s ease;\n /* The hover scaleX must pivot on the bar's own centre: SVG geometry\n transforms around the SVG origin unless transform-box anchors it to the\n element's fill box. Without this the scaled bar slides sideways and\n looks like it vanishes. */\n transform-box: fill-box;\n transform-origin: center;\n}\n\n.barDim_768838850 {\n opacity: 0.35;\n}\n\n.barHit_768838850 {\n fill: transparent;\n pointer-events: all;\n}\n\n/* cache hit-rate trend curve: DeepSeek's brand blue (#4D6BFE, the same hue\n family as the heatmap ramp) — a fixed brand ramp instead of the theme\n accent, which can read near-black in some themes. */\n.trend_768838850 {\n stroke: var(--dsw-trend-line);\n stroke-width: 2;\n opacity: 0.9;\n pointer-events: none;\n}\n\n.trendDot_768838850 {\n fill: var(--dsw-trend-line);\n stroke: var(--dsw-alias-bg-layer-1);\n stroke-width: 2;\n pointer-events: none;\n}\n\n.legend_768838850 {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 13px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.legendItem_768838850 {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n cursor: default;\n}\n\n.legendSwatch_768838850 {\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: 2px;\n}\n\n.legendTrend_768838850 {\n background: var(--dsw-trend-line);\n width: 14px;\n height: 3px;\n border-radius: 2px;\n}\n\n/* ── per-model / per-provider chart + list ─────────────────────────────── */\n\n/* The ring is centred against the list beside it. The list's height is never\n tied to the chart, so expanding a row cannot stretch anything. */\n.models_768838850 {\n display: flex;\n gap: 16px;\n align-items: center;\n flex-wrap: wrap;\n min-width: 0;\n}\n\n/* The ring's own wrapper. Its diameter comes from the measured row width (see\n Donut.tsx_768838850), so it must never flex. */\n.donutWrap_768838850 {\n position: relative;\n flex: 0 0 auto;\n}\n\n.donut_768838850 {\n display: block;\n}\n\n.donutTrack_768838850 {\n stroke: var(--dsw-alias-bg-mask-1);\n}\n\n.donutSeg_768838850 {\n transition: stroke-width 0.12s ease, opacity 0.12s ease;\n}\n\n.donutDim_768838850 {\n opacity: 0.35;\n}\n\n.donutCenter_768838850 {\n fill: var(--dsw-alias-label-primary);\n font-size: 18px;\n font-weight: 600;\n}\n\n.donutLabel_768838850 {\n fill: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n/* Two ranking cards, side by side: MODELS left, PROVIDERS right. Both are\n always on screen (no lens/tab switch), so they share one row grid and\n stretch to a common height; a narrow pane stacks them instead. */\n.rankCards_768838850 {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 12px;\n}\n\n@media (max-width: 720px) {\n .rankCards_768838850 {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n/* Each card is the bordered surface its rows live in; the title is a recessed\n header strip, so the two rankings read as two equal panels. */\n.rankCard_768838850 {\n display: flex;\n flex-direction: column;\n min-width: 0;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-1);\n overflow: hidden;\n}\n\n.rankCardTitle_768838850 {\n padding: 8px 12px;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 55%, transparent);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n font-weight: 600;\n}\n\n.rankList_768838850 {\n list-style: none;\n margin: 0;\n padding: 0;\n flex: 1 1 auto;\n min-width: 0;\n}\n\n/* Every row opens a hover tip (the cross-dimension detail), so it carries the\n same hover affordance as the chart marks. */\n.modelRow_768838850:hover {\n background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 60%, transparent);\n}\n\n/* Position column: the row's rank inside its section. The Other bucket holds\n no single rank, so it renders an empty (but equally wide) cell. */\n.modelRank_768838850 {\n flex: 0 0 auto;\n min-width: 14px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n text-align: right;\n}\n\n.modelRow_768838850 {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n font-size: 13px;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n}\n\n.modelRow_768838850:last-child {\n border-bottom: none;\n}\n\n/* Share bar under a rank row's name: the row's slice of the section total,\n drawn in the row's own colour (a 3px track, like the design mock). */\n.rowTrack_768838850 {\n height: 3px;\n margin-top: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-border-l1);\n overflow: hidden;\n}\n\n.rowFill_768838850 {\n display: block;\n height: 3px;\n border-radius: 2px;\n}\n\n/* Top-3 ranks read as a podium: the ordinal takes the warm accent instead of\n the muted gray the tail ranks keep. */\n.rankList_768838850 > .modelRow_768838850:nth-child(-n + 3) .modelRank_768838850 {\n color: var(--dsw-rank-top);\n font-weight: 700;\n}\n\n/* \"Other\" aggregate row: the entire row is clickable to expand/collapse the\n detail list. The chevron button inside it stops propagation so\n double-firing is avoided. */\n.modelRowExpandable_768838850 {\n cursor: pointer;\n}\n\n/* \"Other\" row toggle (chevron) that expands the aggregated tail models. */\n.modelToggle_768838850 {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n margin-right: 4px;\n border: none;\n background: none;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n vertical-align: middle;\n}\n\n/* Expanded detail rows: indented, slightly recessed. */\n.modelRowSub_768838850 {\n padding-left: 28px;\n background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 55%, transparent);\n font-size: 13px;\n}\n\n/* Second-level indent: a model row inside a provider that is itself folded\n into the Other bucket. Wider than .modelRowSub_768838850 so the nesting stays\n readable. Declared after it — same specificity, so this one wins. */\n.modelRowDeep_768838850 {\n padding-left: 48px;\n}\n\n/* \"Other\" details expand with an accordion: the wrapper is a grid whose\n single track animates 0fr → 1fr. */\n.modelOtherWrap_768838850 {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows 0.25s ease;\n}\n\n.modelOtherOpen_768838850 {\n grid-template-rows: 1fr;\n}\n\n.modelOtherList_768838850 {\n overflow: hidden;\n min-height: 0;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n/* Two-line row anatomy: [swatch] [name / provider] ……… [tokens / share].\n The name block takes the free width; the values block hugs the right. */\n.modelId_768838850 {\n display: flex;\n flex-direction: column;\n gap: 1px;\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.modelValues_768838850 {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 1px;\n flex: 0 0 auto;\n}\n\n.modelName_768838850 {\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n}\n\n.modelProvider_768838850 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.modelTokens_768838850 {\n color: var(--dsw-alias-label-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n.modelPct_768838850 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n}\n\n/* ── tooltips ──────────────────────────────────────────────────────────── */\n\n/* Tooltips render as fixed-position portals on document.body_768838850 (see ChartTip),\n so they escape every ancestor's clipping and never overflow the settings\n panel: ChartTip clamps each tip inside the panel bounds and flips it above\n the hovered element when there is no room below. The plate follows the\n active theme: the DSH overlay token is a light gray in light mode and a\n dark gray under body[data-ds-dark-theme], so the tip reads correctly in\n both instead of staying dark in light mode. */\n.tip_768838850 {\n position: fixed;\n /* The tip is portaled to document.body_768838850, so it competes with the settings\n modal itself (z-index 1000) for the top layer: 100 would sit under the\n modal and the tip would be invisible. 1100 matches the official\n toast/portaled-menu layer, which is exactly the \"over a modal\" tier. */\n z-index: 1100;\n pointer-events: none;\n padding: 8px 10px;\n border-radius: 8px;\n background: var(--dsw-alias-bg-overlay);\n border: 1px solid var(--dsw-alias-border-l2);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n box-shadow: 0 2px 12px var(--dsw-alias-bg-mask-2);\n white-space: nowrap;\n}\n\n.tipTitle_768838850 {\n font-weight: 600;\n margin-bottom: 4px;\n}\n\n/* A provider row's raw route id, kept out of the row label but reachable on\n hover (the row shows the display name). */\n.tipSubtitle_768838850 {\n margin: -2px 0 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n}\n\n/* Breakdown heading inside a row tip: names the cross-dimension list under it\n (\"By provider\" under a model, \"By model\" under a provider). */\n.tipLabel_768838850 {\n margin-bottom: 2px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n}\n\n/* The breakdown line pushes its volume to the right edge of the plate. */\n.tipName_768838850 {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.tipValue_768838850 {\n margin-left: auto;\n padding-left: 12px;\n color: var(--dsw-alias-label-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n.tipRow_768838850 {\n display: flex;\n align-items: center;\n gap: 5px;\n}\n\n/* Hover tooltip breakdown rows for the \"Other\" aggregate: indented, muted,\n same gray swatch as the Other step. */\n.tipRowOther_768838850 {\n padding-left: 8px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.tipBreakdown_768838850 {\n border-top: 1px solid var(--dsw-alias-border-l1);\n margin-top: 4px;\n padding-top: 4px;\n}\n\n/* ── chart palette ──────────────────────────────────────────────────────── */\n\n/* Light variant (the theme's default): model colours are the reasonix\n token-total palette (rank order by token volume + gray Other) with a\n white veil mixed in (color-mix 30% white) — the raw hues read dark and\n heavy on the light card surface, and the veil lifts lightness and dulls\n saturation the way a translucent white overlay would, keeping the hues\n colourful instead of muddy. The heatmap ramp is a fixed emerald green\n scale (GitHub-style activity heatmap), stepping from a near-white tint to\n a deep green; the hit-rate curve rides the brand blue.\n Ranks 6-10 extend the reasonix five to ten (this plugin's addition): each\n is picked to keep the ten hues apart on both themes.\n The palette must ALSO live on :root: tooltips are fixed portals on\n document.body_768838850 (see ChartTip), outside the panel subtree, and the inline\n var(--dsw-chart-N) swatches they carry only resolve from :root. */\n:root, .panel_768838850 {\n --dsw-heat-0: #f4f5f5;\n --dsw-heat-1: #daf6ea;\n --dsw-heat-2: #c7f0df;\n --dsw-heat-3: #82edc0;\n --dsw-heat-4: #00b96b;\n --dsw-heat-5: #00663b;\n --dsw-trend-line: #4d6bfe;\n /* Overview-card tone accents (stat cards 1..6) and the podium ordinal.\n Six hues, each picked to sit apart from both the chart set and the heat\n ramp, at full strength so 12% badge tints stay visible on white. */\n --dsw-tone-1: #4d6bfe;\n --dsw-tone-2: #00b96b;\n --dsw-tone-3: #e07b39;\n --dsw-tone-4: #975bf1;\n --dsw-tone-5: #0d8a8a;\n --dsw-tone-6: #d34591;\n --dsw-rank-top: #c46212;\n --dsw-chart-1: color-mix(in srgb, #0576ff 70%, white);\n --dsw-chart-2: color-mix(in srgb, #2f6f37 70%, white);\n --dsw-chart-3: color-mix(in srgb, #c46212 70%, white);\n --dsw-chart-4: color-mix(in srgb, #975bf1 70%, white);\n --dsw-chart-5: color-mix(in srgb, #d34591 70%, white);\n --dsw-chart-6: color-mix(in srgb, #0d8a8a 70%, white);\n --dsw-chart-7: color-mix(in srgb, #b3341f 70%, white);\n --dsw-chart-8: color-mix(in srgb, #7a9018 70%, white);\n --dsw-chart-9: color-mix(in srgb, #4b3fd0 70%, white);\n --dsw-chart-10: color-mix(in srgb, #d4a017 70%, white);\n --dsw-chart-other: color-mix(in srgb, #576270 70%, white);\n /* Provider series: a separate five-hue set for the provider section, so a\n provider never wears a model's colour. */\n --dsw-provider-1: color-mix(in srgb, #1f7a8c 70%, white);\n --dsw-provider-2: color-mix(in srgb, #6a8e3a 70%, white);\n --dsw-provider-3: color-mix(in srgb, #a15c2f 70%, white);\n --dsw-provider-4: color-mix(in srgb, #7b5ea7 70%, white);\n --dsw-provider-5: color-mix(in srgb, #b03a5b 70%, white);\n --dsw-provider-other: color-mix(in srgb, #576270 70%, white);\n}\n\n/* Dark variant: the same reasonix hues under a thicker white veil\n (35% — dark surfaces need the extra lift), so segments read soft and\n bright instead of sinking into the background. */\n@media (prefers-color-scheme: dark) {\n :root, .panel_768838850 {\n --dsw-heat-0: #1b211e;\n --dsw-heat-1: #123a2a;\n --dsw-heat-2: #17553a;\n --dsw-heat-3: #1c7a4e;\n --dsw-heat-4: #2fbf7c;\n --dsw-heat-5: #7ef0b4;\n --dsw-trend-line: #7d95ff;\n /* Dark tones are lifted versions of the light six: same identity hue,\n brighter so 16% badge tints and 3px bars read on dark surfaces. */\n --dsw-tone-1: #7d95ff;\n --dsw-tone-2: #2fbf7c;\n --dsw-tone-3: #e89a5c;\n --dsw-tone-4: #b18cff;\n --dsw-tone-5: #3bc5c5;\n --dsw-tone-6: #f076ac;\n --dsw-rank-top: #e08543;\n --dsw-chart-1: color-mix(in srgb, #0576ff 65%, white);\n --dsw-chart-2: color-mix(in srgb, #2f6f37 65%, white);\n --dsw-chart-3: color-mix(in srgb, #c46212 65%, white);\n --dsw-chart-4: color-mix(in srgb, #975bf1 65%, white);\n --dsw-chart-5: color-mix(in srgb, #d34591 65%, white);\n --dsw-chart-6: color-mix(in srgb, #0d8a8a 65%, white);\n --dsw-chart-7: color-mix(in srgb, #b3341f 65%, white);\n --dsw-chart-8: color-mix(in srgb, #7a9018 65%, white);\n --dsw-chart-9: color-mix(in srgb, #4b3fd0 65%, white);\n --dsw-chart-10: color-mix(in srgb, #d4a017 65%, white);\n --dsw-chart-other: color-mix(in srgb, #576270 65%, white);\n --dsw-provider-1: color-mix(in srgb, #1f7a8c 65%, white);\n --dsw-provider-2: color-mix(in srgb, #6a8e3a 65%, white);\n --dsw-provider-3: color-mix(in srgb, #a15c2f 65%, white);\n --dsw-provider-4: color-mix(in srgb, #7b5ea7 65%, white);\n --dsw-provider-5: color-mix(in srgb, #b03a5b 65%, white);\n --dsw-provider-other: color-mix(in srgb, #576270 65%, white);\n }\n\n /* Dark surfaces swallow pale tints, so the card accents step up: badge\n 12% → 16%, corner wash 7% → 10%. */\n .cardIcon_768838850 {\n background: color-mix(in srgb, var(--card-accent) 16%, transparent);\n }\n\n .card_768838850::after {\n background: linear-gradient(135deg, color-mix(in srgb, var(--card-accent) 10%, transparent), transparent 60%);\n }\n}\n";
29431
- const tagId$2 = "dsh-token-total/TokenTotalPanel.module.css";
29432
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"" + tagId$2 + "\"]") === null) {
29435
+ const css$3 = "/**\n * Usage statistics panel styles — a DSH-native CSS Module. Every visual\n * value rides the DSH semantic tokens (--dsw-alias-* colors, --dsw-font-*\n * typography, --ds-* motion); no static palette values, no theme selectors.\n * The heatmap's 5 levels come from the brand accent via color-mix; model\n * colours are the fixed --dsw-chart-1..5 series (rank order by token\n * volume) plus the gray --dsw-chart-other step — the reasonix token-total\n * palette, with a lifted dark variant defined below.\n */\n\n/* The panel as a standalone main panel. It gets the same 960px content column\n the Plugins page gives it — the declarations below mirror the Plugins page's\n own `.page_768838850` so both entries render identically. Without the cap the charts\n would stretch to whatever the centre column happens to be.\n\n One deliberate difference from that page: its 28px top inset is NOT part of\n this container. A main panel starts at the window's top-left corner, so an\n inset painted by this scrolling container is a strip above the content that\n no window-drag region covers; `.backRow_768838850` below owns the inset instead, which\n is the shape the shipped page plugins use for the same reason\n (`ui-plugin-manager`'s `.pageHead_768838850`/`.detailTop_768838850` and `ui-schedule`'s page\n head). The rendered position is unchanged. */\n.page_768838850 {\n display: flex;\n flex-direction: column;\n align-items: center;\n box-sizing: border-box;\n height: 100%;\n overflow: auto;\n padding: 0 clamp(24px, 4vw, 48px) 48px;\n color: var(--dsw-alias-label-primary);\n}\n\n.page_768838850 > * {\n width: 100%;\n max-width: 960px;\n}\n\n/* The standalone panel's back control. Only the main panel renders this seat —\n the Plugins page entry already sits inside the page's own chrome, which\n draws its own crumb back to the bundle list. The spacing matches the gap the\n panel keeps between its own sections.\n\n The row also carries the panel's former 28px top inset: it starts at the\n window's top edge, so the whole strip above the back control drags the\n window (Electron app-regions are geometry, not stacking, so a strip owned by\n the scrolling container would subtract itself from the drag row beneath\n it). */\n.backRow_768838850 {\n display: flex;\n box-sizing: border-box;\n padding-top: 28px;\n margin-bottom: 18px;\n}\n\n.back_768838850 {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.panel_768838850 {\n display: flex;\n flex-direction: column;\n gap: 18px;\n min-width: 0;\n}\n\n/* ── toolbar ───────────────────────────────────────────────────────────── */\n\n.toolbar_768838850 {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 10px;\n}\n\n/* Each picker (time range) lives in a framed group. */\n.group_768838850 {\n display: inline-flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 2px;\n padding: 3px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 9px;\n background: var(--dsw-alias-bg-layer-1);\n}\n\n/* A range-preset chip: ghost Button inside the group, active state tinted\n with the brand accent (same blue as the section bars and the total card). */\n.segItem_768838850 {\n border-radius: 6px;\n}\n\n.segItem_768838850:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.segActive_768838850,\n.segActive_768838850:hover:not(:disabled) {\n background: color-mix(in srgb, var(--dsw-tone-1) 14%, transparent);\n color: var(--dsw-tone-1);\n font-weight: 600;\n}\n\n.customRange_768838850 {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.dateInput_768838850 {\n width: 150px;\n flex: 0 0 auto;\n}\n\n.customSep_768838850 {\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* Trailing toolbar edge: the \"as of\" stamp sits immediately left of the\n refresh action (it stamps the very data that button refreshes). */\n.toolbarEnd_768838850 {\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n gap: 10px;\n}\n\n.asOf_768838850 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n white-space: nowrap;\n}\n\n/* Keep the remaining toolbar action at the trailing edge. */\n.refresh_768838850 {\n flex: 0 0 auto;\n}\n\n/* ── states ────────────────────────────────────────────────────────────── */\n\n.errorBanner_768838850 {\n padding: 10px 14px;\n border: 1px solid var(--dsw-alias-state-warn-primary);\n border-radius: 8px;\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 12%, transparent);\n color: var(--dsw-alias-state-warn-label);\n font-size: 13px;\n}\n\n.loading_768838850 {\n padding: 24px;\n text-align: center;\n color: var(--dsw-alias-label-tertiary);\n font-size: 13px;\n}\n\n.empty_768838850 {\n padding: 24px;\n text-align: center;\n color: var(--dsw-alias-label-tertiary);\n font-size: 13px;\n border: 1px dashed var(--dsw-alias-border-l2);\n border-radius: 8px;\n}\n\n/* ── numeric cards ─────────────────────────────────────────────────────── */\n\n/* Six equal tracks: the overview row is one grid of six identical cards\n (long value or not), so no card crowds its neighbours. At the Plugins\n page's 960px content width that is six columns on one row. */\n.cards_768838850 {\n display: grid;\n grid-template-columns: repeat(6, minmax(0, 1fr));\n gap: 10px;\n}\n\n/* Below the width where six cards hold their own, the grid folds to three\n columns (two rows of three), then to two (three rows of two). */\n@media (max-width: 720px) {\n .cards_768838850 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n}\n\n@media (max-width: 430px) {\n .cards_768838850 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n}\n\n/* Each stat card wears one accent hue (tone 1..6 → --dsw-tone-1..6): a 3px\n accent bar on the left edge, the icon in a tinted badge, and a whisper of\n the hue washing the top-left corner — the overview row reads in colour\n instead of one gray register. --card-accent is set by the .cardToneN_768838850 map\n below; content sits above the wash via a z-index layer. */\n.card_768838850 {\n --card-accent: var(--dsw-alias-label-tertiary);\n position: relative;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 14px 14px 12px 18px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-1);\n box-shadow: 0 1px 2px var(--dsw-alias-bg-mask-2);\n min-width: 0;\n}\n\n.card_768838850::before {\n content: \"\";\n position: absolute;\n left: 0;\n top: 12px;\n bottom: 12px;\n width: 3px;\n border-radius: 0 3px 3px 0;\n background: var(--card-accent);\n}\n\n.card_768838850::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background: linear-gradient(135deg, color-mix(in srgb, var(--card-accent) 7%, transparent), transparent 60%);\n pointer-events: none;\n}\n\n/* Content must paint above the corner wash (the ::after pseudo is the last\n child, so it wins a same-layer paint order). */\n.card_768838850 > * {\n position: relative;\n z-index: 1;\n}\n\n.cardTone1_768838850 { --card-accent: var(--dsw-tone-1); }\n.cardTone2_768838850 { --card-accent: var(--dsw-tone-2); }\n.cardTone3_768838850 { --card-accent: var(--dsw-tone-3); }\n.cardTone4_768838850 { --card-accent: var(--dsw-tone-4); }\n.cardTone5_768838850 { --card-accent: var(--dsw-tone-5); }\n.cardTone6_768838850 { --card-accent: var(--dsw-tone-6); }\n\n.cardHead_768838850 {\n display: flex;\n align-items: center;\n gap: 7px;\n}\n\n/* Icon badge: the accent hue at 12% behind its own glyph. */\n.cardIcon_768838850 {\n box-sizing: border-box;\n width: 24px;\n height: 24px;\n padding: 5px;\n border-radius: 7px;\n color: var(--card-accent);\n background: color-mix(in srgb, var(--card-accent) 12%, transparent);\n flex: 0 0 auto;\n}\n\n.cardLabel_768838850 {\n color: var(--dsw-alias-label-secondary);\n font-size: 13px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Values never wrap: a wrapped number defeats FitText's measurement (the\n wrapped line is exactly as wide as its box) and reads as a layout break.\n Oversized text shrinks instead — see FitText in TokenTotalPanel.tsx_768838850. */\n.cardValue_768838850 {\n color: var(--dsw-alias-label-primary);\n font-weight: 600;\n line-height: 1.15;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.cardValueSm_768838850 {\n font-size: 14px;\n}\n\n.cardValueWrap_768838850 {\n word-break: break-word;\n}\n\n/* The \"most used model\" card value: the model name over the provider, the\n same two-line anatomy as the per-model list rows (modelName/modelProvider\n classes), instead of the raw \"provider/model\" ref. */\n.cardModelLines_768838850 {\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n\n/* A muted second line under a card value (the absolute cached-token volume\n under the hit-rate percentage). Same no-wrap rule as the value above. */\n.cardSub_768838850 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 1.2;\n white-space: nowrap;\n overflow: hidden;\n}\n\n/* ── sections / chart chrome ───────────────────────────────────────────── */\n\n.section_768838850 {\n display: flex;\n flex-direction: column;\n gap: 12px;\n min-width: 0;\n padding: 14px 16px 16px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-1);\n box-shadow: 0 1px 2px var(--dsw-alias-bg-mask-2);\n}\n\n.sectionHead_768838850 {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n/* Section titles carry the same brand accent bar as the stat cards' tone\n language, so every card heading is anchored the same way. */\n.sectionTitle_768838850 {\n margin: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 15px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n.sectionTitle_768838850::before {\n content: \"\";\n width: 3px;\n height: 13px;\n border-radius: 2px;\n background: var(--dsw-tone-1);\n flex: 0 0 auto;\n}\n\n/* Header meta cluster right of a section title (trend cap note + curve\n legend). Kept as one wrap-friendly row on a common baseline. */\n.headMeta_768838850 {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n font-size: 12px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.trendNote_768838850 {\n font-size: 13px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* Heatmap and the token trend share ONE row — one card each, left and right.\n Both columns stretch to a common height; the heatmap centres its SVG in the\n taller partner. Below 720px the pair folds to a single column. */\n.duo_768838850 {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n gap: 12px;\n align-items: stretch;\n}\n\n@media (max-width: 720px) {\n .duo_768838850 {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n.chartWrap_768838850 {\n position: relative;\n min-width: 0;\n}\n\n/* ── heatmap ───────────────────────────────────────────────────────────── */\n\n.heatWrap_768838850 {\n position: relative;\n /* hidden, not auto: the SVG now fills the container exactly, and an\n auto scrollbar would flash when a fixed tooltip passes over the wrap's\n right edge. */\n overflow: hidden;\n min-width: 0;\n /* In the duo row the heatmap card shares height with the trend card; the\n grid centres itself in whatever slack the partner leaves. */\n flex: 1 1 auto;\n display: flex;\n align-items: center;\n}\n\n.heatmap_768838850 {\n display: block;\n margin: 0 auto;\n /* The ~364 day cells are flat SVG rects (no per-cell filter), so there is no\n blur chain left to re-rasterize — but promoting the SVG onto its own\n compositing layer still keeps the whole grid off the scroll repaint path,\n which is what made scrolling this panel drop frames while idle was clean\n (#4). Cheap and invisible, so it stays. Note that the promotion is what\n does the work: `contain: paint` on its own measured no better than no\n mitigation at all. */\n transform: translateZ(0);\n}\n\n.heatLegend_768838850 {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 13px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* Axis labels drawn inside the heatmap SVG: the weekday column on the left and\n the month strip along the bottom. SVG <text> takes `fill`, not `color`. */\n.heatAxis_768838850 {\n fill: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n}\n\n.heatCell_768838850 {\n display: inline-block;\n border-radius: 2px;\n /* No width/height here: the SVG cells carry their size as geometry\n attributes (x/y/width/height), and a CSS width/height would override\n those on SVG2 rects — pinning every cell to a fixed px and widening the\n visual gap. The legend swatches carry the same size inline, so both\n always match the measured geom.size_768838850.\n No filter either: the reference chart paints each tile as a flat, matte\n rounded square, so a sheen/under-shadow would read as a smudge at this\n cell size rather than depth. */\n}\n\n/* The five heat levels ride a fixed emerald ramp sampled pixel-for-pixel from\n the reference chart (a GitHub-style green scale), with a darker variant for\n dark mode below — never the theme accent, which can read near-black against\n the base surface in dark mode. level0 (no data) is a neutral empty cell.\n The fills are fully opaque: the reference tiles are solid, and mixing toward\n transparent (the previous glass treatment) lightened every step and broke\n the sampled ramp. The cells are SVG <rect>s, so the color rides `fill`\n (background is a no-op on SVG geometry) — but the legend swatches are HTML,\n so both declarations stay in step. */\n.heatLevel0_768838850 {\n fill: var(--dsw-heat-0);\n background: var(--dsw-heat-0);\n}\n\n.heatLevel1_768838850 {\n fill: var(--dsw-heat-1);\n background: var(--dsw-heat-1);\n}\n\n.heatLevel2_768838850 {\n fill: var(--dsw-heat-2);\n background: var(--dsw-heat-2);\n}\n\n.heatLevel3_768838850 {\n fill: var(--dsw-heat-3);\n background: var(--dsw-heat-3);\n}\n\n.heatLevel4_768838850 {\n fill: var(--dsw-heat-4);\n background: var(--dsw-heat-4);\n}\n\n.heatLevel5_768838850 {\n fill: var(--dsw-heat-5);\n background: var(--dsw-heat-5);\n}\n\n/* ── daily trend ───────────────────────────────────────────────────────── */\n\n.chart_768838850 {\n display: block;\n}\n\n.grid_768838850 {\n stroke: var(--dsw-alias-border-l1);\n stroke-width: 1;\n}\n\n.axis_768838850 {\n fill: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n\n.axisRate_768838850 {\n fill: var(--dsw-alias-label-tertiary);\n}\n\n.bar_768838850 {\n transition: opacity 0.12s ease;\n /* The hover scaleX must pivot on the bar's own centre: SVG geometry\n transforms around the SVG origin unless transform-box anchors it to the\n element's fill box. Without this the scaled bar slides sideways and\n looks like it vanishes. */\n transform-box: fill-box;\n transform-origin: center;\n}\n\n.barDim_768838850 {\n opacity: 0.35;\n}\n\n.barHit_768838850 {\n fill: transparent;\n pointer-events: all;\n}\n\n/* cache hit-rate trend curve: DeepSeek's brand blue (#4D6BFE, the same hue\n family as the heatmap ramp) — a fixed brand ramp instead of the theme\n accent, which can read near-black in some themes. */\n.trend_768838850 {\n stroke: var(--dsw-trend-line);\n stroke-width: 2;\n opacity: 0.9;\n pointer-events: none;\n}\n\n.trendDot_768838850 {\n fill: var(--dsw-trend-line);\n stroke: var(--dsw-alias-bg-layer-1);\n stroke-width: 2;\n pointer-events: none;\n}\n\n.legend_768838850 {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 13px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.legendItem_768838850 {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n cursor: default;\n}\n\n.legendSwatch_768838850 {\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: 2px;\n}\n\n.legendTrend_768838850 {\n background: var(--dsw-trend-line);\n width: 14px;\n height: 3px;\n border-radius: 2px;\n}\n\n/* ── per-model / per-provider chart + list ─────────────────────────────── */\n\n/* The ring is centred against the list beside it. The list's height is never\n tied to the chart, so expanding a row cannot stretch anything. */\n.models_768838850 {\n display: flex;\n gap: 16px;\n align-items: center;\n flex-wrap: wrap;\n min-width: 0;\n}\n\n/* The ring's own wrapper. Its diameter comes from the measured row width (see\n Donut.tsx_768838850), so it must never flex. */\n.donutWrap_768838850 {\n position: relative;\n flex: 0 0 auto;\n}\n\n.donut_768838850 {\n display: block;\n}\n\n.donutTrack_768838850 {\n stroke: var(--dsw-alias-bg-mask-1);\n}\n\n.donutSeg_768838850 {\n transition: stroke-width 0.12s ease, opacity 0.12s ease;\n}\n\n.donutDim_768838850 {\n opacity: 0.35;\n}\n\n.donutCenter_768838850 {\n fill: var(--dsw-alias-label-primary);\n font-size: 18px;\n font-weight: 600;\n}\n\n.donutLabel_768838850 {\n fill: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n/* Two ranking cards, side by side: MODELS left, PROVIDERS right. Both are\n always on screen (no lens/tab switch), so they share one row grid and\n stretch to a common height; a narrow pane stacks them instead. */\n.rankCards_768838850 {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 12px;\n}\n\n@media (max-width: 720px) {\n .rankCards_768838850 {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n/* Each card is the bordered surface its rows live in; the title is a recessed\n header strip, so the two rankings read as two equal panels. */\n.rankCard_768838850 {\n display: flex;\n flex-direction: column;\n min-width: 0;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-1);\n overflow: hidden;\n}\n\n.rankCardTitle_768838850 {\n padding: 8px 12px;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 55%, transparent);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n font-weight: 600;\n}\n\n.rankList_768838850 {\n list-style: none;\n margin: 0;\n padding: 0;\n flex: 1 1 auto;\n min-width: 0;\n}\n\n/* Every row opens a hover tip (the cross-dimension detail), so it carries the\n same hover affordance as the chart marks. */\n.modelRow_768838850:hover {\n background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 60%, transparent);\n}\n\n/* Position column: the row's rank inside its section. The Other bucket holds\n no single rank, so it renders an empty (but equally wide) cell. */\n.modelRank_768838850 {\n flex: 0 0 auto;\n min-width: 14px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n text-align: right;\n}\n\n.modelRow_768838850 {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n font-size: 13px;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n}\n\n.modelRow_768838850:last-child {\n border-bottom: none;\n}\n\n/* Share bar under a rank row's name: the row's slice of the section total,\n drawn in the row's own colour (a 3px track, like the design mock). */\n.rowTrack_768838850 {\n height: 3px;\n margin-top: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-border-l1);\n overflow: hidden;\n}\n\n.rowFill_768838850 {\n display: block;\n height: 3px;\n border-radius: 2px;\n}\n\n/* Top-3 ranks read as a podium: the ordinal takes the warm accent instead of\n the muted gray the tail ranks keep. */\n.rankList_768838850 > .modelRow_768838850:nth-child(-n + 3) .modelRank_768838850 {\n color: var(--dsw-rank-top);\n font-weight: 700;\n}\n\n/* \"Other\" aggregate row: the entire row is clickable to expand/collapse the\n detail list. The chevron button inside it stops propagation so\n double-firing is avoided. */\n.modelRowExpandable_768838850 {\n cursor: pointer;\n}\n\n/* \"Other\" row toggle (chevron) that expands the aggregated tail models. */\n.modelToggle_768838850 {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n margin-right: 4px;\n border: none;\n background: none;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n vertical-align: middle;\n}\n\n/* Expanded detail rows: indented, slightly recessed. */\n.modelRowSub_768838850 {\n padding-left: 28px;\n background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 55%, transparent);\n font-size: 13px;\n}\n\n/* Second-level indent: a model row inside a provider that is itself folded\n into the Other bucket. Wider than .modelRowSub_768838850 so the nesting stays\n readable. Declared after it — same specificity, so this one wins. */\n.modelRowDeep_768838850 {\n padding-left: 48px;\n}\n\n/* \"Other\" details expand with an accordion: the wrapper is a grid whose\n single track animates 0fr → 1fr. */\n.modelOtherWrap_768838850 {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows 0.25s ease;\n}\n\n.modelOtherOpen_768838850 {\n grid-template-rows: 1fr;\n}\n\n.modelOtherList_768838850 {\n overflow: hidden;\n min-height: 0;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n/* Two-line row anatomy: [swatch] [name / provider] ……… [tokens / share].\n The name block takes the free width; the values block hugs the right. */\n.modelId_768838850 {\n display: flex;\n flex-direction: column;\n gap: 1px;\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.modelValues_768838850 {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 1px;\n flex: 0 0 auto;\n}\n\n.modelName_768838850 {\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n}\n\n.modelProvider_768838850 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.modelTokens_768838850 {\n color: var(--dsw-alias-label-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n.modelPct_768838850 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n}\n\n/* ── tooltips ──────────────────────────────────────────────────────────── */\n\n/* Tooltips render as fixed-position portals on document.body_768838850 (see ChartTip),\n so they escape every ancestor's clipping and never overflow the settings\n panel: ChartTip clamps each tip inside the panel bounds and flips it above\n the hovered element when there is no room below. The plate follows the\n active theme: the DSH overlay token is a light gray in light mode and a\n dark gray under body[data-ds-dark-theme], so the tip reads correctly in\n both instead of staying dark in light mode. */\n.tip_768838850 {\n position: fixed;\n /* The tip is portaled to document.body_768838850, so it competes with the settings\n modal itself (z-index 1000) for the top layer: 100 would sit under the\n modal and the tip would be invisible. 1100 matches the official\n toast/portaled-menu layer, which is exactly the \"over a modal\" tier. */\n z-index: 1100;\n pointer-events: none;\n padding: 8px 10px;\n border-radius: 8px;\n background: var(--dsw-alias-bg-overlay);\n border: 1px solid var(--dsw-alias-border-l2);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n box-shadow: 0 2px 12px var(--dsw-alias-bg-mask-2);\n white-space: nowrap;\n}\n\n.tipTitle_768838850 {\n font-weight: 600;\n margin-bottom: 4px;\n}\n\n/* A provider row's raw route id, kept out of the row label but reachable on\n hover (the row shows the display name). */\n.tipSubtitle_768838850 {\n margin: -2px 0 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n}\n\n/* Breakdown heading inside a row tip: names the cross-dimension list under it\n (\"By provider\" under a model, \"By model\" under a provider). */\n.tipLabel_768838850 {\n margin-bottom: 2px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n}\n\n/* The breakdown line pushes its volume to the right edge of the plate. */\n.tipName_768838850 {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.tipValue_768838850 {\n margin-left: auto;\n padding-left: 12px;\n color: var(--dsw-alias-label-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n.tipRow_768838850 {\n display: flex;\n align-items: center;\n gap: 5px;\n}\n\n/* Hover tooltip breakdown rows for the \"Other\" aggregate: indented, muted,\n same gray swatch as the Other step. */\n.tipRowOther_768838850 {\n padding-left: 8px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.tipBreakdown_768838850 {\n border-top: 1px solid var(--dsw-alias-border-l1);\n margin-top: 4px;\n padding-top: 4px;\n}\n\n/* ── chart palette ──────────────────────────────────────────────────────── */\n\n/* Light variant (the theme's default): model colours are the reasonix\n token-total palette (rank order by token volume + gray Other) with a\n white veil mixed in (color-mix 30% white) — the raw hues read dark and\n heavy on the light card surface, and the veil lifts lightness and dulls\n saturation the way a translucent white overlay would, keeping the hues\n colourful instead of muddy. The heatmap ramp is a fixed emerald green\n scale (GitHub-style activity heatmap), stepping from a near-white tint to\n a deep green; the hit-rate curve rides the brand blue.\n Ranks 6-10 extend the reasonix five to ten (this plugin's addition): each\n is picked to keep the ten hues apart on both themes.\n The palette must ALSO live on :root: tooltips are fixed portals on\n document.body_768838850 (see ChartTip), outside the panel subtree, and the inline\n var(--dsw-chart-N) swatches they carry only resolve from :root. */\n:root, .panel_768838850 {\n --dsw-heat-0: #f4f5f5;\n --dsw-heat-1: #daf6ea;\n --dsw-heat-2: #c7f0df;\n --dsw-heat-3: #82edc0;\n --dsw-heat-4: #00b96b;\n --dsw-heat-5: #00663b;\n --dsw-trend-line: #4d6bfe;\n /* Overview-card tone accents (stat cards 1..6) and the podium ordinal.\n Six hues, each picked to sit apart from both the chart set and the heat\n ramp, at full strength so 12% badge tints stay visible on white. */\n --dsw-tone-1: #4d6bfe;\n --dsw-tone-2: #00b96b;\n --dsw-tone-3: #e07b39;\n --dsw-tone-4: #975bf1;\n --dsw-tone-5: #0d8a8a;\n --dsw-tone-6: #d34591;\n --dsw-rank-top: #c46212;\n --dsw-chart-1: color-mix(in srgb, #0576ff 70%, white);\n --dsw-chart-2: color-mix(in srgb, #2f6f37 70%, white);\n --dsw-chart-3: color-mix(in srgb, #c46212 70%, white);\n --dsw-chart-4: color-mix(in srgb, #975bf1 70%, white);\n --dsw-chart-5: color-mix(in srgb, #d34591 70%, white);\n --dsw-chart-6: color-mix(in srgb, #0d8a8a 70%, white);\n --dsw-chart-7: color-mix(in srgb, #b3341f 70%, white);\n --dsw-chart-8: color-mix(in srgb, #7a9018 70%, white);\n --dsw-chart-9: color-mix(in srgb, #4b3fd0 70%, white);\n --dsw-chart-10: color-mix(in srgb, #d4a017 70%, white);\n --dsw-chart-other: color-mix(in srgb, #576270 70%, white);\n /* Provider series: a separate five-hue set for the provider section, so a\n provider never wears a model's colour. */\n --dsw-provider-1: color-mix(in srgb, #1f7a8c 70%, white);\n --dsw-provider-2: color-mix(in srgb, #6a8e3a 70%, white);\n --dsw-provider-3: color-mix(in srgb, #a15c2f 70%, white);\n --dsw-provider-4: color-mix(in srgb, #7b5ea7 70%, white);\n --dsw-provider-5: color-mix(in srgb, #b03a5b 70%, white);\n --dsw-provider-other: color-mix(in srgb, #576270 70%, white);\n}\n\n/* Dark variant: the same reasonix hues under a thicker white veil\n (35% — dark surfaces need the extra lift), so segments read soft and\n bright instead of sinking into the background. */\n@media (prefers-color-scheme: dark) {\n :root, .panel_768838850 {\n --dsw-heat-0: #1b211e;\n --dsw-heat-1: #123a2a;\n --dsw-heat-2: #17553a;\n --dsw-heat-3: #1c7a4e;\n --dsw-heat-4: #2fbf7c;\n --dsw-heat-5: #7ef0b4;\n --dsw-trend-line: #7d95ff;\n /* Dark tones are lifted versions of the light six: same identity hue,\n brighter so 16% badge tints and 3px bars read on dark surfaces. */\n --dsw-tone-1: #7d95ff;\n --dsw-tone-2: #2fbf7c;\n --dsw-tone-3: #e89a5c;\n --dsw-tone-4: #b18cff;\n --dsw-tone-5: #3bc5c5;\n --dsw-tone-6: #f076ac;\n --dsw-rank-top: #e08543;\n --dsw-chart-1: color-mix(in srgb, #0576ff 65%, white);\n --dsw-chart-2: color-mix(in srgb, #2f6f37 65%, white);\n --dsw-chart-3: color-mix(in srgb, #c46212 65%, white);\n --dsw-chart-4: color-mix(in srgb, #975bf1 65%, white);\n --dsw-chart-5: color-mix(in srgb, #d34591 65%, white);\n --dsw-chart-6: color-mix(in srgb, #0d8a8a 65%, white);\n --dsw-chart-7: color-mix(in srgb, #b3341f 65%, white);\n --dsw-chart-8: color-mix(in srgb, #7a9018 65%, white);\n --dsw-chart-9: color-mix(in srgb, #4b3fd0 65%, white);\n --dsw-chart-10: color-mix(in srgb, #d4a017 65%, white);\n --dsw-chart-other: color-mix(in srgb, #576270 65%, white);\n --dsw-provider-1: color-mix(in srgb, #1f7a8c 65%, white);\n --dsw-provider-2: color-mix(in srgb, #6a8e3a 65%, white);\n --dsw-provider-3: color-mix(in srgb, #a15c2f 65%, white);\n --dsw-provider-4: color-mix(in srgb, #7b5ea7 65%, white);\n --dsw-provider-5: color-mix(in srgb, #b03a5b 65%, white);\n --dsw-provider-other: color-mix(in srgb, #576270 65%, white);\n }\n\n /* Dark surfaces swallow pale tints, so the card accents step up: badge\n 12% → 16%, corner wash 7% → 10%. */\n .cardIcon_768838850 {\n background: color-mix(in srgb, var(--card-accent) 16%, transparent);\n }\n\n .card_768838850::after {\n background: linear-gradient(135deg, color-mix(in srgb, var(--card-accent) 10%, transparent), transparent 60%);\n }\n}\n";
29436
+ const tagId$3 = "dsh-token-total/TokenTotalPanel.module.css";
29437
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"" + tagId$3 + "\"]") === null) {
29433
29438
  const tag = document.createElement("style");
29434
29439
  tag.dataset.plugin = "dsh-token-total";
29435
- tag.dataset.pluginCss = tagId$2;
29436
- tag.textContent = css$2;
29440
+ tag.dataset.pluginCss = tagId$3;
29441
+ tag.textContent = css$3;
29437
29442
  document.head.appendChild(tag);
29438
29443
  }
29439
29444
  var TokenTotalPanel_module_default = {
@@ -29645,6 +29650,13 @@ window.__ModuleLoader__.load({
29645
29650
  }
29646
29651
  return out;
29647
29652
  }
29653
+ /** Canonicalize a DISPLAY NAME, never a route id. Case and word separators
29654
+ * do not distinguish models, but versions, punctuation and suffixes do:
29655
+ * gpt-6.1-sol / GPT 6.1 sol -> gpt-6.1-sol, not gpt-6.1 or gpt-61-sol.
29656
+ * Do not strip a slash here: it may be part of the actual display name. */
29657
+ function normalizeModelName(displayName) {
29658
+ return displayName.normalize("NFKC").trim().toLowerCase().replace(/[\s_\p{Dash_Punctuation}]+/gu, "-").replace(/^-+|-+$/g, "") || "(unknown)";
29659
+ }
29648
29660
  //#endregion
29649
29661
  //#region src/client/format.ts
29650
29662
  /** Exact token counts with thousands separators — no 万/亿/k/M units, the
@@ -29686,7 +29698,7 @@ window.__ModuleLoader__.load({
29686
29698
  return ((/* @__PURE__ */ new Date(day + "T00:00:00")).getDay() + 6) % 7;
29687
29699
  }
29688
29700
  function shortDay(day) {
29689
- const parts = day.split("-");
29701
+ const parts = day.slice(0, 10).split("-");
29690
29702
  const m = parts[1];
29691
29703
  const d = parts[2];
29692
29704
  return `${Number(m)}/${Number(d)}`;
@@ -30439,15 +30451,23 @@ window.__ModuleLoader__.load({
30439
30451
  const dayCount = new Set(visible.map((d) => d.day.slice(0, 10))).size;
30440
30452
  const multiDayHourly = granularity === "hour" && dayCount > 1;
30441
30453
  const axisMode = multiDayHourly ? "day" : granularity;
30442
- const labelCandidates = [];
30443
- for (let i = 0; i < n; i++) if (!multiDayHourly || i === 0 || visible[i].day.slice(0, 10) !== visible[i - 1].day.slice(0, 10)) labelCandidates.push(i);
30454
+ const labelGroups = [];
30455
+ for (let i = 0; i < n; i++) {
30456
+ const last = labelGroups[labelGroups.length - 1];
30457
+ if (multiDayHourly && last && visible[last.end].day.slice(0, 10) === visible[i].day.slice(0, 10)) last.end = i;
30458
+ else labelGroups.push({
30459
+ start: i,
30460
+ end: i
30461
+ });
30462
+ }
30444
30463
  const labelMinGap = 42;
30445
- const labeledIdx = /* @__PURE__ */ new Set();
30464
+ const labeledGroups = /* @__PURE__ */ new Set();
30446
30465
  let lastLabelX = Number.POSITIVE_INFINITY;
30447
- for (let k = labelCandidates.length - 1; k >= 0; k--) {
30448
- const x = padL + barHalf + labelCandidates[k] * step;
30466
+ for (let k = labelGroups.length - 1; k >= 0; k--) {
30467
+ const g = labelGroups[k];
30468
+ const x = padL + barHalf + (g.start + g.end) / 2 * step;
30449
30469
  if (lastLabelX - x >= labelMinGap) {
30450
- labeledIdx.add(labelCandidates[k]);
30470
+ labeledGroups.add(k);
30451
30471
  lastLabelX = x;
30452
30472
  }
30453
30473
  }
@@ -30542,44 +30562,41 @@ window.__ModuleLoader__.load({
30542
30562
  };
30543
30563
  });
30544
30564
  const hovered = tip?.day === d.day;
30545
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", { children: [
30546
- bars.map((b) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
30547
- className: clsx(TokenTotalPanel_module_default.bar, b.dimmed && TokenTotalPanel_module_default.barDim),
30548
- x: b.x,
30549
- y: b.y,
30550
- width: barW,
30551
- height: b.h,
30552
- fill: b.color,
30553
- style: hovered ? { transform: `scaleX(${(barW + 3) / barW})` } : void 0
30554
- }, `${d.day}-${b.model}`)),
30555
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
30556
- className: TokenTotalPanel_module_default.barHit,
30557
- x,
30558
- y: padT,
30559
- width: barW,
30560
- height: plotH,
30561
- onMouseEnter: (e) => {
30562
- setTip({
30563
- day: d.day,
30564
- total: d.total,
30565
- byModel: d.byModel,
30566
- otherByModel: d.otherByModel,
30567
- cacheHit: d.cacheHit,
30568
- cacheMiss: d.cacheMiss,
30569
- anchor: e.currentTarget
30570
- });
30571
- },
30572
- onMouseLeave: () => setTip(null)
30573
- }),
30574
- labeledIdx.has(i) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
30575
- className: TokenTotalPanel_module_default.axis,
30576
- x: padL + barHalf + i * step,
30577
- y: 212,
30578
- textAnchor: "middle",
30579
- children: bucketAxisLabel(d.day, axisMode)
30580
- })
30581
- ] }, d.day);
30565
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", { children: [bars.map((b) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
30566
+ className: clsx(TokenTotalPanel_module_default.bar, b.dimmed && TokenTotalPanel_module_default.barDim),
30567
+ x: b.x,
30568
+ y: b.y,
30569
+ width: barW,
30570
+ height: b.h,
30571
+ fill: b.color,
30572
+ style: hovered ? { transform: `scaleX(${(barW + 3) / barW})` } : void 0
30573
+ }, `${d.day}-${b.model}`)), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
30574
+ className: TokenTotalPanel_module_default.barHit,
30575
+ x,
30576
+ y: padT,
30577
+ width: barW,
30578
+ height: plotH,
30579
+ onMouseEnter: (e) => {
30580
+ setTip({
30581
+ day: d.day,
30582
+ total: d.total,
30583
+ byModel: d.byModel,
30584
+ otherByModel: d.otherByModel,
30585
+ cacheHit: d.cacheHit,
30586
+ cacheMiss: d.cacheMiss,
30587
+ anchor: e.currentTarget
30588
+ });
30589
+ },
30590
+ onMouseLeave: () => setTip(null)
30591
+ })] }, d.day);
30582
30592
  }),
30593
+ labelGroups.map((g, k) => labeledGroups.has(k) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
30594
+ className: TokenTotalPanel_module_default.axis,
30595
+ x: padL + barHalf + (g.start + g.end) / 2 * step,
30596
+ y: 212,
30597
+ textAnchor: "middle",
30598
+ children: bucketAxisLabel(visible[g.start].day, axisMode)
30599
+ }, `axis-${k}`)),
30583
30600
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
30584
30601
  className: TokenTotalPanel_module_default.trend,
30585
30602
  d: trendPath,
@@ -31500,6 +31517,11 @@ window.__ModuleLoader__.load({
31500
31517
  function billedTotal(totals) {
31501
31518
  return totals.uncachedInputTokens + totals.cacheReadTokens + totals.cacheWriteTokens + totals.outputTokens;
31502
31519
  }
31520
+ function cacheHitPercentOf(totals) {
31521
+ const hit = totals.cacheReadTokens;
31522
+ const miss = totals.uncachedInputTokens + totals.cacheWriteTokens;
31523
+ return hit + miss === 0 ? null : hit / (hit + miss) * 100;
31524
+ }
31503
31525
  //#endregion
31504
31526
  //#region src/client/use-session-usage.ts
31505
31527
  /** The composer row's window onto the whole session tree. The native usage
@@ -31554,13 +31576,13 @@ window.__ModuleLoader__.load({
31554
31576
  }
31555
31577
  //#endregion
31556
31578
  //#region \0token-total-css:/home/runner/work/dsh-token-total/dsh-token-total/src/client/StatsLineEnhanced.module.css?inline
31557
- const css$1 = "/* Session stats pills under the composer (shadow of the official StatsPills):\n a gauge pill (counts + output speed, click opens the time dialog) and a\n database pill (total tokens + cache hit, click opens the usage dialog).\n Replicated from the official StatsPills.module_348665330.css_348665330 + stat-dialog.module_348665330.css_348665330\n (13/20 tertiary tier, hover-pill affordance, shared dialog skin).\n\n Host contract: the row serves two containers at once, and picks between them\n at attach time — the component marks which one it landed in (see\n StatsLineEnhanced's `markDockContainer`):\n - through 0.1.6-alpha.1 the dock slot renders straight into InputBar's own\n column, and this row owns the content-width clamp, its side gutters and\n its 4px top pad — the official StatsPills.module_348665330.css_348665330 of that line;\n - 0.1.6-alpha.2 renders it inside InputBar's flex `.dock_348665330` beside the resident\n ContextMeter, which took all three jobs over, so the row only has to\n shrink inside it (the official stylesheet's current form).\n Both forms are kept side by side because one published build has to render\n correctly on either host line. */\n\n.root_348665330 {\n display: flex;\n justify-content: center;\n gap: 12px;\n box-sizing: border-box;\n /* <= 0.1.6-alpha.1: this row is the composer column's content-width box. */\n width: 100%;\n max-width: var(--dsh-chat-content-width);\n margin: 0 auto;\n padding: 4px calc(var(--dsh-composer-side-clearance) + 16px) 0px;\n font-size: var(--dsh-content-font-size-secondary, 13px);\n line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px));\n}\n\n/* 0.1.6-alpha.2+: InputBar's `.dock_348665330` owns the centring, the 12px gap, the top\n pad and the side clearance. */\n.root_348665330[data-dock-row] {\n width: auto;\n min-width: 0;\n max-width: 100%;\n margin: 0;\n padding: 0;\n}\n\n/* Dialog anchor: shrink-wraps its pill so the panel clamp measures the pill. */\n.anchor_348665330 {\n display: inline-flex;\n min-width: 0;\n}\n\n/* Split-mode anchor (DSH >= 0.2.1-alpha.1). The host split the single `stats`\n dock entry into one entry per pill and let its own `.dock_348665330` flex row own the\n layout, so the anchor IS the entry root and carries the text tier `.root_348665330`\n used to set — the official StatsPills.module_348665330.css_348665330 moved exactly this pair of\n declarations from `.root_348665330` onto `.anchor_348665330`. The tier stays off the plain\n `.anchor_348665330` because the pre-split row must keep its own `.root_348665330` tier. */\n.dockAnchor_348665330 {\n font-size: var(--dsh-content-font-size-secondary, 13px);\n line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px));\n}\n\n.pill_348665330 {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n box-sizing: border-box;\n max-width: 100%;\n padding: 1px 8px;\n border: none;\n border-radius: var(--dsw-radius-sm);\n background: none;\n color: var(--dsw-alias-label-tertiary);\n font: inherit;\n font-variant-numeric: tabular-nums;\n line-height: inherit;\n white-space: nowrap;\n}\n\n.pill_348665330 svg {\n width: 14px;\n height: 14px;\n flex: none;\n}\n\n/* Only the button form (a pill with dialog rows to open) invites interaction;\n the static span form keeps the resting tertiary reading. */\nbutton.pill_348665330 {\n cursor: pointer;\n}\n\nbutton.pill_348665330:hover,\nbutton.pill_348665330[aria-expanded='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.label_348665330 {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sep_348665330 {\n color: var(--dsw-alias-separator-primary);\n margin: 0 6px;\n}\n\n/* The live throughput reading sits inline exactly like the official figure:\n no reserved width, no box of its own. The earlier `min-width: 10ch` slot kept\n the centred row from shifting while the number grew, but it also left a\n permanent gap before the separator — the official pill has no such slot, and\n native parity wins over that jitter fix. */\n.speed_348665330 {\n display: inline;\n}\n\n/* Portal dialog surface: fixed in the viewport, left/top supplied inline from\n the anchored-position clamp (12px viewport margin, layers above overlays).\n Material = the official stat-dialog PAIRING, which dsh 0.1.7's menu\n redesign made mandatory: `--dsw-specific-menu` is translucent there\n (rgba 58%/45%), so the blur token must ride along — the 0.1.5-era recipe\n this file copied was a single opaque line, and a fill-only copy reads as\n bare transparency over the page (issue #6). */\n.dialogPanel_348665330 {\n position: fixed;\n z-index: 1100;\n box-sizing: border-box;\n width: max-content;\n min-width: min(300px, calc(100vw - 24px));\n max-width: min(440px, calc(100vw - 24px));\n padding: 12px;\n border: 0;\n border-radius: var(--dsw-radius-lg);\n background: var(--dsw-specific-menu);\n backdrop-filter: var(--dsw-menu-backdrop-filter);\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);\n box-shadow: var(--dsw-elevation-prominent);\n font-size: var(--dsh-content-font-size-secondary, 13px);\n line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px));\n color: var(--dsw-alias-label-secondary);\n cursor: default;\n}\n\n/* Dialog heading row: the section name left, the headline value right. */\n.dialogTitle_348665330 {\n display: flex;\n justify-content: space-between;\n gap: 16px;\n margin-bottom: 8px;\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n\n/* Rule under the heading, above its rows. */\n.dialogTitleRule_348665330 {\n margin-bottom: 8px;\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n.dialogTitleValue_348665330 {\n font-variant-numeric: tabular-nums;\n}\n\n/* Heading glyph seated left of the section name. */\n.dialogTitleLabel_348665330 {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n\n.dialogTitleLabel_348665330 svg {\n width: 14px;\n height: 14px;\n flex: none;\n}\n\n.dialogDetails_348665330 {\n display: grid;\n grid-template-columns: minmax(76px, auto) minmax(0, 1fr);\n gap: 4px 12px;\n margin: 0;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.dialogDetails_348665330 dt,\n.dialogDetails_348665330 dd {\n min-width: 0;\n margin: 0;\n}\n\n.dialogDetails_348665330 dd {\n color: var(--dsw-alias-label-secondary);\n font-variant-numeric: tabular-nums;\n text-align: right;\n}\n";
31558
- const tagId$1 = "dsh-token-total/StatsLineEnhanced.module.css";
31559
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"" + tagId$1 + "\"]") === null) {
31579
+ const css$2 = "/* Session stats pills under the composer (shadow of the official StatsPills):\n a gauge pill (counts + output speed, click opens the time dialog) and a\n database pill (total tokens + cache hit, click opens the usage dialog).\n Replicated from the official StatsPills.module_348665330.css_348665330 + stat-dialog.module_348665330.css_348665330\n (13/20 tertiary tier, hover-pill affordance, shared dialog skin).\n\n Host contract: the row serves two containers at once, and picks between them\n at attach time — the component marks which one it landed in (see\n StatsLineEnhanced's `markDockContainer`):\n - through 0.1.6-alpha.1 the dock slot renders straight into InputBar's own\n column, and this row owns the content-width clamp, its side gutters and\n its 4px top pad — the official StatsPills.module_348665330.css_348665330 of that line;\n - 0.1.6-alpha.2 renders it inside InputBar's flex `.dock_348665330` beside the resident\n ContextMeter, which took all three jobs over, so the row only has to\n shrink inside it (the official stylesheet's current form).\n Both forms are kept side by side because one published build has to render\n correctly on either host line. */\n\n.root_348665330 {\n display: flex;\n justify-content: center;\n gap: 12px;\n box-sizing: border-box;\n /* <= 0.1.6-alpha.1: this row is the composer column's content-width box. */\n width: 100%;\n max-width: var(--dsh-chat-content-width);\n margin: 0 auto;\n padding: 4px calc(var(--dsh-composer-side-clearance) + 16px) 0px;\n font-size: var(--dsh-content-font-size-secondary, 13px);\n line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px));\n}\n\n/* 0.1.6-alpha.2+: InputBar's `.dock_348665330` owns the centring, the 12px gap, the top\n pad and the side clearance. */\n.root_348665330[data-dock-row] {\n width: auto;\n min-width: 0;\n max-width: 100%;\n margin: 0;\n padding: 0;\n}\n\n/* Dialog anchor: shrink-wraps its pill so the panel clamp measures the pill. */\n.anchor_348665330 {\n display: inline-flex;\n min-width: 0;\n}\n\n/* Split-mode anchor (DSH >= 0.2.1-alpha.1). The host split the single `stats`\n dock entry into one entry per pill and let its own `.dock_348665330` flex row own the\n layout, so the anchor IS the entry root and carries the text tier `.root_348665330`\n used to set — the official StatsPills.module_348665330.css_348665330 moved exactly this pair of\n declarations from `.root_348665330` onto `.anchor_348665330`. The tier stays off the plain\n `.anchor_348665330` because the pre-split row must keep its own `.root_348665330` tier. */\n.dockAnchor_348665330 {\n font-size: var(--dsh-content-font-size-secondary, 13px);\n line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px));\n}\n\n.pill_348665330 {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n box-sizing: border-box;\n max-width: 100%;\n padding: 1px 8px;\n border: none;\n border-radius: var(--dsw-radius-sm);\n background: none;\n color: var(--dsw-alias-label-tertiary);\n font: inherit;\n font-variant-numeric: tabular-nums;\n line-height: inherit;\n white-space: nowrap;\n}\n\n.pill_348665330 svg {\n width: 14px;\n height: 14px;\n flex: none;\n}\n\n/* Only the button form (a pill with dialog rows to open) invites interaction;\n the static span form keeps the resting tertiary reading. */\nbutton.pill_348665330 {\n cursor: pointer;\n}\n\nbutton.pill_348665330:hover,\nbutton.pill_348665330[aria-expanded='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.label_348665330 {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sep_348665330 {\n color: var(--dsw-alias-separator-primary);\n margin: 0 6px;\n}\n\n/* The live throughput reading sits inline exactly like the official figure:\n no reserved width, no box of its own. The earlier `min-width: 10ch` slot kept\n the centred row from shifting while the number grew, but it also left a\n permanent gap before the separator — the official pill has no such slot, and\n native parity wins over that jitter fix. */\n.speed_348665330 {\n display: inline;\n}\n\n/* Portal dialog surface: fixed in the viewport, left/top supplied inline from\n the anchored-position clamp (12px viewport margin, layers above overlays).\n Material = the official stat-dialog PAIRING, which dsh 0.1.7's menu\n redesign made mandatory: `--dsw-specific-menu` is translucent there\n (rgba 58%/45%), so the blur token must ride along — the 0.1.5-era recipe\n this file copied was a single opaque line, and a fill-only copy reads as\n bare transparency over the page (issue #6). */\n.dialogPanel_348665330 {\n position: fixed;\n z-index: 1100;\n box-sizing: border-box;\n width: max-content;\n min-width: min(300px, calc(100vw - 24px));\n max-width: min(440px, calc(100vw - 24px));\n padding: 12px;\n border: 0;\n border-radius: var(--dsw-radius-lg);\n background: var(--dsw-specific-menu);\n backdrop-filter: var(--dsw-menu-backdrop-filter);\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);\n box-shadow: var(--dsw-elevation-prominent);\n font-size: var(--dsh-content-font-size-secondary, 13px);\n line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px));\n color: var(--dsw-alias-label-secondary);\n cursor: default;\n}\n\n/* Dialog heading row: the section name left, the headline value right. */\n.dialogTitle_348665330 {\n display: flex;\n justify-content: space-between;\n gap: 16px;\n margin-bottom: 8px;\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n\n/* Rule under the heading, above its rows. */\n.dialogTitleRule_348665330 {\n margin-bottom: 8px;\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n.dialogTitleValue_348665330 {\n font-variant-numeric: tabular-nums;\n}\n\n/* Heading glyph seated left of the section name. */\n.dialogTitleLabel_348665330 {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n\n.dialogTitleLabel_348665330 svg {\n width: 14px;\n height: 14px;\n flex: none;\n}\n\n.dialogDetails_348665330 {\n display: grid;\n grid-template-columns: minmax(76px, auto) minmax(0, 1fr);\n gap: 4px 12px;\n margin: 0;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.dialogDetails_348665330 dt,\n.dialogDetails_348665330 dd {\n min-width: 0;\n margin: 0;\n}\n\n.dialogDetails_348665330 dd {\n color: var(--dsw-alias-label-secondary);\n font-variant-numeric: tabular-nums;\n text-align: right;\n}\n";
31580
+ const tagId$2 = "dsh-token-total/StatsLineEnhanced.module.css";
31581
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"" + tagId$2 + "\"]") === null) {
31560
31582
  const tag = document.createElement("style");
31561
31583
  tag.dataset.plugin = "dsh-token-total";
31562
- tag.dataset.pluginCss = tagId$1;
31563
- tag.textContent = css$1;
31584
+ tag.dataset.pluginCss = tagId$2;
31585
+ tag.textContent = css$2;
31564
31586
  document.head.appendChild(tag);
31565
31587
  }
31566
31588
  var StatsLineEnhanced_module_default = {
@@ -32040,13 +32062,13 @@ window.__ModuleLoader__.load({
32040
32062
  }
32041
32063
  //#endregion
32042
32064
  //#region \0token-total-css:/home/runner/work/dsh-token-total/dsh-token-total/src/client/ContextUsageEntry.module.css?inline
32043
- const css = "/* Mirror the host ContextMeter, including its theme and font-size tokens. */\n.root_1877794043 {\n flex: none;\n display: inline-flex;\n}\n\n.trigger_1877794043 {\n border-radius: var(--dsw-radius-sm);\n color: var(--dsw-alias-label-tertiary);\n font-family: inherit;\n font-size: var(--dsh-content-font-size-secondary, 13px);\n font-variant-numeric: tabular-nums;\n line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px));\n white-space: nowrap;\n cursor: pointer;\n background: transparent;\n border: none;\n flex: none;\n align-items: center;\n gap: 6px;\n padding: 1px 8px;\n display: inline-flex;\n}\n\n.trigger_1877794043:hover,\n.trigger_1877794043[aria-expanded='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.track_1877794043 {\n fill: none;\n stroke: var(--dsw-alias-border-l3);\n stroke-width: 2px;\n}\n\n.fill_1877794043 {\n fill: none;\n stroke: var(--dsw-alias-label-tertiary);\n stroke-width: 2px;\n stroke-linecap: round;\n}\n\n.panel_1877794043 {\n z-index: 1100;\n box-sizing: border-box;\n border-radius: var(--dsw-radius-lg);\n background: var(--dsw-specific-menu);\n width: min(264px, calc(100vw - 24px));\n backdrop-filter: var(--dsw-menu-backdrop-filter);\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);\n box-shadow: var(--dsw-elevation-prominent);\n color: var(--dsw-alias-label-secondary);\n cursor: default;\n border: 0;\n padding: 12px;\n font-size: 12px;\n line-height: 20px;\n position: fixed;\n}\n\n.header_1877794043 {\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n.figures_1877794043 {\n font-variant-numeric: tabular-nums;\n color: var(--dsw-alias-label-primary);\n margin-left: auto;\n font-weight: 500;\n}\n\n.percent_1877794043 {\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n\n.headline_1877794043 { color: var(--dsw-alias-label-tertiary); }\n.headline_1877794043:empty { display: none; }\n\n.bar_1877794043 {\n corner-shape: round;\n background: var(--dsw-alias-interactive-bg-hover);\n border-radius: 999px;\n gap: 1px;\n height: 4px;\n margin: 10px 0 12px;\n display: flex;\n overflow: hidden;\n}\n\n.segment_1877794043 {\n background: var(--meter-tint, var(--dsw-alias-label-tertiary));\n border-radius: 1px;\n flex: none;\n min-width: 2px;\n height: 100%;\n}\n\n.swatch_1877794043 {\n background: var(--meter-tint);\n vertical-align: baseline;\n border-radius: 2px;\n width: 8px;\n height: 8px;\n margin-right: 6px;\n display: inline-block;\n}\n\n.colorSystem_1877794043 { --meter-tint: var(--dsw-static-neutral-bluish-400); }\n.colorTools_1877794043 { --meter-tint: #a78bfa; }\n.colorMessages_1877794043 { --meter-tint: var(--dsw-static-blue-450); }\n.rows_1877794043 { margin: 6px 0 0; }\n\n.row_1877794043 {\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n padding: 2px 0;\n display: flex;\n}\n\n.row_1877794043 dt { color: var(--dsw-alias-label-secondary); }\n.row_1877794043 dd {\n font-variant-numeric: tabular-nums;\n color: var(--dsw-alias-label-primary);\n margin: 0;\n}\n";
32044
- const tagId = "dsh-token-total/ContextUsageEntry.module.css";
32045
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"" + tagId + "\"]") === null) {
32065
+ const css$1 = "/* Mirror the host ContextMeter, including its theme and font-size tokens. */\n.root_1877794043 {\n flex: none;\n display: inline-flex;\n}\n\n.trigger_1877794043 {\n border-radius: var(--dsw-radius-sm);\n color: var(--dsw-alias-label-tertiary);\n font-family: inherit;\n font-size: var(--dsh-content-font-size-secondary, 13px);\n font-variant-numeric: tabular-nums;\n line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px));\n white-space: nowrap;\n cursor: pointer;\n background: transparent;\n border: none;\n flex: none;\n align-items: center;\n gap: 6px;\n padding: 1px 8px;\n display: inline-flex;\n}\n\n.trigger_1877794043:hover,\n.trigger_1877794043[aria-expanded='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.track_1877794043 {\n fill: none;\n stroke: var(--dsw-alias-border-l3);\n stroke-width: 2px;\n}\n\n.fill_1877794043 {\n fill: none;\n stroke: var(--dsw-alias-label-tertiary);\n stroke-width: 2px;\n stroke-linecap: round;\n}\n\n.panel_1877794043 {\n z-index: 1100;\n box-sizing: border-box;\n border-radius: var(--dsw-radius-lg);\n background: var(--dsw-specific-menu);\n width: min(264px, calc(100vw - 24px));\n backdrop-filter: var(--dsw-menu-backdrop-filter);\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);\n box-shadow: var(--dsw-elevation-prominent);\n color: var(--dsw-alias-label-secondary);\n cursor: default;\n border: 0;\n padding: 12px;\n font-size: 12px;\n line-height: 20px;\n position: fixed;\n}\n\n.header_1877794043 {\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n.figures_1877794043 {\n font-variant-numeric: tabular-nums;\n color: var(--dsw-alias-label-primary);\n margin-left: auto;\n font-weight: 500;\n}\n\n.percent_1877794043 {\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n\n.headline_1877794043 { color: var(--dsw-alias-label-tertiary); }\n.headline_1877794043:empty { display: none; }\n\n.bar_1877794043 {\n corner-shape: round;\n background: var(--dsw-alias-interactive-bg-hover);\n border-radius: 999px;\n gap: 1px;\n height: 4px;\n margin: 10px 0 12px;\n display: flex;\n overflow: hidden;\n}\n\n.segment_1877794043 {\n background: var(--meter-tint, var(--dsw-alias-label-tertiary));\n border-radius: 1px;\n flex: none;\n min-width: 2px;\n height: 100%;\n}\n\n.swatch_1877794043 {\n background: var(--meter-tint);\n vertical-align: baseline;\n border-radius: 2px;\n width: 8px;\n height: 8px;\n margin-right: 6px;\n display: inline-block;\n}\n\n.colorSystem_1877794043 { --meter-tint: var(--dsw-static-neutral-bluish-400); }\n.colorTools_1877794043 { --meter-tint: #a78bfa; }\n.colorMessages_1877794043 { --meter-tint: var(--dsw-static-blue-450); }\n.rows_1877794043 { margin: 6px 0 0; }\n\n.row_1877794043 {\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n padding: 2px 0;\n display: flex;\n}\n\n.row_1877794043 dt { color: var(--dsw-alias-label-secondary); }\n.row_1877794043 dd {\n font-variant-numeric: tabular-nums;\n color: var(--dsw-alias-label-primary);\n margin: 0;\n}\n";
32066
+ const tagId$1 = "dsh-token-total/ContextUsageEntry.module.css";
32067
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"" + tagId$1 + "\"]") === null) {
32046
32068
  const tag = document.createElement("style");
32047
32069
  tag.dataset.plugin = "dsh-token-total";
32048
- tag.dataset.pluginCss = tagId;
32049
- tag.textContent = css;
32070
+ tag.dataset.pluginCss = tagId$1;
32071
+ tag.textContent = css$1;
32050
32072
  document.head.appendChild(tag);
32051
32073
  }
32052
32074
  var ContextUsageEntry_module_default = {
@@ -32606,6 +32628,1072 @@ window.__ModuleLoader__.load({
32606
32628
  return glass !== null && glass.bridgeId === "deepseek-harness-background" && glass.version === 1;
32607
32629
  }
32608
32630
  //#endregion
32631
+ //#region src/client/use-session-detail.ts
32632
+ /** Serialized polling for one visible Usage view, never leaking another
32633
+ * session's answer. Abort and stop all timers when the tab unmounts. */
32634
+ const DETAIL_POLL_MS = 1500;
32635
+ function useSessionDetail(sessionId) {
32636
+ const [reading, setReading] = (0, react.useState)(null);
32637
+ const refresh = (0, react.useRef)(null);
32638
+ (0, react.useEffect)(() => {
32639
+ let active = true;
32640
+ let pending = false;
32641
+ let timer;
32642
+ let controller;
32643
+ const request = () => {
32644
+ if (!active || pending || !sessionId) return;
32645
+ if (timer !== void 0) clearTimeout(timer);
32646
+ pending = true;
32647
+ controller = new AbortController();
32648
+ fetchSessionDetail(sessionId, controller.signal).then((detail) => {
32649
+ if (active) setReading({
32650
+ sessionId,
32651
+ detail,
32652
+ error: false
32653
+ });
32654
+ }).catch(() => {
32655
+ if (active) setReading((previous) => ({
32656
+ sessionId,
32657
+ detail: previous?.sessionId === sessionId ? previous.detail : null,
32658
+ error: true
32659
+ }));
32660
+ }).finally(() => {
32661
+ pending = false;
32662
+ if (active) timer = setTimeout(request, DETAIL_POLL_MS);
32663
+ });
32664
+ };
32665
+ const wake = () => {
32666
+ if (document.visibilityState === "visible") request();
32667
+ };
32668
+ refresh.current = request;
32669
+ document.addEventListener("visibilitychange", wake);
32670
+ request();
32671
+ return () => {
32672
+ active = false;
32673
+ refresh.current = null;
32674
+ controller?.abort();
32675
+ if (timer !== void 0) clearTimeout(timer);
32676
+ document.removeEventListener("visibilitychange", wake);
32677
+ };
32678
+ }, [sessionId]);
32679
+ const current = reading?.sessionId === sessionId ? reading : null;
32680
+ return {
32681
+ detail: current?.detail ?? null,
32682
+ loading: current === null,
32683
+ error: current?.error ?? false,
32684
+ retry: () => refresh.current?.()
32685
+ };
32686
+ }
32687
+ //#endregion
32688
+ //#region src/client/model-logos-data.ts
32689
+ /**
32690
+ * Official per-brand logos for the usage panel: the inner markup of each
32691
+ * brand's 24x24 SVG, extracted verbatim from @lobehub/icons-static-svg
32692
+ * (MIT). Regenerate from .tmp/gen-logos.mjs after refreshing .tmp/logos/;
32693
+ * brand colors are baked in, so no fill follows currentColor. Brand
32694
+ * matching lives in model-logos-core.ts.
32695
+ */
32696
+ const MODEL_LOGOS = {
32697
+ deepseek: `<path d="M23.748 4.482c-.254-.124-.364.113-.512.234-.051.039-.094.09-.137.136-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.156-.708-.311-.955-.65-.172-.241-.219-.51-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.093.172.187.129.323-.082.28-.18.552-.266.833-.055.179-.137.217-.329.14a5.526 5.526 0 01-1.736-1.18c-.857-.828-1.631-1.742-2.597-2.458a11.365 11.365 0 00-.689-.471c-.985-.957.13-1.743.388-1.836.27-.098.093-.432-.779-.428-.872.004-1.67.295-2.687.684a3.055 3.055 0 01-.465.137 9.597 9.597 0 00-2.883-.102c-1.885.21-3.39 1.102-4.497 2.623C.082 8.606-.231 10.684.152 12.85c.403 2.284 1.569 4.175 3.36 5.653 1.858 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.133-.284 4.994-1.86.47.234.962.327 1.78.397.63.059 1.236-.03 1.705-.128.735-.156.684-.837.419-.961-2.155-1.004-1.682-.595-2.113-.926 1.096-1.296 2.746-2.642 3.392-7.003.05-.347.007-.565 0-.845-.004-.17.035-.237.23-.256a4.173 4.173 0 001.545-.475c1.396-.763 1.96-2.015 2.093-3.517.02-.23-.004-.467-.247-.588zM11.581 18c-2.089-1.642-3.102-2.183-3.52-2.16-.392.024-.321.471-.235.763.09.288.207.486.371.739.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.167-1.361-.802-2.5-1.86-3.301-3.307-.774-1.393-1.224-2.887-1.298-4.482-.02-.386.093-.522.477-.592a4.696 4.696 0 011.529-.039c2.132.312 3.946 1.265 5.468 2.774.868.86 1.525 1.887 2.202 2.891.72 1.066 1.494 2.082 2.48 2.914.348.292.625.514.891.677-.802.09-2.14.11-3.054-.614zm1-6.44a.306.306 0 01.415-.287.302.302 0 01.2.288.306.306 0 01-.31.307.303.303 0 01-.304-.308zm3.11 1.596c-.2.081-.399.151-.59.16a1.245 1.245 0 01-.798-.254c-.274-.23-.47-.358-.552-.758a1.73 1.73 0 01.016-.588c.07-.327-.008-.537-.239-.727-.187-.156-.426-.199-.688-.199a.559.559 0 01-.254-.078c-.11-.054-.2-.19-.114-.358.028-.054.16-.186.192-.21.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.391.451.462.576.685.914.176.265.336.537.445.848.067.195-.019.354-.25.452z" fill="#4D6BFE"></path>`,
32698
+ openai: `<g fill="#0F0F0F" fill-rule="evenodd"><path d="M9.205 8.658v-2.26c0-.19.072-.333.238-.428l4.543-2.616c.619-.357 1.356-.523 2.117-.523 2.854 0 4.662 2.212 4.662 4.566 0 .167 0 .357-.024.547l-4.71-2.759a.797.797 0 00-.856 0l-5.97 3.473zm10.609 8.8V12.06c0-.333-.143-.57-.429-.737l-5.97-3.473 1.95-1.118a.433.433 0 01.476 0l4.543 2.617c1.309.76 2.189 2.378 2.189 3.948 0 1.808-1.07 3.473-2.76 4.163zM7.802 12.703l-1.95-1.142c-.167-.095-.239-.238-.239-.428V5.899c0-2.545 1.95-4.472 4.591-4.472 1 0 1.927.333 2.712.928L8.23 5.067c-.285.166-.428.404-.428.737v6.898zM12 15.128l-2.795-1.57v-3.33L12 8.658l2.795 1.57v3.33L12 15.128zm1.796 7.23c-1 0-1.927-.332-2.712-.927l4.686-2.712c.285-.166.428-.404.428-.737v-6.898l1.974 1.142c.167.095.238.238.238.428v5.233c0 2.545-1.974 4.472-4.614 4.472zm-5.637-5.303l-4.544-2.617c-1.308-.761-2.188-2.378-2.188-3.948A4.482 4.482 0 014.21 6.327v5.423c0 .333.143.571.428.738l5.947 3.449-1.95 1.118a.432.432 0 01-.476 0zm-.262 3.9c-2.688 0-4.662-2.021-4.662-4.519 0-.19.024-.38.047-.57l4.686 2.71c.286.167.571.167.856 0l5.97-3.448v2.26c0 .19-.07.333-.237.428l-4.543 2.616c-.619.357-1.356.523-2.117.523zm5.899 2.83a5.947 5.947 0 005.827-4.756C22.287 18.339 24 15.84 24 13.296c0-1.665-.713-3.282-1.998-4.448.119-.5.19-.999.19-1.498 0-3.401-2.759-5.947-5.946-5.947-.642 0-1.26.095-1.88.31A5.962 5.962 0 0010.205 0a5.947 5.947 0 00-5.827 4.757C1.713 5.447 0 7.945 0 10.49c0 1.666.713 3.283 1.998 4.448-.119.5-.19 1-.19 1.499 0 3.401 2.759 5.946 5.946 5.946.642 0 1.26-.095 1.88-.309a5.96 5.96 0 004.162 1.713z"></path></g>`,
32699
+ claude: `<path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z" fill="#D97757" fill-rule="nonzero"></path>`,
32700
+ gemini: `<path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="#3186FF"></path><path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="url(#lobe-icons-gemini-0-_R_0_)"></path><path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="url(#lobe-icons-gemini-1-_R_0_)"></path><path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="url(#lobe-icons-gemini-2-_R_0_)"></path><defs><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-gemini-0-_R_0_" x1="7" x2="11" y1="15.5" y2="12"><stop stop-color="#08B962"></stop><stop offset="1" stop-color="#08B962" stop-opacity="0"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-gemini-1-_R_0_" x1="8" x2="11.5" y1="5.5" y2="11"><stop stop-color="#F94543"></stop><stop offset="1" stop-color="#F94543" stop-opacity="0"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-gemini-2-_R_0_" x1="3.5" x2="17.5" y1="13.5" y2="12"><stop stop-color="#FABC12"></stop><stop offset=".46" stop-color="#FABC12" stop-opacity="0"></stop></linearGradient></defs>`,
32701
+ qwen: `<path d="M19.713 2.825h-5.907c0-.251-.066-.503-.196-.728L12.819.728A1.46 1.46 0 0 0 11.559 0h-1.58c-.52 0-1 .275-1.26.728l-2.42 4.19a1.45 1.45 0 0 0 0 1.453l.791 1.37c.26.448.74.727 1.26.727h11.36c.52 0 1-.275 1.26-.728l.79-1.37a1.45 1.45 0 0 0 0-1.451l-.79-1.37a1.46 1.46 0 0 0-1.26-.728zM.195 9.905l2.951 5.115a1.46 1.46 0 0 0-.531.531l-.791 1.37a1.45 1.45 0 0 0 0 1.452l.79 1.37c.26.448.74.727 1.26.727h4.84c.52 0 1-.275 1.26-.728l.79-1.37a1.45 1.45 0 0 0 0-1.451L5.086 7.083a1.46 1.46 0 0 0-1.26-.728h-1.58c-.52 0-1 .276-1.26.728l-.79 1.37a1.45 1.45 0 0 0 0 1.452m15.888 13.367 2.951-5.115c.217.125.469.196.728.196h1.582c.52 0 1-.275 1.26-.728l.79-1.37a1.45 1.45 0 0 0 0-1.451l-2.42-4.191a1.46 1.46 0 0 0-1.259-.728h-1.582c-.52 0-1 .276-1.259.728l-5.678 9.838a1.45 1.45 0 0 0 0 1.452l.79 1.37c.26.448.74.727 1.26.727h1.582c.52 0 1-.275 1.26-.728z" fill="#082dff"></path>`,
32702
+ zhipu: `<path d="M11.991 23.503a.24.24 0 00-.244.248.24.24 0 00.244.249.24.24 0 00.245-.249.24.24 0 00-.22-.247l-.025-.001zM9.671 5.365a1.697 1.697 0 011.099 2.132l-.071.172-.016.04-.018.054c-.07.16-.104.32-.104.498-.035.71.47 1.279 1.186 1.314h.366c1.309.053 2.338 1.173 2.286 2.523-.052 1.332-1.152 2.38-2.478 2.327h-.174c-.715.018-1.274.64-1.239 1.368 0 .124.018.23.053.337.209.373.54.658.96.8.75.23 1.517-.125 1.9-.782l.018-.035c.402-.64 1.17-.96 1.92-.711.854.284 1.378 1.226 1.099 2.167a1.661 1.661 0 01-2.077 1.102 1.711 1.711 0 01-.907-.711l-.017-.035c-.2-.323-.463-.58-.851-.711l-.056-.018a1.646 1.646 0 00-1.954.746 1.66 1.66 0 01-1.065.764 1.677 1.677 0 01-1.989-1.279c-.209-.906.332-1.83 1.257-2.043a1.51 1.51 0 01.296-.035h.018c.68-.071 1.151-.622 1.116-1.333a1.307 1.307 0 00-.227-.693 2.515 2.515 0 01-.366-1.403 2.39 2.39 0 01.366-1.208c.14-.195.21-.444.227-.693.018-.71-.506-1.261-1.186-1.332l-.07-.018a1.43 1.43 0 01-.299-.07l-.05-.019a1.7 1.7 0 01-1.047-2.114 1.68 1.68 0 012.094-1.101zm-5.575 10.11c.26-.264.639-.367.994-.27.355.096.633.379.728.74.095.362-.007.748-.267 1.013-.402.41-1.053.41-1.455 0a1.062 1.062 0 010-1.482zm14.845-.294c.359-.09.738.024.992.297.254.274.344.665.237 1.025-.107.36-.396.634-.756.718-.551.128-1.1-.22-1.23-.781a1.05 1.05 0 01.757-1.26zm-.064-4.39c.314.32.49.753.49 1.206 0 .452-.176.886-.49 1.206-.315.32-.74.5-1.185.5-.444 0-.87-.18-1.184-.5a1.727 1.727 0 010-2.412 1.654 1.654 0 012.369 0zm-11.243.163c.364.484.447 1.128.218 1.691a1.665 1.665 0 01-2.188.923c-.855-.36-1.26-1.358-.907-2.228a1.68 1.68 0 011.33-1.038c.593-.08 1.183.169 1.547.652zm11.545-4.221c.368 0 .708.2.892.524.184.324.184.724 0 1.048a1.026 1.026 0 01-.892.524c-.568 0-1.03-.47-1.03-1.048 0-.579.462-1.048 1.03-1.048zm-14.358 0c.368 0 .707.2.891.524.184.324.184.724 0 1.048a1.026 1.026 0 01-.891.524c-.569 0-1.03-.47-1.03-1.048 0-.579.461-1.048 1.03-1.048zm10.031-1.475c.925 0 1.675.764 1.675 1.706s-.75 1.705-1.675 1.705-1.674-.763-1.674-1.705c0-.942.75-1.706 1.674-1.706zm-2.626-.684c.362-.082.653-.356.761-.718a1.062 1.062 0 00-.238-1.028 1.017 1.017 0 00-.996-.294c-.547.14-.881.7-.752 1.257.13.558.675.907 1.225.783zm0 16.876c.359-.087.644-.36.75-.72a1.062 1.062 0 00-.237-1.019 1.018 1.018 0 00-.985-.301 1.037 1.037 0 00-.762.717c-.108.361-.017.754.239 1.028.245.263.606.377.953.305l.043-.01zM17.19 3.5a.631.631 0 00.628-.64c0-.355-.279-.64-.628-.64a.631.631 0 00-.628.64c0 .355.28.64.628.64zm-10.38 0a.631.631 0 00.628-.64c0-.355-.28-.64-.628-.64a.631.631 0 00-.628.64c0 .355.279.64.628.64zm-5.182 7.852a.631.631 0 00-.628.64c0 .354.28.639.628.639a.63.63 0 00.627-.606l.001-.034a.62.62 0 00-.628-.64zm5.182 9.13a.631.631 0 00-.628.64c0 .355.279.64.628.64a.631.631 0 00.628-.64c0-.355-.28-.64-.628-.64zm10.38.018a.631.631 0 00-.628.64c0 .355.28.64.628.64a.631.631 0 00.628-.64c0-.355-.279-.64-.628-.64zm5.182-9.148a.631.631 0 00-.628.64c0 .354.279.639.628.639a.631.631 0 00.628-.64c0-.355-.28-.64-.628-.64zm-.384-4.992a.24.24 0 00.244-.249.24.24 0 00-.244-.249.24.24 0 00-.244.249c0 .142.122.249.244.249zM11.991.497a.24.24 0 00.245-.248A.24.24 0 0011.99 0a.24.24 0 00-.244.249c0 .133.108.236.223.247l.021.001zM2.011 6.36a.24.24 0 00.245-.249.24.24 0 00-.244-.249.24.24 0 00-.244.249.24.24 0 00.244.249zm0 11.263a.24.24 0 00-.243.248.24.24 0 00.244.249.24.24 0 00.244-.249.252.252 0 00-.244-.248zm19.995-.018a.24.24 0 00-.245.248.24.24 0 00.245.25.24.24 0 00.244-.25.252.252 0 00-.244-.248z" fill="#3859FF" fill-rule="nonzero"></path>`,
32703
+ kimi: `<path d="M21.846 0a1.923 1.923 0 110 3.846H20.15a.226.226 0 01-.227-.226V1.923C19.923.861 20.784 0 21.846 0z" fill="#1783FF"></path><path d="M11.065 11.199l7.257-7.2c.137-.136.06-.41-.116-.41H14.3a.164.164 0 00-.117.051l-7.82 7.756c-.122.12-.302.013-.302-.179V3.82c0-.127-.083-.23-.185-.23H3.186c-.103 0-.186.103-.186.23V19.77c0 .128.083.23.186.23h2.69c.103 0 .186-.102.186-.23v-3.25c0-.069.025-.135.069-.178l2.424-2.406a.158.158 0 01.205-.023l6.484 4.772a7.677 7.677 0 003.453 1.283c.108.012.2-.095.2-.23v-3.06c0-.117-.07-.212-.164-.227a5.028 5.028 0 01-2.027-.807l-5.613-4.064c-.117-.078-.132-.279-.028-.381z" fill="#16191E"></path>`,
32704
+ grok: `<g fill="#0F0F0F" fill-rule="evenodd"><path d="M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815"></path></g>`,
32705
+ llama: `<path d="M6.897 4h-.024l-.031 2.615h.022c1.715 0 3.046 1.357 5.94 6.246l.175.297.012.02 1.62-2.438-.012-.019a48.763 48.763 0 00-1.098-1.716 28.01 28.01 0 00-1.175-1.629C10.413 4.932 8.812 4 6.896 4z" fill="url(#lobe-icons-meta-0-_R_0_)"></path><path d="M6.873 4C4.95 4.01 3.247 5.258 2.02 7.17a4.352 4.352 0 00-.01.017l2.254 1.231.011-.017c.718-1.083 1.61-1.774 2.568-1.785h.021L6.896 4h-.023z" fill="url(#lobe-icons-meta-1-_R_0_)"></path><path d="M2.019 7.17l-.011.017C1.2 8.447.598 9.995.274 11.664l-.005.022 2.534.6.004-.022c.27-1.467.786-2.828 1.456-3.845l.011-.017L2.02 7.17z" fill="url(#lobe-icons-meta-2-_R_0_)"></path><path d="M2.807 12.264l-2.533-.6-.005.022c-.177.918-.267 1.851-.269 2.786v.023l2.598.233v-.023a12.591 12.591 0 01.21-2.44z" fill="url(#lobe-icons-meta-3-_R_0_)"></path><path d="M2.677 15.537a5.462 5.462 0 01-.079-.813v-.022L0 14.468v.024a8.89 8.89 0 00.146 1.652l2.535-.585a4.106 4.106 0 01-.004-.022z" fill="url(#lobe-icons-meta-4-_R_0_)"></path><path d="M3.27 16.89c-.284-.31-.484-.756-.589-1.328l-.004-.021-2.535.585.004.021c.192 1.01.568 1.85 1.106 2.487l.014.017 2.018-1.745a2.106 2.106 0 01-.015-.016z" fill="url(#lobe-icons-meta-5-_R_0_)"></path><path d="M10.78 9.654c-1.528 2.35-2.454 3.825-2.454 3.825-2.035 3.2-2.739 3.917-3.871 3.917a1.545 1.545 0 01-1.186-.508l-2.017 1.744.014.017C2.01 19.518 3.058 20 4.356 20c1.963 0 3.374-.928 5.884-5.33l1.766-3.13a41.283 41.283 0 00-1.227-1.886z" fill="#0082FB"></path><path d="M13.502 5.946l-.016.016c-.4.43-.786.908-1.16 1.416.378.483.768 1.024 1.175 1.63.48-.743.928-1.345 1.367-1.807l.016-.016-1.382-1.24z" fill="url(#lobe-icons-meta-6-_R_0_)"></path><path d="M20.918 5.713C19.853 4.633 18.583 4 17.225 4c-1.432 0-2.637.787-3.723 1.944l-.016.016 1.382 1.24.016-.017c.715-.747 1.408-1.12 2.176-1.12.826 0 1.6.39 2.27 1.075l.015.016 1.589-1.425-.016-.016z" fill="#0082FB"></path><path d="M23.998 14.125c-.06-3.467-1.27-6.566-3.064-8.396l-.016-.016-1.588 1.424.015.016c1.35 1.392 2.277 3.98 2.361 6.971v.023h2.292v-.022z" fill="url(#lobe-icons-meta-7-_R_0_)"></path><path d="M23.998 14.15v-.023h-2.292v.022c.004.14.006.282.006.424 0 .815-.121 1.474-.368 1.95l-.011.022 1.708 1.782.013-.02c.62-.96.946-2.293.946-3.91 0-.083 0-.165-.002-.247z" fill="url(#lobe-icons-meta-8-_R_0_)"></path><path d="M21.344 16.52l-.011.02c-.214.402-.519.67-.917.787l.778 2.462a3.493 3.493 0 00.438-.182 3.558 3.558 0 001.366-1.218l.044-.065.012-.02-1.71-1.784z" fill="url(#lobe-icons-meta-9-_R_0_)"></path><path d="M19.92 17.393c-.262 0-.492-.039-.718-.14l-.798 2.522c.449.153.927.222 1.46.222.492 0 .943-.073 1.352-.215l-.78-2.462c-.167.05-.341.075-.517.073z" fill="url(#lobe-icons-meta-10-_R_0_)"></path><path d="M18.323 16.534l-.014-.017-1.836 1.914.016.017c.637.682 1.246 1.105 1.937 1.337l.797-2.52c-.291-.125-.573-.353-.9-.731z" fill="url(#lobe-icons-meta-11-_R_0_)"></path><path d="M18.309 16.515c-.55-.642-1.232-1.712-2.303-3.44l-1.396-2.336-.011-.02-1.62 2.438.012.02.989 1.668c.959 1.61 1.74 2.774 2.493 3.585l.016.016 1.834-1.914a2.353 2.353 0 01-.014-.017z" fill="url(#lobe-icons-meta-12-_R_0_)"></path><defs><linearGradient id="lobe-icons-meta-0-_R_0_" x1="75.897%" x2="26.312%" y1="89.199%" y2="12.194%"><stop offset=".06%" stop-color="#0867DF"></stop><stop offset="45.39%" stop-color="#0668E1"></stop><stop offset="85.91%" stop-color="#0064E0"></stop></linearGradient><linearGradient id="lobe-icons-meta-1-_R_0_" x1="21.67%" x2="97.068%" y1="75.874%" y2="23.985%"><stop offset="13.23%" stop-color="#0064DF"></stop><stop offset="99.88%" stop-color="#0064E0"></stop></linearGradient><linearGradient id="lobe-icons-meta-2-_R_0_" x1="38.263%" x2="60.895%" y1="89.127%" y2="16.131%"><stop offset="1.47%" stop-color="#0072EC"></stop><stop offset="68.81%" stop-color="#0064DF"></stop></linearGradient><linearGradient id="lobe-icons-meta-3-_R_0_" x1="47.032%" x2="52.15%" y1="90.19%" y2="15.745%"><stop offset="7.31%" stop-color="#007CF6"></stop><stop offset="99.43%" stop-color="#0072EC"></stop></linearGradient><linearGradient id="lobe-icons-meta-4-_R_0_" x1="52.155%" x2="47.591%" y1="58.301%" y2="37.004%"><stop offset="7.31%" stop-color="#007FF9"></stop><stop offset="100%" stop-color="#007CF6"></stop></linearGradient><linearGradient id="lobe-icons-meta-5-_R_0_" x1="37.689%" x2="61.961%" y1="12.502%" y2="63.624%"><stop offset="7.31%" stop-color="#007FF9"></stop><stop offset="100%" stop-color="#0082FB"></stop></linearGradient><linearGradient id="lobe-icons-meta-6-_R_0_" x1="34.808%" x2="62.313%" y1="68.859%" y2="23.174%"><stop offset="27.99%" stop-color="#007FF8"></stop><stop offset="91.41%" stop-color="#0082FB"></stop></linearGradient><linearGradient id="lobe-icons-meta-7-_R_0_" x1="43.762%" x2="57.602%" y1="6.235%" y2="98.514%"><stop offset="0%" stop-color="#0082FB"></stop><stop offset="99.95%" stop-color="#0081FA"></stop></linearGradient><linearGradient id="lobe-icons-meta-8-_R_0_" x1="60.055%" x2="39.88%" y1="4.661%" y2="69.077%"><stop offset="6.19%" stop-color="#0081FA"></stop><stop offset="100%" stop-color="#0080F9"></stop></linearGradient><linearGradient id="lobe-icons-meta-9-_R_0_" x1="30.282%" x2="61.081%" y1="59.32%" y2="33.244%"><stop offset="0%" stop-color="#027AF3"></stop><stop offset="100%" stop-color="#0080F9"></stop></linearGradient><linearGradient id="lobe-icons-meta-10-_R_0_" x1="20.433%" x2="82.112%" y1="50.001%" y2="50.001%"><stop offset="0%" stop-color="#0377EF"></stop><stop offset="99.94%" stop-color="#0279F1"></stop></linearGradient><linearGradient id="lobe-icons-meta-11-_R_0_" x1="40.303%" x2="72.394%" y1="35.298%" y2="57.811%"><stop offset=".19%" stop-color="#0471E9"></stop><stop offset="100%" stop-color="#0377EF"></stop></linearGradient><linearGradient id="lobe-icons-meta-12-_R_0_" x1="32.254%" x2="68.003%" y1="19.719%" y2="84.908%"><stop offset="27.65%" stop-color="#0867DF"></stop><stop offset="100%" stop-color="#0471E9"></stop></linearGradient></defs>`,
32706
+ mistral: `<path d="M3.428 3.4h3.429v3.428H3.428V3.4zm13.714 0h3.43v3.428h-3.43V3.4z" fill="gold"></path><path d="M3.428 6.828h6.857v3.429H3.429V6.828zm10.286 0h6.857v3.429h-6.857V6.828z" fill="#FFAF00"></path><path d="M3.428 10.258h17.144v3.428H3.428v-3.428z" fill="#FF8205"></path><path d="M3.428 13.686h3.429v3.428H3.428v-3.428zm6.858 0h3.429v3.428h-3.429v-3.428zm6.856 0h3.43v3.428h-3.43v-3.428z" fill="#FA500F"></path><path d="M0 17.114h10.286v3.429H0v-3.429zm13.714 0H24v3.429H13.714v-3.429z" fill="#E10500"></path>`,
32707
+ doubao: `<path d="M5.31 15.756c.172-3.75 1.883-5.999 2.549-6.739-3.26 2.058-5.425 5.658-6.358 8.308v1.12C1.501 21.513 4.226 24 7.59 24a6.59 6.59 0 002.2-.375c.353-.12.7-.248 1.039-.378.913-.899 1.65-1.91 2.243-2.992-4.877 2.431-7.974.072-7.763-4.5l.002.001z" fill="#1E37FC"></path><path d="M22.57 10.283c-1.212-.901-4.109-2.404-7.397-2.8.295 3.792.093 8.766-2.1 12.773a12.782 12.782 0 01-2.244 2.992c3.764-1.448 6.746-3.457 8.596-5.219 2.82-2.683 3.353-5.178 3.361-6.66a2.737 2.737 0 00-.216-1.084v-.002z" fill="#37E1BE"></path><path d="M14.303 1.867C12.955.7 11.248 0 9.39 0 7.532 0 5.883.677 4.545 1.807 2.791 3.29 1.627 5.557 1.5 8.125v9.201c.932-2.65 3.097-6.25 6.357-8.307.5-.318 1.025-.595 1.569-.829 1.883-.801 3.878-.932 5.746-.706-.222-2.83-.718-5.002-.87-5.617h.001z" fill="#A569FF"></path><path d="M17.305 4.961a199.47 199.47 0 01-1.08-1.094c-.202-.213-.398-.419-.586-.622l-1.333-1.378c.151.615.648 2.786.869 5.617 3.288.395 6.185 1.898 7.396 2.8-1.306-1.275-3.475-3.487-5.266-5.323z" fill="#1E37FC"></path>`,
32708
+ minimax: `<defs><linearGradient id="lobe-icons-minimax-_R_0_" x1="0%" x2="100.182%" y1="50.057%" y2="50.057%"><stop offset="0%" stop-color="#E2167E"></stop><stop offset="100%" stop-color="#FE603C"></stop></linearGradient></defs><path d="M16.278 2c1.156 0 2.093.927 2.093 2.07v12.501a.74.74 0 00.744.709.74.74 0 00.743-.709V9.099a2.06 2.06 0 012.071-2.049A2.06 2.06 0 0124 9.1v6.561a.649.649 0 01-.652.645.649.649 0 01-.653-.645V9.1a.762.762 0 00-.766-.758.762.762 0 00-.766.758v7.472a2.037 2.037 0 01-2.048 2.026 2.037 2.037 0 01-2.048-2.026v-12.5a.785.785 0 00-.788-.753.785.785 0 00-.789.752l-.001 15.904A2.037 2.037 0 0113.441 22a2.037 2.037 0 01-2.048-2.026V18.04c0-.356.292-.645.652-.645.36 0 .652.289.652.645v1.934c0 .263.142.506.372.638.23.131.514.131.744 0a.734.734 0 00.372-.638V4.07c0-1.143.937-2.07 2.093-2.07zm-5.674 0c1.156 0 2.093.927 2.093 2.07v11.523a.648.648 0 01-.652.645.648.648 0 01-.652-.645V4.07a.785.785 0 00-.789-.78.785.785 0 00-.789.78v14.013a2.06 2.06 0 01-2.07 2.048 2.06 2.06 0 01-2.071-2.048V9.1a.762.762 0 00-.766-.758.762.762 0 00-.766.758v3.8a2.06 2.06 0 01-2.071 2.049A2.06 2.06 0 010 12.9v-1.378c0-.357.292-.646.652-.646.36 0 .653.29.653.646V12.9c0 .418.343.757.766.757s.766-.339.766-.757V9.099a2.06 2.06 0 012.07-2.048 2.06 2.06 0 012.071 2.048v8.984c0 .419.343.758.767.758.423 0 .766-.339.766-.758V4.07c0-1.143.937-2.07 2.093-2.07z" fill="url(#lobe-icons-minimax-_R_0_)" fill-rule="nonzero"></path>`,
32709
+ hunyuan: `<circle cx="12" cy="12" fill="#0055E9" r="12"></circle><path d="M12 0c.518 0 1.028.033 1.528.096A6.188 6.188 0 0112.12 12.28l-.12.001c-2.99 0-5.242 2.179-5.554 5.11-.223 2.086.353 4.412 2.242 6.146C3.672 22.1 0 17.479 0 12 0 5.373 5.373 0 12 0z" fill="#A8DFF5"></path><path d="M5.286 5a2.438 2.438 0 01.682 3.38c-3.962 5.966-3.215 10.743 2.648 15.136C3.636 22.056 0 17.452 0 12c0-1.787.39-3.482 1.09-5.006.253-.435.525-.872.817-1.311A2.438 2.438 0 015.286 5z" fill="#0055E9"></path><path d="M12.98.04c.272.021.543.053.81.093.583.106 1.117.254 1.538.44 6.638 2.927 8.07 10.052 1.748 15.642a4.125 4.125 0 01-5.822-.358c-1.51-1.706-1.3-4.184.357-5.822.858-.848 3.108-1.223 4.045-2.441 1.257-1.634 2.122-6.009-2.523-7.506L12.98.039z" fill="#00BCFF"></path><path d="M13.528.096A6.187 6.187 0 0112 12.281a5.75 5.75 0 00-1.71.255c.147-.905.595-1.784 1.321-2.501.858-.848 3.108-1.223 4.045-2.441 1.27-1.651 2.14-6.104-2.676-7.554.184.014.367.033.548.056z" fill="#ECECEE"></path>`,
32710
+ ernie: `<path d="M11.32 1.176a1.4 1.4 0 011.36 0l8.64 4.843c.421.234.68.67.68 1.141v9.68c0 .472-.259.908-.68 1.143l-8.64 4.84a1.4 1.4 0 01-1.36 0l-8.64-4.84A1.31 1.31 0 012 16.84V7.159c0-.471.259-.907.68-1.142l8.64-4.84zm7.42 13.839V8.227L12.002 12 12 19.551l6.059-3.394a1.31 1.31 0 00.68-1.142zM12.68 4.833a1.393 1.393 0 00-1.36 0L5.944 7.846c-.421.235-.68.67-.68 1.142v6.027c0 .47.259.905.68 1.142l2.795 1.566V11.09a1.546 1.546 0 00.221.79 1.527 1.527 0 01-.216-.834l.004-.094.02-.15.018-.084.017-.062.039-.117.062-.142.035-.065.081-.13.094-.122.084-.091.08-.075.125-.1.071-.048.134-.076 5.87-3.29-2.796-1.566z" fill="url(#lobe-icons-wenxin-_R_0_)"></path><path d="M12 11.088c0-.875-.73-1.584-1.631-1.584a1.66 1.66 0 00-.855.237c-.027.016-.055.033-.08.05a2.361 2.361 0 00-.123.093c-.022.02-.045.038-.066.059l-.048.045-.063.067c-.014.016-.028.031-.04.048a2.303 2.303 0 00-.094.125l-.042.069a1.7 1.7 0 00-.07.13l-.036.081a.764.764 0 00-.022.06c-.01.03-.02.058-.028.087l-.017.062a.883.883 0 00-.03.16c-.002.025-.007.05-.008.074a1.527 1.527 0 00.213.929c.302.508.85.792 1.414.792.277 0 .558-.068.814-.212l.815-.457v-.914L12 11.088z" fill="#012F8D"></path><defs><linearGradient id="lobe-icons-wenxin-_R_0_" x1="9.155%" x2="90.531%" y1="75.177%" y2="25.028%"><stop offset="0%" stop-color="#0A51C3"></stop><stop offset="100%" stop-color="#23A4FB"></stop></linearGradient></defs>`,
32711
+ stepfun: `<path d="M22.012 0h1.032v.927H24v.968h-.956V3.78h-1.032V1.896h-1.878v-.97h1.878V0zM2.6 12.371V1.87h.969v10.502h-.97zm10.423.66h10.95v.918h-6.208v9.579h-4.742V13.03zM5.629 3.333v12.356H0v4.51h10.386V8L20.859 8l-.003-4.668-15.227.001z" fill="url(#lobe-icons-stepfun-_R_0_)" fill-rule="evenodd"></path><defs><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-stepfun-_R_0_" x1="1.646" x2="18.342" y1="1.916" y2="22.091"><stop stop-color="#01A9FF"></stop><stop offset="1" stop-color="#0160FF"></stop></linearGradient></defs>`,
32712
+ cohere: `<path clip-rule="evenodd" d="M8.128 14.099c.592 0 1.77-.033 3.398-.703 1.897-.781 5.672-2.2 8.395-3.656 1.905-1.018 2.74-2.366 2.74-4.18A4.56 4.56 0 0018.1 1H7.549A6.55 6.55 0 001 7.55c0 3.617 2.745 6.549 7.128 6.549z" fill="#39594D" fill-rule="evenodd"></path><path clip-rule="evenodd" d="M9.912 18.61a4.387 4.387 0 012.705-4.052l3.323-1.38c3.361-1.394 7.06 1.076 7.06 4.715a5.104 5.104 0 01-5.105 5.104l-3.597-.001a4.386 4.386 0 01-4.386-4.387z" fill="#D18EE2" fill-rule="evenodd"></path><path d="M4.776 14.962A3.775 3.775 0 001 18.738v.489a3.776 3.776 0 007.551 0v-.49a3.775 3.775 0 00-3.775-3.775z" fill="#FF7759"></path>`,
32713
+ xiaomi: `<g fill="#FF6900" fill-rule="evenodd"><path d="M.958 15.936a.459.459 0 01.459.44v2.729a.46.46 0 01-.918 0v-2.729a.459.459 0 01.459-.44zm4.814-2.035a.46.46 0 01.553.45v4.754a.458.458 0 11-.918 0V15.48L3.74 17.202a.462.462 0 01-.655.016.462.462 0 01-.065-.082L.628 14.67a.459.459 0 01.658-.637l2.124 2.187 2.127-2.188a.46.46 0 01.235-.13zm2.068.004a.46.46 0 01.458.445v4.755a.46.46 0 01-.458.458.459.459 0 01-.458-.458V14.35a.459.459 0 01.458-.445zm1.973 2.014a.46.46 0 01.46.457v2.729a.46.46 0 01-.784.324.46.46 0 01-.134-.324v-2.729a.46.46 0 01.458-.458zm.002-2.045a.458.458 0 01.328.157l2.127 2.19 2.125-2.19a.459.459 0 01.784.318v4.756a.46.46 0 01-.455.458.46.46 0 01-.458-.458V15.48l-1.667 1.723a.46.46 0 01-.65.008l-.005-.005c0-.002-.002-.002-.004-.003l-2.455-2.534a.46.46 0 01-.008-.667.461.461 0 01.338-.128zm6.797 1.206a.46.46 0 01.53.651A1.966 1.966 0 0019.81 18.4a.462.462 0 01.623.18.46.46 0 01-.181.624 2.863 2.863 0 01-1.38.353l-.142-.004a2.88 2.88 0 01-2.393-4.263.461.461 0 01.274-.21zm.864-.931a2.884 2.884 0 013.915 3.914.46.46 0 01-.402.24l-.057-.004a.458.458 0 01-.164-.055.46.46 0 01-.182-.622 1.967 1.967 0 00-2.669-2.67.459.459 0 11-.441-.803zM9.59 6.368c1.481 0 1.696 1.202 1.696 1.654v2.648h-.917v-.432c-.26.346-.792.535-1.36.535-.133 0-1.289-.03-1.384-1.136-.082-.932.675-1.61 2.053-1.61h.691c0-.563-.367-.886-.983-.886-.44.013-.864.174-1.2.458l-.36-.664c.484-.379 1.012-.567 1.764-.567zm4.427.1c1.263 0 2.082.97 2.083 2.15 0 1.181-.824 2.154-2.083 2.154-1.26 0-2.084-.972-2.084-2.152 0-1.18.82-2.153 2.084-2.153zm6.801.015c.68 0 1.202.465 1.197 1.548v2.642H21.1V8.29c0-.312-.002-.98-.63-.98s-.628.667-.628.838v2.524h-.89V8.148c0-.17-.001-.838-.63-.838-.628 0-.628.668-.628.98v2.383h-.917v-4.03h.917V7a1.22 1.22 0 01.947-.516c.398 0 .76.193.982.686a1.321 1.321 0 011.195-.686zm-18.093.872l1.457-1.772H5.32L3.311 8.07l2.14 2.602H4.24L2.725 8.796 1.21 10.672H0L2.138 8.07.13 5.583h1.138l1.458 1.772zm4.149 3.317h-.916V6.644h.916v4.028zm16.99 0h-.916V6.644h.916v4.028zM9.925 8.71c-1.055 0-1.359.412-1.326.742.032.329.324.537.757.537a1.013 1.013 0 001.014-.968l.002-.31h-.447zM14.018 7.3c-.663 0-1.184.487-1.184 1.32 0 .832.52 1.32 1.184 1.32.662 0 1.182-.49 1.182-1.32 0-.832-.52-1.32-1.182-1.32zM6.417 5.001a.568.568 0 01.587.582.588.588 0 01-1.175 0A.57.57 0 016.417 5zm16.991 0a.57.57 0 01.592.582.588.588 0 01-1.174 0 .57.57 0 01.357-.542.572.572 0 01.225-.04z"></path></g>`,
32714
+ baichuan: `<defs><linearGradient id="lobe-icons-baichuan-_R_0_" x1="17.764%" x2="100%" y1="8.678%" y2="91.322%"><stop offset="0%" stop-color="#FEC13E"></stop><stop offset="100%" stop-color="#FF6933"></stop></linearGradient></defs><path d="M7.333 2h-3.2l-2 4.333V17.8L0 22h5.2l2.028-4.2L7.333 2zm7.334 0h-5.2v20h5.2V2zM16.8 7.733H22V22h-5.2V7.733zM22 2h-5.2v4.133H22V2z" fill="url(#lobe-icons-baichuan-_R_0_)" fill-rule="nonzero"></path>`,
32715
+ yi: `<g fill-rule="evenodd"><path d="M18.62 13.927c.611 0 1.107.505 1.107 1.128v5.817c0 .623-.496 1.128-1.108 1.128a1.118 1.118 0 01-1.108-1.128v-5.817c0-.623.496-1.128 1.108-1.128zM16.59 3.052a1.094 1.094 0 011.562-.129c.466.404.522 1.116.126 1.59l-5.938 7.111v9.147c0 .624-.496 1.129-1.108 1.129a1.118 1.118 0 01-1.108-1.129v-9.477l.003-.088.01-.087c.015-.232.102-.462.261-.654l6.192-7.413zM2.906 2.256a1.094 1.094 0 011.559.157l4.387 5.45a1.142 1.142 0 01-.155 1.587 1.094 1.094 0 01-1.559-.157l-4.387-5.45a1.144 1.144 0 01.06-1.498l.095-.09z"></path><ellipse cx="20.146" cy="10.692" fill="#00FF25" rx="1.354" ry="1.379"></ellipse></g>`,
32716
+ spark: `<path d="M2 13.08C2 9.182 4.772 6.367 9.32 2.122c-.65 7.883 6.41 8.272 5.023 12.214-.99 2.815-4.244 1.949-4.59 1.342 0 0 1.212.347 1.385-.866.174-1.213-2.252-1.862-3.81-4.937-2.6 2.988-.954 9.008 4.2 9.008 4.764 0 6.583-4.937 4.894-8.099 0 0 4.071.693 4.418 3.811.346 3.119-3.638 8.533-9.095 8.403C6.288 22.868 2 18.84 2 13.08z" fill="#3DC8F9"></path><path d="M17.852 6.107L11.615 0c-.52 5.933.866 8.374 4.894 9.485 2.729.753 3.307 1.04 4.504 2.772-.338-2.407-.78-3.812-3.161-6.15z" fill="#EA0100"></path><path clip-rule="evenodd" d="M9.033 18.323c.709.354 1.542.56 2.495.56 4.764 0 6.583-4.937 4.894-8.099 0 0 4.071.693 4.418 3.811.156 1.403-.565 3.27-1.902 4.89-3.458 1.57-7.29.84-9.905-1.162z" fill="#1652D8" fill-rule="evenodd"></path>`,
32717
+ sensenova: `<path d="M23 8.333h-7.333v7.334H23V8.333z" fill="#06FDB7"></path><path d="M1 1v14.667h7.333V8.333h7.334V1H1z" fill="#5B2AD8"></path><path d="M14.038 4.333h.17l1.459 1.456v.17l-1.63-1.626zM13.224 4.333h.17l2.273 2.268v.17l-2.443-2.438zM12.41 4.333h.17l3.087 3.08v.17l-3.257-3.25zM11.596 4.333h.17l3.9 3.892v.108h-.06l-4.01-4zM10.782 4.333h.17l4.01 4h-.17l-4.01-4zM9.968 4.333h.17l4.009 4h-.17l-4.01-4zM9.154 4.333h.17l4.009 4h-.17l-4.01-4zM8.34 4.333h.17l4.01 4h-.17l-4.01-4zM7.521 4.333h.17l4.01 4h-.17l-4.01-4zM6.707 4.333h.17l4.01 4h-.17l-4.01-4zM5.892 4.333h.17l4.009 4h-.17l-4.01-4zM5.077 4.333h.17l4.01 4h-.17l-4.01-4zM4.333 4.403v-.07h.1l4.01 4h-.11v.06l-4-3.99zM4.333 5.215v-.17l4 3.991v.17l-4-3.99zM4.333 6.027v-.17l4 3.991v.17l-4-3.99zM4.333 6.84v-.17l4 3.99v.17l-4-3.99zM4.333 7.652v-.17l4 3.99v.17l-4-3.99zM4.333 8.464v-.17l4 3.99v.17l-4-3.99zM4.333 9.276v-.17l4 3.991v.17l-4-3.991zM4.333 10.088v-.17l4 3.991v.17l-4-3.991zM4.333 10.9v-.17l4 3.991v.17l-4-3.991zM4.333 11.712v-.17l4 3.991v.134h-.036l-3.964-3.955zM4.333 12.526v-.17l3.318 3.31h-.17l-3.148-3.14zM4.333 13.34v-.169l2.502 2.496h-.17L4.333 13.34zM4.333 14.152v-.169l1.688 1.684h-.17l-1.518-1.514zM4.333 14.965v-.17l.874.872h-.17l-.704-.702zM15.667 5.146l-.815-.813h.17l.645.644v.169z" fill="#06FDB7"></path><path d="M23 15.667h-7.333V23H23v-7.333z" fill="#5B2AD8"></path><path d="M15.667 15.667H8.333V23h7.334v-7.333z" fill="#06FDB7"></path>`,
32718
+ internlm: `<path d="M5.54 19.662s2.24-.25 2.365-.29c.125-.042 2.45.082 2.45.082l1.493.374 1.37.498.373.125 2.033-.748 2.45-.373 1.659.041 1.286.166.54.166-.042 2.242-1.12-.291-2.159-.166-1.494.124-1.286.291-1.161.374-.83.332-1.744-.664-2.116-.416H7.158l-1.618.291v-2.158z" fill="#858599" fill-opacity=".5"></path><path d="M13.46 23c-3.773-2.078-7.78-.832-7.82-.819l-.453.144v-2.86l.24-.078c.174-.056 4.324-1.354 8.366.871l-.333.607c-3.244-1.786-6.66-1.115-7.58-.885V21.4c1.203-.286 4.595-.834 7.913.993L13.46 23V23z" fill="#858599"></path><path d="M13.413 23l-.334-.607c3.319-1.827 6.71-1.279 7.914-.993v-1.419c-.92-.231-4.337-.9-7.58.885l-.334-.607c4.042-2.225 8.192-.927 8.366-.87l.24.077v2.862l-.452-.147c-.04-.013-4.046-1.258-7.82.819z" fill="#858599"></path><path d="M17.756 16.476a.904.904 0 00-.264-.651.822.822 0 00-.632-.255.997.997 0 00-.644.293c-.175.212-.26.433-.259.685a.874.874 0 00.256.632c.175.187.39.272.644.255.246 0 .459-.1.633-.293a.97.97 0 00.268-.667l-.002.001zM10.769 17.143a.928.928 0 00.264-.658.993.993 0 00-.262-.679.908.908 0 00-.633-.227 1.089 1.089 0 00-.644.274 1.005 1.005 0 00-.265.685c0 .25.089.465.264.643.17.187.383.271.636.255.26-.008.471-.1.639-.293z" fill="#858599" fill-opacity=".5"></path><path d="M13.4 19.65c-.693 0-1.374-.058-1.895-.192-1.403-.36-2.52-1.01-3.413-1.986-.929-1.017-.988-1.996-1.05-3.033-.008-.133-.016-.267-.026-.405-.083-1.147-.626-2.941-.631-2.958l-.043-.141.086-.119A6.966 6.966 0 019.44 8.441c1.128-.47 2.47-.716 4.105-.752 2.721-.159 5.688.973 7.056 2.692l.086.109-.62 2.89c-.006.155-.052.968-.276 2.63-.263 1.947-2.668 3.061-3.903 3.377-.628.162-1.57.262-2.488.262zm-6.41-8.603c.134.46.538 1.912.613 2.944.01.139.018.277.026.412.06 1.01.109 1.809.896 2.672.815.89 1.837 1.484 3.125 1.814 1.092.28 3.061.194 4.091-.071.887-.228 3.24-1.19 3.468-2.889.24-1.786.272-2.593.273-2.6v-.026l.572-2.664c-.9-1.728-1.433-2.082-2.578-2.514-1.206-.455-2.677.075-3.903.148h-.01c-3.126.068-5.418-.935-6.574 2.773h.001z" fill="#858599"></path><path d="M19.545 10.862c.223.573.317.86.526 1.386 0 0 .552-.887.727-1.522.175-.641.068-1.458-.07-2.221-.344-1.282-.612-1.381-1.647-2.14a8.668 8.668 0 00-1.565-.84 12.303 12.303 0 00-3.83-.8 12.175 12.175 0 00-3.842.57 8.258 8.258 0 00-1.602.745c-1.075.695-1.823 1.674-2.24 2.932-.112.473-.29.927-.245 1.365.2 2.01 1.512 2.893 1.422 2.409-.117-.625-.042-.994.119-1.592.304-1.13 1.025-1.965 2.163-2.497h.004c.221-.062 1.344-.7 2.834.062.396.17 1.088.629 1.434.618.347-.01.846-.345 1.21-.572.683-.428 1.33-.574 2.184-.303 1.243.39 2.005 1.274 2.418 2.401z" fill="#858599"></path><path d="M1.217 9.86l.934.274 1.071-.055.77-.522.825-.742.604-.825.77-.797.741-.467 1.016-.22-.687 1.209-.577.576-1.209 1.676-.549.825-.632.44-.907.604s-.797.165-.879.192c-.081.028-.741.138-.741.138l-.577-.028-.44-.137.412-.825.056-.604v-.714l-.001.002z" fill="#858599" fill-opacity=".5"></path><path d="M3.607 5.108l-.083.63-.22.441-.274.412-.688.412.825.412.907.357.934.193.412.028.99-.688 1.043-.934-.357-.11-1.29-.137-.963-.358-.687-.356-.55-.302z" fill="#858599" fill-opacity=".5"></path><path d="M1.521 12.399c-.29 0-.596-.018-.917-.051L0 12.278l.298-.19.159-.173c.022-.033.085-.144.19-.377v-.002c.17-.365.228-.975.177-1.813l-.036-.564.435.36c.454.376 1.024.466 1.74.272.64-.182 1.337-.78 2.068-1.774.673-.968 1.64-1.624 2.88-1.952l.116-.031.783.61-.704-.05a2.182 2.182 0 00-.191.206l-.014.017-.018.016c-.404.718-.982 1.426-1.56 2.201l-.008.014c-.089.156-.18.317-.279.477v.009l-.032.051c-.592.962-1.243 1.683-1.935 2.145-.635.445-1.49.67-2.548.67v-.001zm-.5-.505c1.194.077 2.124-.112 2.77-.567l.005-.003c.626-.417 1.223-1.078 1.773-1.964a.244.244 0 01.041-.074c.098-.159.19-.321.28-.48v-.001c.392-.75.842-1.417 1.343-1.988-.748.33-1.341.82-1.8 1.481l-.004.006c-.808 1.101-1.572 1.742-2.333 1.958-.673.182-1.263.15-1.764-.095.01.69-.068 1.207-.237 1.573-.026.058-.05.108-.072.153h-.002z" fill="#858599"></path><path d="M1.577 12.399c-.29 0-.596-.018-.917-.051l.05-.486c1.371.145 2.425-.035 3.136-.535l.006-.003c.626-.417 1.222-1.078 1.772-1.963a.277.277 0 01.079-.116l.32.37a.22.22 0 00.072-.141l-.005.058-.03.052c-.592.962-1.243 1.683-1.935 2.145-.636.445-1.49.67-2.548.67zM5.751 7.717a9.381 9.381 0 01-.311.016c-.823.029-1.7-.2-2.615-.682.792-.512 1.013-1.096.982-1.621.189.15.386.281.591.393 1.345.758 2.766.878 5.195.198l-.165-.46c-2.308.637-3.558.532-4.793-.165a3.803 3.803 0 01-.967-.759l-.033-.036-.5-.542.094.697c.014.058.3 1.417-1.01 2.08l-.398.201.383.228c1.073.638 2.114.96 3.094.96l.453-.507v-.001zM11.93 15.21a.405.405 0 01-.366-.253c-.326-.745-.582-1.055-.969-1.525-.39-.474-1.223-1.277-1.36-1.393-.184-.156-.236-.368-.126-.515.055-.072.219-.219.556.005.683.452 2.198 1.812 2.608 2.904.15.397 0 .667-.201.749a.367.367 0 01-.143.028h.001zM14.877 15.23a.37.37 0 01-.146-.03c-.201-.085-.346-.357-.192-.752.424-1.086 1.957-2.427 2.645-2.87.34-.22.502-.072.556.002.109.147.054.358-.131.512-.139.115-.982.905-1.379 1.376-.392.465-.651.772-.988 1.513a.404.404 0 01-.364.25v-.002z" fill="#858599"></path><path d="M16.382 3.316c.01-.566-.265-1.054-.827-1.462-.57-.4-1.252-.602-2.045-.608-.792-.006-1.471.189-2.031.587-.563.401-.85.884-.857 1.445.002.176.017.336.04.486 2.1-.676 3.981-.62 5.64.167.045-.21.072-.414.08-.616v.001z" fill="#858599" fill-opacity=".5"></path><path d="M7.6 14.716l-.01-.024a1.824 1.824 0 01-.072-.192l-.059-.189-.388.013-.03.326c.002.013.009.044.016.1v.011c.003.02.004.036.008.052a.555.555 0 01-.164.431c-.112.12-.258.172-.45.164-.24-.01-.32-.105-.358-.176-.105-.19-.112-.291-.107-.336.015-.123.04-.254.077-.385.055-.206.013-.444-.126-.708l-.143-.272a1.787 1.787 0 01-.14-.384.974.974 0 01.022-.458.641.641 0 01.264-.374.695.695 0 01.496-.1l.015.002h.015c.192 0 .349.02.469.051a2.208 2.208 0 01-.027-.58 1.5 1.5 0 00-.38-.107H6.52l-.095-.008a1.369 1.369 0 00-.826.189c-.272.16-.456.394-.544.7a1.691 1.691 0 00-.03.815c.008.041.017.09.033.136.043.135.113.285.21.446.148.243.193.323.205.35l.005.009c.018.033.022.084.01.15l-.005.023a7.4 7.4 0 01-.034.172c-.115.298-.127.574-.036.815a.964.964 0 00.486.558c.134.066.288.108.46.125.094.01.192.01.294.005a.957.957 0 00.784-.454 1.13 1.13 0 00.17-.87l-.004-.026H7.6zM21.925 12.059a1.165 1.165 0 00-.556-.697h-.001a1.325 1.325 0 00-.797-.175l-.031.003-.093.011h-.008a1.553 1.553 0 00-.528.197 1.959 1.959 0 01-.016.563l.1-.04c.128-.053.302-.095.532-.13l.013-.002a.567.567 0 01.474.103c.155.113.26.254.32.428.05.164.057.305.022.43a2.77 2.77 0 01-.144.41 9.169 9.169 0 01-.191.383.908.908 0 00-.102.57c.024.176.05.322.078.446a.608.608 0 01-.036.329l-.003.006c-.037.117-.235.18-.35.208-.263.063-.381-.033-.451-.12a.78.78 0 01-.173-.51l.004-.053a.806.806 0 01.014-.093l-.008-.337-.431.01-.046.185a1.285 1.285 0 01-.064.188l-.011.027-.005.029c-.05.307.013.598.187.868l.004.006c.19.274.463.426.787.437.087.005.17.002.25-.004.192-.018.363-.069.509-.15a.992.992 0 00.459-.567c.085-.252.068-.527-.05-.816l-.03-.171-.002-.013a.306.306 0 01.015-.18c.045-.108.106-.233.181-.375.098-.173.162-.32.196-.444a.665.665 0 00.033-.152 1.75 1.75 0 00-.053-.806l.002-.002zM16.59 3.853c.033-.185.053-.359.06-.533.012-.648-.301-1.209-.93-1.667-.609-.427-1.344-.646-2.184-.653-.843-.008-1.575.207-2.176.633-.628.45-.951 1.002-.96 1.643v.006c.002.128.01.256.026.39a.38.38 0 00-.095.23v.01c0 .216.032.433.097.643l.001.006c.09.265.245.518.46.75l.063.068.567.063c.485.282 1.132.433 1.928.447h.103c.587 0 1.1-.072 1.527-.213l.011-.004c.16-.063.316-.138.465-.224.452.043.791-.18.965-.633l.043-.046-.002-.065c.067-.205.184-.608.03-.851h.001zM11.643 2.03c.514-.365 1.149-.547 1.888-.542.74.006 1.38.196 1.903.562.497.361.735.774.727 1.255-.004.089-.01.18-.023.274a6.882 6.882 0 00-2.685-.527c-.816 0-1.67.13-2.558.39a4.038 4.038 0 01-.006-.165c.006-.482.253-.89.754-1.247zm4.513 2.293l-.165.357s-.215.311-.45.272l-.092-.015-.078.049a2.724 2.724 0 01-.454.226c-.397.13-.89.192-1.462.184-.708-.014-1.276-.14-1.688-.38l-.037-.021-.048-.03-.491-.054c-.094-.11-.226-.34-.226-.34l-.135-.392-.008-.204c1.988-.626 3.79-.574 5.355.155.002.029-.02.193-.02.193zm.147.364v-.004l.003.004h-.003z" fill="#858599"></path>`,
32719
+ ai360: `<path clip-rule="evenodd" d="M12 0h.018c1.473-.002 2.88.261 4.179.754C20.755 2.456 24 6.85 24 12c0 6.627-5.373 12-12 12S0 18.627 0 12 5.373 0 12 0zm8.604 18.967A11.024 11.024 0 0023.07 12c0-1.717-.39-3.344-1.089-4.794a2.59 2.59 0 01-3.214.62 6.278 6.278 0 01-1.333-.992C16.283 5.73 15.109 4.66 13.696 3.9c-3.211-1.729-6.825-1.501-9.695.447A11.033 11.033 0 00.93 12c0 1.663.367 3.241 1.024 4.657.75-.973 2.131-1.346 3.232-.71.667.384 1.257.92 1.837 1.447l.176.16c1.365 1.234 2.794 2.355 4.558 2.965 3.053 1.053 6.356.437 8.847-1.552z" fill="url(#lobe-icons-ai-360-0-_R_0_)" fill-rule="evenodd"></path><path d="M5.643 10.312c-.83.11-1.401.766-1.408 1.618a1.715 1.715 0 001.45 1.72c.805.128 1.64-.426 1.87-1.26.046-.167.076-.338.106-.51.025-.14.05-.282.084-.42.318-1.317 1.237-1.95 2.788-1.93 1.086.013 1.318.271 1.68 1.855.017.076.043.151.07.226.26.714.976 1.17 1.67 1.065a1.647 1.647 0 001.38-1.438c.083-.729-.348-1.264-1.122-1.575-.34-.136-.664-.158-.995-.141-.726.037-1.121-.36-1.339-.977a3.359 3.359 0 01-.134-.65c-.014-.093-.027-.186-.043-.278-.156-.887-.835-1.51-1.669-1.532-.791-.02-1.464.551-1.665 1.418l-.06.27-.025.117c-.355 1.636-.974 2.205-2.638 2.422z" fill="url(#lobe-icons-ai-360-1-_R_0_)"></path><path d="M18.059 13.644c.989-.206 1.577-.838 1.592-1.697.015-.83-.624-1.582-1.46-1.724-.77-.13-1.599.383-1.844 1.18-.069.22-.117.448-.165.676-.06.29-.122.58-.225.854-.367.986-1.593 1.546-2.926 1.394-.824-.095-1.106-.446-1.342-1.674-.18-.938-.864-1.535-1.681-1.467-.85.07-1.515.829-1.468 1.673.05.892.678 1.44 1.705 1.489 1.375.064 1.75.396 1.926 1.787.067.531.267.967.685 1.288 1.02.783 2.407.208 2.66-1.108l.022-.114c.152-.796.3-1.577 1.04-2.101.36-.255.761-.326 1.166-.397.105-.019.21-.037.315-.06z" fill="url(#lobe-icons-ai-360-2-_R_0_)"></path><path d="M13.83 7.961a.755.755 0 11-1.51 0 .755.755 0 011.51 0z" fill="url(#lobe-icons-ai-360-3-_R_0_)"></path><path d="M10.809 16.678a.755.755 0 100-1.511.755.755 0 000 1.51z" fill="url(#lobe-icons-ai-360-4-_R_0_)"></path><defs><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-ai-360-0-_R_0_" x1="12" x2="12" y1="0" y2="24"><stop stop-color="#12B7FA"></stop><stop offset="1" stop-color="#006ffb"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-ai-360-1-_R_0_" x1="11.943" x2="11.943" y1="6.085" y2="17.778"><stop stop-color="#006ffb"></stop><stop offset="1" stop-color="#12B7FA"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-ai-360-2-_R_0_" x1="11.943" x2="11.943" y1="6.085" y2="17.778"><stop stop-color="#006ffb"></stop><stop offset="1" stop-color="#12B7FA"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-ai-360-3-_R_0_" x1="11.943" x2="11.943" y1="6.085" y2="17.778"><stop stop-color="#006ffb"></stop><stop offset="1" stop-color="#12B7FA"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-ai-360-4-_R_0_" x1="11.943" x2="11.943" y1="6.085" y2="17.778"><stop stop-color="#006ffb"></stop><stop offset="1" stop-color="#12B7FA"></stop></linearGradient></defs>`,
32720
+ microsoft: `<path d="M11.49 2H2v9.492h9.492V2h-.002z" fill="#F25022"></path><path d="M22 2h-9.492v9.492H22V2z" fill="#7FBA00"></path><path d="M11.49 12.508H2V22h9.492v-9.492h-.002z" fill="#00A4EF"></path><path d="M22 12.508h-9.492V22H22v-9.492z" fill="#FFB900"></path>`,
32721
+ nvidia: `<path d="M10.212 8.976V7.62c.127-.01.256-.017.388-.021 3.596-.117 5.957 3.184 5.957 3.184s-2.548 3.647-5.282 3.647a3.227 3.227 0 01-1.063-.175v-4.109c1.4.174 1.681.812 2.523 2.258l1.873-1.627a4.905 4.905 0 00-3.67-1.846 6.594 6.594 0 00-.729.044m0-4.476v2.025c.13-.01.259-.019.388-.024 5.002-.174 8.261 4.226 8.261 4.226s-3.743 4.69-7.643 4.69c-.338 0-.675-.031-1.007-.092v1.25c.278.038.558.057.838.057 3.629 0 6.253-1.91 8.794-4.169.421.347 2.146 1.193 2.501 1.564-2.416 2.083-8.048 3.763-11.24 3.763-.308 0-.603-.02-.894-.048V19.5H24v-15H10.21zm0 9.756v1.068c-3.356-.616-4.287-4.21-4.287-4.21a7.173 7.173 0 014.287-2.138v1.172h-.005a3.182 3.182 0 00-2.502 1.178s.615 2.276 2.507 2.931m-5.961-3.3c1.436-1.935 3.604-3.148 5.961-3.336V6.523C5.81 6.887 2 10.723 2 10.723s2.158 6.427 8.21 7.015v-1.166C5.77 16 4.25 10.958 4.25 10.958h-.002z" fill="#74B71B" fill-rule="nonzero"></path>`,
32722
+ amazon: `<defs><linearGradient id="lobe-icons-bedrock-_R_0_" x1="80%" x2="20%" y1="20%" y2="80%"><stop offset="0%" stop-color="#6350FB"></stop><stop offset="50%" stop-color="#3D8FFF"></stop><stop offset="100%" stop-color="#9AD8F8"></stop></linearGradient></defs><path d="M13.05 15.513h3.08c.214 0 .389.177.389.394v1.82a1.704 1.704 0 011.296 1.661c0 .943-.755 1.708-1.685 1.708-.931 0-1.686-.765-1.686-1.708 0-.807.554-1.484 1.297-1.662v-1.425h-2.69v4.663a.395.395 0 01-.188.338l-2.69 1.641a.385.385 0 01-.405-.002l-4.926-3.086a.395.395 0 01-.185-.336V16.3L2.196 14.87A.395.395 0 012 14.555L2 14.528V9.406c0-.14.073-.27.192-.34l2.465-1.462V4.448c0-.129.062-.249.165-.322l.021-.014L9.77 1.058a.385.385 0 01.407 0l2.69 1.675a.395.395 0 01.185.336V7.6h3.856V5.683a1.704 1.704 0 01-1.296-1.662c0-.943.755-1.708 1.685-1.708.931 0 1.685.765 1.685 1.708 0 .807-.553 1.484-1.296 1.662v2.311a.391.391 0 01-.389.394h-4.245v1.806h6.624a1.69 1.69 0 011.64-1.313c.93 0 1.685.764 1.685 1.707 0 .943-.754 1.708-1.685 1.708a1.69 1.69 0 01-1.64-1.314H13.05v1.937h4.953l.915 1.18a1.66 1.66 0 01.84-.227c.931 0 1.685.764 1.685 1.707 0 .943-.754 1.708-1.685 1.708-.93 0-1.685-.765-1.685-1.708 0-.346.102-.668.276-.937l-.724-.935H13.05v1.806zM9.973 1.856L7.93 3.122V6.09h-.778V3.604L5.435 4.669v2.945l2.11 1.36L9.712 7.61V5.334h.778V7.83c0 .136-.07.263-.184.335L7.963 9.638v2.081l1.422 1.009-.446.646-1.406-.998-1.53 1.005-.423-.66 1.605-1.055v-1.99L5.038 8.29l-2.26 1.34v1.676l1.972-1.189.398.677-2.37 1.429V14.3l2.166 1.258 2.27-1.368.397.677-2.176 1.311V19.3l1.876 1.175 2.365-1.426.398.678-2.017 1.216 1.918 1.201 2.298-1.403v-5.78l-4.758 2.893-.4-.675 5.158-3.136V3.289L9.972 1.856zM16.13 18.47a.913.913 0 00-.908.92c0 .507.406.918.908.918a.913.913 0 00.907-.919.913.913 0 00-.907-.92zm3.63-3.81a.913.913 0 00-.908.92c0 .508.406.92.907.92a.913.913 0 00.908-.92.913.913 0 00-.908-.92zm1.555-4.99a.913.913 0 00-.908.92c0 .507.407.918.908.918a.913.913 0 00.907-.919.913.913 0 00-.907-.92zM17.296 3.1a.913.913 0 00-.907.92c0 .508.406.92.907.92a.913.913 0 00.908-.92.913.913 0 00-.908-.92z" fill="url(#lobe-icons-bedrock-_R_0_)" fill-rule="nonzero"></path>`,
32723
+ ibm: `<g fill="#1F70C1" fill-rule="evenodd"><path clip-rule="evenodd" d="M24 16.333V17h-3.158v-.667H24zm-7.579 0V17h-3.158v-.667h3.158zm2.464 0L18.63 17l-.25-.667h.504zm-7.075 0a2.528 2.528 0 01-1.717.667h-5.04v-.667h6.757zm-7.389 0V17H0v-.667h4.421zm12-1.333v.667h-3.158V15h3.158zm2.958 0l-.246.667h-1L17.885 15h1.494zm-6.937 0c-.057.237-.148.46-.265.667H5.053V15h7.39zm-8.02 0v.667H0V15h4.421zM24 15v.667h-3.158V15H24zm-1.263-1.333v.666h-1.895v-.666h1.895zm-6.316 0v.666h-1.895v-.666h1.895zm3.453 0l-.248.666h-1.989l-.25-.666h2.487zm-7.52 0c.056.212.088.435.088.666h-2.337v-.666h2.249zm-4.143 0v.666H6.316v-.666H8.21zm-5.053 0v.666H1.263v-.666h1.895zm19.579-1.334V13h-1.895v-.667h1.895zm-6.316 0V13h-1.895v-.667h1.895zm3.948 0l-.247.667h-2.987l-.245-.667h3.48zm-8.792 0c.218.188.405.414.55.667H6.315v-.667h5.26zm-8.42 0V13H1.264v-.667h1.895zM18.456 11l.177.539.176-.539h3.929v.667h-1.895v-.613l-.215.613H16.63l-.209-.613v.613h-1.895V11h3.929zM3.158 11v.667H1.263V11h1.895zm8.968 0a2.555 2.555 0 01-.55.667h-5.26V11h5.81zm10.61-1.333v.666h-3.709l.224-.666h3.486zm-4.722 0l.224.666h-3.712v-.666h3.488zm-5.572 0c0 .23-.032.454-.088.666h-2.249v-.666h2.337zm-4.231 0v.666H6.316v-.666H8.21zm-5.053 0v.666H1.263v-.666h1.895zm14.419-1.334l.22.667h-4.534v-.667h4.314zm6.423 0V9h-4.536l.229-.667H24zm-11.823 0c.117.206.208.43.265.667h-7.39v-.667h7.125zm-7.756 0V9H0v-.667h4.421zM17.133 7l.224.667h-4.094V7h3.87zM24 7v.667h-4.089L20.13 7H24zM10.093 7c.662 0 1.264.253 1.717.667H5.053V7h5.04zM4.42 7v.667H0V7h4.421z"></path></g>`,
32724
+ databricks: `<path d="M21.821 9.894l-9.81 5.595L1.505 9.511 1 9.787v4.34l11.01 6.256 9.811-5.574v2.297l-9.81 5.596-10.506-5.979L1 17v.745L12.01 24 23 17.745v-4.34l-.505-.277-10.484 5.957-9.832-5.574v-2.298l9.832 5.574L23 10.532V6.255l-.547-.319-10.442 5.936-9.327-5.276 9.327-5.298 7.663 4.362.673-.383v-.532L12.011 0 1 6.255v.681l11.01 6.255 9.811-5.595z" fill="#EE3D2C" fill-rule="nonzero"></path>`,
32725
+ perplexity: `<path d="M19.785 0v7.272H22.5V17.62h-2.935V24l-7.037-6.194v6.145h-1.091v-6.152L4.392 24v-6.465H1.5V7.188h2.884V0l7.053 6.494V.19h1.09v6.49L19.786 0zm-7.257 9.044v7.319l5.946 5.234V14.44l-5.946-5.397zm-1.099-.08l-5.946 5.398v7.235l5.946-5.234V8.965zm8.136 7.58h1.844V8.349H13.46l6.105 5.54v2.655zm-8.982-8.28H2.59v8.195h1.8v-2.576l6.192-5.62zM5.475 2.476v4.71h5.115l-5.115-4.71zm13.219 0l-5.115 4.71h5.115v-4.71z" fill="#22B8CD" fill-rule="nonzero"></path>`,
32726
+ ai21: `<g fill="#E91E63" fill-rule="evenodd"><path d="M6.47 17l-.367-1.189H2.718L2.35 17H0l3.398-9.789h2.026L8.864 17H6.47zm-2.052-6.993l-1.17 4.028H5.56l-1.142-4.028zm4.707-2.796h2.23V17h-2.23V7.211zM11.955 15c.1-.483.277-.946.524-1.37.214-.359.482-.68.795-.951.32-.273.658-.52 1.013-.741.28-.168.54-.33.781-.483.222-.14.433-.296.632-.468.172-.148.317-.325.428-.525.107-.199.16-.423.157-.65 0-.392-.104-.674-.313-.846a1.176 1.176 0 00-.775-.259 1.207 1.207 0 00-.863.329c-.231.219-.347.585-.347 1.098H11.8a3.387 3.387 0 01.224-1.245c.146-.377.371-.716.66-.993.306-.29.667-.514 1.06-.657A4.04 4.04 0 0115.183 7c.42-.002.84.057 1.244.175.376.107.73.287 1.04.531.305.246.55.562.714.923.185.419.275.875.265 1.335.005.39-.084.774-.259 1.12-.167.328-.38.63-.632.894-.246.259-.517.49-.808.693-.29.2-.554.37-.789.51-.326.224-.596.417-.809.58a3.872 3.872 0 00-.51.455 1.229 1.229 0 00-.265.434 1.633 1.633 0 00-.074.517h4.078V17h-6.606a9.24 9.24 0 01.183-2zM18.8 8.93a5.05 5.05 0 001.135-.105c.25-.049.484-.156.686-.314.163-.139.28-.324.34-.532.068-.25.1-.51.095-.77H23V17h-2.243v-6.475H18.8V8.93z"></path></g>`,
32727
+ upstage: `<path d="M19.763 0l-.373 1.297h2.594L22.354 0h-2.591zM16.192 2.27l-.376 1.298h5.52l.37-1.298h-5.514zM12.897 4.54l-.376 1.298h8.166l.37-1.298h-8.16zM2.85 6.81l-.377 1.298h17.565l.37-1.297H2.848zM3.884 9.081l-.376 1.297H19.39l.37-1.297H3.882zM4.088 24l.376-1.297H1.866L1.5 24h2.588zM7.662 21.73l.376-1.297H2.515L2.15 21.73h5.513zM10.957 19.459l.376-1.297h-8.17l-.366 1.297h8.16zM21.005 17.189l.376-1.297H3.812l-.366 1.297h17.559zM19.967 14.919l.376-1.297H4.461l-.366 1.297h15.872zM18.786 12.649l.376-1.297H4.26l-.366 1.297h14.893z" fill="url(#lobe-icons-upsate-_R_0_)"></path><defs><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-upsate-_R_0_" x1="11.927" x2="11.927" y2="24"><stop offset="0" stop-color="#AEBCFE"></stop><stop offset="1" stop-color="#805DFA"></stop></linearGradient></defs>`,
32728
+ jina: `<g fill="#0F1E3D" fill-rule="evenodd"><path d="M6.608 21.416a4.608 4.608 0 100-9.217 4.608 4.608 0 000 9.217zM20.894 2.015c.614 0 1.106.492 1.106 1.106v9.002c0 5.13-4.148 9.309-9.217 9.37v-9.355l-.03-9.032c0-.614.491-1.106 1.106-1.106h7.158l-.123.015z"></path></g>`,
32729
+ reka: `<g fill="#0F0F0F" fill-rule="evenodd"><path d="M3.662.014C4.347.004 5.052.012 5.74.012h3.9q1.01.006 2.02-.006c-.005.87-.01 1.779 0 2.647-.16-.027-.593-.018-.774-.018H4.943l-1.408.001c-.263.001-.595.01-.852-.004.014 1.216.002 2.455.002 3.673v4.681c0 .185-.008.48.016.656-.834-.039-1.849-.005-2.7-.01.032-.717.008-1.576.008-2.307V3.69c-.001-.44-.023-.812.065-1.246.11-.557.377-1.07.77-1.481A3 3 0 0 1 2.756.03c.245-.022.644-.01.905-.017M23.74 11.641c-.688-.03-1.54-.007-2.237-.007H15.92c-.853.001-1.373.024-2.139-.422a3.02 3.02 0 0 1-1.4-1.842c-.146-.553-.1-1.285-.1-1.863V5.299l-.002-1.535c0-.37-.011-.794.035-1.156.053-.388.183-.763.382-1.1A3.01 3.01 0 0 1 15.102.013c.387-.022.869-.01 1.261-.01l2.224.001h1.607c.88-.001 1.449-.037 2.237.426a3.02 3.02 0 0 1 1.293 1.544c.08.217.12.395.177.615v1.027c-.072.167-.123.472-.227.719a3.04 3.04 0 0 1-1.176 1.375c-.318.204-.74.34-1.098.467l-.951.34-3.181 1.132c-.552.196-1.205.41-1.74.626-.03-.646.008-1.316-.007-1.965-.005-.2-.006-.432.01-.632.463-.189.96-.368 1.43-.547l2.719-1.038c.357-.137.717-.268 1.074-.405.174-.067.352-.135.433-.315.186-.414-.112-.74-.538-.739q-.555 0-1.106.003l-2.161-.002H16.12c-.248 0-.506-.008-.752.018-.124.008-.327.157-.362.28-.07.246-.052.597-.052.852l.003 1.055V7.5c0 .497.01 1.024-.004 1.519.334-.026.816-.01 1.164-.01H18.2c1.825 0 3.726-.027 5.547.004-.023.228-.01.686-.01.93zm-11.272.779h7.626c.361 0 .814-.013 1.165.03a3.04 3.04 0 0 1 2.45 1.907c.084.215.13.419.192.64v6.485c-.052.193-.097.395-.166.58a3.05 3.05 0 0 1-1.352 1.597c-.154.088-.241.13-.404.19-.078.028-.388.124-.43.15h-6.903c-.062-.036-.497-.172-.648-.245A3.05 3.05 0 0 1 12.444 22c-.47-1.365.06-2.953 1.31-3.685.356-.209.745-.33 1.132-.467l1.37-.486c1.465-.52 2.956-1.073 4.424-1.571-.029.83.016 1.742-.005 2.588-.121.057-.337.13-.468.18l-.894.34-2.847 1.085c-.158.06-.327.118-.481.181-.188.098-.73.226-.864.37-.36.388-.097.89.415.887.42-.003.772 0 1.15-.002l1.988.001h1.367c.256 0 .52.008.774-.013.21-.018.393-.228.416-.432.026-.229.018-.458.017-.688l-.001-1.018v-2.639c0-.516-.008-1.054.006-1.568-1.352-.03-2.79-.007-4.148-.007-1.532 0-3.117-.02-4.645.007.015-.292.006-.642.006-.939zm-4.554.015c.33-.021.705-.002 1.04-.008.847-.016 1.738.023 2.582-.002-.195.22-.434.43-.646.637l-1.017 1.002L7.04 16.84c-.435.427-.912.866-1.333 1.304.124.154.418.431.571.585l1.084 1.082 2.176 2.168q1.034 1 2.047 2.022H7.849c-.248-.236-.495-.493-.74-.735l-1.632-1.6q-.595-.569-1.18-1.147c-.27-.268-.57-.541-.775-.86a2.656 2.656 0 0 1 .338-3.262c.21-.22.454-.447.672-.66l1.58-1.548q.611-.612 1.239-1.21c.137-.134.427-.44.564-.543m-7.909-.001c.755-.032 1.53.006 2.286-.008.13-.002.273-.003.403.002-.029.317-.01.988-.01 1.338v2.557L2.686 24H.007l.002-7.917V13.61c0-.34-.018-.847-.003-1.175"></path></g>`,
32730
+ snowflake: `<path clip-rule="evenodd" d="M23.252 10.365l-2.843 1.636 2.843 1.631a1.47 1.47 0 01.697.903 1.492 1.492 0 01-.15 1.135c-.202.342-.53.591-.912.693a1.498 1.498 0 01-1.132-.15l-5.09-2.924a1.473 1.473 0 01-.68-.851 1.446 1.446 0 01-.068-.485 1.5 1.5 0 01.745-1.248l5.09-2.921a1.496 1.496 0 012.044.547 1.479 1.479 0 01-.544 2.034zm-2.692 7.927l-5.087-2.92a1.477 1.477 0 00-.867-.195 1.478 1.478 0 00-.982.468c-.257.276-.4.639-.403 1.017v5.847A1.49 1.49 0 0014.718 24c.828 0 1.497-.668 1.497-1.491v-3.27l2.849 1.636a1.493 1.493 0 002.044-.544 1.49 1.49 0 00-.548-2.04zm-5.87-5.719l-2.116 2.102a.42.42 0 01-.265.112h-.621a.427.427 0 01-.265-.112l-2.115-2.102a.42.42 0 01-.11-.262v-.62a.43.43 0 01.11-.265l2.114-2.102a.426.426 0 01.264-.11h.623a.422.422 0 01.265.11l2.116 2.102a.43.43 0 01.109.265v.62a.428.428 0 01-.11.262zM13 11.99a.442.442 0 00-.113-.266l-.612-.607a.431.431 0 00-.266-.11h-.024a.426.426 0 00-.264.11l-.612.607a.436.436 0 00-.107.266v.024c0 .085.047.202.107.262l.612.61c.061.06.179.11.264.11h.024a.434.434 0 00.266-.11l.612-.61a.429.429 0 00.112-.262v-.024zM3.436 5.704l5.089 2.924c.274.157.578.219.868.195.375-.026.726-.194.983-.47.256-.275.4-.64.403-1.017V1.489C10.78.667 10.11 0 9.284 0c-.829 0-1.498.667-1.498 1.49v3.27l-2.85-1.639a1.496 1.496 0 00-2.045.546 1.489 1.489 0 00.546 2.037zm11.17 3.119c.29.024.594-.038.866-.195l5.087-2.923a1.474 1.474 0 00.697-.903 1.496 1.496 0 00-.149-1.135 1.496 1.496 0 00-2.044-.545L16.215 4.76V1.489C16.215.667 15.546 0 14.718 0c-.83 0-1.497.667-1.497 1.49v5.845a1.491 1.491 0 001.385 1.487zm-5.213 6.354a1.479 1.479 0 00-.868.194l-5.089 2.92a1.476 1.476 0 00-.696.905 1.498 1.498 0 00.148 1.135 1.496 1.496 0 002.044.543l2.851-1.636v3.27c0 .825.67 1.491 1.498 1.491.826 0 1.496-.667 1.496-1.49v-5.847a1.5 1.5 0 00-.401-1.017 1.477 1.477 0 00-.982-.468zm-1.38-2.74c.05-.156.072-.32.068-.484a1.497 1.497 0 00-.751-1.248l-5.084-2.92a1.499 1.499 0 00-2.045.547 1.481 1.481 0 00.549 2.034l2.841 1.636L.75 13.633a1.47 1.47 0 00-.698.903 1.492 1.492 0 00.15 1.135c.202.343.53.592.912.693.382.102.789.048 1.132-.15l5.086-2.924c.345-.195.577-.505.684-.852z" fill="#249EDC" fill-rule="evenodd"></path>`,
32731
+ sambanova: `<path d="M23 23h-1.223V8.028c0-3.118-2.568-5.806-5.744-5.806H8.027c-3.176 0-5.744 2.565-5.744 5.686 0 3.119 2.568 5.684 5.744 5.684h.794c1.346 0 2.445 1.1 2.445 2.444 0 1.346-1.1 2.446-2.445 2.446H1v-1.223h7.761c.671 0 1.223-.551 1.223-1.16 0-.67-.552-1.16-1.223-1.16h-.794C4.177 14.872 1 11.756 1 7.909 1 4.058 4.176 1 8.027 1h8.066C19.88 1 23 4.239 23 8.028V23z" fill="#EE7624"></path><path d="M8.884 12.672c1.71.06 3.361 1.588 3.361 3.422 0 1.833-1.528 3.421-3.421 3.421H1v1.223h7.761c2.568 0 4.705-2.077 4.705-4.644 0-.672-.123-1.283-.43-1.894-.245-.551-.67-1.1-1.099-1.528-.489-.429-1.039-.734-1.65-.977-.525-.175-1.048-.193-1.594-.212-.218-.008-.441-.016-.669-.034-.428 0-1.406-.245-1.956-.61a3.369 3.369 0 01-1.223-1.406c-.183-.489-.305-.977-.305-1.528A3.417 3.417 0 017.96 4.482h8.066c1.895 0 3.422 1.65 3.422 3.483v15.032h1.223V8.027c0-2.568-2.077-4.768-4.645-4.768h-8c-2.568 0-4.705 2.077-4.705 4.646 0 .67.123 1.282.43 1.894a4.45 4.45 0 001.099 1.528c.429.428 1.039.734 1.588.976.306.123.611.183.976.246.857.06 1.406.123 1.466.123h.003z" fill="#EE7624"></path><path d="M1 23h7.761v-.003c3.85 0 7.03-3.116 7.09-7.026 0-3.79-3.117-6.906-6.967-6.906H8.09c-.672 0-1.222-.552-1.222-1.16 0-.608.487-1.16 1.159-1.16h8.069c.608 0 1.159.611 1.159 1.283v14.97h1.223V8.024c0-1.345-1.1-2.505-2.445-2.505H7.967a2.451 2.451 0 00-2.445 2.445 2.45 2.45 0 002.445 2.445h.794c3.176 0 5.744 2.568 5.744 5.684s-2.568 5.684-5.744 5.684H1V23z" fill="#EE7624"></path>`,
32732
+ infinigence: `<path d="M14.186 19.885V4.226H5v4.137h4.226v11.522H5V24h13.412v-4.115h-4.226z" fill="#7F1084"></path><path d="M18.412 0h-4.226v4.226h4.226V0z" fill="#2EA7E0"></path>`,
32733
+ rwkv: `<defs><linearGradient id="lobe-icons-rwkv-_R_0_" x1="100%" x2="0%" y1="53.893%" y2="53.893%"><stop offset="0%" stop-color="#1D1A5C"></stop><stop offset="49.586%" stop-color="#3431C3"></stop><stop offset="100%" stop-color="#7361F7"></stop></linearGradient></defs><path d="M15.127 21.824c.093.299.339.553.345.896.022.107-.051.417-.168.21-.249-.832-.33-.035-1.065-1.184-.158-.313-.429-.055-.663-.04-.694-.228-.49-.293-.905.3-.315.088-.049-.643.101-.724.29-.248.749-.086.917-.356.282-1.143-.64-2.567-1.158-3.55-.169-.264.013-.577-.025-.862-.15-.408-.188-.302-.049-.734-.227-.473-.863.266-1.22.255-.285.004-.523-.45-.893-.48-1.335.004-2.581.808-3.926.671a1.228 1.228 0 00-.681.215c-.414.222-.909.203-1.288.522-.119.095-.27.104-.414.098-.27.04-.477.37-.784.34-.312-.109-.566.079-.86.057-.34-.285-.781-.057-1.174.008a.286.286 0 01-.308-.05c-.09-.072-.264-.082-.324-.177-.03-.059.028-.145.1-.204.527-.405 1.137-.666 1.72-.974 1.146-.594 2.118-1.463 3.16-2.218.066-.05.085-.12-.035-.119-1.612.135-3.146 1.048-4.74 1.012-.176.023-.339.127-.522.15-.876-.185.65-1.16.954-1.261 1.704-.711 3.598-.843 5.184-1.836.188-.132-.17-.268-.004-.53.39-1.29 1.576-1.805 2.735-2.184.594-.231 1.137-.672 1.797-.679.325.016.634-.113.852-.36 1.163-1.071 2.442-2.012 3.674-2.999 1.413-1.783 2.282-5.175 5.216-3.656.92.395 1.974.365 2.807.976.297.189.857.765.236.85-1.702.291-2.552-.23-2.63 1.454-.03.39.064.75-.158 1.086-.014.694.352 1.508-.084 2.129-.364.63-.078 1.413-.38 2.047-.22.534-.65.93-1.049 1.323-1.304 1.63-2.266 3.476-2.589 5.572-.122.627-.478 1.56.097 2.056.607.612 1.25 1.458 2.18 1.012.306-.14.884-.189.84.274-.05.083-.258-.098-.371-.056-.16.102.072.316.029.465-.022.14-.134.12-.23.054-.281-.112-.685.002-1.005-.01-.258.045-.512.162-.762.05-.116-.049-.229-.1-.356-.103-.39-.022-.884.182-1.103-.147-.242-.454-.293-.104-.532.048-.235-.015-.067-.35.014-.46.249-.57 1.846.517 1.183-.432-2.29-2.01-.777-2.686-1.646-2.69-.17-.089-.103-.405-.366-.173-.335.35-.46-.098-.46-.4-.04-.175-.177-.3-.125-.479.022-.39-.496.085-.38.41.057.616-.132 1.225-.102 1.833.24 1.276.41 2.897 1.864 3.276.177.076.463.432.253.565-.093-.01-.16-.11-.243-.153-.116-.078-.257.009-.378.018-.034.008-.088.007-.1.046l-.003.002z" fill="url(#lobe-icons-rwkv-_R_0_)" fill-rule="nonzero"></path>`,
32734
+ falcon: `<path d="M11.098 7.563H4.75V9.77h1.77v6.668h2.807V9.77h1.77V7.563zM14.812 7.563h-2.807v8.875h2.807V7.563zM19.433 7.563h-2.807v8.875h2.807V7.563z" fill="#6400FF"></path><path d="M12 24v-1.055c3.01 0 5.613-1.079 7.737-3.208 2.123-2.13 3.209-4.727 3.209-7.737 0-3.009-1.08-5.607-3.209-7.736-2.128-2.13-4.732-3.21-7.736-3.21V0c3.294 0 6.148 1.184 8.482 3.518C22.817 5.852 24 8.706 24 12c0 3.295-1.183 6.155-3.518 8.483C18.147 22.811 15.3 24 12.001 24z" fill="#6400FF"></path>`,
32735
+ groq: `<g fill="#F55036" fill-rule="evenodd"><path d="M12.036 2c-3.853-.035-7 3-7.036 6.781-.035 3.782 3.055 6.872 6.908 6.907h2.42v-2.566h-2.292c-2.407.028-4.38-1.866-4.408-4.23-.029-2.362 1.901-4.298 4.308-4.326h.1c2.407 0 4.358 1.915 4.365 4.278v6.305c0 2.342-1.944 4.25-4.323 4.279a4.375 4.375 0 01-3.033-1.252l-1.851 1.818A7 7 0 0012.029 22h.092c3.803-.056 6.858-3.083 6.879-6.816v-6.5C18.907 4.963 15.817 2 12.036 2z"></path></g>`,
32736
+ together: `<path d="M23.197 4.503A6 6 0 0015 2.307a5.973 5.973 0 00-2.995 4.933l5.996.008v.515h-5.996c.039.937.298 1.87.8 2.74a6 6 0 1010.39-6z" fill="#EF2CC1"></path><path d="M.805 4.5A6 6 0 003 12.697a5.972 5.972 0 005.77.127L5.779 7.627l.446-.257 2.997 5.192A6 6 0 10.804 4.5z" fill="#CAAEF5"></path><path d="M12 23.894a6 6 0 005.999-6c0-2.13-1.1-3.996-2.775-5.06l-3.005 5.189-.444-.258 2.997-5.192A6 6 0 1012 23.894z" fill="#FC4C02"></path>`,
32737
+ fireworks: `<path clip-rule="evenodd" d="M14.8 5l-2.801 6.795L9.195 5H7.397l3.072 7.428a1.64 1.64 0 003.038.002L16.598 5H14.8zm1.196 10.352l5.124-5.244-.699-1.669-5.596 5.739a1.664 1.664 0 00-.343 1.807 1.642 1.642 0 001.516 1.012L16 17l8-.02-.699-1.669-7.303.041h-.002zM2.88 10.104l.699-1.669 5.596 5.739c.468.479.603 1.189.343 1.807a1.643 1.643 0 01-1.516 1.012l-8-.018-.002.002.699-1.669 7.303.042-5.122-5.246z" fill="#5019C5" fill-rule="evenodd"></path>`,
32738
+ cerebras: `<g fill="#F15A29"><path clip-rule="evenodd" d="M14.121 2.701a9.299 9.299 0 000 18.598V22.7c-5.91 0-10.7-4.791-10.7-10.701S8.21 1.299 14.12 1.299V2.7zm4.752 3.677A7.353 7.353 0 109.42 17.643l-.901 1.074a8.754 8.754 0 01-1.08-12.334 8.755 8.755 0 0112.335-1.08l-.901 1.075zm-2.255.844a5.407 5.407 0 00-5.048 9.563l-.656 1.24a6.81 6.81 0 016.358-12.043l-.654 1.24zM14.12 8.539a3.46 3.46 0 100 6.922v1.402a4.863 4.863 0 010-9.726v1.402z" fill="#F15A29" fill-rule="evenodd"></path><path d="M15.407 10.836a2.24 2.24 0 00-.51-.409 1.084 1.084 0 00-.544-.152c-.255 0-.483.047-.684.14a1.58 1.58 0 00-.84.912c-.074.203-.11.416-.11.631 0 .218.036.43.11.631a1.594 1.594 0 00.84.913c.2.093.43.14.684.14.216 0 .417-.046.602-.135.188-.09.35-.225.475-.392l.928 1.006c-.14.14-.3.261-.482.363a3.367 3.367 0 01-1.083.38c-.17.026-.317.04-.44.04a3.315 3.315 0 01-1.182-.21 2.825 2.825 0 01-.961-.597 2.816 2.816 0 01-.644-.929 2.987 2.987 0 01-.238-1.21c0-.444.08-.847.238-1.21.15-.35.368-.666.643-.929.278-.261.605-.464.962-.596a3.315 3.315 0 011.182-.21c.355 0 .712.068 1.072.204.361.138.685.36.944.649l-.962.97z"></path></g>`,
32739
+ openrouter: `<path d="M18.654 3.87a5.087 5.087 0 110 10.174L23.7 19.09c.64.641.187 1.737-.72 1.737H8.48a8.479 8.479 0 010-16.958h10.175zM8.479 7.26a5.087 5.087 0 100 10.176 5.087 5.087 0 000-10.175z" fill="#C8FF00"></path>`,
32740
+ siliconflow: `<path clip-rule="evenodd" d="M22.956 6.521H12.522c-.577 0-1.044.468-1.044 1.044v3.13c0 .577-.466 1.044-1.043 1.044H1.044c-.577 0-1.044.467-1.044 1.044v4.174C0 17.533.467 18 1.044 18h10.434c.577 0 1.044-.467 1.044-1.043v-3.13c0-.578.466-1.044 1.043-1.044h9.391c.577 0 1.044-.467 1.044-1.044V7.565c0-.576-.467-1.044-1.044-1.044z" fill="#6E29F6" fill-rule="evenodd"></path>`,
32741
+ ollama: `<g fill="#0F0F0F" fill-rule="evenodd"><path d="M7.905 1.09c.216.085.411.225.588.41.295.306.544.744.734 1.263.191.522.315 1.1.362 1.68a5.054 5.054 0 012.049-.636l.051-.004c.87-.07 1.73.087 2.48.474.101.053.2.11.297.17.05-.569.172-1.134.36-1.644.19-.52.439-.957.733-1.264a1.67 1.67 0 01.589-.41c.257-.1.53-.118.796-.042.401.114.745.368 1.016.737.248.337.434.769.561 1.287.23.934.27 2.163.115 3.645l.053.04.026.019c.757.576 1.284 1.397 1.563 2.35.435 1.487.216 3.155-.534 4.088l-.018.021.002.003c.417.762.67 1.567.724 2.4l.002.03c.064 1.065-.2 2.137-.814 3.19l-.007.01.01.024c.472 1.157.62 2.322.438 3.486l-.006.039a.651.651 0 01-.747.536.648.648 0 01-.54-.742c.167-1.033.01-2.069-.48-3.123a.643.643 0 01.04-.617l.004-.006c.604-.924.854-1.83.8-2.72-.046-.779-.325-1.544-.8-2.273a.644.644 0 01.18-.886l.009-.006c.243-.159.467-.565.58-1.12a4.229 4.229 0 00-.095-1.974c-.205-.7-.58-1.284-1.105-1.683-.595-.454-1.383-.673-2.38-.61a.653.653 0 01-.632-.371c-.314-.665-.772-1.141-1.343-1.436a3.288 3.288 0 00-1.772-.332c-1.245.099-2.343.801-2.67 1.686a.652.652 0 01-.61.425c-1.067.002-1.893.252-2.497.703-.522.39-.878.935-1.066 1.588a4.07 4.07 0 00-.068 1.886c.112.558.331 1.02.582 1.269l.008.007c.212.207.257.53.109.785-.36.622-.629 1.549-.673 2.44-.05 1.018.186 1.902.719 2.536l.016.019a.643.643 0 01.095.69c-.576 1.236-.753 2.252-.562 3.052a.652.652 0 01-1.269.298c-.243-1.018-.078-2.184.473-3.498l.014-.035-.008-.012a4.339 4.339 0 01-.598-1.309l-.005-.019a5.764 5.764 0 01-.177-1.785c.044-.91.278-1.842.622-2.59l.012-.026-.002-.002c-.293-.418-.51-.953-.63-1.545l-.005-.024a5.352 5.352 0 01.093-2.49c.262-.915.777-1.701 1.536-2.269.06-.045.123-.09.186-.132-.159-1.493-.119-2.73.112-3.67.127-.518.314-.95.562-1.287.27-.368.614-.622 1.015-.737.266-.076.54-.059.797.042zm4.116 9.09c.936 0 1.8.313 2.446.855.63.527 1.005 1.235 1.005 1.94 0 .888-.406 1.58-1.133 2.022-.62.375-1.451.557-2.403.557-1.009 0-1.871-.259-2.493-.734-.617-.47-.963-1.13-.963-1.845 0-.707.398-1.417 1.056-1.946.668-.537 1.55-.849 2.485-.849zm0 .896a3.07 3.07 0 00-1.916.65c-.461.37-.722.835-.722 1.25 0 .428.21.829.61 1.134.455.347 1.124.548 1.943.548.799 0 1.473-.147 1.932-.426.463-.28.7-.686.7-1.257 0-.423-.246-.89-.683-1.256-.484-.405-1.14-.643-1.864-.643zm.662 1.21l.004.004c.12.151.095.37-.056.49l-.292.23v.446a.375.375 0 01-.376.373.375.375 0 01-.376-.373v-.46l-.271-.218a.347.347 0 01-.052-.49.353.353 0 01.494-.051l.215.172.22-.174a.353.353 0 01.49.051zm-5.04-1.919c.478 0 .867.39.867.871a.87.87 0 01-.868.871.87.87 0 01-.867-.87.87.87 0 01.867-.872zm8.706 0c.48 0 .868.39.868.871a.87.87 0 01-.868.871.87.87 0 01-.867-.87.87.87 0 01.867-.872zM7.44 2.3l-.003.002a.659.659 0 00-.285.238l-.005.006c-.138.189-.258.467-.348.832-.17.692-.216 1.631-.124 2.782.43-.128.899-.208 1.404-.237l.01-.001.019-.034c.046-.082.095-.161.148-.239.123-.771.022-1.692-.253-2.444-.134-.364-.297-.65-.453-.813a.628.628 0 00-.107-.09L7.44 2.3zm9.174.04l-.002.001a.628.628 0 00-.107.09c-.156.163-.32.45-.453.814-.29.794-.387 1.776-.23 2.572l.058.097.008.014h.03a5.184 5.184 0 011.466.212c.086-1.124.038-2.043-.128-2.722-.09-.365-.21-.643-.349-.832l-.004-.006a.659.659 0 00-.285-.239h-.004z"></path></g>`,
32742
+ huggingface: `<path d="M2.25 11.535c0-3.407 1.847-6.554 4.844-8.258a9.822 9.822 0 019.687 0c2.997 1.704 4.844 4.851 4.844 8.258 0 5.266-4.337 9.535-9.687 9.535S2.25 16.8 2.25 11.535z" fill="#FF9D0B"></path><path d="M11.938 20.086c4.797 0 8.687-3.829 8.687-8.551 0-4.722-3.89-8.55-8.687-8.55-4.798 0-8.688 3.828-8.688 8.55 0 4.722 3.89 8.55 8.688 8.55z" fill="#FFD21E"></path><path d="M11.875 15.113c2.457 0 3.25-2.156 3.25-3.263 0-.576-.393-.394-1.023-.089-.582.283-1.365.675-2.224.675-1.798 0-3.25-1.693-3.25-.586 0 1.107.79 3.263 3.25 3.263h-.003z" fill="#FF323D"></path><path d="M14.76 9.21c.32.108.445.753.767.585.447-.233.707-.708.659-1.204a1.235 1.235 0 00-.879-1.059 1.262 1.262 0 00-1.33.394c-.322.384-.377.92-.14 1.36.153.283.638-.177.925-.079l-.002.003zm-5.887 0c-.32.108-.448.753-.768.585a1.226 1.226 0 01-.658-1.204c.048-.495.395-.913.878-1.059a1.262 1.262 0 011.33.394c.322.384.377.92.14 1.36-.152.283-.64-.177-.925-.079l.003.003zm1.12 5.34a2.166 2.166 0 011.325-1.106c.07-.02.144.06.219.171l.192.306c.069.1.139.175.209.175.074 0 .15-.074.223-.172l.205-.302c.08-.11.157-.188.234-.165.537.168.986.536 1.25 1.026.932-.724 1.275-1.905 1.275-2.633 0-.508-.306-.426-.81-.19l-.616.296c-.52.24-1.148.48-1.824.48-.676 0-1.302-.24-1.823-.48l-.589-.283c-.52-.248-.838-.342-.838.177 0 .703.32 1.831 1.187 2.56l.18.14z" fill="#3A3B45"></path><path d="M17.812 10.366a.806.806 0 00.813-.8c0-.441-.364-.8-.813-.8a.806.806 0 00-.812.8c0 .442.364.8.812.8zm-11.624 0a.806.806 0 00.812-.8c0-.441-.364-.8-.812-.8a.806.806 0 00-.813.8c0 .442.364.8.813.8zM4.515 13.073c-.405 0-.765.162-1.017.46a1.455 1.455 0 00-.333.925 1.801 1.801 0 00-.485-.074c-.387 0-.737.146-.985.409a1.41 1.41 0 00-.2 1.722 1.302 1.302 0 00-.447.694c-.06.222-.12.69.2 1.166a1.267 1.267 0 00-.093 1.236c.238.533.81.958 1.89 1.405l.24.096c.768.3 1.473.492 1.478.494.89.243 1.808.375 2.732.394 1.465 0 2.513-.443 3.115-1.314.93-1.342.842-2.575-.274-3.763l-.151-.154c-.692-.684-1.155-1.69-1.25-1.912-.195-.655-.71-1.383-1.562-1.383-.46.007-.889.233-1.15.605-.25-.31-.495-.553-.715-.694a1.87 1.87 0 00-.993-.312zm14.97 0c.405 0 .767.162 1.017.46.216.262.333.588.333.925.158-.047.322-.071.487-.074.388 0 .738.146.985.409a1.41 1.41 0 01.2 1.722c.22.178.377.422.445.694.06.222.12.69-.2 1.166.244.37.279.836.093 1.236-.238.533-.81.958-1.889 1.405l-.239.096c-.77.3-1.475.492-1.48.494-.89.243-1.808.375-2.732.394-1.465 0-2.513-.443-3.115-1.314-.93-1.342-.842-2.575.274-3.763l.151-.154c.695-.684 1.157-1.69 1.252-1.912.195-.655.708-1.383 1.56-1.383.46.007.889.233 1.15.605.25-.31.495-.553.718-.694.244-.162.523-.265.814-.3l.176-.012z" fill="#FF9D0B"></path><path d="M9.785 20.132c.688-.994.638-1.74-.305-2.667-.945-.928-1.495-2.288-1.495-2.288s-.205-.788-.672-.714c-.468.074-.81 1.25.17 1.971.977.721-.195 1.21-.573.534-.375-.677-1.405-2.416-1.94-2.751-.532-.332-.907-.148-.782.541.125.687 2.357 2.35 2.14 2.707-.218.362-.983-.42-.983-.42S2.953 14.9 2.43 15.46c-.52.558.398 1.026 1.7 1.803 1.308.778 1.41.985 1.225 1.28-.187.295-3.07-2.1-3.34-1.083-.27 1.011 2.943 1.304 2.745 2.006-.2.7-2.265-1.324-2.685-.537-.425.79 2.913 1.718 2.94 1.725 1.075.276 3.813.859 4.77-.522zm4.432 0c-.687-.994-.64-1.74.305-2.667.943-.928 1.493-2.288 1.493-2.288s.205-.788.675-.714c.465.074.807 1.25-.17 1.971-.98.721.195 1.21.57.534.377-.677 1.407-2.416 1.94-2.751.532-.332.91-.148.782.541-.125.687-2.355 2.35-2.137 2.707.215.362.98-.42.98-.42S21.05 14.9 21.57 15.46c.52.558-.395 1.026-1.7 1.803-1.308.778-1.408.985-1.225 1.28.187.295 3.07-2.1 3.34-1.083.27 1.011-2.94 1.304-2.743 2.006.2.7 2.263-1.324 2.685-.537.423.79-2.912 1.718-2.94 1.725-1.077.276-3.815.859-4.77-.522z" fill="#FFD21E"></path>`,
32743
+ novita: `<path clip-rule="evenodd" d="M9.167 4.17v5.665L0 19.003h9.167v-5.666l5.666 5.666H24L9.167 4.17z" fill="#23D57C" fill-rule="evenodd"></path>`,
32744
+ deepinfra: `<path d="M3.294 7.821A2.297 2.297 0 011 5.527a2.297 2.297 0 012.294-2.295A2.297 2.297 0 015.59 5.527 2.297 2.297 0 013.294 7.82zm0-3.688a1.396 1.396 0 000 2.79 1.396 1.396 0 000-2.79zM3.294 14.293A2.297 2.297 0 011 11.998a2.297 2.297 0 012.294-2.294 2.297 2.297 0 012.295 2.294 2.297 2.297 0 01-2.295 2.295zm0-3.688a1.395 1.395 0 000 2.788 1.395 1.395 0 100-2.788zM3.294 20.761A2.297 2.297 0 011 18.467a2.297 2.297 0 012.294-2.295 2.297 2.297 0 012.295 2.295 2.297 2.297 0 01-2.295 2.294zm0-3.688a1.396 1.396 0 000 2.79 1.396 1.396 0 000-2.79zM20.738 7.821a2.297 2.297 0 01-2.295-2.294 2.297 2.297 0 012.294-2.295 2.297 2.297 0 012.295 2.295 2.297 2.297 0 01-2.294 2.294zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.626-1.395-1.395-1.395zM20.738 14.293a2.297 2.297 0 01-2.295-2.295 2.297 2.297 0 012.294-2.294 2.297 2.297 0 012.295 2.294 2.297 2.297 0 01-2.294 2.295zm0-3.688c-.769 0-1.395.625-1.395 1.393a1.396 1.396 0 002.79 0c0-.77-.626-1.393-1.395-1.393zM20.738 20.761a2.297 2.297 0 01-2.295-2.294 2.297 2.297 0 012.294-2.295 2.297 2.297 0 012.295 2.295 2.297 2.297 0 01-2.294 2.294zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.626-1.395-1.395-1.395zM12.016 11.057a2.297 2.297 0 01-2.294-2.294 2.297 2.297 0 012.294-2.295 2.297 2.297 0 012.295 2.295 2.297 2.297 0 01-2.295 2.294zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.625-1.395-1.395-1.395zM12.017 4.589a2.297 2.297 0 01-2.295-2.295A2.297 2.297 0 0112.017 0a2.297 2.297 0 012.294 2.294 2.297 2.297 0 01-2.294 2.295zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.626-1.395-1.395-1.395zM12.017 17.529a2.297 2.297 0 01-2.295-2.295 2.297 2.297 0 012.295-2.294 2.297 2.297 0 012.294 2.294 2.297 2.297 0 01-2.294 2.295zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.626-1.395-1.395-1.395zM12.016 24a2.297 2.297 0 01-2.294-2.295 2.297 2.297 0 012.294-2.294 2.297 2.297 0 012.295 2.294A2.297 2.297 0 0112.016 24zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.625-1.395-1.395-1.395z" fill="#2A3275"></path><path d="M8.363 8.222a.742.742 0 01-.277-.053l-1.494-.596a.75.75 0 11.557-1.392l1.493.595a.75.75 0 01-.278 1.446h-.001zM8.363 14.566a.743.743 0 01-.277-.053l-1.494-.595a.75.75 0 11.557-1.393l1.493.596a.75.75 0 01-.278 1.445h-.001zM17.124 11.397a.741.741 0 01-.277-.054l-1.493-.595a.75.75 0 11.555-1.392l1.493.595a.75.75 0 01-.278 1.446zM17.124 5.05a.744.744 0 01-.277-.054L15.354 4.4a.75.75 0 01.555-1.392l1.493.596a.75.75 0 01-.278 1.445zM17.124 17.739a.743.743 0 01-.277-.053l-1.494-.596a.75.75 0 11.556-1.392l1.493.596a.75.75 0 01-.278 1.445zM6.91 17.966a.75.75 0 01-.279-1.445l1.494-.595a.749.749 0 11.556 1.392l-1.493.595a.743.743 0 01-.277.053H6.91zM6.91 11.66a.75.75 0 01-.279-1.446l1.494-.595a.75.75 0 01.556 1.392l-1.493.595a.743.743 0 01-.277.053H6.91zM6.91 5.033a.75.75 0 01-.279-1.446l1.494-.595a.75.75 0 01.556 1.392l-1.493.596a.744.744 0 01-.277.053H6.91zM8.363 21.364a.743.743 0 01-.277-.053l-1.494-.596a.75.75 0 01.555-1.392l1.494.595a.75.75 0 01-.278 1.446zM15.63 8.223a.75.75 0 01-.278-1.447l1.494-.595a.75.75 0 01.556 1.393l-1.494.595a.744.744 0 01-.276.054h-.002zM15.63 14.567a.75.75 0 01-.278-1.446l1.494-.596a.75.75 0 01.556 1.394l-1.494.595a.743.743 0 01-.276.053h-.002zM15.63 21.363a.749.749 0 01-.278-1.445l1.494-.595a.75.75 0 11.555 1.392l-1.494.595a.741.741 0 01-.277.053z" fill="#5699DB"></path>`,
32745
+ modelscope: `<path d="M0 7.967h2.667v2.667H0zM8 10.633h2.667V13.3H8z" fill="#36CED0"></path><path d="M0 10.633h2.667V13.3H0zM2.667 13.3h2.666v2.667H8v2.666H2.667V13.3zM2.667 5.3H8v2.667H5.333v2.666H2.667V5.3zM10.667 13.3h2.667v2.667h-2.667z" fill="#624AFF"></path><path d="M24 7.967h-2.667v2.667H24zM16 10.633h-2.667V13.3H16z" fill="#36CED0"></path><path d="M24 10.633h-2.667V13.3H24zM21.333 13.3h-2.666v2.667H16v2.666h5.333V13.3zM21.333 5.3H16v2.667h2.667v2.666h2.666V5.3z" fill="#624AFF"></path>`
32746
+ };
32747
+ //#endregion
32748
+ //#region src/client/model-logos-core.ts
32749
+ /**
32750
+ * Brand matching for the usage panel's per-model logos: maps whatever naming
32751
+ * fields a usage record carries (provider id, raw model id, resolved display
32752
+ * names) onto one of the bundled brand logos in model-logos-data.ts. This is
32753
+ * presentation-only metadata — a miss just means the neutral glyph, never a
32754
+ * lost record.
32755
+ */
32756
+ /** Brand id -> first-matching pattern over one stage's lowercased joined
32757
+ * haystack, most distinctive brands first.
32758
+ * Long unique names match as plain substrings; short or collision-prone
32759
+ * ones (the OpenAI "o3" series, StepFun "step", Cohere "command", Yi,
32760
+ * Amazon "nova", Microsoft "phi") require word/dash boundaries so
32761
+ * "gpt-4o" stays OpenAI, "multistep-2" stays unknown and "commander" is
32762
+ * not Cohere. Serving platforms (groq, openrouter, ollama, …) sit last:
32763
+ * an identifiable model id always beats the platform that served it. */
32764
+ const MATCHERS = [
32765
+ ["ai360", /ai360|360gpt|智脑/],
32766
+ ["deepseek", /deepseek/],
32767
+ ["openai", /openai|chatgpt|gpt|davinci|\bo[134](?:-|$)/],
32768
+ ["claude", /claude|anthropic/],
32769
+ ["gemini", /gemini|gemma|google|vertex/],
32770
+ ["qwen", /qwen|qwq|qvq|tongyi|通义|百炼/],
32771
+ ["zhipu", /zhipu|chatglm|glm|智谱|(?:^|[^a-z0-9])zai(?:-|$)/],
32772
+ ["kimi", /kimi|moonshot|月之暗面/],
32773
+ ["grok", /grok|\bxai\b/],
32774
+ ["llama", /(?:^|[^a-z0-9])llama|codellama|\bmeta\b/],
32775
+ ["mistral", /mistral|mixtral|codestral|ministral|magistral|pixtral|voxtral|devstral/],
32776
+ ["doubao", /doubao|bytedance|volcengine|豆包|火山|(?:^|[^a-z0-9])seed(?:-|$)/],
32777
+ ["minimax", /minimax|abab/],
32778
+ ["hunyuan", /hunyuan|tencent|混元|腾讯/],
32779
+ ["ernie", /ernie|wenxin|baidu|qianfan|文心|百度/],
32780
+ ["stepfun", /stepfun|阶跃|(?:^|[^a-z0-9])step(?:-|$)/],
32781
+ ["cohere", /cohere|(?:^|[^a-z0-9])command(?:-|$)|c4ai/],
32782
+ ["xiaomi", /xiaomi|mimo|小米/],
32783
+ ["baichuan", /baichuan|百川/],
32784
+ ["yi", /01-?ai|lingyi|零一万物|(?:^|[^a-z0-9])yi(?:-|$)/],
32785
+ ["spark", /spark|iflytek|xfyun|讯飞|星火/],
32786
+ ["sensenova", /sensenova|商汤/],
32787
+ ["internlm", /internlm|书生/],
32788
+ ["microsoft", /microsoft|azure|(?:^|[^a-z0-9])phi(?:-\d|$)/],
32789
+ ["nvidia", /nvidia|nemotron|英伟达/],
32790
+ ["amazon", /amazon|bedrock|aws|(?:^|[^a-z0-9])(?:nova|titan)(?:-|$)/],
32791
+ ["ibm", /(?:^|[^a-z0-9])ibm(?:-|$)|granite/],
32792
+ ["databricks", /databricks|dbrx/],
32793
+ ["perplexity", /perplexity|(?:^|[^a-z0-9])sonar(?:-|$)/],
32794
+ ["ai21", /ai21|jamba/],
32795
+ ["upstage", /upstage|(?:^|[^a-z0-9])solar(?:-|$)/],
32796
+ ["jina", /jina/],
32797
+ ["reka", /(?:^|[^a-z0-9])reka(?:-|$)/],
32798
+ ["snowflake", /snowflake|arctic/],
32799
+ ["sambanova", /sambanova/],
32800
+ ["infinigence", /infinigence|无问芯穹/],
32801
+ ["rwkv", /(?:^|[^a-z0-9])rwkv(?:-|$)/],
32802
+ ["falcon", /(?:^|[^a-z0-9])(?:falcon|tii)(?:-|$)/],
32803
+ ["groq", /groq/],
32804
+ ["together", /together/],
32805
+ ["fireworks", /fireworks/],
32806
+ ["cerebras", /cerebras/],
32807
+ ["openrouter", /openrouter/],
32808
+ ["siliconflow", /siliconflow|siliconcloud|硅基流动/],
32809
+ ["ollama", /ollama/],
32810
+ ["huggingface", /huggingface|hugging/],
32811
+ ["novita", /novita/],
32812
+ ["deepinfra", /deepinfra/],
32813
+ ["modelscope", /modelscope|魔搭/]
32814
+ ];
32815
+ MATCHERS.map(([id]) => id);
32816
+ /** Resolve the brand id for one usage record. The model's own naming (raw
32817
+ * model id plus its resolved display name) decides the brand when it can;
32818
+ * the provider fields (route id and provider display names) are the fallback
32819
+ * for opaque model ids, so a Llama served through a vertex/google route keeps
32820
+ * the Llama mark. Empty/undefined parts are ignored; null when no bundled
32821
+ * brand matches. */
32822
+ function resolveModelLogo(provider, model, name, providers) {
32823
+ return matchBrand(model, name) ?? matchBrand(provider, ...providers ?? []);
32824
+ }
32825
+ function matchBrand(...parts) {
32826
+ const haystack = parts.filter((part) => typeof part === "string" && part !== "").join("/").toLowerCase();
32827
+ if (haystack === "") return null;
32828
+ for (const [id, pattern] of MATCHERS) if (pattern.test(haystack)) return id;
32829
+ return null;
32830
+ }
32831
+ /** Inner SVG markup of a brand's logo, or undefined for an unknown id. */
32832
+ function modelLogoMarkup(id) {
32833
+ return id === null ? void 0 : MODEL_LOGOS[id];
32834
+ }
32835
+ //#endregion
32836
+ //#region src/client/ModelLogo.tsx
32837
+ /** Neutral glyph for models no bundled brand matches: a soft four-point AI
32838
+ * spark in the panel's muted gray, so an unknown model reads as "unbranded"
32839
+ * rather than as some other vendor. */
32840
+ const FALLBACK = "<path d=\"M12 1.6l2.14 5.96a2 2 0 0 0 1.22 1.22l5.96 2.14-5.96 2.14a2 2 0 0 0-1.22 1.22L12 20.24l-2.14-5.96a2 2 0 0 0-1.22-1.22L2.68 10.92l5.96-2.14a2 2 0 0 0 1.22-1.22L12 1.6z\" fill=\"#9aa3b3\"/>";
32841
+ /** One model's brand logo inline. The markup is a bundled constant (never
32842
+ * request data) rendered as-is so each brand keeps its own gradients,
32843
+ * circles and multi-path fills; ids inside stay unique across brands. */
32844
+ function ModelLogo({ model, name, provider, providers, size = 13, className }) {
32845
+ const markup = modelLogoMarkup(resolveModelLogo(provider, model, name, providers)) ?? FALLBACK;
32846
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
32847
+ width: size,
32848
+ height: size,
32849
+ viewBox: "0 0 24 24",
32850
+ "aria-hidden": "true",
32851
+ className,
32852
+ dangerouslySetInnerHTML: { __html: markup }
32853
+ });
32854
+ }
32855
+ //#endregion
32856
+ //#region \0token-total-css:/home/runner/work/dsh-token-total/dsh-token-total/src/client/SessionUsageView.module.css?inline
32857
+ const css = "/* A light, self-contained Usage surface. Tables fit the available width:\n * no horizontal scroll containers, fixed column contracts, titles for names.\n * Stat cards follow the reference dashboard: tinted left edge + icon chip,\n * label, big value, small subtitle. Request log folds by conversation turn. */\n.scroll_900471699 { height:100%; min-height:0; overflow-y:auto; background:#ffffff; color:#252936; color-scheme:light; container-type:inline-size; }\n.page_900471699 { box-sizing:border-box; width:100%; max-width:1160px; margin:0 auto; padding:24px 26px 32px; font-family:system-ui,-apple-system,\"Segoe UI\",sans-serif; font-size:13px; }\n.page_900471699 * { box-sizing:border-box; }\n.scope_900471699 { color:#8790a3; font-size:11px; margin:0 0 14px; }\n.stats_900471699 { display:grid; gap:12px; margin-bottom:18px; }\n.statRow_900471699 { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:12px; }\n.stat_900471699 { min-width:0; position:relative; overflow:hidden; background:#fff; border:1px solid #e4e7ee; border-left:4px solid var(--tone); border-radius:12px; padding:12px 16px 11px; }\n.statHead_900471699 { display:flex; align-items:center; gap:8px; margin-bottom:8px; }\n.statIcon_900471699 { display:flex; align-items:center; justify-content:center; width:32px; height:32px; border-radius:10px; color:#fff; background:linear-gradient(135deg, var(--tone), var(--tone-soft)); flex-shrink:0; box-shadow:0 3px 8px var(--tone-soft); }\n.statMark_900471699 { position:absolute; right:-14px; bottom:-18px; width:92px; height:92px; color:var(--tone); pointer-events:none; }\n.statLabel_900471699 { font-size:12px; color:#7d8495; }\n.statValue_900471699 { display:block; font-size:25px; font-weight:650; letter-spacing:-0.5px; white-space:nowrap; font-variant-numeric:tabular-nums; }\n.statSub_900471699 { display:block; margin-top:5px; font-size:11px; color:#939aac; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n.toneBlue_900471699 { --tone:#4f79f6; --tone-soft:#eaf0fe; }\n.tonePurple_900471699 { --tone:#8b5cf6; --tone-soft:#f1ebfe; }\n.toneGreen_900471699 { --tone:#18a97b; --tone-soft:#e5f6f0; }\n.toneOrange_900471699 { --tone:#e8892c; --tone-soft:#fcf1e4; }\n.toneTeal_900471699 { --tone:#16a4b8; --tone-soft:#e4f5f8; }\n.tonePink_900471699 { --tone:#d9538c; --tone-soft:#fbeaf1; }\n.card_900471699 { min-width:0; background:#fff; border:1px solid #e4e7ee; border-radius:12px; margin-bottom:18px; overflow:hidden; }\n.cardHead_900471699 { display:flex; align-items:center; justify-content:space-between; gap:10px; min-height:54px; padding:15px 18px; border-bottom:1px solid #eef0f4; }\n.cardHead_900471699 h2 { font-size:14px; font-weight:600; margin:0; }\n.cardHead_900471699 > span { display:flex; gap:7px; align-items:center; font-size:11px; }\n.count_900471699 { display:inline-flex; align-items:center; justify-content:center; min-width:21px; padding:2px 6px; font-size:10px; color:#8b93a3; background:#f3f5f8; border-radius:5px; margin-left:5px; font-weight:500; }\n.mid_900471699 { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:18px; align-items:stretch; }\n.mid_900471699 .card_900471699 { height:100%; margin-bottom:0; }\n.mid_900471699 { margin-bottom:18px; }\n.table_900471699 { border-collapse:collapse; width:100%; table-layout:fixed; font-size:11px; }\n.table_900471699 th { color:#929aaa; font-weight:500; padding:12px 5px; text-align:right; vertical-align:middle; line-height:1.3; overflow-wrap:anywhere; }\n.table_900471699 td { padding:13px 5px; text-align:right; border-top:1px solid #eef0f4; color:#626c80; font-variant-numeric:tabular-nums; white-space:nowrap; }\n.table_900471699 th:first-child,.table_900471699 td:first-child { text-align:left; padding-left:16px; }\n.table_900471699 th:last-child,.table_900471699 td:last-child { padding-right:16px; }\n.childName_900471699 { width:28%; }\n.childRequests_900471699 { width:11%; }\n.modelName_900471699 { width:30%; }\n.modelRequests_900471699 { width:11%; }\n.modelHit_900471699 { width:16%; }\n.ellipsis_900471699 { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:#394354; }\n/* By-model rows lead with the model's brand logo; the name keeps truncating\n * inside the flexible remainder of the cell. */\n.modelNameCell_900471699 { display:flex; align-items:center; gap:6px; min-width:0; }\n.modelNameCell_900471699 .ellipsis_900471699 { flex:1; min-width:0; }\n/* Gray provider label under a model name shown by several rows (同名模型). */\n.modelProvider_900471699 { display:block; margin-top:2px; font-size:10px; color:#939aaa; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n.number_900471699 { font-variant-numeric:tabular-nums; }\n.speedCell_900471699 { display:inline-flex; align-items:baseline; gap:3px; white-space:nowrap; }\n.speedCell_900471699 small { font-size:9px; color:#929aaa; }\n.good_900471699 { color:#21a17b; }\n.warn_900471699 { color:#d69a21; }\n.bad_900471699 { color:#e06571; }\n.live_900471699 { color:#169bb3; }\n.muted_900471699 { color:#939aaa; }\n.empty_900471699 { margin:0; padding:28px 18px; color:#9aa2b1; font-size:12px; text-align:center; }\n.action_900471699 { color:#818b9e; background:none; border:0; padding:3px 0; font:inherit; font-size:11px; cursor:pointer; }\n.action_900471699:hover { color:#279cb6; }\n.action_900471699:focus-visible,.turnHead_900471699:focus-visible { outline:2px solid #2ab1c6; outline-offset:-2px; }\n.turnList_900471699 { padding:0 14px 14px; }\n.turn_900471699 { margin-top:10px; border:1px solid #e7eaf0; border-radius:9px; background:#fff; overflow:hidden; }\n.turnHead_900471699 { display:grid; grid-template-columns:12px minmax(0,1fr) auto; align-items:center; gap:12px; padding:13px 14px; width:100%; text-align:left; background:#f8f9fc; border:0; cursor:pointer; color:#616c7f; font:inherit; font-size:11px; }\n.chevron_900471699 { color:#99a1af; transition:transform 0.2s; }\n.rotated_900471699 { transform:rotate(90deg); }\n.turnTitle_900471699 { display:flex; align-items:center; gap:6px; min-width:0; font-size:12px; font-weight:600; color:#394354; }\n/* Turn topic is the group title now (the page header owns the session name),\n * so it carries the primary text color and truncates before the metrics. */\n.turnTopic_900471699 { min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }\n/* A subagent's turns look like this session's turns apart from the agent tag;\n * the tag keeps the full session name in its tooltip. */\n.turnAgent_900471699 { flex:none; padding:1px 6px; border-radius:5px; background:#e9edf4; color:#6f7889; font-size:10px; font-weight:500; }\n.turnSummary_900471699 { display:flex; gap:5px; align-items:center; white-space:nowrap; }\n.turnSummary_900471699 > span:last-child { margin-left:8px; }\n.turnBody_900471699 { border-top:1px solid #eef0f4; }\n.turnBody_900471699[hidden] { display:none; }\n/* A request row is one line: time, what answered, and its metrics pinned to the\n * row end. The metrics never wrap; they truncate with a tooltip before the head\n * gives up its model name. */\n.turnRequest_900471699 { display:grid; grid-template-columns:64px minmax(0,1fr) auto; align-items:center; gap:12px; padding:10px 16px; border-top:1px solid #f3f5f9; }\n.turnRequest_900471699:first-child { border-top:0; }\n.turnRequestHead_900471699 { display:flex; align-items:center; gap:8px; font-size:11px; color:#616c7f; min-width:0; }\n.requestTime_900471699 { color:#9aa3b3; font-variant-numeric:tabular-nums; flex-shrink:0; }\n.statusDot_900471699 { width:5px; height:5px; border-radius:50%; background:currentColor; flex-shrink:0; }\n/* Per-model brand logo: colors are baked into each logo's markup, only the\n * layout contract lives here. Unknown models get the neutral gray fallback. */\n.modelLogo_900471699 { flex-shrink:0; }\n.recordModel_900471699 { min-width:0; display:flex; align-items:center; gap:6px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; color:#394354; font-weight:500; }\n.routeText_900471699 { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; color:#8b93a4; flex-shrink:1; }\n.effort_900471699 { white-space:nowrap; color:#9aa3b3; background:#f1f3f7; border-radius:5px; padding:1px 6px; }\n.recordMeta_900471699 { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; text-align:right; font-size:10px; color:#949cab; font-variant-numeric:tabular-nums; }\n.note_900471699 { font-size:10px; line-height:1.7; color:#9aa3b3; margin:0; }\n.error_900471699 { background:#fff4f1; color:#b86751; border:1px solid #f4d8ce; border-radius:9px; padding:12px 16px; margin-bottom:16px; font-size:12px; display:flex; gap:16px; justify-content:space-between; }\n@container (max-width:1050px) {\n .mid_900471699 { grid-template-columns:minmax(0,1fr); }\n .statRow_900471699 { grid-template-columns:repeat(2,minmax(0,1fr)); }\n .statValue_900471699 { font-size:23px; }\n .table_900471699 { font-size:12px; }\n .childName_900471699 { width:34%; }\n}\n@container (max-width:700px) {\n .page_900471699 { padding:18px 14px 24px; }\n .stat_900471699 { padding:12px 12px 11px; }\n .statValue_900471699 { font-size:20px; }\n .table_900471699 { font-size:10px; }\n .table_900471699 th,.table_900471699 td { padding:10px 3px; }\n .table_900471699 th:first-child,.table_900471699 td:first-child { padding-left:10px; }\n .table_900471699 th:last-child,.table_900471699 td:last-child { padding-right:10px; }\n .childName_900471699 { width:25%; }\n .childRequests_900471699 { width:11%; }\n .modelName_900471699 { width:25%; }\n .modelRequests_900471699 { width:11%; }\n .modelHit_900471699 { width:17%; }\n .turnHead_900471699 { gap:8px; padding:11px 10px; }\n .turnSummary_900471699 { grid-column:2; font-size:10px; }\n .turnRequest_900471699 { grid-template-columns:56px minmax(120px,1fr) auto; gap:8px; padding:10px; }\n .turnRequestHead_900471699 { gap:6px; }\n .routeText_900471699 { display:none; }\n}\n@media (prefers-reduced-motion:reduce) {\n .chevron_900471699 { transition:none; }\n}\n";
32858
+ const tagId = "dsh-token-total/SessionUsageView.module.css";
32859
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"" + tagId + "\"]") === null) {
32860
+ const tag = document.createElement("style");
32861
+ tag.dataset.plugin = "dsh-token-total";
32862
+ tag.dataset.pluginCss = tagId;
32863
+ tag.textContent = css;
32864
+ document.head.appendChild(tag);
32865
+ }
32866
+ var SessionUsageView_module_default = {
32867
+ "scroll": "scroll_900471699",
32868
+ "page": "page_900471699",
32869
+ "scope": "scope_900471699",
32870
+ "stats": "stats_900471699",
32871
+ "statRow": "statRow_900471699",
32872
+ "stat": "stat_900471699",
32873
+ "statHead": "statHead_900471699",
32874
+ "statIcon": "statIcon_900471699",
32875
+ "statMark": "statMark_900471699",
32876
+ "statLabel": "statLabel_900471699",
32877
+ "statValue": "statValue_900471699",
32878
+ "statSub": "statSub_900471699",
32879
+ "toneBlue": "toneBlue_900471699",
32880
+ "tonePurple": "tonePurple_900471699",
32881
+ "toneGreen": "toneGreen_900471699",
32882
+ "toneOrange": "toneOrange_900471699",
32883
+ "toneTeal": "toneTeal_900471699",
32884
+ "tonePink": "tonePink_900471699",
32885
+ "card": "card_900471699",
32886
+ "cardHead": "cardHead_900471699",
32887
+ "count": "count_900471699",
32888
+ "mid": "mid_900471699",
32889
+ "table": "table_900471699",
32890
+ "childName": "childName_900471699",
32891
+ "childRequests": "childRequests_900471699",
32892
+ "modelName": "modelName_900471699",
32893
+ "modelRequests": "modelRequests_900471699",
32894
+ "modelHit": "modelHit_900471699",
32895
+ "ellipsis": "ellipsis_900471699",
32896
+ "modelNameCell": "modelNameCell_900471699",
32897
+ "modelProvider": "modelProvider_900471699",
32898
+ "number": "number_900471699",
32899
+ "speedCell": "speedCell_900471699",
32900
+ "good": "good_900471699",
32901
+ "warn": "warn_900471699",
32902
+ "bad": "bad_900471699",
32903
+ "live": "live_900471699",
32904
+ "muted": "muted_900471699",
32905
+ "empty": "empty_900471699",
32906
+ "action": "action_900471699",
32907
+ "turnHead": "turnHead_900471699",
32908
+ "turnList": "turnList_900471699",
32909
+ "turn": "turn_900471699",
32910
+ "chevron": "chevron_900471699",
32911
+ "rotated": "rotated_900471699",
32912
+ "turnTitle": "turnTitle_900471699",
32913
+ "turnTopic": "turnTopic_900471699",
32914
+ "turnAgent": "turnAgent_900471699",
32915
+ "turnSummary": "turnSummary_900471699",
32916
+ "turnBody": "turnBody_900471699",
32917
+ "turnRequest": "turnRequest_900471699",
32918
+ "turnRequestHead": "turnRequestHead_900471699",
32919
+ "requestTime": "requestTime_900471699",
32920
+ "statusDot": "statusDot_900471699",
32921
+ "modelLogo": "modelLogo_900471699",
32922
+ "recordModel": "recordModel_900471699",
32923
+ "routeText": "routeText_900471699",
32924
+ "effort": "effort_900471699",
32925
+ "recordMeta": "recordMeta_900471699",
32926
+ "note": "note_900471699",
32927
+ "error": "error_900471699"
32928
+ };
32929
+ //#endregion
32930
+ //#region src/client/SessionUsageView.tsx
32931
+ const seconds = (ms) => ms !== null && Number.isFinite(ms) ? `${(ms / 1e3).toFixed(1)}s` : "—";
32932
+ const secText = (ms) => ms !== null && Number.isFinite(ms) ? String(Math.round(ms / 100) / 10) : "—";
32933
+ const tokShort = (n) => n >= 1e6 ? `${(n / 1e6).toFixed(1)}M` : n >= 1e3 ? `${(n / 1e3).toFixed(1)}k` : String(n);
32934
+ const pctInt = (rate) => rate === null ? "—" : `${Math.round(rate)}%`;
32935
+ const speed = (n) => n !== null && Number.isFinite(n) ? `${Math.round(n)} tok/s` : "—";
32936
+ const clock = (ms) => new Date(ms).toLocaleTimeString([], {
32937
+ hour: "2-digit",
32938
+ minute: "2-digit",
32939
+ second: "2-digit"
32940
+ });
32941
+ const modelShort = (ref) => ref.includes("/") ? ref.slice(ref.indexOf("/") + 1) : ref;
32942
+ const zero = () => ({
32943
+ uncachedInputTokens: 0,
32944
+ outputTokens: 0,
32945
+ cacheReadTokens: 0,
32946
+ cacheWriteTokens: 0
32947
+ });
32948
+ const sum = (rows) => rows.reduce((acc, r) => ({
32949
+ uncachedInputTokens: acc.uncachedInputTokens + r.totals.uncachedInputTokens,
32950
+ outputTokens: acc.outputTokens + r.totals.outputTokens,
32951
+ cacheReadTokens: acc.cacheReadTokens + r.totals.cacheReadTokens,
32952
+ cacheWriteTokens: acc.cacheWriteTokens + r.totals.cacheWriteTokens
32953
+ }), zero());
32954
+ function Token({ n }) {
32955
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
32956
+ className: SessionUsageView_module_default.number,
32957
+ title: formatTokens(n),
32958
+ children: formatCompact(n)
32959
+ });
32960
+ }
32961
+ function Hit({ totals }) {
32962
+ const rate = cacheHitPercentOf(totals);
32963
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
32964
+ className: rate === null ? SessionUsageView_module_default.muted : rate >= 80 ? SessionUsageView_module_default.good : rate >= 50 ? SessionUsageView_module_default.warn : SessionUsageView_module_default.bad,
32965
+ children: rate === null ? "—" : `${rate.toFixed(1)}%`
32966
+ });
32967
+ }
32968
+ const icons = {
32969
+ requests: "M4 9h16M4 15h16M10 3 8 21M16 3l-2 18",
32970
+ tokens: "M4 8c0-2.2 3.6-4 8-4s8 1.8 8 4-3.6 4-8 4-8-1.8-8-4Zm0 0v8c0 2.2 3.6 4 8 4s8-1.8 8-4V8",
32971
+ hit: "M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0ZM16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z",
32972
+ speed: "M13 2 4 14h7l-1 8 9-12h-7l1-8Z",
32973
+ input: "M12 3v12M7 10l5 5 5-5M4 21h16",
32974
+ output: "M12 21V9M7 14l5-5 5 5M4 3h16",
32975
+ read: "M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7ZM15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z",
32976
+ write: "M12 20h9M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5Z"
32977
+ };
32978
+ function Stat({ tone, name, label, value, sub, title }) {
32979
+ const icon = icons[name];
32980
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
32981
+ className: `${SessionUsageView_module_default.stat} ${tone}`,
32982
+ children: [
32983
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
32984
+ className: SessionUsageView_module_default.statMark,
32985
+ viewBox: "0 0 24 24",
32986
+ "aria-hidden": "true",
32987
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("linearGradient", {
32988
+ id: `usage-mark-${name}`,
32989
+ x1: "0",
32990
+ y1: "0",
32991
+ x2: "1",
32992
+ y2: "1",
32993
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("stop", {
32994
+ offset: "0",
32995
+ stopColor: "currentColor",
32996
+ stopOpacity: "0.3"
32997
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("stop", {
32998
+ offset: "1",
32999
+ stopColor: "currentColor",
33000
+ stopOpacity: "0.03"
33001
+ })]
33002
+ }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
33003
+ d: icon,
33004
+ fill: `url(#usage-mark-${name})`,
33005
+ stroke: `url(#usage-mark-${name})`,
33006
+ strokeWidth: "1.1",
33007
+ strokeLinecap: "round",
33008
+ strokeLinejoin: "round"
33009
+ })]
33010
+ }),
33011
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
33012
+ className: SessionUsageView_module_default.statHead,
33013
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33014
+ className: SessionUsageView_module_default.statIcon,
33015
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
33016
+ width: "18",
33017
+ height: "18",
33018
+ viewBox: "0 0 24 24",
33019
+ fill: "none",
33020
+ stroke: "currentColor",
33021
+ strokeWidth: "1.8",
33022
+ strokeLinecap: "round",
33023
+ strokeLinejoin: "round",
33024
+ "aria-hidden": "true",
33025
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: icon })
33026
+ })
33027
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33028
+ className: SessionUsageView_module_default.statLabel,
33029
+ children: label
33030
+ })]
33031
+ }),
33032
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
33033
+ className: SessionUsageView_module_default.statValue,
33034
+ title,
33035
+ children: value
33036
+ }),
33037
+ sub !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33038
+ className: SessionUsageView_module_default.statSub,
33039
+ children: sub
33040
+ })
33041
+ ]
33042
+ });
33043
+ }
33044
+ function Metrics({ detail, t }) {
33045
+ const billed = billedTotal(detail.totals);
33046
+ const failed = detail.records.filter((row) => row.status === "failed").length;
33047
+ const failRate = detail.requests > 0 ? (failed / detail.requests * 100).toFixed(1) : "0.0";
33048
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
33049
+ className: SessionUsageView_module_default.stats,
33050
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
33051
+ className: SessionUsageView_module_default.statRow,
33052
+ children: [
33053
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Stat, {
33054
+ tone: SessionUsageView_module_default.toneBlue,
33055
+ name: "requests",
33056
+ label: t("requestsCount"),
33057
+ value: formatTokens(detail.requests),
33058
+ sub: `${t("failed")} ${failed} · ${failRate}%`
33059
+ }),
33060
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Stat, {
33061
+ tone: SessionUsageView_module_default.tonePurple,
33062
+ name: "tokens",
33063
+ label: t("tokens"),
33064
+ value: formatCompact(billed),
33065
+ title: formatTokens(billed),
33066
+ sub: `${formatTokens(billed)} tokens`
33067
+ }),
33068
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Stat, {
33069
+ tone: SessionUsageView_module_default.toneGreen,
33070
+ name: "hit",
33071
+ label: t("hit"),
33072
+ value: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Hit, { totals: detail.totals }),
33073
+ sub: `${formatCompact(detail.totals.cacheReadTokens)} ${t("cacheHit")}`
33074
+ }),
33075
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Stat, {
33076
+ tone: SessionUsageView_module_default.toneOrange,
33077
+ name: "speed",
33078
+ label: t("speed"),
33079
+ value: speed(detail.tokensPerSecond),
33080
+ sub: `${t("first")} ${seconds(detail.averageFirstTokenMs)}`
33081
+ })
33082
+ ]
33083
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
33084
+ className: SessionUsageView_module_default.statRow,
33085
+ children: [
33086
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Stat, {
33087
+ tone: SessionUsageView_module_default.toneTeal,
33088
+ name: "input",
33089
+ label: t("inputFull"),
33090
+ value: formatCompact(detail.totals.uncachedInputTokens),
33091
+ title: formatTokens(detail.totals.uncachedInputTokens),
33092
+ sub: formatTokens(detail.totals.uncachedInputTokens)
33093
+ }),
33094
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Stat, {
33095
+ tone: SessionUsageView_module_default.toneOrange,
33096
+ name: "output",
33097
+ label: t("outputFull"),
33098
+ value: formatCompact(detail.totals.outputTokens),
33099
+ title: formatTokens(detail.totals.outputTokens),
33100
+ sub: formatTokens(detail.totals.outputTokens)
33101
+ }),
33102
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Stat, {
33103
+ tone: SessionUsageView_module_default.tonePurple,
33104
+ name: "read",
33105
+ label: t("readFull"),
33106
+ value: formatCompact(detail.totals.cacheReadTokens),
33107
+ title: formatTokens(detail.totals.cacheReadTokens),
33108
+ sub: formatTokens(detail.totals.cacheReadTokens)
33109
+ }),
33110
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Stat, {
33111
+ tone: SessionUsageView_module_default.tonePink,
33112
+ name: "write",
33113
+ label: t("writeFull"),
33114
+ value: formatCompact(detail.totals.cacheWriteTokens),
33115
+ title: formatTokens(detail.totals.cacheWriteTokens),
33116
+ sub: formatTokens(detail.totals.cacheWriteTokens)
33117
+ })
33118
+ ]
33119
+ })]
33120
+ });
33121
+ }
33122
+ function Tables({ detail, t }) {
33123
+ const nameCounts = /* @__PURE__ */ new Map();
33124
+ for (const row of detail.models) {
33125
+ const key = normalizeModelName(row.name?.trim() || row.model);
33126
+ nameCounts.set(key, (nameCounts.get(key) ?? 0) + 1);
33127
+ }
33128
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
33129
+ className: SessionUsageView_module_default.mid,
33130
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
33131
+ className: SessionUsageView_module_default.card,
33132
+ children: [
33133
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
33134
+ className: SessionUsageView_module_default.cardHead,
33135
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", { children: [
33136
+ t("children"),
33137
+ " ",
33138
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33139
+ className: SessionUsageView_module_default.count,
33140
+ children: detail.subagents.length
33141
+ })
33142
+ ] })
33143
+ }),
33144
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
33145
+ className: `${SessionUsageView_module_default.table} ${SessionUsageView_module_default.childTable}`,
33146
+ children: [
33147
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("colgroup", { children: [
33148
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", { className: SessionUsageView_module_default.childName }),
33149
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", { className: SessionUsageView_module_default.childRequests }),
33150
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", {}),
33151
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", {}),
33152
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", {}),
33153
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", {})
33154
+ ] }),
33155
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
33156
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("session") }),
33157
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("requests") }),
33158
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("tokens") }),
33159
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("hit") }),
33160
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("first") }),
33161
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("speed") })
33162
+ ] }) }),
33163
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: detail.subagents.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
33164
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33165
+ className: SessionUsageView_module_default.ellipsis,
33166
+ title: row.name || row.sessionId,
33167
+ children: row.name || row.sessionId
33168
+ }) }),
33169
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: formatTokens(row.requests) }),
33170
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Token, { n: billedTotal(row.totals) }) }),
33171
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Hit, { totals: row.totals }) }),
33172
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: seconds(row.averageFirstTokenMs) }),
33173
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33174
+ className: SessionUsageView_module_default.speedCell,
33175
+ children: row.tokensPerSecond === null ? "—" : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [Math.round(row.tokensPerSecond), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: "tok/s" })] })
33176
+ }) })
33177
+ ] }, row.sessionId)) })
33178
+ ]
33179
+ }),
33180
+ detail.subagents.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
33181
+ className: SessionUsageView_module_default.empty,
33182
+ children: t("noChildren")
33183
+ })
33184
+ ]
33185
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
33186
+ className: SessionUsageView_module_default.card,
33187
+ children: [
33188
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
33189
+ className: SessionUsageView_module_default.cardHead,
33190
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", { children: [
33191
+ t("models"),
33192
+ " ",
33193
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33194
+ className: SessionUsageView_module_default.count,
33195
+ children: detail.models.length
33196
+ })
33197
+ ] })
33198
+ }),
33199
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
33200
+ className: `${SessionUsageView_module_default.table} ${SessionUsageView_module_default.modelTable}`,
33201
+ children: [
33202
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("colgroup", { children: [
33203
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", { className: SessionUsageView_module_default.modelName }),
33204
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", { className: SessionUsageView_module_default.modelRequests }),
33205
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", {}),
33206
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", {}),
33207
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", {}),
33208
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", {}),
33209
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("col", { className: SessionUsageView_module_default.modelHit })
33210
+ ] }),
33211
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
33212
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("model") }),
33213
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("requests") }),
33214
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("input") }),
33215
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("output") }),
33216
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("read") }),
33217
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("write") }),
33218
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("hit") })
33219
+ ] }) }),
33220
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: detail.models.map((row) => {
33221
+ const name = row.name?.trim() || row.model;
33222
+ const providers = row.providers ?? [];
33223
+ const shared = (nameCounts.get(normalizeModelName(name)) ?? 0) > 1;
33224
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
33225
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("td", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
33226
+ className: SessionUsageView_module_default.modelNameCell,
33227
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelLogo, {
33228
+ model: row.model,
33229
+ name: row.name,
33230
+ providers: row.providers,
33231
+ className: SessionUsageView_module_default.modelLogo
33232
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33233
+ className: SessionUsageView_module_default.ellipsis,
33234
+ title: row.model,
33235
+ children: name
33236
+ })]
33237
+ }), shared && providers.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", {
33238
+ className: SessionUsageView_module_default.modelProvider,
33239
+ title: providers.join(" / "),
33240
+ children: providers.join(" / ")
33241
+ }) : null] }),
33242
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: formatTokens(row.requests) }),
33243
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Token, { n: row.totals.uncachedInputTokens }) }),
33244
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Token, { n: row.totals.outputTokens }) }),
33245
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Token, { n: row.totals.cacheReadTokens }) }),
33246
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Token, { n: row.totals.cacheWriteTokens }) }),
33247
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Hit, { totals: row.totals }) })
33248
+ ] }, row.model);
33249
+ }) })
33250
+ ]
33251
+ }),
33252
+ detail.models.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
33253
+ className: SessionUsageView_module_default.empty,
33254
+ children: t("noModels")
33255
+ })
33256
+ ]
33257
+ })]
33258
+ });
33259
+ }
33260
+ function Records({ detail, t }) {
33261
+ const [opened, setOpened] = (0, react.useState)(() => /* @__PURE__ */ new Set());
33262
+ const [allOpen, setAllOpen] = (0, react.useState)(false);
33263
+ const toggleAll = () => {
33264
+ setAllOpen(!allOpen);
33265
+ setOpened(/* @__PURE__ */ new Set());
33266
+ };
33267
+ const toggle = (id) => setOpened((previous) => {
33268
+ const next = new Set(previous);
33269
+ if (next.has(id)) next.delete(id);
33270
+ else next.add(id);
33271
+ return next;
33272
+ });
33273
+ const providerNames = new Map(detail.routes.map((route) => [route.provider, route.name]));
33274
+ const groups = [];
33275
+ const index = /* @__PURE__ */ new Map();
33276
+ for (const record of detail.records) {
33277
+ const key = `${record.sessionId}:${record.turn}`;
33278
+ let group = index.get(key);
33279
+ if (!group) {
33280
+ group = {
33281
+ key,
33282
+ turn: record.turn,
33283
+ name: record.sessionName || record.sessionId,
33284
+ topic: record.turnName || `${t("turn")} ${record.turn}`,
33285
+ main: record.sessionId === detail.sessionId,
33286
+ rows: []
33287
+ };
33288
+ index.set(key, group);
33289
+ groups.push(group);
33290
+ }
33291
+ group.rows.push(record);
33292
+ }
33293
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
33294
+ className: SessionUsageView_module_default.card,
33295
+ children: [
33296
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
33297
+ className: SessionUsageView_module_default.cardHead,
33298
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", { children: [
33299
+ t("records"),
33300
+ " ",
33301
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33302
+ className: SessionUsageView_module_default.count,
33303
+ children: detail.records.length
33304
+ })
33305
+ ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
33306
+ type: "button",
33307
+ className: SessionUsageView_module_default.action,
33308
+ onClick: toggleAll,
33309
+ children: t(allOpen ? "collapse" : "expand")
33310
+ })]
33311
+ }),
33312
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
33313
+ className: SessionUsageView_module_default.turnList,
33314
+ children: groups.map((group) => {
33315
+ const open = allOpen !== opened.has(group.key);
33316
+ const totals = sum(group.rows);
33317
+ const billed = billedTotal(totals);
33318
+ const running = group.rows.filter((row) => row.status === "running").length;
33319
+ const rates = group.rows.map((row) => row.tokensPerSecond).filter((n) => n !== null);
33320
+ const avgRate = rates.length ? Math.round(rates.reduce((a, b) => a + b, 0) / rates.length) : null;
33321
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
33322
+ className: SessionUsageView_module_default.turn,
33323
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
33324
+ type: "button",
33325
+ className: SessionUsageView_module_default.turnHead,
33326
+ onClick: () => toggle(group.key),
33327
+ "aria-expanded": open,
33328
+ "aria-controls": `usage-turn-${encodeURIComponent(group.key)}`,
33329
+ children: [
33330
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
33331
+ className: `${SessionUsageView_module_default.chevron} ${open ? SessionUsageView_module_default.rotated : ""}`,
33332
+ width: "12",
33333
+ height: "12",
33334
+ viewBox: "0 0 12 12",
33335
+ "aria-hidden": "true",
33336
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
33337
+ d: "m4 2 4 4-4 4",
33338
+ stroke: "currentColor",
33339
+ strokeWidth: "1.5",
33340
+ fill: "none"
33341
+ })
33342
+ }),
33343
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
33344
+ className: SessionUsageView_module_default.turnTitle,
33345
+ children: [group.main ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33346
+ className: SessionUsageView_module_default.turnAgent,
33347
+ title: group.name,
33348
+ children: t("children")
33349
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33350
+ className: SessionUsageView_module_default.turnTopic,
33351
+ title: group.turn === 0 ? t("compaction") : group.topic,
33352
+ children: group.turn === 0 ? t("compaction") : group.topic
33353
+ })]
33354
+ }),
33355
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
33356
+ className: SessionUsageView_module_default.turnSummary,
33357
+ children: [
33358
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
33359
+ group.rows.length,
33360
+ " ",
33361
+ t("reqTimes"),
33362
+ " · ",
33363
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33364
+ className: SessionUsageView_module_default.number,
33365
+ title: formatTokens(billed),
33366
+ children: tokShort(billed)
33367
+ }),
33368
+ " ",
33369
+ t("tokenWord"),
33370
+ running > 0 ? ` · ${running} ${t("inProgress")}` : ""
33371
+ ] }),
33372
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
33373
+ t("avgCache"),
33374
+ " ",
33375
+ pctInt(cacheHitPercentOf(totals))
33376
+ ] }),
33377
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
33378
+ t("avgRate"),
33379
+ " ",
33380
+ avgRate === null ? "—" : avgRate,
33381
+ " ",
33382
+ t("perSec")
33383
+ ] })
33384
+ ]
33385
+ })
33386
+ ]
33387
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
33388
+ id: `usage-turn-${encodeURIComponent(group.key)}`,
33389
+ className: SessionUsageView_module_default.turnBody,
33390
+ hidden: !open,
33391
+ children: group.rows.map((record) => {
33392
+ const duration = record.finishedAt !== null ? record.finishedAt - record.startedAt : null;
33393
+ const billed = billedTotal(record.totals);
33394
+ const hit = cacheHitPercentOf(record.totals);
33395
+ const meta = [];
33396
+ if (duration !== null) meta.push({ text: `${secText(duration)} ${t("sec")}` });
33397
+ if (record.firstTokenMs !== null) meta.push({ text: `${t("firstWait")} ${secText(record.firstTokenMs)} ${t("sec")}` });
33398
+ meta.push({
33399
+ text: `${tokShort(billed)} ${t("tokenWord")}`,
33400
+ title: formatTokens(billed)
33401
+ });
33402
+ if (hit !== null) meta.push({ text: `${t("cacheShort")} ${pctInt(hit)}` });
33403
+ if (record.tokensPerSecond !== null) meta.push({ text: `${Math.round(record.tokensPerSecond)} ${t("perSec")}` });
33404
+ const statusText = record.status === "running" ? t("answering") : record.status === "completed" ? "" : t(record.status);
33405
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
33406
+ className: SessionUsageView_module_default.turnRequest,
33407
+ children: [
33408
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33409
+ className: SessionUsageView_module_default.requestTime,
33410
+ children: clock(record.startedAt)
33411
+ }),
33412
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
33413
+ className: SessionUsageView_module_default.turnRequestHead,
33414
+ children: [
33415
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: `${SessionUsageView_module_default.statusDot} ${record.status === "running" ? SessionUsageView_module_default.live : record.status === "failed" ? SessionUsageView_module_default.bad : record.status === "interrupted" ? SessionUsageView_module_default.muted : SessionUsageView_module_default.good}` }),
33416
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
33417
+ className: SessionUsageView_module_default.recordModel,
33418
+ title: `${record.provider} / ${record.model}`,
33419
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelLogo, {
33420
+ provider: record.provider,
33421
+ model: record.model,
33422
+ className: SessionUsageView_module_default.modelLogo
33423
+ }), record.model || "—"]
33424
+ }),
33425
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
33426
+ className: SessionUsageView_module_default.routeText,
33427
+ title: record.provider,
33428
+ children: [
33429
+ providerNames.get(record.provider) || record.provider || "—",
33430
+ " · ",
33431
+ modelShort(record.model) || "—"
33432
+ ]
33433
+ }),
33434
+ statusText !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
33435
+ className: record.status === "running" ? SessionUsageView_module_default.live : record.status === "failed" ? SessionUsageView_module_default.bad : SessionUsageView_module_default.muted,
33436
+ children: statusText
33437
+ }),
33438
+ record.effort ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
33439
+ className: SessionUsageView_module_default.effort,
33440
+ children: ["· ", record.effort]
33441
+ }) : null
33442
+ ]
33443
+ }),
33444
+ record.finishedAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
33445
+ className: SessionUsageView_module_default.recordMeta,
33446
+ children: meta.map((item, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
33447
+ title: item.title,
33448
+ children: [i > 0 ? " · " : "", item.text]
33449
+ }, i))
33450
+ })
33451
+ ]
33452
+ }, record.id);
33453
+ })
33454
+ })]
33455
+ }, group.key);
33456
+ })
33457
+ }),
33458
+ detail.records.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
33459
+ className: SessionUsageView_module_default.empty,
33460
+ children: t("empty")
33461
+ })
33462
+ ]
33463
+ });
33464
+ }
33465
+ /** Pure presentation export also used by offline visual regression fixtures. */
33466
+ function SessionUsageContent({ detail, t }) {
33467
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
33468
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
33469
+ className: SessionUsageView_module_default.scope,
33470
+ children: t("scope")
33471
+ }),
33472
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Metrics, {
33473
+ detail,
33474
+ t
33475
+ }),
33476
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tables, {
33477
+ detail,
33478
+ t
33479
+ }),
33480
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Records, {
33481
+ detail,
33482
+ t
33483
+ }, detail.sessionId),
33484
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
33485
+ className: SessionUsageView_module_default.note,
33486
+ children: t("note")
33487
+ })
33488
+ ] });
33489
+ }
33490
+ function SessionUsageView({ sessionId, t }) {
33491
+ const { detail, loading, error, retry } = useSessionDetail(sessionId);
33492
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
33493
+ className: SessionUsageView_module_default.scroll,
33494
+ "data-dsh-session-usage": true,
33495
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
33496
+ className: SessionUsageView_module_default.page,
33497
+ children: [
33498
+ loading && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
33499
+ className: SessionUsageView_module_default.empty,
33500
+ role: "status",
33501
+ children: t("loading")
33502
+ }),
33503
+ error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
33504
+ className: SessionUsageView_module_default.error,
33505
+ role: "status",
33506
+ children: [t("failedLoad"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
33507
+ type: "button",
33508
+ className: SessionUsageView_module_default.action,
33509
+ onClick: retry,
33510
+ children: t("retry")
33511
+ })]
33512
+ }),
33513
+ detail && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionUsageContent, {
33514
+ detail,
33515
+ t
33516
+ })
33517
+ ]
33518
+ })
33519
+ });
33520
+ }
33521
+ //#endregion
33522
+ //#region src/client/session-usage-locales.ts
33523
+ /** Session Usage view translations, independent of the global dashboard. */
33524
+ const SESSION_USAGE_NS = "sessionUsage";
33525
+ const usageZh = {
33526
+ tab: "用量",
33527
+ requests: "请求数",
33528
+ tokens: "总 tokens",
33529
+ hit: "命中率",
33530
+ first: "平均首 token",
33531
+ speed: "token 速度",
33532
+ input: "入",
33533
+ output: "出",
33534
+ read: "读",
33535
+ write: "写",
33536
+ requestsCount: "请求数量",
33537
+ inputFull: "输入",
33538
+ outputFull: "输出",
33539
+ readFull: "缓存读取",
33540
+ writeFull: "缓存写入",
33541
+ cacheHit: "缓存命中",
33542
+ compaction: "压缩调用",
33543
+ reqTimes: "个请求",
33544
+ children: "子代理",
33545
+ session: "会话",
33546
+ models: "按模型",
33547
+ model: "模型",
33548
+ records: "请求记录",
33549
+ expand: "全部展开",
33550
+ collapse: "全部收起",
33551
+ loading: "正在读取会话用量…",
33552
+ empty: "本会话还没有请求记录",
33553
+ noChildren: "暂无子代理",
33554
+ noModels: "暂无模型用量",
33555
+ scope: "本会话及所有子代理 · 历史日志累计",
33556
+ note: "统计包含本会话与全部后代的独立请求、重试和压缩调用,不重复计算继承历史。首 token 与速度仅使用已记录的时间信息,缺失时显示 —。",
33557
+ failedLoad: "用量读取失败,已保留上次结果。",
33558
+ retry: "重新读取",
33559
+ completed: "已完成",
33560
+ running: "进行中",
33561
+ failed: "失败",
33562
+ interrupted: "已中断",
33563
+ main: "主会话",
33564
+ turn: "轮",
33565
+ step: "步",
33566
+ started: "开始",
33567
+ duration: "耗时",
33568
+ firstDetail: "首 token",
33569
+ provider: "供应商",
33570
+ status: "状态",
33571
+ exact: "完整 token 数",
33572
+ answering: "正在回答...",
33573
+ firstWait: "首字耗时",
33574
+ sec: "秒",
33575
+ tokenWord: "token",
33576
+ perSec: "token/秒",
33577
+ cacheShort: "缓存",
33578
+ avgCache: "平均缓存",
33579
+ avgRate: "平均速率",
33580
+ inProgress: "个进行中"
33581
+ };
33582
+ const usageEn = {
33583
+ tab: "Usage",
33584
+ requests: "Requests",
33585
+ tokens: "Total tokens",
33586
+ hit: "Cache hit rate",
33587
+ first: "Avg. first token",
33588
+ speed: "Token speed",
33589
+ input: "In",
33590
+ output: "Out",
33591
+ read: "Read",
33592
+ write: "Write",
33593
+ requestsCount: "Requests",
33594
+ inputFull: "Input",
33595
+ outputFull: "Output",
33596
+ readFull: "Cache read",
33597
+ writeFull: "Cache write",
33598
+ cacheHit: "cache hits",
33599
+ compaction: "Compaction",
33600
+ reqTimes: "requests",
33601
+ children: "Subagents",
33602
+ session: "Session",
33603
+ models: "By model",
33604
+ model: "Model",
33605
+ records: "Request log",
33606
+ expand: "Expand all",
33607
+ collapse: "Collapse all",
33608
+ loading: "Reading session usage…",
33609
+ empty: "No requests in this session yet",
33610
+ noChildren: "No subagents yet",
33611
+ noModels: "No model usage yet",
33612
+ scope: "This session and all subagents · Historical log totals",
33613
+ note: "Includes independent requests, retries and compaction calls from this session and all descendants, without counting inherited history twice. Timing uses recorded timestamps only; missing values appear as —.",
33614
+ failedLoad: "Could not read usage. The last successful result is preserved.",
33615
+ retry: "Retry",
33616
+ completed: "Completed",
33617
+ running: "Running",
33618
+ failed: "Failed",
33619
+ interrupted: "Interrupted",
33620
+ main: "Main session",
33621
+ turn: "Turn",
33622
+ step: "Step",
33623
+ started: "Started",
33624
+ duration: "Duration",
33625
+ firstDetail: "First token",
33626
+ provider: "Provider",
33627
+ status: "Status",
33628
+ exact: "Exact token count",
33629
+ answering: "answering...",
33630
+ firstWait: "first token",
33631
+ sec: "s",
33632
+ tokenWord: "token",
33633
+ perSec: "token/s",
33634
+ cacheShort: "cache",
33635
+ avgCache: "avg cache",
33636
+ avgRate: "avg rate",
33637
+ inProgress: "in progress"
33638
+ };
33639
+ const usageZhTW = {
33640
+ ...usageZh,
33641
+ tab: "用量",
33642
+ requests: "請求數",
33643
+ tokens: "總 tokens",
33644
+ hit: "命中率",
33645
+ first: "平均首 token",
33646
+ speed: "token 速度",
33647
+ input: "入",
33648
+ output: "出",
33649
+ read: "讀",
33650
+ write: "寫",
33651
+ requestsCount: "請求數量",
33652
+ inputFull: "輸入",
33653
+ outputFull: "輸出",
33654
+ readFull: "快取讀取",
33655
+ writeFull: "快取寫入",
33656
+ cacheHit: "快取命中",
33657
+ compaction: "壓縮呼叫",
33658
+ reqTimes: "個請求",
33659
+ children: "子代理",
33660
+ session: "會話",
33661
+ models: "按模型",
33662
+ records: "請求記錄",
33663
+ expand: "全部展開",
33664
+ collapse: "全部收起",
33665
+ loading: "正在讀取會話用量…",
33666
+ empty: "本會話還沒有請求記錄",
33667
+ noChildren: "暫無子代理",
33668
+ noModels: "暫無模型用量",
33669
+ scope: "本會話及所有子代理 · 歷史日誌累計",
33670
+ note: "統計包含本會話與全部後代的獨立請求、重試和壓縮呼叫,不重複計算繼承歷史。首 token 與速度僅使用已記錄的時間資訊,缺失時顯示 —。",
33671
+ failedLoad: "用量讀取失敗,已保留上次結果。",
33672
+ retry: "重新讀取",
33673
+ completed: "已完成",
33674
+ running: "進行中",
33675
+ failed: "失敗",
33676
+ interrupted: "已中斷",
33677
+ main: "主會話",
33678
+ turn: "輪",
33679
+ step: "步",
33680
+ started: "開始",
33681
+ duration: "耗時",
33682
+ firstDetail: "首 token",
33683
+ provider: "供應商",
33684
+ status: "狀態",
33685
+ exact: "完整 token 數",
33686
+ answering: "正在回答...",
33687
+ firstWait: "首字耗時",
33688
+ sec: "秒",
33689
+ tokenWord: "token",
33690
+ perSec: "token/秒",
33691
+ cacheShort: "快取",
33692
+ avgCache: "平均快取",
33693
+ avgRate: "平均速率",
33694
+ inProgress: "個進行中"
33695
+ };
33696
+ //#endregion
32609
33697
  //#region src/client/index.tsx
32610
33698
  /** This bundle's npm package name — the key the Plugins page matches on. */
32611
33699
  const BUNDLE_NAME = "dsh-token-total";
@@ -32722,11 +33810,16 @@ window.__ModuleLoader__.load({
32722
33810
  const offEn = ctx.locale.register(LOCALE_NS, "en", en);
32723
33811
  const offZhTw = ctx.locale.register(LOCALE_NS, "zh-TW", zhTW);
32724
33812
  const offContext = Object.entries(CONTEXT_LOCALES).map(([locale, dict]) => ctx.locale.register(CONTEXT_LOCALE_NS, locale, dict));
33813
+ const offSession = [
33814
+ ctx.locale.register(SESSION_USAGE_NS, "zh", usageZh),
33815
+ ctx.locale.register(SESSION_USAGE_NS, "en", usageEn),
33816
+ ctx.locale.register(SESSION_USAGE_NS, "zh-TW", usageZhTW)
33817
+ ];
32725
33818
  return () => {
32726
33819
  offZh();
32727
33820
  offEn();
32728
33821
  offZhTw();
32729
- for (const off of offContext) off();
33822
+ for (const off of [...offContext, ...offSession]) off();
32730
33823
  };
32731
33824
  }, "dsh-token-total: dictionaries");
32732
33825
  ctx.effect(() => {
@@ -32787,6 +33880,14 @@ window.__ModuleLoader__.load({
32787
33880
  label: () => t("nav"),
32788
33881
  locale: LOCALE_NS
32789
33882
  }, StatsPanelIcon));
33883
+ const sessionT = ctx.locale.bind(SESSION_USAGE_NS);
33884
+ ctx.slots.inject("conversation.view", () => ctx.slots.register({
33885
+ name: "conversation.view",
33886
+ id: "token-total-usage",
33887
+ order: 20,
33888
+ label: () => sessionT("tab"),
33889
+ locale: SESSION_USAGE_NS
33890
+ }, SessionUsageView));
32790
33891
  ctx.slots.inject(COMPOSER_DOCK, () => {
32791
33892
  const dockIds = () => new Set(ctx.slots.entries(COMPOSER_DOCK).map((entry) => entry.options.id).filter((id) => id !== void 0));
32792
33893
  let decided = false;