@opengeni/react 0.36.0 → 0.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/{chunk-J2RVJ6JX.js → chunk-4IJCL7YO.js} +13 -2
- package/dist/chunk-4IJCL7YO.js.map +1 -0
- package/dist/{chunk-OKKMZDQF.js → chunk-FSPDND3P.js} +2 -2
- package/dist/{chunk-FT2TXNGZ.js → chunk-HJ4OQVGW.js} +174 -14
- package/dist/chunk-HJ4OQVGW.js.map +1 -0
- package/dist/{chunk-PVW56EVR.js → chunk-IP22SLO6.js} +447 -13
- package/dist/chunk-IP22SLO6.js.map +1 -0
- package/dist/{chunk-U255M5EZ.js → chunk-SJKT4TKW.js} +39 -6
- package/dist/chunk-SJKT4TKW.js.map +1 -0
- package/dist/{chunk-XT7JF2EH.js → chunk-UCZPNXV3.js} +96 -17
- package/dist/chunk-UCZPNXV3.js.map +1 -0
- package/dist/components/chat-composer.d.ts +3 -1
- package/dist/components/model-policy-picker.d.ts +78 -0
- package/dist/components/session-chrome.d.ts +1 -1
- package/dist/composer.d.ts +2 -0
- package/dist/composer.js +17 -3
- package/dist/hooks/use-composer.d.ts +9 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +30 -9
- package/dist/index.js.map +1 -1
- package/dist/model-policy.d.ts +12 -4
- package/dist/model-policy.js +5 -1
- package/dist/session-ui.js +2 -2
- package/dist/session.js +3 -3
- package/dist/timeline/types.d.ts +5 -0
- package/package.json +2 -2
- package/src/components/chat-composer.tsx +8 -3
- package/src/components/composer.tsx +17 -1
- package/src/components/copy-button.tsx +13 -6
- package/src/components/model-picker.tsx +2 -2
- package/src/components/model-policy-picker.tsx +582 -0
- package/src/components/session-chrome.tsx +138 -14
- package/src/composer.ts +13 -0
- package/src/hooks/use-composer.ts +213 -16
- package/src/index.ts +15 -0
- package/src/model-policy.ts +69 -14
- package/src/timeline/projection.ts +21 -1
- package/src/timeline/types.ts +5 -0
- package/dist/chunk-FT2TXNGZ.js.map +0 -1
- package/dist/chunk-J2RVJ6JX.js.map +0 -1
- package/dist/chunk-PVW56EVR.js.map +0 -1
- package/dist/chunk-U255M5EZ.js.map +0 -1
- package/dist/chunk-XT7JF2EH.js.map +0 -1
- /package/dist/{chunk-OKKMZDQF.js.map → chunk-FSPDND3P.js.map} +0 -0
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
shouldSteerOnKey,
|
|
3
3
|
shouldSubmitOnKey
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-HJ4OQVGW.js";
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
coerceReasoningEffortForModel,
|
|
7
|
+
effortOptionsForModel,
|
|
8
|
+
findPickerRow,
|
|
9
|
+
groupPickerRowsByBillingClass,
|
|
10
|
+
labelReasoningEffort,
|
|
11
|
+
projectClientModelRows,
|
|
12
|
+
runnableLatencyModesForModel
|
|
13
|
+
} from "./chunk-SJKT4TKW.js";
|
|
8
14
|
import {
|
|
9
15
|
Tooltip,
|
|
10
16
|
TooltipContent,
|
|
@@ -1249,10 +1255,10 @@ import { useId, useMemo as useMemo3 } from "react";
|
|
|
1249
1255
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1250
1256
|
var EMPTY_CLIENT_MODELS = [];
|
|
1251
1257
|
function isCodexClientModel(model) {
|
|
1252
|
-
return model.id.startsWith("codex/") || model.
|
|
1258
|
+
return model.id.startsWith("codex/") || model.source === "codex";
|
|
1253
1259
|
}
|
|
1254
1260
|
function isCodexPickerRow(row) {
|
|
1255
|
-
return row.id.startsWith("codex/") || row.
|
|
1261
|
+
return row.id.startsWith("codex/") || row.catalog.source === "codex";
|
|
1256
1262
|
}
|
|
1257
1263
|
function applyCodexOnlyRows(rows, codexOnly) {
|
|
1258
1264
|
if (!codexOnly) return rows;
|
|
@@ -1291,17 +1297,17 @@ function ModelPicker({
|
|
|
1291
1297
|
codexOnly = false
|
|
1292
1298
|
}) {
|
|
1293
1299
|
const selectId = useId();
|
|
1294
|
-
const
|
|
1300
|
+
const effectiveRows2 = useMemo3(
|
|
1295
1301
|
() => rows && rows.length > 0 ? applyCodexOnlyRows(rows, codexOnly) : [],
|
|
1296
1302
|
[rows, codexOnly]
|
|
1297
1303
|
);
|
|
1298
1304
|
const billingGroups = useMemo3(
|
|
1299
|
-
() =>
|
|
1300
|
-
[
|
|
1305
|
+
() => effectiveRows2.length > 0 ? groupPickerRowsByBillingClass(effectiveRows2) : [],
|
|
1306
|
+
[effectiveRows2]
|
|
1301
1307
|
);
|
|
1302
1308
|
const providerGroupList = useMemo3(() => providerGroups(models, codexOnly), [models, codexOnly]);
|
|
1303
|
-
const useBillingGroups = Boolean(
|
|
1304
|
-
if (models.length === 0 &&
|
|
1309
|
+
const useBillingGroups = Boolean(effectiveRows2.length);
|
|
1310
|
+
if (models.length === 0 && effectiveRows2.length === 0) {
|
|
1305
1311
|
return null;
|
|
1306
1312
|
}
|
|
1307
1313
|
return /* @__PURE__ */ jsxs2("span", { className: cn("relative inline-flex items-center", className), children: [
|
|
@@ -1902,9 +1908,20 @@ function Attachments() {
|
|
|
1902
1908
|
}
|
|
1903
1909
|
);
|
|
1904
1910
|
}
|
|
1905
|
-
var Input = forwardRef(function ComposerInput({ rows = 1, placeholder, className, "aria-label": ariaLabel, ...props }, forwardedRef) {
|
|
1911
|
+
var Input = forwardRef(function ComposerInput({ rows = 1, placeholder, className, "aria-label": ariaLabel, autoFocus = false, ...props }, forwardedRef) {
|
|
1906
1912
|
const controller = useComposerController();
|
|
1913
|
+
const autoFocusedRef = useRef4(false);
|
|
1907
1914
|
const paletteOpen = controller.paletteEnabled && controller.paletteMounted && controller.palette.open;
|
|
1915
|
+
useEffect3(() => {
|
|
1916
|
+
if (!autoFocus || controller.disabled || autoFocusedRef.current) return;
|
|
1917
|
+
const frame = window.requestAnimationFrame(() => {
|
|
1918
|
+
const textarea = controller.textareaRef.current;
|
|
1919
|
+
if (!textarea || textarea.disabled) return;
|
|
1920
|
+
autoFocusedRef.current = true;
|
|
1921
|
+
textarea.focus();
|
|
1922
|
+
});
|
|
1923
|
+
return () => window.cancelAnimationFrame(frame);
|
|
1924
|
+
}, [autoFocus, controller.disabled, controller.textareaRef]);
|
|
1908
1925
|
return /* @__PURE__ */ jsx3(
|
|
1909
1926
|
"textarea",
|
|
1910
1927
|
{
|
|
@@ -1917,6 +1934,7 @@ var Input = forwardRef(function ComposerInput({ rows = 1, placeholder, className
|
|
|
1917
1934
|
onPaste: controller.handlePaste,
|
|
1918
1935
|
placeholder: controller.paused && !controller.disabled ? controller.messages.pausedPlaceholder : placeholder ?? controller.messages.messagePlaceholder,
|
|
1919
1936
|
disabled: controller.disabled,
|
|
1937
|
+
autoFocus: autoFocus && !controller.disabled,
|
|
1920
1938
|
"aria-label": ariaLabel ?? controller.messages.inputLabel,
|
|
1921
1939
|
"aria-keyshortcuts": "Enter Meta+Enter Control+Enter Shift+Enter",
|
|
1922
1940
|
"aria-autocomplete": controller.paletteEnabled && controller.paletteMounted ? "list" : void 0,
|
|
@@ -2758,6 +2776,415 @@ function transcriptionErrorMessage(code, messages) {
|
|
|
2758
2776
|
}
|
|
2759
2777
|
}
|
|
2760
2778
|
|
|
2779
|
+
// src/components/model-policy-picker.tsx
|
|
2780
|
+
import {
|
|
2781
|
+
CheckIcon,
|
|
2782
|
+
ChevronDownIcon as ChevronDownIcon3,
|
|
2783
|
+
ChevronLeftIcon,
|
|
2784
|
+
ChevronRightIcon,
|
|
2785
|
+
KeyRoundIcon,
|
|
2786
|
+
ZapIcon
|
|
2787
|
+
} from "lucide-react";
|
|
2788
|
+
import { motion as motion4, useReducedMotion } from "motion/react";
|
|
2789
|
+
import { DropdownMenu } from "radix-ui";
|
|
2790
|
+
import { useEffect as useEffect5, useMemo as useMemo5, useState as useState6 } from "react";
|
|
2791
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2792
|
+
var defaultModelPolicyPickerMessages = {
|
|
2793
|
+
label: "Model and effort",
|
|
2794
|
+
loading: "Loading model catalog\u2026",
|
|
2795
|
+
noModels: "No models available.",
|
|
2796
|
+
thinking: "Thinking",
|
|
2797
|
+
fast: "Fast",
|
|
2798
|
+
fastRateHint: "2\xD7 rate",
|
|
2799
|
+
codexOnly: "Codex-only session",
|
|
2800
|
+
billingHints: {
|
|
2801
|
+
opengeni_credits: "Will use credits",
|
|
2802
|
+
codex_subscription: "ChatGPT / Codex plan",
|
|
2803
|
+
byok: "Billed to your AI Gateway"
|
|
2804
|
+
}
|
|
2805
|
+
};
|
|
2806
|
+
var SLIDE_EASE = [0.22, 1, 0.36, 1];
|
|
2807
|
+
function OpenGeniMark(props) {
|
|
2808
|
+
return /* @__PURE__ */ jsx5(
|
|
2809
|
+
"svg",
|
|
2810
|
+
{
|
|
2811
|
+
viewBox: "0 0 140 133",
|
|
2812
|
+
fill: "none",
|
|
2813
|
+
stroke: "currentColor",
|
|
2814
|
+
strokeWidth: 1.2,
|
|
2815
|
+
strokeLinejoin: "round",
|
|
2816
|
+
"aria-hidden": "true",
|
|
2817
|
+
...props,
|
|
2818
|
+
children: /* @__PURE__ */ jsx5("g", { transform: "translate(-17.5,-20.999893188476562) scale(1.75)", children: /* @__PURE__ */ jsx5("g", { transform: "translate(0,-952.36218)", children: /* @__PURE__ */ jsx5("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" }) }) })
|
|
2819
|
+
}
|
|
2820
|
+
);
|
|
2821
|
+
}
|
|
2822
|
+
function ChatGptMark(props) {
|
|
2823
|
+
return /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx5("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" }) });
|
|
2824
|
+
}
|
|
2825
|
+
function BillingClassMark(props) {
|
|
2826
|
+
const labels = {
|
|
2827
|
+
opengeni_credits: "OpenGeni",
|
|
2828
|
+
codex_subscription: "Codex",
|
|
2829
|
+
byok: "Bring your own key"
|
|
2830
|
+
};
|
|
2831
|
+
const label = props["aria-label"] ?? labels[props.billingClass];
|
|
2832
|
+
const accessibility = label.length === 0 ? { "aria-hidden": true } : { role: "img", "aria-label": label };
|
|
2833
|
+
const shell = cn(
|
|
2834
|
+
"inline-flex size-3.5 shrink-0 items-center justify-center overflow-hidden text-og-fg-subtle",
|
|
2835
|
+
props.className
|
|
2836
|
+
);
|
|
2837
|
+
const mark = "size-3.5";
|
|
2838
|
+
return /* @__PURE__ */ jsx5(
|
|
2839
|
+
"span",
|
|
2840
|
+
{
|
|
2841
|
+
className: shell,
|
|
2842
|
+
"data-testid": `billing-class-icon-${props.billingClass}`,
|
|
2843
|
+
...accessibility,
|
|
2844
|
+
children: props.billingClass === "opengeni_credits" ? /* @__PURE__ */ jsx5(OpenGeniMark, { className: mark }) : props.billingClass === "codex_subscription" ? /* @__PURE__ */ jsx5(ChatGptMark, { className: mark }) : /* @__PURE__ */ jsx5(KeyRoundIcon, { className: mark, "aria-hidden": true })
|
|
2845
|
+
}
|
|
2846
|
+
);
|
|
2847
|
+
}
|
|
2848
|
+
function isCodexModel(model) {
|
|
2849
|
+
return model.id.startsWith("codex/") || model.source === "codex";
|
|
2850
|
+
}
|
|
2851
|
+
function applyCodexOnly(rows, codexOnly, unavailableReason) {
|
|
2852
|
+
if (!codexOnly) return rows;
|
|
2853
|
+
return rows.map(
|
|
2854
|
+
(row) => isCodexModel(row.catalog) ? row : {
|
|
2855
|
+
...row,
|
|
2856
|
+
selectable: false,
|
|
2857
|
+
unavailableReason: row.unavailableReason ?? unavailableReason
|
|
2858
|
+
}
|
|
2859
|
+
);
|
|
2860
|
+
}
|
|
2861
|
+
function effectiveRows(props) {
|
|
2862
|
+
const rows = props.rows !== void 0 ? props.rows : projectClientModelRows(props.models ?? []);
|
|
2863
|
+
const messages = { ...defaultModelPolicyPickerMessages, ...props.messages };
|
|
2864
|
+
return applyCodexOnly(rows, props.codexOnly === true, messages.codexOnly);
|
|
2865
|
+
}
|
|
2866
|
+
function defaultNavState(rows, modelId) {
|
|
2867
|
+
const selected = findPickerRow(rows, modelId);
|
|
2868
|
+
if (!selected) {
|
|
2869
|
+
const rails = new Set(rows.map((row) => row.billingClass));
|
|
2870
|
+
const onlyRail = rails.size === 1 ? rows[0]?.billingClass : null;
|
|
2871
|
+
return onlyRail ? { level: "models", rail: onlyRail, modelId: null } : { level: "providers", rail: null, modelId: null };
|
|
2872
|
+
}
|
|
2873
|
+
return { level: "thinking", rail: selected.billingClass, modelId: selected.id };
|
|
2874
|
+
}
|
|
2875
|
+
function usePickerNavState(sessionKey, rows, model) {
|
|
2876
|
+
const [state, setState] = useState6(() => defaultNavState(rows, model));
|
|
2877
|
+
useEffect5(() => {
|
|
2878
|
+
setState(defaultNavState(rows, model));
|
|
2879
|
+
}, [sessionKey]);
|
|
2880
|
+
return [state, setState];
|
|
2881
|
+
}
|
|
2882
|
+
function PickerNavRow(props) {
|
|
2883
|
+
return /* @__PURE__ */ jsxs5(
|
|
2884
|
+
"button",
|
|
2885
|
+
{
|
|
2886
|
+
type: "button",
|
|
2887
|
+
disabled: props.disabled,
|
|
2888
|
+
title: props.title,
|
|
2889
|
+
onClick: props.onClick,
|
|
2890
|
+
"data-testid": props.testId,
|
|
2891
|
+
className: cn(
|
|
2892
|
+
"flex w-full cursor-pointer items-center gap-2 rounded-og-sm px-2.5 py-2 text-left text-og-fg outline-none transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40",
|
|
2893
|
+
props.disabled && "cursor-not-allowed opacity-50"
|
|
2894
|
+
),
|
|
2895
|
+
children: [
|
|
2896
|
+
props.icon,
|
|
2897
|
+
/* @__PURE__ */ jsxs5("span", { className: "min-w-0 flex-1", children: [
|
|
2898
|
+
/* @__PURE__ */ jsx5("span", { className: cn("block truncate text-sm", props.active && "font-medium"), children: props.label }),
|
|
2899
|
+
props.hint ? /* @__PURE__ */ jsx5("span", { className: "mt-0.5 block truncate text-xs text-og-fg-subtle", children: props.hint }) : null
|
|
2900
|
+
] }),
|
|
2901
|
+
props.trailing ? /* @__PURE__ */ jsx5("span", { className: "ml-auto shrink-0", children: props.trailing }) : null,
|
|
2902
|
+
props.showChevron === false ? null : /* @__PURE__ */ jsx5(ChevronRightIcon, { className: "size-3.5 shrink-0 text-og-fg-subtle" })
|
|
2903
|
+
]
|
|
2904
|
+
}
|
|
2905
|
+
);
|
|
2906
|
+
}
|
|
2907
|
+
function PickerBackHeader(props) {
|
|
2908
|
+
return /* @__PURE__ */ jsxs5("div", { className: "mb-1 flex items-center gap-0.5 border-b border-og-border/70 px-0.5 pb-1.5", children: [
|
|
2909
|
+
/* @__PURE__ */ jsxs5(
|
|
2910
|
+
"button",
|
|
2911
|
+
{
|
|
2912
|
+
type: "button",
|
|
2913
|
+
onClick: props.onBack,
|
|
2914
|
+
"data-testid": "model-picker-back",
|
|
2915
|
+
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-none transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40",
|
|
2916
|
+
children: [
|
|
2917
|
+
/* @__PURE__ */ jsx5(ChevronLeftIcon, { className: "size-3.5 shrink-0 text-og-fg-subtle" }),
|
|
2918
|
+
props.icon,
|
|
2919
|
+
/* @__PURE__ */ jsx5("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: props.label })
|
|
2920
|
+
]
|
|
2921
|
+
}
|
|
2922
|
+
),
|
|
2923
|
+
props.trailing ? /* @__PURE__ */ jsx5("div", { className: "relative z-10 shrink-0", children: props.trailing }) : null
|
|
2924
|
+
] });
|
|
2925
|
+
}
|
|
2926
|
+
function PickerAnimatedPage(props) {
|
|
2927
|
+
const reduceMotion = useReducedMotion();
|
|
2928
|
+
return /* @__PURE__ */ jsx5(
|
|
2929
|
+
motion4.div,
|
|
2930
|
+
{
|
|
2931
|
+
initial: reduceMotion ? false : { x: props.direction * 14, opacity: 0 },
|
|
2932
|
+
animate: { x: 0, opacity: 1 },
|
|
2933
|
+
transition: { duration: reduceMotion ? 0 : 0.18, ease: SLIDE_EASE },
|
|
2934
|
+
className: "w-full",
|
|
2935
|
+
children: props.children
|
|
2936
|
+
},
|
|
2937
|
+
props.pageKey
|
|
2938
|
+
);
|
|
2939
|
+
}
|
|
2940
|
+
function ModelPolicyPickerMenu(props) {
|
|
2941
|
+
const messages = useMemo5(
|
|
2942
|
+
() => ({ ...defaultModelPolicyPickerMessages, ...props.messages }),
|
|
2943
|
+
[props.messages]
|
|
2944
|
+
);
|
|
2945
|
+
const rows = effectiveRows(props);
|
|
2946
|
+
const groups = useMemo5(() => groupPickerRowsByBillingClass(rows), [rows]);
|
|
2947
|
+
const [localNav, setLocalNav] = usePickerNavState(
|
|
2948
|
+
props.nav === void 0 ? props.sessionKey : void 0,
|
|
2949
|
+
rows,
|
|
2950
|
+
props.model
|
|
2951
|
+
);
|
|
2952
|
+
const nav = props.nav ?? localNav;
|
|
2953
|
+
const setNav = props.onNavChange ?? setLocalNav;
|
|
2954
|
+
const [direction, setDirection] = useState6(1);
|
|
2955
|
+
const effectiveNav = nav.level === "providers" && groups.length === 1 ? { level: "models", rail: groups[0].billingClass, modelId: null } : nav;
|
|
2956
|
+
const activeGroup = effectiveNav.rail === null ? void 0 : groups.find((group) => group.billingClass === effectiveNav.rail);
|
|
2957
|
+
const focusModel = effectiveNav.modelId === null ? void 0 : findPickerRow(rows, effectiveNav.modelId);
|
|
2958
|
+
const selectedRow = findPickerRow(rows, props.model);
|
|
2959
|
+
const { latencyMode, loading, onLatencyModeChange } = props;
|
|
2960
|
+
useEffect5(() => {
|
|
2961
|
+
if (loading || !selectedRow?.selectable) return;
|
|
2962
|
+
const supportsCurrentMode = runnableLatencyModesForModel(selectedRow.catalog).includes(
|
|
2963
|
+
latencyMode
|
|
2964
|
+
);
|
|
2965
|
+
if (!supportsCurrentMode && latencyMode !== "standard") {
|
|
2966
|
+
onLatencyModeChange("standard");
|
|
2967
|
+
}
|
|
2968
|
+
}, [latencyMode, loading, onLatencyModeChange, selectedRow]);
|
|
2969
|
+
const go = (next, nextDirection) => {
|
|
2970
|
+
setDirection(nextDirection);
|
|
2971
|
+
setNav(next);
|
|
2972
|
+
};
|
|
2973
|
+
const selectEffort = (row, effort) => {
|
|
2974
|
+
if (!row.selectable) return;
|
|
2975
|
+
if (row.id !== props.model) props.onModelChange(row.id);
|
|
2976
|
+
props.onEffortChange(coerceReasoningEffortForModel(row.catalog, effort));
|
|
2977
|
+
};
|
|
2978
|
+
const pageKey = effectiveNav.level === "providers" ? "providers" : effectiveNav.level === "models" ? `models:${effectiveNav.rail ?? ""}` : `thinking:${effectiveNav.modelId ?? ""}`;
|
|
2979
|
+
let body;
|
|
2980
|
+
if (props.loading) {
|
|
2981
|
+
body = /* @__PURE__ */ jsx5("p", { className: "px-2 py-3 text-xs text-og-fg-subtle", children: messages.loading });
|
|
2982
|
+
} else if (groups.length === 0) {
|
|
2983
|
+
body = /* @__PURE__ */ jsx5("p", { className: "px-2 py-3 text-xs text-og-fg-subtle", children: messages.noModels });
|
|
2984
|
+
} else if (effectiveNav.level === "providers") {
|
|
2985
|
+
body = /* @__PURE__ */ jsx5("div", { className: "flex flex-col gap-0.5", "data-testid": "model-picker-providers", children: groups.map((group) => /* @__PURE__ */ jsx5(
|
|
2986
|
+
PickerNavRow,
|
|
2987
|
+
{
|
|
2988
|
+
label: group.label,
|
|
2989
|
+
hint: messages.billingHints[group.billingClass],
|
|
2990
|
+
icon: /* @__PURE__ */ jsx5(BillingClassMark, { billingClass: group.billingClass }),
|
|
2991
|
+
active: selectedRow?.billingClass === group.billingClass,
|
|
2992
|
+
testId: `model-picker-rail-${group.billingClass}`,
|
|
2993
|
+
onClick: () => go({ level: "models", rail: group.billingClass, modelId: null }, 1)
|
|
2994
|
+
},
|
|
2995
|
+
group.billingClass
|
|
2996
|
+
)) });
|
|
2997
|
+
} else if (effectiveNav.level === "models" && activeGroup) {
|
|
2998
|
+
body = /* @__PURE__ */ jsxs5("div", { "data-testid": "model-picker-models", children: [
|
|
2999
|
+
groups.length > 1 ? /* @__PURE__ */ jsx5(
|
|
3000
|
+
PickerBackHeader,
|
|
3001
|
+
{
|
|
3002
|
+
label: activeGroup.label,
|
|
3003
|
+
icon: /* @__PURE__ */ jsx5(BillingClassMark, { billingClass: activeGroup.billingClass }),
|
|
3004
|
+
onBack: () => go({ level: "providers", rail: null, modelId: null }, -1)
|
|
3005
|
+
}
|
|
3006
|
+
) : null,
|
|
3007
|
+
/* @__PURE__ */ jsx5("div", { className: "flex flex-col gap-0.5", children: activeGroup.rows.map((row) => /* @__PURE__ */ jsx5(
|
|
3008
|
+
PickerNavRow,
|
|
3009
|
+
{
|
|
3010
|
+
label: row.label,
|
|
3011
|
+
hint: row.unavailableReason ?? void 0,
|
|
3012
|
+
disabled: !row.selectable,
|
|
3013
|
+
title: row.unavailableReason ?? void 0,
|
|
3014
|
+
active: row.id === props.model,
|
|
3015
|
+
testId: `model-picker-choice-${row.id}`,
|
|
3016
|
+
onClick: () => {
|
|
3017
|
+
if (row.selectable) {
|
|
3018
|
+
go({ level: "thinking", rail: row.billingClass, modelId: row.id }, 1);
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
},
|
|
3022
|
+
`${row.billingClass}:${row.id}`
|
|
3023
|
+
)) })
|
|
3024
|
+
] });
|
|
3025
|
+
} else if (effectiveNav.level === "thinking" && focusModel) {
|
|
3026
|
+
const activeModel = focusModel.id === props.model;
|
|
3027
|
+
const supportsFast = runnableLatencyModesForModel(focusModel.catalog).includes("fast");
|
|
3028
|
+
body = /* @__PURE__ */ jsxs5("div", { "data-testid": "model-picker-reasoning", children: [
|
|
3029
|
+
/* @__PURE__ */ jsx5(
|
|
3030
|
+
PickerBackHeader,
|
|
3031
|
+
{
|
|
3032
|
+
label: focusModel.label,
|
|
3033
|
+
icon: /* @__PURE__ */ jsx5(BillingClassMark, { billingClass: focusModel.billingClass }),
|
|
3034
|
+
onBack: () => go({ level: "models", rail: focusModel.billingClass, modelId: null }, -1),
|
|
3035
|
+
trailing: supportsFast ? /* @__PURE__ */ jsx5(
|
|
3036
|
+
"button",
|
|
3037
|
+
{
|
|
3038
|
+
type: "button",
|
|
3039
|
+
disabled: !focusModel.selectable,
|
|
3040
|
+
"aria-pressed": activeModel && props.latencyMode === "fast",
|
|
3041
|
+
"aria-label": activeModel && props.latencyMode === "fast" ? `Disable ${messages.fast}` : `Enable ${messages.fast}`,
|
|
3042
|
+
title: `${messages.fast} \xB7 ${messages.fastRateHint}`,
|
|
3043
|
+
"data-testid": "model-picker-fast",
|
|
3044
|
+
onClick: () => {
|
|
3045
|
+
if (!activeModel) {
|
|
3046
|
+
props.onModelChange(focusModel.id);
|
|
3047
|
+
props.onEffortChange(
|
|
3048
|
+
coerceReasoningEffortForModel(focusModel.catalog, props.effort)
|
|
3049
|
+
);
|
|
3050
|
+
}
|
|
3051
|
+
props.onLatencyModeChange(
|
|
3052
|
+
activeModel && props.latencyMode === "fast" ? "standard" : "fast"
|
|
3053
|
+
);
|
|
3054
|
+
},
|
|
3055
|
+
className: cn(
|
|
3056
|
+
"flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-og-sm text-og-fg-subtle outline-none transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50",
|
|
3057
|
+
activeModel && props.latencyMode === "fast" && "text-og-fg"
|
|
3058
|
+
),
|
|
3059
|
+
children: /* @__PURE__ */ jsx5(
|
|
3060
|
+
ZapIcon,
|
|
3061
|
+
{
|
|
3062
|
+
className: cn(
|
|
3063
|
+
"size-3.5",
|
|
3064
|
+
activeModel && props.latencyMode === "fast" && "fill-current"
|
|
3065
|
+
)
|
|
3066
|
+
}
|
|
3067
|
+
)
|
|
3068
|
+
}
|
|
3069
|
+
) : null
|
|
3070
|
+
}
|
|
3071
|
+
),
|
|
3072
|
+
/* @__PURE__ */ jsx5("p", { className: "px-2.5 pt-1 pb-1 text-xs font-medium tracking-wide text-og-fg-subtle uppercase", children: messages.thinking }),
|
|
3073
|
+
/* @__PURE__ */ jsx5("div", { className: "flex flex-col gap-0.5", children: effortOptionsForModel(focusModel.catalog).map((effort) => {
|
|
3074
|
+
const selected = activeModel && effort === props.effort;
|
|
3075
|
+
return /* @__PURE__ */ jsxs5(
|
|
3076
|
+
"button",
|
|
3077
|
+
{
|
|
3078
|
+
type: "button",
|
|
3079
|
+
disabled: !focusModel.selectable,
|
|
3080
|
+
onClick: () => selectEffort(focusModel, effort),
|
|
3081
|
+
className: cn(
|
|
3082
|
+
"flex h-8 w-full cursor-pointer items-center rounded-og-sm px-2.5 text-left text-sm text-og-fg outline-none transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50",
|
|
3083
|
+
selected && "bg-og-surface-2"
|
|
3084
|
+
),
|
|
3085
|
+
children: [
|
|
3086
|
+
/* @__PURE__ */ jsx5("span", { className: "min-w-0 flex-1 truncate", children: labelReasoningEffort(effort) }),
|
|
3087
|
+
selected ? /* @__PURE__ */ jsx5(
|
|
3088
|
+
CheckIcon,
|
|
3089
|
+
{
|
|
3090
|
+
className: "ml-auto size-3.5 shrink-0",
|
|
3091
|
+
"data-testid": "model-picker-effort-check"
|
|
3092
|
+
}
|
|
3093
|
+
) : null
|
|
3094
|
+
]
|
|
3095
|
+
},
|
|
3096
|
+
effort
|
|
3097
|
+
);
|
|
3098
|
+
}) })
|
|
3099
|
+
] });
|
|
3100
|
+
} else {
|
|
3101
|
+
body = /* @__PURE__ */ jsx5("div", { className: "flex flex-col gap-0.5", "data-testid": "model-picker-providers", children: groups.map((group) => /* @__PURE__ */ jsx5(
|
|
3102
|
+
PickerNavRow,
|
|
3103
|
+
{
|
|
3104
|
+
label: group.label,
|
|
3105
|
+
hint: messages.billingHints[group.billingClass],
|
|
3106
|
+
icon: /* @__PURE__ */ jsx5(BillingClassMark, { billingClass: group.billingClass }),
|
|
3107
|
+
testId: `model-picker-rail-${group.billingClass}`,
|
|
3108
|
+
onClick: () => go({ level: "models", rail: group.billingClass, modelId: null }, 1)
|
|
3109
|
+
},
|
|
3110
|
+
group.billingClass
|
|
3111
|
+
)) });
|
|
3112
|
+
}
|
|
3113
|
+
return /* @__PURE__ */ jsxs5("div", { "data-testid": "model-picker-menu", className: "relative overflow-hidden", children: [
|
|
3114
|
+
props.error ? /* @__PURE__ */ jsx5("p", { className: "px-2 py-1 text-xs text-og-status-failed", role: "alert", children: props.error }) : null,
|
|
3115
|
+
/* @__PURE__ */ jsx5(PickerAnimatedPage, { pageKey, direction, children: body })
|
|
3116
|
+
] });
|
|
3117
|
+
}
|
|
3118
|
+
function ModelPolicyPicker(props) {
|
|
3119
|
+
const [open, setOpen] = useState6(false);
|
|
3120
|
+
const messages = useMemo5(
|
|
3121
|
+
() => ({ ...defaultModelPolicyPickerMessages, ...props.messages }),
|
|
3122
|
+
[props.messages]
|
|
3123
|
+
);
|
|
3124
|
+
const rows = effectiveRows(props);
|
|
3125
|
+
const [nav, setNav] = usePickerNavState(props.sessionKey, rows, props.model);
|
|
3126
|
+
const selected = findPickerRow(rows, props.model);
|
|
3127
|
+
if (props.loading) {
|
|
3128
|
+
return /* @__PURE__ */ jsx5(
|
|
3129
|
+
"span",
|
|
3130
|
+
{
|
|
3131
|
+
className: cn(
|
|
3132
|
+
"inline-flex h-8 w-40 shrink-0 animate-pulse rounded-full bg-og-surface-2",
|
|
3133
|
+
props.className
|
|
3134
|
+
),
|
|
3135
|
+
"aria-label": messages.loading,
|
|
3136
|
+
"data-testid": "model-picker-loading"
|
|
3137
|
+
}
|
|
3138
|
+
);
|
|
3139
|
+
}
|
|
3140
|
+
return /* @__PURE__ */ jsxs5(DropdownMenu.Root, { open, onOpenChange: setOpen, children: [
|
|
3141
|
+
/* @__PURE__ */ jsx5(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs5(
|
|
3142
|
+
"button",
|
|
3143
|
+
{
|
|
3144
|
+
type: "button",
|
|
3145
|
+
disabled: props.disabled,
|
|
3146
|
+
"aria-label": messages.label,
|
|
3147
|
+
className: cn(
|
|
3148
|
+
"inline-flex h-8 max-w-64 items-center gap-1 rounded-full border border-transparent px-2.5 text-xs text-og-fg-muted outline-none 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",
|
|
3149
|
+
props.className
|
|
3150
|
+
),
|
|
3151
|
+
children: [
|
|
3152
|
+
/* @__PURE__ */ jsx5(
|
|
3153
|
+
BillingClassMark,
|
|
3154
|
+
{
|
|
3155
|
+
billingClass: selected?.billingClass ?? (props.model.startsWith("codex/") ? "codex_subscription" : "opengeni_credits"),
|
|
3156
|
+
className: "text-og-fg"
|
|
3157
|
+
}
|
|
3158
|
+
),
|
|
3159
|
+
/* @__PURE__ */ jsx5("span", { className: "truncate font-medium text-og-fg", children: selected?.label ?? props.model }),
|
|
3160
|
+
/* @__PURE__ */ jsx5("span", { children: labelReasoningEffort(props.effort) }),
|
|
3161
|
+
props.latencyMode === "fast" ? /* @__PURE__ */ jsx5(
|
|
3162
|
+
ZapIcon,
|
|
3163
|
+
{
|
|
3164
|
+
className: "size-3.5 shrink-0 text-og-fg",
|
|
3165
|
+
"aria-label": messages.fast,
|
|
3166
|
+
"data-testid": "model-picker-fast-icon"
|
|
3167
|
+
}
|
|
3168
|
+
) : null,
|
|
3169
|
+
/* @__PURE__ */ jsx5(ChevronDownIcon3, { className: "size-3 shrink-0" })
|
|
3170
|
+
]
|
|
3171
|
+
}
|
|
3172
|
+
) }),
|
|
3173
|
+
/* @__PURE__ */ jsx5(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx5(
|
|
3174
|
+
DropdownMenu.Content,
|
|
3175
|
+
{
|
|
3176
|
+
align: "start",
|
|
3177
|
+
side: props.menuSide ?? "bottom",
|
|
3178
|
+
sideOffset: 8,
|
|
3179
|
+
collisionPadding: 12,
|
|
3180
|
+
onCloseAutoFocus: (event) => event.preventDefault(),
|
|
3181
|
+
className: "z-50 flex max-h-[min(20rem,var(--radix-dropdown-menu-content-available-height))] w-72 max-w-[calc(100vw-16px)] flex-col overflow-hidden rounded-og-lg border border-og-border bg-og-surface-1 p-1.5 text-og-fg shadow-og-lg",
|
|
3182
|
+
children: /* @__PURE__ */ jsx5("div", { className: "min-h-0 flex-1 overflow-y-auto overscroll-contain", children: /* @__PURE__ */ jsx5(ModelPolicyPickerMenu, { ...props, nav, onNavChange: setNav }) })
|
|
3183
|
+
}
|
|
3184
|
+
) })
|
|
3185
|
+
] });
|
|
3186
|
+
}
|
|
3187
|
+
|
|
2761
3188
|
export {
|
|
2762
3189
|
INITIAL_TRANSCRIPTION_CONTROL_STATE,
|
|
2763
3190
|
transitionTranscriptionControl,
|
|
@@ -2797,6 +3224,13 @@ export {
|
|
|
2797
3224
|
SendButton,
|
|
2798
3225
|
Help,
|
|
2799
3226
|
Status,
|
|
2800
|
-
ComposerTranscriptionControl
|
|
3227
|
+
ComposerTranscriptionControl,
|
|
3228
|
+
defaultModelPolicyPickerMessages,
|
|
3229
|
+
BillingClassMark,
|
|
3230
|
+
PickerNavRow,
|
|
3231
|
+
PickerBackHeader,
|
|
3232
|
+
PickerAnimatedPage,
|
|
3233
|
+
ModelPolicyPickerMenu,
|
|
3234
|
+
ModelPolicyPicker
|
|
2801
3235
|
};
|
|
2802
|
-
//# sourceMappingURL=chunk-
|
|
3236
|
+
//# sourceMappingURL=chunk-IP22SLO6.js.map
|