@ai-matrx/agents 0.59.198 → 0.59.200

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.
@@ -2,7 +2,7 @@
2
2
  "use client";
3
3
 
4
4
  // settings/react/index.ts
5
- import { useSyncExternalStore as useSyncExternalStore2 } from "react";
5
+ import { useSyncExternalStore } from "react";
6
6
 
7
7
  // generated/llm-enums.ts
8
8
  var LLM_PARAMS_KEYS = [
@@ -81,168 +81,6 @@ 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
-
246
84
  // settings/ui-gates.ts
247
85
  var UI_GATE_KEYS = [
248
86
  "tools",
@@ -252,2141 +90,100 @@ var UI_GATE_KEYS = [
252
90
  ];
253
91
  var UI_GATE_EDITABLE_KEYS = [
254
92
  "image_urls",
255
- "file_urls",
256
- "youtube_videos"
257
- ];
258
- var UI_GATE_KEY_SET = new Set(UI_GATE_KEYS);
259
-
260
- // settings/logic.ts
261
- var ALL_KNOWN_KEYS = /* @__PURE__ */ new Set([
262
- ...LLM_PARAMS_KEYS,
263
- // Provider-native media-gen control names (moved from chat's retired parser,
264
- // so one parser recognizes everything chat did). Duplicates of generated keys are harmless.
265
- "aspect_ratio",
266
- "background",
267
- "duration",
268
- "duration_seconds",
269
- "encode_quality",
270
- "end_image",
271
- "enhance_prompt",
272
- "first_frame_image",
273
- "generate_audio",
274
- "image",
275
- "image_format",
276
- "image_input",
277
- "image_inputs",
278
- "image_size",
279
- "image_url",
280
- "include_rai_reason",
281
- "input_fidelity",
282
- "input_images",
283
- "last_frame",
284
- "last_frame_image",
285
- "mask",
286
- "media",
287
- "moderation",
288
- "num_outputs",
289
- "number_of_images",
290
- "output_compression",
291
- "output_mime_type",
292
- "output_quality",
293
- "partial_images",
294
- "person_generation",
295
- "prompt_image",
296
- "quality",
297
- "ratio",
298
- "reference_strength",
299
- "render_quality",
300
- "resolution",
301
- "seconds",
302
- "start_image",
303
- "start_image_url",
304
- "style",
305
- "video_action",
306
- "video_input",
307
- "multi_speaker",
308
- // Legacy DB keys — normalizer converts at Redux boundary, but we still recognize them
309
- "max_tokens",
310
- "output_format",
311
- "n",
312
- // Frontend-only capability flags (never sent to the API)
313
- "tools",
314
- "file_urls",
315
- "image_urls",
316
- "youtube_videos",
317
- "multi_speaker",
318
- "internal_web_search",
319
- "internal_url_context",
320
- // Backend param not yet in generated types
321
- "image_loras",
322
- // Stop sequences
323
- "stop_sequences"
324
- ]);
325
- var UI_ONLY_SET = new Set(UI_GATE_KEYS);
326
- function mergeEffectiveSettings(defaults, overrides) {
327
- const merged = { ...defaults };
328
- for (const [key, value] of Object.entries(overrides)) {
329
- if (value === null) delete merged[key];
330
- else if (value !== void 0) merged[key] = value;
331
- }
332
- return merged;
333
- }
334
-
335
- // settings/store.ts
336
- var EMPTY = Object.freeze({});
337
- function readSettingsEntry(state, agentId) {
338
- return agentId ? state.entries[agentId] : void 0;
339
- }
340
- function readEffectiveSettings(entry) {
341
- return entry ? mergeEffectiveSettings(entry.defaults, entry.overrides) : EMPTY;
342
- }
343
-
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";
403
- import {
404
- cn,
405
- Popover,
406
- PopoverTrigger,
407
- PopoverContent,
408
- Tooltip,
409
- TooltipContent,
410
- TooltipProvider,
411
- TooltipTrigger,
412
- selectTriggerVariants,
413
- Drawer,
414
- DrawerTrigger,
415
- DrawerContent,
416
- DrawerTitle,
417
- useDialogContainer,
418
- useIsMobile
419
- } from "@ai-matrx/design-system";
420
- import { Input } from "@ai-matrx/design-system/controls";
421
- import { MakerBrandGlyph, ServiceBrandGlyph } from "@ai-matrx/icons/brand-glyphs";
422
-
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 }]
526
- }
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
- ] });
597
- }
598
-
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
- );
617
- }
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" })
632
- ] });
633
- }
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
- ] });
640
- }
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,
819
- value,
820
- mono
821
- }) {
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",
826
- {
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"
833
- }
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",
863
- {
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
883
- }
884
- ),
885
- /* @__PURE__ */ jsx4(AdminRow, { label: "Priority", value: String(offering.priority), mono: true }),
886
- /* @__PURE__ */ jsx4(
887
- AdminRow,
888
- {
889
- label: "Points in",
890
- value: offering.pointsInput == null ? null : `${fmtPoints(offering.pointsInput)} / 1M`,
891
- mono: true
892
- }
893
- ),
894
- /* @__PURE__ */ jsx4(
895
- AdminRow,
896
- {
897
- label: "Points out",
898
- value: offering.pointsOutput == null ? null : `${fmtPoints(offering.pointsOutput)} / 1M`,
899
- mono: true
900
- }
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,
964
- {
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",
1145
- {
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"
1150
- }
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",
1175
- {
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
1184
- }
1185
- );
1186
- }
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({
1234
- value,
1235
- onChange,
1236
- yesLabel,
1237
- noLabel
1238
- }) {
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,
1306
- {
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
1330
- },
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"
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
1448
- },
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
- ] })
1489
- ] });
1490
- }
1491
- function ModelRow({
1492
- model,
1493
- classTier,
1494
- tier,
1495
- variant,
1496
- selected,
1497
- isFavorite,
1498
- locked = false,
1499
- onSelect,
1500
- onHover,
1501
- onToggleFavorite
1502
- }) {
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"
1562
- }
1563
- ),
1564
- model.isDeprecated && !retired && /* @__PURE__ */ jsx4(
1565
- "span",
1566
- {
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)
1601
- }
1602
- )
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
- );
93
+ "file_urls",
94
+ "youtube_videos"
95
+ ];
96
+ var UI_GATE_KEY_SET = new Set(UI_GATE_KEYS);
97
+
98
+ // settings/logic.ts
99
+ var ALL_KNOWN_KEYS = /* @__PURE__ */ new Set([
100
+ ...LLM_PARAMS_KEYS,
101
+ // Provider-native media-gen control names (moved from chat's retired parser,
102
+ // so one parser recognizes everything chat did). Duplicates of generated keys are harmless.
103
+ "aspect_ratio",
104
+ "background",
105
+ "duration",
106
+ "duration_seconds",
107
+ "encode_quality",
108
+ "end_image",
109
+ "enhance_prompt",
110
+ "first_frame_image",
111
+ "generate_audio",
112
+ "image",
113
+ "image_format",
114
+ "image_input",
115
+ "image_inputs",
116
+ "image_size",
117
+ "image_url",
118
+ "include_rai_reason",
119
+ "input_fidelity",
120
+ "input_images",
121
+ "last_frame",
122
+ "last_frame_image",
123
+ "mask",
124
+ "media",
125
+ "moderation",
126
+ "num_outputs",
127
+ "number_of_images",
128
+ "output_compression",
129
+ "output_mime_type",
130
+ "output_quality",
131
+ "partial_images",
132
+ "person_generation",
133
+ "prompt_image",
134
+ "quality",
135
+ "ratio",
136
+ "reference_strength",
137
+ "render_quality",
138
+ "resolution",
139
+ "seconds",
140
+ "start_image",
141
+ "start_image_url",
142
+ "style",
143
+ "video_action",
144
+ "video_input",
145
+ "multi_speaker",
146
+ // Legacy DB keys — normalizer converts at Redux boundary, but we still recognize them
147
+ "max_tokens",
148
+ "output_format",
149
+ "n",
150
+ // Frontend-only capability flags (never sent to the API)
151
+ "tools",
152
+ "file_urls",
153
+ "image_urls",
154
+ "youtube_videos",
155
+ "multi_speaker",
156
+ "internal_web_search",
157
+ "internal_url_context",
158
+ // Backend param not yet in generated types
159
+ "image_loras",
160
+ // Stop sequences
161
+ "stop_sequences"
162
+ ]);
163
+ var UI_ONLY_SET = new Set(UI_GATE_KEYS);
164
+ function mergeEffectiveSettings(defaults, overrides) {
165
+ const merged = { ...defaults };
166
+ for (const [key, value] of Object.entries(overrides)) {
167
+ if (value === null) delete merged[key];
168
+ else if (value !== void 0) merged[key] = value;
169
+ }
170
+ return merged;
1622
171
  }
