@opengeni/react 3.3.2 → 3.5.1-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/artifacts.js +12 -12
- package/dist/{browser-viewer-MKKFRRRV.js → browser-viewer-E5DDEFQ4.js} +3 -3
- package/dist/{chunk-2DZVYHVO.js → chunk-4JFUT22W.js} +39 -13
- package/dist/chunk-4JFUT22W.js.map +1 -0
- package/dist/{chunk-ELIYWBZR.js → chunk-BV5A4OTE.js} +4 -4
- package/dist/{chunk-3AGBGTRT.js → chunk-IB27C53Y.js} +130 -16
- package/dist/chunk-IB27C53Y.js.map +1 -0
- package/dist/{chunk-JAQ5K7W6.js → chunk-TJFMMDQU.js} +56 -53
- package/dist/chunk-TJFMMDQU.js.map +1 -0
- package/dist/{chunk-XYRDDSXF.js → chunk-UNCXXIQR.js} +16 -12
- package/dist/{chunk-XYRDDSXF.js.map → chunk-UNCXXIQR.js.map} +1 -1
- package/dist/{chunk-ZPBTI3TE.js → chunk-W2RGYBCV.js} +4 -4
- package/dist/{chunk-WSK7G5LE.js → chunk-W3OUAH6M.js} +80 -80
- package/dist/chunk-W3OUAH6M.js.map +1 -0
- package/dist/{chunk-X4A66EWZ.js → chunk-WMGF4Z7X.js} +41 -43
- package/dist/chunk-WMGF4Z7X.js.map +1 -0
- package/dist/{chunk-YG4QEQF5.js → chunk-WY3MELVJ.js} +7769 -7753
- package/dist/chunk-WY3MELVJ.js.map +1 -0
- package/dist/composer.js +4 -4
- package/dist/{computer-viewer-FWEZISW4.js → computer-viewer-7TEZC6Y2.js} +3 -3
- package/dist/hooks/use-file-attachments.d.ts +2 -0
- package/dist/hooks/use-session-events.d.ts +1 -1
- package/dist/index.js +85 -87
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +3 -3
- package/dist/model-policy.d.ts +2 -1
- package/dist/model-policy.js +1 -1
- package/dist/{queue-surface-implementation-BSKUWHRI.js → queue-surface-implementation-XL2A6PBM.js} +2 -2
- package/dist/realtime.js +2 -2
- package/dist/session-ui.js +6 -6
- package/dist/session.js +4 -4
- package/dist/timeline/types.d.ts +2 -0
- package/package.json +2 -2
- package/src/components/composer.tsx +15 -5
- package/src/components/message-timeline.tsx +16 -2
- package/src/components/model-policy-picker.tsx +37 -10
- package/src/components/sandbox-workspace.tsx +7 -6
- package/src/hooks/use-file-attachments.ts +28 -2
- package/src/hooks/use-session-events.ts +168 -8
- package/src/model-policy.ts +48 -53
- package/src/timeline/projection.ts +6 -1
- package/src/timeline/types.ts +2 -0
- package/styles/compiled.css +5 -0
- package/dist/chunk-2DZVYHVO.js.map +0 -1
- package/dist/chunk-3AGBGTRT.js.map +0 -1
- package/dist/chunk-JAQ5K7W6.js.map +0 -1
- package/dist/chunk-WSK7G5LE.js.map +0 -1
- package/dist/chunk-X4A66EWZ.js.map +0 -1
- package/dist/chunk-YG4QEQF5.js.map +0 -1
- /package/dist/{browser-viewer-MKKFRRRV.js.map → browser-viewer-E5DDEFQ4.js.map} +0 -0
- /package/dist/{chunk-ELIYWBZR.js.map → chunk-BV5A4OTE.js.map} +0 -0
- /package/dist/{chunk-ZPBTI3TE.js.map → chunk-W2RGYBCV.js.map} +0 -0
- /package/dist/{computer-viewer-FWEZISW4.js.map → computer-viewer-7TEZC6Y2.js.map} +0 -0
- /package/dist/{queue-surface-implementation-BSKUWHRI.js.map → queue-surface-implementation-XL2A6PBM.js.map} +0 -0
|
@@ -15,15 +15,15 @@ import {
|
|
|
15
15
|
encodeStreamOpen,
|
|
16
16
|
interactionHostPlatform
|
|
17
17
|
} from "./chunk-5YK2ZDIG.js";
|
|
18
|
+
import {
|
|
19
|
+
copyTextToClipboard
|
|
20
|
+
} from "./chunk-JVYQRRC4.js";
|
|
18
21
|
import {
|
|
19
22
|
usePageLiveActivity
|
|
20
23
|
} from "./chunk-KZ73RL76.js";
|
|
21
24
|
import {
|
|
22
25
|
useEmbeddedBrowserInteraction
|
|
23
26
|
} from "./chunk-NEXLLTP4.js";
|
|
24
|
-
import {
|
|
25
|
-
copyTextToClipboard
|
|
26
|
-
} from "./chunk-JVYQRRC4.js";
|
|
27
27
|
import {
|
|
28
28
|
formatBytes
|
|
29
29
|
} from "./chunk-VTOREEXF.js";
|
|
@@ -3904,4 +3904,4 @@ export {
|
|
|
3904
3904
|
useSiteAuthConnections,
|
|
3905
3905
|
BrowserViewer
|
|
3906
3906
|
};
|
|
3907
|
-
//# sourceMappingURL=chunk-
|
|
3907
|
+
//# sourceMappingURL=chunk-W2RGYBCV.js.map
|
|
@@ -2,6 +2,69 @@ import {
|
|
|
2
2
|
cn
|
|
3
3
|
} from "./chunk-22KP6LR5.js";
|
|
4
4
|
|
|
5
|
+
// src/components/timeline-annotations.tsx
|
|
6
|
+
import { Suspense, lazy, useRef, useState } from "react";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var TimelineAnnotationsDialog = lazy(() => import("./timeline-annotations-dialog-U7EVLR75.js"));
|
|
9
|
+
function TimelineAnnotationsChip({
|
|
10
|
+
annotations,
|
|
11
|
+
editable = false,
|
|
12
|
+
focusAnnotationId,
|
|
13
|
+
onFocusConsumed,
|
|
14
|
+
onUpdate,
|
|
15
|
+
onRemove,
|
|
16
|
+
onRevealSource,
|
|
17
|
+
className
|
|
18
|
+
}) {
|
|
19
|
+
const [open, setOpen] = useState(false);
|
|
20
|
+
const triggerRef = useRef(null);
|
|
21
|
+
if (annotations.length === 0) return null;
|
|
22
|
+
const focusRequested = Boolean(
|
|
23
|
+
focusAnnotationId && annotations.some((item) => item.id === focusAnnotationId)
|
|
24
|
+
);
|
|
25
|
+
const visible = open || focusRequested;
|
|
26
|
+
const countLabel = `${annotations.length} ${annotations.length === 1 ? "annotation" : "annotations"}`;
|
|
27
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
28
|
+
/* @__PURE__ */ jsx(
|
|
29
|
+
"button",
|
|
30
|
+
{
|
|
31
|
+
ref: triggerRef,
|
|
32
|
+
type: "button",
|
|
33
|
+
className: cn(
|
|
34
|
+
"inline-flex min-h-8 items-center gap-1.5 rounded-full border border-og-border bg-og-surface-1 px-2.5 py-1 text-og-sm font-medium text-og-fg-muted outline-hidden transition hover:bg-og-surface-2 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-[44px]",
|
|
35
|
+
className
|
|
36
|
+
),
|
|
37
|
+
"aria-label": `Review ${countLabel}`,
|
|
38
|
+
"aria-haspopup": "dialog",
|
|
39
|
+
"aria-expanded": visible,
|
|
40
|
+
onClick: () => setOpen((current) => !current),
|
|
41
|
+
children: countLabel
|
|
42
|
+
}
|
|
43
|
+
),
|
|
44
|
+
visible ? /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
|
|
45
|
+
TimelineAnnotationsDialog,
|
|
46
|
+
{
|
|
47
|
+
annotations,
|
|
48
|
+
editable,
|
|
49
|
+
focusAnnotationId,
|
|
50
|
+
onFocusConsumed: () => {
|
|
51
|
+
setOpen(true);
|
|
52
|
+
onFocusConsumed?.();
|
|
53
|
+
},
|
|
54
|
+
onUpdate,
|
|
55
|
+
onRemove,
|
|
56
|
+
onRevealSource,
|
|
57
|
+
triggerRef,
|
|
58
|
+
countLabel,
|
|
59
|
+
onDismiss: (restoreFocus) => {
|
|
60
|
+
setOpen(false);
|
|
61
|
+
if (restoreFocus) triggerRef.current?.focus();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
) }) : null
|
|
65
|
+
] });
|
|
66
|
+
}
|
|
67
|
+
|
|
5
68
|
// src/components/queue-draft-policy.ts
|
|
6
69
|
function requestQueueDraftEdit(composer, confirmReplacement, editImmediately) {
|
|
7
70
|
if (composer.hasDraftContent()) {
|
|
@@ -13,17 +76,17 @@ function requestQueueDraftEdit(composer, confirmReplacement, editImmediately) {
|
|
|
13
76
|
|
|
14
77
|
// src/components/queue-surface-state.tsx
|
|
15
78
|
import { Loader2Icon, RotateCwIcon } from "lucide-react";
|
|
16
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
79
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
17
80
|
function EmptyQueueStateSurface({ queue }) {
|
|
18
81
|
const hasError = Boolean(queue.error || queue.mutationError);
|
|
19
|
-
return /* @__PURE__ */
|
|
82
|
+
return /* @__PURE__ */ jsx2(
|
|
20
83
|
"div",
|
|
21
84
|
{
|
|
22
85
|
className: "og-root mx-auto mb-2 w-full max-w-3xl shrink-0 px-4 sm:px-6",
|
|
23
86
|
"data-testid": "queue-surface",
|
|
24
|
-
children: /* @__PURE__ */
|
|
25
|
-
queue.stoppingPreviousAttempt ? /* @__PURE__ */
|
|
26
|
-
hasError ? /* @__PURE__ */
|
|
87
|
+
children: /* @__PURE__ */ jsxs2("div", { className: "overflow-hidden rounded-lg border border-border bg-surface/80 shadow-sm", children: [
|
|
88
|
+
queue.stoppingPreviousAttempt ? /* @__PURE__ */ jsx2(QueueStoppingStatus, { queue, dividerAfter: hasError }) : null,
|
|
89
|
+
hasError ? /* @__PURE__ */ jsx2(QueueErrorAlert, { queue }) : null
|
|
27
90
|
] })
|
|
28
91
|
}
|
|
29
92
|
);
|
|
@@ -32,7 +95,7 @@ function QueueStoppingStatus({
|
|
|
32
95
|
queue,
|
|
33
96
|
dividerAfter = false
|
|
34
97
|
}) {
|
|
35
|
-
return /* @__PURE__ */
|
|
98
|
+
return /* @__PURE__ */ jsxs2(
|
|
36
99
|
"div",
|
|
37
100
|
{
|
|
38
101
|
role: "status",
|
|
@@ -40,17 +103,17 @@ function QueueStoppingStatus({
|
|
|
40
103
|
className: `flex min-h-11 items-center gap-2.5 bg-status-waiting/[0.07] px-3 py-2 text-og-control text-fg ${dividerAfter ? "border-b border-status-waiting/20" : ""}`,
|
|
41
104
|
"data-testid": "stopping-previous-attempt",
|
|
42
105
|
children: [
|
|
43
|
-
/* @__PURE__ */
|
|
106
|
+
/* @__PURE__ */ jsx2(
|
|
44
107
|
Loader2Icon,
|
|
45
108
|
{
|
|
46
109
|
"aria-hidden": "true",
|
|
47
110
|
className: "size-3.5 shrink-0 animate-spin text-status-waiting motion-reduce:animate-none"
|
|
48
111
|
}
|
|
49
112
|
),
|
|
50
|
-
/* @__PURE__ */
|
|
51
|
-
/* @__PURE__ */
|
|
113
|
+
/* @__PURE__ */ jsxs2("span", { className: "min-w-0", children: [
|
|
114
|
+
/* @__PURE__ */ jsx2("span", { className: "font-medium", children: queue.effectiveControl?.state === "paused" ? "Stopping current attempt\u2026" : "Stopping previous attempt\u2026" }),
|
|
52
115
|
" ",
|
|
53
|
-
/* @__PURE__ */
|
|
116
|
+
/* @__PURE__ */ jsx2("span", { className: "text-fg-muted", children: queue.effectiveControl?.state === "paused" ? "Queued work stays saved until you resume." : "Queued work is saved and starts automatically." })
|
|
54
117
|
] })
|
|
55
118
|
]
|
|
56
119
|
}
|
|
@@ -60,13 +123,13 @@ function QueueErrorAlert({
|
|
|
60
123
|
queue,
|
|
61
124
|
dividerBefore = false
|
|
62
125
|
}) {
|
|
63
|
-
return /* @__PURE__ */
|
|
126
|
+
return /* @__PURE__ */ jsx2("div", { className: `${dividerBefore ? "border-t border-border" : ""} p-2`, children: /* @__PURE__ */ jsxs2(
|
|
64
127
|
"div",
|
|
65
128
|
{
|
|
66
129
|
role: "alert",
|
|
67
130
|
className: "flex min-w-0 max-w-full flex-wrap items-start gap-2 rounded-md bg-status-failed/10 px-2 py-1.5 text-og-control text-status-failed",
|
|
68
131
|
children: [
|
|
69
|
-
/* @__PURE__ */
|
|
132
|
+
/* @__PURE__ */ jsx2(
|
|
70
133
|
"span",
|
|
71
134
|
{
|
|
72
135
|
role: "region",
|
|
@@ -78,7 +141,7 @@ function QueueErrorAlert({
|
|
|
78
141
|
children: (queue.mutationError ?? queue.error)?.message
|
|
79
142
|
}
|
|
80
143
|
),
|
|
81
|
-
/* @__PURE__ */
|
|
144
|
+
/* @__PURE__ */ jsx2(
|
|
82
145
|
"button",
|
|
83
146
|
{
|
|
84
147
|
type: "button",
|
|
@@ -89,7 +152,7 @@ function QueueErrorAlert({
|
|
|
89
152
|
"aria-label": "Dismiss queue error and retry",
|
|
90
153
|
title: "Retry loading the queue",
|
|
91
154
|
className: "ms-auto inline-flex size-7 shrink-0 items-center justify-center self-start rounded-md outline-hidden transition-colors hover:bg-surface-3 focus-visible:ring-2 focus-visible:ring-ring/40 motion-reduce:transition-none pointer-coarse:size-[44px]",
|
|
92
|
-
children: /* @__PURE__ */
|
|
155
|
+
children: /* @__PURE__ */ jsx2(RotateCwIcon, { className: "size-3.5" })
|
|
93
156
|
}
|
|
94
157
|
)
|
|
95
158
|
]
|
|
@@ -97,74 +160,11 @@ function QueueErrorAlert({
|
|
|
97
160
|
) });
|
|
98
161
|
}
|
|
99
162
|
|
|
100
|
-
// src/components/timeline-annotations.tsx
|
|
101
|
-
import { Suspense, lazy, useRef, useState } from "react";
|
|
102
|
-
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
103
|
-
var TimelineAnnotationsDialog = lazy(() => import("./timeline-annotations-dialog-U7EVLR75.js"));
|
|
104
|
-
function TimelineAnnotationsChip({
|
|
105
|
-
annotations,
|
|
106
|
-
editable = false,
|
|
107
|
-
focusAnnotationId,
|
|
108
|
-
onFocusConsumed,
|
|
109
|
-
onUpdate,
|
|
110
|
-
onRemove,
|
|
111
|
-
onRevealSource,
|
|
112
|
-
className
|
|
113
|
-
}) {
|
|
114
|
-
const [open, setOpen] = useState(false);
|
|
115
|
-
const triggerRef = useRef(null);
|
|
116
|
-
if (annotations.length === 0) return null;
|
|
117
|
-
const focusRequested = Boolean(
|
|
118
|
-
focusAnnotationId && annotations.some((item) => item.id === focusAnnotationId)
|
|
119
|
-
);
|
|
120
|
-
const visible = open || focusRequested;
|
|
121
|
-
const countLabel = `${annotations.length} ${annotations.length === 1 ? "annotation" : "annotations"}`;
|
|
122
|
-
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
123
|
-
/* @__PURE__ */ jsx2(
|
|
124
|
-
"button",
|
|
125
|
-
{
|
|
126
|
-
ref: triggerRef,
|
|
127
|
-
type: "button",
|
|
128
|
-
className: cn(
|
|
129
|
-
"inline-flex min-h-8 items-center gap-1.5 rounded-full border border-og-border bg-og-surface-1 px-2.5 py-1 text-og-sm font-medium text-og-fg-muted outline-hidden transition hover:bg-og-surface-2 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-[44px]",
|
|
130
|
-
className
|
|
131
|
-
),
|
|
132
|
-
"aria-label": `Review ${countLabel}`,
|
|
133
|
-
"aria-haspopup": "dialog",
|
|
134
|
-
"aria-expanded": visible,
|
|
135
|
-
onClick: () => setOpen((current) => !current),
|
|
136
|
-
children: countLabel
|
|
137
|
-
}
|
|
138
|
-
),
|
|
139
|
-
visible ? /* @__PURE__ */ jsx2(Suspense, { fallback: null, children: /* @__PURE__ */ jsx2(
|
|
140
|
-
TimelineAnnotationsDialog,
|
|
141
|
-
{
|
|
142
|
-
annotations,
|
|
143
|
-
editable,
|
|
144
|
-
focusAnnotationId,
|
|
145
|
-
onFocusConsumed: () => {
|
|
146
|
-
setOpen(true);
|
|
147
|
-
onFocusConsumed?.();
|
|
148
|
-
},
|
|
149
|
-
onUpdate,
|
|
150
|
-
onRemove,
|
|
151
|
-
onRevealSource,
|
|
152
|
-
triggerRef,
|
|
153
|
-
countLabel,
|
|
154
|
-
onDismiss: (restoreFocus) => {
|
|
155
|
-
setOpen(false);
|
|
156
|
-
if (restoreFocus) triggerRef.current?.focus();
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
) }) : null
|
|
160
|
-
] });
|
|
161
|
-
}
|
|
162
|
-
|
|
163
163
|
export {
|
|
164
|
+
TimelineAnnotationsChip,
|
|
164
165
|
requestQueueDraftEdit,
|
|
165
166
|
EmptyQueueStateSurface,
|
|
166
167
|
QueueStoppingStatus,
|
|
167
|
-
QueueErrorAlert
|
|
168
|
-
TimelineAnnotationsChip
|
|
168
|
+
QueueErrorAlert
|
|
169
169
|
};
|
|
170
|
-
//# sourceMappingURL=chunk-
|
|
170
|
+
//# sourceMappingURL=chunk-W3OUAH6M.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/timeline-annotations.tsx","../src/components/queue-draft-policy.ts","../src/components/queue-surface-state.tsx"],"sourcesContent":["import type {\n DraftTimelineAnnotation,\n TimelineAnnotation,\n TimelineAnnotationSource,\n} from \"@opengeni/sdk\";\nimport { Suspense, lazy, useRef, useState } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type TimelineAnnotationLike = DraftTimelineAnnotation | TimelineAnnotation;\n\nconst TimelineAnnotationsDialog = lazy(() => import(\"./timeline-annotations-dialog\"));\n\nexport function TimelineAnnotationsChip({\n annotations,\n editable = false,\n focusAnnotationId,\n onFocusConsumed,\n onUpdate,\n onRemove,\n onRevealSource,\n className,\n}: {\n annotations: readonly TimelineAnnotationLike[];\n editable?: boolean | undefined;\n focusAnnotationId?: string | null | undefined;\n onFocusConsumed?: (() => void) | undefined;\n onUpdate?: ((id: string, note: string) => void) | undefined;\n onRemove?: ((id: string) => void) | undefined;\n onRevealSource?: ((source: TimelineAnnotationSource) => boolean) | undefined;\n className?: string | undefined;\n}) {\n const [open, setOpen] = useState(false);\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n\n if (annotations.length === 0) return null;\n const focusRequested = Boolean(\n focusAnnotationId && annotations.some((item) => item.id === focusAnnotationId),\n );\n const visible = open || focusRequested;\n const countLabel = `${annotations.length} ${annotations.length === 1 ? \"annotation\" : \"annotations\"}`;\n\n return (\n <>\n <button\n ref={triggerRef}\n type=\"button\"\n className={cn(\n \"inline-flex min-h-8 items-center gap-1.5 rounded-full border border-og-border bg-og-surface-1 px-2.5 py-1 text-og-sm font-medium text-og-fg-muted outline-hidden transition hover:bg-og-surface-2 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-[44px]\",\n className,\n )}\n aria-label={`Review ${countLabel}`}\n aria-haspopup=\"dialog\"\n aria-expanded={visible}\n onClick={() => setOpen((current) => !current)}\n >\n {countLabel}\n </button>\n {visible ? (\n <Suspense fallback={null}>\n <TimelineAnnotationsDialog\n annotations={annotations}\n editable={editable}\n focusAnnotationId={focusAnnotationId}\n onFocusConsumed={() => {\n setOpen(true);\n onFocusConsumed?.();\n }}\n onUpdate={onUpdate}\n onRemove={onRemove}\n onRevealSource={onRevealSource}\n triggerRef={triggerRef}\n countLabel={countLabel}\n onDismiss={(restoreFocus) => {\n setOpen(false);\n if (restoreFocus) triggerRef.current?.focus();\n }}\n />\n </Suspense>\n ) : null}\n </>\n );\n}\n\nexport default TimelineAnnotationsChip;\n","import type { ComposerState } from \"../hooks/use-composer\";\n\n/**\n * Decide whether checking out a queued prompt would replace current composer\n * content. `hasDraftContent` reads the synchronous draft refs, so this stays\n * correct even when a controlled input update has not rendered yet.\n */\nexport function requestQueueDraftEdit(\n composer: Pick<ComposerState, \"hasDraftContent\">,\n confirmReplacement: () => void,\n editImmediately: () => void,\n): void {\n if (composer.hasDraftContent()) {\n confirmReplacement();\n } else {\n editImmediately();\n }\n}\n","import { Loader2Icon, RotateCwIcon } from \"lucide-react\";\n\nimport type { UseTurnQueueResult } from \"../hooks/use-turn-queue\";\n\ntype QueueStateProps = {\n queue: UseTurnQueueResult;\n};\n\nexport function EmptyQueueStateSurface({ queue }: QueueStateProps) {\n const hasError = Boolean(queue.error || queue.mutationError);\n return (\n <div\n className=\"og-root mx-auto mb-2 w-full max-w-3xl shrink-0 px-4 sm:px-6\"\n data-testid=\"queue-surface\"\n >\n <div className=\"overflow-hidden rounded-lg border border-border bg-surface/80 shadow-sm\">\n {queue.stoppingPreviousAttempt ? (\n <QueueStoppingStatus queue={queue} dividerAfter={hasError} />\n ) : null}\n {hasError ? <QueueErrorAlert queue={queue} /> : null}\n </div>\n </div>\n );\n}\n\nexport function QueueStoppingStatus({\n queue,\n dividerAfter = false,\n}: QueueStateProps & { dividerAfter?: boolean }) {\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className={`flex min-h-11 items-center gap-2.5 bg-status-waiting/[0.07] px-3 py-2 text-og-control text-fg ${\n dividerAfter ? \"border-b border-status-waiting/20\" : \"\"\n }`}\n data-testid=\"stopping-previous-attempt\"\n >\n <Loader2Icon\n aria-hidden=\"true\"\n className=\"size-3.5 shrink-0 animate-spin text-status-waiting motion-reduce:animate-none\"\n />\n <span className=\"min-w-0\">\n <span className=\"font-medium\">\n {queue.effectiveControl?.state === \"paused\"\n ? \"Stopping current attempt…\"\n : \"Stopping previous attempt…\"}\n </span>{\" \"}\n <span className=\"text-fg-muted\">\n {queue.effectiveControl?.state === \"paused\"\n ? \"Queued work stays saved until you resume.\"\n : \"Queued work is saved and starts automatically.\"}\n </span>\n </span>\n </div>\n );\n}\n\nexport function QueueErrorAlert({\n queue,\n dividerBefore = false,\n}: QueueStateProps & { dividerBefore?: boolean }) {\n return (\n <div className={`${dividerBefore ? \"border-t border-border\" : \"\"} p-2`}>\n <div\n role=\"alert\"\n className=\"flex min-w-0 max-w-full flex-wrap items-start gap-2 rounded-md bg-status-failed/10 px-2 py-1.5 text-og-control text-status-failed\"\n >\n <span\n role=\"region\"\n aria-label=\"Queue error details\"\n tabIndex={0}\n className=\"max-h-[min(5rem,20dvh)] min-w-0 max-w-full flex-[1_1_5rem] overflow-auto overscroll-contain whitespace-pre-wrap rounded-sm outline-hidden [overflow-wrap:anywhere] [unicode-bidi:plaintext] focus-visible:ring-2 focus-visible:ring-ring/40\"\n data-testid=\"queue-error-message\"\n dir=\"auto\"\n >\n {(queue.mutationError ?? queue.error)?.message}\n </span>\n <button\n type=\"button\"\n onClick={() => {\n queue.clearMutationError();\n void queue.refresh();\n }}\n aria-label=\"Dismiss queue error and retry\"\n title=\"Retry loading the queue\"\n className=\"ms-auto inline-flex size-7 shrink-0 items-center justify-center self-start rounded-md outline-hidden transition-colors hover:bg-surface-3 focus-visible:ring-2 focus-visible:ring-ring/40 motion-reduce:transition-none pointer-coarse:size-[44px]\"\n >\n <RotateCwIcon className=\"size-3.5\" />\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAKA,SAAS,UAAU,MAAM,QAAQ,gBAAgB;AAqC7C,mBACE,KADF;AAhCJ,IAAM,4BAA4B,KAAK,MAAM,OAAO,2CAA+B,CAAC;AAE7E,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GASG;AACD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,aAAa,OAAiC,IAAI;AAExD,MAAI,YAAY,WAAW,EAAG,QAAO;AACrC,QAAM,iBAAiB;AAAA,IACrB,qBAAqB,YAAY,KAAK,CAAC,SAAS,KAAK,OAAO,iBAAiB;AAAA,EAC/E;AACA,QAAM,UAAU,QAAQ;AACxB,QAAM,aAAa,GAAG,YAAY,MAAM,IAAI,YAAY,WAAW,IAAI,eAAe,aAAa;AAEnG,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAK;AAAA,QACL,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QACA,cAAY,UAAU,UAAU;AAAA,QAChC,iBAAc;AAAA,QACd,iBAAe;AAAA,QACf,SAAS,MAAM,QAAQ,CAAC,YAAY,CAAC,OAAO;AAAA,QAE3C;AAAA;AAAA,IACH;AAAA,IACC,UACC,oBAAC,YAAS,UAAU,MAClB;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA,iBAAiB,MAAM;AACrB,kBAAQ,IAAI;AACZ,4BAAkB;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW,CAAC,iBAAiB;AAC3B,kBAAQ,KAAK;AACb,cAAI,aAAc,YAAW,SAAS,MAAM;AAAA,QAC9C;AAAA;AAAA,IACF,GACF,IACE;AAAA,KACN;AAEJ;;;AC1EO,SAAS,sBACd,UACA,oBACA,iBACM;AACN,MAAI,SAAS,gBAAgB,GAAG;AAC9B,uBAAmB;AAAA,EACrB,OAAO;AACL,oBAAgB;AAAA,EAClB;AACF;;;ACjBA,SAAS,aAAa,oBAAoB;AAepC,SAEI,OAAAA,MAFJ,QAAAC,aAAA;AAPC,SAAS,uBAAuB,EAAE,MAAM,GAAoB;AACjE,QAAM,WAAW,QAAQ,MAAM,SAAS,MAAM,aAAa;AAC3D,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,eAAY;AAAA,MAEZ,0BAAAC,MAAC,SAAI,WAAU,2EACZ;AAAA,cAAM,0BACL,gBAAAD,KAAC,uBAAoB,OAAc,cAAc,UAAU,IACzD;AAAA,QACH,WAAW,gBAAAA,KAAC,mBAAgB,OAAc,IAAK;AAAA,SAClD;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA,eAAe;AACjB,GAAiD;AAC/C,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,aAAU;AAAA,MACV,WAAW,iGACT,eAAe,sCAAsC,EACvD;AAAA,MACA,eAAY;AAAA,MAEZ;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,eAAY;AAAA,YACZ,WAAU;AAAA;AAAA,QACZ;AAAA,QACA,gBAAAC,MAAC,UAAK,WAAU,WACd;AAAA,0BAAAD,KAAC,UAAK,WAAU,eACb,gBAAM,kBAAkB,UAAU,WAC/B,mCACA,mCACN;AAAA,UAAQ;AAAA,UACR,gBAAAA,KAAC,UAAK,WAAU,iBACb,gBAAM,kBAAkB,UAAU,WAC/B,8CACA,kDACN;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA,gBAAgB;AAClB,GAAkD;AAChD,SACE,gBAAAA,KAAC,SAAI,WAAW,GAAG,gBAAgB,2BAA2B,EAAE,QAC9D,0BAAAC;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAU;AAAA,MAEV;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,cAAW;AAAA,YACX,UAAU;AAAA,YACV,WAAU;AAAA,YACV,eAAY;AAAA,YACZ,KAAI;AAAA,YAEF,iBAAM,iBAAiB,MAAM,QAAQ;AAAA;AAAA,QACzC;AAAA,QACA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAM;AACb,oBAAM,mBAAmB;AACzB,mBAAK,MAAM,QAAQ;AAAA,YACrB;AAAA,YACA,cAAW;AAAA,YACX,OAAM;AAAA,YACN,WAAU;AAAA,YAEV,0BAAAA,KAAC,gBAAa,WAAU,YAAW;AAAA;AAAA,QACrC;AAAA;AAAA;AAAA,EACF,GACF;AAEJ;","names":["jsx","jsxs"]}
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
// src/model-policy.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"supergrok_subscription",
|
|
7
|
-
"byok"
|
|
8
|
-
];
|
|
2
|
+
import {
|
|
3
|
+
compareModelPickerOrder,
|
|
4
|
+
modelPickerBillingClassFor
|
|
5
|
+
} from "@opengeni/sdk/model-picker-order";
|
|
9
6
|
var BILLING_CLASS_LABELS = {
|
|
10
7
|
opengeni_credits: "OpenGeni",
|
|
11
8
|
external: "External",
|
|
12
9
|
codex_subscription: "Codex",
|
|
13
10
|
supergrok_subscription: "SuperGrok",
|
|
14
|
-
byok: "
|
|
11
|
+
byok: "Workspace providers",
|
|
12
|
+
organization_byok: "Organization providers"
|
|
15
13
|
};
|
|
16
14
|
var AVAILABILITY_REASON_LABELS = {
|
|
17
15
|
missing_credential: "Credentials required",
|
|
@@ -23,31 +21,13 @@ var AVAILABILITY_REASON_LABELS = {
|
|
|
23
21
|
unsupported: "Unsupported"
|
|
24
22
|
};
|
|
25
23
|
function billingClassForModel(model) {
|
|
26
|
-
if (model.
|
|
27
|
-
return "
|
|
24
|
+
if (model.provider === "organization-gateway" || model.provider === "organization-openrouter") {
|
|
25
|
+
return "organization_byok";
|
|
28
26
|
}
|
|
29
|
-
if (model.
|
|
30
|
-
return "supergrok_subscription";
|
|
31
|
-
}
|
|
32
|
-
if (model.source === "codex") {
|
|
33
|
-
return "codex_subscription";
|
|
34
|
-
}
|
|
35
|
-
if (model.source === "workspace_gateway") {
|
|
36
|
-
return "byok";
|
|
37
|
-
}
|
|
38
|
-
if (model.credentialSource?.kind === "connected_subscription") {
|
|
39
|
-
return model.credentialSource.provider === "xai" ? "supergrok_subscription" : "codex_subscription";
|
|
40
|
-
}
|
|
41
|
-
if (model.credentialSource?.kind === "workspace_connection") {
|
|
27
|
+
if (model.provider === "workspace-gateway" || model.provider === "workspace-openrouter") {
|
|
42
28
|
return "byok";
|
|
43
29
|
}
|
|
44
|
-
|
|
45
|
-
return "codex_subscription";
|
|
46
|
-
}
|
|
47
|
-
if (model.billing?.upstreamPayer === "workspace") {
|
|
48
|
-
return "byok";
|
|
49
|
-
}
|
|
50
|
-
return "opengeni_credits";
|
|
30
|
+
return modelPickerBillingClassFor(model);
|
|
51
31
|
}
|
|
52
32
|
function billingClassLabel(billingClass) {
|
|
53
33
|
return BILLING_CLASS_LABELS[billingClass];
|
|
@@ -101,6 +81,18 @@ function labelReasoningEffort(effort) {
|
|
|
101
81
|
return effort.slice(0, 1).toUpperCase() + effort.slice(1);
|
|
102
82
|
}
|
|
103
83
|
function payerSummaryForModel(model) {
|
|
84
|
+
if (model.cost === "free") {
|
|
85
|
+
return "Free in this deployment";
|
|
86
|
+
}
|
|
87
|
+
if (model.cost === "credits") {
|
|
88
|
+
return "OpenGeni credits";
|
|
89
|
+
}
|
|
90
|
+
if (model.cost === "subscription") {
|
|
91
|
+
return model.source === "supergrok" ? "SuperGrok subscription \xB7 external billing" : "Codex subscription \xB7 external billing";
|
|
92
|
+
}
|
|
93
|
+
if (model.cost === "workspace") {
|
|
94
|
+
return workspaceProviderPayerSummary(model);
|
|
95
|
+
}
|
|
104
96
|
const billing = model.billing;
|
|
105
97
|
if (!billing) {
|
|
106
98
|
return "Route unknown";
|
|
@@ -112,7 +104,7 @@ function payerSummaryForModel(model) {
|
|
|
112
104
|
return model.source === "supergrok" ? "SuperGrok subscription \xB7 external billing" : "Codex subscription \xB7 external billing";
|
|
113
105
|
}
|
|
114
106
|
if (billing.upstreamPayer === "workspace") {
|
|
115
|
-
return
|
|
107
|
+
return workspaceProviderPayerSummary(model);
|
|
116
108
|
}
|
|
117
109
|
return "External provider \xB7 no OpenGeni credits";
|
|
118
110
|
}
|
|
@@ -125,13 +117,28 @@ function advancedSourceSummary(model) {
|
|
|
125
117
|
return source.provider === "xai" ? "Connected SuperGrok subscription" : "Connected Codex subscription";
|
|
126
118
|
}
|
|
127
119
|
if (source.kind === "workspace_connection") {
|
|
128
|
-
|
|
120
|
+
if (model.provider === "workspace-openrouter") {
|
|
121
|
+
return "Workspace OpenRouter connection";
|
|
122
|
+
}
|
|
123
|
+
if (model.provider === "workspace-gateway" || model.source === "workspace_gateway") {
|
|
124
|
+
return "Workspace Vercel AI Gateway";
|
|
125
|
+
}
|
|
126
|
+
return "Workspace provider connection";
|
|
129
127
|
}
|
|
130
128
|
if (source.kind === "deployment") {
|
|
131
129
|
return source.mechanism === "azure_ad_bearer" ? "Deployment Azure identity" : "Deployment API key";
|
|
132
130
|
}
|
|
133
131
|
return null;
|
|
134
132
|
}
|
|
133
|
+
function workspaceProviderPayerSummary(model) {
|
|
134
|
+
if (model.provider === "workspace-openrouter") {
|
|
135
|
+
return "Billed to the workspace OpenRouter account";
|
|
136
|
+
}
|
|
137
|
+
if (model.provider === "workspace-gateway" || model.source === "workspace_gateway") {
|
|
138
|
+
return "Billed to the workspace Vercel account";
|
|
139
|
+
}
|
|
140
|
+
return "Billed to the workspace provider account";
|
|
141
|
+
}
|
|
135
142
|
function projectPickerRows(models) {
|
|
136
143
|
return models.filter((catalog) => {
|
|
137
144
|
const billingClass = billingClassForModel(catalog);
|
|
@@ -170,16 +177,7 @@ function projectClientModelRows(models) {
|
|
|
170
177
|
});
|
|
171
178
|
}
|
|
172
179
|
function sortPickerRows(rows) {
|
|
173
|
-
return [...rows].sort(
|
|
174
|
-
const classDelta = BILLING_CLASS_ORDER.indexOf(left.billingClass) - BILLING_CLASS_ORDER.indexOf(right.billingClass);
|
|
175
|
-
if (classDelta !== 0) {
|
|
176
|
-
return classDelta;
|
|
177
|
-
}
|
|
178
|
-
if (left.selectable !== right.selectable) {
|
|
179
|
-
return left.selectable ? -1 : 1;
|
|
180
|
-
}
|
|
181
|
-
return left.label.localeCompare(right.label);
|
|
182
|
-
});
|
|
180
|
+
return [...rows].sort(compareModelPickerOrder);
|
|
183
181
|
}
|
|
184
182
|
function findPickerRow(rows, modelId) {
|
|
185
183
|
return rows.find((row) => row.id === modelId) ?? null;
|
|
@@ -220,4 +218,4 @@ export {
|
|
|
220
218
|
findPickerRow,
|
|
221
219
|
groupPickerRowsByBillingClass
|
|
222
220
|
};
|
|
223
|
-
//# sourceMappingURL=chunk-
|
|
221
|
+
//# sourceMappingURL=chunk-WMGF4Z7X.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\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\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 return \"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 route · no authentication\"\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\nexport function projectPickerRows(models: WorkspaceModelCatalogModel[]): PickerModelRow[] {\n return models\n .filter((catalog) => {\n const billingClass = billingClassForModel(catalog);\n return billingClass === \"opengeni_credits\" || catalog.credentialReadiness.status === \"ready\";\n })\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): Array<{ billingClass: PickerBillingClass; label: string; rows: PickerModelRow[] }>;\nexport function groupPickerRowsByBillingClass<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n): Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n}>;\nexport function groupPickerRowsByBillingClass<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\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 return groups;\n}\n"],"mappings":"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","names":[]}
|