Skip to content

Commit 8078d88

Browse files
committed
gui: add β˜€οΈπŸŒπŸŒ™ icons to gpt-5.6-sol/terra/luna globally
New utility gui/src/model-display.ts exports modelLabel(slug) which prepends visual icons for the 5.6 trio. Applied across all GUI pages: - Dashboard sidecar dropdowns - Models page model list - Subagents featured + available lists - Usage page model table + day chart tooltips - Logs page model column + detail panel Icons: β˜€οΈ sol, 🌍 terra, πŸŒ™ luna. Provider-prefixed slugs also match (e.g. openrouter/openai/gpt-5.6-sol).
1 parent dc43fba commit 8078d88

6 files changed

Lines changed: 38 additions & 9 deletions

File tree

β€Žgui/src/model-display.tsβ€Ž

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Global model display-name mapping: prepends a visual icon for recognized model slugs.
3+
* Used across all GUI surfaces (dropdowns, tables, badges) so the 5.6 trio is instantly
4+
* distinguishable.
5+
*/
6+
7+
const MODEL_ICONS: Record<string, string> = {
8+
"gpt-5.6-sol": "\u2600\uFE0F", // β˜€οΈ sun
9+
"gpt-5.6-terra": "\uD83C\uDF0D", // 🌍 earth
10+
"gpt-5.6-luna": "\uD83C\uDF19", // πŸŒ™ moon
11+
};
12+
13+
/** Return a display label with an icon prefix for recognized slugs, else the raw slug. */
14+
export function modelLabel(slug: string): string {
15+
// Check bare slug first, then try the tail after a provider prefix (e.g. "openrouter/openai/gpt-5.6-sol").
16+
const icon = MODEL_ICONS[slug] ?? MODEL_ICONS[slug.slice(slug.lastIndexOf("/") + 1)];
17+
return icon ? `${icon} ${slug}` : slug;
18+
}
19+
20+
/** Return just the icon for a slug, or empty string if none. */
21+
export function modelIcon(slug: string): string {
22+
return MODEL_ICONS[slug] ?? MODEL_ICONS[slug.slice(slug.lastIndexOf("/") + 1)] ?? "";
23+
}

β€Žgui/src/pages/Dashboard.tsxβ€Ž

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ interface UpdateJob {
4949
restarted?: boolean;
5050
}
5151