1623
- function LocalModelRow({ model, selected, onSelect }) {
1624
- const dim = model.needsMoreMemory === true;
1625
- return /* @__PURE__ */ jsxs3(
1626
- "div",
1627
- {
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,
1633
- onKeyDown: (e) => {
1634
- if (e.key === "Enter" || e.key === " ") {
1635
- e.preventDefault();
1636
- onSelect();
1637
- }
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
- );
172
+
173
+ // settings/store.ts
174
+ var EMPTY = Object.freeze({});
175
+ function readSettingsEntry(state, agentId) {
176
+ return agentId ? state.entries[agentId] : void 0;
1665
177
  }
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,
2001
- disabled,
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
- ] });
178
+ function readEffectiveSettings(entry) {
179
+ return entry ? mergeEffectiveSettings(entry.defaults, entry.overrides) : EMPTY;
2388
180
  }
2389
181
 
182
+ // settings/react/ModelSettingsPanel.tsx
183
+ import { Checkbox as Checkbox2 } from "@ai-matrx/design-system";
184
+ import { Button as Button2, Chip, Switch as Switch2 } from "@ai-matrx/design-system/controls";
185
+ import { ModelListDropdown } from "@ai-matrx/agents/models/react";
186
+
2390
187
  // settings/settings-catalogue.ts
2391
188
  import { humanizeIdentifier } from "@ai-matrx/kit/text-case";
