@opengeni/react 0.37.0 → 0.41.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.
Files changed (71) hide show
  1. package/README.md +88 -2
  2. package/dist/{chunk-7CJOAW3V.js → chunk-EB67J347.js} +1 -135
  3. package/dist/chunk-EB67J347.js.map +1 -0
  4. package/dist/chunk-EKZH6IDG.js +141 -0
  5. package/dist/chunk-EKZH6IDG.js.map +1 -0
  6. package/dist/{chunk-FSPDND3P.js → chunk-JALF5FI3.js} +8 -6
  7. package/dist/{chunk-FSPDND3P.js.map → chunk-JALF5FI3.js.map} +1 -1
  8. package/dist/{chunk-UCZPNXV3.js → chunk-KR2SK5GJ.js} +1292 -711
  9. package/dist/chunk-KR2SK5GJ.js.map +1 -0
  10. package/dist/{chunk-IP22SLO6.js → chunk-OMCFRWHL.js} +28 -441
  11. package/dist/chunk-OMCFRWHL.js.map +1 -0
  12. package/dist/{chunk-HJ4OQVGW.js → chunk-Q2NCKWTK.js} +10 -5
  13. package/dist/chunk-Q2NCKWTK.js.map +1 -0
  14. package/dist/{chunk-ALA3UGWB.js → chunk-SXIQK54Z.js} +8 -6
  15. package/dist/{chunk-ALA3UGWB.js.map → chunk-SXIQK54Z.js.map} +1 -1
  16. package/dist/chunk-WZT5G5OR.js +433 -0
  17. package/dist/chunk-WZT5G5OR.js.map +1 -0
  18. package/dist/client.d.ts +2 -0
  19. package/dist/components/chat-composer.d.ts +5 -1
  20. package/dist/components/human-input-form.d.ts +16 -6
  21. package/dist/components/human-input-surface.d.ts +19 -0
  22. package/dist/components/machine-input-display.d.ts +12 -0
  23. package/dist/components/message-timeline.d.ts +6 -1
  24. package/dist/components/session-chrome.d.ts +1 -0
  25. package/dist/components/tip-follow.d.ts +30 -0
  26. package/dist/composer.js +14 -11
  27. package/dist/hooks/use-composer.d.ts +1 -1
  28. package/dist/index.d.ts +4 -0
  29. package/dist/index.js +2246 -2236
  30. package/dist/index.js.map +1 -1
  31. package/dist/machines.js +4 -3
  32. package/dist/realtime/dropdown-menu.d.ts +16 -0
  33. package/dist/realtime/realtime-control.d.ts +126 -0
  34. package/dist/realtime.d.ts +11 -0
  35. package/dist/realtime.js +1023 -0
  36. package/dist/realtime.js.map +1 -0
  37. package/dist/session-context.d.ts +7 -1
  38. package/dist/session-ui.d.ts +2 -0
  39. package/dist/session-ui.js +5 -3
  40. package/dist/session.js +4 -3
  41. package/dist/timeline/compute-label.d.ts +2 -0
  42. package/dist/timeline/index.d.ts +1 -0
  43. package/package.json +7 -2
  44. package/src/client.ts +13 -0
  45. package/src/components/chat-composer.tsx +11 -2
  46. package/src/components/composer-transcription-control.tsx +2 -2
  47. package/src/components/composer.tsx +14 -5
  48. package/src/components/human-input-form.tsx +506 -186
  49. package/src/components/human-input-surface.tsx +80 -0
  50. package/src/components/machine-input-display.ts +83 -0
  51. package/src/components/message-timeline.tsx +348 -308
  52. package/src/components/model-policy-picker.tsx +8 -3
  53. package/src/components/sandbox-files.tsx +1 -1
  54. package/src/components/session-chrome.tsx +3 -1
  55. package/src/components/tip-follow.ts +127 -6
  56. package/src/hooks/use-composer.ts +16 -13
  57. package/src/index.ts +4 -0
  58. package/src/realtime/dropdown-menu.tsx +123 -0
  59. package/src/realtime/realtime-control.tsx +1178 -0
  60. package/src/realtime.ts +27 -0
  61. package/src/session-context.ts +16 -0
  62. package/src/session-ui.ts +2 -0
  63. package/src/timeline/compute-label.tsx +18 -0
  64. package/src/timeline/index.ts +3 -0
  65. package/src/timeline/tool-renderers.tsx +232 -43
  66. package/styles/index.css +61 -0
  67. package/styles/tokens.css +2 -0
  68. package/dist/chunk-7CJOAW3V.js.map +0 -1
  69. package/dist/chunk-HJ4OQVGW.js.map +0 -1
  70. package/dist/chunk-IP22SLO6.js.map +0 -1
  71. package/dist/chunk-UCZPNXV3.js.map +0 -1
