@ai-matrx/agents 0.59.194 → 0.59.196
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/CHANGELOG.md +6 -1
- package/dist/content-transfer/index.cjs +1 -1
- package/dist/content-transfer/index.js +1 -1
- package/dist/content-transfer/react/index.cjs +1 -1
- package/dist/content-transfer/react/index.js +1 -1
- package/dist/mandates/index.cjs +4 -4
- package/dist/mandates/index.d.cts +6 -6
- package/dist/mandates/index.d.ts +6 -6
- package/dist/mandates/index.js +4 -4
- package/dist/settings/index.cjs +104 -75
- package/dist/settings/index.d.cts +91 -1
- package/dist/settings/index.d.ts +91 -1
- package/dist/settings/index.js +104 -75
- package/dist/settings/react/index.cjs +2846 -566
- package/dist/settings/react/index.d.cts +112 -101
- package/dist/settings/react/index.d.ts +112 -101
- package/dist/settings/react/index.js +2874 -578
- package/package.json +6 -6
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"use client";
|
|
3
3
|
|
|
4
4
|
// settings/react/index.ts
|
|
5
|
-
import { useSyncExternalStore } from "react";
|
|
5
|
+
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
6
6
|
|
|
7
7
|
// generated/llm-enums.ts
|
|
8
8
|
var LLM_PARAMS_KEYS = [
|
|
@@ -81,6 +81,168 @@ var LLM_PARAMS_KEYS = [
|
|
|
81
81
|
"tts_quality"
|
|
82
82
|
];
|
|
83
83
|
|
|
84
|
+
// models/capabilities.ts
|
|
85
|
+
function isManagedAgentModelCapability(capabilities) {
|
|
86
|
+
return capabilities.interaction === "agent";
|
|
87
|
+
}
|
|
88
|
+
function isDecisionModelCapability(capabilities) {
|
|
89
|
+
return capabilities.interaction === "decision";
|
|
90
|
+
}
|
|
91
|
+
function acceptsTextInstructions(capabilities) {
|
|
92
|
+
if (capabilities.interaction === "realtime") return true;
|
|
93
|
+
const input = capabilities.input ?? [];
|
|
94
|
+
return input.length === 0 || input.includes("text");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// models/feature-map.ts
|
|
98
|
+
var FEATURE_BUCKET_ORDER = [
|
|
99
|
+
"thinking",
|
|
100
|
+
"tools",
|
|
101
|
+
"schema",
|
|
102
|
+
"search",
|
|
103
|
+
"extraction",
|
|
104
|
+
"x_search",
|
|
105
|
+
"other"
|
|
106
|
+
];
|
|
107
|
+
var FEATURE_BUCKETS = {
|
|
108
|
+
schema: { label: "Schema", description: "Structured & JSON output" },
|
|
109
|
+
tools: { label: "Tools", description: "Function & tool calling" },
|
|
110
|
+
search: { label: "Search", description: "Web search" },
|
|
111
|
+
x_search: { label: "X Search", description: "X (Twitter) platform search" },
|
|
112
|
+
thinking: { label: "Thinking", description: "Reasoning & extended thinking" },
|
|
113
|
+
extraction: {
|
|
114
|
+
label: "Extraction",
|
|
115
|
+
description: "NER, classification & entity extraction"
|
|
116
|
+
},
|
|
117
|
+
other: { label: "Other", description: "Uncategorized or niche features" }
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// models/format.ts
|
|
121
|
+
var RATING_TO_TIER = {
|
|
122
|
+
1: "$",
|
|
123
|
+
2: "$$",
|
|
124
|
+
3: "$$$",
|
|
125
|
+
4: "$$$$",
|
|
126
|
+
5: "$$$$$",
|
|
127
|
+
6: "$$$$$+"
|
|
128
|
+
// renders as the "5+" band
|
|
129
|
+
};
|
|
130
|
+
var TOP_TIER_COST_RATING = 6;
|
|
131
|
+
var TOP_TIER_LOCKED_TITLE = "This model is limited to approved accounts";
|
|
132
|
+
function isTopTierRating(rating) {
|
|
133
|
+
return typeof rating === "number" && rating >= TOP_TIER_COST_RATING;
|
|
134
|
+
}
|
|
135
|
+
function costRatingTier(rating) {
|
|
136
|
+
if (typeof rating !== "number") return null;
|
|
137
|
+
return RATING_TO_TIER[rating] ?? null;
|
|
138
|
+
}
|
|
139
|
+
function speedRatingLabel(rating) {
|
|
140
|
+
if (typeof rating !== "number") return null;
|
|
141
|
+
return rating >= 6 ? "5+" : String(rating);
|
|
142
|
+
}
|
|
143
|
+
function speedRatingWord(rating) {
|
|
144
|
+
if (typeof rating !== "number") return "\u2014";
|
|
145
|
+
if (rating <= 2) return "Slow";
|
|
146
|
+
if (rating === 3) return "Med";
|
|
147
|
+
if (rating === 4) return "Fast";
|
|
148
|
+
if (rating === 5) return "Fast+";
|
|
149
|
+
return "Max";
|
|
150
|
+
}
|
|
151
|
+
function costRatingWord(rating) {
|
|
152
|
+
if (typeof rating !== "number") return "\u2014";
|
|
153
|
+
if (rating <= 1) return "Low";
|
|
154
|
+
if (rating === 2) return "Low+";
|
|
155
|
+
if (rating === 3) return "Med";
|
|
156
|
+
if (rating === 4) return "High";
|
|
157
|
+
if (rating === 5) return "High+";
|
|
158
|
+
return "Max";
|
|
159
|
+
}
|
|
160
|
+
function priceTierRating(tier) {
|
|
161
|
+
return tier.endsWith("+") ? 6 : tier.length;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// models/service-label.ts
|
|
165
|
+
var SERVICE_LABEL = "Service";
|
|
166
|
+
var SERVICE_LABEL_PLURAL = "Services";
|
|
167
|
+
function serviceCountLabel(count) {
|
|
168
|
+
const noun = (count === 1 ? SERVICE_LABEL : SERVICE_LABEL_PLURAL).toLowerCase();
|
|
169
|
+
return `${count} ${noun}`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// models/catalog/types.ts
|
|
173
|
+
var INPUT_MODALITIES = ["text", "image", "audio", "video"];
|
|
174
|
+
var OUTPUT_MODALITIES = [
|
|
175
|
+
"text",
|
|
176
|
+
"image",
|
|
177
|
+
"audio",
|
|
178
|
+
"video",
|
|
179
|
+
"entities",
|
|
180
|
+
"decision"
|
|
181
|
+
];
|
|
182
|
+
|
|
183
|
+
// models/succession.ts
|
|
184
|
+
var MAX_SUCCESSION_HOPS = 8;
|
|
185
|
+
function buildSuccessionIndex(models) {
|
|
186
|
+
return new Map(models.map((m) => [m.id, m]));
|
|
187
|
+
}
|
|
188
|
+
function isSupersedable(node) {
|
|
189
|
+
return node.isDeprecated || node.retiredAt != null;
|
|
190
|
+
}
|
|
191
|
+
var loggedBroken = /* @__PURE__ */ new Set();
|
|
192
|
+
function logBroken(modelId, reason) {
|
|
193
|
+
if (loggedBroken.has(modelId)) return;
|
|
194
|
+
loggedBroken.add(modelId);
|
|
195
|
+
console.warn(`[models/succession] ${modelId}: successor chain broken (${reason}); keeping the original model.`);
|
|
196
|
+
}
|
|
197
|
+
function resolveSuccessor(modelId, index) {
|
|
198
|
+
const start = index.get(modelId);
|
|
199
|
+
if (!start || !isSupersedable(start) || !start.successorId) return modelId;
|
|
200
|
+
const seen = /* @__PURE__ */ new Set([modelId]);
|
|
201
|
+
let current = start;
|
|
202
|
+
for (let hop = 0; hop < MAX_SUCCESSION_HOPS; hop += 1) {
|
|
203
|
+
const nextId = current.successorId;
|
|
204
|
+
if (!nextId) {
|
|
205
|
+
logBroken(modelId, `${current.id} is superseded and names no successor`);
|
|
206
|
+
return modelId;
|
|
207
|
+
}
|
|
208
|
+
if (seen.has(nextId)) {
|
|
209
|
+
logBroken(modelId, `cycle at ${nextId}`);
|
|
210
|
+
return modelId;
|
|
211
|
+
}
|
|
212
|
+
const next = index.get(nextId);
|
|
213
|
+
if (!next) {
|
|
214
|
+
logBroken(modelId, `successor ${nextId} is not in the catalog`);
|
|
215
|
+
return modelId;
|
|
216
|
+
}
|
|
217
|
+
if (!isSupersedable(next)) return next.id;
|
|
218
|
+
seen.add(nextId);
|
|
219
|
+
current = next;
|
|
220
|
+
}
|
|
221
|
+
logBroken(modelId, `more than ${MAX_SUCCESSION_HOPS} hops`);
|
|
222
|
+
return modelId;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// models/fit.ts
|
|
226
|
+
var featuresOf = (c) => {
|
|
227
|
+
const f = c.features;
|
|
228
|
+
if (!f) return [];
|
|
229
|
+
return Array.isArray(f) ? f : f.raw ?? [];
|
|
230
|
+
};
|
|
231
|
+
function seesImages(c) {
|
|
232
|
+
return (c.input ?? []).includes("image") || featuresOf(c).includes("vision");
|
|
233
|
+
}
|
|
234
|
+
function takesInput(c, modality) {
|
|
235
|
+
if (modality === "image") return seesImages(c);
|
|
236
|
+
return (c.input ?? []).includes(modality);
|
|
237
|
+
}
|
|
238
|
+
var MEDIA_GENERATION_FEATURES = /* @__PURE__ */ new Set(["image_generation", "video_generation", "audio_generation", "music_generation"]);
|
|
239
|
+
function isChatModelCapability(c) {
|
|
240
|
+
if (c.interaction !== "turn") return false;
|
|
241
|
+
if (!(c.input ?? []).includes("text")) return false;
|
|
242
|
+
if (!(c.output ?? []).includes("text")) return false;
|
|
243
|
+
return !featuresOf(c).some((f) => MEDIA_GENERATION_FEATURES.has(f));
|
|
244
|
+
}
|
|
245
|
+
|
|
84
246
|
// settings/ui-gates.ts
|
|
85
247
|
var UI_GATE_KEYS = [
|
|
86
248
|
"tools",
|
|
@@ -179,357 +341,2269 @@ function readEffectiveSettings(entry) {
|
|
|
179
341
|
return entry ? mergeEffectiveSettings(entry.defaults, entry.overrides) : EMPTY;
|
|
180
342
|
}
|
|
181
343
|
|
|
182
|
-
// settings/react/
|
|
183
|
-
import {
|
|
344
|
+
// settings/react/ModelSettingsPanel.tsx
|
|
345
|
+
import { Checkbox as Checkbox2 } from "@ai-matrx/design-system";
|
|
346
|
+
import { Button as Button2, Chip, Switch as Switch2 } from "@ai-matrx/design-system/controls";
|
|
347
|
+
|
|
348
|
+
// models/react/context.tsx
|
|
349
|
+
import { createContext, useContext, useEffect, useMemo, useSyncExternalStore } from "react";
|
|
350
|
+
import { jsx } from "react/jsx-runtime";
|
|
351
|
+
var ModelCatalogContext = createContext(null);
|
|
352
|
+
function useBinding(hook) {
|
|
353
|
+
const binding = useContext(ModelCatalogContext);
|
|
354
|
+
if (!binding) {
|
|
355
|
+
throw new Error(`${hook}() needs <ModelCatalogProvider catalog={createModelCatalog(...)} favorites={createModelFavorites(...)}> above it. A picker with no catalog is a lie on screen.`);
|
|
356
|
+
}
|
|
357
|
+
return binding;
|
|
358
|
+
}
|
|
359
|
+
var useModelCatalogUiPorts = () => useBinding("useModelCatalogUiPorts").ports;
|
|
360
|
+
function useModelCatalog(variant) {
|
|
361
|
+
const { catalog } = useBinding("useModelCatalog");
|
|
362
|
+
const state = useSyncExternalStore(catalog.subscribe, catalog.getState, catalog.getState);
|
|
363
|
+
useEffect(() => {
|
|
364
|
+
void catalog.load(variant);
|
|
365
|
+
}, [catalog, variant]);
|
|
366
|
+
const v = state[variant];
|
|
367
|
+
const loading = v.status === "idle" || v.status === "loading";
|
|
368
|
+
return {
|
|
369
|
+
models: loading ? [] : v.models,
|
|
370
|
+
isLoading: loading,
|
|
371
|
+
error: loading ? null : v.error,
|
|
372
|
+
reload: () => {
|
|
373
|
+
void catalog.reload(variant);
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
function useModelFavorites(active) {
|
|
378
|
+
const { favorites } = useBinding("useModelFavorites");
|
|
379
|
+
const state = useSyncExternalStore(favorites.subscribe, favorites.getState, favorites.getState);
|
|
380
|
+
useEffect(() => {
|
|
381
|
+
void favorites.reconcile();
|
|
382
|
+
}, [favorites, active]);
|
|
383
|
+
const favoriteSet = useMemo(() => new Set(state.favoriteIds), [state.favoriteIds]);
|
|
384
|
+
return { favoriteIds: state.favoriteIds, favoriteSet, toggleFavorite: favorites.toggle };
|
|
385
|
+
}
|
|
386
|
+
var NO_LOCAL_MODELS = [];
|
|
387
|
+
var noopSubscribe = () => () => {
|
|
388
|
+
};
|
|
389
|
+
function useLocalModels(override) {
|
|
390
|
+
const contextPort = useBinding("useLocalModels").ports.localModels;
|
|
391
|
+
const port = override ?? contextPort;
|
|
392
|
+
const models = useSyncExternalStore(
|
|
393
|
+
port ? port.subscribe : noopSubscribe,
|
|
394
|
+
port ? port.getModels : () => NO_LOCAL_MODELS,
|
|
395
|
+
port ? port.getModels : () => NO_LOCAL_MODELS
|
|
396
|
+
);
|
|
397
|
+
return { models, groupLabel: port?.groupLabel ?? "On this computer", open: port?.open ? (id) => port.open?.(id) : void 0 };
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// models/react/ModelListDropdown.tsx
|
|
401
|
+
import { formatCount } from "@ai-matrx/kit/format";
|
|
402
|
+
import { useEffect as useEffect2, useMemo as useMemo2, useRef, useState } from "react";
|
|
184
403
|
import {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
SelectContent,
|
|
190
|
-
SelectItem,
|
|
191
|
-
SelectTrigger,
|
|
192
|
-
SelectValue,
|
|
193
|
-
Slider,
|
|
194
|
-
Textarea,
|
|
404
|
+
cn,
|
|
405
|
+
Popover,
|
|
406
|
+
PopoverTrigger,
|
|
407
|
+
PopoverContent,
|
|
195
408
|
Tooltip,
|
|
196
409
|
TooltipContent,
|
|
197
410
|
TooltipProvider,
|
|
198
|
-
TooltipTrigger
|
|
411
|
+
TooltipTrigger,
|
|
412
|
+
selectTriggerVariants,
|
|
413
|
+
Drawer,
|
|
414
|
+
DrawerTrigger,
|
|
415
|
+
DrawerContent,
|
|
416
|
+
DrawerTitle,
|
|
417
|
+
useDialogContainer,
|
|
418
|
+
useIsMobile
|
|
199
419
|
} from "@ai-matrx/design-system";
|
|
200
|
-
import {
|
|
420
|
+
import { Input } from "@ai-matrx/design-system/controls";
|
|
421
|
+
import { MakerBrandGlyph, ServiceBrandGlyph } from "@ai-matrx/icons/brand-glyphs";
|
|
201
422
|
|
|
202
|
-
//
|
|
203
|
-
var
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
423
|
+
// catalog/shared/icon-paths.ts
|
|
424
|
+
var SHAPES = {
|
|
425
|
+
star: {
|
|
426
|
+
paths: [
|
|
427
|
+
"M11.5 3.2a.6.6 0 0 1 1 0l2.3 4.7 5.2.8a.6.6 0 0 1 .3 1l-3.8 3.7.9 5.2a.6.6 0 0 1-.9.6L12 16.8l-4.6 2.4a.6.6 0 0 1-.9-.6l.9-5.2-3.8-3.7a.6.6 0 0 1 .3-1l5.2-.8Z"
|
|
428
|
+
],
|
|
429
|
+
fillable: true
|
|
430
|
+
},
|
|
431
|
+
chevronRight: { paths: ["m9 18 6-6-6-6"] },
|
|
432
|
+
chevronDown: { paths: ["m6 9 6 6 6-6"] },
|
|
433
|
+
search: {
|
|
434
|
+
paths: ["m21 21-4.3-4.3"],
|
|
435
|
+
circles: [{ cx: 11, cy: 11, r: 8 }]
|
|
436
|
+
},
|
|
437
|
+
x: { paths: ["M18 6 6 18", "m6 6 12 12"] },
|
|
438
|
+
check: { paths: ["M20 6 9 17l-5-5"] },
|
|
439
|
+
arrowUpDown: {
|
|
440
|
+
paths: ["m21 16-4 4-4-4", "M17 20V4", "m3 8 4-4 4 4", "M7 4v16"]
|
|
441
|
+
},
|
|
442
|
+
folder: {
|
|
443
|
+
paths: [
|
|
444
|
+
"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
|
|
445
|
+
]
|
|
446
|
+
},
|
|
447
|
+
tag: {
|
|
448
|
+
paths: [
|
|
449
|
+
"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z"
|
|
450
|
+
],
|
|
451
|
+
circles: [{ cx: 7.5, cy: 7.5, r: 0.5, filled: true }]
|
|
452
|
+
},
|
|
453
|
+
rotateCcw: {
|
|
454
|
+
paths: [
|
|
455
|
+
"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",
|
|
456
|
+
"M3 3v5h5"
|
|
457
|
+
]
|
|
458
|
+
},
|
|
459
|
+
loader: { paths: ["M21 12a9 9 0 1 1-6.219-8.56"] },
|
|
460
|
+
alertTriangle: {
|
|
461
|
+
paths: [
|
|
462
|
+
"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",
|
|
463
|
+
"M12 9v4",
|
|
464
|
+
"M12 17h.01"
|
|
465
|
+
]
|
|
466
|
+
},
|
|
467
|
+
/**
|
|
468
|
+
* The Orchestra marker (Lucide `music-4`): the glyph the Workflow Studio's
|
|
469
|
+
* picker used for a conductor, kept identical so the same agent wears the
|
|
470
|
+
* same mark in every client.
|
|
471
|
+
*/
|
|
472
|
+
music4: {
|
|
473
|
+
paths: ["M9 18V5l12-2v13", "m9 9 12-2"],
|
|
474
|
+
circles: [
|
|
475
|
+
{ cx: 6, cy: 18, r: 3 },
|
|
476
|
+
{ cx: 18, cy: 16, r: 3 }
|
|
477
|
+
]
|
|
478
|
+
},
|
|
479
|
+
clock: {
|
|
480
|
+
paths: ["M12 6v6l4 2"],
|
|
481
|
+
circles: [{ cx: 12, cy: 12, r: 10 }]
|
|
482
|
+
},
|
|
483
|
+
globe: {
|
|
484
|
+
paths: ["M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20", "M2 12h20"],
|
|
485
|
+
circles: [{ cx: 12, cy: 12, r: 10 }]
|
|
486
|
+
},
|
|
487
|
+
users: {
|
|
488
|
+
paths: [
|
|
489
|
+
"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",
|
|
490
|
+
"M22 21v-2a4 4 0 0 0-3-3.87",
|
|
491
|
+
"M16 3.13a4 4 0 0 1 0 7.75"
|
|
492
|
+
],
|
|
493
|
+
circles: [{ cx: 9, cy: 7, r: 4 }]
|
|
494
|
+
},
|
|
495
|
+
externalLink: {
|
|
496
|
+
paths: [
|
|
497
|
+
"M15 3h6v6",
|
|
498
|
+
"M10 14 21 3",
|
|
499
|
+
"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"
|
|
500
|
+
]
|
|
501
|
+
},
|
|
502
|
+
messageCircle: { paths: ["M7.9 20A9 9 0 1 0 4 16.1L2 22Z"] },
|
|
503
|
+
rocket: {
|
|
504
|
+
paths: [
|
|
505
|
+
"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91 0",
|
|
506
|
+
"m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2",
|
|
507
|
+
"M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0",
|
|
508
|
+
"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"
|
|
509
|
+
]
|
|
510
|
+
},
|
|
511
|
+
/**
|
|
512
|
+
* THE ARCHIVE GLYPH (Lucide `archive`) — the ONE mark of the platform
|
|
513
|
+
* archive filter, drawn identically in every Matrx client so the control a
|
|
514
|
+
* person learns on one surface is recognizable on all of them.
|
|
515
|
+
*/
|
|
516
|
+
archive: {
|
|
517
|
+
paths: [
|
|
518
|
+
"M3 3h18a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z",
|
|
519
|
+
"M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8",
|
|
520
|
+
"M10 12h4"
|
|
521
|
+
]
|
|
522
|
+
},
|
|
523
|
+
circleCheck: {
|
|
524
|
+
paths: ["m9 12 2 2 4-4"],
|
|
525
|
+
circles: [{ cx: 12, cy: 12, r: 10 }]
|
|
208
526
|
}
|
|
209
|
-
|
|
527
|
+
};
|
|
528
|
+
var ICON_PATHS = SHAPES;
|
|
529
|
+
var ICON_NAMES = Object.keys(ICON_PATHS);
|
|
530
|
+
|
|
531
|
+
// catalog/react/icons.tsx
|
|
532
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
533
|
+
function Svg({ children, ...props }) {
|
|
534
|
+
return /* @__PURE__ */ jsx2(
|
|
535
|
+
"svg",
|
|
536
|
+
{
|
|
537
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
538
|
+
viewBox: "0 0 24 24",
|
|
539
|
+
fill: "none",
|
|
540
|
+
stroke: "currentColor",
|
|
541
|
+
strokeWidth: 2,
|
|
542
|
+
strokeLinecap: "round",
|
|
543
|
+
strokeLinejoin: "round",
|
|
544
|
+
"aria-hidden": "true",
|
|
545
|
+
...props,
|
|
546
|
+
children
|
|
547
|
+
}
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
function Shape({ name, filled }) {
|
|
551
|
+
const shape = ICON_PATHS[name];
|
|
552
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
553
|
+
shape.paths.map((d, index) => /* @__PURE__ */ jsx2(
|
|
554
|
+
"path",
|
|
555
|
+
{
|
|
556
|
+
d,
|
|
557
|
+
...filled && shape.fillable ? { fill: "currentColor" } : {}
|
|
558
|
+
},
|
|
559
|
+
`p${index}`
|
|
560
|
+
)),
|
|
561
|
+
(shape.circles ?? []).map((circle, index) => /* @__PURE__ */ jsx2(
|
|
562
|
+
"circle",
|
|
563
|
+
{
|
|
564
|
+
cx: circle.cx,
|
|
565
|
+
cy: circle.cy,
|
|
566
|
+
r: circle.r,
|
|
567
|
+
...circle.filled ? { fill: "currentColor" } : {}
|
|
568
|
+
},
|
|
569
|
+
`c${index}`
|
|
570
|
+
))
|
|
571
|
+
] });
|
|
572
|
+
}
|
|
573
|
+
function makeIcon(name) {
|
|
574
|
+
return function Icon(props) {
|
|
575
|
+
return /* @__PURE__ */ jsx2(Svg, { ...props, children: /* @__PURE__ */ jsx2(Shape, { name, filled: false }) });
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
var ArrowUpDownIcon = makeIcon("arrowUpDown");
|
|
579
|
+
var FolderIcon = makeIcon("folder");
|
|
580
|
+
var TagIcon = makeIcon("tag");
|
|
581
|
+
var RotateCcwIcon = makeIcon("rotateCcw");
|
|
582
|
+
var LoaderIcon = makeIcon("loader");
|
|
583
|
+
var UsersIcon = makeIcon("users");
|
|
584
|
+
var MessageCircleIcon = makeIcon("messageCircle");
|
|
585
|
+
var RocketIcon = makeIcon("rocket");
|
|
586
|
+
var CircleCheckIcon = makeIcon("circleCheck");
|
|
587
|
+
var AlertTriangleIcon = makeIcon("alertTriangle");
|
|
588
|
+
var Music4Icon = makeIcon("music4");
|
|
589
|
+
function MousePointerClickIcon(props) {
|
|
590
|
+
return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
|
|
591
|
+
/* @__PURE__ */ jsx2("path", { d: "M14 4.1 12 6" }),
|
|
592
|
+
/* @__PURE__ */ jsx2("path", { d: "m5.1 8-2.9-.8" }),
|
|
593
|
+
/* @__PURE__ */ jsx2("path", { d: "m6 12-1.9 2" }),
|
|
594
|
+
/* @__PURE__ */ jsx2("path", { d: "M7.2 2.2 8 5.1" }),
|
|
595
|
+
/* @__PURE__ */ jsx2("path", { d: "M9.037 9.69a.498.498 0 0 1 .653-.653l11 4.5a.5.5 0 0 1-.074.949l-4.349 1.041a1 1 0 0 0-.74.739l-1.04 4.35a.5.5 0 0 1-.95.074z" })
|
|
596
|
+
] });
|
|
210
597
|
}
|
|
211
598
|
|
|
212
|
-
//
|
|
213
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
599
|
+
// models/react/icons.tsx
|
|
600
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
601
|
+
function Svg2({ children, ...props }) {
|
|
602
|
+
return /* @__PURE__ */ jsx3(
|
|
603
|
+
"svg",
|
|
604
|
+
{
|
|
605
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
606
|
+
viewBox: "0 0 24 24",
|
|
607
|
+
fill: "none",
|
|
608
|
+
stroke: "currentColor",
|
|
609
|
+
strokeWidth: 2,
|
|
610
|
+
strokeLinecap: "round",
|
|
611
|
+
strokeLinejoin: "round",
|
|
612
|
+
"aria-hidden": "true",
|
|
613
|
+
...props,
|
|
614
|
+
children
|
|
615
|
+
}
|
|
616
|
+
);
|
|
219
617
|
}
|
|
220
|
-
function
|
|
221
|
-
return /* @__PURE__ */
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
618
|
+
function ShieldIcon(props) {
|
|
619
|
+
return /* @__PURE__ */ jsx3(Svg2, { ...props, children: /* @__PURE__ */ jsx3("path", { d: "M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" }) });
|
|
620
|
+
}
|
|
621
|
+
function SlidersHorizontalIcon(props) {
|
|
622
|
+
return /* @__PURE__ */ jsxs2(Svg2, { ...props, children: [
|
|
623
|
+
/* @__PURE__ */ jsx3("path", { d: "M10 5H3" }),
|
|
624
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 19H3" }),
|
|
625
|
+
/* @__PURE__ */ jsx3("path", { d: "M14 3v4" }),
|
|
626
|
+
/* @__PURE__ */ jsx3("path", { d: "M16 17v4" }),
|
|
627
|
+
/* @__PURE__ */ jsx3("path", { d: "M21 12h-9" }),
|
|
628
|
+
/* @__PURE__ */ jsx3("path", { d: "M21 19h-5" }),
|
|
629
|
+
/* @__PURE__ */ jsx3("path", { d: "M21 5h-7" }),
|
|
630
|
+
/* @__PURE__ */ jsx3("path", { d: "M8 10v4" }),
|
|
631
|
+
/* @__PURE__ */ jsx3("path", { d: "M8 12H3" })
|
|
225
632
|
] });
|
|
226
633
|
}
|
|
227
|
-
function
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
634
|
+
function TypeIcon(props) {
|
|
635
|
+
return /* @__PURE__ */ jsxs2(Svg2, { ...props, children: [
|
|
636
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 4v16" }),
|
|
637
|
+
/* @__PURE__ */ jsx3("path", { d: "M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2" }),
|
|
638
|
+
/* @__PURE__ */ jsx3("path", { d: "M9 20h6" })
|
|
639
|
+
] });
|
|
232
640
|
}
|
|
233
|
-
function
|
|
234
|
-
|
|
235
|
-
|
|
641
|
+
function ImageIcon(props) {
|
|
642
|
+
return /* @__PURE__ */ jsxs2(Svg2, { ...props, children: [
|
|
643
|
+
/* @__PURE__ */ jsx3("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
|
|
644
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "9", r: "2" }),
|
|
645
|
+
/* @__PURE__ */ jsx3("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
|
|
646
|
+
] });
|
|
647
|
+
}
|
|
648
|
+
function AudioLinesIcon(props) {
|
|
649
|
+
return /* @__PURE__ */ jsxs2(Svg2, { ...props, children: [
|
|
650
|
+
/* @__PURE__ */ jsx3("path", { d: "M2 10v3" }),
|
|
651
|
+
/* @__PURE__ */ jsx3("path", { d: "M6 6v11" }),
|
|
652
|
+
/* @__PURE__ */ jsx3("path", { d: "M10 3v18" }),
|
|
653
|
+
/* @__PURE__ */ jsx3("path", { d: "M14 8v7" }),
|
|
654
|
+
/* @__PURE__ */ jsx3("path", { d: "M18 5v13" }),
|
|
655
|
+
/* @__PURE__ */ jsx3("path", { d: "M22 10v3" })
|
|
656
|
+
] });
|
|
657
|
+
}
|
|
658
|
+
function BoxesIcon(props) {
|
|
659
|
+
return /* @__PURE__ */ jsxs2(Svg2, { ...props, children: [
|
|
660
|
+
/* @__PURE__ */ jsx3("path", { d: "M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z" }),
|
|
661
|
+
/* @__PURE__ */ jsx3("path", { d: "m7 16.5-4.74-2.85" }),
|
|
662
|
+
/* @__PURE__ */ jsx3("path", { d: "m7 16.5 5-3" }),
|
|
663
|
+
/* @__PURE__ */ jsx3("path", { d: "M7 16.5v5.17" }),
|
|
664
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z" }),
|
|
665
|
+
/* @__PURE__ */ jsx3("path", { d: "m17 16.5-5-3" }),
|
|
666
|
+
/* @__PURE__ */ jsx3("path", { d: "m17 16.5 4.74-2.85" }),
|
|
667
|
+
/* @__PURE__ */ jsx3("path", { d: "M17 16.5v5.17" }),
|
|
668
|
+
/* @__PURE__ */ jsx3("path", { d: "M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z" }),
|
|
669
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 8 7.26 5.15" }),
|
|
670
|
+
/* @__PURE__ */ jsx3("path", { d: "m12 8 4.74-2.85" }),
|
|
671
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 13.5V8" })
|
|
672
|
+
] });
|
|
673
|
+
}
|
|
674
|
+
function FileTextIcon(props) {
|
|
675
|
+
return /* @__PURE__ */ jsxs2(Svg2, { ...props, children: [
|
|
676
|
+
/* @__PURE__ */ jsx3("path", { d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z" }),
|
|
677
|
+
/* @__PURE__ */ jsx3("path", { d: "M14 2v5a1 1 0 0 0 1 1h5" }),
|
|
678
|
+
/* @__PURE__ */ jsx3("path", { d: "M10 9H8" }),
|
|
679
|
+
/* @__PURE__ */ jsx3("path", { d: "M16 13H8" }),
|
|
680
|
+
/* @__PURE__ */ jsx3("path", { d: "M16 17H8" })
|
|
681
|
+
] });
|
|
682
|
+
}
|
|
683
|
+
function LayersIcon(props) {
|
|
684
|
+
return /* @__PURE__ */ jsxs2(Svg2, { ...props, children: [
|
|
685
|
+
/* @__PURE__ */ jsx3("path", { d: "M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z" }),
|
|
686
|
+
/* @__PURE__ */ jsx3("path", { d: "M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12" }),
|
|
687
|
+
/* @__PURE__ */ jsx3("path", { d: "M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17" })
|
|
688
|
+
] });
|
|
689
|
+
}
|
|
690
|
+
function ScaleIcon(props) {
|
|
691
|
+
return /* @__PURE__ */ jsxs2(Svg2, { ...props, children: [
|
|
692
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 3v18" }),
|
|
693
|
+
/* @__PURE__ */ jsx3("path", { d: "m19 8 3 8a5 5 0 0 1-6 0zV7" }),
|
|
694
|
+
/* @__PURE__ */ jsx3("path", { d: "M3 7h1a17 17 0 0 0 8-2 17 17 0 0 0 8 2h1" }),
|
|
695
|
+
/* @__PURE__ */ jsx3("path", { d: "m5 8 3 8a5 5 0 0 1-6 0zV7" }),
|
|
696
|
+
/* @__PURE__ */ jsx3("path", { d: "M7 21h10" })
|
|
697
|
+
] });
|
|
698
|
+
}
|
|
699
|
+
function LanguagesIcon(props) {
|
|
700
|
+
return /* @__PURE__ */ jsxs2(Svg2, { ...props, children: [
|
|
701
|
+
/* @__PURE__ */ jsx3("path", { d: "m5 8 6 6" }),
|
|
702
|
+
/* @__PURE__ */ jsx3("path", { d: "m4 14 6-6 2-3" }),
|
|
703
|
+
/* @__PURE__ */ jsx3("path", { d: "M2 5h12" }),
|
|
704
|
+
/* @__PURE__ */ jsx3("path", { d: "M7 2h1" }),
|
|
705
|
+
/* @__PURE__ */ jsx3("path", { d: "m22 22-5-10-5 10" }),
|
|
706
|
+
/* @__PURE__ */ jsx3("path", { d: "M14 18h6" })
|
|
707
|
+
] });
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// models/react/ModelListDropdown.tsx
|
|
711
|
+
import { ChevronDownIcon, ChevronRightIcon, SearchIcon, StarIcon, VideoIcon } from "@ai-matrx/design-system/icons";
|
|
712
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
713
|
+
var PANEL_HEIGHT = 640;
|
|
714
|
+
var LIST_MAX_HEIGHT = `min(${PANEL_HEIGHT}px, var(--radix-popper-available-height, 70dvh))`;
|
|
715
|
+
var LIST_WIDTH = 520;
|
|
716
|
+
var DETAIL_WIDTH = 540;
|
|
717
|
+
var INLINE_LIST_MIN_WIDTH = 400;
|
|
718
|
+
var INLINE_DETAIL_MIN_WIDTH = 280;
|
|
719
|
+
var ADMIN_PANEL_WIDTH = 400;
|
|
720
|
+
var ADMIN_ONLY_SORTS = /* @__PURE__ */ new Set([
|
|
721
|
+
"vendor",
|
|
722
|
+
"api",
|
|
723
|
+
"deprecated",
|
|
724
|
+
"availability",
|
|
725
|
+
"premium"
|
|
726
|
+
]);
|
|
727
|
+
var MODALITY_ICON = {
|
|
728
|
+
text: TypeIcon,
|
|
729
|
+
image: ImageIcon,
|
|
730
|
+
audio: AudioLinesIcon,
|
|
731
|
+
video: VideoIcon,
|
|
732
|
+
document: FileTextIcon,
|
|
733
|
+
entities: BoxesIcon,
|
|
734
|
+
embedding: LayersIcon,
|
|
735
|
+
decision: ScaleIcon
|
|
736
|
+
};
|
|
737
|
+
var INTERACTION_LABEL = {
|
|
738
|
+
turn: "Standard",
|
|
739
|
+
single: "Single-shot",
|
|
740
|
+
extraction: "Extraction",
|
|
741
|
+
realtime: "Realtime",
|
|
742
|
+
embedding: "Embedding",
|
|
743
|
+
agent: "Background agent",
|
|
744
|
+
decision: "Decision",
|
|
745
|
+
adapter: "Adapter",
|
|
746
|
+
detection: "Detector"
|
|
747
|
+
};
|
|
748
|
+
function SpeedDots({ value }) {
|
|
749
|
+
const label = speedRatingLabel(value);
|
|
750
|
+
return /* @__PURE__ */ jsxs3(
|
|
751
|
+
"span",
|
|
752
|
+
{
|
|
753
|
+
className: "inline-flex items-center gap-1",
|
|
754
|
+
title: label == null ? "No speed rating yet" : `Speed ${label}/5`,
|
|
755
|
+
children: [
|
|
756
|
+
/* @__PURE__ */ jsx4("span", { className: "text-[11px] font-medium tabular-nums text-foreground/80", children: speedRatingWord(value) }),
|
|
757
|
+
/* @__PURE__ */ jsxs3("span", { className: "inline-flex items-center gap-0.5", children: [
|
|
758
|
+
[0, 1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx4(
|
|
759
|
+
"span",
|
|
760
|
+
{
|
|
761
|
+
className: cn(
|
|
762
|
+
"h-1.5 w-1.5 rounded-full",
|
|
763
|
+
value != null && i < value ? "bg-foreground/70" : "bg-muted-foreground/25"
|
|
764
|
+
)
|
|
765
|
+
},
|
|
766
|
+
i
|
|
767
|
+
)),
|
|
768
|
+
value != null && value >= 6 && /* @__PURE__ */ jsx4("span", { className: "text-[9px] leading-none text-amber-500", children: "+" })
|
|
769
|
+
] })
|
|
770
|
+
]
|
|
771
|
+
}
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
function SpeedCell({ value }) {
|
|
775
|
+
const word = speedRatingWord(value);
|
|
776
|
+
const label = speedRatingLabel(value);
|
|
777
|
+
return /* @__PURE__ */ jsx4(
|
|
778
|
+
DelayedHint,
|
|
779
|
+
{
|
|
780
|
+
label: label == null ? "No speed rating yet" : `Speed ${word} (${label}/5)`,
|
|
781
|
+
children: /* @__PURE__ */ jsx4("span", { className: "inline-block w-11 text-right text-[11px] font-medium tabular-nums text-foreground/80", children: word })
|
|
782
|
+
}
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
function CostTier({ tier }) {
|
|
786
|
+
if (!tier)
|
|
787
|
+
return /* @__PURE__ */ jsx4("span", { className: "text-[11px] text-muted-foreground/50", children: "\u2014" });
|
|
788
|
+
const rating = priceTierRating(tier);
|
|
789
|
+
const word = costRatingWord(rating);
|
|
790
|
+
return /* @__PURE__ */ jsx4(
|
|
791
|
+
DelayedHint,
|
|
792
|
+
{
|
|
793
|
+
label: `Relative cost ${word} (${rating >= 6 ? "5+" : rating}/5 compared with other models)`,
|
|
794
|
+
children: /* @__PURE__ */ jsx4("span", { className: "inline-block w-11 text-right text-[11px] font-medium tabular-nums text-foreground/80", children: word })
|
|
795
|
+
}
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
function ModalityIcons({ list }) {
|
|
799
|
+
if (list.length === 0)
|
|
800
|
+
return /* @__PURE__ */ jsx4("span", { className: "text-[11px] text-muted-foreground/50", children: "\u2014" });
|
|
801
|
+
return /* @__PURE__ */ jsx4("span", { className: "inline-flex flex-nowrap items-center gap-1 whitespace-nowrap", children: list.map((m) => {
|
|
802
|
+
const Icon = MODALITY_ICON[m];
|
|
803
|
+
return /* @__PURE__ */ jsxs3(
|
|
804
|
+
"span",
|
|
805
|
+
{
|
|
806
|
+
className: "inline-flex shrink-0 items-center gap-0.5 text-xs text-foreground/70",
|
|
807
|
+
title: m,
|
|
808
|
+
children: [
|
|
809
|
+
/* @__PURE__ */ jsx4(Icon, { className: "h-3 w-3" }),
|
|
810
|
+
/* @__PURE__ */ jsx4("span", { className: "capitalize", children: m })
|
|
811
|
+
]
|
|
812
|
+
},
|
|
813
|
+
m
|
|
814
|
+
);
|
|
815
|
+
}) });
|
|
816
|
+
}
|
|
817
|
+
function AdminRow({
|
|
818
|
+
label,
|
|
236
819
|
value,
|
|
237
|
-
|
|
238
|
-
disabled = false,
|
|
239
|
-
id
|
|
820
|
+
mono
|
|
240
821
|
}) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const isValueMismatch = stringValue !== "" && !control.enum.includes(stringValue);
|
|
246
|
-
const emit = (v) => onChange(settingKey === "response_format" ? { type: v } : v);
|
|
247
|
-
const choice = choiceFor(control.enum);
|
|
248
|
-
const picker = choice === "aspect-ratio" ? /* @__PURE__ */ jsx(
|
|
249
|
-
AspectRatioSelect,
|
|
250
|
-
{
|
|
251
|
-
value: isValueMismatch ? "" : stringValue,
|
|
252
|
-
onChange: emit,
|
|
253
|
-
options: control.enum,
|
|
254
|
-
variant: "inline",
|
|
255
|
-
disabled,
|
|
256
|
-
id: inputId,
|
|
257
|
-
placeholder: "Default"
|
|
258
|
-
}
|
|
259
|
-
) : choice === "searchable" ? /* @__PURE__ */ jsx(
|
|
260
|
-
OptionCombobox,
|
|
822
|
+
return /* @__PURE__ */ jsxs3("div", { className: "flex items-baseline gap-2 whitespace-nowrap", children: [
|
|
823
|
+
/* @__PURE__ */ jsx4("span", { className: "w-[76px] shrink-0 text-[10px] uppercase tracking-wide text-muted-foreground", children: label }),
|
|
824
|
+
/* @__PURE__ */ jsx4(
|
|
825
|
+
"span",
|
|
261
826
|
{
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
placeholder: "Default"
|
|
827
|
+
className: cn(
|
|
828
|
+
"min-w-0 truncate text-[11px] text-foreground/90",
|
|
829
|
+
mono && "font-mono"
|
|
830
|
+
),
|
|
831
|
+
title: value ?? void 0,
|
|
832
|
+
children: value ?? "\u2014"
|
|
269
833
|
}
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
834
|
+
)
|
|
835
|
+
] });
|
|
836
|
+
}
|
|
837
|
+
function fmtUsd(n) {
|
|
838
|
+
return n == null ? "\u2014" : `$${n}`;
|
|
839
|
+
}
|
|
840
|
+
function fmtPoints(n) {
|
|
841
|
+
return n == null ? "\u2014" : n.toLocaleString();
|
|
842
|
+
}
|
|
843
|
+
function fmtPointsCompact(n) {
|
|
844
|
+
return formatCount(n, { style: "compact" });
|
|
845
|
+
}
|
|
846
|
+
function AdminOfferingBlock({
|
|
847
|
+
offering,
|
|
848
|
+
index,
|
|
849
|
+
total
|
|
850
|
+
}) {
|
|
851
|
+
const unit = offering.usageBasis ? `/ ${offering.usageBasis}` : "/ 1M tokens";
|
|
852
|
+
return /* @__PURE__ */ jsxs3("div", { className: "rounded-md border border-border p-2", children: [
|
|
853
|
+
/* @__PURE__ */ jsxs3("div", { className: "mb-1.5 flex items-center justify-between gap-2", children: [
|
|
854
|
+
/* @__PURE__ */ jsxs3("span", { className: "truncate text-[11px] font-semibold text-foreground", children: [
|
|
855
|
+
"Offering ",
|
|
856
|
+
index + 1,
|
|
857
|
+
" of ",
|
|
858
|
+
total,
|
|
859
|
+
index === 0 ? " \u2014 preferred" : ""
|
|
860
|
+
] }),
|
|
861
|
+
/* @__PURE__ */ jsx4(
|
|
862
|
+
"span",
|
|
274
863
|
{
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
option
|
|
295
|
-
)) })
|
|
296
|
-
]
|
|
864
|
+
className: cn(
|
|
865
|
+
"shrink-0 rounded px-1.5 py-0.5 text-[9px] font-medium",
|
|
866
|
+
offering.isAvailable ? "bg-primary/10 text-foreground/80" : "bg-destructive/15 text-destructive-ink"
|
|
867
|
+
),
|
|
868
|
+
children: offering.isAvailable ? "Available" : "Unavailable"
|
|
869
|
+
}
|
|
870
|
+
)
|
|
871
|
+
] }),
|
|
872
|
+
/* @__PURE__ */ jsxs3("div", { className: "space-y-0.5", children: [
|
|
873
|
+
/* @__PURE__ */ jsx4(AdminRow, { label: "Model", value: offering.providerModelId, mono: true }),
|
|
874
|
+
/* @__PURE__ */ jsx4(AdminRow, { label: "Vendor", value: offering.vendor, mono: true }),
|
|
875
|
+
/* @__PURE__ */ jsx4(AdminRow, { label: "API", value: offering.apiName, mono: true }),
|
|
876
|
+
/* @__PURE__ */ jsx4(AdminRow, { label: "Translator", value: offering.translatorKey, mono: true }),
|
|
877
|
+
/* @__PURE__ */ jsx4(AdminRow, { label: "Transport", value: offering.transport, mono: true }),
|
|
878
|
+
/* @__PURE__ */ jsx4(
|
|
879
|
+
AdminRow,
|
|
880
|
+
{
|
|
881
|
+
label: "Endpoint",
|
|
882
|
+
value: offering.endpointDisplayName || offering.endpointInternalName ? `${offering.endpointDisplayName ?? "\u2014"} (${offering.endpointInternalName ?? "\u2014"})` : null
|
|
297
883
|
}
|
|
298
884
|
),
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
'"',
|
|
303
|
-
stringValue,
|
|
304
|
-
'" is not a recognized option for this model'
|
|
305
|
-
] })
|
|
306
|
-
] }) })
|
|
307
|
-
] });
|
|
308
|
-
}
|
|
309
|
-
if (control.type === "boolean") {
|
|
310
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
311
|
-
/* @__PURE__ */ jsx(
|
|
312
|
-
Checkbox,
|
|
885
|
+
/* @__PURE__ */ jsx4(AdminRow, { label: "Priority", value: String(offering.priority), mono: true }),
|
|
886
|
+
/* @__PURE__ */ jsx4(
|
|
887
|
+
AdminRow,
|
|
313
888
|
{
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
disabled,
|
|
318
|
-
className: "cursor-pointer"
|
|
889
|
+
label: "Points in",
|
|
890
|
+
value: offering.pointsInput == null ? null : `${fmtPoints(offering.pointsInput)} / 1M`,
|
|
891
|
+
mono: true
|
|
319
892
|
}
|
|
320
893
|
),
|
|
321
|
-
/* @__PURE__ */
|
|
322
|
-
|
|
894
|
+
/* @__PURE__ */ jsx4(
|
|
895
|
+
AdminRow,
|
|
323
896
|
{
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
897
|
+
label: "Points out",
|
|
898
|
+
value: offering.pointsOutput == null ? null : `${fmtPoints(offering.pointsOutput)} / 1M`,
|
|
899
|
+
mono: true
|
|
327
900
|
}
|
|
328
|
-
)
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
901
|
+
),
|
|
902
|
+
offering.pointsCachedInput != null && /* @__PURE__ */ jsx4(
|
|
903
|
+
AdminRow,
|
|
904
|
+
{
|
|
905
|
+
label: "Points cached",
|
|
906
|
+
value: `${fmtPoints(offering.pointsCachedInput)} / 1M`,
|
|
907
|
+
mono: true
|
|
908
|
+
}
|
|
909
|
+
),
|
|
910
|
+
offering.pricing.length === 0 ? /* @__PURE__ */ jsx4(AdminRow, { label: "Pricing", value: "\u2014 (no pricing rows)" }) : offering.pricing.map((band, i) => /* @__PURE__ */ jsxs3("div", { className: "space-y-0.5", children: [
|
|
911
|
+
band.maxTokens != null && /* @__PURE__ */ jsx4(
|
|
912
|
+
AdminRow,
|
|
913
|
+
{
|
|
914
|
+
label: `Band ${i + 1}`,
|
|
915
|
+
value: `\u2264 ${formatCount(band.maxTokens)} tokens`
|
|
916
|
+
}
|
|
917
|
+
),
|
|
918
|
+
/* @__PURE__ */ jsx4(
|
|
919
|
+
AdminRow,
|
|
920
|
+
{
|
|
921
|
+
label: "Input $",
|
|
922
|
+
value: `${fmtUsd(band.inputPrice)} ${unit}`,
|
|
923
|
+
mono: true
|
|
924
|
+
}
|
|
925
|
+
),
|
|
926
|
+
/* @__PURE__ */ jsx4(
|
|
927
|
+
AdminRow,
|
|
928
|
+
{
|
|
929
|
+
label: "Output $",
|
|
930
|
+
value: `${fmtUsd(band.outputPrice)} ${unit}`,
|
|
931
|
+
mono: true
|
|
932
|
+
}
|
|
933
|
+
),
|
|
934
|
+
/* @__PURE__ */ jsx4(
|
|
935
|
+
AdminRow,
|
|
936
|
+
{
|
|
937
|
+
label: "Cached $",
|
|
938
|
+
value: `${fmtUsd(band.cachedInputPrice)} ${unit}`,
|
|
939
|
+
mono: true
|
|
940
|
+
}
|
|
941
|
+
)
|
|
942
|
+
] }, i)),
|
|
943
|
+
/* @__PURE__ */ jsx4(
|
|
944
|
+
AdminRow,
|
|
945
|
+
{
|
|
946
|
+
label: "Billing",
|
|
947
|
+
value: offering.usageBasis ? `Usage basis: ${offering.usageBasis}` : offering.tokenBilled ? "Token-billed (provider-reported tokens)" : "Standard $ / 1M tokens"
|
|
948
|
+
}
|
|
949
|
+
),
|
|
950
|
+
/* @__PURE__ */ jsx4(AdminRow, { label: "Offering", value: offering.offeringId, mono: true })
|
|
951
|
+
] })
|
|
952
|
+
] });
|
|
953
|
+
}
|
|
954
|
+
function AdminOfferingsSection({ model }) {
|
|
955
|
+
const offerings = model.admin?.offerings ?? [];
|
|
956
|
+
return /* @__PURE__ */ jsxs3("div", { className: "flex h-full flex-col", children: [
|
|
957
|
+
/* @__PURE__ */ jsxs3("div", { className: "shrink-0 border-b border-border px-3 py-2 text-[10px] uppercase tracking-wide text-muted-foreground", children: [
|
|
958
|
+
"Offerings \u2014 real vendor / wire data (",
|
|
959
|
+
offerings.length,
|
|
960
|
+
")"
|
|
961
|
+
] }),
|
|
962
|
+
/* @__PURE__ */ jsx4("div", { className: "min-h-0 flex-1 space-y-2 overflow-y-auto p-2", children: offerings.length === 0 ? /* @__PURE__ */ jsx4("div", { className: "rounded-md border border-destructive/40 bg-destructive/10 p-2 text-[11px] text-destructive-ink", children: "No offerings \u2014 this model is not callable (a model without an `ai.offering` row cannot be routed)." }) : offerings.map((o, i) => /* @__PURE__ */ jsx4(
|
|
963
|
+
AdminOfferingBlock,
|
|
354
964
|
{
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
965
|
+
offering: o,
|
|
966
|
+
index: i,
|
|
967
|
+
total: offerings.length
|
|
968
|
+
},
|
|
969
|
+
o.offeringId
|
|
970
|
+
)) })
|
|
971
|
+
] });
|
|
972
|
+
}
|
|
973
|
+
var SERVICE_CHIP_SELECTED = "rounded border border-primary/40 bg-primary/10 px-1.5 py-0.5 text-[10px] font-medium text-foreground";
|
|
974
|
+
var SERVICE_CHIP_UNSELECTED = "rounded border border-border px-1.5 py-0.5 text-[10px] text-foreground/80";
|
|
975
|
+
function ModelDetailCard({
|
|
976
|
+
model,
|
|
977
|
+
tier,
|
|
978
|
+
variant,
|
|
979
|
+
onSelect,
|
|
980
|
+
isCurrentModel,
|
|
981
|
+
pinnedOfferingId,
|
|
982
|
+
onPinOffering,
|
|
983
|
+
includeAdminSection
|
|
984
|
+
}) {
|
|
985
|
+
const pinnedHere = (t) => !!isCurrentModel && !!pinnedOfferingId && t.offeringId === pinnedOfferingId;
|
|
986
|
+
const anyPinnedHere = model.tiers.some(pinnedHere);
|
|
987
|
+
return /* @__PURE__ */ jsxs3("div", { className: "flex h-full flex-col", children: [
|
|
988
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-h-0 flex-1 overflow-y-auto p-4", children: [
|
|
989
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-start justify-between gap-2", children: [
|
|
990
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0", children: [
|
|
991
|
+
/* @__PURE__ */ jsx4("div", { className: "truncate text-sm font-semibold text-foreground", children: model.name }),
|
|
992
|
+
model.maker && /* @__PURE__ */ jsxs3("div", { className: "mt-0.5 flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
993
|
+
/* @__PURE__ */ jsx4(
|
|
994
|
+
MakerBrandGlyph,
|
|
995
|
+
{
|
|
996
|
+
maker: model.maker,
|
|
997
|
+
colored: true,
|
|
998
|
+
className: "h-3.5 w-3.5"
|
|
999
|
+
}
|
|
1000
|
+
),
|
|
1001
|
+
/* @__PURE__ */ jsx4("span", { children: model.maker })
|
|
1002
|
+
] })
|
|
1003
|
+
] }),
|
|
1004
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex shrink-0 flex-col items-end gap-1", children: [
|
|
1005
|
+
model.isPrimary && /* @__PURE__ */ jsx4("span", { className: "rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-foreground/70", children: "Default" }),
|
|
1006
|
+
model.isPremium && /* @__PURE__ */ jsx4("span", { className: "rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-foreground/70", children: "Premium" }),
|
|
1007
|
+
model.isDeprecated && !model.retiredAt && /* @__PURE__ */ jsx4(
|
|
1008
|
+
"span",
|
|
1009
|
+
{
|
|
1010
|
+
className: "rounded bg-destructive/15 px-1.5 py-0.5 text-[10px] font-medium text-destructive-ink",
|
|
1011
|
+
title: "Still runs normally; hidden from default selection.",
|
|
1012
|
+
children: "Deprecated"
|
|
1013
|
+
}
|
|
1014
|
+
),
|
|
1015
|
+
model.retiredAt && /* @__PURE__ */ jsx4(
|
|
1016
|
+
"span",
|
|
1017
|
+
{
|
|
1018
|
+
className: "rounded bg-destructive/15 px-1.5 py-0.5 text-[10px] font-medium text-destructive-ink",
|
|
1019
|
+
title: `The provider no longer serves this model (retired ${model.retiredAt.slice(0, 10)}). It cannot be selected.`,
|
|
1020
|
+
children: "Retired"
|
|
1021
|
+
}
|
|
1022
|
+
)
|
|
1023
|
+
] })
|
|
1024
|
+
] }),
|
|
1025
|
+
model.description && /* @__PURE__ */ jsx4("p", { className: "mt-2 line-clamp-3 text-xs text-muted-foreground", children: model.description }),
|
|
1026
|
+
/* @__PURE__ */ jsxs3("dl", { className: "mt-3 space-y-2 text-xs", children: [
|
|
1027
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1028
|
+
/* @__PURE__ */ jsx4("dt", { className: "mb-0.5 text-[10px] uppercase tracking-wide text-muted-foreground", children: "Input" }),
|
|
1029
|
+
/* @__PURE__ */ jsx4("dd", { children: /* @__PURE__ */ jsx4(ModalityIcons, { list: model.input }) })
|
|
1030
|
+
] }),
|
|
1031
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1032
|
+
/* @__PURE__ */ jsx4("dt", { className: "mb-0.5 text-[10px] uppercase tracking-wide text-muted-foreground", children: "Output" }),
|
|
1033
|
+
/* @__PURE__ */ jsx4("dd", { children: /* @__PURE__ */ jsx4(ModalityIcons, { list: model.output }) })
|
|
1034
|
+
] }),
|
|
1035
|
+
model.features.buckets.length > 0 && /* @__PURE__ */ jsxs3("div", { children: [
|
|
1036
|
+
/* @__PURE__ */ jsx4("dt", { className: "mb-0.5 text-[10px] uppercase tracking-wide text-muted-foreground", children: "Features" }),
|
|
1037
|
+
/* @__PURE__ */ jsx4("dd", { className: "flex flex-wrap gap-1", children: model.features.buckets.map((b) => /* @__PURE__ */ jsx4(
|
|
1038
|
+
"span",
|
|
1039
|
+
{
|
|
1040
|
+
className: "whitespace-nowrap rounded border border-border px-1.5 py-0.5 text-[10px] text-foreground/80",
|
|
1041
|
+
title: FEATURE_BUCKETS[b].description,
|
|
1042
|
+
children: FEATURE_BUCKETS[b].label
|
|
1043
|
+
},
|
|
1044
|
+
b
|
|
1045
|
+
)) })
|
|
1046
|
+
] }),
|
|
1047
|
+
/* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
1048
|
+
/* @__PURE__ */ jsxs3("div", { className: "col-span-2", children: [
|
|
1049
|
+
/* @__PURE__ */ jsx4("dt", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "Points / 1M tokens" }),
|
|
1050
|
+
/* @__PURE__ */ jsx4(
|
|
1051
|
+
"dd",
|
|
1052
|
+
{
|
|
1053
|
+
className: "whitespace-nowrap text-sm font-semibold tabular-nums text-foreground",
|
|
1054
|
+
title: "Points per 1 million tokens \u2014 what usage actually costs you",
|
|
1055
|
+
children: model.pointsInput == null && model.pointsOutput == null ? "\u2014" : `${fmtPoints(model.pointsInput)} in \xB7 ${fmtPoints(model.pointsOutput)} out`
|
|
1056
|
+
}
|
|
1057
|
+
)
|
|
1058
|
+
] }),
|
|
1059
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1060
|
+
/* @__PURE__ */ jsx4("dt", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "Context window" }),
|
|
1061
|
+
/* @__PURE__ */ jsx4("dd", { className: "tabular-nums text-foreground/80", children: model.contextWindow?.toLocaleString() ?? "\u2014" })
|
|
1062
|
+
] }),
|
|
1063
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1064
|
+
/* @__PURE__ */ jsx4("dt", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "Max output" }),
|
|
1065
|
+
/* @__PURE__ */ jsx4("dd", { className: "tabular-nums text-foreground/80", children: model.maxTokens?.toLocaleString() ?? "\u2014" })
|
|
1066
|
+
] }),
|
|
1067
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1068
|
+
/* @__PURE__ */ jsx4("dt", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "Cost" }),
|
|
1069
|
+
/* @__PURE__ */ jsx4("dd", { children: /* @__PURE__ */ jsx4(CostTier, { tier }) })
|
|
1070
|
+
] }),
|
|
1071
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1072
|
+
/* @__PURE__ */ jsx4("dt", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "Speed" }),
|
|
1073
|
+
/* @__PURE__ */ jsx4("dd", { children: /* @__PURE__ */ jsx4(SpeedDots, { value: model.speedRating }) })
|
|
1074
|
+
] }),
|
|
1075
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1076
|
+
/* @__PURE__ */ jsx4("dt", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "Interaction" }),
|
|
1077
|
+
/* @__PURE__ */ jsx4("dd", { className: "text-foreground/80", children: INTERACTION_LABEL[model.interaction] })
|
|
1078
|
+
] })
|
|
1079
|
+
] }),
|
|
1080
|
+
model.tiers[0]?.servedVia && /* @__PURE__ */ jsxs3("div", { children: [
|
|
1081
|
+
/* @__PURE__ */ jsx4("dt", { className: "mb-0.5 text-[10px] uppercase tracking-wide text-muted-foreground", children: model.tiers.length === 1 ? SERVICE_LABEL : SERVICE_LABEL_PLURAL }),
|
|
1082
|
+
/* @__PURE__ */ jsx4("dd", { className: "flex flex-wrap gap-1", children: onPinOffering ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1083
|
+
/* @__PURE__ */ jsx4(
|
|
1084
|
+
"button",
|
|
1085
|
+
{
|
|
1086
|
+
type: "button",
|
|
1087
|
+
onClick: () => onPinOffering(model, void 0),
|
|
1088
|
+
title: "Auto \u2014 the server picks the preferred Service for each call",
|
|
1089
|
+
className: cn(
|
|
1090
|
+
"transition-colors",
|
|
1091
|
+
!anyPinnedHere ? SERVICE_CHIP_SELECTED : cn(
|
|
1092
|
+
SERVICE_CHIP_UNSELECTED,
|
|
1093
|
+
"hover:bg-muted/60 hover:text-foreground"
|
|
1094
|
+
)
|
|
1095
|
+
),
|
|
1096
|
+
children: "Auto"
|
|
1097
|
+
}
|
|
1098
|
+
),
|
|
1099
|
+
model.tiers.map((t) => {
|
|
1100
|
+
const pinned = pinnedHere(t);
|
|
1101
|
+
return /* @__PURE__ */ jsx4(
|
|
1102
|
+
"button",
|
|
1103
|
+
{
|
|
1104
|
+
type: "button",
|
|
1105
|
+
onClick: () => onPinOffering(
|
|
1106
|
+
model,
|
|
1107
|
+
pinned ? void 0 : t.offeringId
|
|
1108
|
+
),
|
|
1109
|
+
title: pinned ? "Pinned \u2014 every call uses this Service. Click to return to Auto." : `Pin every call to ${t.servedVia}`,
|
|
1110
|
+
className: cn(
|
|
1111
|
+
"transition-colors",
|
|
1112
|
+
pinned ? SERVICE_CHIP_SELECTED : cn(
|
|
1113
|
+
SERVICE_CHIP_UNSELECTED,
|
|
1114
|
+
"hover:bg-muted/60 hover:text-foreground"
|
|
1115
|
+
)
|
|
1116
|
+
),
|
|
1117
|
+
children: t.servedVia
|
|
1118
|
+
},
|
|
1119
|
+
t.offeringId
|
|
1120
|
+
);
|
|
1121
|
+
})
|
|
1122
|
+
] }) : model.tiers.map((t, i) => /* @__PURE__ */ jsx4(
|
|
1123
|
+
"span",
|
|
1124
|
+
{
|
|
1125
|
+
className: i === 0 ? SERVICE_CHIP_SELECTED : SERVICE_CHIP_UNSELECTED,
|
|
1126
|
+
title: i === 0 ? "Default serving tier" : "Also available on this tier",
|
|
1127
|
+
children: t.servedVia
|
|
1128
|
+
},
|
|
1129
|
+
t.offeringId
|
|
1130
|
+
)) })
|
|
1131
|
+
] }),
|
|
1132
|
+
model.multilingual && /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1 text-foreground/80", children: [
|
|
1133
|
+
/* @__PURE__ */ jsx4(LanguagesIcon, { className: "h-3.5 w-3.5" }),
|
|
1134
|
+
/* @__PURE__ */ jsx4("span", { children: "Multilingual" })
|
|
1135
|
+
] }),
|
|
1136
|
+
model.features.raw.length > 0 && /* @__PURE__ */ jsxs3("div", { children: [
|
|
1137
|
+
/* @__PURE__ */ jsx4("dt", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "All capability flags" }),
|
|
1138
|
+
/* @__PURE__ */ jsx4("dd", { className: "font-mono text-[10px] leading-relaxed text-muted-foreground/80", children: model.features.raw.join(", ") })
|
|
1139
|
+
] })
|
|
1140
|
+
] }),
|
|
1141
|
+
includeAdminSection && variant === "admin" && /* @__PURE__ */ jsx4("div", { className: "mt-3 rounded-md border border-border", children: /* @__PURE__ */ jsx4(AdminOfferingsSection, { model }) })
|
|
1142
|
+
] }),
|
|
1143
|
+
/* @__PURE__ */ jsx4("div", { className: "shrink-0 border-t border-border p-3", children: /* @__PURE__ */ jsx4(
|
|
1144
|
+
"button",
|
|
367
1145
|
{
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
1146
|
+
type: "button",
|
|
1147
|
+
onClick: onSelect,
|
|
1148
|
+
className: "w-full rounded-md bg-primary py-1.5 text-xs font-medium text-primary-foreground transition-colors hover:bg-primary/90",
|
|
1149
|
+
children: "Select model"
|
|
372
1150
|
}
|
|
373
|
-
)
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
|
|
1151
|
+
) })
|
|
1152
|
+
] });
|
|
1153
|
+
}
|
|
1154
|
+
var HOVER_DELAY_MS = 400;
|
|
1155
|
+
function DelayedHint({
|
|
1156
|
+
label,
|
|
1157
|
+
children
|
|
1158
|
+
}) {
|
|
1159
|
+
return /* @__PURE__ */ jsxs3(Tooltip, { children: [
|
|
1160
|
+
/* @__PURE__ */ jsx4(TooltipTrigger, { asChild: true, children }),
|
|
1161
|
+
/* @__PURE__ */ jsx4(TooltipContent, { side: "top", sideOffset: 6, className: "max-w-64 text-xs", children: label })
|
|
1162
|
+
] });
|
|
1163
|
+
}
|
|
1164
|
+
function ChipRow({ children }) {
|
|
1165
|
+
return /* @__PURE__ */ jsx4("div", { className: "flex flex-nowrap gap-1 overflow-x-auto pb-0.5", children });
|
|
1166
|
+
}
|
|
1167
|
+
function ChipToggle({
|
|
1168
|
+
active,
|
|
1169
|
+
onClick,
|
|
1170
|
+
children,
|
|
1171
|
+
className
|
|
1172
|
+
}) {
|
|
1173
|
+
return /* @__PURE__ */ jsx4(
|
|
1174
|
+
"button",
|
|
377
1175
|
{
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
1176
|
+
type: "button",
|
|
1177
|
+
onClick,
|
|
1178
|
+
className: cn(
|
|
1179
|
+
"inline-flex shrink-0 items-center rounded-md border px-2 py-0.5 text-[11px] transition-colors",
|
|
1180
|
+
active ? "border-primary bg-primary/10 text-foreground" : "border-border text-muted-foreground hover:text-foreground",
|
|
1181
|
+
className
|
|
1182
|
+
),
|
|
1183
|
+
children
|
|
384
1184
|
}
|
|
385
1185
|
);
|
|
386
1186
|
}
|
|
387
|
-
function
|
|
388
|
-
|
|
1187
|
+
function MakerFilterButton({
|
|
1188
|
+
maker,
|
|
1189
|
+
active,
|
|
1190
|
+
onClick
|
|
1191
|
+
}) {
|
|
1192
|
+
return /* @__PURE__ */ jsxs3(
|
|
1193
|
+
"button",
|
|
1194
|
+
{
|
|
1195
|
+
type: "button",
|
|
1196
|
+
"aria-pressed": active,
|
|
1197
|
+
"aria-label": `Filter by ${maker}`,
|
|
1198
|
+
onClick,
|
|
1199
|
+
className: cn(
|
|
1200
|
+
"flex min-w-0 items-center gap-1.5 rounded-md border px-1.5 py-1 text-left transition-colors",
|
|
1201
|
+
active ? "border-primary bg-primary/10 text-foreground" : "border-border text-muted-foreground hover:text-foreground"
|
|
1202
|
+
),
|
|
1203
|
+
children: [
|
|
1204
|
+
/* @__PURE__ */ jsx4(MakerBrandGlyph, { maker, colored: true, className: "h-4 w-4 shrink-0" }),
|
|
1205
|
+
/* @__PURE__ */ jsx4(DelayedHint, { label: maker, children: /* @__PURE__ */ jsx4("span", { className: "min-w-0 truncate text-[11px] font-medium leading-tight", children: maker }) })
|
|
1206
|
+
]
|
|
1207
|
+
}
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
function ServiceFilterButton({
|
|
1211
|
+
service,
|
|
1212
|
+
active,
|
|
1213
|
+
onClick
|
|
1214
|
+
}) {
|
|
1215
|
+
return /* @__PURE__ */ jsxs3(
|
|
1216
|
+
"button",
|
|
1217
|
+
{
|
|
1218
|
+
type: "button",
|
|
1219
|
+
"aria-pressed": active,
|
|
1220
|
+
"aria-label": `Filter by ${service}`,
|
|
1221
|
+
onClick,
|
|
1222
|
+
className: cn(
|
|
1223
|
+
"flex min-w-0 items-center gap-1.5 rounded-md border px-1.5 py-1 text-left transition-colors",
|
|
1224
|
+
active ? "border-primary bg-primary/10 text-foreground" : "border-border text-muted-foreground hover:text-foreground"
|
|
1225
|
+
),
|
|
1226
|
+
children: [
|
|
1227
|
+
/* @__PURE__ */ jsx4(ServiceBrandGlyph, { service, className: "h-4 w-4 shrink-0" }),
|
|
1228
|
+
/* @__PURE__ */ jsx4(DelayedHint, { label: service, children: /* @__PURE__ */ jsx4("span", { className: "min-w-0 truncate text-[11px] font-medium leading-tight", children: service }) })
|
|
1229
|
+
]
|
|
1230
|
+
}
|
|
1231
|
+
);
|
|
1232
|
+
}
|
|
1233
|
+
function TriStateChips({
|
|
389
1234
|
value,
|
|
390
1235
|
onChange,
|
|
391
|
-
|
|
1236
|
+
yesLabel,
|
|
1237
|
+
noLabel
|
|
392
1238
|
}) {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
1239
|
+
return /* @__PURE__ */ jsx4("div", { className: "flex flex-wrap gap-1", children: [
|
|
1240
|
+
["any", "Any"],
|
|
1241
|
+
["yes", yesLabel],
|
|
1242
|
+
["no", noLabel]
|
|
1243
|
+
].map(([key, label]) => /* @__PURE__ */ jsx4(
|
|
1244
|
+
ChipToggle,
|
|
1245
|
+
{
|
|
1246
|
+
active: value === key,
|
|
1247
|
+
onClick: () => onChange(key),
|
|
1248
|
+
children: label
|
|
1249
|
+
},
|
|
1250
|
+
key
|
|
1251
|
+
)) });
|
|
1252
|
+
}
|
|
1253
|
+
function FilterSection({
|
|
1254
|
+
label,
|
|
1255
|
+
children
|
|
1256
|
+
}) {
|
|
1257
|
+
return /* @__PURE__ */ jsxs3("div", { children: [
|
|
1258
|
+
/* @__PURE__ */ jsx4("div", { className: "mb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: label }),
|
|
1259
|
+
children
|
|
1260
|
+
] });
|
|
1261
|
+
}
|
|
1262
|
+
function FiltersPanel({
|
|
1263
|
+
filters,
|
|
1264
|
+
setFilters,
|
|
1265
|
+
variant,
|
|
1266
|
+
makerOptions,
|
|
1267
|
+
serviceOptions,
|
|
1268
|
+
vendorOptions,
|
|
1269
|
+
apiOptions
|
|
1270
|
+
}) {
|
|
1271
|
+
const toggleModality = (kind, m) => setFilters((f) => {
|
|
1272
|
+
const next = new Set(f[kind]);
|
|
1273
|
+
if (next.has(m)) next.delete(m);
|
|
1274
|
+
else next.add(m);
|
|
1275
|
+
return { ...f, [kind]: next };
|
|
1276
|
+
});
|
|
1277
|
+
const toggleFeature = (b) => setFilters((f) => {
|
|
1278
|
+
const next = new Set(f.features);
|
|
1279
|
+
if (next.has(b)) next.delete(b);
|
|
1280
|
+
else next.add(b);
|
|
1281
|
+
return { ...f, features: next };
|
|
1282
|
+
});
|
|
1283
|
+
const toggleSetValue = (kind, value) => setFilters((f) => {
|
|
1284
|
+
const next = new Set(f[kind]);
|
|
1285
|
+
if (next.has(value)) next.delete(value);
|
|
1286
|
+
else next.add(value);
|
|
1287
|
+
return { ...f, [kind]: next };
|
|
1288
|
+
});
|
|
1289
|
+
const sortOptions = [
|
|
1290
|
+
{ key: "name", label: "Name" },
|
|
1291
|
+
{ key: "maker", label: "Maker" },
|
|
1292
|
+
{ key: "service", label: SERVICE_LABEL },
|
|
1293
|
+
{ key: "context", label: "Context window" },
|
|
1294
|
+
{ key: "price", label: variant === "admin" ? "Price ($/M out)" : "Cost" },
|
|
1295
|
+
...variant === "admin" ? [
|
|
1296
|
+
{ key: "vendor", label: "Vendor" },
|
|
1297
|
+
{ key: "api", label: "API" },
|
|
1298
|
+
{ key: "deprecated", label: "Deprecated" },
|
|
1299
|
+
{ key: "availability", label: "Availability" },
|
|
1300
|
+
{ key: "premium", label: "Premium" }
|
|
1301
|
+
] : []
|
|
1302
|
+
];
|
|
1303
|
+
const setChip = (kind) => /* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap gap-1", children: [
|
|
1304
|
+
/* @__PURE__ */ jsx4(
|
|
1305
|
+
ChipToggle,
|
|
403
1306
|
{
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
1307
|
+
active: filters[kind].size === 0,
|
|
1308
|
+
onClick: () => setFilters((f) => ({ ...f, [kind]: /* @__PURE__ */ new Set() })),
|
|
1309
|
+
children: "Any"
|
|
1310
|
+
}
|
|
1311
|
+
),
|
|
1312
|
+
(kind === "makers" ? makerOptions : kind === "services" ? serviceOptions : kind === "vendors" ? vendorOptions : apiOptions).map((v) => /* @__PURE__ */ jsx4(
|
|
1313
|
+
ChipToggle,
|
|
1314
|
+
{
|
|
1315
|
+
active: filters[kind].has(v),
|
|
1316
|
+
onClick: () => toggleSetValue(kind, v),
|
|
1317
|
+
children: v
|
|
1318
|
+
},
|
|
1319
|
+
v
|
|
1320
|
+
))
|
|
1321
|
+
] });
|
|
1322
|
+
return /* @__PURE__ */ jsxs3("div", { className: "flex h-full flex-col text-xs", children: [
|
|
1323
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-h-0 flex-1 space-y-3 overflow-y-auto p-3 pb-4", children: [
|
|
1324
|
+
/* @__PURE__ */ jsx4(FilterSection, { label: "Sort by", children: /* @__PURE__ */ jsx4(ChipRow, { children: sortOptions.map((o) => /* @__PURE__ */ jsx4(
|
|
1325
|
+
ChipToggle,
|
|
1326
|
+
{
|
|
1327
|
+
active: filters.sort === o.key,
|
|
1328
|
+
onClick: () => setFilters((f) => ({ ...f, sort: o.key })),
|
|
1329
|
+
children: o.label
|
|
414
1330
|
},
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
1331
|
+
o.key
|
|
1332
|
+
)) }) }),
|
|
1333
|
+
/* @__PURE__ */ jsx4(FilterSection, { label: "Input", children: /* @__PURE__ */ jsxs3(ChipRow, { children: [
|
|
1334
|
+
/* @__PURE__ */ jsx4(
|
|
1335
|
+
ChipToggle,
|
|
1336
|
+
{
|
|
1337
|
+
active: filters.input.size === 0,
|
|
1338
|
+
onClick: () => setFilters((f) => ({ ...f, input: /* @__PURE__ */ new Set() })),
|
|
1339
|
+
children: "Any"
|
|
1340
|
+
}
|
|
1341
|
+
),
|
|
1342
|
+
INPUT_MODALITIES.map((m) => /* @__PURE__ */ jsx4(
|
|
1343
|
+
ChipToggle,
|
|
1344
|
+
{
|
|
1345
|
+
active: filters.input.has(m),
|
|
1346
|
+
onClick: () => toggleModality("input", m),
|
|
1347
|
+
children: /* @__PURE__ */ jsx4("span", { className: "capitalize", children: m })
|
|
1348
|
+
},
|
|
1349
|
+
m
|
|
1350
|
+
))
|
|
1351
|
+
] }) }),
|
|
1352
|
+
/* @__PURE__ */ jsx4(FilterSection, { label: "Output", children: /* @__PURE__ */ jsxs3(ChipRow, { children: [
|
|
1353
|
+
/* @__PURE__ */ jsx4(
|
|
1354
|
+
ChipToggle,
|
|
1355
|
+
{
|
|
1356
|
+
active: filters.output.size === 0,
|
|
1357
|
+
onClick: () => setFilters((f) => ({ ...f, output: /* @__PURE__ */ new Set() })),
|
|
1358
|
+
children: "Any"
|
|
1359
|
+
}
|
|
1360
|
+
),
|
|
1361
|
+
OUTPUT_MODALITIES.map((m) => /* @__PURE__ */ jsx4(
|
|
1362
|
+
ChipToggle,
|
|
1363
|
+
{
|
|
1364
|
+
active: filters.output.has(m),
|
|
1365
|
+
onClick: () => toggleModality("output", m),
|
|
1366
|
+
children: /* @__PURE__ */ jsx4("span", { className: "capitalize", children: m })
|
|
1367
|
+
},
|
|
1368
|
+
m
|
|
1369
|
+
))
|
|
1370
|
+
] }) }),
|
|
1371
|
+
variant === "admin" && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1372
|
+
/* @__PURE__ */ jsx4(FilterSection, { label: "Deprecated", children: /* @__PURE__ */ jsx4(
|
|
1373
|
+
TriStateChips,
|
|
1374
|
+
{
|
|
1375
|
+
value: filters.deprecated,
|
|
1376
|
+
onChange: (v) => setFilters((f) => ({ ...f, deprecated: v })),
|
|
1377
|
+
yesLabel: "Deprecated only",
|
|
1378
|
+
noLabel: "Active only"
|
|
1379
|
+
}
|
|
1380
|
+
) }),
|
|
1381
|
+
/* @__PURE__ */ jsx4(FilterSection, { label: "Availability", children: /* @__PURE__ */ jsx4(
|
|
1382
|
+
TriStateChips,
|
|
1383
|
+
{
|
|
1384
|
+
value: filters.availability,
|
|
1385
|
+
onChange: (v) => setFilters((f) => ({ ...f, availability: v })),
|
|
1386
|
+
yesLabel: "Available",
|
|
1387
|
+
noLabel: "Unavailable"
|
|
1388
|
+
}
|
|
1389
|
+
) }),
|
|
1390
|
+
/* @__PURE__ */ jsx4(FilterSection, { label: "Premium", children: /* @__PURE__ */ jsx4(
|
|
1391
|
+
TriStateChips,
|
|
1392
|
+
{
|
|
1393
|
+
value: filters.premium,
|
|
1394
|
+
onChange: (v) => setFilters((f) => ({ ...f, premium: v })),
|
|
1395
|
+
yesLabel: "Premium only",
|
|
1396
|
+
noLabel: "Standard only"
|
|
1397
|
+
}
|
|
1398
|
+
) }),
|
|
1399
|
+
/* @__PURE__ */ jsx4(FilterSection, { label: "Vendor", children: setChip("vendors") }),
|
|
1400
|
+
/* @__PURE__ */ jsx4(FilterSection, { label: "API", children: setChip("apis") })
|
|
1401
|
+
] }),
|
|
1402
|
+
/* @__PURE__ */ jsx4(FilterSection, { label: "Maker", children: /* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-3 gap-1", children: [
|
|
1403
|
+
/* @__PURE__ */ jsx4(
|
|
1404
|
+
ChipToggle,
|
|
1405
|
+
{
|
|
1406
|
+
active: filters.makers.size === 0,
|
|
1407
|
+
onClick: () => setFilters((f) => ({ ...f, makers: /* @__PURE__ */ new Set() })),
|
|
1408
|
+
className: "justify-center py-1",
|
|
1409
|
+
children: "Any"
|
|
1410
|
+
}
|
|
1411
|
+
),
|
|
1412
|
+
makerOptions.map((maker) => /* @__PURE__ */ jsx4(
|
|
1413
|
+
MakerFilterButton,
|
|
1414
|
+
{
|
|
1415
|
+
maker,
|
|
1416
|
+
active: filters.makers.has(maker),
|
|
1417
|
+
onClick: () => toggleSetValue("makers", maker)
|
|
1418
|
+
},
|
|
1419
|
+
maker
|
|
1420
|
+
))
|
|
1421
|
+
] }) }),
|
|
1422
|
+
/* @__PURE__ */ jsx4(FilterSection, { label: SERVICE_LABEL, children: /* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-3 gap-1", children: [
|
|
1423
|
+
/* @__PURE__ */ jsx4(
|
|
1424
|
+
ChipToggle,
|
|
1425
|
+
{
|
|
1426
|
+
active: filters.services.size === 0,
|
|
1427
|
+
onClick: () => setFilters((f) => ({ ...f, services: /* @__PURE__ */ new Set() })),
|
|
1428
|
+
className: "justify-center py-1",
|
|
1429
|
+
children: "Any"
|
|
421
1430
|
}
|
|
1431
|
+
),
|
|
1432
|
+
serviceOptions.map((service) => /* @__PURE__ */ jsx4(
|
|
1433
|
+
ServiceFilterButton,
|
|
1434
|
+
{
|
|
1435
|
+
service,
|
|
1436
|
+
active: filters.services.has(service),
|
|
1437
|
+
onClick: () => toggleSetValue("services", service)
|
|
1438
|
+
},
|
|
1439
|
+
service
|
|
1440
|
+
))
|
|
1441
|
+
] }) }),
|
|
1442
|
+
/* @__PURE__ */ jsx4(FilterSection, { label: "Features", children: /* @__PURE__ */ jsx4("div", { className: "flex flex-wrap gap-1", children: FEATURE_BUCKET_ORDER.map((b) => /* @__PURE__ */ jsx4(
|
|
1443
|
+
ChipToggle,
|
|
1444
|
+
{
|
|
1445
|
+
active: filters.features.has(b),
|
|
1446
|
+
onClick: () => toggleFeature(b),
|
|
1447
|
+
children: FEATURE_BUCKETS[b].label
|
|
422
1448
|
},
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
1449
|
+
b
|
|
1450
|
+
)) }) }),
|
|
1451
|
+
/* @__PURE__ */ jsx4(FilterSection, { label: "Interaction", children: /* @__PURE__ */ jsx4("div", { className: "flex flex-wrap gap-1", children: ["any", "turn", "single", "extraction", "realtime"].map(
|
|
1452
|
+
(i) => /* @__PURE__ */ jsx4(
|
|
1453
|
+
ChipToggle,
|
|
1454
|
+
{
|
|
1455
|
+
active: filters.interaction === i,
|
|
1456
|
+
onClick: () => setFilters((f) => ({ ...f, interaction: i })),
|
|
1457
|
+
children: i === "any" ? "Any" : INTERACTION_LABEL[i]
|
|
1458
|
+
},
|
|
1459
|
+
i
|
|
1460
|
+
)
|
|
1461
|
+
) }) })
|
|
1462
|
+
] }),
|
|
1463
|
+
/* @__PURE__ */ jsxs3("div", { className: "z-10 flex shrink-0 flex-nowrap items-center gap-1 border-t border-border bg-popover px-3 py-2", children: [
|
|
1464
|
+
/* @__PURE__ */ jsx4(
|
|
1465
|
+
ChipToggle,
|
|
1466
|
+
{
|
|
1467
|
+
active: filters.multilingualOnly,
|
|
1468
|
+
onClick: () => setFilters((f) => ({ ...f, multilingualOnly: !f.multilingualOnly })),
|
|
1469
|
+
className: "flex-1 justify-center",
|
|
1470
|
+
children: /* @__PURE__ */ jsxs3("span", { className: "inline-flex items-center gap-1", children: [
|
|
1471
|
+
/* @__PURE__ */ jsx4(LanguagesIcon, { className: "h-3 w-3" }),
|
|
1472
|
+
" Multilingual"
|
|
1473
|
+
] })
|
|
1474
|
+
}
|
|
1475
|
+
),
|
|
1476
|
+
variant === "user" && /* @__PURE__ */ jsx4(
|
|
1477
|
+
ChipToggle,
|
|
1478
|
+
{
|
|
1479
|
+
active: filters.includeDeprecated,
|
|
1480
|
+
onClick: () => setFilters((f) => ({
|
|
1481
|
+
...f,
|
|
1482
|
+
includeDeprecated: !f.includeDeprecated
|
|
1483
|
+
})),
|
|
1484
|
+
className: "flex-1 justify-center",
|
|
1485
|
+
children: "Include deprecated"
|
|
1486
|
+
}
|
|
1487
|
+
)
|
|
1488
|
+
] })
|
|
429
1489
|
] });
|
|
430
1490
|
}
|
|
431
|
-
function
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
1491
|
+
function ModelRow({
|
|
1492
|
+
model,
|
|
1493
|
+
classTier,
|
|
1494
|
+
tier,
|
|
1495
|
+
variant,
|
|
1496
|
+
selected,
|
|
1497
|
+
isFavorite,
|
|
1498
|
+
locked = false,
|
|
1499
|
+
onSelect,
|
|
1500
|
+
onHover,
|
|
1501
|
+
onToggleFavorite
|
|
442
1502
|
}) {
|
|
443
|
-
const
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
1503
|
+
const unavailable = variant === "admin" && !(model.admin?.offerings ?? []).some((o) => o.isAvailable);
|
|
1504
|
+
const retired = model.retiredAt != null;
|
|
1505
|
+
const retiredTitle = retired ? `Retired ${model.retiredAt?.slice(0, 10)} \u2014 the provider no longer serves this model, so it cannot be selected.` : locked ? TOP_TIER_LOCKED_TITLE : void 0;
|
|
1506
|
+
const blocked = retired || locked;
|
|
1507
|
+
return /* @__PURE__ */ jsxs3(
|
|
1508
|
+
"div",
|
|
1509
|
+
{
|
|
1510
|
+
role: "button",
|
|
1511
|
+
tabIndex: 0,
|
|
1512
|
+
"aria-disabled": blocked || void 0,
|
|
1513
|
+
title: retiredTitle,
|
|
1514
|
+
onClick: blocked ? void 0 : onSelect,
|
|
1515
|
+
onKeyDown: (e) => {
|
|
1516
|
+
if (blocked) return;
|
|
1517
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1518
|
+
e.preventDefault();
|
|
1519
|
+
onSelect();
|
|
1520
|
+
}
|
|
1521
|
+
},
|
|
1522
|
+
onMouseEnter: onHover,
|
|
1523
|
+
className: cn(
|
|
1524
|
+
"grid w-full grid-cols-[16px_20px_minmax(0,1fr)_2.75rem_3rem_2.75rem] items-center gap-2 rounded px-2 py-1 transition-colors",
|
|
1525
|
+
blocked ? "cursor-not-allowed opacity-60" : "cursor-pointer hover:bg-muted/60 focus:bg-muted/60 focus:outline-none",
|
|
1526
|
+
selected && "bg-muted"
|
|
1527
|
+
),
|
|
1528
|
+
children: [
|
|
1529
|
+
/* @__PURE__ */ jsx4(
|
|
1530
|
+
"button",
|
|
1531
|
+
{
|
|
1532
|
+
type: "button",
|
|
1533
|
+
onClick: (e) => {
|
|
1534
|
+
e.stopPropagation();
|
|
1535
|
+
onToggleFavorite();
|
|
1536
|
+
},
|
|
1537
|
+
title: isFavorite ? "Remove favorite" : "Add favorite",
|
|
1538
|
+
"aria-label": isFavorite ? "Remove favorite" : "Add favorite",
|
|
1539
|
+
className: cn(
|
|
1540
|
+
"flex h-4 w-4 items-center justify-center rounded transition-colors",
|
|
1541
|
+
isFavorite ? "text-amber-400" : "text-muted-foreground/30 hover:text-muted-foreground"
|
|
1542
|
+
),
|
|
1543
|
+
children: /* @__PURE__ */ jsx4(StarIcon, { className: cn("h-3 w-3", isFavorite && "fill-amber-400") })
|
|
1544
|
+
}
|
|
1545
|
+
),
|
|
1546
|
+
/* @__PURE__ */ jsx4(
|
|
1547
|
+
"span",
|
|
1548
|
+
{
|
|
1549
|
+
className: "flex w-5 justify-center",
|
|
1550
|
+
title: model.maker ?? void 0,
|
|
1551
|
+
children: /* @__PURE__ */ jsx4(MakerBrandGlyph, { maker: model.maker, colored: true, className: "h-3.5 w-3.5" })
|
|
1552
|
+
}
|
|
1553
|
+
),
|
|
1554
|
+
/* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
1555
|
+
/* @__PURE__ */ jsx4(DelayedHint, { label: model.name, children: /* @__PURE__ */ jsx4("span", { className: "truncate text-xs font-medium text-foreground", children: model.name }) }),
|
|
1556
|
+
isDecisionModelCapability(model) && /* @__PURE__ */ jsx4(
|
|
1557
|
+
"span",
|
|
1558
|
+
{
|
|
1559
|
+
className: "shrink-0 rounded border border-primary/40 bg-primary/10 px-1 text-[9px] font-medium text-foreground/80",
|
|
1560
|
+
title: "Decision model \u2014 it answers a Questions part with probabilities and generates no text.",
|
|
1561
|
+
children: "decision"
|
|
483
1562
|
}
|
|
484
1563
|
),
|
|
485
|
-
/* @__PURE__ */
|
|
486
|
-
|
|
1564
|
+
model.isDeprecated && !retired && /* @__PURE__ */ jsx4(
|
|
1565
|
+
"span",
|
|
487
1566
|
{
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
1567
|
+
className: "shrink-0 rounded bg-destructive/15 px-1 text-[9px] text-destructive-ink",
|
|
1568
|
+
title: "Deprecated \u2014 still runs; hidden from default selection",
|
|
1569
|
+
children: "dep"
|
|
1570
|
+
}
|
|
1571
|
+
),
|
|
1572
|
+
retired && /* @__PURE__ */ jsx4(
|
|
1573
|
+
"span",
|
|
1574
|
+
{
|
|
1575
|
+
className: "shrink-0 rounded bg-destructive/15 px-1 text-[9px] text-destructive-ink",
|
|
1576
|
+
title: retiredTitle,
|
|
1577
|
+
children: "retired"
|
|
1578
|
+
}
|
|
1579
|
+
),
|
|
1580
|
+
unavailable && /* @__PURE__ */ jsx4(
|
|
1581
|
+
"span",
|
|
1582
|
+
{
|
|
1583
|
+
className: "shrink-0 rounded bg-destructive/15 px-1 text-[9px] text-destructive-ink",
|
|
1584
|
+
title: "No available offerings \u2014 not callable",
|
|
1585
|
+
children: "off"
|
|
1586
|
+
}
|
|
1587
|
+
),
|
|
1588
|
+
classTier ? /* @__PURE__ */ jsx4(
|
|
1589
|
+
"span",
|
|
1590
|
+
{
|
|
1591
|
+
className: "shrink-0 rounded border border-primary/40 bg-primary/10 px-1 text-[9px] font-medium text-foreground/80",
|
|
1592
|
+
title: `Runs on ${classTier.servedVia}`,
|
|
1593
|
+
children: classTier.servedVia
|
|
1594
|
+
}
|
|
1595
|
+
) : model.tiers.length > 1 && /* @__PURE__ */ jsx4(
|
|
1596
|
+
"span",
|
|
1597
|
+
{
|
|
1598
|
+
className: "shrink-0 rounded border border-primary/40 bg-primary/10 px-1 text-[9px] font-medium text-foreground/80",
|
|
1599
|
+
title: model.tiers.map((t) => t.servedVia).join(" \xB7 "),
|
|
1600
|
+
children: serviceCountLabel(model.tiers.length)
|
|
500
1601
|
}
|
|
501
1602
|
)
|
|
502
|
-
]
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
1603
|
+
] }),
|
|
1604
|
+
/* @__PURE__ */ jsx4(SpeedCell, { value: model.speedRating }),
|
|
1605
|
+
/* @__PURE__ */ jsx4(
|
|
1606
|
+
DelayedHint,
|
|
1607
|
+
{
|
|
1608
|
+
label: model.contextWindow == null ? "No context window listed" : `Context window ${formatCount(model.contextWindow)} tokens`,
|
|
1609
|
+
children: /* @__PURE__ */ jsx4("span", { className: "block w-12 whitespace-nowrap text-right font-mono text-[11px] tabular-nums text-foreground/80", children: model.contextWindow == null ? "\u2014" : fmtPointsCompact(model.contextWindow) })
|
|
1610
|
+
}
|
|
1611
|
+
),
|
|
1612
|
+
/* @__PURE__ */ jsx4(
|
|
1613
|
+
DelayedHint,
|
|
1614
|
+
{
|
|
1615
|
+
label: tier == null ? "No relative cost rating yet" : `Relative cost ${tier.replace("+", "")}${tier.endsWith("+") ? "+" : ""} \u2014 more $ is more expensive`,
|
|
1616
|
+
children: /* @__PURE__ */ jsx4("span", { className: "block w-[2.75rem] text-right", children: /* @__PURE__ */ jsx4(CostTier, { tier }) })
|
|
1617
|
+
}
|
|
1618
|
+
)
|
|
1619
|
+
]
|
|
1620
|
+
}
|
|
1621
|
+
);
|
|
1622
|
+
}
|
|
1623
|
+
function LocalModelRow({ model, selected, onSelect }) {
|
|
1624
|
+
const dim = model.needsMoreMemory === true;
|
|
1625
|
+
return /* @__PURE__ */ jsxs3(
|
|
1626
|
+
"div",
|
|
508
1627
|
{
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
onBlur: (e) => commit(e.target.value),
|
|
515
|
-
onFocus: (e) => e.target.select(),
|
|
1628
|
+
role: "button",
|
|
1629
|
+
tabIndex: 0,
|
|
1630
|
+
"data-local-model": model.id,
|
|
1631
|
+
title: dim ? "Needs more memory than this computer has free" : void 0,
|
|
1632
|
+
onClick: onSelect,
|
|
516
1633
|
onKeyDown: (e) => {
|
|
517
|
-
if (e.key === "Enter"
|
|
1634
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1635
|
+
e.preventDefault();
|
|
1636
|
+
onSelect();
|
|
1637
|
+
}
|
|
518
1638
|
},
|
|
1639
|
+
className: cn(
|
|
1640
|
+
"grid w-full cursor-pointer grid-cols-[16px_20px_minmax(0,1fr)_2.75rem_3rem_2.75rem] items-center gap-2 rounded px-2 py-1 transition-colors hover:bg-muted/60 focus:bg-muted/60 focus:outline-none",
|
|
1641
|
+
dim && "opacity-60",
|
|
1642
|
+
selected && "bg-muted"
|
|
1643
|
+
),
|
|
1644
|
+
children: [
|
|
1645
|
+
/* @__PURE__ */ jsx4("span", { className: "w-4" }),
|
|
1646
|
+
/* @__PURE__ */ jsx4("span", { className: "flex w-5 justify-center", title: model.maker ?? void 0, children: /* @__PURE__ */ jsx4(MakerBrandGlyph, { maker: model.maker ?? null, colored: true, className: "h-3.5 w-3.5" }) }),
|
|
1647
|
+
/* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
1648
|
+
/* @__PURE__ */ jsx4("span", { className: "truncate text-xs font-medium text-foreground", children: model.name }),
|
|
1649
|
+
/* @__PURE__ */ jsx4(
|
|
1650
|
+
"span",
|
|
1651
|
+
{
|
|
1652
|
+
className: "shrink-0 rounded border border-primary/40 bg-primary/10 px-1 text-[9px] font-medium text-foreground/80",
|
|
1653
|
+
title: "Runs on this computer",
|
|
1654
|
+
children: "local"
|
|
1655
|
+
}
|
|
1656
|
+
),
|
|
1657
|
+
dim && /* @__PURE__ */ jsx4("span", { className: "shrink-0 rounded bg-muted px-1 text-[9px] text-muted-foreground", title: "Needs more memory than this computer has free", children: "needs memory" })
|
|
1658
|
+
] }),
|
|
1659
|
+
/* @__PURE__ */ jsx4("span", { className: "w-11" }),
|
|
1660
|
+
/* @__PURE__ */ jsx4("span", { className: "block w-12 whitespace-nowrap text-right font-mono text-[11px] tabular-nums text-foreground/80", children: model.contextWindow == null ? "\u2014" : fmtPointsCompact(model.contextWindow) }),
|
|
1661
|
+
/* @__PURE__ */ jsx4("span", { className: "w-[2.75rem]" })
|
|
1662
|
+
]
|
|
1663
|
+
}
|
|
1664
|
+
);
|
|
1665
|
+
}
|
|
1666
|
+
var GROUP_HEADING = "px-2 pb-0.5 pt-1.5 text-[10px] uppercase tracking-wide text-muted-foreground";
|
|
1667
|
+
function ModelListDropdown({
|
|
1668
|
+
value: savedValue,
|
|
1669
|
+
localModels: localModelsProp,
|
|
1670
|
+
onValueChange,
|
|
1671
|
+
inputModalities,
|
|
1672
|
+
outputModalities,
|
|
1673
|
+
selectionPurpose,
|
|
1674
|
+
allowedModelIds,
|
|
1675
|
+
catalogVariant,
|
|
1676
|
+
emptyOptionLabel,
|
|
1677
|
+
onClear,
|
|
1678
|
+
placeholder = "Select a model\u2026",
|
|
1679
|
+
priorityModelIds,
|
|
1680
|
+
pinnedOfferingId,
|
|
1681
|
+
onOfferingPinChange,
|
|
1682
|
+
modelOnly,
|
|
1683
|
+
className,
|
|
1684
|
+
triggerVariant = "default",
|
|
1685
|
+
presentation = "picker",
|
|
1686
|
+
id,
|
|
1687
|
+
disabled = false,
|
|
1688
|
+
disabledTitle,
|
|
1689
|
+
"aria-label": ariaLabel,
|
|
1690
|
+
"aria-labelledby": ariaLabelledBy
|
|
1691
|
+
}) {
|
|
1692
|
+
const isMobile = useIsMobile();
|
|
1693
|
+
const dialogContainer = useDialogContainer();
|
|
1694
|
+
const [pickerOpen, setOpen] = useState(false);
|
|
1695
|
+
const inline = presentation === "inline";
|
|
1696
|
+
const open = inline || pickerOpen;
|
|
1697
|
+
const { favoriteSet, toggleFavorite } = useModelFavorites(open);
|
|
1698
|
+
const ports = useModelCatalogUiPorts();
|
|
1699
|
+
const canUseTopTier = ports.canUseTopTier ?? false;
|
|
1700
|
+
const isSuperAdmin = ports.isSuperAdmin ?? false;
|
|
1701
|
+
const LinkComponent = ports.LinkComponent;
|
|
1702
|
+
const hiddenModelIds = ports.hiddenModelIds;
|
|
1703
|
+
const [adminMode, setAdminMode] = useState(false);
|
|
1704
|
+
const variant = catalogVariant ?? (adminMode && isSuperAdmin ? "admin" : "user");
|
|
1705
|
+
const effectiveSelectionPurpose = selectionPurpose ?? (variant === "admin" ? "admin" : "chat");
|
|
1706
|
+
const { models, isLoading, error } = useModelCatalog(variant);
|
|
1707
|
+
const successionIndex = useMemo2(() => buildSuccessionIndex(models), [models]);
|
|
1708
|
+
const value = savedValue ? resolveSuccessor(savedValue, successionIndex) : savedValue;
|
|
1709
|
+
const healedFrom = useRef(null);
|
|
1710
|
+
useEffect2(() => {
|
|
1711
|
+
if (!savedValue || !value || value === savedValue || healedFrom.current === savedValue) return;
|
|
1712
|
+
healedFrom.current = savedValue;
|
|
1713
|
+
if (onOfferingPinChange && pinnedOfferingId) onOfferingPinChange(void 0);
|
|
1714
|
+
onValueChange(value);
|
|
1715
|
+
}, [savedValue, value, onOfferingPinChange, pinnedOfferingId, onValueChange]);
|
|
1716
|
+
const [query, setQuery] = useState("");
|
|
1717
|
+
const [tab, setTab] = useState("all");
|
|
1718
|
+
const [rightPanel, setRightPanel] = useState(null);
|
|
1719
|
+
const [hovered, setHovered] = useState(null);
|
|
1720
|
+
const [hoveredClass, setHoveredClass] = useState(null);
|
|
1721
|
+
const [mobileDetail, setMobileDetail] = useState(null);
|
|
1722
|
+
const [mobileDetailClass, setMobileDetailClass] = useState(null);
|
|
1723
|
+
const [mobileFilters, setMobileFilters] = useState(false);
|
|
1724
|
+
const inputRef = useRef(null);
|
|
1725
|
+
const [filters, setFilters] = useState(() => ({
|
|
1726
|
+
input: new Set(inputModalities),
|
|
1727
|
+
output: new Set(outputModalities ?? []),
|
|
1728
|
+
features: /* @__PURE__ */ new Set(),
|
|
1729
|
+
makers: /* @__PURE__ */ new Set(),
|
|
1730
|
+
services: /* @__PURE__ */ new Set(),
|
|
1731
|
+
interaction: "any",
|
|
1732
|
+
multilingualOnly: false,
|
|
1733
|
+
sort: "name",
|
|
1734
|
+
vendors: /* @__PURE__ */ new Set(),
|
|
1735
|
+
apis: /* @__PURE__ */ new Set(),
|
|
1736
|
+
includeDeprecated: false,
|
|
1737
|
+
deprecated: "any",
|
|
1738
|
+
availability: "any",
|
|
1739
|
+
premium: "any"
|
|
1740
|
+
}));
|
|
1741
|
+
const setVariantMode = (nextAdmin) => {
|
|
1742
|
+
setAdminMode(nextAdmin);
|
|
1743
|
+
setHovered(null);
|
|
1744
|
+
if (!nextAdmin) {
|
|
1745
|
+
setFilters((f) => ({
|
|
1746
|
+
...f,
|
|
1747
|
+
vendors: /* @__PURE__ */ new Set(),
|
|
1748
|
+
apis: /* @__PURE__ */ new Set(),
|
|
1749
|
+
deprecated: "any",
|
|
1750
|
+
availability: "any",
|
|
1751
|
+
premium: "any",
|
|
1752
|
+
sort: ADMIN_ONLY_SORTS.has(f.sort) ? "name" : f.sort
|
|
1753
|
+
}));
|
|
1754
|
+
}
|
|
1755
|
+
};
|
|
1756
|
+
const allowedModelSet = allowedModelIds ? new Set(allowedModelIds) : null;
|
|
1757
|
+
const priorityModelSet = priorityModelIds ? new Set(priorityModelIds) : null;
|
|
1758
|
+
const eligibleModels = allowedModelSet ? models.filter((model) => allowedModelSet.has(model.id)) : models;
|
|
1759
|
+
const selected = models.find((m) => m.id === value) ?? null;
|
|
1760
|
+
const { models: localAll, groupLabel: localGroupLabel, open: openLocal } = useLocalModels(localModelsProp);
|
|
1761
|
+
const selectedLocal = localAll.find((m) => m.id === value) ?? null;
|
|
1762
|
+
const localEligible = !modelOnly && variant === "user" && !allowedModelSet && (effectiveSelectionPurpose === "chat" || effectiveSelectionPurpose === "agent");
|
|
1763
|
+
const localRows = useMemo2(() => {
|
|
1764
|
+
if (!localEligible || tab !== "all") return [];
|
|
1765
|
+
const q = query.trim().toLowerCase();
|
|
1766
|
+
return q ? localAll.filter((m) => [m.name, m.maker, "local"].some((f) => f?.toLowerCase().includes(q))) : localAll;
|
|
1767
|
+
}, [localEligible, tab, query, localAll]);
|
|
1768
|
+
const shown = selected ?? (selectedLocal ? { name: selectedLocal.name, maker: selectedLocal.maker ?? null } : null);
|
|
1769
|
+
const makerOptions = useMemo2(
|
|
1770
|
+
() => [
|
|
1771
|
+
...new Set(
|
|
1772
|
+
eligibleModels.map((m) => m.maker).filter((v) => !!v)
|
|
1773
|
+
)
|
|
1774
|
+
].sort((a, b) => a.localeCompare(b)),
|
|
1775
|
+
[eligibleModels]
|
|
1776
|
+
);
|
|
1777
|
+
const serviceOptions = useMemo2(
|
|
1778
|
+
() => [
|
|
1779
|
+
...new Set(
|
|
1780
|
+
eligibleModels.flatMap((m) => m.tiers.map((t) => t.servedVia)).filter(Boolean)
|
|
1781
|
+
)
|
|
1782
|
+
].sort((a, b) => a.localeCompare(b)),
|
|
1783
|
+
[eligibleModels]
|
|
1784
|
+
);
|
|
1785
|
+
const vendorOptions = useMemo2(
|
|
1786
|
+
() => [
|
|
1787
|
+
...new Set(
|
|
1788
|
+
eligibleModels.flatMap((m) => (m.admin?.offerings ?? []).map((o) => o.vendor)).filter((v) => !!v)
|
|
1789
|
+
)
|
|
1790
|
+
].sort((a, b) => a.localeCompare(b)),
|
|
1791
|
+
[eligibleModels]
|
|
1792
|
+
);
|
|
1793
|
+
const apiOptions = useMemo2(
|
|
1794
|
+
() => [
|
|
1795
|
+
...new Set(
|
|
1796
|
+
eligibleModels.flatMap((m) => (m.admin?.offerings ?? []).map((o) => o.apiName)).filter((v) => !!v)
|
|
1797
|
+
)
|
|
1798
|
+
].sort((a, b) => a.localeCompare(b)),
|
|
1799
|
+
[eligibleModels]
|
|
1800
|
+
);
|
|
1801
|
+
const chatFitApplies = effectiveSelectionPurpose === "chat" && !(outputModalities ?? []).some((o) => o !== "text");
|
|
1802
|
+
const filtered = useMemo2(() => {
|
|
1803
|
+
const q = query.trim().toLowerCase();
|
|
1804
|
+
const hasAvailable = (m) => (m.admin?.offerings ?? []).some((o) => o.isAvailable);
|
|
1805
|
+
const rows = eligibleModels.filter((m) => {
|
|
1806
|
+
const isDecision = isDecisionModelCapability(m);
|
|
1807
|
+
if (effectiveSelectionPurpose === "chat" && isDecision) return false;
|
|
1808
|
+
if (effectiveSelectionPurpose === "decision" && !isDecision) return false;
|
|
1809
|
+
if (effectiveSelectionPurpose !== "admin" && !acceptsTextInstructions(m))
|
|
1810
|
+
return false;
|
|
1811
|
+
if (effectiveSelectionPurpose === "chat" && isManagedAgentModelCapability(m))
|
|
1812
|
+
return false;
|
|
1813
|
+
if (chatFitApplies && !isChatModelCapability(m)) return false;
|
|
1814
|
+
if (tab === "favorites" && !favoriteSet.has(m.id)) return false;
|
|
1815
|
+
const haystack = [
|
|
1816
|
+
m.name,
|
|
1817
|
+
m.maker,
|
|
1818
|
+
...m.tiers.map((t) => t.servedVia),
|
|
1819
|
+
...variant === "admin" ? (m.admin?.offerings ?? []).flatMap((o) => [
|
|
1820
|
+
o.vendor,
|
|
1821
|
+
o.apiName,
|
|
1822
|
+
o.providerModelId
|
|
1823
|
+
]) : []
|
|
1824
|
+
];
|
|
1825
|
+
if (q && !haystack.some((f) => f?.toLowerCase().includes(q)))
|
|
1826
|
+
return false;
|
|
1827
|
+
if (filters.makers.size > 0 && (!m.maker || !filters.makers.has(m.maker)))
|
|
1828
|
+
return false;
|
|
1829
|
+
if (filters.services.size > 0 && !m.tiers.some((t) => filters.services.has(t.servedVia)))
|
|
1830
|
+
return false;
|
|
1831
|
+
if (filters.vendors.size > 0 && !(m.admin?.offerings ?? []).some(
|
|
1832
|
+
(o) => o.vendor != null && filters.vendors.has(o.vendor)
|
|
1833
|
+
))
|
|
1834
|
+
return false;
|
|
1835
|
+
if (filters.apis.size > 0 && !(m.admin?.offerings ?? []).some(
|
|
1836
|
+
(o) => o.apiName != null && filters.apis.has(o.apiName)
|
|
1837
|
+
))
|
|
1838
|
+
return false;
|
|
1839
|
+
if (variant === "user" && m.id !== value && hiddenModelIds?.includes(m.id))
|
|
1840
|
+
return false;
|
|
1841
|
+
if (variant === "user" && !filters.includeDeprecated && m.isDeprecated && m.id !== value)
|
|
1842
|
+
return false;
|
|
1843
|
+
if (variant === "user" && resolveSuccessor(m.id, successionIndex) !== m.id) return false;
|
|
1844
|
+
if (filters.deprecated !== "any") {
|
|
1845
|
+
if (filters.deprecated === "yes" !== m.isDeprecated) return false;
|
|
1846
|
+
}
|
|
1847
|
+
if (filters.availability !== "any") {
|
|
1848
|
+
if (filters.availability === "yes" !== hasAvailable(m)) return false;
|
|
1849
|
+
}
|
|
1850
|
+
if (filters.premium !== "any") {
|
|
1851
|
+
if (filters.premium === "yes" !== m.isPremium) return false;
|
|
1852
|
+
}
|
|
1853
|
+
for (const m2 of filters.input) if (!takesInput(m, m2)) return false;
|
|
1854
|
+
const outputSatisfied = (want) => m.output.includes(want) || effectiveSelectionPurpose === "agent" && isDecision && want === "text";
|
|
1855
|
+
for (const m2 of filters.output) if (!outputSatisfied(m2)) return false;
|
|
1856
|
+
for (const b of filters.features)
|
|
1857
|
+
if (!m.features.buckets.includes(b)) return false;
|
|
1858
|
+
if (filters.interaction !== "any" && m.interaction !== filters.interaction)
|
|
1859
|
+
return false;
|
|
1860
|
+
if (filters.multilingualOnly && !m.multilingual) return false;
|
|
1861
|
+
return true;
|
|
1862
|
+
});
|
|
1863
|
+
const cmp = (a, b) => {
|
|
1864
|
+
switch (filters.sort) {
|
|
1865
|
+
case "maker":
|
|
1866
|
+
return (a.maker ?? "").localeCompare(b.maker ?? "");
|
|
1867
|
+
case "service":
|
|
1868
|
+
return (a.tiers[0]?.servedVia ?? "\uFFFF").localeCompare(
|
|
1869
|
+
b.tiers[0]?.servedVia ?? "\uFFFF"
|
|
1870
|
+
) || b.tiers.length - a.tiers.length;
|
|
1871
|
+
case "context":
|
|
1872
|
+
return (b.contextWindow ?? 0) - (a.contextWindow ?? 0);
|
|
1873
|
+
case "price": {
|
|
1874
|
+
const price = (m) => (variant === "admin" ? m.outputCost : m.costRating) ?? Infinity;
|
|
1875
|
+
return price(a) - price(b) || a.name.localeCompare(b.name);
|
|
1876
|
+
}
|
|
1877
|
+
case "vendor":
|
|
1878
|
+
return (a.admin?.offerings[0]?.vendor ?? "\uFFFF").localeCompare(
|
|
1879
|
+
b.admin?.offerings[0]?.vendor ?? "\uFFFF"
|
|
1880
|
+
) || a.name.localeCompare(b.name);
|
|
1881
|
+
case "api":
|
|
1882
|
+
return (a.admin?.offerings[0]?.apiName ?? "\uFFFF").localeCompare(
|
|
1883
|
+
b.admin?.offerings[0]?.apiName ?? "\uFFFF"
|
|
1884
|
+
) || a.name.localeCompare(b.name);
|
|
1885
|
+
case "deprecated":
|
|
1886
|
+
return Number(a.isDeprecated) - Number(b.isDeprecated) || a.name.localeCompare(b.name);
|
|
1887
|
+
case "availability": {
|
|
1888
|
+
const avail = (m) => (m.admin?.offerings ?? []).filter((o) => o.isAvailable).length;
|
|
1889
|
+
return avail(b) - avail(a) || a.name.localeCompare(b.name);
|
|
1890
|
+
}
|
|
1891
|
+
case "premium":
|
|
1892
|
+
return Number(b.isPremium) - Number(a.isPremium) || a.name.localeCompare(b.name);
|
|
1893
|
+
default:
|
|
1894
|
+
return a.name.localeCompare(b.name);
|
|
1895
|
+
}
|
|
1896
|
+
};
|
|
1897
|
+
const sorted = [...rows].sort(cmp);
|
|
1898
|
+
const prioritize = (items) => {
|
|
1899
|
+
if (!priorityModelSet || priorityModelSet.size === 0) return items;
|
|
1900
|
+
const priority = items.filter((m) => priorityModelSet.has(m.id));
|
|
1901
|
+
const rest = items.filter((m) => !priorityModelSet.has(m.id));
|
|
1902
|
+
return [...priority, ...rest];
|
|
1903
|
+
};
|
|
1904
|
+
if (tab === "all") {
|
|
1905
|
+
const favs = sorted.filter((m) => favoriteSet.has(m.id));
|
|
1906
|
+
const rest = sorted.filter((m) => !favoriteSet.has(m.id));
|
|
1907
|
+
return [...prioritize(favs), ...prioritize(rest)];
|
|
1908
|
+
}
|
|
1909
|
+
return prioritize(sorted);
|
|
1910
|
+
}, [
|
|
1911
|
+
eligibleModels,
|
|
1912
|
+
query,
|
|
1913
|
+
filters,
|
|
1914
|
+
tab,
|
|
1915
|
+
favoriteSet,
|
|
1916
|
+
variant,
|
|
1917
|
+
priorityModelSet,
|
|
1918
|
+
effectiveSelectionPurpose,
|
|
1919
|
+
chatFitApplies,
|
|
1920
|
+
hiddenModelIds,
|
|
1921
|
+
value,
|
|
1922
|
+
successionIndex
|
|
1923
|
+
]);
|
|
1924
|
+
const listRows = useMemo2(
|
|
1925
|
+
() => filtered.flatMap((m) => {
|
|
1926
|
+
if (modelOnly || m.tiers.length < 2) {
|
|
1927
|
+
return [{ model: m, classTier: null }];
|
|
1928
|
+
}
|
|
1929
|
+
const classes = filters.services.size > 0 ? m.tiers.filter((t) => filters.services.has(t.servedVia)) : m.tiers;
|
|
1930
|
+
return classes.map((t) => ({ model: m, classTier: t }));
|
|
1931
|
+
}),
|
|
1932
|
+
[filtered, modelOnly, filters.services]
|
|
1933
|
+
);
|
|
1934
|
+
const selectedClass = selected ? selected.tiers.find((t) => t.offeringId === pinnedOfferingId) ?? selected.tiers[0] ?? null : null;
|
|
1935
|
+
const selectedClassLabel = !modelOnly && selected && selected.tiers.length > 1 ? selectedClass?.servedVia : void 0;
|
|
1936
|
+
const activeFilterCount = filters.input.size + filters.output.size + filters.features.size + filters.makers.size + filters.services.size + filters.vendors.size + filters.apis.size + (filters.deprecated !== "any" ? 1 : 0) + (filters.availability !== "any" ? 1 : 0) + (filters.premium !== "any" ? 1 : 0) + (filters.interaction !== "any" ? 1 : 0) + (filters.multilingualOnly ? 1 : 0) + (filters.includeDeprecated ? 1 : 0);
|
|
1937
|
+
const handleOpen = (next) => {
|
|
1938
|
+
setOpen(next);
|
|
1939
|
+
if (next) {
|
|
1940
|
+
setTimeout(() => inputRef.current?.focus(), 50);
|
|
1941
|
+
} else {
|
|
1942
|
+
setRightPanel(null);
|
|
1943
|
+
setHovered(null);
|
|
1944
|
+
setMobileDetail(null);
|
|
1945
|
+
setMobileFilters(false);
|
|
1946
|
+
setQuery("");
|
|
1947
|
+
}
|
|
1948
|
+
};
|
|
1949
|
+
const refuseIfRetired = (id2) => {
|
|
1950
|
+
const target = models.find((m) => m.id === id2);
|
|
1951
|
+
if (target && !canUseTopTier && isTopTierRating(target.costRating)) {
|
|
1952
|
+
console.warn(`[ModelListDropdown] Refused to select ${target.name} (${id2}): ${TOP_TIER_LOCKED_TITLE}.`);
|
|
1953
|
+
return true;
|
|
1954
|
+
}
|
|
1955
|
+
if (!target?.retiredAt) return false;
|
|
1956
|
+
console.warn(
|
|
1957
|
+
`[ModelListDropdown] Refused to select ${target.name} (${id2}): retired ${target.retiredAt} \u2014 the provider no longer serves it.`
|
|
1958
|
+
);
|
|
1959
|
+
return true;
|
|
1960
|
+
};
|
|
1961
|
+
const handleSelectClass = (model, classTier) => {
|
|
1962
|
+
if (refuseIfRetired(model.id)) return;
|
|
1963
|
+
if (onOfferingPinChange) {
|
|
1964
|
+
const nextPin = classTier && model.tiers.length > 1 ? classTier.offeringId : void 0;
|
|
1965
|
+
if (nextPin !== (pinnedOfferingId ?? void 0)) onOfferingPinChange(nextPin);
|
|
1966
|
+
}
|
|
1967
|
+
onValueChange(model.id);
|
|
1968
|
+
handleOpen(false);
|
|
1969
|
+
};
|
|
1970
|
+
const handleSelect = (id2, tappedClass) => {
|
|
1971
|
+
const next = models.find((m) => m.id === id2);
|
|
1972
|
+
if (!next) return;
|
|
1973
|
+
const pinnedHere = next.tiers.find((t) => t.offeringId === pinnedOfferingId) ?? null;
|
|
1974
|
+
handleSelectClass(next, tappedClass ?? pinnedHere ?? next.tiers[0] ?? null);
|
|
1975
|
+
};
|
|
1976
|
+
const handleSelectLocal = (local) => {
|
|
1977
|
+
if (openLocal) {
|
|
1978
|
+
openLocal(local.id);
|
|
1979
|
+
handleOpen(false);
|
|
1980
|
+
return;
|
|
1981
|
+
}
|
|
1982
|
+
if (onOfferingPinChange && pinnedOfferingId) onOfferingPinChange(void 0);
|
|
1983
|
+
onValueChange(local.id);
|
|
1984
|
+
handleOpen(false);
|
|
1985
|
+
};
|
|
1986
|
+
const handleClear = () => {
|
|
1987
|
+
onClear?.();
|
|
1988
|
+
handleOpen(false);
|
|
1989
|
+
};
|
|
1990
|
+
const handlePinOffering = (model, offeringId) => {
|
|
1991
|
+
if (!onOfferingPinChange) return;
|
|
1992
|
+
if (refuseIfRetired(model.id)) return;
|
|
1993
|
+
onOfferingPinChange(offeringId);
|
|
1994
|
+
if (model.id !== value) onValueChange(model.id);
|
|
1995
|
+
};
|
|
1996
|
+
const trigger = /* @__PURE__ */ jsxs3(
|
|
1997
|
+
"button",
|
|
1998
|
+
{
|
|
1999
|
+
type: "button",
|
|
2000
|
+
id,
|
|
519
2001
|
disabled,
|
|
520
|
-
|
|
2002
|
+
title: disabled ? disabledTitle : void 0,
|
|
2003
|
+
"aria-label": ariaLabel,
|
|
2004
|
+
"aria-labelledby": ariaLabelledBy,
|
|
2005
|
+
"aria-disabled": disabled || void 0,
|
|
2006
|
+
className: cn(
|
|
2007
|
+
triggerVariant === "settings" ? selectTriggerVariants({
|
|
2008
|
+
size: "default",
|
|
2009
|
+
className: "h-auto min-h-9 max-lg:min-h-11 pointer-coarse:min-h-11 w-full min-w-0 max-w-full whitespace-normal text-left font-medium text-foreground"
|
|
2010
|
+
}) : "inline-flex h-7 min-w-0 max-w-full items-center gap-1 overflow-hidden rounded-md bg-transparent px-1 text-xs font-medium text-foreground/80 transition-colors hover:text-foreground",
|
|
2011
|
+
disabled && "cursor-not-allowed opacity-50 hover:text-foreground/80",
|
|
2012
|
+
className
|
|
2013
|
+
),
|
|
2014
|
+
children: [
|
|
2015
|
+
triggerVariant === "settings" ? /* @__PURE__ */ jsx4("div", { className: "flex min-w-0 flex-1 items-center gap-1.5", children: shown ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2016
|
+
/* @__PURE__ */ jsx4(
|
|
2017
|
+
MakerBrandGlyph,
|
|
2018
|
+
{
|
|
2019
|
+
maker: shown.maker,
|
|
2020
|
+
colored: true,
|
|
2021
|
+
className: "h-3.5 w-3.5 shrink-0"
|
|
2022
|
+
}
|
|
2023
|
+
),
|
|
2024
|
+
/* @__PURE__ */ jsxs3("span", { className: "min-w-0 whitespace-normal text-left leading-tight", children: [
|
|
2025
|
+
shown.name,
|
|
2026
|
+
selectedClassLabel && /* @__PURE__ */ jsxs3("span", { className: "text-muted-foreground", children: [
|
|
2027
|
+
" \xB7 ",
|
|
2028
|
+
selectedClassLabel
|
|
2029
|
+
] })
|
|
2030
|
+
] })
|
|
2031
|
+
] }) : /* @__PURE__ */ jsx4("span", { className: "min-w-0 whitespace-normal text-left leading-tight text-muted-foreground", children: isLoading ? "Loading models\u2026" : emptyOptionLabel && !value ? emptyOptionLabel : placeholder }) }) : /* @__PURE__ */ jsx4("span", { className: "flex min-w-0 flex-1 items-center gap-1.5", children: shown ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2032
|
+
/* @__PURE__ */ jsx4(
|
|
2033
|
+
MakerBrandGlyph,
|
|
2034
|
+
{
|
|
2035
|
+
maker: shown.maker,
|
|
2036
|
+
colored: true,
|
|
2037
|
+
className: "h-3.5 w-3.5 shrink-0"
|
|
2038
|
+
}
|
|
2039
|
+
),
|
|
2040
|
+
/* @__PURE__ */ jsxs3("span", { className: "min-w-0 truncate", children: [
|
|
2041
|
+
shown.name,
|
|
2042
|
+
selectedClassLabel && /* @__PURE__ */ jsxs3("span", { className: "text-muted-foreground", children: [
|
|
2043
|
+
" \xB7 ",
|
|
2044
|
+
selectedClassLabel
|
|
2045
|
+
] })
|
|
2046
|
+
] })
|
|
2047
|
+
] }) : /* @__PURE__ */ jsx4("span", { className: "min-w-0 truncate text-muted-foreground", children: isLoading ? "Loading models\u2026" : emptyOptionLabel && !value ? emptyOptionLabel : placeholder }) }),
|
|
2048
|
+
/* @__PURE__ */ jsx4(
|
|
2049
|
+
ChevronDownIcon,
|
|
2050
|
+
{
|
|
2051
|
+
className: cn(
|
|
2052
|
+
"shrink-0 text-muted-foreground/60",
|
|
2053
|
+
triggerVariant === "settings" ? "h-4 w-4" : "h-3 w-3"
|
|
2054
|
+
)
|
|
2055
|
+
}
|
|
2056
|
+
)
|
|
2057
|
+
]
|
|
2058
|
+
}
|
|
2059
|
+
);
|
|
2060
|
+
const listPanel = /* @__PURE__ */ jsxs3("div", { className: "flex h-full flex-col", children: [
|
|
2061
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1.5 border-b border-border p-2", children: [
|
|
2062
|
+
/* @__PURE__ */ jsxs3("div", { className: "relative flex-1", children: [
|
|
2063
|
+
/* @__PURE__ */ jsx4(SearchIcon, { className: "absolute left-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" }),
|
|
2064
|
+
/* @__PURE__ */ jsx4(
|
|
2065
|
+
Input,
|
|
2066
|
+
{
|
|
2067
|
+
adornment: "start",
|
|
2068
|
+
ref: inputRef,
|
|
2069
|
+
value: query,
|
|
2070
|
+
onChange: (e) => setQuery(e.target.value),
|
|
2071
|
+
placeholder: "Search models\u2026"
|
|
2072
|
+
}
|
|
2073
|
+
)
|
|
2074
|
+
] }),
|
|
2075
|
+
/* @__PURE__ */ jsxs3(
|
|
2076
|
+
"button",
|
|
2077
|
+
{
|
|
2078
|
+
type: "button",
|
|
2079
|
+
onClick: () => isMobile ? setMobileFilters(true) : setRightPanel(rightPanel === "filters" ? null : "filters"),
|
|
2080
|
+
className: cn(
|
|
2081
|
+
"inline-flex h-7 items-center gap-1 rounded-md border px-2 text-[11px] transition-colors",
|
|
2082
|
+
rightPanel === "filters" ? "border-primary bg-primary/10 text-foreground" : "border-border text-muted-foreground hover:text-foreground"
|
|
2083
|
+
),
|
|
2084
|
+
children: [
|
|
2085
|
+
/* @__PURE__ */ jsx4(SlidersHorizontalIcon, { className: "h-3.5 w-3.5" }),
|
|
2086
|
+
"Filters",
|
|
2087
|
+
activeFilterCount > 0 && /* @__PURE__ */ jsx4("span", { className: "text-primary", children: activeFilterCount })
|
|
2088
|
+
]
|
|
2089
|
+
}
|
|
2090
|
+
)
|
|
2091
|
+
] }),
|
|
2092
|
+
/* @__PURE__ */ jsx4("div", { className: "flex items-center gap-1 border-b border-border px-2 py-1", children: ["all", "favorites"].map((t) => /* @__PURE__ */ jsxs3(
|
|
2093
|
+
"button",
|
|
2094
|
+
{
|
|
2095
|
+
type: "button",
|
|
2096
|
+
onClick: () => setTab(t),
|
|
2097
|
+
className: cn(
|
|
2098
|
+
"inline-flex items-center gap-1 rounded px-2 py-0.5 text-[11px] transition-colors",
|
|
2099
|
+
tab === t ? "bg-accent text-foreground" : "text-muted-foreground hover:text-foreground"
|
|
2100
|
+
),
|
|
2101
|
+
children: [
|
|
2102
|
+
t === "favorites" && /* @__PURE__ */ jsx4(
|
|
2103
|
+
StarIcon,
|
|
2104
|
+
{
|
|
2105
|
+
className: cn(
|
|
2106
|
+
"h-3 w-3",
|
|
2107
|
+
tab === t && "fill-amber-400 text-amber-400"
|
|
2108
|
+
)
|
|
2109
|
+
}
|
|
2110
|
+
),
|
|
2111
|
+
t === "all" ? "All" : "Favorites",
|
|
2112
|
+
t === "favorites" && favoriteSet.size > 0 && /* @__PURE__ */ jsx4("span", { className: "text-muted-foreground", children: favoriteSet.size })
|
|
2113
|
+
]
|
|
2114
|
+
},
|
|
2115
|
+
t
|
|
2116
|
+
)) }),
|
|
2117
|
+
/* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-[16px_20px_minmax(0,1fr)_2.75rem_3rem_2.75rem] gap-2 border-b border-border px-2 py-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: [
|
|
2118
|
+
/* @__PURE__ */ jsx4("span", { className: "w-4" }),
|
|
2119
|
+
/* @__PURE__ */ jsx4("span", { className: "w-5", title: "Maker", "aria-label": "Maker" }),
|
|
2120
|
+
/* @__PURE__ */ jsx4("span", { children: "Name" }),
|
|
2121
|
+
/* @__PURE__ */ jsx4("span", { className: "w-11 text-right", children: "Speed" }),
|
|
2122
|
+
/* @__PURE__ */ jsx4(DelayedHint, { label: "How many tokens this model can hold in one conversation", children: /* @__PURE__ */ jsx4("span", { className: "block w-12 text-right", title: "Context window", children: "Window" }) }),
|
|
2123
|
+
/* @__PURE__ */ jsx4(DelayedHint, { label: "Relative cost band \u2014 more $ is more expensive. Not your personal usage.", children: /* @__PURE__ */ jsx4("span", { className: "block w-[2.75rem] text-right", children: "Cost" }) })
|
|
2124
|
+
] }),
|
|
2125
|
+
/* @__PURE__ */ jsx4("div", { className: "min-h-0 flex-1 overflow-y-auto p-1", children: error ? /* @__PURE__ */ jsxs3("div", { className: "p-3 text-xs text-destructive", children: [
|
|
2126
|
+
/* @__PURE__ */ jsxs3("div", { className: "font-medium", children: [
|
|
2127
|
+
"Failed to load ",
|
|
2128
|
+
variant,
|
|
2129
|
+
" catalog"
|
|
2130
|
+
] }),
|
|
2131
|
+
/* @__PURE__ */ jsx4("div", { className: "mt-0.5 font-mono text-[11px] opacity-80", children: error }),
|
|
2132
|
+
variant === "admin" && /* @__PURE__ */ jsx4("div", { className: "mt-1 text-[11px] text-muted-foreground", children: "If this is a 42501, the admin_model_catalog RPC rejected your role (super admin required)." }),
|
|
2133
|
+
ports.renderErrorAction?.(void 0)
|
|
2134
|
+
] }) : isLoading ? /* @__PURE__ */ jsx4("div", { className: "p-4 text-center text-xs text-muted-foreground", children: "Loading catalog\u2026" }) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2135
|
+
emptyOptionLabel && onClear && /* @__PURE__ */ jsx4(
|
|
2136
|
+
"button",
|
|
2137
|
+
{
|
|
2138
|
+
type: "button",
|
|
2139
|
+
onClick: handleClear,
|
|
2140
|
+
className: cn(
|
|
2141
|
+
"mb-1 w-full rounded px-2 py-1.5 text-left text-xs transition-colors hover:bg-muted/60 focus:bg-muted/60 focus:outline-none",
|
|
2142
|
+
!value ? "bg-muted font-medium text-foreground" : "text-muted-foreground"
|
|
2143
|
+
),
|
|
2144
|
+
children: emptyOptionLabel
|
|
2145
|
+
}
|
|
2146
|
+
),
|
|
2147
|
+
localRows.length > 0 && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2148
|
+
/* @__PURE__ */ jsx4("div", { className: GROUP_HEADING, children: localGroupLabel }),
|
|
2149
|
+
localRows.map((l) => /* @__PURE__ */ jsx4(LocalModelRow, { model: l, selected: l.id === value, onSelect: () => handleSelectLocal(l) }, l.id)),
|
|
2150
|
+
filtered.length > 0 && /* @__PURE__ */ jsx4("div", { className: GROUP_HEADING, children: "Cloud" })
|
|
2151
|
+
] }),
|
|
2152
|
+
filtered.length === 0 ? localRows.length > 0 ? null : /* @__PURE__ */ jsx4("div", { className: "p-4 text-center text-xs text-muted-foreground", children: "No models match your filters." }) : listRows.map(({ model: m, classTier }) => /* @__PURE__ */ jsx4(
|
|
2153
|
+
ModelRow,
|
|
2154
|
+
{
|
|
2155
|
+
model: m,
|
|
2156
|
+
classTier,
|
|
2157
|
+
tier: costRatingTier(m.costRating),
|
|
2158
|
+
variant,
|
|
2159
|
+
selected: m.id === value && (classTier == null || classTier.offeringId === selectedClass?.offeringId),
|
|
2160
|
+
isFavorite: favoriteSet.has(m.id),
|
|
2161
|
+
locked: !canUseTopTier && isTopTierRating(m.costRating),
|
|
2162
|
+
onToggleFavorite: () => toggleFavorite(m.id),
|
|
2163
|
+
onSelect: () => isMobile ? (setMobileDetail(m), setMobileDetailClass(classTier)) : handleSelectClass(m, classTier),
|
|
2164
|
+
onHover: isMobile ? void 0 : () => {
|
|
2165
|
+
setHovered(m);
|
|
2166
|
+
setHoveredClass(classTier);
|
|
2167
|
+
if (rightPanel !== "filters") setRightPanel("detail");
|
|
2168
|
+
}
|
|
2169
|
+
},
|
|
2170
|
+
classTier ? `${m.id}:${classTier.offeringId}` : m.id
|
|
2171
|
+
))
|
|
2172
|
+
] }) }),
|
|
2173
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between gap-2 border-t border-border px-2 py-1 text-[10px] text-muted-foreground", children: [
|
|
2174
|
+
/* @__PURE__ */ jsx4("span", { children: error ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2175
|
+
"Models couldn't be loaded",
|
|
2176
|
+
ports.renderErrorAction?.(String(error))
|
|
2177
|
+
] }) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2178
|
+
listRows.length + localRows.length,
|
|
2179
|
+
" model",
|
|
2180
|
+
listRows.length + localRows.length === 1 ? "" : "s",
|
|
2181
|
+
variant === "user" && (hiddenModelIds?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2182
|
+
" \xB7 ",
|
|
2183
|
+
ports.settingsHref && LinkComponent ? /* @__PURE__ */ jsxs3(LinkComponent, { href: ports.settingsHref, className: "underline hover:text-foreground", children: [
|
|
2184
|
+
hiddenModelIds?.length,
|
|
2185
|
+
" hidden by you"
|
|
2186
|
+
] }) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2187
|
+
hiddenModelIds?.length,
|
|
2188
|
+
" hidden by you"
|
|
2189
|
+
] })
|
|
2190
|
+
] }) : null
|
|
2191
|
+
] }) }),
|
|
2192
|
+
isSuperAdmin && catalogVariant == null && /* @__PURE__ */ jsxs3(
|
|
2193
|
+
"button",
|
|
2194
|
+
{
|
|
2195
|
+
type: "button",
|
|
2196
|
+
onClick: () => setVariantMode(variant !== "admin"),
|
|
2197
|
+
title: variant === "admin" ? "Admin view \u2014 real vendor/api/$ data. Click to return to the user view." : "Switch to the admin view (real vendor/api/$ data)",
|
|
2198
|
+
className: cn(
|
|
2199
|
+
"inline-flex items-center gap-1 rounded px-1.5 py-0.5 transition-colors",
|
|
2200
|
+
variant === "admin" ? "bg-primary/10 text-foreground" : "hover:text-foreground"
|
|
2201
|
+
),
|
|
2202
|
+
children: [
|
|
2203
|
+
/* @__PURE__ */ jsx4(ShieldIcon, { className: "h-3 w-3" }),
|
|
2204
|
+
"Admin"
|
|
2205
|
+
]
|
|
2206
|
+
}
|
|
2207
|
+
)
|
|
2208
|
+
] })
|
|
2209
|
+
] });
|
|
2210
|
+
if (disabled) {
|
|
2211
|
+
return trigger;
|
|
2212
|
+
}
|
|
2213
|
+
const mobileBody = /* @__PURE__ */ jsx4("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: mobileDetail ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2214
|
+
/* @__PURE__ */ jsxs3(
|
|
2215
|
+
"button",
|
|
2216
|
+
{
|
|
2217
|
+
onClick: () => setMobileDetail(null),
|
|
2218
|
+
className: "flex shrink-0 items-center gap-1.5 border-b border-border px-3 py-2.5 text-sm font-medium text-primary",
|
|
2219
|
+
children: [
|
|
2220
|
+
/* @__PURE__ */ jsx4(ChevronRightIcon, { className: "h-4 w-4 rotate-180" }),
|
|
2221
|
+
" Back"
|
|
2222
|
+
]
|
|
2223
|
+
}
|
|
2224
|
+
),
|
|
2225
|
+
/* @__PURE__ */ jsx4("div", { className: "min-h-0 flex-1 overflow-y-auto", children: /* @__PURE__ */ jsx4(
|
|
2226
|
+
ModelDetailCard,
|
|
2227
|
+
{
|
|
2228
|
+
model: mobileDetail,
|
|
2229
|
+
tier: costRatingTier(mobileDetail.costRating),
|
|
2230
|
+
variant,
|
|
2231
|
+
onSelect: () => handleSelect(mobileDetail.id, mobileDetailClass),
|
|
2232
|
+
isCurrentModel: mobileDetail.id === value,
|
|
2233
|
+
pinnedOfferingId,
|
|
2234
|
+
onPinOffering: onOfferingPinChange ? handlePinOffering : void 0,
|
|
2235
|
+
includeAdminSection: true
|
|
2236
|
+
}
|
|
2237
|
+
) })
|
|
2238
|
+
] }) : mobileFilters ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2239
|
+
/* @__PURE__ */ jsxs3(
|
|
2240
|
+
"button",
|
|
2241
|
+
{
|
|
2242
|
+
onClick: () => setMobileFilters(false),
|
|
2243
|
+
className: "flex shrink-0 items-center gap-1.5 border-b border-border px-3 py-2.5 text-sm font-medium text-primary",
|
|
2244
|
+
children: [
|
|
2245
|
+
/* @__PURE__ */ jsx4(ChevronRightIcon, { className: "h-4 w-4 rotate-180" }),
|
|
2246
|
+
" Back"
|
|
2247
|
+
]
|
|
2248
|
+
}
|
|
2249
|
+
),
|
|
2250
|
+
/* @__PURE__ */ jsx4("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx4(
|
|
2251
|
+
FiltersPanel,
|
|
2252
|
+
{
|
|
2253
|
+
filters,
|
|
2254
|
+
setFilters,
|
|
2255
|
+
variant,
|
|
2256
|
+
makerOptions,
|
|
2257
|
+
serviceOptions,
|
|
2258
|
+
vendorOptions,
|
|
2259
|
+
apiOptions
|
|
2260
|
+
}
|
|
2261
|
+
) })
|
|
2262
|
+
] }) : listPanel });
|
|
2263
|
+
if (isMobile && inline) {
|
|
2264
|
+
return /* @__PURE__ */ jsx4(TooltipProvider, { delayDuration: HOVER_DELAY_MS, skipDelayDuration: HOVER_DELAY_MS, children: mobileBody });
|
|
2265
|
+
}
|
|
2266
|
+
if (isMobile) {
|
|
2267
|
+
return /* @__PURE__ */ jsxs3(Drawer, { open, onOpenChange: handleOpen, children: [
|
|
2268
|
+
/* @__PURE__ */ jsx4(DrawerTrigger, { asChild: true, children: trigger }),
|
|
2269
|
+
/* @__PURE__ */ jsx4(DrawerContent, { className: "h-[85dvh]", children: /* @__PURE__ */ jsxs3(
|
|
2270
|
+
TooltipProvider,
|
|
2271
|
+
{
|
|
2272
|
+
delayDuration: HOVER_DELAY_MS,
|
|
2273
|
+
skipDelayDuration: HOVER_DELAY_MS,
|
|
2274
|
+
children: [
|
|
2275
|
+
/* @__PURE__ */ jsx4(DrawerTitle, { className: "sr-only", children: "Select model" }),
|
|
2276
|
+
mobileBody
|
|
2277
|
+
]
|
|
2278
|
+
}
|
|
2279
|
+
) })
|
|
2280
|
+
] });
|
|
2281
|
+
}
|
|
2282
|
+
const popoverWidth = LIST_WIDTH + DETAIL_WIDTH + (variant === "admin" ? ADMIN_PANEL_WIDTH : 0);
|
|
2283
|
+
const adminPanelModel = hovered ?? selected;
|
|
2284
|
+
const desktopBody = /* @__PURE__ */ jsx4(
|
|
2285
|
+
TooltipProvider,
|
|
2286
|
+
{
|
|
2287
|
+
delayDuration: HOVER_DELAY_MS,
|
|
2288
|
+
skipDelayDuration: HOVER_DELAY_MS,
|
|
2289
|
+
children: /* @__PURE__ */ jsx4("div", { className: "h-full overflow-x-auto overflow-y-hidden", children: /* @__PURE__ */ jsxs3(
|
|
2290
|
+
"div",
|
|
2291
|
+
{
|
|
2292
|
+
className: "flex h-full",
|
|
2293
|
+
style: inline ? void 0 : { minWidth: popoverWidth },
|
|
2294
|
+
children: [
|
|
2295
|
+
/* @__PURE__ */ jsx4(
|
|
2296
|
+
"div",
|
|
2297
|
+
{
|
|
2298
|
+
className: "flex h-full min-h-0 flex-col border-r border-border",
|
|
2299
|
+
style: inline ? { flex: `0 1 ${LIST_WIDTH}px`, minWidth: INLINE_LIST_MIN_WIDTH } : { width: LIST_WIDTH, flexShrink: 0 },
|
|
2300
|
+
children: listPanel
|
|
2301
|
+
}
|
|
2302
|
+
),
|
|
2303
|
+
/* @__PURE__ */ jsx4(
|
|
2304
|
+
"div",
|
|
2305
|
+
{
|
|
2306
|
+
className: "flex h-full min-h-0 flex-col overflow-hidden",
|
|
2307
|
+
style: inline ? { flex: "1 1 0", minWidth: INLINE_DETAIL_MIN_WIDTH } : { width: DETAIL_WIDTH, flexShrink: 0 },
|
|
2308
|
+
children: rightPanel === "filters" ? /* @__PURE__ */ jsx4(
|
|
2309
|
+
FiltersPanel,
|
|
2310
|
+
{
|
|
2311
|
+
filters,
|
|
2312
|
+
setFilters,
|
|
2313
|
+
variant,
|
|
2314
|
+
makerOptions,
|
|
2315
|
+
serviceOptions,
|
|
2316
|
+
vendorOptions,
|
|
2317
|
+
apiOptions
|
|
2318
|
+
}
|
|
2319
|
+
) : rightPanel === "detail" && hovered ? /* @__PURE__ */ jsx4(
|
|
2320
|
+
"div",
|
|
2321
|
+
{
|
|
2322
|
+
className: "h-full animate-in fade-in-0 duration-300",
|
|
2323
|
+
children: /* @__PURE__ */ jsx4(
|
|
2324
|
+
ModelDetailCard,
|
|
2325
|
+
{
|
|
2326
|
+
model: hovered,
|
|
2327
|
+
tier: costRatingTier(hovered.costRating),
|
|
2328
|
+
variant,
|
|
2329
|
+
onSelect: () => handleSelect(hovered.id, hoveredClass),
|
|
2330
|
+
isCurrentModel: hovered.id === value,
|
|
2331
|
+
pinnedOfferingId,
|
|
2332
|
+
onPinOffering: onOfferingPinChange ? handlePinOffering : void 0
|
|
2333
|
+
}
|
|
2334
|
+
)
|
|
2335
|
+
},
|
|
2336
|
+
hovered.id
|
|
2337
|
+
) : /* @__PURE__ */ jsxs3("div", { className: "flex flex-1 flex-col items-center justify-center gap-2 px-6 text-center", children: [
|
|
2338
|
+
/* @__PURE__ */ jsx4(MousePointerClickIcon, { className: "h-6 w-6 text-muted-foreground/40" }),
|
|
2339
|
+
/* @__PURE__ */ jsx4("p", { className: "text-xs leading-relaxed text-muted-foreground/70", children: "Hover a model to preview its details, or click to select." })
|
|
2340
|
+
] })
|
|
2341
|
+
}
|
|
2342
|
+
),
|
|
2343
|
+
variant === "admin" && /* @__PURE__ */ jsx4(
|
|
2344
|
+
"div",
|
|
2345
|
+
{
|
|
2346
|
+
className: "flex h-full min-h-0 shrink-0 flex-col overflow-hidden border-l border-border",
|
|
2347
|
+
style: { width: ADMIN_PANEL_WIDTH },
|
|
2348
|
+
children: adminPanelModel ? /* @__PURE__ */ jsx4(AdminOfferingsSection, { model: adminPanelModel }) : /* @__PURE__ */ jsxs3("div", { className: "flex flex-1 flex-col items-center justify-center gap-2 px-6 text-center", children: [
|
|
2349
|
+
/* @__PURE__ */ jsx4(ShieldIcon, { className: "h-6 w-6 text-muted-foreground/40" }),
|
|
2350
|
+
/* @__PURE__ */ jsx4("p", { className: "text-xs leading-relaxed text-muted-foreground/70", children: "Hover a model to see every offering's real vendor, api, provider model id and $ pricing." })
|
|
2351
|
+
] })
|
|
2352
|
+
}
|
|
2353
|
+
)
|
|
2354
|
+
]
|
|
2355
|
+
}
|
|
2356
|
+
) })
|
|
2357
|
+
}
|
|
2358
|
+
);
|
|
2359
|
+
if (inline) {
|
|
2360
|
+
return /* @__PURE__ */ jsx4("div", { className: "h-full w-full min-w-0", children: desktopBody });
|
|
2361
|
+
}
|
|
2362
|
+
return /* @__PURE__ */ jsxs3(Popover, { open, onOpenChange: handleOpen, modal: false, children: [
|
|
2363
|
+
/* @__PURE__ */ jsx4(PopoverTrigger, { asChild: true, children: trigger }),
|
|
2364
|
+
/* @__PURE__ */ jsx4(
|
|
2365
|
+
PopoverContent,
|
|
2366
|
+
{
|
|
2367
|
+
align: "start",
|
|
2368
|
+
sideOffset: 4,
|
|
2369
|
+
collisionPadding: 12,
|
|
2370
|
+
sticky: "always",
|
|
2371
|
+
...dialogContainer ? { container: dialogContainer } : {},
|
|
2372
|
+
className: "overflow-hidden p-0",
|
|
2373
|
+
style: {
|
|
2374
|
+
// PopoverContent's 1px border is inside this border-box width.
|
|
2375
|
+
// Give the fixed columns those two pixels at their natural desktop width;
|
|
2376
|
+
// maxWidth still turns the inner panel into a horizontal scrollport.
|
|
2377
|
+
width: popoverWidth + 2,
|
|
2378
|
+
maxWidth: "calc(100vw - 24px)",
|
|
2379
|
+
height: PANEL_HEIGHT,
|
|
2380
|
+
// See LIST_MAX_HEIGHT — this clamp is what keeps the search row on
|
|
2381
|
+
// screen at an 800px-tall window.
|
|
2382
|
+
maxHeight: LIST_MAX_HEIGHT
|
|
2383
|
+
},
|
|
2384
|
+
children: desktopBody
|
|
2385
|
+
}
|
|
2386
|
+
)
|
|
2387
|
+
] });
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
// settings/settings-catalogue.ts
|
|
2391
|
+
import { humanizeIdentifier } from "@ai-matrx/kit/text-case";
|
|
2392
|
+
var CONTROL_TYPES = [
|
|
2393
|
+
"number",
|
|
2394
|
+
"integer",
|
|
2395
|
+
"boolean",
|
|
2396
|
+
"string",
|
|
2397
|
+
"enum",
|
|
2398
|
+
"array",
|
|
2399
|
+
"string_array",
|
|
2400
|
+
"object_array"
|
|
2401
|
+
];
|
|
2402
|
+
function isControlDefinitionShape(value) {
|
|
2403
|
+
return typeof value.type === "string" && CONTROL_TYPES.includes(value.type);
|
|
2404
|
+
}
|
|
2405
|
+
var TEXT_GROUP = [
|
|
2406
|
+
{ key: "response_format", label: "Response Format" },
|
|
2407
|
+
{ key: "stop_sequences", label: "Stop Sequences" },
|
|
2408
|
+
{ key: "temperature", label: "Temperature" },
|
|
2409
|
+
{ key: "max_output_tokens", label: "Max Output Tokens" },
|
|
2410
|
+
{ key: "top_p", label: "Top P" },
|
|
2411
|
+
{ key: "top_k", label: "Top K" },
|
|
2412
|
+
{ key: "thinking_budget", label: "Thinking Budget" },
|
|
2413
|
+
{ key: "thinking_level", label: "Thinking Level" },
|
|
2414
|
+
{ key: "reasoning_effort", label: "Reasoning Effort" },
|
|
2415
|
+
{ key: "reasoning_summary", label: "Reasoning Summary" },
|
|
2416
|
+
// Deep Research agents: charts and images inside the report.
|
|
2417
|
+
{ key: "visualization", label: "Charts and Images" },
|
|
2418
|
+
{ key: "verbosity", label: "Verbosity" },
|
|
2419
|
+
{ key: "tool_choice", label: "Tool Choice" }
|
|
2420
|
+
];
|
|
2421
|
+
var FEATURE_FLAGS_GROUP = [
|
|
2422
|
+
{ key: "stream", label: "Stream Response" },
|
|
2423
|
+
{ key: "store", label: "Store Conversation" },
|
|
2424
|
+
{ key: "parallel_tool_calls", label: "Parallel Tool Calls" },
|
|
2425
|
+
{ key: "include_thoughts", label: "Include Thoughts" },
|
|
2426
|
+
{ key: "internal_web_search", label: "Internal Web Search" },
|
|
2427
|
+
{ key: "internal_url_context", label: "Internal URL Context" },
|
|
2428
|
+
{ key: "disable_safety_checker", label: "Disable Safety Checker" },
|
|
2429
|
+
{ key: "clear_thinking", label: "Clear Thinking" },
|
|
2430
|
+
{ key: "disable_reasoning", label: "Disable Reasoning" },
|
|
2431
|
+
{ key: "generate_audio", label: "Generate Audio" },
|
|
2432
|
+
{ key: "enhance_prompt", label: "Enhance Prompt" },
|
|
2433
|
+
{ key: "include_rai_reason", label: "Include RAI Reason" }
|
|
2434
|
+
];
|
|
2435
|
+
var IMAGE_VIDEO_GROUP = [
|
|
2436
|
+
{ key: "size", label: "Size" },
|
|
2437
|
+
{ key: "quality", label: "Quality" },
|
|
2438
|
+
{ key: "count", label: "Count" },
|
|
2439
|
+
{ key: "steps", label: "Steps" },
|
|
2440
|
+
{ key: "guidance_scale", label: "Guidance Scale" },
|
|
2441
|
+
{ key: "seed", label: "Seed" },
|
|
2442
|
+
{ key: "width", label: "Width" },
|
|
2443
|
+
{ key: "height", label: "Height" },
|
|
2444
|
+
{ key: "fps", label: "FPS" },
|
|
2445
|
+
{ key: "seconds", label: "Duration (s) [legacy string]" },
|
|
2446
|
+
{ key: "output_quality", label: "Output Quality" },
|
|
2447
|
+
{ key: "negative_prompt", label: "Negative Prompt" },
|
|
2448
|
+
{ key: "aspect_ratio", label: "Aspect Ratio" },
|
|
2449
|
+
{ key: "ratio", label: "Aspect Ratio (Together/Runway)" },
|
|
2450
|
+
{ key: "resolution", label: "Resolution" },
|
|
2451
|
+
{ key: "image_size", label: "Image Size" },
|
|
2452
|
+
{ key: "num_outputs", label: "Outputs" },
|
|
2453
|
+
{ key: "number_of_images", label: "Number of Images" },
|
|
2454
|
+
{ key: "render_quality", label: "Render Quality" },
|
|
2455
|
+
{ key: "background", label: "Background" },
|
|
2456
|
+
{ key: "input_fidelity", label: "Input Fidelity" },
|
|
2457
|
+
{ key: "output_compression", label: "Output Compression" },
|
|
2458
|
+
{ key: "moderation", label: "Moderation" },
|
|
2459
|
+
{ key: "partial_images", label: "Partial Images" },
|
|
2460
|
+
{ key: "output_mime_type", label: "Output MIME Type" },
|
|
2461
|
+
{ key: "person_generation", label: "Person Generation" },
|
|
2462
|
+
{ key: "image_format", label: "Image Format" },
|
|
2463
|
+
{ key: "style", label: "Style" },
|
|
2464
|
+
{ key: "reference_strength", label: "Reference Strength" },
|
|
2465
|
+
{ key: "duration_seconds", label: "Duration (s)" },
|
|
2466
|
+
{ key: "duration", label: "Duration" },
|
|
2467
|
+
{ key: "encode_quality", label: "Encode Quality" },
|
|
2468
|
+
{ key: "video_action", label: "Video Action" },
|
|
2469
|
+
{ key: "reference_images", label: "Reference Images" },
|
|
2470
|
+
{ key: "frame_images", label: "Frame Images" },
|
|
2471
|
+
{ key: "image_loras", label: "Image LoRAs" }
|
|
2472
|
+
];
|
|
2473
|
+
var AUDIO_GROUP = [
|
|
2474
|
+
{ key: "tts_voice", label: "Voice" },
|
|
2475
|
+
{ key: "performance_direction", label: "Performance Direction" },
|
|
2476
|
+
{ key: "speech_speed", label: "Speed" },
|
|
2477
|
+
{ key: "turn_pause_ms", label: "Pause Between Turns (ms)" },
|
|
2478
|
+
{ key: "language_code", label: "Language" },
|
|
2479
|
+
{ key: "audio_format", label: "Audio Format" }
|
|
2480
|
+
];
|
|
2481
|
+
var SETTINGS_CATALOGUE = [
|
|
2482
|
+
{ id: "text", label: "", entries: TEXT_GROUP },
|
|
2483
|
+
{ id: "featureFlags", label: "Feature Flags", entries: FEATURE_FLAGS_GROUP },
|
|
2484
|
+
{ id: "imageVideo", label: "Image / Video Settings", entries: IMAGE_VIDEO_GROUP },
|
|
2485
|
+
{ id: "audio", label: "Audio Settings", entries: AUDIO_GROUP }
|
|
2486
|
+
];
|
|
2487
|
+
var CATALOGUE_KEYS = new Set(
|
|
2488
|
+
SETTINGS_CATALOGUE.flatMap((g) => g.entries.map((e) => e.key))
|
|
2489
|
+
);
|
|
2490
|
+
var CATCHALL_EXCLUDED = /* @__PURE__ */ new Set([
|
|
2491
|
+
"rawControls",
|
|
2492
|
+
"unmappedControls",
|
|
2493
|
+
"model_id",
|
|
2494
|
+
"model",
|
|
2495
|
+
// chosen via the dedicated model picker, never a generic settings row
|
|
2496
|
+
"multi_speaker",
|
|
2497
|
+
// edited via the Voice editor alongside tts_voice
|
|
2498
|
+
// Model-gated UI flags live in the ui_gates column + UiGatesEditor, never as
|
|
2499
|
+
// settings rows — even when the model declares them as controls (e.g. every
|
|
2500
|
+
// model now declares `tools` for the tool-support capability).
|
|
2501
|
+
...UI_GATE_KEYS
|
|
2502
|
+
]);
|
|
2503
|
+
function lookupControl(controls, key) {
|
|
2504
|
+
if (!controls) return null;
|
|
2505
|
+
if (CATCHALL_EXCLUDED.has(key)) {
|
|
2506
|
+
if (key === "rawControls" || key === "unmappedControls") return null;
|
|
2507
|
+
}
|
|
2508
|
+
const candidate = controls[key];
|
|
2509
|
+
if (candidate && typeof candidate === "object" && !Array.isArray(candidate)) {
|
|
2510
|
+
const c = candidate;
|
|
2511
|
+
if (isControlDefinitionShape(c)) {
|
|
2512
|
+
return c;
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
return null;
|
|
2516
|
+
}
|
|
2517
|
+
function hasMeaningfulValue(settings, key) {
|
|
2518
|
+
if (!settings) return false;
|
|
2519
|
+
const v = settings[key];
|
|
2520
|
+
return v !== void 0 && v !== null;
|
|
2521
|
+
}
|
|
2522
|
+
function buildSettingsRows(controls, settings) {
|
|
2523
|
+
const groups = SETTINGS_CATALOGUE.map((group) => ({
|
|
2524
|
+
id: group.id,
|
|
2525
|
+
label: group.label,
|
|
2526
|
+
rows: group.entries.flatMap((entry) => {
|
|
2527
|
+
const control = lookupControl(controls, entry.key);
|
|
2528
|
+
if (!control) return [];
|
|
2529
|
+
return [
|
|
2530
|
+
{
|
|
2531
|
+
key: entry.key,
|
|
2532
|
+
label: entry.label,
|
|
2533
|
+
group: group.id,
|
|
2534
|
+
control,
|
|
2535
|
+
supported: true,
|
|
2536
|
+
hasValue: hasMeaningfulValue(settings, entry.key)
|
|
2537
|
+
}
|
|
2538
|
+
];
|
|
2539
|
+
})
|
|
2540
|
+
}));
|
|
2541
|
+
const declaredExtra = [];
|
|
2542
|
+
if (controls) {
|
|
2543
|
+
for (const key of Object.keys(controls)) {
|
|
2544
|
+
if (CATALOGUE_KEYS.has(key) || CATCHALL_EXCLUDED.has(key)) continue;
|
|
2545
|
+
if (lookupControl(controls, key)) declaredExtra.push(key);
|
|
521
2546
|
}
|
|
522
|
-
|
|
2547
|
+
}
|
|
2548
|
+
if (declaredExtra.length > 0) {
|
|
2549
|
+
const rows = declaredExtra.sort().map((key) => ({
|
|
2550
|
+
key,
|
|
2551
|
+
label: humanizeIdentifier(key),
|
|
2552
|
+
group: "other",
|
|
2553
|
+
control: lookupControl(controls, key),
|
|
2554
|
+
supported: true,
|
|
2555
|
+
hasValue: hasMeaningfulValue(settings, key)
|
|
2556
|
+
}));
|
|
2557
|
+
groups.push({ id: "other", label: "Other Settings", rows });
|
|
2558
|
+
}
|
|
2559
|
+
return groups;
|
|
2560
|
+
}
|
|
2561
|
+
var CATALOGUE_LABELS = new Map(
|
|
2562
|
+
SETTINGS_CATALOGUE.flatMap((g) => g.entries.map((e) => [e.key, e.label]))
|
|
2563
|
+
);
|
|
2564
|
+
function settingLabel(key) {
|
|
2565
|
+
return CATALOGUE_LABELS.get(key) ?? humanizeIdentifier(key);
|
|
2566
|
+
}
|
|
2567
|
+
var RECOGNIZED_PARAMS = new Set(LLM_PARAMS_KEYS);
|
|
2568
|
+
var EXTRA_EXCLUDED = /* @__PURE__ */ new Set([
|
|
2569
|
+
...CATCHALL_EXCLUDED,
|
|
2570
|
+
"offering_id",
|
|
2571
|
+
"max_tokens",
|
|
2572
|
+
"output_format",
|
|
2573
|
+
"n"
|
|
2574
|
+
]);
|
|
2575
|
+
function extraSettingKeys(controls, settings, alsoKeys = []) {
|
|
2576
|
+
const out = { translated: [], unsupported: [] };
|
|
2577
|
+
if (!controls) return out;
|
|
2578
|
+
const declaresAny = Object.keys(controls).some((key) => lookupControl(controls, key) !== null);
|
|
2579
|
+
if (!declaresAny) return out;
|
|
2580
|
+
const keys = new Set(Object.keys(settings ?? {}).filter((key) => hasMeaningfulValue(settings, key)));
|
|
2581
|
+
for (const key of alsoKeys) keys.add(key);
|
|
2582
|
+
for (const key of keys) {
|
|
2583
|
+
if (EXTRA_EXCLUDED.has(key) || lookupControl(controls, key)) continue;
|
|
2584
|
+
(RECOGNIZED_PARAMS.has(key) ? out.translated : out.unsupported).push(key);
|
|
2585
|
+
}
|
|
2586
|
+
return out;
|
|
2587
|
+
}
|
|
2588
|
+
|
|
2589
|
+
// settings/setting-state.ts
|
|
2590
|
+
var ENUM_OFF_VALUE = "none";
|
|
2591
|
+
function isOffValue(value, control) {
|
|
2592
|
+
if (value === false) return true;
|
|
2593
|
+
if (value === ENUM_OFF_VALUE) {
|
|
2594
|
+
return !control || control.type === "enum";
|
|
2595
|
+
}
|
|
2596
|
+
return false;
|
|
523
2597
|
}
|
|
524
2598
|
|
|
525
2599
|
// settings/react/InputCapabilitiesEditor.tsx
|
|
526
|
-
import { ErrorBox
|
|
527
|
-
import { Button } from "@ai-matrx/design-system/controls";
|
|
2600
|
+
import { ErrorBox } from "@ai-matrx/design-system";
|
|
2601
|
+
import { Button, Switch } from "@ai-matrx/design-system/controls";
|
|
528
2602
|
|
|
529
2603
|
// settings/react/settings-icons.tsx
|
|
530
|
-
import { jsx as
|
|
531
|
-
function
|
|
532
|
-
return /* @__PURE__ */
|
|
2604
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2605
|
+
function Svg3({ className, children }) {
|
|
2606
|
+
return /* @__PURE__ */ jsx5(
|
|
533
2607
|
"svg",
|
|
534
2608
|
{
|
|
535
2609
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -545,98 +2619,98 @@ function Svg({ className, children }) {
|
|
|
545
2619
|
}
|
|
546
2620
|
);
|
|
547
2621
|
}
|
|
548
|
-
var CircleCheckGlyph = ({ className }) => /* @__PURE__ */
|
|
549
|
-
/* @__PURE__ */
|
|
550
|
-
/* @__PURE__ */
|
|
2622
|
+
var CircleCheckGlyph = ({ className }) => /* @__PURE__ */ jsxs4(Svg3, { className, children: [
|
|
2623
|
+
/* @__PURE__ */ jsx5("circle", { cx: "12", cy: "12", r: "10" }),
|
|
2624
|
+
/* @__PURE__ */ jsx5("path", { d: "m16 9-5.5 5.5L8 12" })
|
|
551
2625
|
] });
|
|
552
|
-
var TriangleAlertGlyph = ({ className }) => /* @__PURE__ */
|
|
553
|
-
/* @__PURE__ */
|
|
554
|
-
/* @__PURE__ */
|
|
555
|
-
/* @__PURE__ */
|
|
2626
|
+
var TriangleAlertGlyph = ({ className }) => /* @__PURE__ */ jsxs4(Svg3, { className, children: [
|
|
2627
|
+
/* @__PURE__ */ jsx5("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }),
|
|
2628
|
+
/* @__PURE__ */ jsx5("path", { d: "M12 9v4" }),
|
|
2629
|
+
/* @__PURE__ */ jsx5("path", { d: "M12 17h.01" })
|
|
556
2630
|
] });
|
|
557
|
-
var VariableGlyph = ({ className }) => /* @__PURE__ */
|
|
558
|
-
/* @__PURE__ */
|
|
559
|
-
/* @__PURE__ */
|
|
560
|
-
/* @__PURE__ */
|
|
561
|
-
/* @__PURE__ */
|
|
2631
|
+
var VariableGlyph = ({ className }) => /* @__PURE__ */ jsxs4(Svg3, { className, children: [
|
|
2632
|
+
/* @__PURE__ */ jsx5("path", { d: "M8 21s-4-3-4-9 4-9 4-9" }),
|
|
2633
|
+
/* @__PURE__ */ jsx5("path", { d: "M16 3s4 3 4 9-4 9-4 9" }),
|
|
2634
|
+
/* @__PURE__ */ jsx5("line", { x1: "15", x2: "9", y1: "9", y2: "15" }),
|
|
2635
|
+
/* @__PURE__ */ jsx5("line", { x1: "9", x2: "15", y1: "9", y2: "15" })
|
|
562
2636
|
] });
|
|
563
|
-
var UnlinkGlyph = ({ className }) => /* @__PURE__ */
|
|
564
|
-
/* @__PURE__ */
|
|
565
|
-
/* @__PURE__ */
|
|
566
|
-
/* @__PURE__ */
|
|
567
|
-
/* @__PURE__ */
|
|
568
|
-
/* @__PURE__ */
|
|
569
|
-
/* @__PURE__ */
|
|
2637
|
+
var UnlinkGlyph = ({ className }) => /* @__PURE__ */ jsxs4(Svg3, { className, children: [
|
|
2638
|
+
/* @__PURE__ */ jsx5("path", { d: "m18.84 12.25 1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07 5.006 5.006 0 0 0-6.95 0l-1.72 1.71" }),
|
|
2639
|
+
/* @__PURE__ */ jsx5("path", { d: "m5.17 11.75-1.71 1.71a5.004 5.004 0 0 0 .12 7.07 5.006 5.006 0 0 0 6.95 0l1.71-1.71" }),
|
|
2640
|
+
/* @__PURE__ */ jsx5("line", { x1: "8", x2: "8", y1: "2", y2: "5" }),
|
|
2641
|
+
/* @__PURE__ */ jsx5("line", { x1: "2", x2: "5", y1: "8", y2: "8" }),
|
|
2642
|
+
/* @__PURE__ */ jsx5("line", { x1: "16", x2: "16", y1: "19", y2: "22" }),
|
|
2643
|
+
/* @__PURE__ */ jsx5("line", { x1: "19", x2: "22", y1: "16", y2: "16" })
|
|
570
2644
|
] });
|
|
571
|
-
var WrenchGlyph = ({ className }) => /* @__PURE__ */
|
|
572
|
-
var Trash2Glyph = ({ className }) => /* @__PURE__ */
|
|
573
|
-
/* @__PURE__ */
|
|
574
|
-
/* @__PURE__ */
|
|
575
|
-
/* @__PURE__ */
|
|
576
|
-
/* @__PURE__ */
|
|
577
|
-
/* @__PURE__ */
|
|
2645
|
+
var WrenchGlyph = ({ className }) => /* @__PURE__ */ jsx5(Svg3, { className, children: /* @__PURE__ */ jsx5("path", { d: "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z" }) });
|
|
2646
|
+
var Trash2Glyph = ({ className }) => /* @__PURE__ */ jsxs4(Svg3, { className, children: [
|
|
2647
|
+
/* @__PURE__ */ jsx5("path", { d: "M10 11v6" }),
|
|
2648
|
+
/* @__PURE__ */ jsx5("path", { d: "M14 11v6" }),
|
|
2649
|
+
/* @__PURE__ */ jsx5("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
|
|
2650
|
+
/* @__PURE__ */ jsx5("path", { d: "M3 6h18" }),
|
|
2651
|
+
/* @__PURE__ */ jsx5("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
|
|
578
2652
|
] });
|
|
579
|
-
var RotateCcwGlyph = ({ className }) => /* @__PURE__ */
|
|
580
|
-
/* @__PURE__ */
|
|
581
|
-
/* @__PURE__ */
|
|
2653
|
+
var RotateCcwGlyph = ({ className }) => /* @__PURE__ */ jsxs4(Svg3, { className, children: [
|
|
2654
|
+
/* @__PURE__ */ jsx5("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
|
|
2655
|
+
/* @__PURE__ */ jsx5("path", { d: "M3 3v5h5" })
|
|
582
2656
|
] });
|
|
583
|
-
var ImageGlyph = ({ className }) => /* @__PURE__ */
|
|
584
|
-
/* @__PURE__ */
|
|
585
|
-
/* @__PURE__ */
|
|
586
|
-
/* @__PURE__ */
|
|
2657
|
+
var ImageGlyph = ({ className }) => /* @__PURE__ */ jsxs4(Svg3, { className, children: [
|
|
2658
|
+
/* @__PURE__ */ jsx5("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
|
|
2659
|
+
/* @__PURE__ */ jsx5("circle", { cx: "9", cy: "9", r: "2" }),
|
|
2660
|
+
/* @__PURE__ */ jsx5("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
|
|
587
2661
|
] });
|
|
588
|
-
var FileTextGlyph = ({ className }) => /* @__PURE__ */
|
|
589
|
-
/* @__PURE__ */
|
|
590
|
-
/* @__PURE__ */
|
|
591
|
-
/* @__PURE__ */
|
|
592
|
-
/* @__PURE__ */
|
|
593
|
-
/* @__PURE__ */
|
|
2662
|
+
var FileTextGlyph = ({ className }) => /* @__PURE__ */ jsxs4(Svg3, { className, children: [
|
|
2663
|
+
/* @__PURE__ */ jsx5("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
|
|
2664
|
+
/* @__PURE__ */ jsx5("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" }),
|
|
2665
|
+
/* @__PURE__ */ jsx5("path", { d: "M10 9H8" }),
|
|
2666
|
+
/* @__PURE__ */ jsx5("path", { d: "M16 13H8" }),
|
|
2667
|
+
/* @__PURE__ */ jsx5("path", { d: "M16 17H8" })
|
|
594
2668
|
] });
|
|
595
|
-
var YoutubeGlyph = ({ className }) => /* @__PURE__ */
|
|
596
|
-
/* @__PURE__ */
|
|
597
|
-
/* @__PURE__ */
|
|
2669
|
+
var YoutubeGlyph = ({ className }) => /* @__PURE__ */ jsxs4(Svg3, { className, children: [
|
|
2670
|
+
/* @__PURE__ */ jsx5("path", { d: "M2.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.55 49.55 0 0 1-16.2 0A2 2 0 0 1 2.5 17" }),
|
|
2671
|
+
/* @__PURE__ */ jsx5("path", { d: "m10 15 5-3-5-3z" })
|
|
598
2672
|
] });
|
|
599
2673
|
|
|
600
2674
|
// settings/react/SettingRowFrame.tsx
|
|
601
|
-
import { Label
|
|
602
|
-
import { jsx as
|
|
603
|
-
var
|
|
2675
|
+
import { Label } from "@ai-matrx/design-system";
|
|
2676
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2677
|
+
var cn2 = (...parts) => parts.filter(Boolean).join(" ");
|
|
604
2678
|
function formatSettingValue(value) {
|
|
605
2679
|
if (typeof value === "boolean") return value ? "On" : "Off";
|
|
606
2680
|
if (value !== null && typeof value === "object") return JSON.stringify(value);
|
|
607
2681
|
return String(value);
|
|
608
2682
|
}
|
|
609
2683
|
function SettingRowFrame({ rowKey, state, leading, label, children, actions }) {
|
|
610
|
-
return /* @__PURE__ */
|
|
2684
|
+
return /* @__PURE__ */ jsxs5(
|
|
611
2685
|
"div",
|
|
612
2686
|
{
|
|
613
2687
|
"data-setting-row": rowKey,
|
|
614
2688
|
"data-setting-state": state,
|
|
615
2689
|
className: "grid grid-cols-[1rem_minmax(0,1fr)_auto] items-start gap-x-2 gap-y-1 py-1 @md:grid-cols-[1rem_9rem_minmax(0,1fr)_auto]",
|
|
616
2690
|
children: [
|
|
617
|
-
/* @__PURE__ */
|
|
618
|
-
/* @__PURE__ */
|
|
619
|
-
children !== void 0 ? /* @__PURE__ */
|
|
620
|
-
/* @__PURE__ */
|
|
2691
|
+
/* @__PURE__ */ jsx6("div", { className: "flex h-7 items-center", children: leading }),
|
|
2692
|
+
/* @__PURE__ */ jsx6("div", { className: "flex min-h-7 min-w-0 items-center", children: label }),
|
|
2693
|
+
children !== void 0 ? /* @__PURE__ */ jsx6("div", { className: "col-span-2 col-start-2 row-start-2 min-w-0 @md:col-span-1 @md:col-start-3 @md:row-start-1", children }) : null,
|
|
2694
|
+
/* @__PURE__ */ jsx6("div", { className: "col-start-3 row-start-1 flex min-h-7 items-center justify-end @md:col-start-4", children: actions })
|
|
621
2695
|
]
|
|
622
2696
|
}
|
|
623
2697
|
);
|
|
624
2698
|
}
|
|
625
2699
|
function RowLabel({ htmlFor, muted, children }) {
|
|
626
|
-
return /* @__PURE__ */
|
|
2700
|
+
return /* @__PURE__ */ jsx6(Label, { htmlFor, className: cn2("min-w-0 truncate type-body", muted ? "text-muted-foreground" : "text-foreground"), children });
|
|
627
2701
|
}
|
|
628
2702
|
function RowText({ children, mono }) {
|
|
629
|
-
return /* @__PURE__ */
|
|
2703
|
+
return /* @__PURE__ */ jsx6("span", { className: cn2("flex min-h-7 items-center truncate type-secondary text-muted-foreground", mono && "font-mono"), children });
|
|
630
2704
|
}
|
|
631
2705
|
function SettingsGroupSection({ id, title, children }) {
|
|
632
|
-
return /* @__PURE__ */
|
|
633
|
-
title ? /* @__PURE__ */
|
|
2706
|
+
return /* @__PURE__ */ jsxs5("section", { "data-settings-group": id, className: title ? "mt-2 border-t border-border pt-2" : void 0, children: [
|
|
2707
|
+
title ? /* @__PURE__ */ jsx6("h3", { className: "pb-1 type-title text-foreground", children: title }) : null,
|
|
634
2708
|
children
|
|
635
2709
|
] });
|
|
636
2710
|
}
|
|
637
2711
|
|
|
638
2712
|
// settings/react/InputCapabilitiesEditor.tsx
|
|
639
|
-
import { Fragment, jsx as
|
|
2713
|
+
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
640
2714
|
var GATE_META = {
|
|
641
2715
|
image_urls: {
|
|
642
2716
|
label: "Image URLs",
|
|
@@ -665,24 +2739,24 @@ function InputCapabilitiesEditor({
|
|
|
665
2739
|
title = "Input Capabilities",
|
|
666
2740
|
disabled = false
|
|
667
2741
|
}) {
|
|
668
|
-
return /* @__PURE__ */
|
|
2742
|
+
return /* @__PURE__ */ jsxs6(SettingsGroupSection, { id: "input-capabilities", title, children: [
|
|
669
2743
|
UI_GATE_EDITABLE_KEYS.map((key) => {
|
|
670
2744
|
const { label, description, Icon } = GATE_META[key];
|
|
671
2745
|
const switchId = `${idPrefix}-${key}`;
|
|
672
2746
|
const changed = changedKeys?.has(key) === true;
|
|
673
|
-
return /* @__PURE__ */
|
|
2747
|
+
return /* @__PURE__ */ jsx7(
|
|
674
2748
|
SettingRowFrame,
|
|
675
2749
|
{
|
|
676
2750
|
rowKey: key,
|
|
677
2751
|
state: values[key] === true ? "on" : "off",
|
|
678
|
-
leading: /* @__PURE__ */
|
|
679
|
-
label: /* @__PURE__ */
|
|
680
|
-
actions: /* @__PURE__ */
|
|
681
|
-
changed && onReset ? /* @__PURE__ */
|
|
2752
|
+
leading: /* @__PURE__ */ jsx7(Icon, { className: "h-4 w-4 text-muted-foreground" }),
|
|
2753
|
+
label: /* @__PURE__ */ jsx7(RowLabel, { htmlFor: switchId, children: label }),
|
|
2754
|
+
actions: /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
2755
|
+
changed && onReset ? /* @__PURE__ */ jsx7(
|
|
682
2756
|
Button,
|
|
683
2757
|
{
|
|
684
2758
|
variant: "quiet",
|
|
685
|
-
icon: /* @__PURE__ */
|
|
2759
|
+
icon: /* @__PURE__ */ jsx7(RotateCcwGlyph, {}),
|
|
686
2760
|
onClick: () => onReset(key),
|
|
687
2761
|
disabled,
|
|
688
2762
|
"aria-label": `${resetLabel}: ${label}`,
|
|
@@ -690,225 +2764,379 @@ function InputCapabilitiesEditor({
|
|
|
690
2764
|
"data-setting-reset": key
|
|
691
2765
|
}
|
|
692
2766
|
) : null,
|
|
693
|
-
/* @__PURE__ */
|
|
2767
|
+
/* @__PURE__ */ jsx7(
|
|
694
2768
|
Switch,
|
|
695
2769
|
{
|
|
696
2770
|
id: switchId,
|
|
697
2771
|
checked: values[key] === true,
|
|
698
2772
|
onCheckedChange: (next) => onChange(key, next),
|
|
699
|
-
disabled
|
|
700
|
-
className: "shrink-0"
|
|
2773
|
+
disabled
|
|
701
2774
|
}
|
|
702
2775
|
)
|
|
703
2776
|
] }),
|
|
704
|
-
children: /* @__PURE__ */
|
|
2777
|
+
children: /* @__PURE__ */ jsx7(RowText, { children: description })
|
|
705
2778
|
},
|
|
706
2779
|
key
|
|
707
2780
|
);
|
|
708
2781
|
}),
|
|
709
|
-
error ? /* @__PURE__ */
|
|
2782
|
+
error ? /* @__PURE__ */ jsx7(ErrorBox, { as: "p", className: "py-1 type-meta text-destructive", message: error }) : null
|
|
710
2783
|
] });
|
|
711
2784
|
}
|
|
712
2785
|
|
|
713
|
-
// settings/react/
|
|
714
|
-
import {
|
|
715
|
-
import {
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
2786
|
+
// settings/react/SettingControlInput.tsx
|
|
2787
|
+
import { useEffect as useEffect3, useState as useState2 } from "react";
|
|
2788
|
+
import {
|
|
2789
|
+
Checkbox,
|
|
2790
|
+
Input as Input2,
|
|
2791
|
+
Label as Label2,
|
|
2792
|
+
Select,
|
|
2793
|
+
SelectContent,
|
|
2794
|
+
SelectItem,
|
|
2795
|
+
SelectTrigger,
|
|
2796
|
+
SelectValue,
|
|
2797
|
+
Slider,
|
|
2798
|
+
Textarea,
|
|
2799
|
+
Tooltip as Tooltip2,
|
|
2800
|
+
TooltipContent as TooltipContent2,
|
|
2801
|
+
TooltipProvider as TooltipProvider2,
|
|
2802
|
+
TooltipTrigger as TooltipTrigger2
|
|
2803
|
+
} from "@ai-matrx/design-system";
|
|
2804
|
+
import { AspectRatioSelect, OptionCombobox, isAspectRatioOptionSet } from "@ai-matrx/design-system/controls";
|
|
2805
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2806
|
+
var SELECT_MAX_OPTIONS = 12;
|
|
2807
|
+
function choiceFor(options) {
|
|
2808
|
+
if (isAspectRatioOptionSet(options)) return "aspect-ratio";
|
|
2809
|
+
if (options.length > SELECT_MAX_OPTIONS) return "searchable";
|
|
2810
|
+
return "select";
|
|
731
2811
|
}
|
|
732
|
-
|
|
733
|
-
{
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
]
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
"model_id",
|
|
821
|
-
"model",
|
|
822
|
-
// chosen via the dedicated model picker, never a generic settings row
|
|
823
|
-
"multi_speaker",
|
|
824
|
-
// edited via the Voice editor alongside tts_voice
|
|
825
|
-
// Model-gated UI flags live in the ui_gates column + UiGatesEditor, never as
|
|
826
|
-
// settings rows — even when the model declares them as controls (e.g. every
|
|
827
|
-
// model now declares `tools` for the tool-support capability).
|
|
828
|
-
...UI_GATE_KEYS
|
|
829
|
-
]);
|
|
830
|
-
function lookupControl(controls, key) {
|
|
831
|
-
if (!controls) return null;
|
|
832
|
-
if (CATCHALL_EXCLUDED.has(key)) {
|
|
833
|
-
if (key === "rawControls" || key === "unmappedControls") return null;
|
|
2812
|
+
function WarningIcon({ className }) {
|
|
2813
|
+
return /* @__PURE__ */ jsxs7("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", className, children: [
|
|
2814
|
+
/* @__PURE__ */ jsx8("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }),
|
|
2815
|
+
/* @__PURE__ */ jsx8("path", { d: "M12 9v4" }),
|
|
2816
|
+
/* @__PURE__ */ jsx8("path", { d: "M12 17h.01" })
|
|
2817
|
+
] });
|
|
2818
|
+
}
|
|
2819
|
+
function flattenTypeObject(value) {
|
|
2820
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value) && "type" in value && Object.keys(value).length === 1) {
|
|
2821
|
+
return value.type;
|
|
2822
|
+
}
|
|
2823
|
+
return value;
|
|
2824
|
+
}
|
|
2825
|
+
function SettingControlInput({
|
|
2826
|
+
settingKey,
|
|
2827
|
+
control,
|
|
2828
|
+
value,
|
|
2829
|
+
onChange,
|
|
2830
|
+
disabled = false,
|
|
2831
|
+
id
|
|
2832
|
+
}) {
|
|
2833
|
+
const inputId = id ?? `setting-control-${settingKey}`;
|
|
2834
|
+
if (control.type === "enum" && control.enum?.length) {
|
|
2835
|
+
const flattened = settingKey === "response_format" ? flattenTypeObject(value) : value;
|
|
2836
|
+
const stringValue = flattened === void 0 || flattened === null ? "" : String(flattened);
|
|
2837
|
+
const isValueMismatch = stringValue !== "" && !control.enum.includes(stringValue);
|
|
2838
|
+
const emit = (v) => onChange(settingKey === "response_format" ? { type: v } : v);
|
|
2839
|
+
const choice = choiceFor(control.enum);
|
|
2840
|
+
const picker = choice === "aspect-ratio" ? /* @__PURE__ */ jsx8(
|
|
2841
|
+
AspectRatioSelect,
|
|
2842
|
+
{
|
|
2843
|
+
value: isValueMismatch ? "" : stringValue,
|
|
2844
|
+
onChange: emit,
|
|
2845
|
+
options: control.enum,
|
|
2846
|
+
variant: "inline",
|
|
2847
|
+
disabled,
|
|
2848
|
+
id: inputId,
|
|
2849
|
+
placeholder: "Default"
|
|
2850
|
+
}
|
|
2851
|
+
) : choice === "searchable" ? /* @__PURE__ */ jsx8(
|
|
2852
|
+
OptionCombobox,
|
|
2853
|
+
{
|
|
2854
|
+
value: isValueMismatch ? "" : stringValue,
|
|
2855
|
+
onChange: emit,
|
|
2856
|
+
options: control.enum,
|
|
2857
|
+
variant: "inline",
|
|
2858
|
+
disabled,
|
|
2859
|
+
id: inputId,
|
|
2860
|
+
placeholder: "Default"
|
|
2861
|
+
}
|
|
2862
|
+
) : null;
|
|
2863
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex flex-1 items-center gap-1.5", children: [
|
|
2864
|
+
picker ?? /* @__PURE__ */ jsxs7(
|
|
2865
|
+
Select,
|
|
2866
|
+
{
|
|
2867
|
+
value: isValueMismatch ? "" : stringValue,
|
|
2868
|
+
onValueChange: emit,
|
|
2869
|
+
disabled,
|
|
2870
|
+
children: [
|
|
2871
|
+
/* @__PURE__ */ jsx8(
|
|
2872
|
+
SelectTrigger,
|
|
2873
|
+
{
|
|
2874
|
+
id: inputId,
|
|
2875
|
+
className: "h-7 flex-1 border-0 bg-transparent px-1 text-xs font-medium text-foreground shadow-none hover:bg-transparent focus:ring-0 pointer-coarse:h-11 [&_svg]:h-3 [&_svg]:w-3",
|
|
2876
|
+
children: /* @__PURE__ */ jsx8(SelectValue, { placeholder: isValueMismatch ? stringValue : "Default" })
|
|
2877
|
+
}
|
|
2878
|
+
),
|
|
2879
|
+
/* @__PURE__ */ jsx8(SelectContent, { className: "text-xs", children: control.enum.map((option) => /* @__PURE__ */ jsx8(
|
|
2880
|
+
SelectItem,
|
|
2881
|
+
{
|
|
2882
|
+
value: option,
|
|
2883
|
+
className: "py-1 text-xs",
|
|
2884
|
+
children: option === ENUM_OFF_VALUE ? "Off" : option
|
|
2885
|
+
},
|
|
2886
|
+
option
|
|
2887
|
+
)) })
|
|
2888
|
+
]
|
|
2889
|
+
}
|
|
2890
|
+
),
|
|
2891
|
+
isValueMismatch && /* @__PURE__ */ jsx8(TooltipProvider2, { delayDuration: 200, children: /* @__PURE__ */ jsxs7(Tooltip2, { children: [
|
|
2892
|
+
/* @__PURE__ */ jsx8(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ jsx8("span", { className: "shrink-0 cursor-help text-amber-500", children: /* @__PURE__ */ jsx8(WarningIcon, { className: "h-3.5 w-3.5" }) }) }),
|
|
2893
|
+
/* @__PURE__ */ jsxs7(TooltipContent2, { side: "top", className: "max-w-[220px] type-secondary", children: [
|
|
2894
|
+
'"',
|
|
2895
|
+
stringValue,
|
|
2896
|
+
'" is not a recognized option for this model'
|
|
2897
|
+
] })
|
|
2898
|
+
] }) })
|
|
2899
|
+
] });
|
|
834
2900
|
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
2901
|
+
if (control.type === "boolean") {
|
|
2902
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
|
|
2903
|
+
/* @__PURE__ */ jsx8(
|
|
2904
|
+
Checkbox,
|
|
2905
|
+
{
|
|
2906
|
+
id: inputId,
|
|
2907
|
+
checked: value === true,
|
|
2908
|
+
onCheckedChange: (c) => onChange(c === true),
|
|
2909
|
+
disabled,
|
|
2910
|
+
className: "cursor-pointer"
|
|
2911
|
+
}
|
|
2912
|
+
),
|
|
2913
|
+
/* @__PURE__ */ jsx8(
|
|
2914
|
+
Label2,
|
|
2915
|
+
{
|
|
2916
|
+
htmlFor: inputId,
|
|
2917
|
+
className: "cursor-pointer text-xs text-muted-foreground",
|
|
2918
|
+
children: value === true ? "On" : "Off"
|
|
2919
|
+
}
|
|
2920
|
+
)
|
|
2921
|
+
] });
|
|
841
2922
|
}
|
|
842
|
-
|
|
2923
|
+
if (control.type === "number" || control.type === "integer") {
|
|
2924
|
+
const numeric = typeof value === "number" ? value : void 0;
|
|
2925
|
+
const hasRange = control.min !== void 0 && control.max !== void 0;
|
|
2926
|
+
return /* @__PURE__ */ jsx8(
|
|
2927
|
+
NumberInput,
|
|
2928
|
+
{
|
|
2929
|
+
value: numeric,
|
|
2930
|
+
placeholderValue: typeof control.default === "number" ? control.default : void 0,
|
|
2931
|
+
onChange,
|
|
2932
|
+
onSliderChange: hasRange ? onChange : void 0,
|
|
2933
|
+
min: control.min,
|
|
2934
|
+
max: control.max,
|
|
2935
|
+
step: control.type === "integer" ? 1 : 0.01,
|
|
2936
|
+
isInteger: control.type === "integer",
|
|
2937
|
+
disabled,
|
|
2938
|
+
withSlider: hasRange
|
|
2939
|
+
}
|
|
2940
|
+
);
|
|
2941
|
+
}
|
|
2942
|
+
if (control.type === "string_array") {
|
|
2943
|
+
const arrayValue = Array.isArray(value) ? value.join("\n") : "";
|
|
2944
|
+
return /* @__PURE__ */ jsx8(
|
|
2945
|
+
Textarea,
|
|
2946
|
+
{
|
|
2947
|
+
id: inputId,
|
|
2948
|
+
value: arrayValue,
|
|
2949
|
+
onChange: (e) => onChange(e.target.value.split("\n").filter((s) => s.trim())),
|
|
2950
|
+
disabled,
|
|
2951
|
+
className: "min-h-14 px-2 py-1.5 font-mono text-base leading-snug disabled:opacity-50 sm:text-xs",
|
|
2952
|
+
placeholder: "One value per line..."
|
|
2953
|
+
}
|
|
2954
|
+
);
|
|
2955
|
+
}
|
|
2956
|
+
if (control.type === "array" || control.type === "object_array" || typeof value === "object" && value !== null) {
|
|
2957
|
+
return /* @__PURE__ */ jsx8(
|
|
2958
|
+
JsonValueInput,
|
|
2959
|
+
{
|
|
2960
|
+
id: inputId,
|
|
2961
|
+
value,
|
|
2962
|
+
onChange,
|
|
2963
|
+
disabled
|
|
2964
|
+
}
|
|
2965
|
+
);
|
|
2966
|
+
}
|
|
2967
|
+
return /* @__PURE__ */ jsx8(
|
|
2968
|
+
Input2,
|
|
2969
|
+
{
|
|
2970
|
+
id: inputId,
|
|
2971
|
+
type: "text",
|
|
2972
|
+
value: value === void 0 || value === null ? "" : String(value),
|
|
2973
|
+
onChange: (e) => onChange(e.target.value),
|
|
2974
|
+
disabled,
|
|
2975
|
+
className: "h-7 w-full px-2 text-base pointer-coarse:h-11 sm:text-xs"
|
|
2976
|
+
}
|
|
2977
|
+
);
|
|
843
2978
|
}
|
|
844
|
-
function
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
2979
|
+
function JsonValueInput({
|
|
2980
|
+
id,
|
|
2981
|
+
value,
|
|
2982
|
+
onChange,
|
|
2983
|
+
disabled
|
|
2984
|
+
}) {
|
|
2985
|
+
const toText = (v) => v === void 0 || v === null ? "" : JSON.stringify(v, null, 2);
|
|
2986
|
+
const [draft, setDraft] = useState2(() => toText(value));
|
|
2987
|
+
const [jsonError, setJsonError] = useState2(null);
|
|
2988
|
+
useEffect3(() => {
|
|
2989
|
+
setDraft(toText(value));
|
|
2990
|
+
setJsonError(null);
|
|
2991
|
+
}, [JSON.stringify(value)]);
|
|
2992
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-1", children: [
|
|
2993
|
+
/* @__PURE__ */ jsx8(
|
|
2994
|
+
Textarea,
|
|
2995
|
+
{
|
|
2996
|
+
id,
|
|
2997
|
+
value: draft,
|
|
2998
|
+
onChange: (e) => {
|
|
2999
|
+
setDraft(e.target.value);
|
|
3000
|
+
try {
|
|
3001
|
+
JSON.parse(e.target.value);
|
|
3002
|
+
setJsonError(null);
|
|
3003
|
+
} catch (err) {
|
|
3004
|
+
setJsonError(err instanceof Error ? err.message : "Invalid JSON");
|
|
3005
|
+
}
|
|
3006
|
+
},
|
|
3007
|
+
onBlur: (e) => {
|
|
3008
|
+
if (e.target.value.trim() === "") return;
|
|
3009
|
+
try {
|
|
3010
|
+
onChange(JSON.parse(e.target.value));
|
|
3011
|
+
setJsonError(null);
|
|
3012
|
+
} catch {
|
|
3013
|
+
}
|
|
3014
|
+
},
|
|
3015
|
+
disabled,
|
|
3016
|
+
className: "min-h-12 px-2 py-1.5 font-mono text-base leading-snug sm:text-xs",
|
|
3017
|
+
spellCheck: false
|
|
3018
|
+
}
|
|
3019
|
+
),
|
|
3020
|
+
jsonError && /* @__PURE__ */ jsx8("p", { className: "type-meta text-amber-600 dark:text-amber-400", children: jsonError })
|
|
3021
|
+
] });
|
|
848
3022
|
}
|
|
849
|
-
function
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
];
|
|
866
|
-
})
|
|
3023
|
+
function NumberInput({
|
|
3024
|
+
value,
|
|
3025
|
+
placeholderValue,
|
|
3026
|
+
onChange,
|
|
3027
|
+
onSliderChange,
|
|
3028
|
+
min,
|
|
3029
|
+
max,
|
|
3030
|
+
step = 1,
|
|
3031
|
+
isInteger = false,
|
|
3032
|
+
disabled = false,
|
|
3033
|
+
withSlider = false
|
|
3034
|
+
}) {
|
|
3035
|
+
const boxClass = "h-7 px-2 text-xs tabular-nums pointer-coarse:h-11";
|
|
3036
|
+
const [draftState, setDraftState] = useState2(() => ({
|
|
3037
|
+
sourceValue: value,
|
|
3038
|
+
text: value === void 0 ? "" : String(value)
|
|
867
3039
|
}));
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
const
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
3040
|
+
const shown = value === void 0 ? "" : String(value);
|
|
3041
|
+
const draft = draftState.sourceValue === value ? draftState.text : shown;
|
|
3042
|
+
const unset = value === void 0;
|
|
3043
|
+
const hint = placeholderValue === void 0 ? "Default" : String(placeholderValue);
|
|
3044
|
+
const setDraft = (text) => setDraftState({ sourceValue: value, text });
|
|
3045
|
+
const sliderStep = isInteger ? Math.max(1, Math.trunc(step)) : step;
|
|
3046
|
+
const commit = (raw) => {
|
|
3047
|
+
if (raw === "" || raw === "-") return;
|
|
3048
|
+
const parsed = isInteger ? parseInt(raw, 10) : parseFloat(raw);
|
|
3049
|
+
if (!isNaN(parsed)) {
|
|
3050
|
+
if (parsed !== value) onChange(parsed);
|
|
3051
|
+
} else setDraft(shown);
|
|
3052
|
+
};
|
|
3053
|
+
if (withSlider) {
|
|
3054
|
+
return /* @__PURE__ */ jsxs7(
|
|
3055
|
+
"div",
|
|
3056
|
+
{
|
|
3057
|
+
className: "grid grid-cols-[1fr_4.5rem] items-center gap-2",
|
|
3058
|
+
children: [
|
|
3059
|
+
/* @__PURE__ */ jsx8(
|
|
3060
|
+
Slider,
|
|
3061
|
+
{
|
|
3062
|
+
...min !== void 0 ? { min } : {},
|
|
3063
|
+
...max !== void 0 ? { max } : {},
|
|
3064
|
+
step: sliderStep,
|
|
3065
|
+
value: [value ?? placeholderValue ?? min ?? 0],
|
|
3066
|
+
"data-unset": unset ? "true" : void 0,
|
|
3067
|
+
className: unset ? "opacity-50" : void 0,
|
|
3068
|
+
onValueChange: (val) => {
|
|
3069
|
+
const first = val[0] ?? value ?? placeholderValue ?? min ?? 0;
|
|
3070
|
+
const nextValue = isInteger ? Math.trunc(first) : first;
|
|
3071
|
+
onSliderChange?.(nextValue);
|
|
3072
|
+
setDraft(String(nextValue));
|
|
3073
|
+
},
|
|
3074
|
+
disabled
|
|
3075
|
+
}
|
|
3076
|
+
),
|
|
3077
|
+
/* @__PURE__ */ jsx8(
|
|
3078
|
+
Input2,
|
|
3079
|
+
{
|
|
3080
|
+
type: "text",
|
|
3081
|
+
inputMode: "decimal",
|
|
3082
|
+
value: draft,
|
|
3083
|
+
placeholder: hint,
|
|
3084
|
+
onChange: (e) => setDraft(e.target.value),
|
|
3085
|
+
onBlur: (e) => commit(e.target.value),
|
|
3086
|
+
onFocus: (e) => e.target.select(),
|
|
3087
|
+
onKeyDown: (e) => {
|
|
3088
|
+
if (e.key === "Enter") e.currentTarget.blur();
|
|
3089
|
+
},
|
|
3090
|
+
disabled,
|
|
3091
|
+
className: boxClass
|
|
3092
|
+
}
|
|
3093
|
+
)
|
|
3094
|
+
]
|
|
3095
|
+
}
|
|
3096
|
+
);
|
|
885
3097
|
}
|
|
886
|
-
return
|
|
3098
|
+
return /* @__PURE__ */ jsx8(
|
|
3099
|
+
Input2,
|
|
3100
|
+
{
|
|
3101
|
+
type: "text",
|
|
3102
|
+
inputMode: "decimal",
|
|
3103
|
+
value: draft,
|
|
3104
|
+
placeholder: hint,
|
|
3105
|
+
onChange: (e) => setDraft(e.target.value),
|
|
3106
|
+
onBlur: (e) => commit(e.target.value),
|
|
3107
|
+
onFocus: (e) => e.target.select(),
|
|
3108
|
+
onKeyDown: (e) => {
|
|
3109
|
+
if (e.key === "Enter") e.currentTarget.blur();
|
|
3110
|
+
},
|
|
3111
|
+
disabled,
|
|
3112
|
+
className: `${boxClass} w-full`
|
|
3113
|
+
}
|
|
3114
|
+
);
|
|
887
3115
|
}
|
|
888
3116
|
|
|
889
3117
|
// settings/react/ModelSettingsPanel.tsx
|
|
890
|
-
import { Fragment as
|
|
3118
|
+
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
891
3119
|
function StatusGlyph({ issue, source }) {
|
|
892
3120
|
const title = issue ? issue.message : source ? `Valid \xB7 ${source}` : "Valid";
|
|
893
|
-
return /* @__PURE__ */
|
|
3121
|
+
return /* @__PURE__ */ jsx9(
|
|
894
3122
|
"span",
|
|
895
3123
|
{
|
|
896
|
-
className:
|
|
3124
|
+
className: cn2("inline-flex h-7 w-6 shrink-0 items-center justify-center", issue ? "text-warning" : "text-success"),
|
|
897
3125
|
role: "img",
|
|
898
3126
|
"aria-label": title,
|
|
899
3127
|
title,
|
|
900
|
-
children: issue ? /* @__PURE__ */
|
|
3128
|
+
children: issue ? /* @__PURE__ */ jsx9(TriangleAlertGlyph, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx9(CircleCheckGlyph, { className: "h-3.5 w-3.5" })
|
|
901
3129
|
}
|
|
902
3130
|
);
|
|
903
3131
|
}
|
|
904
3132
|
function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
905
3133
|
const read = target.read(row.key, control);
|
|
906
3134
|
const resetLabel = target.resetLabel ?? "Reset to agent";
|
|
907
|
-
const reset = read.changedHere && target.resetToInherited ? /* @__PURE__ */
|
|
3135
|
+
const reset = read.changedHere && target.resetToInherited ? /* @__PURE__ */ jsx9(
|
|
908
3136
|
Button2,
|
|
909
3137
|
{
|
|
910
3138
|
variant: "quiet",
|
|
911
|
-
icon: /* @__PURE__ */
|
|
3139
|
+
icon: /* @__PURE__ */ jsx9(RotateCcwGlyph, {}),
|
|
912
3140
|
onClick: () => target.resetToInherited?.(row.key),
|
|
913
3141
|
disabled,
|
|
914
3142
|
"aria-label": `${resetLabel}: ${row.label}`,
|
|
@@ -917,20 +3145,20 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
917
3145
|
}
|
|
918
3146
|
) : null;
|
|
919
3147
|
if (read.state === "bound") {
|
|
920
|
-
return /* @__PURE__ */
|
|
3148
|
+
return /* @__PURE__ */ jsx9(
|
|
921
3149
|
SettingRowFrame,
|
|
922
3150
|
{
|
|
923
3151
|
rowKey: row.key,
|
|
924
3152
|
state: "bound",
|
|
925
|
-
leading: /* @__PURE__ */
|
|
926
|
-
label: /* @__PURE__ */
|
|
927
|
-
actions: /* @__PURE__ */
|
|
3153
|
+
leading: /* @__PURE__ */ jsx9(Checkbox2, { checked: true, disabled: true, "aria-label": `${row.label} is a run input` }),
|
|
3154
|
+
label: /* @__PURE__ */ jsx9(RowLabel, { children: row.label }),
|
|
3155
|
+
actions: /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
928
3156
|
reset,
|
|
929
|
-
target.unbind ? /* @__PURE__ */
|
|
3157
|
+
target.unbind ? /* @__PURE__ */ jsx9(
|
|
930
3158
|
Button2,
|
|
931
3159
|
{
|
|
932
3160
|
variant: "quiet",
|
|
933
|
-
icon: /* @__PURE__ */
|
|
3161
|
+
icon: /* @__PURE__ */ jsx9(UnlinkGlyph, {}),
|
|
934
3162
|
onClick: () => target.unbind?.(row.key, control),
|
|
935
3163
|
disabled,
|
|
936
3164
|
"aria-label": `Make ${row.label} a fixed setting`,
|
|
@@ -938,9 +3166,9 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
938
3166
|
}
|
|
939
3167
|
) : null
|
|
940
3168
|
] }),
|
|
941
|
-
children: /* @__PURE__ */
|
|
942
|
-
/* @__PURE__ */
|
|
943
|
-
/* @__PURE__ */
|
|
3169
|
+
children: /* @__PURE__ */ jsxs8("span", { className: "flex min-h-7 min-w-0 items-center gap-2", "data-bound-control": row.key, children: [
|
|
3170
|
+
/* @__PURE__ */ jsx9(Chip, { tone: "primary", icon: /* @__PURE__ */ jsx9(VariableGlyph, {}), label: `{{${read.variableName}}}` }),
|
|
3171
|
+
/* @__PURE__ */ jsx9("span", { className: "truncate type-meta text-muted-foreground", children: read.value === void 0 || read.value === null || read.value === "" ? "Model default" : formatSettingValue(read.value) })
|
|
944
3172
|
] })
|
|
945
3173
|
}
|
|
946
3174
|
);
|
|
@@ -950,12 +3178,12 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
950
3178
|
const isOff = isSet && isOffValue(value, control);
|
|
951
3179
|
const checkboxId = `${idPrefix}-setting-${row.key}`;
|
|
952
3180
|
const canBind = Boolean(target.bind) && (target.canBind?.(row.key) ?? true);
|
|
953
|
-
return /* @__PURE__ */
|
|
3181
|
+
return /* @__PURE__ */ jsx9(
|
|
954
3182
|
SettingRowFrame,
|
|
955
3183
|
{
|
|
956
3184
|
rowKey: row.key,
|
|
957
3185
|
state: isOff ? "off" : read.state,
|
|
958
|
-
leading: /* @__PURE__ */
|
|
3186
|
+
leading: /* @__PURE__ */ jsx9(
|
|
959
3187
|
Checkbox2,
|
|
960
3188
|
{
|
|
961
3189
|
id: checkboxId,
|
|
@@ -964,14 +3192,14 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
964
3192
|
onCheckedChange: (next) => next === true ? target.turnOn(row.key, control) : target.clear(row.key)
|
|
965
3193
|
}
|
|
966
3194
|
),
|
|
967
|
-
label: /* @__PURE__ */
|
|
968
|
-
actions: /* @__PURE__ */
|
|
969
|
-
/* @__PURE__ */
|
|
970
|
-
canBind ? /* @__PURE__ */
|
|
3195
|
+
label: /* @__PURE__ */ jsx9(RowLabel, { htmlFor: checkboxId, muted: !isSet, children: row.label }),
|
|
3196
|
+
actions: /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
3197
|
+
/* @__PURE__ */ jsx9(StatusGlyph, { issue: read.issue, source: read.source }),
|
|
3198
|
+
canBind ? /* @__PURE__ */ jsx9(
|
|
971
3199
|
Button2,
|
|
972
3200
|
{
|
|
973
3201
|
variant: "quiet",
|
|
974
|
-
icon: /* @__PURE__ */
|
|
3202
|
+
icon: /* @__PURE__ */ jsx9(VariableGlyph, {}),
|
|
975
3203
|
onClick: () => target.bind?.(row.key, control),
|
|
976
3204
|
disabled,
|
|
977
3205
|
"aria-label": `Make ${row.label} a run input`,
|
|
@@ -979,11 +3207,11 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
979
3207
|
"data-bind-control": row.key
|
|
980
3208
|
}
|
|
981
3209
|
) : null,
|
|
982
|
-
isSet && read.issue?.fixable && target.fix ? /* @__PURE__ */
|
|
3210
|
+
isSet && read.issue?.fixable && target.fix ? /* @__PURE__ */ jsx9(
|
|
983
3211
|
Button2,
|
|
984
3212
|
{
|
|
985
3213
|
variant: "quiet",
|
|
986
|
-
icon: /* @__PURE__ */
|
|
3214
|
+
icon: /* @__PURE__ */ jsx9(WrenchGlyph, {}),
|
|
987
3215
|
onClick: () => target.fix?.(row.key),
|
|
988
3216
|
disabled,
|
|
989
3217
|
"aria-label": `Fix ${row.label} automatically`,
|
|
@@ -991,12 +3219,12 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
991
3219
|
}
|
|
992
3220
|
) : null,
|
|
993
3221
|
reset,
|
|
994
|
-
isSet ? /* @__PURE__ */
|
|
3222
|
+
isSet ? /* @__PURE__ */ jsx9(
|
|
995
3223
|
Button2,
|
|
996
3224
|
{
|
|
997
3225
|
variant: "quiet",
|
|
998
3226
|
removes: true,
|
|
999
|
-
icon: /* @__PURE__ */
|
|
3227
|
+
icon: /* @__PURE__ */ jsx9(Trash2Glyph, {}),
|
|
1000
3228
|
onClick: () => target.clear(row.key),
|
|
1001
3229
|
disabled,
|
|
1002
3230
|
"aria-label": `Clear ${row.label} to not set`,
|
|
@@ -1005,8 +3233,8 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
1005
3233
|
}
|
|
1006
3234
|
) : null
|
|
1007
3235
|
] }),
|
|
1008
|
-
children: isSet ? /* @__PURE__ */
|
|
1009
|
-
/* @__PURE__ */
|
|
3236
|
+
children: isSet ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
3237
|
+
/* @__PURE__ */ jsx9(
|
|
1010
3238
|
SettingControlInput,
|
|
1011
3239
|
{
|
|
1012
3240
|
settingKey: row.key,
|
|
@@ -1017,23 +3245,77 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
|
|
|
1017
3245
|
id: `${idPrefix}-control-${row.key}`
|
|
1018
3246
|
}
|
|
1019
3247
|
),
|
|
1020
|
-
read.issue ? /* @__PURE__ */
|
|
1021
|
-
] }) : /* @__PURE__ */
|
|
3248
|
+
read.issue ? /* @__PURE__ */ jsx9("p", { className: "pt-1 type-meta text-warning-ink", children: read.issue.message }) : null
|
|
3249
|
+
] }) : /* @__PURE__ */ jsx9(RowText, { children: read.modelDefault !== void 0 && read.modelDefault !== null ? `Not set \xB7 Model default: ${formatSettingValue(read.modelDefault)}` : "Not set" })
|
|
1022
3250
|
}
|
|
1023
3251
|
);
|
|
1024
3252
|
}
|
|
1025
3253
|
function ExtraSettingRow({ rowKey, label, value, kind, onClear, onReset, resetLabel = "Reset to agent", disabled = false }) {
|
|
1026
|
-
return /* @__PURE__ */
|
|
3254
|
+
return /* @__PURE__ */ jsx9(
|
|
1027
3255
|
SettingRowFrame,
|
|
1028
3256
|
{
|
|
1029
3257
|
rowKey,
|
|
1030
3258
|
state: kind,
|
|
1031
|
-
label: /* @__PURE__ */
|
|
1032
|
-
actions: /* @__PURE__ */
|
|
1033
|
-
kind === "translated" ? /* @__PURE__ */
|
|
1034
|
-
onReset ? /* @__PURE__ */
|
|
3259
|
+
label: /* @__PURE__ */ jsx9(RowLabel, { children: label }),
|
|
3260
|
+
actions: /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
3261
|
+
kind === "translated" ? /* @__PURE__ */ jsx9(Chip, { tone: "sky", label: "Translated", title: "Kept as set and sent as this model's closest equivalent" }) : /* @__PURE__ */ jsx9(Chip, { tone: "warning", label: "Not on this model", title: "This model has no such setting" }),
|
|
3262
|
+
onReset ? /* @__PURE__ */ jsx9(Button2, { variant: "quiet", icon: /* @__PURE__ */ jsx9(RotateCcwGlyph, {}), onClick: onReset, disabled, "aria-label": `${resetLabel}: ${label}`, title: resetLabel, "data-setting-reset": rowKey }) : /* @__PURE__ */ jsx9(Button2, { variant: "quiet", removes: true, icon: /* @__PURE__ */ jsx9(Trash2Glyph, {}), onClick: onClear, disabled, "aria-label": `Clear ${label}`, title: "Clear to not set", "data-setting-clear": rowKey })
|
|
1035
3263
|
] }),
|
|
1036
|
-
children: /* @__PURE__ */
|
|
3264
|
+
children: /* @__PURE__ */ jsx9(RowText, { mono: value !== void 0 && value !== null, children: value === void 0 || value === null ? "Not set" : isOffValue(value, null) ? "Off" : formatSettingValue(value) })
|
|
3265
|
+
}
|
|
3266
|
+
);
|
|
3267
|
+
}
|
|
3268
|
+
function ModelRow2({ model, resetLabel, idPrefix, disabled }) {
|
|
3269
|
+
const off = disabled || model.disabled === true;
|
|
3270
|
+
const oneMessageId = `${idPrefix}-model-one-message`;
|
|
3271
|
+
return /* @__PURE__ */ jsx9(
|
|
3272
|
+
SettingRowFrame,
|
|
3273
|
+
{
|
|
3274
|
+
rowKey: "model",
|
|
3275
|
+
state: model.value ? "set" : "unset",
|
|
3276
|
+
label: /* @__PURE__ */ jsx9(RowLabel, { children: "Model" }),
|
|
3277
|
+
actions: model.changedHere && model.resetToInherited ? /* @__PURE__ */ jsx9(
|
|
3278
|
+
Button2,
|
|
3279
|
+
{
|
|
3280
|
+
variant: "quiet",
|
|
3281
|
+
icon: /* @__PURE__ */ jsx9(RotateCcwGlyph, {}),
|
|
3282
|
+
onClick: () => model.resetToInherited?.(),
|
|
3283
|
+
disabled: off,
|
|
3284
|
+
"aria-label": `${resetLabel}: Model`,
|
|
3285
|
+
title: resetLabel,
|
|
3286
|
+
"data-setting-reset": "model"
|
|
3287
|
+
}
|
|
3288
|
+
) : null,
|
|
3289
|
+
children: /* @__PURE__ */ jsxs8("div", { className: "flex min-h-7 min-w-0 flex-wrap items-center gap-x-2", children: [
|
|
3290
|
+
/* @__PURE__ */ jsx9(
|
|
3291
|
+
ModelListDropdown,
|
|
3292
|
+
{
|
|
3293
|
+
"aria-label": "Model",
|
|
3294
|
+
value: model.value,
|
|
3295
|
+
onValueChange: model.change,
|
|
3296
|
+
inputModalities: [],
|
|
3297
|
+
disabled: off,
|
|
3298
|
+
className: "min-w-0",
|
|
3299
|
+
pinnedOfferingId: model.pinnedOfferingId,
|
|
3300
|
+
onOfferingPinChange: model.changePin,
|
|
3301
|
+
...model.emptyChoice ? { emptyOptionLabel: model.emptyChoice.label, onClear: model.emptyChoice.choose, placeholder: model.emptyChoice.label } : {},
|
|
3302
|
+
...model.localModels ? { localModels: model.localModels } : {},
|
|
3303
|
+
...model.disabledTitle ? { disabledTitle: model.disabledTitle } : {}
|
|
3304
|
+
}
|
|
3305
|
+
),
|
|
3306
|
+
model.oneMessage ? /* @__PURE__ */ jsxs8("label", { htmlFor: oneMessageId, className: "flex min-h-7 items-center gap-1 type-secondary text-muted-foreground", title: "Use this model for the next message, then go back", children: [
|
|
3307
|
+
/* @__PURE__ */ jsx9(
|
|
3308
|
+
Switch2,
|
|
3309
|
+
{
|
|
3310
|
+
id: oneMessageId,
|
|
3311
|
+
checked: model.oneMessage.on,
|
|
3312
|
+
onCheckedChange: (next) => model.oneMessage?.change(next),
|
|
3313
|
+
disabled
|
|
3314
|
+
}
|
|
3315
|
+
),
|
|
3316
|
+
"This message only"
|
|
3317
|
+
] }) : null
|
|
3318
|
+
] })
|
|
1037
3319
|
}
|
|
1038
3320
|
);
|
|
1039
3321
|
}
|
|
@@ -1050,15 +3332,33 @@ function ModelSettingsPanel({
|
|
|
1050
3332
|
disabled = false
|
|
1051
3333
|
}) {
|
|
1052
3334
|
const groups = controls ? buildSettingsRows(controls, values).filter((group) => group.rows.length > 0) : [];
|
|
1053
|
-
|
|
1054
|
-
|
|
3335
|
+
const extras = extraSettingKeys(controls, values, target.changedKeys);
|
|
3336
|
+
const resetLabel = target.resetLabel ?? "Reset to agent";
|
|
3337
|
+
const extraRow = (key, kind) => /* @__PURE__ */ jsx9(
|
|
3338
|
+
ExtraSettingRow,
|
|
3339
|
+
{
|
|
3340
|
+
rowKey: key,
|
|
3341
|
+
label: settingLabel(key),
|
|
3342
|
+
value: values?.[key],
|
|
3343
|
+
kind,
|
|
3344
|
+
onClear: () => target.clear(key),
|
|
3345
|
+
onReset: target.resetToInherited && target.read(key, null).changedHere ? () => target.resetToInherited?.(key) : void 0,
|
|
3346
|
+
resetLabel,
|
|
3347
|
+
disabled
|
|
3348
|
+
},
|
|
3349
|
+
key
|
|
3350
|
+
);
|
|
3351
|
+
return /* @__PURE__ */ jsxs8("div", { "data-model-settings-panel": "", className: "@container flex min-w-0 flex-col", children: [
|
|
3352
|
+
model ? /* @__PURE__ */ jsx9(ModelRow2, { model, resetLabel, idPrefix, disabled }) : null,
|
|
1055
3353
|
notices,
|
|
1056
|
-
|
|
1057
|
-
|
|
3354
|
+
extras.unsupported.map((key) => extraRow(key, "unsupported")),
|
|
3355
|
+
extras.translated.length > 0 ? /* @__PURE__ */ jsx9(SettingsGroupSection, { id: "translated", title: "Translated for this model", children: /* @__PURE__ */ jsx9("div", { "data-translated-settings": "", children: extras.translated.map((key) => extraRow(key, "translated")) }) }) : null,
|
|
3356
|
+
groups.length === 0 && emptyNote ? /* @__PURE__ */ jsx9("div", { className: "py-2 type-secondary text-muted-foreground", children: emptyNote }) : null,
|
|
3357
|
+
groups.map((group) => /* @__PURE__ */ jsx9(SettingsGroupSection, { id: group.id, title: group.label || void 0, children: group.rows.map((row) => {
|
|
1058
3358
|
const custom = renderRow?.(row);
|
|
1059
|
-
if (custom !== void 0) return /* @__PURE__ */
|
|
3359
|
+
if (custom !== void 0) return /* @__PURE__ */ jsx9("div", { children: custom }, row.key);
|
|
1060
3360
|
if (!row.control) return null;
|
|
1061
|
-
return /* @__PURE__ */
|
|
3361
|
+
return /* @__PURE__ */ jsx9(
|
|
1062
3362
|
ModelSettingRow,
|
|
1063
3363
|
{
|
|
1064
3364
|
row,
|
|
@@ -1070,14 +3370,14 @@ function ModelSettingsPanel({
|
|
|
1070
3370
|
row.key
|
|
1071
3371
|
);
|
|
1072
3372
|
}) }, group.id)),
|
|
1073
|
-
capabilities ? /* @__PURE__ */
|
|
3373
|
+
capabilities ? /* @__PURE__ */ jsx9(
|
|
1074
3374
|
InputCapabilitiesEditor,
|
|
1075
3375
|
{
|
|
1076
3376
|
values: capabilities.values,
|
|
1077
3377
|
onChange: capabilities.change,
|
|
1078
3378
|
changedKeys: capabilities.changedKeys,
|
|
1079
3379
|
onReset: capabilities.resetToInherited,
|
|
1080
|
-
resetLabel
|
|
3380
|
+
resetLabel,
|
|
1081
3381
|
error: capabilities.error,
|
|
1082
3382
|
idPrefix: `${idPrefix}-capability`,
|
|
1083
3383
|
disabled
|
|
@@ -1088,7 +3388,7 @@ function ModelSettingsPanel({
|
|
|
1088
3388
|
|
|
1089
3389
|
// settings/react/index.ts
|
|
1090
3390
|
function useSettingsSelector(store, select) {
|
|
1091
|
-
return
|
|
3391
|
+
return useSyncExternalStore2(
|
|
1092
3392
|
store.subscribe,
|
|
1093
3393
|
() => select(store.getState()),
|
|
1094
3394
|
() => select(store.getState())
|
|
@@ -1112,13 +3412,9 @@ function memoEffective(entry) {
|
|
|
1112
3412
|
return hit;
|
|
1113
3413
|
}
|
|
1114
3414
|
export {
|
|
1115
|
-
ExtraSettingRow,
|
|
1116
|
-
InputCapabilitiesEditor,
|
|
1117
3415
|
ModelSettingsPanel,
|
|
1118
|
-
SettingControlInput,
|
|
1119
3416
|
SettingRowFrame,
|
|
1120
3417
|
RowLabel as SettingRowLabel,
|
|
1121
|
-
SettingsGroupSection,
|
|
1122
3418
|
formatSettingValue,
|
|
1123
3419
|
useEffectiveSettings,
|
|
1124
3420
|
useSettingsEntry,
|