@opengeni/react 3.7.0-canary.3 → 3.7.0-canary.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/{chunk-4JFUT22W.js → chunk-JT33KZZN.js} +48 -245
- package/dist/chunk-JT33KZZN.js.map +1 -0
- package/dist/chunk-KWEZ4MPF.js +220 -0
- package/dist/chunk-KWEZ4MPF.js.map +1 -0
- package/dist/{chunk-2ZICNIGZ.js → chunk-LUYB4SRW.js} +6 -3
- package/dist/{chunk-2ZICNIGZ.js.map → chunk-LUYB4SRW.js.map} +1 -1
- package/dist/components/model-policy-picker-menu.d.ts +9 -0
- package/dist/components/model-policy-picker.d.ts +10 -15
- package/dist/composer.d.ts +2 -1
- package/dist/composer.js +4 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/model-policy-picker-menu-R6WXNWJL.js +13 -0
- package/dist/model-policy-picker-menu-R6WXNWJL.js.map +1 -0
- package/dist/realtime.js +1 -1
- package/dist/session-ui.js +2 -2
- package/package.json +2 -2
- package/src/components/model-policy-picker-menu.tsx +261 -0
- package/src/components/model-policy-picker.tsx +84 -346
- package/src/components/session-conversation.tsx +4 -1
- package/src/composer.ts +2 -1
- package/src/index.ts +1 -1
- package/styles/compiled.css +26 -7
- package/styles/responsive.css +1 -1
- package/dist/chunk-4JFUT22W.js.map +0 -1
package/README.md
CHANGED
|
@@ -789,3 +789,18 @@ with streaming, tool calls, and a worker spawn, plus fleet and scheduled-task
|
|
|
789
789
|
views and a dark/light toggle. `realtime.html` is the public-package reference
|
|
790
790
|
consumer described above, with deterministic mock and same-origin live modes.
|
|
791
791
|
`bun run demo:build` is part of the repo gate.
|
|
792
|
+
|
|
793
|
+
### Model selection
|
|
794
|
+
|
|
795
|
+
`ModelPolicyPicker` opens a flat, searchable list grouped by payment source, with
|
|
796
|
+
its current model first. Choosing a model applies it and closes the popover.
|
|
797
|
+
Thinking and supported speed controls remain in a fixed footer instead of a
|
|
798
|
+
nested page. Model changes preserve supported reasoning effort and latency;
|
|
799
|
+
unsupported effort falls back to the new model's default, and unsupported speed
|
|
800
|
+
returns to Standard. A model with one reasoning level displays a disabled effort
|
|
801
|
+
control. Availability and Codex-only session restrictions still disable choices.
|
|
802
|
+
|
|
803
|
+
The trigger renders immediately; the searchable popover loads when opened. Hosts
|
|
804
|
+
can translate its search, current-selection, empty-result, attachment-warning, and
|
|
805
|
+
thinking labels through `messages`, and override payment descriptions through
|
|
806
|
+
`messages.billingHints`.
|
|
@@ -3,13 +3,9 @@ import {
|
|
|
3
3
|
usePortalTokenStyle
|
|
4
4
|
} from "./chunk-VZTQ73XT.js";
|
|
5
5
|
import {
|
|
6
|
-
effortOptionsForModel,
|
|
7
6
|
findPickerRow,
|
|
8
|
-
groupPickerRowsByBillingClass,
|
|
9
7
|
labelReasoningEffort,
|
|
10
|
-
|
|
11
|
-
projectClientModelRows,
|
|
12
|
-
runnableLatencyModesForModel
|
|
8
|
+
projectClientModelRows
|
|
13
9
|
} from "./chunk-WMGF4Z7X.js";
|
|
14
10
|
import {
|
|
15
11
|
cn
|
|
@@ -17,7 +13,6 @@ import {
|
|
|
17
13
|
|
|
18
14
|
// src/components/model-policy-picker.tsx
|
|
19
15
|
import {
|
|
20
|
-
CheckIcon,
|
|
21
16
|
ChevronDownIcon,
|
|
22
17
|
ChevronLeftIcon,
|
|
23
18
|
ChevronRightIcon,
|
|
@@ -26,14 +21,19 @@ import {
|
|
|
26
21
|
ZapIcon
|
|
27
22
|
} from "lucide-react";
|
|
28
23
|
import { motion, useReducedMotion } from "motion/react";
|
|
29
|
-
import { DropdownMenu } from "radix-ui";
|
|
30
24
|
import {
|
|
31
|
-
|
|
25
|
+
Suspense,
|
|
26
|
+
lazy,
|
|
32
27
|
useMemo,
|
|
33
|
-
|
|
28
|
+
useId,
|
|
34
29
|
useState
|
|
35
30
|
} from "react";
|
|
36
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
31
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
32
|
+
var LazyModelPolicyPickerMenu = lazy(
|
|
33
|
+
() => import("./model-policy-picker-menu-R6WXNWJL.js").then(({ ModelPolicyPickerPopover }) => ({
|
|
34
|
+
default: ModelPolicyPickerPopover
|
|
35
|
+
}))
|
|
36
|
+
);
|
|
37
37
|
var defaultModelPolicyPickerMessages = {
|
|
38
38
|
label: "Model and effort",
|
|
39
39
|
loading: "Loading model catalog\u2026",
|
|
@@ -42,6 +42,13 @@ var defaultModelPolicyPickerMessages = {
|
|
|
42
42
|
fast: "Fast",
|
|
43
43
|
fastRateHint: "2\xD7 rate",
|
|
44
44
|
codexOnly: "Codex-only session",
|
|
45
|
+
searchLabel: "Search models or providers",
|
|
46
|
+
searchPlaceholder: "Search models or providers\u2026",
|
|
47
|
+
currentModel: "Current model",
|
|
48
|
+
noMatches: "No matching models. Try a model or provider name.",
|
|
49
|
+
unsupportedAttachments: "Unsupported attachments stay in the session but are hidden from this model.",
|
|
50
|
+
thinkingEffort: "Thinking effort",
|
|
51
|
+
selected: "Selected",
|
|
45
52
|
billingHints: {
|
|
46
53
|
opengeni_credits: "Will use credits",
|
|
47
54
|
external: "Provider terms and limits apply",
|
|
@@ -130,26 +137,6 @@ function effectiveRows(props) {
|
|
|
130
137
|
const messages = { ...defaultModelPolicyPickerMessages, ...props.messages };
|
|
131
138
|
return applyCodexOnly(rows, props.codexOnly === true, messages.codexOnly);
|
|
132
139
|
}
|
|
133
|
-
function defaultNavState(rows, modelId) {
|
|
134
|
-
const selected = findPickerRow(rows, modelId);
|
|
135
|
-
if (!selected) {
|
|
136
|
-
const rails = new Set(rows.map((row) => row.billingClass));
|
|
137
|
-
const onlyRail = rails.size === 1 ? rows[0]?.billingClass : null;
|
|
138
|
-
return onlyRail ? { level: "models", rail: onlyRail, modelId: null } : { level: "providers", rail: null, modelId: null };
|
|
139
|
-
}
|
|
140
|
-
return {
|
|
141
|
-
level: "thinking",
|
|
142
|
-
rail: selected.billingClass,
|
|
143
|
-
modelId: selected.id
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
function usePickerNavState(sessionKey, rows, model) {
|
|
147
|
-
const [state, setState] = useState(() => defaultNavState(rows, model));
|
|
148
|
-
useEffect(() => {
|
|
149
|
-
setState(defaultNavState(rows, model));
|
|
150
|
-
}, [sessionKey]);
|
|
151
|
-
return [state, setState];
|
|
152
|
-
}
|
|
153
140
|
function PickerNavRow(props) {
|
|
154
141
|
return /* @__PURE__ */ jsxs(
|
|
155
142
|
"button",
|
|
@@ -208,213 +195,24 @@ function PickerAnimatedPage(props) {
|
|
|
208
195
|
props.pageKey
|
|
209
196
|
);
|
|
210
197
|
}
|
|
211
|
-
function ModelPolicyPickerMenu(props) {
|
|
212
|
-
const messages = useMemo(
|
|
213
|
-
() => ({ ...defaultModelPolicyPickerMessages, ...props.messages }),
|
|
214
|
-
[props.messages]
|
|
215
|
-
);
|
|
216
|
-
const rows = effectiveRows(props);
|
|
217
|
-
const groups = useMemo(() => groupPickerRowsByBillingClass(rows), [rows]);
|
|
218
|
-
const [localNav, setLocalNav] = usePickerNavState(
|
|
219
|
-
props.nav === void 0 ? props.sessionKey : void 0,
|
|
220
|
-
rows,
|
|
221
|
-
props.model
|
|
222
|
-
);
|
|
223
|
-
const nav = props.nav ?? localNav;
|
|
224
|
-
const setNav = props.onNavChange ?? setLocalNav;
|
|
225
|
-
const [direction, setDirection] = useState(1);
|
|
226
|
-
const effectiveNav = nav.level === "providers" && groups.length === 1 ? {
|
|
227
|
-
level: "models",
|
|
228
|
-
rail: groups[0].billingClass,
|
|
229
|
-
modelId: null
|
|
230
|
-
} : nav;
|
|
231
|
-
const activeGroup = effectiveNav.rail === null ? void 0 : groups.find((group) => group.billingClass === effectiveNav.rail);
|
|
232
|
-
const focusModel = effectiveNav.modelId === null ? void 0 : findPickerRow(rows, effectiveNav.modelId);
|
|
233
|
-
const selectedRow = findPickerRow(rows, props.model);
|
|
234
|
-
const go = (next, nextDirection) => {
|
|
235
|
-
setDirection(nextDirection);
|
|
236
|
-
setNav(next);
|
|
237
|
-
};
|
|
238
|
-
const selectEffort = (row, effort) => {
|
|
239
|
-
if (!row.selectable) return;
|
|
240
|
-
if (row.id !== props.model) props.onModelChange(row.id);
|
|
241
|
-
props.onEffortChange(effort);
|
|
242
|
-
};
|
|
243
|
-
const pageKey = effectiveNav.level === "providers" ? "providers" : effectiveNav.level === "models" ? `models:${effectiveNav.rail ?? ""}` : `thinking:${effectiveNav.modelId ?? ""}`;
|
|
244
|
-
let body;
|
|
245
|
-
if (props.loading) {
|
|
246
|
-
body = /* @__PURE__ */ jsx("p", { className: "px-2 py-3 text-og-control text-og-fg-subtle", children: messages.loading });
|
|
247
|
-
} else if (groups.length === 0) {
|
|
248
|
-
body = /* @__PURE__ */ jsx("p", { className: "px-2 py-3 text-og-control text-og-fg-subtle", children: messages.noModels });
|
|
249
|
-
} else if (effectiveNav.level === "providers") {
|
|
250
|
-
body = /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", "data-testid": "model-picker-providers", children: groups.map((group) => /* @__PURE__ */ jsx(
|
|
251
|
-
PickerNavRow,
|
|
252
|
-
{
|
|
253
|
-
label: group.label,
|
|
254
|
-
hint: messages.billingHints[group.billingClass],
|
|
255
|
-
icon: /* @__PURE__ */ jsx(BillingClassMark, { billingClass: group.billingClass }),
|
|
256
|
-
active: selectedRow?.billingClass === group.billingClass,
|
|
257
|
-
testId: `model-picker-rail-${group.billingClass}`,
|
|
258
|
-
onClick: () => go({ level: "models", rail: group.billingClass, modelId: null }, 1)
|
|
259
|
-
},
|
|
260
|
-
group.billingClass
|
|
261
|
-
)) });
|
|
262
|
-
} else if (effectiveNav.level === "models" && activeGroup) {
|
|
263
|
-
body = /* @__PURE__ */ jsxs("div", { "data-testid": "model-picker-models", children: [
|
|
264
|
-
groups.length > 1 ? /* @__PURE__ */ jsx(
|
|
265
|
-
PickerBackHeader,
|
|
266
|
-
{
|
|
267
|
-
label: activeGroup.label,
|
|
268
|
-
icon: /* @__PURE__ */ jsx(BillingClassMark, { billingClass: activeGroup.billingClass }),
|
|
269
|
-
onBack: () => go({ level: "providers", rail: null, modelId: null }, -1)
|
|
270
|
-
}
|
|
271
|
-
) : null,
|
|
272
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: activeGroup.rows.map((row) => /* @__PURE__ */ jsx(
|
|
273
|
-
PickerNavRow,
|
|
274
|
-
{
|
|
275
|
-
label: row.label,
|
|
276
|
-
hint: row.unavailableReason ?? payerSummaryForModel(row.catalog),
|
|
277
|
-
disabled: !row.selectable,
|
|
278
|
-
title: row.unavailableReason ?? void 0,
|
|
279
|
-
active: row.id === props.model,
|
|
280
|
-
testId: `model-picker-choice-${row.id}`,
|
|
281
|
-
onClick: () => {
|
|
282
|
-
if (row.selectable) {
|
|
283
|
-
go(
|
|
284
|
-
{
|
|
285
|
-
level: "thinking",
|
|
286
|
-
rail: row.billingClass,
|
|
287
|
-
modelId: row.id
|
|
288
|
-
},
|
|
289
|
-
1
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
},
|
|
294
|
-
`${row.billingClass}:${row.id}`
|
|
295
|
-
)) })
|
|
296
|
-
] });
|
|
297
|
-
} else if (effectiveNav.level === "thinking" && focusModel) {
|
|
298
|
-
const activeModel = focusModel.id === props.model;
|
|
299
|
-
const supportsFast = runnableLatencyModesForModel(focusModel.catalog).includes("fast");
|
|
300
|
-
body = /* @__PURE__ */ jsxs("div", { "data-testid": "model-picker-reasoning", children: [
|
|
301
|
-
/* @__PURE__ */ jsx(
|
|
302
|
-
PickerBackHeader,
|
|
303
|
-
{
|
|
304
|
-
label: focusModel.label,
|
|
305
|
-
icon: /* @__PURE__ */ jsx(BillingClassMark, { billingClass: focusModel.billingClass }),
|
|
306
|
-
onBack: () => go({ level: "models", rail: focusModel.billingClass, modelId: null }, -1),
|
|
307
|
-
trailing: supportsFast && props.allowLatencyMode !== false ? /* @__PURE__ */ jsx(
|
|
308
|
-
"button",
|
|
309
|
-
{
|
|
310
|
-
type: "button",
|
|
311
|
-
disabled: !focusModel.selectable,
|
|
312
|
-
"aria-pressed": activeModel && props.latencyMode === "fast",
|
|
313
|
-
"aria-label": activeModel && props.latencyMode === "fast" ? `Disable ${messages.fast}` : `Enable ${messages.fast}`,
|
|
314
|
-
title: `${messages.fast} \xB7 ${messages.fastRateHint}`,
|
|
315
|
-
"data-testid": "model-picker-fast",
|
|
316
|
-
onClick: () => {
|
|
317
|
-
if (!activeModel) {
|
|
318
|
-
props.onModelChange(focusModel.id);
|
|
319
|
-
}
|
|
320
|
-
props.onLatencyModeChange(
|
|
321
|
-
activeModel && props.latencyMode === "fast" ? "standard" : "fast"
|
|
322
|
-
);
|
|
323
|
-
},
|
|
324
|
-
className: cn(
|
|
325
|
-
"flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-og-sm text-og-fg-subtle outline-hidden transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50",
|
|
326
|
-
activeModel && props.latencyMode === "fast" && "text-og-fg"
|
|
327
|
-
),
|
|
328
|
-
children: /* @__PURE__ */ jsx(
|
|
329
|
-
ZapIcon,
|
|
330
|
-
{
|
|
331
|
-
className: cn(
|
|
332
|
-
"size-3.5",
|
|
333
|
-
activeModel && props.latencyMode === "fast" && "fill-current"
|
|
334
|
-
)
|
|
335
|
-
}
|
|
336
|
-
)
|
|
337
|
-
}
|
|
338
|
-
) : null
|
|
339
|
-
}
|
|
340
|
-
),
|
|
341
|
-
/* @__PURE__ */ jsx("p", { className: "px-2.5 pt-1 pb-1 text-og-control font-medium tracking-wide text-og-fg-subtle uppercase", children: messages.thinking }),
|
|
342
|
-
focusModel.catalog.capabilities?.inputModalities.includes("image") === false ? /* @__PURE__ */ jsx("p", { className: "px-2.5 pb-1.5 text-og-control leading-relaxed text-og-fg-subtle", children: "Unsupported attachments stay in the session but are hidden from this model." }) : null,
|
|
343
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: effortOptionsForModel(focusModel.catalog).map((effort) => {
|
|
344
|
-
const selected = activeModel && effort === props.effort;
|
|
345
|
-
return /* @__PURE__ */ jsxs(
|
|
346
|
-
"button",
|
|
347
|
-
{
|
|
348
|
-
type: "button",
|
|
349
|
-
disabled: !focusModel.selectable,
|
|
350
|
-
onClick: () => selectEffort(focusModel, effort),
|
|
351
|
-
className: cn(
|
|
352
|
-
"flex h-[var(--og-model-picker-effort-height)] w-full cursor-pointer items-center rounded-og-sm px-[var(--og-model-picker-row-padding-x)] text-left text-og-menu text-og-fg outline-hidden transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50",
|
|
353
|
-
selected && "bg-og-surface-2"
|
|
354
|
-
),
|
|
355
|
-
children: [
|
|
356
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: labelReasoningEffort(effort) }),
|
|
357
|
-
selected ? /* @__PURE__ */ jsx(
|
|
358
|
-
CheckIcon,
|
|
359
|
-
{
|
|
360
|
-
className: "ml-auto size-3.5 shrink-0",
|
|
361
|
-
"data-testid": "model-picker-effort-check"
|
|
362
|
-
}
|
|
363
|
-
) : null
|
|
364
|
-
]
|
|
365
|
-
},
|
|
366
|
-
effort
|
|
367
|
-
);
|
|
368
|
-
}) })
|
|
369
|
-
] });
|
|
370
|
-
} else {
|
|
371
|
-
body = /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", "data-testid": "model-picker-providers", children: groups.map((group) => /* @__PURE__ */ jsx(
|
|
372
|
-
PickerNavRow,
|
|
373
|
-
{
|
|
374
|
-
label: group.label,
|
|
375
|
-
hint: messages.billingHints[group.billingClass],
|
|
376
|
-
icon: /* @__PURE__ */ jsx(BillingClassMark, { billingClass: group.billingClass }),
|
|
377
|
-
testId: `model-picker-rail-${group.billingClass}`,
|
|
378
|
-
onClick: () => go({ level: "models", rail: group.billingClass, modelId: null }, 1)
|
|
379
|
-
},
|
|
380
|
-
group.billingClass
|
|
381
|
-
)) });
|
|
382
|
-
}
|
|
383
|
-
return /* @__PURE__ */ jsxs("div", { "data-testid": "model-picker-menu", className: "relative overflow-hidden", children: [
|
|
384
|
-
props.error ? /* @__PURE__ */ jsx("p", { className: "px-2 py-1 text-og-control text-og-status-failed", role: "alert", children: props.error }) : null,
|
|
385
|
-
/* @__PURE__ */ jsx(PickerAnimatedPage, { pageKey, direction, children: body })
|
|
386
|
-
] });
|
|
387
|
-
}
|
|
388
198
|
function useModelPolicyPickerState(props) {
|
|
389
199
|
const [uncontrolledOpen, setUncontrolledOpen] = useState(props.defaultOpen ?? false);
|
|
390
200
|
const open = props.open ?? uncontrolledOpen;
|
|
391
|
-
const rows = effectiveRows(props);
|
|
392
|
-
const [nav, setNav] = usePickerNavState(props.sessionKey, rows, props.model);
|
|
393
|
-
const previousControlledOpen = useRef(props.open);
|
|
394
|
-
useEffect(() => {
|
|
395
|
-
const wasOpen = previousControlledOpen.current;
|
|
396
|
-
previousControlledOpen.current = props.open;
|
|
397
|
-
if (props.open === true && wasOpen !== true) {
|
|
398
|
-
setNav(defaultNavState(rows, props.model));
|
|
399
|
-
}
|
|
400
|
-
}, [props.open]);
|
|
401
201
|
const setOpen = (next) => {
|
|
402
|
-
if (next) {
|
|
403
|
-
setNav(defaultNavState(rows, props.model));
|
|
404
|
-
}
|
|
405
202
|
if (props.open === void 0) setUncontrolledOpen(next);
|
|
406
203
|
props.onOpenChange?.(next);
|
|
407
204
|
};
|
|
408
|
-
return { open, setOpen, rows
|
|
205
|
+
return { open, setOpen, rows: effectiveRows(props) };
|
|
409
206
|
}
|
|
410
207
|
function ModelPolicyPicker(props) {
|
|
208
|
+
const contentId = useId();
|
|
411
209
|
const trigger = usePortalTokenSource();
|
|
412
210
|
const portalStyle = usePortalTokenStyle(trigger.source);
|
|
413
211
|
const messages = useMemo(
|
|
414
212
|
() => ({ ...defaultModelPolicyPickerMessages, ...props.messages }),
|
|
415
213
|
[props.messages]
|
|
416
214
|
);
|
|
417
|
-
const { open, setOpen, rows
|
|
215
|
+
const { open, setOpen, rows } = useModelPolicyPickerState(props);
|
|
418
216
|
const selected = findPickerRow(rows, props.model);
|
|
419
217
|
if (props.loading) {
|
|
420
218
|
return /* @__PURE__ */ jsx(
|
|
@@ -429,12 +227,17 @@ function ModelPolicyPicker(props) {
|
|
|
429
227
|
}
|
|
430
228
|
);
|
|
431
229
|
}
|
|
432
|
-
return /* @__PURE__ */ jsxs(
|
|
433
|
-
/* @__PURE__ */
|
|
230
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
231
|
+
/* @__PURE__ */ jsxs(
|
|
434
232
|
"button",
|
|
435
233
|
{
|
|
436
234
|
ref: trigger.ref,
|
|
437
235
|
type: "button",
|
|
236
|
+
"aria-haspopup": "dialog",
|
|
237
|
+
"aria-expanded": open,
|
|
238
|
+
"aria-controls": open ? contentId : void 0,
|
|
239
|
+
"data-state": open ? "open" : "closed",
|
|
240
|
+
onClick: () => setOpen(!open),
|
|
438
241
|
disabled: props.disabled,
|
|
439
242
|
"aria-label": messages.label,
|
|
440
243
|
className: cn(
|
|
@@ -449,9 +252,16 @@ function ModelPolicyPicker(props) {
|
|
|
449
252
|
className: "text-og-fg"
|
|
450
253
|
}
|
|
451
254
|
),
|
|
452
|
-
/* @__PURE__ */ jsx("span", { className: "og-model-policy-label-full min-w-0 truncate font-medium text-og-fg max-sm:hidden", children: selected?.label ?? props.model }),
|
|
453
|
-
/* @__PURE__ */ jsx("span", { className: "og-model-policy-label-short min-w-0 truncate font-medium text-og-fg sm:hidden", children: selected?.shortLabel ?? selected?.label ?? props.model }),
|
|
454
|
-
/* @__PURE__ */ jsx(
|
|
255
|
+
/* @__PURE__ */ jsx("span", { className: "og-model-policy-label-full min-w-0 truncate font-medium text-og-fg max-sm:hidden @max-[20rem]/model-controls:hidden", children: selected?.label ?? props.model }),
|
|
256
|
+
/* @__PURE__ */ jsx("span", { className: "og-model-policy-label-short min-w-0 truncate font-medium text-og-fg sm:hidden @max-[20rem]/model-controls:block", children: selected?.shortLabel ?? selected?.label ?? props.model }),
|
|
257
|
+
/* @__PURE__ */ jsx(
|
|
258
|
+
"span",
|
|
259
|
+
{
|
|
260
|
+
className: "og-model-policy-effort min-w-0 shrink-[9999] truncate",
|
|
261
|
+
title: labelReasoningEffort(props.effort),
|
|
262
|
+
children: labelReasoningEffort(props.effort)
|
|
263
|
+
}
|
|
264
|
+
),
|
|
455
265
|
props.latencyMode === "fast" ? /* @__PURE__ */ jsx(
|
|
456
266
|
ZapIcon,
|
|
457
267
|
{
|
|
@@ -463,34 +273,27 @@ function ModelPolicyPicker(props) {
|
|
|
463
273
|
/* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-3 shrink-0" })
|
|
464
274
|
]
|
|
465
275
|
}
|
|
466
|
-
)
|
|
467
|
-
/* @__PURE__ */ jsx(
|
|
468
|
-
|
|
276
|
+
),
|
|
277
|
+
open ? /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
|
|
278
|
+
LazyModelPolicyPickerMenu,
|
|
469
279
|
{
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
className: cn(
|
|
476
|
-
"og-root og-model-policy-menu z-50 flex max-h-[min(20rem,var(--radix-dropdown-menu-content-available-height))] w-[var(--og-model-picker-menu-width)] max-w-[calc(100vw-16px)] flex-col overflow-hidden rounded-og-lg border border-og-border bg-og-surface-1 p-[var(--og-model-picker-menu-padding)] text-og-fg shadow-og-lg",
|
|
477
|
-
props.contentClassName
|
|
478
|
-
),
|
|
479
|
-
style: { ...portalStyle, ...props.contentStyle },
|
|
480
|
-
"data-testid": "model-picker-content",
|
|
481
|
-
children: /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto overscroll-contain", children: /* @__PURE__ */ jsx(ModelPolicyPickerMenu, { ...props, nav, onNavChange: setNav }) })
|
|
280
|
+
...props,
|
|
281
|
+
anchor: trigger.currentRef,
|
|
282
|
+
contentId,
|
|
283
|
+
portalStyle,
|
|
284
|
+
onOpenChange: setOpen
|
|
482
285
|
}
|
|
483
|
-
) })
|
|
286
|
+
) }) : null
|
|
484
287
|
] });
|
|
485
288
|
}
|
|
486
289
|
|
|
487
290
|
export {
|
|
488
291
|
defaultModelPolicyPickerMessages,
|
|
489
292
|
BillingClassMark,
|
|
293
|
+
effectiveRows,
|
|
490
294
|
PickerNavRow,
|
|
491
295
|
PickerBackHeader,
|
|
492
296
|
PickerAnimatedPage,
|
|
493
|
-
ModelPolicyPickerMenu,
|
|
494
297
|
ModelPolicyPicker
|
|
495
298
|
};
|
|
496
|
-
//# sourceMappingURL=chunk-
|
|
299
|
+
//# sourceMappingURL=chunk-JT33KZZN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/model-policy-picker.tsx"],"sourcesContent":["import type { ClientModel, LatencyMode, ReasoningEffort } from \"@opengeni/sdk\";\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n Globe2Icon,\n KeyRoundIcon,\n ZapIcon,\n} from \"lucide-react\";\nimport { motion, useReducedMotion } from \"motion/react\";\nimport {\n Suspense,\n lazy,\n useMemo,\n useId,\n useState,\n type CSSProperties,\n type ReactNode,\n type SVGProps,\n} from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { usePortalTokenSource, usePortalTokenStyle } from \"../lib/use-portal-token-style\";\nimport {\n findPickerRow,\n labelReasoningEffort,\n projectClientModelRows,\n type PickerBillingClass,\n type PickerModelRow,\n} from \"../model-policy\";\n\nconst LazyModelPolicyPickerMenu = lazy(() =>\n import(\"./model-policy-picker-menu\").then(({ ModelPolicyPickerPopover }) => ({\n default: ModelPolicyPickerPopover,\n })),\n);\n\ntype ClientPickerModelRow = PickerModelRow<ClientModel>;\n\nexport type ModelPolicyPickerMessages = {\n label: string;\n loading: string;\n noModels: string;\n thinking: string;\n fast: string;\n fastRateHint: string;\n codexOnly: string;\n searchLabel?: string;\n searchPlaceholder?: string;\n currentModel?: string;\n noMatches?: string;\n unsupportedAttachments?: string;\n thinkingEffort?: string;\n selected?: string;\n\n billingHints: Record<PickerBillingClass, string>;\n};\n\nexport const defaultModelPolicyPickerMessages: ModelPolicyPickerMessages = {\n label: \"Model and effort\",\n loading: \"Loading model catalog…\",\n noModels: \"No models available.\",\n thinking: \"Thinking\",\n fast: \"Fast\",\n fastRateHint: \"2× rate\",\n codexOnly: \"Codex-only session\",\n searchLabel: \"Search models or providers\",\n searchPlaceholder: \"Search models or providers…\",\n currentModel: \"Current model\",\n noMatches: \"No matching models. Try a model or provider name.\",\n unsupportedAttachments:\n \"Unsupported attachments stay in the session but are hidden from this model.\",\n thinkingEffort: \"Thinking effort\",\n selected: \"Selected\",\n\n billingHints: {\n opengeni_credits: \"Will use credits\",\n external: \"Provider terms and limits apply\",\n codex_subscription: \"ChatGPT / Codex plan\",\n supergrok_subscription: \"SuperGrok / xAI plan\",\n byok: \"Billed to the workspace provider account\",\n organization_byok: \"Billed to the organization provider account\",\n },\n};\n\nexport type ModelPolicyPickerProps = {\n /** Lightweight deployment models. Catalog rows take precedence when supplied. */\n models?: ClientModel[] | undefined;\n /** Catalog-backed rows with availability and billing-class truth. */\n rows?: PickerModelRow[] | undefined;\n model: string;\n effort: ReasoningEffort;\n latencyMode: LatencyMode;\n disabled?: boolean | undefined;\n loading?: boolean | undefined;\n error?: string | null | undefined;\n /** Controlled menu state. Omit for the built-in uncontrolled behavior. */\n open?: boolean | undefined;\n /** Initial menu state when `open` is uncontrolled. */\n defaultOpen?: boolean | undefined;\n onOpenChange?: ((open: boolean) => void) | undefined;\n /** Non-Codex models stay visible but cannot be selected. */\n codexOnly?: boolean | undefined;\n /** Identity of the current session scope. */\n sessionKey?: string | undefined;\n /** Prefer bottom on new-chat surfaces and top for bottom-docked composers. */\n menuSide?: \"top\" | \"bottom\" | undefined;\n /** Hide latency controls on surfaces whose saved policy does not include latency. */\n allowLatencyMode?: boolean | undefined;\n /** Classes for the portalled menu surface. Prefer --og-* tokens for theming. */\n contentClassName?: string | undefined;\n /** Inline styles for the portalled menu, applied after inherited --og-* tokens. */\n contentStyle?: CSSProperties | undefined;\n className?: string | undefined;\n messages?: Partial<ModelPolicyPickerMessages> | undefined;\n onModelChange: (modelId: string) => void;\n onEffortChange: (effort: ReasoningEffort) => void;\n onLatencyModeChange: (latencyMode: LatencyMode) => void;\n};\n\nconst SLIDE_EASE = [0.22, 1, 0.36, 1] as const;\n\nfunction OpenGeniMark(props: SVGProps<SVGSVGElement>) {\n return (\n <svg\n viewBox=\"0 0 140 133\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.2}\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n {...props}\n >\n <g transform=\"translate(-17.5,-20.999893188476562) scale(1.75)\">\n <g transform=\"translate(0,-952.36218)\">\n <path d=\"m 60.7828,964.36215 27.1809,0.8834 -27.1809,25.9958 z m -1.9745,1.4513 0,26.7845 -25.2681,0 c 8.6166,-8.7334 16.8796,-17.8103 25.2681,-26.7845 z m 27.7053,3.628 3.4864,1.1989 -12.5877,7.4768 z m -68.1835,2.9656 5.5226,0 12.8654,14.0705 -5.9854,6.1204 -12.4026,0 c 9e-4,-6.7347 0,-13.4597 0,-20.1909 z m -1.9746,1.2304 0,5.8364 -6.3555,0 z m 3.363,20.9796 38.627,0 -10.7675,29.43465 z m 39.0898,4.54286 0,41.20229 -12.5878,-6.8775 c 4.1972,-11.443 8.3886,-22.879 12.5878,-34.32479 z\" />\n </g>\n </g>\n </svg>\n );\n}\n\nfunction ChatGptMark(props: SVGProps<SVGSVGElement>) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" {...props}>\n <path d=\"M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3653-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8414 3.3698-2.02 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.783-2.7622a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z\" />\n </svg>\n );\n}\n\nfunction XaiMark(props: SVGProps<SVGSVGElement>) {\n return (\n <svg viewBox=\"0 0 466.04 516.93\" fill=\"currentColor\" aria-hidden=\"true\" {...props}>\n <polygon points=\"0.12 182.71 234.14 516.92 338.15 516.92 104.13 182.71 0.12 182.71\" />\n <polygon points=\"0 516.92 104.08 516.92 156.08 442.67 104.04 368.34 0 516.92\" />\n <polygon points=\"466.04 0 361.96 0 182.1 256.86 234.15 331.18 466.04 0\" />\n <polygon points=\"380.78 516.92 466.04 516.92 466.04 37.16 380.78 158.92 380.78 516.92\" />\n </svg>\n );\n}\n\nexport function BillingClassMark(props: {\n billingClass: PickerBillingClass;\n className?: string | undefined;\n \"aria-label\"?: string | undefined;\n}) {\n const labels: Record<PickerBillingClass, string> = {\n opengeni_credits: \"OpenGeni\",\n external: \"External provider\",\n codex_subscription: \"Codex\",\n supergrok_subscription: \"SuperGrok\",\n byok: \"Workspace provider account\",\n organization_byok: \"Organization provider account\",\n };\n const label = props[\"aria-label\"] ?? labels[props.billingClass];\n const accessibility =\n label.length === 0\n ? { \"aria-hidden\": true as const }\n : { role: \"img\" as const, \"aria-label\": label };\n const shell = cn(\n \"inline-flex size-3.5 shrink-0 items-center justify-center overflow-hidden text-og-fg-subtle\",\n props.className,\n );\n const mark = \"size-3.5\";\n return (\n <span\n className={shell}\n data-testid={`billing-class-icon-${props.billingClass}`}\n {...accessibility}\n >\n {props.billingClass === \"opengeni_credits\" ? (\n <OpenGeniMark className={mark} />\n ) : props.billingClass === \"external\" ? (\n <Globe2Icon className={mark} aria-hidden />\n ) : props.billingClass === \"codex_subscription\" ? (\n <ChatGptMark className={mark} />\n ) : props.billingClass === \"supergrok_subscription\" ? (\n <XaiMark className={mark} />\n ) : (\n <KeyRoundIcon className={mark} aria-hidden />\n )}\n </span>\n );\n}\n\nfunction isCodexModel(model: ClientModel): boolean {\n return model.id.startsWith(\"codex/\") || model.source === \"codex\";\n}\n\nfunction billingClassForMissingSelection(modelId: string): PickerBillingClass {\n if (modelId.startsWith(\"workspace-gateway/\")) return \"byok\";\n if (modelId.startsWith(\"workspace-openrouter/\")) return \"byok\";\n // A deployment OpenRouter ID does not encode its workspace-facing cost.\n // Missing rows therefore use the credits-safe rail instead of falsely\n // claiming that an unknown former selection was externally funded.\n if (modelId.startsWith(\"openrouter/\")) return \"opengeni_credits\";\n if (modelId.startsWith(\"codex/\")) return \"codex_subscription\";\n if (modelId.startsWith(\"supergrok/\")) return \"supergrok_subscription\";\n return \"opengeni_credits\";\n}\n\nfunction applyCodexOnly(\n rows: ClientPickerModelRow[],\n codexOnly: boolean,\n unavailableReason: string,\n): ClientPickerModelRow[] {\n if (!codexOnly) return rows;\n return rows.map((row) =>\n isCodexModel(row.catalog)\n ? row\n : {\n ...row,\n selectable: false,\n unavailableReason: row.unavailableReason ?? unavailableReason,\n },\n );\n}\n\nexport function effectiveRows(props: ModelPolicyPickerProps): ClientPickerModelRow[] {\n const rows = props.rows !== undefined ? props.rows : projectClientModelRows(props.models ?? []);\n const messages = { ...defaultModelPolicyPickerMessages, ...props.messages };\n return applyCodexOnly(rows, props.codexOnly === true, messages.codexOnly);\n}\n\nexport function PickerNavRow(props: {\n label: string;\n hint?: string | undefined;\n icon?: ReactNode;\n trailing?: ReactNode;\n showChevron?: boolean | undefined;\n disabled?: boolean | undefined;\n title?: string | undefined;\n active?: boolean | undefined;\n testId?: string | undefined;\n onClick: () => void;\n}) {\n return (\n <button\n type=\"button\"\n disabled={props.disabled}\n title={props.title}\n onClick={props.onClick}\n data-testid={props.testId}\n className={cn(\n \"flex w-full cursor-pointer items-center gap-2 rounded-og-sm px-[var(--og-model-picker-row-padding-x)] py-[var(--og-model-picker-row-padding-y)] text-left text-og-fg outline-hidden transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40\",\n props.disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n {props.icon}\n <span className=\"min-w-0 flex-1\">\n <span className={cn(\"block truncate text-og-menu\", props.active && \"font-medium\")}>\n {props.label}\n </span>\n {props.hint ? (\n <span className=\"mt-0.5 block truncate text-og-control text-og-fg-subtle\">\n {props.hint}\n </span>\n ) : null}\n </span>\n {props.trailing ? <span className=\"ml-auto shrink-0\">{props.trailing}</span> : null}\n {props.showChevron === false ? null : (\n <ChevronRightIcon className=\"size-3.5 shrink-0 text-og-fg-subtle\" />\n )}\n </button>\n );\n}\n\nexport function PickerBackHeader(props: {\n label: string;\n icon?: ReactNode;\n onBack: () => void;\n trailing?: ReactNode;\n}) {\n return (\n <div className=\"mb-1 flex items-center gap-0.5 border-b border-og-border/70 px-0.5 pb-1.5\">\n <button\n type=\"button\"\n onClick={props.onBack}\n data-testid=\"model-picker-back\"\n className=\"flex min-w-0 flex-1 cursor-pointer items-center gap-1.5 rounded-og-sm px-1.5 py-1.5 text-left text-og-fg outline-hidden transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40\"\n >\n <ChevronLeftIcon className=\"size-3.5 shrink-0 text-og-fg-subtle\" />\n {props.icon}\n <span className=\"min-w-0 flex-1 truncate text-og-menu font-medium\">{props.label}</span>\n </button>\n {props.trailing ? <div className=\"relative z-10 shrink-0\">{props.trailing}</div> : null}\n </div>\n );\n}\n\nexport function PickerAnimatedPage(props: {\n pageKey: string;\n direction: 1 | -1;\n children: ReactNode;\n}) {\n const reduceMotion = useReducedMotion();\n return (\n <motion.div\n key={props.pageKey}\n initial={reduceMotion ? false : { x: props.direction * 14, opacity: 0 }}\n animate={{ x: 0, opacity: 1 }}\n transition={{ duration: reduceMotion ? 0 : 0.18, ease: SLIDE_EASE }}\n className=\"w-full\"\n >\n {props.children}\n </motion.div>\n );\n}\n\n/** @internal Shared controlled/uncontrolled state seam. */\nexport function useModelPolicyPickerState(props: ModelPolicyPickerProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(props.defaultOpen ?? false);\n const open = props.open ?? uncontrolledOpen;\n const setOpen = (next: boolean) => {\n if (props.open === undefined) setUncontrolledOpen(next);\n props.onOpenChange?.(next);\n };\n return { open, setOpen, rows: effectiveRows(props) };\n}\n\nexport function ModelPolicyPicker(props: ModelPolicyPickerProps) {\n const contentId = useId();\n const trigger = usePortalTokenSource<HTMLButtonElement>();\n const portalStyle = usePortalTokenStyle(trigger.source);\n const messages = useMemo(\n () => ({ ...defaultModelPolicyPickerMessages, ...props.messages }),\n [props.messages],\n );\n const { open, setOpen, rows } = useModelPolicyPickerState(props);\n const selected = findPickerRow(rows, props.model);\n\n if (props.loading) {\n return (\n <span\n className={cn(\n \"og-root inline-flex h-8 w-40 shrink-0 animate-pulse rounded-full bg-og-surface-2\",\n props.className,\n )}\n aria-label={messages.loading}\n data-testid=\"model-picker-loading\"\n />\n );\n }\n return (\n <>\n <button\n ref={trigger.ref}\n type=\"button\"\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={open ? contentId : undefined}\n data-state={open ? \"open\" : \"closed\"}\n onClick={() => setOpen(!open)}\n disabled={props.disabled}\n aria-label={messages.label}\n className={cn(\n \"og-root og-model-policy-trigger inline-flex h-[var(--og-model-picker-trigger-height)] min-w-0 max-w-64 items-center gap-1 rounded-full border border-transparent px-2.5 text-og-control text-og-fg-muted outline-hidden transition-colors hover:border-og-border hover:bg-og-surface-2 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50 max-sm:h-11 max-sm:max-w-[7.5rem] max-sm:px-2\",\n props.className,\n )}\n >\n <BillingClassMark\n billingClass={selected?.billingClass ?? billingClassForMissingSelection(props.model)}\n className=\"text-og-fg\"\n />\n <span className=\"og-model-policy-label-full min-w-0 truncate font-medium text-og-fg max-sm:hidden @max-[20rem]/model-controls:hidden\">\n {selected?.label ?? props.model}\n </span>\n <span className=\"og-model-policy-label-short min-w-0 truncate font-medium text-og-fg sm:hidden @max-[20rem]/model-controls:block\">\n {selected?.shortLabel ?? selected?.label ?? props.model}\n </span>\n <span\n className=\"og-model-policy-effort min-w-0 shrink-[9999] truncate\"\n title={labelReasoningEffort(props.effort)}\n >\n {labelReasoningEffort(props.effort)}\n </span>\n {props.latencyMode === \"fast\" ? (\n <ZapIcon\n className=\"size-3.5 shrink-0 fill-current stroke-current text-og-fg\"\n aria-label={messages.fast}\n data-testid=\"model-picker-fast-icon\"\n />\n ) : null}\n <ChevronDownIcon className=\"size-3 shrink-0\" />\n </button>\n\n {open ? (\n <Suspense fallback={null}>\n <LazyModelPolicyPickerMenu\n {...props}\n anchor={trigger.currentRef}\n contentId={contentId}\n portalStyle={portalStyle}\n onOpenChange={setOpen}\n />\n </Suspense>\n ) : null}\n </>\n );\n}\n"],"mappings":"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","names":[]}
|