@@ -1,15 +1,9 @@
1
1
  import {
2
2
  shouldSteerOnKey,
3
3
  shouldSubmitOnKey
4
- } from "./chunk-HJ4OQVGW.js";
4
+ } from "./chunk-Q2NCKWTK.js";
5
5
  import {
6
- coerceReasoningEffortForModel,
7
- effortOptionsForModel,
8
- findPickerRow,
9
- groupPickerRowsByBillingClass,
10
- labelReasoningEffort,
11
- projectClientModelRows,
12
- runnableLatencyModesForModel
6
+ groupPickerRowsByBillingClass
13
7
  } from "./chunk-SJKT4TKW.js";
14
8
  import {
15
9
  Tooltip,
@@ -17,14 +11,14 @@ import {
17
11
  TooltipProvider,
18
12
  TooltipTrigger
19
13
  } from "./chunk-ATSTR5P3.js";
20
- import {
21
- cn
22
- } from "./chunk-TK7G6XLT.js";
23
14
  import {
24
15
  composerSubmissionErrorMessage,
25
16
  formatBytes,
26
17
  formatRelativeTime
27
18
  } from "./chunk-LAKLF4PA.js";
19
+ import {
20
+ cn
21
+ } from "./chunk-TK7G6XLT.js";
28
22
 
29
23
  // src/hooks/use-transcription.ts
30
24
  import {
@@ -1297,17 +1291,17 @@ function ModelPicker({
1297
1291
  codexOnly = false
1298
1292
  }) {
1299
1293
  const selectId = useId();
1300
- const effectiveRows2 = useMemo3(
1294
+ const effectiveRows = useMemo3(
1301
1295
  () => rows && rows.length > 0 ? applyCodexOnlyRows(rows, codexOnly) : [],
1302
1296
  [rows, codexOnly]
1303
1297
  );
1304
1298
  const billingGroups = useMemo3(
1305
- () => effectiveRows2.length > 0 ? groupPickerRowsByBillingClass(effectiveRows2) : [],
1306
- [effectiveRows2]
1299
+ () => effectiveRows.length > 0 ? groupPickerRowsByBillingClass(effectiveRows) : [],
1300
+ [effectiveRows]
1307
1301
  );
1308
1302
  const providerGroupList = useMemo3(() => providerGroups(models, codexOnly), [models, codexOnly]);
1309
- const useBillingGroups = Boolean(effectiveRows2.length);
1310
- if (models.length === 0 && effectiveRows2.length === 0) {
1303
+ const useBillingGroups = Boolean(effectiveRows.length);
1304
+ if (models.length === 0 && effectiveRows.length === 0) {
1311
1305
  return null;
1312
1306
  }
1313
1307
  return /* @__PURE__ */ jsxs2("span", { className: cn("relative inline-flex items-center", className), children: [
@@ -1970,7 +1964,11 @@ var Footer = forwardRef(function ComposerFooter({ className, ...props }, ref) {
1970
1964
  {
1971
1965
  ...props,
1972
1966
  ref,
1973
- className: cn("flex items-end gap-1.5 px-2 pb-2 pt-0.5 sm:px-2.5 sm:pb-2.5", className)
1967
+ className: cn(
1968
+ "flex items-end gap-1.5 px-2 pb-2 pt-0.5 sm:px-2.5 sm:pb-2.5",
1969
+ "max-sm:items-center max-sm:gap-1",
1970
+ className
1971
+ )
1974
1972
  }
1975
1973
  );
1976
1974
  });
@@ -1981,7 +1979,11 @@ var Controls = forwardRef(
1981
1979
  {
1982
1980
  ...props,
1983
1981
  ref,
1984
- className: cn("flex min-w-0 flex-1 flex-wrap items-center gap-1.5", className)
1982
+ className: cn(
1983
+ "flex min-w-0 flex-1 flex-wrap items-center gap-1.5",
1984
+ "max-sm:flex-nowrap max-sm:gap-1",
1985
+ className
1986
+ )
1985
1987
  }
1986
1988
  );
1987
1989
  }
@@ -2021,6 +2023,7 @@ var AttachButton = forwardRef(
2021
2023
  type: "file",
2022
2024
  accept,
2023
2025
  multiple,
2026
+ "data-og-composer-attach": true,
2024
2027
  className: "hidden",
2025
2028
  onChange: controller.handleFileChange
2026
2029
  }
@@ -2037,7 +2040,7 @@ var AttachButton = forwardRef(
2037
2040
  className: cn(
2038
2041
  "inline-flex size-8 items-center justify-center rounded-og-md",
2039
2042
  "text-og-fg-muted transition-colors duration-150 hover:bg-og-surface-2 hover:text-og-fg",
2040
- "disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:size-11",
2043
+ "disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:size-9",
2041
2044
  className
2042
2045
  ),
2043
2046
  children: children ?? /* @__PURE__ */ jsx3(PaperclipIcon, { className: "size-4" })
@@ -2086,7 +2089,7 @@ var PauseButton = forwardRef(
2086
2089
  disabled: busy,
2087
2090
  "aria-label": ariaLabel ?? controller.messages.pauseAriaLabel,
2088
2091
  className: cn(
2089
- "inline-flex size-8 items-center justify-center rounded-og-md border border-og-border pointer-coarse:size-11",
2092
+ "inline-flex size-8 items-center justify-center rounded-og-md border border-og-border pointer-coarse:size-9",
2090
2093
  "bg-og-surface-2 text-og-fg-muted transition-colors duration-150",
2091
2094
  "hover:border-og-status-waiting/50 hover:text-og-status-waiting",
2092
2095
  "disabled:opacity-50",
@@ -2112,7 +2115,7 @@ var SendButton = forwardRef(
2112
2115
  "data-og-tip": tip,
2113
2116
  "aria-label": ariaLabel ?? (controller.paused ? controller.messages.sendAndResumeAriaLabel : controller.messages.sendMessageAriaLabel),
2114
2117
  className: cn(
2115
- "inline-flex size-8 items-center justify-center rounded-og-md pointer-coarse:size-11",
2118
+ "inline-flex size-8 items-center justify-center rounded-og-md pointer-coarse:size-9",
2116
2119
  "bg-og-accent text-og-accent-fg shadow-og-sm",
2117
2120
  "transition-[background-color,transform,opacity] duration-150 ease-og-spring",
2118
2121
  "hover:bg-og-accent-strong active:scale-95",
@@ -2580,7 +2583,7 @@ function ComposerTranscriptionControl({
2580
2583
  transition: { duration: 0.16, ease: [0.22, 1, 0.36, 1] },
2581
2584
  className: cn(
2582
2585
  "inline-flex h-8 items-center gap-1 rounded-og-md border border-og-border/80",
2583
- "bg-og-surface-2/70 pl-2 pr-1 pointer-coarse:h-11"
2586
+ "bg-og-surface-2/70 pl-2 pr-1 pointer-coarse:h-9"
2584
2587
  ),
2585
2588
  children: [
2586
2589
  status === "requesting-permission" ? /* @__PURE__ */ jsx4(
@@ -2652,7 +2655,7 @@ function ComposerTranscriptionControl({
2652
2655
  "aria-pressed": false,
2653
2656
  "aria-disabled": unavailableMessage !== null,
2654
2657
  className: cn(
2655
- "inline-flex size-8 shrink-0 items-center justify-center rounded-og-md pointer-coarse:size-11",
2658
+ "inline-flex size-8 shrink-0 items-center justify-center rounded-og-md pointer-coarse:size-9",
2656
2659
  "text-og-fg-muted transition-colors duration-150 motion-reduce:transition-none",
2657
2660
  unavailableMessage ? "cursor-not-allowed opacity-45" : "hover:bg-og-surface-2 hover:text-og-fg"
2658
2661
  ),
@@ -2776,415 +2779,6 @@ function transcriptionErrorMessage(code, messages) {
2776
2779
  }
2777
2780
  }
2778
2781
 
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
-
3188
2782
  export {
3189
2783
  INITIAL_TRANSCRIPTION_CONTROL_STATE,
3190
2784
  transitionTranscriptionControl,
@@ -3224,13 +2818,6 @@ export {
3224
2818
  SendButton,
3225
2819
  Help,
3226
2820
  Status,
3227
- ComposerTranscriptionControl,
3228
- defaultModelPolicyPickerMessages,
3229
- BillingClassMark,
3230
- PickerNavRow,
3231
- PickerBackHeader,
3232
- PickerAnimatedPage,
3233
- ModelPolicyPickerMenu,
3234
- ModelPolicyPicker
2821
+ ComposerTranscriptionControl
3235
2822
  };
3236
- //# sourceMappingURL=chunk-IP22SLO6.js.map
2823
+ //# sourceMappingURL=chunk-OMCFRWHL.js.map