@opengeni/react 7.0.0 → 7.1.0-canary.35916963870001

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 (68) hide show
  1. package/README.md +34 -0
  2. package/dist/approvals.d.ts +2 -1
  3. package/dist/{chunk-D5NOQPLR.js → chunk-CJCVYUKK.js} +25 -15
  4. package/dist/chunk-CJCVYUKK.js.map +1 -0
  5. package/dist/{chunk-IYUPN32E.js → chunk-DBPVUGQT.js} +6 -1
  6. package/dist/{chunk-IYUPN32E.js.map → chunk-DBPVUGQT.js.map} +1 -1
  7. package/dist/{chunk-JKLGJQO5.js → chunk-HJDDS2L6.js} +35 -15
  8. package/dist/chunk-HJDDS2L6.js.map +1 -0
  9. package/dist/{chunk-5GAL23FF.js → chunk-IOLPHOF4.js} +2 -5
  10. package/dist/chunk-IOLPHOF4.js.map +1 -0
  11. package/dist/{chunk-D7GAPJ3V.js → chunk-RAJYEBEG.js} +63 -30
  12. package/dist/chunk-RAJYEBEG.js.map +1 -0
  13. package/dist/{chunk-IP4BUBKH.js → chunk-TA4W6KBP.js} +24 -13
  14. package/dist/chunk-TA4W6KBP.js.map +1 -0
  15. package/dist/{chunk-UXE5SSNN.js → chunk-U56XI627.js} +2 -2
  16. package/dist/{chunk-JPHDWKZE.js → chunk-X7YDBAQD.js} +12 -7
  17. package/dist/chunk-X7YDBAQD.js.map +1 -0
  18. package/dist/{chunk-HJ5VJ4JB.js → chunk-ZA4K7YY2.js} +73 -15
  19. package/dist/chunk-ZA4K7YY2.js.map +1 -0
  20. package/dist/components/markdown.d.ts +2 -0
  21. package/dist/components/model-policy-picker.d.ts +17 -1
  22. package/dist/components/session-conversation.d.ts +3 -0
  23. package/dist/composer.d.ts +1 -1
  24. package/dist/composer.js +4 -4
  25. package/dist/connect.js +1 -1
  26. package/dist/hooks/use-session-events.d.ts +6 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.js +10 -13
  29. package/dist/index.js.map +1 -1
  30. package/dist/machines.js +1 -1
  31. package/dist/{model-policy-picker-menu-RVOQ4ZZG.js → model-policy-picker-menu-S3SF65AH.js} +4 -4
  32. package/dist/model-policy.js +1 -1
  33. package/dist/realtime.js +2 -2
  34. package/dist/session-ui.js +6 -6
  35. package/dist/session.js +2 -2
  36. package/dist/timeline/tool-display-name.d.ts +2 -1
  37. package/dist/timeline/types.d.ts +2 -1
  38. package/package.json +3 -3
  39. package/src/approvals.ts +8 -1
  40. package/src/components/approval-surface.tsx +12 -2
  41. package/src/components/machine-card.tsx +5 -5
  42. package/src/components/machine-dock-bar.tsx +1 -1
  43. package/src/components/machines/machine-detail.tsx +5 -2
  44. package/src/components/markdown.tsx +101 -55
  45. package/src/components/model-policy-picker-menu.tsx +131 -33
  46. package/src/components/model-policy-picker.tsx +61 -12
  47. package/src/components/session-commands-panel.tsx +8 -3
  48. package/src/components/session-conversation.tsx +5 -1
  49. package/src/composer.ts +1 -0
  50. package/src/hooks/use-last-started-turn-policy.ts +3 -7
  51. package/src/hooks/use-session-events.ts +32 -7
  52. package/src/index.ts +1 -0
  53. package/src/model-policy.ts +1 -4
  54. package/src/timeline/projection.ts +4 -0
  55. package/src/timeline/rolling-activity.tsx +4 -2
  56. package/src/timeline/tool-display-name.ts +8 -6
  57. package/src/timeline/tool-renderers.tsx +5 -3
  58. package/src/timeline/types.ts +2 -0
  59. package/styles/compiled.css +15 -0
  60. package/dist/chunk-5GAL23FF.js.map +0 -1
  61. package/dist/chunk-D5NOQPLR.js.map +0 -1
  62. package/dist/chunk-D7GAPJ3V.js.map +0 -1
  63. package/dist/chunk-HJ5VJ4JB.js.map +0 -1
  64. package/dist/chunk-IP4BUBKH.js.map +0 -1
  65. package/dist/chunk-JKLGJQO5.js.map +0 -1
  66. package/dist/chunk-JPHDWKZE.js.map +0 -1
  67. /package/dist/{chunk-UXE5SSNN.js.map → chunk-U56XI627.js.map} +0 -0
  68. /package/dist/{model-policy-picker-menu-RVOQ4ZZG.js.map → model-policy-picker-menu-S3SF65AH.js.map} +0 -0
