@tangle-network/sandbox-ui 0.79.0 → 0.81.0
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/dist/{WorkflowGraph-SJ2SG5TP.js → WorkflowGraph-472MC3ML.js} +32 -4
- package/dist/chat.d.ts +87 -6
- package/dist/chat.js +11 -5
- package/dist/{chunk-UEMWLVVY.js → chunk-2NS724P4.js} +3 -1
- package/dist/{chunk-IWIZ7RZE.js → chunk-2T6KBMLN.js} +1 -1
- package/dist/{chunk-L62ZT6RS.js → chunk-I3G23XHN.js} +14 -412
- package/dist/chunk-R4AR3TKR.js +424 -0
- package/dist/{chunk-UQXDIQWD.js → chunk-YBFGWPUF.js} +175 -38
- package/dist/dashboard.d.ts +80 -3
- package/dist/dashboard.js +9 -3
- package/dist/globals.css +9 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +29 -19
- package/dist/model-brand-CsFykzMA.d.ts +101 -0
- package/dist/pages.d.ts +1 -2
- package/dist/pages.js +2 -1
- package/dist/styles.css +9 -0
- package/dist/workbench.js +3 -2
- package/dist/workflows.js +2 -2
- package/package.json +1 -1
- package/dist/model-picker-COjPVMzg.d.ts +0 -145
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BrandLogo,
|
|
3
|
+
ModelBrandStack,
|
|
4
|
+
brandInfo,
|
|
5
|
+
canonicalModelId,
|
|
6
|
+
normalizeBrandKey,
|
|
7
|
+
resolveModelBrandIdentity
|
|
8
|
+
} from "./chunk-I3G23XHN.js";
|
|
9
|
+
import {
|
|
10
|
+
cn
|
|
11
|
+
} from "./chunk-EI44GEQ5.js";
|
|
12
|
+
|
|
13
|
+
// src/dashboard/model-picker.tsx
|
|
14
|
+
import * as React from "react";
|
|
15
|
+
import { ChevronDown, Search, Sparkles, Loader2 } from "lucide-react";
|
|
16
|
+
import * as Popover from "@radix-ui/react-dropdown-menu";
|
|
17
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
18
|
+
function modelDedupKey(model) {
|
|
19
|
+
const canonical = canonicalModelId(model).toLowerCase();
|
|
20
|
+
const segments = canonical.split("/").filter(Boolean);
|
|
21
|
+
const modelId = segments[segments.length - 1] ?? canonical;
|
|
22
|
+
const lab = resolveModelBrandIdentity(model).lab.key;
|
|
23
|
+
return lab === "unknown" ? canonical : `${lab}/${modelId}`;
|
|
24
|
+
}
|
|
25
|
+
function dedupeModels(models) {
|
|
26
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
27
|
+
const result = [];
|
|
28
|
+
for (const model of models) {
|
|
29
|
+
const key = modelDedupKey(model);
|
|
30
|
+
const existingIndex = byKey.get(key);
|
|
31
|
+
if (existingIndex === void 0) {
|
|
32
|
+
byKey.set(key, result.length);
|
|
33
|
+
result.push(model);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const existing = result[existingIndex];
|
|
37
|
+
if (!existing.featured && model.featured) {
|
|
38
|
+
result[existingIndex] = model;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
var DEFAULT_FEATURED_MODEL_IDS = [
|
|
44
|
+
"anthropic/claude-opus-4-8",
|
|
45
|
+
"anthropic/claude-sonnet-4-6",
|
|
46
|
+
"openai/gpt-5.4",
|
|
47
|
+
"google/gemini-2.5-pro",
|
|
48
|
+
"deepseek/deepseek-v3"
|
|
49
|
+
];
|
|
50
|
+
function formatPricing(pricing) {
|
|
51
|
+
const prompt = Number(pricing?.prompt ?? 0);
|
|
52
|
+
const completion = Number(pricing?.completion ?? 0);
|
|
53
|
+
if (!prompt && !completion) return null;
|
|
54
|
+
const fmt = (n) => {
|
|
55
|
+
const perM = n * 1e6;
|
|
56
|
+
if (perM === 0) return "0";
|
|
57
|
+
if (perM >= 1) return `$${perM.toFixed(2)}`;
|
|
58
|
+
return `$${perM.toFixed(2)}`;
|
|
59
|
+
};
|
|
60
|
+
return `${fmt(prompt)} / ${fmt(completion)} per 1M`;
|
|
61
|
+
}
|
|
62
|
+
function formatContext(ctx) {
|
|
63
|
+
if (!ctx) return null;
|
|
64
|
+
if (ctx >= 1e6) return `${(ctx / 1e6).toFixed(1)}M ctx`;
|
|
65
|
+
if (ctx >= 1e3) return `${Math.round(ctx / 1e3)}k ctx`;
|
|
66
|
+
return `${ctx} ctx`;
|
|
67
|
+
}
|
|
68
|
+
var PRIORITY_MODEL_GROUPS = ["anthropic", "openai", "google", "deepseek", "zai", "moonshot"];
|
|
69
|
+
function modelGroupKey(model) {
|
|
70
|
+
const identity = resolveModelBrandIdentity(model);
|
|
71
|
+
if (identity.lab.key !== "unknown") return identity.lab.key;
|
|
72
|
+
if (identity.host.key !== "unknown") return identity.host.key;
|
|
73
|
+
return (model._provider ?? model.provider ?? "other").toLowerCase();
|
|
74
|
+
}
|
|
75
|
+
function modelGroupLabel(key) {
|
|
76
|
+
if (key === "moonshot") return "Kimi";
|
|
77
|
+
const brand = brandInfo(normalizeBrandKey(key));
|
|
78
|
+
return brand.key === "unknown" ? key : brand.label;
|
|
79
|
+
}
|
|
80
|
+
function modelGroupRank(key) {
|
|
81
|
+
const priorityIndex = PRIORITY_MODEL_GROUPS.indexOf(normalizeBrandKey(key));
|
|
82
|
+
return priorityIndex === -1 ? Number.POSITIVE_INFINITY : priorityIndex;
|
|
83
|
+
}
|
|
84
|
+
function compareModelGroups(a, b) {
|
|
85
|
+
const aRank = modelGroupRank(a);
|
|
86
|
+
const bRank = modelGroupRank(b);
|
|
87
|
+
if (aRank !== bRank) return aRank - bRank;
|
|
88
|
+
return modelGroupLabel(a).localeCompare(modelGroupLabel(b));
|
|
89
|
+
}
|
|
90
|
+
function compareModelsByDisplayName(a, b) {
|
|
91
|
+
return (a.name ?? a.id).localeCompare(b.name ?? b.id);
|
|
92
|
+
}
|
|
93
|
+
function stripBrandPrefix(name, identity) {
|
|
94
|
+
if (!identity) return name;
|
|
95
|
+
for (const label of [identity.lab.label, identity.host.label]) {
|
|
96
|
+
if (!label) continue;
|
|
97
|
+
if (name.toLowerCase().startsWith(label.toLowerCase())) {
|
|
98
|
+
const after = name.slice(label.length);
|
|
99
|
+
if (/^[\s:]/.test(after)) {
|
|
100
|
+
const rest = after.replace(/^[\s:]+/, "").trim();
|
|
101
|
+
if (rest) return rest;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return name;
|
|
106
|
+
}
|
|
107
|
+
function ModelPicker({
|
|
108
|
+
value,
|
|
109
|
+
onChange,
|
|
110
|
+
models,
|
|
111
|
+
loading = false,
|
|
112
|
+
recents,
|
|
113
|
+
popular,
|
|
114
|
+
excludeProviders,
|
|
115
|
+
modalities,
|
|
116
|
+
variant = "field",
|
|
117
|
+
label = "Model",
|
|
118
|
+
placeholder = "Choose a model",
|
|
119
|
+
className,
|
|
120
|
+
triggerClassName,
|
|
121
|
+
disabled,
|
|
122
|
+
side,
|
|
123
|
+
avoidCollisions
|
|
124
|
+
}) {
|
|
125
|
+
const [query, setQuery] = React.useState("");
|
|
126
|
+
const [open, setOpen] = React.useState(false);
|
|
127
|
+
const searchInputRef = React.useRef(null);
|
|
128
|
+
React.useLayoutEffect(() => {
|
|
129
|
+
if (!open) return;
|
|
130
|
+
const frame = requestAnimationFrame(() => {
|
|
131
|
+
searchInputRef.current?.focus();
|
|
132
|
+
searchInputRef.current?.select();
|
|
133
|
+
});
|
|
134
|
+
return () => cancelAnimationFrame(frame);
|
|
135
|
+
}, [open]);
|
|
136
|
+
const deduped = React.useMemo(() => dedupeModels(models), [models]);
|
|
137
|
+
const filtered = React.useMemo(() => {
|
|
138
|
+
const excluded = new Set((excludeProviders ?? []).map((p) => p.toLowerCase()));
|
|
139
|
+
const allowedModalities = modalities ? new Set(modalities) : null;
|
|
140
|
+
const q = query.trim().toLowerCase();
|
|
141
|
+
return deduped.filter((m) => {
|
|
142
|
+
const provider = (m._provider ?? m.provider ?? "").toLowerCase();
|
|
143
|
+
if (excluded.has(provider)) return false;
|
|
144
|
+
if (allowedModalities && m.architecture?.modality && !allowedModalities.has(m.architecture.modality)) return false;
|
|
145
|
+
if (!q) return true;
|
|
146
|
+
const id = canonicalModelId(m).toLowerCase();
|
|
147
|
+
const name = (m.name ?? "").toLowerCase();
|
|
148
|
+
const identity = resolveModelBrandIdentity(m);
|
|
149
|
+
return id.includes(q) || name.includes(q) || provider.includes(q) || identity.host.label.toLowerCase().includes(q) || identity.lab.label.toLowerCase().includes(q);
|
|
150
|
+
});
|
|
151
|
+
}, [deduped, query, modalities, excludeProviders]);
|
|
152
|
+
const grouped = React.useMemo(() => {
|
|
153
|
+
const groups = /* @__PURE__ */ new Map();
|
|
154
|
+
for (const m of filtered) {
|
|
155
|
+
const key = modelGroupKey(m);
|
|
156
|
+
const list = groups.get(key);
|
|
157
|
+
if (list) list.push(m);
|
|
158
|
+
else groups.set(key, [m]);
|
|
159
|
+
}
|
|
160
|
+
return Array.from(groups.entries()).map(([key, list]) => [key, [...list].sort(compareModelsByDisplayName)]).sort(([a], [b]) => compareModelGroups(a, b));
|
|
161
|
+
}, [filtered]);
|
|
162
|
+
const current = React.useMemo(
|
|
163
|
+
() => models.find((m) => canonicalModelId(m) === value),
|
|
164
|
+
[models, value]
|
|
165
|
+
);
|
|
166
|
+
const currentIdentity = current ? resolveModelBrandIdentity(current) : null;
|
|
167
|
+
const currentLabel = stripBrandPrefix(
|
|
168
|
+
current?.name ?? current?.id ?? value,
|
|
169
|
+
currentIdentity
|
|
170
|
+
);
|
|
171
|
+
const recentIds = React.useMemo(() => {
|
|
172
|
+
if (!recents?.length) return [];
|
|
173
|
+
const lookup = new Map(models.map((m) => [canonicalModelId(m), m]));
|
|
174
|
+
return recents.map((id) => lookup.get(id)).filter((m) => Boolean(m)).slice(0, 4);
|
|
175
|
+
}, [recents, models]);
|
|
176
|
+
const popularModels = React.useMemo(() => {
|
|
177
|
+
if (!popular?.length) return [];
|
|
178
|
+
const lookup = new Map(models.map((m) => [canonicalModelId(m), m]));
|
|
179
|
+
return popular.map((id) => lookup.get(id)).filter((m) => Boolean(m));
|
|
180
|
+
}, [popular, models]);
|
|
181
|
+
const featuredModels = React.useMemo(() => {
|
|
182
|
+
const flagged = deduped.filter((m) => m.featured);
|
|
183
|
+
if (flagged.length > 0) return flagged;
|
|
184
|
+
const seedKeys = new Set(
|
|
185
|
+
DEFAULT_FEATURED_MODEL_IDS.map((id) => modelDedupKey({ id }))
|
|
186
|
+
);
|
|
187
|
+
const seeded = deduped.filter((m) => seedKeys.has(modelDedupKey(m)));
|
|
188
|
+
const order = DEFAULT_FEATURED_MODEL_IDS.map((id) => modelDedupKey({ id }));
|
|
189
|
+
return seeded.sort(
|
|
190
|
+
(a, b) => order.indexOf(modelDedupKey(a)) - order.indexOf(modelDedupKey(b))
|
|
191
|
+
);
|
|
192
|
+
}, [deduped]);
|
|
193
|
+
const handleSelect = (id) => {
|
|
194
|
+
onChange(id);
|
|
195
|
+
setOpen(false);
|
|
196
|
+
setQuery("");
|
|
197
|
+
};
|
|
198
|
+
const triggerLabel = label ? `${label}: ${currentLabel || placeholder}` : currentLabel || placeholder;
|
|
199
|
+
const trigger = variant === "pill" ? /* @__PURE__ */ jsxs(
|
|
200
|
+
"button",
|
|
201
|
+
{
|
|
202
|
+
type: "button",
|
|
203
|
+
"aria-label": triggerLabel,
|
|
204
|
+
disabled,
|
|
205
|
+
className: cn(
|
|
206
|
+
"inline-flex h-8 items-center gap-1.5 rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container",
|
|
207
|
+
"px-2.5 text-xs font-medium text-foreground shadow-sm",
|
|
208
|
+
"transition-colors duration-[var(--transition-fast)]",
|
|
209
|
+
"hover:border-[var(--md3-outline-variant)] hover:bg-surface-container-high",
|
|
210
|
+
"focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
211
|
+
"data-[state=open]:border-[var(--md3-outline)] data-[state=open]:bg-surface-container-high",
|
|
212
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
213
|
+
className,
|
|
214
|
+
triggerClassName
|
|
215
|
+
),
|
|
216
|
+
children: [
|
|
217
|
+
currentIdentity ? /* @__PURE__ */ jsx(ModelBrandStack, { identity: currentIdentity, size: "sm" }) : /* @__PURE__ */ jsx(Sparkles, { className: "h-3 w-3 text-muted-foreground" }),
|
|
218
|
+
/* @__PURE__ */ jsx("span", { className: "truncate max-w-[160px]", children: currentLabel || placeholder }),
|
|
219
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "ml-auto h-3 w-3 shrink-0 text-muted-foreground transition-transform data-[state=open]:rotate-180" })
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
) : /* @__PURE__ */ jsxs(
|
|
223
|
+
"button",
|
|
224
|
+
{
|
|
225
|
+
type: "button",
|
|
226
|
+
"aria-label": triggerLabel,
|
|
227
|
+
disabled,
|
|
228
|
+
className: cn(
|
|
229
|
+
"flex w-full items-center justify-between gap-2 rounded-[var(--radius-md)]",
|
|
230
|
+
"border border-[var(--md3-outline-variant)] bg-surface-container px-3 py-2.5 text-sm text-left",
|
|
231
|
+
"transition-colors duration-[var(--transition-fast)]",
|
|
232
|
+
"hover:border-[var(--md3-outline-variant)] hover:bg-surface-container-high",
|
|
233
|
+
"focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
234
|
+
"data-[state=open]:border-[var(--md3-outline)] data-[state=open]:bg-surface-container-high",
|
|
235
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
236
|
+
className,
|
|
237
|
+
triggerClassName
|
|
238
|
+
),
|
|
239
|
+
children: [
|
|
240
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
|
|
241
|
+
currentIdentity && /* @__PURE__ */ jsx(ModelBrandStack, { identity: currentIdentity, size: "sm" }),
|
|
242
|
+
/* @__PURE__ */ jsx("span", { className: cn("truncate", current ? "text-foreground font-medium" : "text-muted-foreground"), children: currentLabel || placeholder })
|
|
243
|
+
] }),
|
|
244
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 shrink-0 text-muted-foreground transition-transform data-[state=open]:rotate-180" })
|
|
245
|
+
]
|
|
246
|
+
}
|
|
247
|
+
);
|
|
248
|
+
return /* @__PURE__ */ jsxs("div", { className: cn(variant === "field" ? "space-y-1.5" : "inline-flex", variant === "field" ? className : void 0), children: [
|
|
249
|
+
variant === "field" && label && /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-muted-foreground uppercase tracking-[0.06em]", children: label }),
|
|
250
|
+
/* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange: setOpen, modal: false, children: [
|
|
251
|
+
/* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: trigger }),
|
|
252
|
+
/* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsxs(
|
|
253
|
+
Popover.Content,
|
|
254
|
+
{
|
|
255
|
+
side,
|
|
256
|
+
sideOffset: 4,
|
|
257
|
+
align: variant === "pill" ? "start" : "start",
|
|
258
|
+
avoidCollisions,
|
|
259
|
+
collisionPadding: 24,
|
|
260
|
+
className: cn(
|
|
261
|
+
"z-50 w-[var(--radix-dropdown-menu-trigger-width)] min-w-[320px] max-w-[460px]",
|
|
262
|
+
// Cap to the smaller of the fixed height and the viewport space on
|
|
263
|
+
// the open side, so a list pinned downward never runs off-screen.
|
|
264
|
+
"max-h-[min(440px,var(--radix-dropdown-menu-content-available-height))] overflow-hidden flex flex-col",
|
|
265
|
+
"rounded-[var(--radius-md)] border border-[var(--md3-outline-variant)] bg-surface-container-highest shadow-[0_8px_30px_rgba(0,0,0,0.45)] ring-1 ring-[#ffffff14]",
|
|
266
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
267
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
268
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
|
|
269
|
+
),
|
|
270
|
+
children: [
|
|
271
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-b border-[var(--md3-outline-variant)] bg-surface-container-high px-3 py-2", children: [
|
|
272
|
+
/* @__PURE__ */ jsx(Search, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
273
|
+
/* @__PURE__ */ jsx(
|
|
274
|
+
"input",
|
|
275
|
+
{
|
|
276
|
+
ref: searchInputRef,
|
|
277
|
+
type: "text",
|
|
278
|
+
value: query,
|
|
279
|
+
onChange: (e) => setQuery(e.target.value),
|
|
280
|
+
onKeyDown: (e) => {
|
|
281
|
+
if (e.key.length === 1) e.stopPropagation();
|
|
282
|
+
},
|
|
283
|
+
placeholder: "Search models...",
|
|
284
|
+
autoFocus: true,
|
|
285
|
+
className: "flex-1 bg-transparent text-sm font-medium outline-none placeholder:font-normal placeholder:text-muted-foreground"
|
|
286
|
+
}
|
|
287
|
+
),
|
|
288
|
+
loading && /* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin text-muted-foreground" })
|
|
289
|
+
] }),
|
|
290
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto", children: [
|
|
291
|
+
!query && featuredModels.length > 0 && /* @__PURE__ */ jsx(Section, { label: "Recommended", tone: "featured", children: featuredModels.map((m) => /* @__PURE__ */ jsx(
|
|
292
|
+
ModelRow,
|
|
293
|
+
{
|
|
294
|
+
model: m,
|
|
295
|
+
active: canonicalModelId(m) === value,
|
|
296
|
+
onSelect: handleSelect,
|
|
297
|
+
featured: true
|
|
298
|
+
},
|
|
299
|
+
`featured-${canonicalModelId(m)}`
|
|
300
|
+
)) }),
|
|
301
|
+
!query && popularModels.length > 0 && /* @__PURE__ */ jsx(Section, { label: "Top models", tone: "featured", children: popularModels.map((m) => /* @__PURE__ */ jsx(
|
|
302
|
+
ModelRow,
|
|
303
|
+
{
|
|
304
|
+
model: m,
|
|
305
|
+
active: canonicalModelId(m) === value,
|
|
306
|
+
onSelect: handleSelect,
|
|
307
|
+
featured: true
|
|
308
|
+
},
|
|
309
|
+
`popular-${canonicalModelId(m)}`
|
|
310
|
+
)) }),
|
|
311
|
+
!query && recentIds.length > 0 && /* @__PURE__ */ jsx(Section, { label: "Recent", children: recentIds.map((m) => /* @__PURE__ */ jsx(
|
|
312
|
+
ModelRow,
|
|
313
|
+
{
|
|
314
|
+
model: m,
|
|
315
|
+
active: canonicalModelId(m) === value,
|
|
316
|
+
onSelect: handleSelect
|
|
317
|
+
},
|
|
318
|
+
`recent-${canonicalModelId(m)}`
|
|
319
|
+
)) }),
|
|
320
|
+
grouped.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-3 py-8 text-center text-xs text-muted-foreground", children: loading ? "Loading models..." : query ? "No models match." : "No models available." }) : grouped.map(([groupKey, list]) => /* @__PURE__ */ jsx(Section, { label: modelGroupLabel(groupKey), children: list.map((m) => /* @__PURE__ */ jsx(
|
|
321
|
+
ModelRow,
|
|
322
|
+
{
|
|
323
|
+
model: m,
|
|
324
|
+
active: canonicalModelId(m) === value,
|
|
325
|
+
onSelect: handleSelect
|
|
326
|
+
},
|
|
327
|
+
canonicalModelId(m)
|
|
328
|
+
)) }, groupKey))
|
|
329
|
+
] }),
|
|
330
|
+
/* @__PURE__ */ jsxs("div", { className: "border-t border-[var(--md3-outline-variant)] px-3 py-1.5 text-[10px] text-muted-foreground", children: [
|
|
331
|
+
filtered.length,
|
|
332
|
+
" of ",
|
|
333
|
+
deduped.length,
|
|
334
|
+
" model",
|
|
335
|
+
deduped.length === 1 ? "" : "s"
|
|
336
|
+
] })
|
|
337
|
+
]
|
|
338
|
+
}
|
|
339
|
+
) })
|
|
340
|
+
] })
|
|
341
|
+
] });
|
|
342
|
+
}
|
|
343
|
+
function Section({ label, children, tone }) {
|
|
344
|
+
const identity = brandInfo(normalizeBrandKey(label));
|
|
345
|
+
return /* @__PURE__ */ jsxs("div", { className: "py-1", children: [
|
|
346
|
+
/* @__PURE__ */ jsxs(
|
|
347
|
+
"div",
|
|
348
|
+
{
|
|
349
|
+
className: cn(
|
|
350
|
+
"flex items-center gap-1.5 px-3 pt-1.5 pb-0.5 text-[10px] font-mono uppercase tracking-widest",
|
|
351
|
+
tone === "featured" ? "text-primary" : "text-muted-foreground"
|
|
352
|
+
),
|
|
353
|
+
children: [
|
|
354
|
+
identity.key !== "unknown" && /* @__PURE__ */ jsx(BrandLogo, { brand: identity, size: "xs" }),
|
|
355
|
+
/* @__PURE__ */ jsx("span", { children: label })
|
|
356
|
+
]
|
|
357
|
+
}
|
|
358
|
+
),
|
|
359
|
+
/* @__PURE__ */ jsx("div", { children })
|
|
360
|
+
] });
|
|
361
|
+
}
|
|
362
|
+
function PickerItem({
|
|
363
|
+
onSelect,
|
|
364
|
+
active,
|
|
365
|
+
featured,
|
|
366
|
+
children
|
|
367
|
+
}) {
|
|
368
|
+
return /* @__PURE__ */ jsx(
|
|
369
|
+
Popover.Item,
|
|
370
|
+
{
|
|
371
|
+
onSelect: (e) => {
|
|
372
|
+
e.preventDefault();
|
|
373
|
+
onSelect();
|
|
374
|
+
},
|
|
375
|
+
className: cn(
|
|
376
|
+
"flex cursor-pointer items-start gap-2 rounded-md px-3 py-2 outline-none",
|
|
377
|
+
"transition-colors duration-[var(--transition-fast)]",
|
|
378
|
+
"hover:bg-accent/50 focus:bg-accent/50",
|
|
379
|
+
featured && "mx-1 border border-primary/10 bg-primary/[0.04] px-2.5",
|
|
380
|
+
active && "bg-primary/10 font-medium text-foreground ring-1 ring-inset ring-primary/25 hover:bg-primary/15 focus:bg-primary/15"
|
|
381
|
+
),
|
|
382
|
+
children
|
|
383
|
+
}
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
function ModelRow({
|
|
387
|
+
model,
|
|
388
|
+
active,
|
|
389
|
+
onSelect,
|
|
390
|
+
featured
|
|
391
|
+
}) {
|
|
392
|
+
const id = canonicalModelId(model);
|
|
393
|
+
const pricing = formatPricing(model.pricing);
|
|
394
|
+
const ctx = formatContext(model.context_length);
|
|
395
|
+
const identity = resolveModelBrandIdentity(model);
|
|
396
|
+
const via = !identity.combined ? identity.host.label : null;
|
|
397
|
+
return /* @__PURE__ */ jsxs(PickerItem, { onSelect: () => onSelect(id), active, featured, children: [
|
|
398
|
+
/* @__PURE__ */ jsx(ModelBrandStack, { identity, size: "md" }),
|
|
399
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
400
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
401
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-sm font-medium", children: model.name ?? model.id }),
|
|
402
|
+
via && /* @__PURE__ */ jsxs("span", { className: "shrink-0 rounded-full border border-[var(--md3-outline-variant)] bg-surface-container px-1.5 py-px text-[9px] font-medium text-muted-foreground", children: [
|
|
403
|
+
"via ",
|
|
404
|
+
via
|
|
405
|
+
] })
|
|
406
|
+
] }),
|
|
407
|
+
(ctx || pricing) && /* @__PURE__ */ jsxs("div", { className: "mt-0.5 flex items-center gap-1.5 text-[11px] text-muted-foreground", children: [
|
|
408
|
+
ctx && /* @__PURE__ */ jsx("span", { className: "shrink-0", children: ctx }),
|
|
409
|
+
ctx && pricing && /* @__PURE__ */ jsx("span", { className: "shrink-0 opacity-40", children: "\xB7" }),
|
|
410
|
+
pricing && /* @__PURE__ */ jsx("span", { className: "shrink-0 font-mono", children: pricing })
|
|
411
|
+
] })
|
|
412
|
+
] })
|
|
413
|
+
] });
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export {
|
|
417
|
+
modelDedupKey,
|
|
418
|
+
dedupeModels,
|
|
419
|
+
DEFAULT_FEATURED_MODEL_IDS,
|
|
420
|
+
formatPricing,
|
|
421
|
+
formatContext,
|
|
422
|
+
stripBrandPrefix,
|
|
423
|
+
ModelPicker
|
|
424
|
+
};
|