2392
189
  var CONTROL_TYPES = [
@@ -2601,9 +398,9 @@ import { ErrorBox } from "@ai-matrx/design-system";
2601
398
  import { Button, Switch } from "@ai-matrx/design-system/controls";
2602
399
 
2603
400
  // settings/react/settings-icons.tsx
2604
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2605
- function Svg3({ className, children }) {
2606
- return /* @__PURE__ */ jsx5(
401
+ import { jsx, jsxs } from "react/jsx-runtime";
402
+ function Svg({ className, children }) {
403
+ return /* @__PURE__ */ jsx(
2607
404
  "svg",
2608
405
  {
2609
406
  xmlns: "http://www.w3.org/2000/svg",
@@ -2619,98 +416,98 @@ function Svg3({ className, children }) {
2619
416
  }
2620
417
  );
2621
418
  }
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" })
419
+ var CircleCheckGlyph = ({ className }) => /* @__PURE__ */ jsxs(Svg, { className, children: [
420
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
421
+ /* @__PURE__ */ jsx("path", { d: "m16 9-5.5 5.5L8 12" })
2625
422
  ] });
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" })
423
+ var TriangleAlertGlyph = ({ className }) => /* @__PURE__ */ jsxs(Svg, { className, children: [
424
+ /* @__PURE__ */ jsx("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" }),
425
+ /* @__PURE__ */ jsx("path", { d: "M12 9v4" }),
426
+ /* @__PURE__ */ jsx("path", { d: "M12 17h.01" })
2630
427
  ] });
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" })
428
+ var VariableGlyph = ({ className }) => /* @__PURE__ */ jsxs(Svg, { className, children: [
429
+ /* @__PURE__ */ jsx("path", { d: "M8 21s-4-3-4-9 4-9 4-9" }),
430
+ /* @__PURE__ */ jsx("path", { d: "M16 3s4 3 4 9-4 9-4 9" }),
431
+ /* @__PURE__ */ jsx("line", { x1: "15", x2: "9", y1: "9", y2: "15" }),
432
+ /* @__PURE__ */ jsx("line", { x1: "9", x2: "15", y1: "9", y2: "15" })
2636
433
  ] });
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" })
434
+ var UnlinkGlyph = ({ className }) => /* @__PURE__ */ jsxs(Svg, { className, children: [
435
+ /* @__PURE__ */ jsx("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" }),
436
+ /* @__PURE__ */ jsx("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" }),
437
+ /* @__PURE__ */ jsx("line", { x1: "8", x2: "8", y1: "2", y2: "5" }),
438
+ /* @__PURE__ */ jsx("line", { x1: "2", x2: "5", y1: "8", y2: "8" }),
439
+ /* @__PURE__ */ jsx("line", { x1: "16", x2: "16", y1: "19", y2: "22" }),
440
+ /* @__PURE__ */ jsx("line", { x1: "19", x2: "22", y1: "16", y2: "16" })
2644
441
  ] });
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" })
442
+ var WrenchGlyph = ({ className }) => /* @__PURE__ */ jsx(Svg, { className, children: /* @__PURE__ */ jsx("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" }) });
443
+ var Trash2Glyph = ({ className }) => /* @__PURE__ */ jsxs(Svg, { className, children: [
444
+ /* @__PURE__ */ jsx("path", { d: "M10 11v6" }),
445
+ /* @__PURE__ */ jsx("path", { d: "M14 11v6" }),
446
+ /* @__PURE__ */ jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
447
+ /* @__PURE__ */ jsx("path", { d: "M3 6h18" }),
448
+ /* @__PURE__ */ jsx("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
2652
449
  ] });
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" })
450
+ var RotateCcwGlyph = ({ className }) => /* @__PURE__ */ jsxs(Svg, { className, children: [
451
+ /* @__PURE__ */ jsx("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
452
+ /* @__PURE__ */ jsx("path", { d: "M3 3v5h5" })
2656
453
  ] });
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" })
454
+ var ImageGlyph = ({ className }) => /* @__PURE__ */ jsxs(Svg, { className, children: [
455
+ /* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
456
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "2" }),
457
+ /* @__PURE__ */ jsx("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
2661
458
  ] });
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" })
459
+ var FileTextGlyph = ({ className }) => /* @__PURE__ */ jsxs(Svg, { className, children: [
460
+ /* @__PURE__ */ jsx("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
461
+ /* @__PURE__ */ jsx("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" }),
462
+ /* @__PURE__ */ jsx("path", { d: "M10 9H8" }),
463
+ /* @__PURE__ */ jsx("path", { d: "M16 13H8" }),
464
+ /* @__PURE__ */ jsx("path", { d: "M16 17H8" })
2668
465
  ] });
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" })
466
+ var YoutubeGlyph = ({ className }) => /* @__PURE__ */ jsxs(Svg, { className, children: [
467
+ /* @__PURE__ */ jsx("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" }),
468
+ /* @__PURE__ */ jsx("path", { d: "m10 15 5-3-5-3z" })
2672
469
  ] });
2673
470
 
2674
471
  // settings/react/SettingRowFrame.tsx
2675
472
  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(" ");
473
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
474
+ var cn = (...parts) => parts.filter(Boolean).join(" ");
2678
475
  function formatSettingValue(value) {
2679
476
  if (typeof value === "boolean") return value ? "On" : "Off";
2680
477
  if (value !== null && typeof value === "object") return JSON.stringify(value);
2681
478
  return String(value);
2682
479
  }
2683
480
  function SettingRowFrame({ rowKey, state, leading, label, children, actions }) {
2684
- return /* @__PURE__ */ jsxs5(
481
+ return /* @__PURE__ */ jsxs2(
2685
482
  "div",
2686
483
  {
2687
484
  "data-setting-row": rowKey,
2688
485
  "data-setting-state": state,
2689
486
  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]",
2690
487
  children: [
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 })
488
+ /* @__PURE__ */ jsx2("div", { className: "flex h-7 items-center", children: leading }),
489
+ /* @__PURE__ */ jsx2("div", { className: "flex min-h-7 min-w-0 items-center", children: label }),
490
+ children !== void 0 ? /* @__PURE__ */ jsx2("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,
491
+ /* @__PURE__ */ jsx2("div", { className: "col-start-3 row-start-1 flex min-h-7 items-center justify-end @md:col-start-4", children: actions })
2695
492
  ]
2696
493
  }
2697
494
  );
2698
495
  }
2699
496
  function RowLabel({ htmlFor, muted, children }) {
2700
- return /* @__PURE__ */ jsx6(Label, { htmlFor, className: cn2("min-w-0 truncate type-body", muted ? "text-muted-foreground" : "text-foreground"), children });
497
+ return /* @__PURE__ */ jsx2(Label, { htmlFor, className: cn("min-w-0 truncate type-body", muted ? "text-muted-foreground" : "text-foreground"), children });
2701
498
  }
2702
499
  function RowText({ children, mono }) {
2703
- return /* @__PURE__ */ jsx6("span", { className: cn2("flex min-h-7 items-center truncate type-secondary text-muted-foreground", mono && "font-mono"), children });
500
+ return /* @__PURE__ */ jsx2("span", { className: cn("flex min-h-7 items-center truncate type-secondary text-muted-foreground", mono && "font-mono"), children });
2704
501
  }
2705
502
  function SettingsGroupSection({ id, title, children }) {
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,
503
+ return /* @__PURE__ */ jsxs2("section", { "data-settings-group": id, className: title ? "mt-2 border-t border-border pt-2" : void 0, children: [
504
+ title ? /* @__PURE__ */ jsx2("h3", { className: "pb-1 type-title text-foreground", children: title }) : null,
2708
505
  children
2709
506
  ] });
2710
507
  }
2711
508
 
2712
509
  // settings/react/InputCapabilitiesEditor.tsx
2713
- import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
510
+ import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
2714
511
  var GATE_META = {
2715
512
  image_urls: {
2716
513
  label: "Image URLs",
@@ -2739,24 +536,24 @@ function InputCapabilitiesEditor({
2739
536
  title = "Input Capabilities",
2740
537
  disabled = false
2741
538
  }) {
2742
- return /* @__PURE__ */ jsxs6(SettingsGroupSection, { id: "input-capabilities", title, children: [
539
+ return /* @__PURE__ */ jsxs3(SettingsGroupSection, { id: "input-capabilities", title, children: [
2743
540
  UI_GATE_EDITABLE_KEYS.map((key) => {
2744
541
  const { label, description, Icon } = GATE_META[key];
2745
542
  const switchId = `${idPrefix}-${key}`;
2746
543
  const changed = changedKeys?.has(key) === true;
2747
- return /* @__PURE__ */ jsx7(
544
+ return /* @__PURE__ */ jsx3(
2748
545
  SettingRowFrame,
2749
546
  {
2750
547
  rowKey: key,
2751
548
  state: values[key] === true ? "on" : "off",
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(
549
+ leading: /* @__PURE__ */ jsx3(Icon, { className: "h-4 w-4 text-muted-foreground" }),
550
+ label: /* @__PURE__ */ jsx3(RowLabel, { htmlFor: switchId, children: label }),
551
+ actions: /* @__PURE__ */ jsxs3(Fragment, { children: [
552
+ changed && onReset ? /* @__PURE__ */ jsx3(
2756
553
  Button,
2757
554
  {
2758
555
  variant: "quiet",
2759
- icon: /* @__PURE__ */ jsx7(RotateCcwGlyph, {}),
556
+ icon: /* @__PURE__ */ jsx3(RotateCcwGlyph, {}),
2760
557
  onClick: () => onReset(key),
2761
558
  disabled,
2762
559
  "aria-label": `${resetLabel}: ${label}`,
@@ -2764,7 +561,7 @@ function InputCapabilitiesEditor({
2764
561
  "data-setting-reset": key
2765
562
  }
2766
563
  ) : null,
2767
- /* @__PURE__ */ jsx7(
564
+ /* @__PURE__ */ jsx3(
2768
565
  Switch,
2769
566
  {
2770
567
  id: switchId,
@@ -2774,20 +571,20 @@ function InputCapabilitiesEditor({
2774
571
  }
2775
572
  )
2776
573
  ] }),
2777
- children: /* @__PURE__ */ jsx7(RowText, { children: description })
574
+ children: /* @__PURE__ */ jsx3(RowText, { children: description })
2778
575
  },
2779
576
  key
2780
577
  );
2781
578
  }),
2782
- error ? /* @__PURE__ */ jsx7(ErrorBox, { as: "p", className: "py-1 type-meta text-destructive", message: error }) : null
579
+ error ? /* @__PURE__ */ jsx3(ErrorBox, { as: "p", className: "py-1 type-meta text-destructive", message: error }) : null
2783
580
  ] });
2784
581
  }
2785
582
 
2786
583
  // settings/react/SettingControlInput.tsx
2787
- import { useEffect as useEffect3, useState as useState2 } from "react";
584
+ import { useEffect, useState } from "react";
2788
585
  import {
2789
586
  Checkbox,
2790
- Input as Input2,
587
+ Input,
2791
588
  Label as Label2,
2792
589
  Select,
2793
590
  SelectContent,
@@ -2796,13 +593,13 @@ import {
2796
593
  SelectValue,
2797
594
  Slider,
2798
595
  Textarea,
2799
- Tooltip as Tooltip2,
2800
- TooltipContent as TooltipContent2,
2801
- TooltipProvider as TooltipProvider2,
2802
- TooltipTrigger as TooltipTrigger2
596
+ Tooltip,
597
+ TooltipContent,
598
+ TooltipProvider,
599
+ TooltipTrigger
2803
600
  } from "@ai-matrx/design-system";
2804
601
  import { AspectRatioSelect, OptionCombobox, isAspectRatioOptionSet } from "@ai-matrx/design-system/controls";
2805
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
602
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
2806
603
  var SELECT_MAX_OPTIONS = 12;
2807
604
  function choiceFor(options) {
2808
605
  if (isAspectRatioOptionSet(options)) return "aspect-ratio";
@@ -2810,10 +607,10 @@ function choiceFor(options) {
2810
607
  return "select";
2811
608
  }
2812
609
  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" })
610
+ return /* @__PURE__ */ jsxs4("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: [
611
+ /* @__PURE__ */ jsx4("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" }),
612
+ /* @__PURE__ */ jsx4("path", { d: "M12 9v4" }),
613
+ /* @__PURE__ */ jsx4("path", { d: "M12 17h.01" })
2817
614
  ] });
2818
615
  }
2819
616
  function flattenTypeObject(value) {
@@ -2837,7 +634,7 @@ function SettingControlInput({
2837
634
  const isValueMismatch = stringValue !== "" && !control.enum.includes(stringValue);
2838
635
  const emit = (v) => onChange(settingKey === "response_format" ? { type: v } : v);
2839
636
  const choice = choiceFor(control.enum);
2840
- const picker = choice === "aspect-ratio" ? /* @__PURE__ */ jsx8(
637
+ const picker = choice === "aspect-ratio" ? /* @__PURE__ */ jsx4(
2841
638
  AspectRatioSelect,
2842
639
  {
2843
640
  value: isValueMismatch ? "" : stringValue,
@@ -2848,7 +645,7 @@ function SettingControlInput({
2848
645
  id: inputId,
2849
646
  placeholder: "Default"
2850
647
  }
2851
- ) : choice === "searchable" ? /* @__PURE__ */ jsx8(
648
+ ) : choice === "searchable" ? /* @__PURE__ */ jsx4(
2852
649
  OptionCombobox,
2853
650
  {
2854
651
  value: isValueMismatch ? "" : stringValue,
@@ -2860,23 +657,23 @@ function SettingControlInput({
2860
657
  placeholder: "Default"
2861
658
  }
2862
659
  ) : null;
2863
- return /* @__PURE__ */ jsxs7("div", { className: "flex flex-1 items-center gap-1.5", children: [
2864
- picker ?? /* @__PURE__ */ jsxs7(
660
+ return /* @__PURE__ */ jsxs4("div", { className: "flex flex-1 items-center gap-1.5", children: [
661
+ picker ?? /* @__PURE__ */ jsxs4(
2865
662
  Select,
2866
663
  {
2867
664
  value: isValueMismatch ? "" : stringValue,
2868
665
  onValueChange: emit,
2869
666
  disabled,
2870
667
  children: [
2871
- /* @__PURE__ */ jsx8(
668
+ /* @__PURE__ */ jsx4(
2872
669
  SelectTrigger,
2873
670
  {
2874
671
  id: inputId,
2875
672
  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" })
673
+ children: /* @__PURE__ */ jsx4(SelectValue, { placeholder: isValueMismatch ? stringValue : "Default" })
2877
674
  }
2878
675
  ),
2879
- /* @__PURE__ */ jsx8(SelectContent, { className: "text-xs", children: control.enum.map((option) => /* @__PURE__ */ jsx8(
676
+ /* @__PURE__ */ jsx4(SelectContent, { className: "text-xs", children: control.enum.map((option) => /* @__PURE__ */ jsx4(
2880
677
  SelectItem,
2881
678
  {
2882
679
  value: option,
@@ -2888,9 +685,9 @@ function SettingControlInput({
2888
685
  ]
2889
686
  }
2890
687
  ),
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: [
688
+ isValueMismatch && /* @__PURE__ */ jsx4(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs4(Tooltip, { children: [
689
+ /* @__PURE__ */ jsx4(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx4("span", { className: "shrink-0 cursor-help text-amber-500", children: /* @__PURE__ */ jsx4(WarningIcon, { className: "h-3.5 w-3.5" }) }) }),
690
+ /* @__PURE__ */ jsxs4(TooltipContent, { side: "top", className: "max-w-[220px] type-secondary", children: [
2894
691
  '"',
2895
692
  stringValue,
2896
693
  '" is not a recognized option for this model'
@@ -2899,8 +696,8 @@ function SettingControlInput({
2899
696
  ] });
2900
697
  }
2901
698
  if (control.type === "boolean") {
2902
- return /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
2903
- /* @__PURE__ */ jsx8(
699
+ return /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
700
+ /* @__PURE__ */ jsx4(
2904
701
  Checkbox,
2905
702
  {
2906
703
  id: inputId,
@@ -2910,7 +707,7 @@ function SettingControlInput({
2910
707
  className: "cursor-pointer"
2911
708
  }
2912
709
  ),
2913
- /* @__PURE__ */ jsx8(
710
+ /* @__PURE__ */ jsx4(
2914
711
  Label2,
2915
712
  {
2916
713
  htmlFor: inputId,
@@ -2923,7 +720,7 @@ function SettingControlInput({
2923
720
  if (control.type === "number" || control.type === "integer") {
2924
721
  const numeric = typeof value === "number" ? value : void 0;
2925
722
  const hasRange = control.min !== void 0 && control.max !== void 0;
2926
- return /* @__PURE__ */ jsx8(
723
+ return /* @__PURE__ */ jsx4(
2927
724
  NumberInput,
2928
725
  {
2929
726
  value: numeric,
@@ -2941,7 +738,7 @@ function SettingControlInput({
2941
738
  }
2942
739
  if (control.type === "string_array") {
2943
740
  const arrayValue = Array.isArray(value) ? value.join("\n") : "";
2944
- return /* @__PURE__ */ jsx8(
741
+ return /* @__PURE__ */ jsx4(
2945
742
  Textarea,
2946
743
  {
2947
744
  id: inputId,
@@ -2954,7 +751,7 @@ function SettingControlInput({
2954
751
  );
2955
752
  }
2956
753
  if (control.type === "array" || control.type === "object_array" || typeof value === "object" && value !== null) {
2957
- return /* @__PURE__ */ jsx8(
754
+ return /* @__PURE__ */ jsx4(
2958
755
  JsonValueInput,
2959
756
  {
2960
757
  id: inputId,
@@ -2964,8 +761,8 @@ function SettingControlInput({
2964
761
  }
2965
762
  );
2966
763
  }
2967
- return /* @__PURE__ */ jsx8(
2968
- Input2,
764
+ return /* @__PURE__ */ jsx4(
765
+ Input,
2969
766
  {
2970
767
  id: inputId,
2971
768
  type: "text",
@@ -2983,14 +780,14 @@ function JsonValueInput({
2983
780
  disabled
2984
781
  }) {
2985
782
  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(() => {
783
+ const [draft, setDraft] = useState(() => toText(value));
784
+ const [jsonError, setJsonError] = useState(null);
785
+ useEffect(() => {
2989
786
  setDraft(toText(value));
2990
787
  setJsonError(null);
2991
788
  }, [JSON.stringify(value)]);
2992
- return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-1", children: [
2993
- /* @__PURE__ */ jsx8(
789
+ return /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-1", children: [
790
+ /* @__PURE__ */ jsx4(
2994
791
  Textarea,
2995
792
  {
2996
793
  id,
@@ -3017,7 +814,7 @@ function JsonValueInput({
3017
814
  spellCheck: false
3018
815
  }
3019
816
  ),
3020
- jsonError && /* @__PURE__ */ jsx8("p", { className: "type-meta text-amber-600 dark:text-amber-400", children: jsonError })
817
+ jsonError && /* @__PURE__ */ jsx4("p", { className: "type-meta text-amber-600 dark:text-amber-400", children: jsonError })
3021
818
  ] });
3022
819
  }
3023
820
  function NumberInput({
@@ -3033,7 +830,7 @@ function NumberInput({
3033
830
  withSlider = false
3034
831
  }) {
3035
832
  const boxClass = "h-7 px-2 text-xs tabular-nums pointer-coarse:h-11";
3036
- const [draftState, setDraftState] = useState2(() => ({
833
+ const [draftState, setDraftState] = useState(() => ({
3037
834
  sourceValue: value,
3038
835
  text: value === void 0 ? "" : String(value)
3039
836
  }));
@@ -3051,12 +848,12 @@ function NumberInput({
3051
848
  } else setDraft(shown);
3052
849
  };
3053
850
  if (withSlider) {
3054
- return /* @__PURE__ */ jsxs7(
851
+ return /* @__PURE__ */ jsxs4(
3055
852
  "div",
3056
853
  {
3057
854
  className: "grid grid-cols-[1fr_4.5rem] items-center gap-2",
3058
855
  children: [
3059
- /* @__PURE__ */ jsx8(
856
+ /* @__PURE__ */ jsx4(
3060
857
  Slider,
3061
858
  {
3062
859
  ...min !== void 0 ? { min } : {},
@@ -3074,8 +871,8 @@ function NumberInput({
3074
871
  disabled
3075
872
  }
3076
873
  ),
3077
- /* @__PURE__ */ jsx8(
3078
- Input2,
874
+ /* @__PURE__ */ jsx4(
875
+ Input,
3079
876
  {
3080
877
  type: "text",
3081
878
  inputMode: "decimal",
@@ -3095,8 +892,8 @@ function NumberInput({
3095
892
  }
3096
893
  );
3097
894
  }
3098
- return /* @__PURE__ */ jsx8(
3099
- Input2,
895
+ return /* @__PURE__ */ jsx4(
896
+ Input,
3100
897
  {
3101
898
  type: "text",
3102
899
  inputMode: "decimal",
@@ -3115,28 +912,28 @@ function NumberInput({
3115
912
  }
3116
913
 
3117
914
  // settings/react/ModelSettingsPanel.tsx
3118
- import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
915
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
3119
916
  function StatusGlyph({ issue, source }) {
3120
917
  const title = issue ? issue.message : source ? `Valid \xB7 ${source}` : "Valid";
3121
- return /* @__PURE__ */ jsx9(
918
+ return /* @__PURE__ */ jsx5(
3122
919
  "span",
3123
920
  {
3124
- className: cn2("inline-flex h-7 w-6 shrink-0 items-center justify-center", issue ? "text-warning" : "text-success"),
921
+ className: cn("inline-flex h-7 w-6 shrink-0 items-center justify-center", issue ? "text-warning" : "text-success"),
3125
922
  role: "img",
3126
923
  "aria-label": title,
3127
924
  title,
3128
- children: issue ? /* @__PURE__ */ jsx9(TriangleAlertGlyph, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx9(CircleCheckGlyph, { className: "h-3.5 w-3.5" })
925
+ children: issue ? /* @__PURE__ */ jsx5(TriangleAlertGlyph, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx5(CircleCheckGlyph, { className: "h-3.5 w-3.5" })
3129
926
  }
3130
927
  );
3131
928
  }
3132
929
  function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
3133
930
  const read = target.read(row.key, control);
3134
931
  const resetLabel = target.resetLabel ?? "Reset to agent";
3135
- const reset = read.changedHere && target.resetToInherited ? /* @__PURE__ */ jsx9(
932
+ const reset = read.changedHere && target.resetToInherited ? /* @__PURE__ */ jsx5(
3136
933
  Button2,
3137
934
  {
3138
935
  variant: "quiet",
3139
- icon: /* @__PURE__ */ jsx9(RotateCcwGlyph, {}),
936
+ icon: /* @__PURE__ */ jsx5(RotateCcwGlyph, {}),
3140
937
  onClick: () => target.resetToInherited?.(row.key),
3141
938
  disabled,
3142
939
  "aria-label": `${resetLabel}: ${row.label}`,
@@ -3145,20 +942,20 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
3145
942
  }
3146
943
  ) : null;
3147
944
  if (read.state === "bound") {
3148
- return /* @__PURE__ */ jsx9(
945
+ return /* @__PURE__ */ jsx5(
3149
946
  SettingRowFrame,
3150
947
  {
3151
948
  rowKey: row.key,
3152
949
  state: "bound",
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: [
950
+ leading: /* @__PURE__ */ jsx5(Checkbox2, { checked: true, disabled: true, "aria-label": `${row.label} is a run input` }),
951
+ label: /* @__PURE__ */ jsx5(RowLabel, { children: row.label }),
952
+ actions: /* @__PURE__ */ jsxs5(Fragment2, { children: [
3156
953
  reset,
3157
- target.unbind ? /* @__PURE__ */ jsx9(
954
+ target.unbind ? /* @__PURE__ */ jsx5(
3158
955
  Button2,
3159
956
  {
3160
957
  variant: "quiet",
3161
- icon: /* @__PURE__ */ jsx9(UnlinkGlyph, {}),
958
+ icon: /* @__PURE__ */ jsx5(UnlinkGlyph, {}),
3162
959
  onClick: () => target.unbind?.(row.key, control),
3163
960
  disabled,
3164
961
  "aria-label": `Make ${row.label} a fixed setting`,
@@ -3166,9 +963,9 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
3166
963
  }
3167
964
  ) : null
3168
965
  ] }),
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) })
966
+ children: /* @__PURE__ */ jsxs5("span", { className: "flex min-h-7 min-w-0 items-center gap-2", "data-bound-control": row.key, children: [
967
+ /* @__PURE__ */ jsx5(Chip, { tone: "primary", icon: /* @__PURE__ */ jsx5(VariableGlyph, {}), label: `{{${read.variableName}}}` }),
968
+ /* @__PURE__ */ jsx5("span", { className: "truncate type-meta text-muted-foreground", children: read.value === void 0 || read.value === null || read.value === "" ? "Model default" : formatSettingValue(read.value) })
3172
969
  ] })
3173
970
  }
3174
971
  );
@@ -3178,12 +975,12 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
3178
975
  const isOff = isSet && isOffValue(value, control);
3179
976
  const checkboxId = `${idPrefix}-setting-${row.key}`;
3180
977
  const canBind = Boolean(target.bind) && (target.canBind?.(row.key) ?? true);
3181
- return /* @__PURE__ */ jsx9(
978
+ return /* @__PURE__ */ jsx5(
3182
979
  SettingRowFrame,
3183
980
  {
3184
981
  rowKey: row.key,
3185
982
  state: isOff ? "off" : read.state,
3186
- leading: /* @__PURE__ */ jsx9(
983
+ leading: /* @__PURE__ */ jsx5(
3187
984
  Checkbox2,
3188
985
  {
3189
986
  id: checkboxId,
@@ -3192,14 +989,14 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
3192
989
  onCheckedChange: (next) => next === true ? target.turnOn(row.key, control) : target.clear(row.key)
3193
990
  }
3194
991
  ),
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(
992
+ label: /* @__PURE__ */ jsx5(RowLabel, { htmlFor: checkboxId, muted: !isSet, children: row.label }),
993
+ actions: /* @__PURE__ */ jsxs5(Fragment2, { children: [
994
+ /* @__PURE__ */ jsx5(StatusGlyph, { issue: read.issue, source: read.source }),
995
+ canBind ? /* @__PURE__ */ jsx5(
3199
996
  Button2,
3200
997
  {
3201
998
  variant: "quiet",
3202
- icon: /* @__PURE__ */ jsx9(VariableGlyph, {}),
999
+ icon: /* @__PURE__ */ jsx5(VariableGlyph, {}),
3203
1000
  onClick: () => target.bind?.(row.key, control),
3204
1001
  disabled,
3205
1002
  "aria-label": `Make ${row.label} a run input`,
@@ -3207,11 +1004,11 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
3207
1004
  "data-bind-control": row.key
3208
1005
  }
3209
1006
  ) : null,
3210
- isSet && read.issue?.fixable && target.fix ? /* @__PURE__ */ jsx9(
1007
+ isSet && read.issue?.fixable && target.fix ? /* @__PURE__ */ jsx5(
3211
1008
  Button2,
3212
1009
  {
3213
1010
  variant: "quiet",
3214
- icon: /* @__PURE__ */ jsx9(WrenchGlyph, {}),
1011
+ icon: /* @__PURE__ */ jsx5(WrenchGlyph, {}),
3215
1012
  onClick: () => target.fix?.(row.key),
3216
1013
  disabled,
3217
1014
  "aria-label": `Fix ${row.label} automatically`,
@@ -3219,12 +1016,12 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
3219
1016
  }
3220
1017
  ) : null,
3221
1018
  reset,
3222
- isSet ? /* @__PURE__ */ jsx9(
1019
+ isSet ? /* @__PURE__ */ jsx5(
3223
1020
  Button2,
3224
1021
  {
3225
1022
  variant: "quiet",
3226
1023
  removes: true,
3227
- icon: /* @__PURE__ */ jsx9(Trash2Glyph, {}),
1024
+ icon: /* @__PURE__ */ jsx5(Trash2Glyph, {}),
3228
1025
  onClick: () => target.clear(row.key),
3229
1026
  disabled,
3230
1027
  "aria-label": `Clear ${row.label} to not set`,
@@ -3233,8 +1030,8 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
3233
1030
  }
3234
1031
  ) : null
3235
1032
  ] }),
3236
- children: isSet ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
3237
- /* @__PURE__ */ jsx9(
1033
+ children: isSet ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
1034
+ /* @__PURE__ */ jsx5(
3238
1035
  SettingControlInput,
3239
1036
  {
3240
1037
  settingKey: row.key,
@@ -3245,40 +1042,40 @@ function ModelSettingRow({ row, control, target, idPrefix, disabled }) {
3245
1042
  id: `${idPrefix}-control-${row.key}`
3246
1043
  }
3247
1044
  ),
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" })
1045
+ read.issue ? /* @__PURE__ */ jsx5("p", { className: "pt-1 type-meta text-warning-ink", children: read.issue.message }) : null
1046
+ ] }) : /* @__PURE__ */ jsx5(RowText, { children: read.modelDefault !== void 0 && read.modelDefault !== null ? `Not set \xB7 Model default: ${formatSettingValue(read.modelDefault)}` : "Not set" })
3250
1047
  }
3251
1048
  );
3252
1049
  }
3253
1050
  function ExtraSettingRow({ rowKey, label, value, kind, onClear, onReset, resetLabel = "Reset to agent", disabled = false }) {
3254
- return /* @__PURE__ */ jsx9(
1051
+ return /* @__PURE__ */ jsx5(
3255
1052
  SettingRowFrame,
3256
1053
  {
3257
1054
  rowKey,
3258
1055
  state: kind,
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 })
1056
+ label: /* @__PURE__ */ jsx5(RowLabel, { children: label }),
1057
+ actions: /* @__PURE__ */ jsxs5(Fragment2, { children: [
1058
+ kind === "translated" ? /* @__PURE__ */ jsx5(Chip, { tone: "sky", label: "Translated", title: "Kept as set and sent as this model's closest equivalent" }) : /* @__PURE__ */ jsx5(Chip, { tone: "warning", label: "Not on this model", title: "This model has no such setting" }),
1059
+ onReset ? /* @__PURE__ */ jsx5(Button2, { variant: "quiet", icon: /* @__PURE__ */ jsx5(RotateCcwGlyph, {}), onClick: onReset, disabled, "aria-label": `${resetLabel}: ${label}`, title: resetLabel, "data-setting-reset": rowKey }) : /* @__PURE__ */ jsx5(Button2, { variant: "quiet", removes: true, icon: /* @__PURE__ */ jsx5(Trash2Glyph, {}), onClick: onClear, disabled, "aria-label": `Clear ${label}`, title: "Clear to not set", "data-setting-clear": rowKey })
3263
1060
  ] }),
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) })
1061
+ children: /* @__PURE__ */ jsx5(RowText, { mono: value !== void 0 && value !== null, children: value === void 0 || value === null ? "Not set" : isOffValue(value, null) ? "Off" : formatSettingValue(value) })
3265
1062
  }
3266
1063
  );
3267
1064
  }
3268
- function ModelRow2({ model, resetLabel, idPrefix, disabled }) {
1065
+ function ModelRow({ model, resetLabel, idPrefix, disabled }) {
3269
1066
  const off = disabled || model.disabled === true;
3270
1067
  const oneMessageId = `${idPrefix}-model-one-message`;
3271
- return /* @__PURE__ */ jsx9(
1068
+ return /* @__PURE__ */ jsx5(
3272
1069
  SettingRowFrame,
3273
1070
  {
3274
1071
  rowKey: "model",
3275
1072
  state: model.value ? "set" : "unset",
3276
- label: /* @__PURE__ */ jsx9(RowLabel, { children: "Model" }),
3277
- actions: model.changedHere && model.resetToInherited ? /* @__PURE__ */ jsx9(
1073
+ label: /* @__PURE__ */ jsx5(RowLabel, { children: "Model" }),
1074
+ actions: model.changedHere && model.resetToInherited ? /* @__PURE__ */ jsx5(
3278
1075
  Button2,
3279
1076
  {
3280
1077
  variant: "quiet",
3281
- icon: /* @__PURE__ */ jsx9(RotateCcwGlyph, {}),
1078
+ icon: /* @__PURE__ */ jsx5(RotateCcwGlyph, {}),
3282
1079
  onClick: () => model.resetToInherited?.(),
3283
1080
  disabled: off,
3284
1081
  "aria-label": `${resetLabel}: Model`,
@@ -3286,8 +1083,8 @@ function ModelRow2({ model, resetLabel, idPrefix, disabled }) {
3286
1083
  "data-setting-reset": "model"
3287
1084
  }
3288
1085
  ) : 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(
1086
+ children: /* @__PURE__ */ jsxs5("div", { className: "flex min-h-7 min-w-0 flex-wrap items-center gap-x-2", children: [
1087
+ /* @__PURE__ */ jsx5(
3291
1088
  ModelListDropdown,
3292
1089
  {
3293
1090
  "aria-label": "Model",
@@ -3303,8 +1100,8 @@ function ModelRow2({ model, resetLabel, idPrefix, disabled }) {
3303
1100
  ...model.disabledTitle ? { disabledTitle: model.disabledTitle } : {}
3304
1101
  }
3305
1102
  ),
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(
1103
+ model.oneMessage ? /* @__PURE__ */ jsxs5("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: [
1104
+ /* @__PURE__ */ jsx5(
3308
1105
  Switch2,
3309
1106
  {
3310
1107
  id: oneMessageId,
@@ -3334,7 +1131,7 @@ function ModelSettingsPanel({
3334
1131
  const groups = controls ? buildSettingsRows(controls, values).filter((group) => group.rows.length > 0) : [];
3335
1132
  const extras = extraSettingKeys(controls, values, target.changedKeys);
3336
1133
  const resetLabel = target.resetLabel ?? "Reset to agent";
3337
- const extraRow = (key, kind) => /* @__PURE__ */ jsx9(
1134
+ const extraRow = (key, kind) => /* @__PURE__ */ jsx5(
3338
1135
  ExtraSettingRow,
3339
1136
  {
3340
1137
  rowKey: key,
@@ -3348,17 +1145,17 @@ function ModelSettingsPanel({
3348
1145
  },
3349
1146
  key
3350
1147
  );
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,
1148
+ return /* @__PURE__ */ jsxs5("div", { "data-model-settings-panel": "", className: "@container flex min-w-0 flex-col", children: [
1149
+ model ? /* @__PURE__ */ jsx5(ModelRow, { model, resetLabel, idPrefix, disabled }) : null,
3353
1150
  notices,
3354
1151
  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) => {
1152
+ extras.translated.length > 0 ? /* @__PURE__ */ jsx5(SettingsGroupSection, { id: "translated", title: "Translated for this model", children: /* @__PURE__ */ jsx5("div", { "data-translated-settings": "", children: extras.translated.map((key) => extraRow(key, "translated")) }) }) : null,
1153
+ groups.length === 0 && emptyNote ? /* @__PURE__ */ jsx5("div", { className: "py-2 type-secondary text-muted-foreground", children: emptyNote }) : null,
1154
+ groups.map((group) => /* @__PURE__ */ jsx5(SettingsGroupSection, { id: group.id, title: group.label || void 0, children: group.rows.map((row) => {
3358
1155
  const custom = renderRow?.(row);
3359
- if (custom !== void 0) return /* @__PURE__ */ jsx9("div", { children: custom }, row.key);
1156
+ if (custom !== void 0) return /* @__PURE__ */ jsx5("div", { children: custom }, row.key);
3360
1157
  if (!row.control) return null;
3361
- return /* @__PURE__ */ jsx9(
1158
+ return /* @__PURE__ */ jsx5(
3362
1159
  ModelSettingRow,
3363
1160
  {
3364
1161
  row,
@@ -3370,7 +1167,7 @@ function ModelSettingsPanel({
3370
1167
  row.key
3371
1168
  );
3372
1169
  }) }, group.id)),
3373
- capabilities ? /* @__PURE__ */ jsx9(
1170
+ capabilities ? /* @__PURE__ */ jsx5(
3374
1171
  InputCapabilitiesEditor,
3375
1172
  {
3376
1173
  values: capabilities.values,
@@ -3388,7 +1185,7 @@ function ModelSettingsPanel({
3388
1185
 
3389
1186
  // settings/react/index.ts
3390
1187
  function useSettingsSelector(store, select) {
3391
- return useSyncExternalStore2(
1188
+ return useSyncExternalStore(
3392
1189
  store.subscribe,
3393
1190
  () => select(store.getState()),
3394
1191
  () => select(store.getState())