@@ -7,7 +7,7 @@ import {
7
7
  findPickerRow,
8
8
  labelReasoningEffort,
9
9
  projectClientModelRows
10
- } from "./chunk-5GAL23FF.js";
10
+ } from "./chunk-IOLPHOF4.js";
11
11
  import {
12
12
  cn
13
13
  } from "./chunk-22KP6LR5.js";
@@ -19,6 +19,7 @@ import {
19
19
  ChevronRightIcon,
20
20
  Globe2Icon,
21
21
  KeyRoundIcon,
22
+ SparklesIcon,
22
23
  ZapIcon
23
24
  } from "lucide-react";
24
25
  import { motion, useReducedMotion } from "motion/react";
@@ -31,7 +32,7 @@ import {
31
32
  } from "react";
32
33
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
33
34
  var LazyModelPolicyPickerMenu = lazy(
34
- () => import("./model-policy-picker-menu-RVOQ4ZZG.js").then(({ ModelPolicyPickerPopover }) => ({
35
+ () => import("./model-policy-picker-menu-S3SF65AH.js").then(({ ModelPolicyPickerPopover }) => ({
35
36
  default: ModelPolicyPickerPopover
36
37
  }))
37
38
  );
@@ -39,6 +40,9 @@ var defaultModelPolicyPickerMessages = {
39
40
  label: "Model and effort",
40
41
  loading: "Loading model catalog\u2026",
41
42
  noModels: "No models available.",
43
+ connectTitle: "Connect a model",
44
+ connectBody: "Use a subscription or a provider key you already have.",
45
+ connectAction: "Open Models",
42
46
  thinking: "Thinking",
43
47
  fast: "Fast",
44
48
  fastRateHint: "2\xD7 rate",
@@ -84,10 +88,11 @@ function BillingClassMark(props) {
84
88
  byok: "Workspace provider account",
85
89
  organization_byok: "Organization provider account"
86
90
  };
87
- const label = props["aria-label"] ?? labels[props.billingClass];
91
+ if (props.presentation?.icon === null) return null;
92
+ const label = props["aria-label"] ?? props.presentation?.label ?? labels[props.billingClass];
88
93
  const accessibility = label.length === 0 ? { "aria-hidden": true } : { role: "img", "aria-label": label };
89
94
  const shell = cn(
90
- "inline-flex size-3.5 shrink-0 items-center justify-center overflow-hidden text-og-fg-subtle",
95
+ "inline-flex size-3.5 shrink-0 items-center justify-center overflow-hidden text-og-fg-subtle [&>svg]:size-full [&>img]:size-full",
91
96
  props.className
92
97
  );
93
98
  const mark = "size-3.5";
@@ -97,7 +102,7 @@ function BillingClassMark(props) {
97
102
  className: shell,
98
103
  "data-testid": `billing-class-icon-${props.billingClass}`,
99
104
  ...accessibility,
100
- children: props.billingClass === "opengeni_credits" ? /* @__PURE__ */ jsx(OpenGeniMark, { className: mark }) : props.billingClass === "external" ? /* @__PURE__ */ jsx(Globe2Icon, { className: mark, "aria-hidden": true }) : props.billingClass === "codex_subscription" ? /* @__PURE__ */ jsx(ChatGptMark, { className: mark }) : props.billingClass === "supergrok_subscription" ? /* @__PURE__ */ jsx(XaiMark, { className: mark }) : /* @__PURE__ */ jsx(KeyRoundIcon, { className: mark, "aria-hidden": true })
105
+ children: props.presentation?.icon !== void 0 ? props.presentation.icon : props.billingClass === "opengeni_credits" ? /* @__PURE__ */ jsx(OpenGeniMark, { className: mark }) : props.billingClass === "external" ? /* @__PURE__ */ jsx(Globe2Icon, { className: mark, "aria-hidden": true }) : props.billingClass === "codex_subscription" ? /* @__PURE__ */ jsx(ChatGptMark, { className: mark }) : props.billingClass === "supergrok_subscription" ? /* @__PURE__ */ jsx(XaiMark, { className: mark }) : /* @__PURE__ */ jsx(KeyRoundIcon, { className: mark, "aria-hidden": true })
101
106
  }
102
107
  );
103
108
  }
@@ -125,7 +130,10 @@ function applyCodexOnly(rows, codexOnly, unavailableReason) {
125
130
  function effectiveRows(props) {
126
131
  const rows = props.rows !== void 0 ? props.rows : projectClientModelRows(props.models ?? []);
127
132
  const messages = { ...defaultModelPolicyPickerMessages, ...props.messages };
128
- return applyCodexOnly(rows, props.codexOnly === true, messages.codexOnly);
133
+ return applyCodexOnly(rows, props.codexOnly === true, messages.codexOnly).map((row) => {
134
+ const label = props.groupPresentation?.[row.billingClass]?.label;
135
+ return label === void 0 ? row : { ...row, billingClassLabel: label };
136
+ });
129
137
  }
130
138
  function PickerNavRow(props) {
131
139
  return /* @__PURE__ */ jsxs(
@@ -205,6 +213,7 @@ function ModelPolicyPicker(props) {
205
213
  );
206
214
  const { open, setOpen, rows } = useModelPolicyPickerState(props);
207
215
  const selected = findPickerRow(rows, props.model);
216
+ const needsModel = !rows.some((row) => row.selectable) && (rows.length > 0 || Boolean(props.connectModelsHref));
208
217
  if (props.loading) {
209
218
  return /* @__PURE__ */ jsx(
210
219
  "span",
@@ -232,20 +241,22 @@ function ModelPolicyPicker(props) {
232
241
  disabled: props.disabled,
233
242
  "aria-label": messages.label,
234
243
  className: cn(
235
- "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",
244
+ "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 px-2.5 text-og-control outline-hidden transition-colors 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",
245
+ needsModel ? "border-og-border bg-og-surface-2 text-og-fg hover:bg-og-surface-3" : "border-transparent text-og-fg-muted hover:border-og-border hover:bg-og-surface-2 hover:text-og-fg",
236
246
  props.className
237
247
  ),
238
248
  children: [
239
- /* @__PURE__ */ jsx(
249
+ needsModel ? /* @__PURE__ */ jsx(SparklesIcon, { className: "size-3.5 shrink-0", "aria-hidden": true }) : /* @__PURE__ */ jsx(
240
250
  BillingClassMark,
241
251
  {
242
252
  billingClass: selected?.billingClass ?? billingClassForMissingSelection(props.model),
253
+ presentation: props.groupPresentation?.[selected?.billingClass ?? billingClassForMissingSelection(props.model)],
243
254
  className: "text-og-fg"
244
255
  }
245
256
  ),
246
- /* @__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 }),
247
- /* @__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 }),
248
- selected && effortOptionsForModel(selected.catalog).length > 1 && selected.catalog.capabilities?.reasoning.runnable !== false ? /* @__PURE__ */ jsx(
257
+ /* @__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: needsModel ? messages.connectTitle : selected?.label ?? props.model }),
258
+ /* @__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: needsModel ? messages.connectTitle : selected?.shortLabel ?? selected?.label ?? props.model }),
259
+ selected && !needsModel && effortOptionsForModel(selected.catalog).length > 1 && selected.catalog.capabilities?.reasoning.runnable !== false ? /* @__PURE__ */ jsx(
249
260
  "span",
250
261
  {
251
262
  className: "og-model-policy-effort min-w-0 shrink-[9999] truncate",
@@ -253,7 +264,7 @@ function ModelPolicyPicker(props) {
253
264
  children: labelReasoningEffort(props.effort)
254
265
  }
255
266
  ) : null,
256
- props.latencyMode === "fast" ? /* @__PURE__ */ jsx(
267
+ props.latencyMode === "fast" && !needsModel ? /* @__PURE__ */ jsx(
257
268
  ZapIcon,
258
269
  {
259
270
  className: "size-3.5 shrink-0 fill-current stroke-current text-og-fg",
@@ -287,4 +298,4 @@ export {
287
298
  PickerAnimatedPage,
288
299
  ModelPolicyPicker
289
300
  };
290
- //# sourceMappingURL=chunk-IP4BUBKH.js.map
301
+ //# sourceMappingURL=chunk-TA4W6KBP.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 SparklesIcon,\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 effortOptionsForModel,\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\n/** Presentation only; never changes model identity, billing or availability. */\nexport type ModelPolicyPickerGroupPresentation = Partial<\n Record<\n PickerBillingClass,\n {\n label?: string | undefined;\n /** Omit to preserve the default; null hides the supporting text. */\n description?: string | null | undefined;\n /** Decorative, non-interactive content. Omit for the default; null hides it. */\n icon?: ReactNode | undefined;\n }\n >\n>;\n\nexport type ModelPolicyPickerMessages = {\n label: string;\n loading: string;\n noModels: string;\n connectTitle: string;\n connectBody: string;\n connectAction: 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 free?: 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 connectTitle: \"Connect a model\",\n connectBody: \"Use a subscription or a provider key you already have.\",\n connectAction: \"Open Models\",\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: \"This model cannot view the attached images.\",\n thinkingEffort: \"Thinking effort\",\n selected: \"Selected\",\n free: \"Free\",\n\n billingHints: {\n opengeni_credits: \"Provided by OpenGeni\",\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 /** Host branding for payment-source groups, shared by menu and trigger. */\n groupPresentation?: ModelPolicyPickerGroupPresentation | undefined;\n /** Lightweight deployment models. Catalog rows take precedence when supplied. */\n models?: ClientModel[] | undefined;\n /** Warn only when the draft actually contains images this model cannot view. */\n hasImageAttachments?: boolean | 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 /** Settings → Models. Shown when the catalog has no model that can run. */\n connectModelsHref?: string | 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\n// Solid facets keep the brand legible at the picker’s 14px icon size.\nfunction OpenGeniMark(props: SVGProps<SVGSVGElement>) {\n return (\n <svg viewBox=\"0 0 140 133\" fill=\"currentColor\" aria-hidden=\"true\" {...props}>\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 presentation?: ModelPolicyPickerGroupPresentation[PickerBillingClass] | undefined;\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 if (props.presentation?.icon === null) return null;\n const label = props[\"aria-label\"] ?? props.presentation?.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 [&>svg]:size-full [&>img]:size-full\",\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.presentation?.icon !== undefined ? (\n props.presentation.icon\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).map((row) => {\n const label = props.groupPresentation?.[row.billingClass]?.label;\n return label === undefined ? row : { ...row, billingClassLabel: label };\n });\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 description?: 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 aria-description={props.description}\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 const needsModel =\n !rows.some((row) => row.selectable) && (rows.length > 0 || Boolean(props.connectModelsHref));\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 px-2.5 text-og-control outline-hidden transition-colors 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 needsModel\n ? \"border-og-border bg-og-surface-2 text-og-fg hover:bg-og-surface-3\"\n : \"border-transparent text-og-fg-muted hover:border-og-border hover:bg-og-surface-2 hover:text-og-fg\",\n props.className,\n )}\n >\n {needsModel ? (\n <SparklesIcon className=\"size-3.5 shrink-0\" aria-hidden />\n ) : (\n <BillingClassMark\n billingClass={selected?.billingClass ?? billingClassForMissingSelection(props.model)}\n presentation={\n props.groupPresentation?.[\n selected?.billingClass ?? billingClassForMissingSelection(props.model)\n ]\n }\n className=\"text-og-fg\"\n />\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 {needsModel ? messages.connectTitle : (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 {needsModel\n ? messages.connectTitle\n : (selected?.shortLabel ?? selected?.label ?? props.model)}\n </span>\n {selected &&\n !needsModel &&\n effortOptionsForModel(selected.catalog).length > 1 &&\n selected.catalog.capabilities?.reasoning.runnable !== false ? (\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 ) : null}\n {props.latencyMode === \"fast\" && !needsModel ? (\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":[]}
@@ -19,7 +19,7 @@ import {
19
19
  } from "./chunk-PLYRL5ER.js";
20
20
  import {
21
21
  groupPickerRowsByBillingClass
22
- } from "./chunk-5GAL23FF.js";
22
+ } from "./chunk-IOLPHOF4.js";
23
23
  import {
24
24
  cn
25
25
  } from "./chunk-22KP6LR5.js";
@@ -4666,4 +4666,4 @@ export {
4666
4666
  useVoiceInput,
4667
4667
  ComposerTranscriptionControl
4668
4668
  };
4669
- //# sourceMappingURL=chunk-UXE5SSNN.js.map
4669
+ //# sourceMappingURL=chunk-U56XI627.js.map
@@ -498,10 +498,12 @@ function MetricSparkline({
498
498
  // src/components/machine-card.tsx
499
499
  import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
500
500
  function KindIcon({ machine }) {
501
- if (machine.isSessionGroup)
501
+ if (machine.kind === "local" || machine.kind === "selfhosted")
502
+ return /* @__PURE__ */ jsx5(LaptopIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
503
+ if (machine.kind === "docker" || machine.isSessionGroup)
502
504
  return /* @__PURE__ */ jsx5(ServerIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
503
505
  if (machine.kind === "modal") return /* @__PURE__ */ jsx5(CpuIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
504
- return /* @__PURE__ */ jsx5(LaptopIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
506
+ return /* @__PURE__ */ jsx5(ServerIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
505
507
  }
506
508
  function MachineCard({
507
509
  machine,
@@ -590,7 +592,7 @@ function MachineCard({
590
592
  /* @__PURE__ */ jsxs5("div", { className: "mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-og-xs text-og-fg-subtle", children: [
591
593
  /* @__PURE__ */ jsx5("span", { "data-machine-scope": machine.scope, className: "capitalize", children: machine.scope === "user" ? "personal" : machine.scope }),
592
594
  /* @__PURE__ */ jsx5("span", { "aria-hidden": true, children: "\xB7" }),
593
- /* @__PURE__ */ jsx5("span", { className: "capitalize", children: machine.isSessionGroup ? "session sandbox" : machine.kind }),
595
+ /* @__PURE__ */ jsx5("span", { className: "capitalize", children: machine.kind }),
594
596
  /* @__PURE__ */ jsx5("span", { "aria-hidden": true, children: "\xB7" }),
595
597
  /* @__PURE__ */ jsxs5("span", { className: "font-og-mono", children: [
596
598
  machine.os,
@@ -1227,9 +1229,12 @@ function MachineOperationPolicyEditor({
1227
1229
  // src/components/machines/machine-detail.tsx
1228
1230
  import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1229
1231
  function KindIcon2({ kind, session }) {
1230
- if (session) return /* @__PURE__ */ jsx8(ServerIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
1232
+ if (kind === "local" || kind === "selfhosted")
1233
+ return /* @__PURE__ */ jsx8(LaptopIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
1234
+ if (kind === "docker" || session)
1235
+ return /* @__PURE__ */ jsx8(ServerIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
1231
1236
  if (kind === "modal") return /* @__PURE__ */ jsx8(CpuIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
1232
- return /* @__PURE__ */ jsx8(LaptopIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
1237
+ return /* @__PURE__ */ jsx8(ServerIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
1233
1238
  }
1234
1239
  function MachineDetail({
1235
1240
  machine,
@@ -1571,7 +1576,7 @@ function MachinesDashboard({
1571
1576
  import { LaptopIcon as LaptopIcon4, CpuIcon as CpuIcon3, UsersIcon as UsersIcon2 } from "lucide-react";
1572
1577
  import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1573
1578
  function MachineDockBar({ name, kind, state, className }) {
1574
- const Icon = kind === "selfhosted" ? LaptopIcon4 : CpuIcon3;
1579
+ const Icon = kind === "selfhosted" || kind === "local" ? LaptopIcon4 : CpuIcon3;
1575
1580
  const stateBadge = MACHINE_STATE_BADGE_META[state];
1576
1581
  return /* @__PURE__ */ jsxs10(
1577
1582
  "div",
@@ -2442,4 +2447,4 @@ export {
2442
2447
  EnrollmentDeviceFlow,
2443
2448
  EnrollmentConsent
2444
2449
  };
2445
- //# sourceMappingURL=chunk-JPHDWKZE.js.map
2450
+ //# sourceMappingURL=chunk-X7YDBAQD.js.map