@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 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
- payerSummaryForModel,
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
- useEffect,
25
+ Suspense,
26
+ lazy,
32
27
  useMemo,
33
- useRef,
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, nav, setNav };
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, nav, setNav } = useModelPolicyPickerState(props);
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(DropdownMenu.Root, { open, onOpenChange: setOpen, children: [
433
- /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
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("span", { className: "og-model-policy-effort max-sm:hidden", children: labelReasoningEffort(props.effort) }),
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(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx(
468
- DropdownMenu.Content,
276
+ ),
277
+ open ? /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
278
+ LazyModelPolicyPickerMenu,
469
279
  {
470
- align: "start",
471
- side: props.menuSide ?? "bottom",
472
- sideOffset: 8,
473
- collisionPadding: 12,
474
- onCloseAutoFocus: (event) => event.preventDefault(),
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-4JFUT22W.js.map
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":[]}