52+
import { modelLabel } from "../model-display";
53+
5254
const SEARCH_SIDECAR_MODELS = ["gpt-5.6-luna", "gpt-5.4-mini", "gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "gpt-5.6-sol", "gpt-5.6-terra"];
5355
const VISION_SIDECAR_MODELS = ["gpt-5.6-luna", "gpt-5.4-mini", "gpt-5.4", "gpt-5.5", "gpt-5.6-sol", "gpt-5.6-terra"];
5456
const REASONING_LEVELS = ["low", "medium", "high"];
@@ -442,7 +444,7 @@ export default function Dashboard({ apiBase }: { apiBase: string }) {
442444
<div className="setting-controls" style={{ display: "flex", gap: 8 }}>
443445
<Select
444446
value={sidecar?.webSearch.model ?? "gpt-5.6-luna"}
445-
options={SEARCH_SIDECAR_MODELS.map(m => ({ value: m, label: m }))}
447+
options={SEARCH_SIDECAR_MODELS.map(m => ({ value: m, label: modelLabel(m) }))}
446448
onChange={v => saveSidecar({ webSearch: { model: v, reasoning: sidecar!.webSearch.reasoning } })}
447449
disabled={!sidecar || sidecarSaving}
448450
label={t("dash.searchModel")}
@@ -466,7 +468,7 @@ export default function Dashboard({ apiBase }: { apiBase: string }) {
466468
</div>
467469
<Select
468470
value={sidecar?.vision.model ?? "gpt-5.6-luna"}
469-
options={VISION_SIDECAR_MODELS.map(m => ({ value: m, label: m }))}
471+
options={VISION_SIDECAR_MODELS.map(m => ({ value: m, label: modelLabel(m) }))}
470472
onChange={v => saveSidecar({ vision: { model: v } })}
471473
disabled={!sidecar || sidecarSaving}
472474
label={t("dash.visionModel")}

β€Žgui/src/pages/Logs.tsxβ€Ž

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useI18n, LOCALES } from "../i18n";
33
import { formatTokens } from "../format-tokens";
44
import { statusCodeInfo } from "../status-codes";
55
import { IconX } from "../icons";
6+
import { modelLabel } from "../model-display";
67
import { EmptyState } from "../ui";
78

89
interface UsageBreakdown {
@@ -164,7 +165,7 @@ export default function Logs({ apiBase }: { apiBase: string }) {
164165
</td>
165166
<td className="mono log-col-model" title={modelTitle(log)}>
166167
<span style={{ display: "inline-flex", alignItems: "center", gap: 6, flexWrap: "wrap" }}>
167-
<span>{log.resolvedModel ?? log.model}</span>
168+
<span>{modelLabel(log.resolvedModel ?? log.model)}</span>
168169
{speedLabel(log) && <span className="badge badge-amber">{speedLabel(log)}</span>}
169170
</span>
170171
</td>
@@ -203,7 +204,7 @@ export default function Logs({ apiBase }: { apiBase: string }) {
203204
<div className="log-detail-grid">
204205
<span className="muted">{t("logs.col.time")}</span><span className="mono">{new Date(detail.timestamp).toLocaleString(localeTag)}</span>
205206
<span className="muted">{t("logs.col.request")}</span><span className="mono log-detail-break">{detail.requestId ?? "-"}</span>
206-
<span className="muted">{t("logs.col.model")}</span><span className="mono">{detail.resolvedModel ?? detail.model}</span>
207+
<span className="muted">{t("logs.col.model")}</span><span className="mono">{modelLabel(detail.resolvedModel ?? detail.model)}</span>
207208
<span className="muted">{t("logs.col.provider")}</span><span>{detail.provider}</span>
208209
{detail.errorCode && (<><span className="muted">{t("logs.col.error")}</span><span className="mono">{detail.errorCode}</span></>)}
209210
{detail.upstreamError && (<><span className="muted">{t("logs.col.upstreamReason")}</span><span className="mono log-detail-break">{detail.upstreamError}</span></>)}

β€Žgui/src/pages/Models.tsxβ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
22
import { Switch, Notice, EmptyState, Select } from "../ui";
33
import { IconChevron, IconBoxes } from "../icons";
44
import { useT } from "../i18n";
5+
import { modelLabel } from "../model-display";
56

67
interface ModelRow {
78
provider: string;
@@ -498,7 +499,7 @@ export default function Models({ apiBase }: { apiBase: string }) {
498499
return (
499500
<div key={m.namespaced} className="row" style={{ padding: "5px 0" }}>
500501
<Switch on={!off} onClick={() => toggle(m.namespaced)} disabled={busy} label={m.id} />
501-
<code className="mono" style={{ fontSize: 13, color: off ? "var(--faint)" : "var(--text)", textDecoration: off ? "line-through" : "none" }}>{m.id}</code>
502+
<code className="mono" style={{ fontSize: 13, color: off ? "var(--faint)" : "var(--text)", textDecoration: off ? "line-through" : "none" }}>{modelLabel(m.id)}</code>
502503
{m.contextCapped && <span className="muted mono" style={{ fontSize: 11, padding: "1px 6px", border: "1px solid var(--border)", borderRadius: 999 }}>{t("models.contextCappedValue", { value: fmtK(m.contextCap ?? contextCapValue) })}</span>}
503504
</div>
504505
);

β€Žgui/src/pages/Subagents.tsxβ€Ž

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useEffect, useMemo, useState } from "react";
22
import { Notice, EmptyState } from "../ui";
33
import { IconArrowUp, IconArrowDown, IconX, IconCheck, IconSearch, IconBot } from "../icons";
44
import { useT, Trans } from "../i18n";
5+
import { modelLabel } from "../model-display";
56

67
export default function Subagents({ apiBase }: { apiBase: string }) {
78
const t = useT();
@@ -82,7 +83,7 @@ export default function Subagents({ apiBase }: { apiBase: string }) {
8283
{chosen.map((m, i) => (
8384
<div key={m} className="card panel-accent row" style={{ padding: "8px 12px", gap: 10 }}>
8485
<span className="mono" style={{ width: 18, color: "var(--accent)", fontWeight: 700 }}>{i + 1}</span>
85-
<code className="mono" style={{ flex: 1, color: "var(--text)" }}>{m}</code>
86+
<code className="mono" style={{ flex: 1, color: "var(--text)" }}>{modelLabel(m)}</code>
8687
<button className="btn btn-ghost btn-icon btn-sm" onClick={() => move(i, -1)} disabled={i === 0} aria-label={t("sub.moveUp", { m })}>
8788
<IconArrowUp />
8889
</button>
@@ -134,7 +135,7 @@ export default function Subagents({ apiBase }: { apiBase: string }) {
134135
{sel && <IconCheck style={{ width: 16, height: 16 }} />}
135136
</span>
136137
<IconBot style={{ width: 15, height: 15, color: "var(--faint)", flexShrink: 0 }} />
137-
<code className="mono" style={{ color: "var(--text)" }}>{m}</code>
138+
<code className="mono" style={{ color: "var(--text)" }}>{modelLabel(m)}</code>
138139
</button>
139140
);
140141
})}

β€Žgui/src/pages/Usage.tsxβ€Ž

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
22
import { useI18n } from "../i18n";
33
import { formatTokens } from "../format-tokens";
44
import { EmptyState } from "../ui";
5+
import { modelLabel } from "../model-display";
56

67
type Range = "all" | "30d" | "7d";
78

@@ -304,7 +305,7 @@ export default function Usage({ apiBase }: { apiBase: string }) {
304305
{d.models.slice(0, 8).map(m => (
305306
<div key={`${m.provider}/${m.model}`} className="daybar-tip-row">
306307
<span className="daybar-tip-swatch" style={{ background: modelColor(m.model, m.provider) }} />
307-
<span className="daybar-tip-name">{m.model}</span>
308+
<span className="daybar-tip-name">{modelLabel(m.model)}</span>
308309
<span className="daybar-tip-val">{formatTokens(m.totalTokens, locale)}</span>
309310
</div>
310311
))}
@@ -386,7 +387,7 @@ export default function Usage({ apiBase }: { apiBase: string }) {
386387
<tbody>
387388
{filteredModels.map(m => (
388389
<tr key={`${m.provider}/${m.model}/${m.resolvedModel ?? ""}`}>
389-
<td className="mono">{m.resolvedModel ?? m.model}</td>
390+
<td className="mono">{modelLabel(m.resolvedModel ?? m.model)}</td>
390391
<td className="muted">{m.provider}</td>
391392
<td className="num">{m.requests}</td>
392393
<td className="num">{m.measuredRequests}</td>

0 commit comments

Comments
Β (0)