@opengeni/react 7.0.0-canary.35795903742001 → 7.1.0-canary.35855175602001
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 +30 -0
- package/dist/artifacts.js +17 -17
- package/dist/{browser-viewer-LGH4IP47.js → browser-viewer-MN7MOYQT.js} +5 -5
- package/dist/{chunk-YS24CFDI.js → chunk-2O2HXRGP.js} +7 -7
- package/dist/{chunk-IP4BUBKH.js → chunk-3LL47F4U.js} +28 -17
- package/dist/chunk-3LL47F4U.js.map +1 -0
- package/dist/{chunk-UXE5SSNN.js → chunk-4ACTWOOW.js} +8 -8
- package/dist/{chunk-5GAL23FF.js → chunk-IOLPHOF4.js} +2 -5
- package/dist/chunk-IOLPHOF4.js.map +1 -0
- package/dist/{chunk-JPHDWKZE.js → chunk-PFDNB3U7.js} +15 -10
- package/dist/chunk-PFDNB3U7.js.map +1 -0
- package/dist/{chunk-RAJYEBEG.js → chunk-SHRCATV6.js} +5 -5
- package/dist/{chunk-H5YGYNXS.js → chunk-TV5PP2PE.js} +11 -11
- package/dist/chunk-TV5PP2PE.js.map +1 -0
- package/dist/{chunk-PNAVEK2U.js → chunk-UQS7BGNQ.js} +12 -12
- package/dist/{chunk-HJDDS2L6.js → chunk-VI7HELBI.js} +6 -6
- package/dist/{chunk-HJ5VJ4JB.js → chunk-WKFFRFJF.js} +73 -15
- package/dist/chunk-WKFFRFJF.js.map +1 -0
- package/dist/{chunk-THGUSVPR.js → chunk-ZC2DK5SC.js} +56 -56
- package/dist/components/model-policy-picker.d.ts +17 -1
- package/dist/composer.d.ts +1 -1
- package/dist/composer.js +7 -7
- package/dist/{computer-viewer-CTFCJVS7.js → computer-viewer-FX4WOZMX.js} +4 -4
- package/dist/connect.js +5 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +111 -111
- package/dist/interaction.js +5 -5
- package/dist/machines.js +2 -2
- package/dist/{model-policy-picker-menu-RVOQ4ZZG.js → model-policy-picker-menu-AGXXJZ2B.js} +4 -4
- package/dist/model-policy.js +1 -1
- package/dist/realtime.js +5 -5
- package/dist/session-ui.js +12 -12
- package/dist/session.js +2 -2
- package/package.json +3 -3
- package/src/components/machine-card.tsx +5 -5
- package/src/components/machine-dock-bar.tsx +1 -1
- package/src/components/machines/machine-detail.tsx +5 -2
- package/src/components/model-policy-picker-menu.tsx +131 -33
- package/src/components/model-policy-picker.tsx +61 -12
- package/src/composer.ts +1 -0
- package/src/index.ts +1 -0
- package/src/model-policy.ts +1 -4
- package/styles/compiled.css +15 -0
- package/dist/chunk-5GAL23FF.js.map +0 -1
- package/dist/chunk-H5YGYNXS.js.map +0 -1
- package/dist/chunk-HJ5VJ4JB.js.map +0 -1
- package/dist/chunk-IP4BUBKH.js.map +0 -1
- package/dist/chunk-JPHDWKZE.js.map +0 -1
- /package/dist/{browser-viewer-LGH4IP47.js.map → browser-viewer-MN7MOYQT.js.map} +0 -0
- /package/dist/{chunk-YS24CFDI.js.map → chunk-2O2HXRGP.js.map} +0 -0
- /package/dist/{chunk-UXE5SSNN.js.map → chunk-4ACTWOOW.js.map} +0 -0
- /package/dist/{chunk-RAJYEBEG.js.map → chunk-SHRCATV6.js.map} +0 -0
- /package/dist/{chunk-PNAVEK2U.js.map → chunk-UQS7BGNQ.js.map} +0 -0
- /package/dist/{chunk-HJDDS2L6.js.map → chunk-VI7HELBI.js.map} +0 -0
- /package/dist/{chunk-THGUSVPR.js.map → chunk-ZC2DK5SC.js.map} +0 -0
- /package/dist/{computer-viewer-CTFCJVS7.js.map → computer-viewer-FX4WOZMX.js.map} +0 -0
- /package/dist/{model-policy-picker-menu-RVOQ4ZZG.js.map → model-policy-picker-menu-AGXXJZ2B.js.map} +0 -0
package/README.md
CHANGED
|
@@ -991,6 +991,36 @@ can translate its search, current-selection, empty-result, attachment-warning, a
|
|
|
991
991
|
thinking labels through `messages`, and override payment descriptions through
|
|
992
992
|
`messages.billingHints`.
|
|
993
993
|
|
|
994
|
+
Hosts can rebrand the full picker without replacing its interaction logic:
|
|
995
|
+
|
|
996
|
+
```tsx
|
|
997
|
+
<ModelPolicyPicker
|
|
998
|
+
{...pickerProps}
|
|
999
|
+
groupPresentation={{
|
|
1000
|
+
opengeni_credits: {
|
|
1001
|
+
label: "Acme Assist",
|
|
1002
|
+
icon: <AcmeMark aria-hidden="true" />,
|
|
1003
|
+
description: "Provided by your workspace",
|
|
1004
|
+
},
|
|
1005
|
+
codex_subscription: { description: null },
|
|
1006
|
+
}}
|
|
1007
|
+
/>
|
|
1008
|
+
```
|
|
1009
|
+
|
|
1010
|
+
`groupPresentation` is a partial map keyed by `PickerBillingClass`. Labels apply
|
|
1011
|
+
to group headings, search, and trigger-icon accessibility. Icons apply to both
|
|
1012
|
+
the menu and trigger; supply decorative, non-interactive content (SVG or image)
|
|
1013
|
+
that fits the existing 14px slot. Explicit `null` hides an icon or description;
|
|
1014
|
+
omitted fields retain defaults. Descriptions override `messages.billingHints`,
|
|
1015
|
+
can also be shown for the deployment-provided group, and are searchable. Existing
|
|
1016
|
+
`rows[].billingClassLabel` remains the fallback when no label override is supplied.
|
|
1017
|
+
This is presentation only: model IDs, billing, ordering, availability and callbacks
|
|
1018
|
+
are unchanged. The type `ModelPolicyPickerGroupPresentation` is exported from
|
|
1019
|
+
both `@opengeni/react` and `@opengeni/react/composer`. The native `ModelPicker`
|
|
1020
|
+
is a separate control; this API targets the full `ModelPolicyPicker` shown above.
|
|
1021
|
+
|
|
1022
|
+
For a rendered example, open the composer-responsive demo with `?branding=host`.
|
|
1023
|
+
|
|
994
1024
|
Subscription descriptions appear once per provider group. Free models carry a
|
|
995
1025
|
Free badge. Pass `hasImageAttachments` for the current draft to show an image
|
|
996
1026
|
compatibility warning only when the selected model cannot view those images.
|
package/dist/artifacts.js
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EditableSpreadsheetArtifactSurface,
|
|
3
|
+
EditableSpreadsheetGrid,
|
|
4
|
+
SpreadsheetArtifactSurface,
|
|
5
|
+
SpreadsheetGrid,
|
|
6
|
+
SpreadsheetProjectionGrid
|
|
7
|
+
} from "./chunk-OWHPKAOV.js";
|
|
8
|
+
import {
|
|
9
|
+
PUBLISHED_HTML_ARTIFACT_IFRAME_SANDBOX,
|
|
10
|
+
PublishedHtmlArtifactFrame,
|
|
11
|
+
openGeniSiteBridgePortFromBootstrap,
|
|
12
|
+
publishedHtmlArtifactDocument
|
|
13
|
+
} from "./chunk-UGMKPUEM.js";
|
|
1
14
|
import {
|
|
2
15
|
EditablePresentationArtifactSurface,
|
|
3
16
|
PresentationArtifactSurface,
|
|
@@ -5,6 +18,10 @@ import {
|
|
|
5
18
|
PresentationProjectionArtifactSurface,
|
|
6
19
|
PresentationProjectionEditor
|
|
7
20
|
} from "./chunk-VR4Z73EU.js";
|
|
21
|
+
import {
|
|
22
|
+
isRetainedImageContentType,
|
|
23
|
+
useRetainedImageObjectUrl
|
|
24
|
+
} from "./chunk-WYWRYUNQ.js";
|
|
8
25
|
import {
|
|
9
26
|
DocumentArtifactSurface,
|
|
10
27
|
DocumentEditor,
|
|
@@ -12,23 +29,6 @@ import {
|
|
|
12
29
|
DocumentProjectionEditor,
|
|
13
30
|
EditableDocumentArtifactSurface
|
|
14
31
|
} from "./chunk-XMXRI5JK.js";
|
|
15
|
-
import {
|
|
16
|
-
PUBLISHED_HTML_ARTIFACT_IFRAME_SANDBOX,
|
|
17
|
-
PublishedHtmlArtifactFrame,
|
|
18
|
-
openGeniSiteBridgePortFromBootstrap,
|
|
19
|
-
publishedHtmlArtifactDocument
|
|
20
|
-
} from "./chunk-UGMKPUEM.js";
|
|
21
|
-
import {
|
|
22
|
-
isRetainedImageContentType,
|
|
23
|
-
useRetainedImageObjectUrl
|
|
24
|
-
} from "./chunk-WYWRYUNQ.js";
|
|
25
|
-
import {
|
|
26
|
-
EditableSpreadsheetArtifactSurface,
|
|
27
|
-
EditableSpreadsheetGrid,
|
|
28
|
-
SpreadsheetArtifactSurface,
|
|
29
|
-
SpreadsheetGrid,
|
|
30
|
-
SpreadsheetProjectionGrid
|
|
31
|
-
} from "./chunk-OWHPKAOV.js";
|
|
32
32
|
import {
|
|
33
33
|
ArtifactSurface,
|
|
34
34
|
EditableArtifactMessage
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BrowserViewer
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-UQS7BGNQ.js";
|
|
4
|
+
import "./chunk-TV5PP2PE.js";
|
|
5
5
|
import "./chunk-5YK2ZDIG.js";
|
|
6
|
-
import "./chunk-JVYQRRC4.js";
|
|
7
6
|
import "./chunk-KZ73RL76.js";
|
|
8
|
-
import "./chunk-PLYRL5ER.js";
|
|
9
7
|
import "./chunk-NEXLLTP4.js";
|
|
8
|
+
import "./chunk-PLYRL5ER.js";
|
|
10
9
|
import "./chunk-22KP6LR5.js";
|
|
10
|
+
import "./chunk-JVYQRRC4.js";
|
|
11
11
|
export {
|
|
12
12
|
BrowserViewer
|
|
13
13
|
};
|
|
14
|
-
//# sourceMappingURL=browser-viewer-
|
|
14
|
+
//# sourceMappingURL=browser-viewer-MN7MOYQT.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
isSourcePlacementChangedError,
|
|
5
5
|
useInteractionInterventions,
|
|
6
6
|
useInteractionInvalidation
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-TV5PP2PE.js";
|
|
8
8
|
import {
|
|
9
9
|
DesktopViewer
|
|
10
10
|
} from "./chunk-4MDLEHXL.js";
|
|
@@ -17,9 +17,6 @@ import {
|
|
|
17
17
|
encodeStreamClose,
|
|
18
18
|
encodeStreamOpen
|
|
19
19
|
} from "./chunk-5YK2ZDIG.js";
|
|
20
|
-
import {
|
|
21
|
-
copyTextToClipboard
|
|
22
|
-
} from "./chunk-JVYQRRC4.js";
|
|
23
20
|
import {
|
|
24
21
|
usePageLiveActivity
|
|
25
22
|
} from "./chunk-KZ73RL76.js";
|
|
@@ -29,6 +26,9 @@ import {
|
|
|
29
26
|
import {
|
|
30
27
|
cn
|
|
31
28
|
} from "./chunk-22KP6LR5.js";
|
|
29
|
+
import {
|
|
30
|
+
copyTextToClipboard
|
|
31
|
+
} from "./chunk-JVYQRRC4.js";
|
|
32
32
|
|
|
33
33
|
// src/components/computer-viewer.tsx
|
|
34
34
|
import { interactionControlFailureFromError } from "@opengeni/sdk/interaction";
|
|
@@ -2325,10 +2325,10 @@ function computerConnectionLabel(state) {
|
|
|
2325
2325
|
}
|
|
2326
2326
|
|
|
2327
2327
|
export {
|
|
2328
|
-
useComputerFrameStream,
|
|
2329
|
-
useComputerSession,
|
|
2330
2328
|
useComputerSessions,
|
|
2329
|
+
useComputerSession,
|
|
2330
|
+
useComputerFrameStream,
|
|
2331
2331
|
ComputerViewer,
|
|
2332
2332
|
computerKey
|
|
2333
2333
|
};
|
|
2334
|
-
//# sourceMappingURL=chunk-
|
|
2334
|
+
//# sourceMappingURL=chunk-2O2HXRGP.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
usePortalTokenSource,
|
|
3
|
-
usePortalTokenStyle
|
|
4
|
-
} from "./chunk-VZTQ73XT.js";
|
|
5
1
|
import {
|
|
6
2
|
effortOptionsForModel,
|
|
7
3
|
findPickerRow,
|
|
8
4
|
labelReasoningEffort,
|
|
9
5
|
projectClientModelRows
|
|
10
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-IOLPHOF4.js";
|
|
7
|
+
import {
|
|
8
|
+
usePortalTokenSource,
|
|
9
|
+
usePortalTokenStyle
|
|
10
|
+
} from "./chunk-VZTQ73XT.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-
|
|
35
|
+
() => import("./model-policy-picker-menu-AGXXJZ2B.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
|
-
|
|
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
|
|
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-
|
|
301
|
+
//# sourceMappingURL=chunk-3LL47F4U.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":[]}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
shouldSteerOnKey,
|
|
3
|
+
shouldSubmitOnKey
|
|
4
|
+
} from "./chunk-AKOMC3VO.js";
|
|
5
|
+
import {
|
|
6
|
+
groupPickerRowsByBillingClass
|
|
7
|
+
} from "./chunk-IOLPHOF4.js";
|
|
1
8
|
import {
|
|
2
9
|
Tooltip,
|
|
3
10
|
TooltipContent,
|
|
@@ -8,18 +15,11 @@ import {
|
|
|
8
15
|
import {
|
|
9
16
|
ComposerResponsiveContext
|
|
10
17
|
} from "./chunk-VZTQ73XT.js";
|
|
11
|
-
import {
|
|
12
|
-
shouldSteerOnKey,
|
|
13
|
-
shouldSubmitOnKey
|
|
14
|
-
} from "./chunk-AKOMC3VO.js";
|
|
15
18
|
import {
|
|
16
19
|
composerSubmissionErrorMessage,
|
|
17
20
|
formatBytes,
|
|
18
21
|
formatRelativeTime
|
|
19
22
|
} from "./chunk-PLYRL5ER.js";
|
|
20
|
-
import {
|
|
21
|
-
groupPickerRowsByBillingClass
|
|
22
|
-
} from "./chunk-5GAL23FF.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-
|
|
4669
|
+
//# sourceMappingURL=chunk-4ACTWOOW.js.map
|
|
@@ -159,10 +159,7 @@ function organizationProviderPayerSummary(model) {
|
|
|
159
159
|
return "Billed to the organization provider account";
|
|
160
160
|
}
|
|
161
161
|
function projectPickerRows(models) {
|
|
162
|
-
return models.filter((catalog) => {
|
|
163
|
-
const billingClass = billingClassForModel(catalog);
|
|
164
|
-
return billingClass === "opengeni_credits" || catalog.credentialReadiness.status === "ready";
|
|
165
|
-
}).map((catalog) => {
|
|
162
|
+
return models.filter((catalog) => catalog.credentialReadiness.status === "ready").map((catalog) => {
|
|
166
163
|
const billingClass = billingClassForModel(catalog);
|
|
167
164
|
return {
|
|
168
165
|
id: catalog.id,
|
|
@@ -246,4 +243,4 @@ export {
|
|
|
246
243
|
findPickerRow,
|
|
247
244
|
groupPickerRowsByBillingClass
|
|
248
245
|
};
|
|
249
|
-
//# sourceMappingURL=chunk-
|
|
246
|
+
//# sourceMappingURL=chunk-IOLPHOF4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/model-policy.ts"],"sourcesContent":["import {\n compareModelPickerOrder,\n modelPickerBillingClassFor,\n type ModelPickerBillingClass,\n} from \"@opengeni/sdk/model-picker-order\";\nimport type { ClientModel, ReasoningEffort, WorkspaceModelCatalogModel } from \"@opengeni/sdk\";\n\nexport type PickerBillingClass = ModelPickerBillingClass;\n\nexport type PickerModelRow<TCatalog extends ClientModel = WorkspaceModelCatalogModel> = {\n id: string;\n label: string;\n /** Catalog-curated compact label for dense UI; fall back to `label` when absent. */\n shortLabel?: string | undefined;\n billingClass: PickerBillingClass;\n billingClassLabel: string;\n selectable: boolean;\n unavailableReason: string | null;\n provider: string;\n providerLabel: string;\n catalog: TCatalog;\n};\n\nexport type LatencyModeId = \"standard\" | \"priority\" | \"fast\";\n\nconst BILLING_CLASS_LABELS: Record<PickerBillingClass, string> = {\n opengeni_credits: \"OpenGeni\",\n external: \"External\",\n codex_subscription: \"Codex\",\n supergrok_subscription: \"SuperGrok\",\n byok: \"Workspace providers\",\n organization_byok: \"Organization providers\",\n};\n\nconst AVAILABILITY_REASON_LABELS: Record<string, string> = {\n missing_credential: \"Credentials required\",\n needs_reauth: \"Reconnect required\",\n credential_not_ready: \"Credential not ready\",\n not_entitled: \"Not entitled\",\n provider_unhealthy: \"Provider unavailable\",\n policy_blocked: \"Blocked by workspace policy\",\n unsupported: \"Unsupported\",\n};\n\nexport function billingClassForModel(model: ClientModel): PickerBillingClass {\n if (model.provider === \"organization-gateway\" || model.provider === \"organization-openrouter\") {\n return \"organization_byok\";\n }\n if (model.provider === \"workspace-gateway\" || model.provider === \"workspace-openrouter\") {\n return \"byok\";\n }\n return modelPickerBillingClassFor(model);\n}\n\nexport function billingClassLabel(billingClass: PickerBillingClass): string {\n return BILLING_CLASS_LABELS[billingClass];\n}\n\nexport function availabilityReasonLabel(\n reason: WorkspaceModelCatalogModel[\"availability\"][\"reason\"],\n): string | null {\n if (!reason) {\n return null;\n }\n return AVAILABILITY_REASON_LABELS[reason] ?? \"Unavailable\";\n}\n\nexport function effortOptionsForModel(model: ClientModel): ReasoningEffort[] {\n const efforts = model.capabilities?.reasoning.efforts;\n if (!efforts || efforts.length === 0) {\n return [\"low\"];\n }\n const order: ReasoningEffort[] = [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\n return order.filter((effort) => efforts.includes(effort));\n}\n\nexport function defaultEffortForModel(model: ClientModel): ReasoningEffort {\n const options = effortOptionsForModel(model);\n const configured = model.capabilities?.reasoning.defaultEffort;\n if (configured && options.includes(configured)) {\n return configured;\n }\n return options[0] ?? \"low\";\n}\n\nexport function coerceReasoningEffortForModel(\n model: ClientModel,\n effort: ReasoningEffort,\n): ReasoningEffort {\n const options = effortOptionsForModel(model);\n if (options.includes(effort)) {\n return effort;\n }\n return defaultEffortForModel(model);\n}\n\nexport function runnableLatencyModesForModel(model: ClientModel): LatencyModeId[] {\n const modes = model.capabilities?.latencyModes ?? [];\n return modes.filter((mode) => mode.runnable).map((mode) => mode.id);\n}\n\nexport function labelLatencyMode(mode: LatencyModeId): string {\n if (mode === \"fast\") {\n return \"Fast\";\n }\n if (mode === \"priority\") {\n return \"Priority\";\n }\n return \"Standard\";\n}\n\nexport function labelReasoningEffort(effort: ReasoningEffort): string {\n if (effort === \"xhigh\") {\n return \"Extra high\";\n }\n return effort.slice(0, 1).toUpperCase() + effort.slice(1);\n}\n\n/** Payment prompts must use cost policy, never the presentation group. */\nexport function modelUsesCredits(model: ClientModel | undefined): boolean {\n if (model?.cost !== undefined) return model.cost === \"credits\";\n return model?.billing?.metering === \"opengeni_credits\";\n}\n\nexport function payerSummaryForModel(model: ClientModel): string {\n if (model.cost === \"free\") {\n return \"Free in this deployment\";\n }\n if (model.cost === \"credits\") {\n return \"OpenGeni credits\";\n }\n if (model.cost === \"subscription\") {\n return model.source === \"supergrok\"\n ? \"SuperGrok subscription · external billing\"\n : \"Codex subscription · external billing\";\n }\n if (model.cost === \"workspace\") {\n return workspaceProviderPayerSummary(model);\n }\n if (model.cost === \"organization\") {\n return organizationProviderPayerSummary(model);\n }\n\n // Older client-config payloads do not carry `cost`; preserve their existing\n // settlement-derived label until every deployment has rolled forward.\n const billing = model.billing;\n if (!billing) {\n return \"Route unknown\";\n }\n if (billing.metering === \"opengeni_credits\") {\n return \"OpenGeni credits · automatic managed route\";\n }\n if (billing.upstreamPayer === \"connected_subscription\") {\n return model.source === \"supergrok\"\n ? \"SuperGrok subscription · external billing\"\n : \"Codex subscription · external billing\";\n }\n if (billing.upstreamPayer === \"workspace\") {\n return workspaceProviderPayerSummary(model);\n }\n if (billing.upstreamPayer === \"organization\") {\n return organizationProviderPayerSummary(model);\n }\n return billing.upstreamPayer === \"deployment\"\n ? \"OpenGeni · no model credits\"\n : \"External provider · no OpenGeni credits\";\n}\n\nexport function advancedSourceSummary(model: ClientModel): string | null {\n const source = model.credentialSource;\n if (!source) {\n return model.billing?.metering === \"external\" && model.billing.upstreamPayer === \"deployment\"\n ? \"Deployment-provided connection\"\n : null;\n }\n if (source.kind === \"connected_subscription\") {\n return source.provider === \"xai\"\n ? \"Connected SuperGrok subscription\"\n : \"Connected Codex subscription\";\n }\n if (source.kind === \"workspace_connection\") {\n if (model.provider === \"workspace-openrouter\") {\n return \"Workspace OpenRouter connection\";\n }\n if (model.provider === \"workspace-gateway\" || model.source === \"workspace_gateway\") {\n return \"Workspace Vercel AI Gateway\";\n }\n return \"Workspace provider connection\";\n }\n if (source.kind === \"deployment\") {\n return source.mechanism === \"azure_ad_bearer\"\n ? \"Deployment Azure identity\"\n : \"Deployment API key\";\n }\n return null;\n}\n\nfunction workspaceProviderPayerSummary(model: ClientModel): string {\n if (model.provider === \"workspace-openrouter\") {\n return \"Billed to the workspace OpenRouter account\";\n }\n if (model.provider === \"workspace-gateway\" || model.source === \"workspace_gateway\") {\n return \"Billed to the workspace Vercel account\";\n }\n return \"Billed to the workspace provider account\";\n}\n\nfunction organizationProviderPayerSummary(model: ClientModel): string {\n if (model.provider === \"organization-openrouter\") {\n return \"Billed to the organization OpenRouter account\";\n }\n if (model.provider === \"organization-gateway\") {\n return \"Billed to the organization Vercel account\";\n }\n return \"Billed to the organization provider account\";\n}\n\nexport function projectPickerRows(models: WorkspaceModelCatalogModel[]): PickerModelRow[] {\n return models\n .filter((catalog) => catalog.credentialReadiness.status === \"ready\")\n .map((catalog) => {\n const billingClass = billingClassForModel(catalog);\n return {\n id: catalog.id,\n label: catalog.label,\n ...(catalog.shortLabel ? { shortLabel: catalog.shortLabel } : {}),\n billingClass,\n billingClassLabel: billingClassLabel(billingClass),\n selectable: catalog.availability.selectable,\n unavailableReason: catalog.availability.selectable\n ? null\n : availabilityReasonLabel(catalog.availability.reason),\n provider: catalog.provider,\n providerLabel: catalog.providerLabel,\n catalog,\n };\n });\n}\n\n/** Project the lightweight client-config model list into the same picker contract. */\nexport function projectClientModelRows(models: ClientModel[]): PickerModelRow<ClientModel>[] {\n return models.map((catalog) => {\n const billingClass = billingClassForModel(catalog);\n return {\n id: catalog.id,\n label: catalog.label,\n ...(catalog.shortLabel ? { shortLabel: catalog.shortLabel } : {}),\n billingClass,\n billingClassLabel: billingClassLabel(billingClass),\n selectable: true,\n unavailableReason: null,\n provider: catalog.provider,\n providerLabel: catalog.providerLabel,\n catalog,\n };\n });\n}\n\nexport function sortPickerRows<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n): PickerModelRow<TCatalog>[] {\n return [...rows].sort(compareModelPickerOrder);\n}\n\nexport function findPickerRow<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n modelId: string,\n): PickerModelRow<TCatalog> | null {\n return rows.find((row) => row.id === modelId) ?? null;\n}\n\nexport function groupPickerRowsByBillingClass(\n rows: PickerModelRow[],\n options?: { codexOnly?: boolean },\n): Array<{ billingClass: PickerBillingClass; label: string; rows: PickerModelRow[] }>;\nexport function groupPickerRowsByBillingClass<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n options?: { codexOnly?: boolean },\n): Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n}>;\nexport function groupPickerRowsByBillingClass<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n options?: { codexOnly?: boolean },\n): Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n}> {\n const sorted = sortPickerRows(rows);\n const groups: Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n }> = [];\n for (const row of sorted) {\n const existing = groups.find((group) => group.billingClass === row.billingClass);\n if (existing) {\n existing.rows.push(row);\n continue;\n }\n groups.push({\n billingClass: row.billingClass,\n label: row.billingClassLabel,\n rows: [row],\n });\n }\n const codexIndex = groups.findIndex((group) => group.billingClass === \"codex_subscription\");\n const codex = groups[codexIndex];\n const selectableOpenGeni = groups\n .find((group) => group.billingClass === \"opengeni_credits\")\n ?.rows.filter((row) => row.selectable);\n // Presentation only: never change the catalog/default model ordering or selection.\n const onlyFreeOpenGeni =\n selectableOpenGeni !== undefined &&\n selectableOpenGeni.length > 0 &&\n selectableOpenGeni.every((row) => row.catalog.cost === \"free\");\n if (\n codex &&\n codex.rows.some((row) => row.selectable) &&\n (options?.codexOnly || onlyFreeOpenGeni)\n ) {\n groups.splice(codexIndex, 1);\n groups.unshift(codex);\n }\n return groups;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
useMutationRunner,
|
|
3
3
|
usePageLiveActivity
|
|
4
4
|
} from "./chunk-KZ73RL76.js";
|
|
5
|
+
import {
|
|
6
|
+
useOpenGeni
|
|
7
|
+
} from "./chunk-NEXLLTP4.js";
|
|
5
8
|
import {
|
|
6
9
|
formatBytes,
|
|
7
10
|
formatRelativeTime
|
|
8
11
|
} from "./chunk-PLYRL5ER.js";
|
|
9
|
-
import {
|
|
10
|
-
useOpenGeni
|
|
11
|
-
} from "./chunk-NEXLLTP4.js";
|
|
12
12
|
import {
|
|
13
13
|
cn
|
|
14
14
|
} from "./chunk-22KP6LR5.js";
|
|
@@ -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.
|
|
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(
|
|
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.
|
|
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 (
|
|
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(
|
|
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-
|
|
2450
|
+
//# sourceMappingURL=chunk-PFDNB3U7.js.map
|