@opengeni/react 1.4.4 → 1.4.5-canary.37485542607001
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 +17 -6
- package/dist/artifacts.d.ts +1 -0
- package/dist/artifacts.js +22 -15
- package/dist/artifacts.js.map +1 -1
- package/dist/{browser-viewer-5EEAS3IU.js → browser-viewer-CV23VIHB.js} +8 -6
- package/dist/{chunk-XS67YG5R.js → chunk-4O7OE7ON.js} +45 -4
- package/dist/chunk-4O7OE7ON.js.map +1 -0
- package/dist/{chunk-JHTIMBOL.js → chunk-5JSUNNQN.js} +26 -4
- package/dist/{chunk-JHTIMBOL.js.map → chunk-5JSUNNQN.js.map} +1 -1
- package/dist/{chunk-QMMCJGFI.js → chunk-6BAMPGBV.js} +6 -3
- package/dist/chunk-6BAMPGBV.js.map +1 -0
- package/dist/{chunk-I6OY3MWC.js → chunk-6FOTSVWU.js} +2 -2
- package/dist/{chunk-LVS3MH5T.js → chunk-ATIRUHBZ.js} +128 -10
- package/dist/chunk-ATIRUHBZ.js.map +1 -0
- package/dist/chunk-BOFEQC6K.js +162 -0
- package/dist/chunk-BOFEQC6K.js.map +1 -0
- package/dist/{chunk-2OQA3CPB.js → chunk-CESBPQP5.js} +19 -5
- package/dist/chunk-CESBPQP5.js.map +1 -0
- package/dist/{chunk-YVFRBXST.js → chunk-GMNGUPMX.js} +2 -2
- package/dist/{chunk-PHBFJCEU.js → chunk-I5EGRXXG.js} +110 -7
- package/dist/chunk-I5EGRXXG.js.map +1 -0
- package/dist/{chunk-PBCZL4JP.js → chunk-INIZSNXT.js} +2 -2
- package/dist/chunk-IZV5FTJC.js +55 -0
- package/dist/chunk-IZV5FTJC.js.map +1 -0
- package/dist/chunk-JDJJMBB3.js +1883 -0
- package/dist/chunk-JDJJMBB3.js.map +1 -0
- package/dist/chunk-LHF6BVM4.js +83 -0
- package/dist/chunk-LHF6BVM4.js.map +1 -0
- package/dist/{chunk-C5BF4L26.js → chunk-LSMWZSCJ.js} +7 -7
- package/dist/chunk-LTKGTXUQ.js +174 -0
- package/dist/chunk-LTKGTXUQ.js.map +1 -0
- package/dist/chunk-N7S72EXK.js +25 -0
- package/dist/chunk-N7S72EXK.js.map +1 -0
- package/dist/{chunk-CVYCLFMH.js → chunk-PEHTX3V7.js} +19 -1
- package/dist/chunk-PEHTX3V7.js.map +1 -0
- package/dist/chunk-R5R5RQQD.js +51 -0
- package/dist/chunk-R5R5RQQD.js.map +1 -0
- package/dist/{chunk-IYQCWGU5.js → chunk-RGTZ2VDR.js} +35 -62
- package/dist/chunk-RGTZ2VDR.js.map +1 -0
- package/dist/chunk-RI42H5IU.js +326 -0
- package/dist/chunk-RI42H5IU.js.map +1 -0
- package/dist/{chunk-EAOSEIXB.js → chunk-RRRS5D5T.js} +727 -1983
- package/dist/chunk-RRRS5D5T.js.map +1 -0
- package/dist/{chunk-JH7V627O.js → chunk-SHLZMAJN.js} +2 -11
- package/dist/chunk-SHLZMAJN.js.map +1 -0
- package/dist/{chunk-IUHHPMAX.js → chunk-SZOCY5VG.js} +18 -87
- package/dist/chunk-SZOCY5VG.js.map +1 -0
- package/dist/{chunk-L2J3PU7A.js → chunk-VYIPNDUZ.js} +29 -100
- package/dist/chunk-VYIPNDUZ.js.map +1 -0
- package/dist/{chunk-G6YRCIYJ.js → chunk-YK6QMGVL.js} +55 -60
- package/dist/chunk-YK6QMGVL.js.map +1 -0
- package/dist/chunk-ZIB4H5LN.js +101 -0
- package/dist/chunk-ZIB4H5LN.js.map +1 -0
- package/dist/client.d.ts +9 -3
- package/dist/clipboard.js +1 -1
- package/dist/components/browser-viewer.d.ts +6 -0
- package/dist/components/composer.d.ts +3 -69
- package/dist/components/human-input-form.d.ts +3 -32
- package/dist/components/markdown.d.ts +8 -0
- package/dist/components/model-policy-picker.d.ts +4 -37
- package/dist/components/opper-mark.d.ts +7 -0
- package/dist/components/provider-recovery-notice.d.ts +15 -0
- package/dist/components/remark-soft-line-breaks.d.ts +38 -0
- package/dist/components/sandbox-workspace.d.ts +13 -0
- package/dist/components/session-chrome.d.ts +5 -3
- package/dist/components/session-conversation.d.ts +15 -3
- package/dist/composer-messages.d.ts +74 -0
- package/dist/composer-messages.js +9 -0
- package/dist/composer.js +15 -10
- package/dist/{computer-viewer-ELNLZGHI.js → computer-viewer-K4CKYRX6.js} +4 -4
- package/dist/connect-setup.d.ts +2 -0
- package/dist/connect.d.ts +1 -1
- package/dist/connect.js +21 -6
- package/dist/connect.js.map +1 -1
- package/dist/{embedded-voice-NIL4RDX3.js → embedded-voice-K7SOZVVZ.js} +6 -4
- package/dist/{embedded-voice-NIL4RDX3.js.map → embedded-voice-K7SOZVVZ.js.map} +1 -1
- package/dist/hooks/shared-machines-list.d.ts +4 -0
- package/dist/hooks/use-client-config-flags.d.ts +6 -0
- package/dist/hooks/use-goal.d.ts +2 -1
- package/dist/hooks/use-new-session-draft.d.ts +74 -0
- package/dist/human-input-model.d.ts +40 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +116 -73
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +5 -5
- package/dist/{latest-question-2POFPYNB.js → latest-question-27HGRPVF.js} +3 -3
- package/dist/lib/clipboard.d.ts +7 -0
- package/dist/lib/provider-recovery.d.ts +49 -0
- package/dist/lib/transient-retry.d.ts +25 -0
- package/dist/machines.js +2 -2
- package/dist/model-mark-paths.d.ts +34 -0
- package/dist/model-mark-paths.js +16 -0
- package/dist/model-picker-model.d.ts +111 -0
- package/dist/model-picker-model.js +25 -0
- package/dist/model-picker-model.js.map +1 -0
- package/dist/{model-policy-picker-menu-WRNSRFQC.js → model-policy-picker-menu-I5KPC3D6.js} +6 -4
- package/dist/model-policy-picker-menu-I5KPC3D6.js.map +1 -0
- package/dist/model-policy.d.ts +10 -0
- package/dist/model-policy.js +5 -1
- package/dist/new-session-draft.d.ts +7 -0
- package/dist/new-session-draft.js +639 -0
- package/dist/new-session-draft.js.map +1 -0
- package/dist/organization-model.d.ts +32 -0
- package/dist/organization-model.js +65 -0
- package/dist/organization-model.js.map +1 -0
- package/dist/{platform-activity-row-PJJVATTZ.js → platform-activity-row-NJ47YBXW.js} +7 -84
- package/dist/platform-activity-row-NJ47YBXW.js.map +1 -0
- package/dist/queue-presentation-model.d.ts +72 -0
- package/dist/queue-presentation-model.js +38 -0
- package/dist/queue-presentation-model.js.map +1 -0
- package/dist/{queue-surface-implementation-67FS7FUI.js → queue-surface-implementation-YPJFQ3O6.js} +24 -252
- package/dist/queue-surface-implementation-YPJFQ3O6.js.map +1 -0
- package/dist/realtime.js +5 -3
- package/dist/{sandbox-files-34CJJNOY.js → sandbox-files-2DGDO6NI.js} +5 -5
- package/dist/sandbox-files-2DGDO6NI.js.map +1 -0
- package/dist/sandbox-label-model.d.ts +23 -0
- package/dist/sandbox-label-model.js +28 -0
- package/dist/sandbox-label-model.js.map +1 -0
- package/dist/session-agents-model.d.ts +10 -0
- package/dist/session-agents-model.js +25 -0
- package/dist/session-agents-model.js.map +1 -0
- package/dist/session-attention-model.d.ts +8 -0
- package/dist/session-attention-model.js +46 -0
- package/dist/session-attention-model.js.map +1 -0
- package/dist/session-feedback-model.d.ts +20 -0
- package/dist/session-feedback-model.js +56 -0
- package/dist/session-feedback-model.js.map +1 -0
- package/dist/session-list-model.d.ts +119 -0
- package/dist/session-list-model.js +244 -0
- package/dist/session-list-model.js.map +1 -0
- package/dist/session-status-model.d.ts +19 -0
- package/dist/session-ui.js +26 -17
- package/dist/session-ui.js.map +1 -1
- package/dist/session.js +8 -6
- package/dist/testing/session-scenarios.d.ts +10 -0
- package/dist/testing/session-scenarios.js +303 -0
- package/dist/testing/session-scenarios.js.map +1 -0
- package/dist/timeline/genie-copy.d.ts +3 -0
- package/dist/timeline/genie-loading.d.ts +11 -0
- package/dist/timeline/index.d.ts +1 -1
- package/dist/timeline/notice-presentation.d.ts +7 -0
- package/dist/timeline/patch-apply-command.d.ts +18 -0
- package/dist/timeline/platform-activity-presentation.d.ts +7 -0
- package/dist/timeline/presented-image.d.ts +6 -1
- package/dist/timeline/question-nav-model.d.ts +23 -0
- package/dist/timeline/registry.d.ts +10 -1
- package/dist/timeline/retained-loaders.d.ts +1 -1
- package/dist/timeline/tool-presentation.d.ts +172 -0
- package/dist/timeline/turn-summary-model.d.ts +90 -0
- package/dist/timeline/turn-summary.d.ts +4 -74
- package/dist/timeline/work-presentation.d.ts +42 -0
- package/dist/timeline-model.d.ts +24 -0
- package/dist/timeline-model.js +152 -0
- package/dist/timeline-model.js.map +1 -0
- package/package.json +55 -3
- package/src/artifacts.ts +1 -0
- package/src/client.ts +9 -3
- package/src/components/browser-viewer.tsx +23 -2
- package/src/components/claude-mark.tsx +2 -1
- package/src/components/composer.tsx +8 -146
- package/src/components/grok-mark.tsx +2 -1
- package/src/components/human-input-form.tsx +13 -124
- package/src/components/markdown.tsx +19 -1
- package/src/components/message-timeline.tsx +45 -99
- package/src/components/model-mark.tsx +2 -1
- package/src/components/model-policy-picker-menu.tsx +30 -85
- package/src/components/model-policy-picker.tsx +20 -150
- package/src/components/opper-mark.tsx +18 -0
- package/src/components/provider-recovery-notice.tsx +41 -0
- package/src/components/queue-surface-implementation.tsx +20 -349
- package/src/components/remark-soft-line-breaks.ts +166 -0
- package/src/components/sandbox-workspace.tsx +17 -1
- package/src/components/session-chrome.tsx +114 -99
- package/src/components/session-conversation.tsx +55 -6
- package/src/components/session-status.tsx +17 -16
- package/src/composer-messages.ts +150 -0
- package/src/connect-setup.tsx +45 -11
- package/src/connect.ts +1 -1
- package/src/hooks/shared-machines-list.ts +34 -1
- package/src/hooks/use-client-config-flags.ts +8 -0
- package/src/hooks/use-goal.ts +66 -10
- package/src/hooks/use-new-session-draft.ts +813 -0
- package/src/human-input-model.ts +147 -0
- package/src/index.ts +16 -0
- package/src/lib/clipboard.ts +29 -0
- package/src/lib/format.ts +7 -0
- package/src/lib/provider-recovery.ts +202 -0
- package/src/lib/transient-retry.ts +99 -0
- package/src/model-mark-paths.ts +53 -0
- package/src/model-picker-model.ts +330 -0
- package/src/model-policy.ts +75 -5
- package/src/new-session-draft.ts +22 -0
- package/src/organization-model.ts +118 -0
- package/src/queue-presentation-model.ts +464 -0
- package/src/sandbox-label-model.ts +41 -0
- package/src/session-agents-model.ts +33 -0
- package/src/session-attention-model.ts +59 -0
- package/src/session-feedback-model.ts +95 -0
- package/src/session-list-model.ts +377 -0
- package/src/session-status-model.ts +62 -0
- package/src/testing/session-scenarios.ts +326 -0
- package/src/timeline/activity-rail.tsx +54 -24
- package/src/timeline/genie-copy.ts +19 -0
- package/src/timeline/genie-loading.tsx +15 -19
- package/src/timeline/index.ts +1 -0
- package/src/timeline/notice-presentation.ts +22 -0
- package/src/timeline/patch-apply-command.tsx +135 -0
- package/src/timeline/platform-activity-presentation.ts +122 -0
- package/src/timeline/platform-activity-row.tsx +6 -96
- package/src/timeline/presented-image.ts +16 -2
- package/src/timeline/projection.ts +12 -1
- package/src/timeline/question-nav-model.ts +28 -0
- package/src/timeline/registry.ts +11 -1
- package/src/timeline/retained-loaders.ts +9 -4
- package/src/timeline/rolling-activity.tsx +7 -19
- package/src/timeline/tool-presentation.ts +1316 -0
- package/src/timeline/tool-renderers.tsx +254 -1024
- package/src/timeline/turn-summary-model.ts +338 -0
- package/src/timeline/turn-summary.tsx +21 -326
- package/src/timeline/work-presentation.ts +139 -0
- package/src/timeline-model.ts +108 -0
- package/styles/compiled.css +17 -4
- package/styles/connect.css +4 -0
- package/styles/responsive.css +11 -2
- package/dist/chunk-2OQA3CPB.js.map +0 -1
- package/dist/chunk-CVYCLFMH.js.map +0 -1
- package/dist/chunk-EAOSEIXB.js.map +0 -1
- package/dist/chunk-G6YRCIYJ.js.map +0 -1
- package/dist/chunk-HXYOSSQO.js +0 -117
- package/dist/chunk-HXYOSSQO.js.map +0 -1
- package/dist/chunk-IUHHPMAX.js.map +0 -1
- package/dist/chunk-IYQCWGU5.js.map +0 -1
- package/dist/chunk-JH7V627O.js.map +0 -1
- package/dist/chunk-L2J3PU7A.js.map +0 -1
- package/dist/chunk-LVS3MH5T.js.map +0 -1
- package/dist/chunk-PHBFJCEU.js.map +0 -1
- package/dist/chunk-QMMCJGFI.js.map +0 -1
- package/dist/chunk-XS67YG5R.js.map +0 -1
- package/dist/platform-activity-row-PJJVATTZ.js.map +0 -1
- package/dist/queue-surface-implementation-67FS7FUI.js.map +0 -1
- /package/dist/{browser-viewer-5EEAS3IU.js.map → browser-viewer-CV23VIHB.js.map} +0 -0
- /package/dist/{chunk-I6OY3MWC.js.map → chunk-6FOTSVWU.js.map} +0 -0
- /package/dist/{chunk-YVFRBXST.js.map → chunk-GMNGUPMX.js.map} +0 -0
- /package/dist/{chunk-PBCZL4JP.js.map → chunk-INIZSNXT.js.map} +0 -0
- /package/dist/{chunk-C5BF4L26.js.map → chunk-LSMWZSCJ.js.map} +0 -0
- /package/dist/{computer-viewer-ELNLZGHI.js.map → composer-messages.js.map} +0 -0
- /package/dist/{model-policy-picker-menu-WRNSRFQC.js.map → computer-viewer-K4CKYRX6.js.map} +0 -0
- /package/dist/{latest-question-2POFPYNB.js.map → latest-question-27HGRPVF.js.map} +0 -0
- /package/dist/{sandbox-files-34CJJNOY.js.map → model-mark-paths.js.map} +0 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
coerceReasoningEffortForModel,
|
|
4
|
+
effortOptionsForModel,
|
|
5
|
+
findPickerRow,
|
|
6
|
+
groupPickerRowsByBillingClass,
|
|
7
|
+
payerSummaryForModel,
|
|
8
|
+
projectClientModelRows,
|
|
9
|
+
runnableLatencyModesForModel,
|
|
10
|
+
scopedBillingClassLabel
|
|
11
|
+
} from "./chunk-4O7OE7ON.js";
|
|
12
|
+
|
|
13
|
+
// src/model-picker-model.ts
|
|
14
|
+
var defaultModelPolicyPickerMessages = {
|
|
15
|
+
label: "Model and effort",
|
|
16
|
+
loading: "Loading model catalog\u2026",
|
|
17
|
+
noModels: "No models available.",
|
|
18
|
+
connectTitle: "Connect a model",
|
|
19
|
+
connectBody: "Use a subscription or a provider key you already have.",
|
|
20
|
+
connectAction: "Open Models",
|
|
21
|
+
thinking: "Thinking",
|
|
22
|
+
fast: "Fast",
|
|
23
|
+
fastRateHint: "2\xD7 rate",
|
|
24
|
+
codexOnly: "Codex-only session",
|
|
25
|
+
searchLabel: "Search models or providers",
|
|
26
|
+
searchPlaceholder: "Search models or providers\u2026",
|
|
27
|
+
currentModel: "Current model",
|
|
28
|
+
noMatches: "No matching models. Try a model or provider name.",
|
|
29
|
+
unsupportedAttachments: "This model cannot view the attached images.",
|
|
30
|
+
thinkingEffort: "Thinking effort",
|
|
31
|
+
selected: "Selected",
|
|
32
|
+
free: "Free",
|
|
33
|
+
billingHints: {
|
|
34
|
+
opengeni_credits: "Provided by Opengeni",
|
|
35
|
+
external: "Provider terms and limits apply",
|
|
36
|
+
codex_subscription: "ChatGPT / Codex plan",
|
|
37
|
+
supergrok_subscription: "SuperGrok / xAI plan",
|
|
38
|
+
claude_subscription: "Claude plan",
|
|
39
|
+
byok: "Billed to the connected provider account",
|
|
40
|
+
organization_byok: "Billed to the connected provider account"
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
var SCOPED_BILLING_HINTS = {
|
|
44
|
+
byok: "Billed to the workspace provider account",
|
|
45
|
+
organization_byok: "Billed to the organization provider account"
|
|
46
|
+
};
|
|
47
|
+
function isCodexPickerModel(model) {
|
|
48
|
+
return model.id.startsWith("codex/") || model.source === "codex";
|
|
49
|
+
}
|
|
50
|
+
function billingClassForMissingSelection(modelId) {
|
|
51
|
+
if (modelId.startsWith("workspace-claude-subscription/")) return "claude_subscription";
|
|
52
|
+
if (modelId.startsWith("workspace-anthropic/")) return "byok";
|
|
53
|
+
if (modelId.startsWith("organization-claude-subscription/")) return "claude_subscription";
|
|
54
|
+
if (modelId.startsWith("organization-anthropic/")) return "organization_byok";
|
|
55
|
+
if (modelId.startsWith("workspace-gateway/")) return "byok";
|
|
56
|
+
if (modelId.startsWith("workspace-openrouter/")) return "byok";
|
|
57
|
+
if (modelId.startsWith("workspace-opper/")) return "byok";
|
|
58
|
+
if (modelId.startsWith("openrouter/")) return "opengeni_credits";
|
|
59
|
+
if (modelId.startsWith("opper/")) return "opengeni_credits";
|
|
60
|
+
if (modelId.startsWith("codex/")) return "codex_subscription";
|
|
61
|
+
if (modelId.startsWith("supergrok/")) return "supergrok_subscription";
|
|
62
|
+
return "opengeni_credits";
|
|
63
|
+
}
|
|
64
|
+
function applyCodexOnly(rows, codexOnly, unavailableReason) {
|
|
65
|
+
if (!codexOnly) return rows;
|
|
66
|
+
return rows.map(
|
|
67
|
+
(row) => isCodexPickerModel(row.catalog) ? row : {
|
|
68
|
+
...row,
|
|
69
|
+
selectable: false,
|
|
70
|
+
unavailableReason: row.unavailableReason ?? unavailableReason
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
function groupPresentationFor(props, billingClass) {
|
|
75
|
+
const own = props.groupPresentation?.[billingClass];
|
|
76
|
+
if (own !== void 0 || props.collapseScopes === false) return own;
|
|
77
|
+
if (billingClass === "byok") return props.groupPresentation?.organization_byok;
|
|
78
|
+
if (billingClass === "organization_byok") return props.groupPresentation?.byok;
|
|
79
|
+
return void 0;
|
|
80
|
+
}
|
|
81
|
+
function effectiveRows(props) {
|
|
82
|
+
const rows = props.rows !== void 0 ? props.rows : projectClientModelRows(props.models ?? []);
|
|
83
|
+
const messages = { ...defaultModelPolicyPickerMessages, ...props.messages };
|
|
84
|
+
return applyCodexOnly(rows, props.codexOnly === true, messages.codexOnly).map((row) => {
|
|
85
|
+
const scoped = props.collapseScopes === false ? {
|
|
86
|
+
...row,
|
|
87
|
+
label: row.catalog.label,
|
|
88
|
+
billingClassLabel: scopedBillingClassLabel(row.billingClass)
|
|
89
|
+
} : row;
|
|
90
|
+
if (props.collapseScopes === false) {
|
|
91
|
+
if (row.catalog.shortLabel) scoped.shortLabel = row.catalog.shortLabel;
|
|
92
|
+
else delete scoped.shortLabel;
|
|
93
|
+
}
|
|
94
|
+
const label = groupPresentationFor(props, row.billingClass)?.label;
|
|
95
|
+
return label === void 0 ? scoped : { ...scoped, billingClassLabel: label };
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function modelPickerMenuView(props, query) {
|
|
99
|
+
const messages = { ...defaultModelPolicyPickerMessages, ...props.messages };
|
|
100
|
+
const rows = effectiveRows(props);
|
|
101
|
+
const selected = findPickerRow(rows, props.model);
|
|
102
|
+
const words = query.toLowerCase().trim().split(/\s+/).filter(Boolean);
|
|
103
|
+
const filtered = rows.filter((row) => {
|
|
104
|
+
const description = groupPresentationFor(props, row.billingClass)?.description;
|
|
105
|
+
const text = `${row.label} ${row.id} ${row.providerLabel} ${row.billingClassLabel} ${description === void 0 ? payerSummaryForModel(row.catalog) : description ?? ""}`.toLowerCase();
|
|
106
|
+
return words.every((word) => text.includes(word));
|
|
107
|
+
});
|
|
108
|
+
const matchingIds = new Set(filtered.map((row) => row.id));
|
|
109
|
+
const groups = groupPickerRowsByBillingClass(rows, {
|
|
110
|
+
codexOnly: props.codexOnly === true,
|
|
111
|
+
selectedId: props.model,
|
|
112
|
+
collapseScopes: props.collapseScopes !== false
|
|
113
|
+
}).map((group) => {
|
|
114
|
+
const presentation = groupPresentationFor(props, group.billingClass);
|
|
115
|
+
const override = presentation?.description;
|
|
116
|
+
const defaultHint = props.collapseScopes === false && messages.billingHints[group.billingClass] === defaultModelPolicyPickerMessages.billingHints[group.billingClass] ? SCOPED_BILLING_HINTS[group.billingClass] ?? messages.billingHints[group.billingClass] : messages.billingHints[group.billingClass];
|
|
117
|
+
return {
|
|
118
|
+
billingClass: group.billingClass,
|
|
119
|
+
label: presentation?.label ?? group.label,
|
|
120
|
+
rows: group.rows.filter((row) => matchingIds.has(row.id)),
|
|
121
|
+
description: override === void 0 ? group.billingClass === "opengeni_credits" ? null : defaultHint : override
|
|
122
|
+
};
|
|
123
|
+
}).filter((group) => group.rows.length > 0);
|
|
124
|
+
const anySelectable = rows.some((row) => row.selectable);
|
|
125
|
+
const unsupportedAttachments = props.hasImageAttachments === true && selected?.catalog.capabilities?.inputModalities.includes("image") === false;
|
|
126
|
+
return {
|
|
127
|
+
messages,
|
|
128
|
+
rows,
|
|
129
|
+
selected,
|
|
130
|
+
anySelectable,
|
|
131
|
+
searching: words.length > 0,
|
|
132
|
+
groups,
|
|
133
|
+
matchCount: filtered.length,
|
|
134
|
+
thinking: selected ? modelPickerThinking(props, selected) : null,
|
|
135
|
+
unsupportedAttachments
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function modelPickerThinking(props, selected) {
|
|
139
|
+
const efforts = effortOptionsForModel(selected.catalog);
|
|
140
|
+
const showThinking = efforts.length > 1 && selected.catalog.capabilities?.reasoning.runnable !== false;
|
|
141
|
+
const showFast = props.allowLatencyMode !== false && runnableLatencyModesForModel(selected.catalog).includes("fast");
|
|
142
|
+
if (!showThinking && !showFast) return null;
|
|
143
|
+
return {
|
|
144
|
+
efforts,
|
|
145
|
+
value: coerceReasoningEffortForModel(selected.catalog, props.effort),
|
|
146
|
+
showThinking,
|
|
147
|
+
showFast,
|
|
148
|
+
disabled: !selected.selectable
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function modelPickerChoice(props, row) {
|
|
152
|
+
if (!row.selectable) return null;
|
|
153
|
+
return {
|
|
154
|
+
model: row.id === props.model ? null : row.id,
|
|
155
|
+
effort: coerceReasoningEffortForModel(row.catalog, props.effort),
|
|
156
|
+
latencyMode: props.latencyMode !== "standard" && !runnableLatencyModesForModel(row.catalog).includes(props.latencyMode) ? "standard" : null
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function compactEffortLabel(effort, label) {
|
|
160
|
+
return effort === "xhigh" ? "X-high" : label;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export {
|
|
164
|
+
defaultModelPolicyPickerMessages,
|
|
165
|
+
SCOPED_BILLING_HINTS,
|
|
166
|
+
isCodexPickerModel,
|
|
167
|
+
billingClassForMissingSelection,
|
|
168
|
+
groupPresentationFor,
|
|
169
|
+
effectiveRows,
|
|
170
|
+
modelPickerMenuView,
|
|
171
|
+
modelPickerChoice,
|
|
172
|
+
compactEffortLabel
|
|
173
|
+
};
|
|
174
|
+
//# sourceMappingURL=chunk-LTKGTXUQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/model-picker-model.ts"],"sourcesContent":["/**\n * The model picker's presentation logic, free of any renderer: which rows show,\n * how they group and filter, and which thinking/latency controls apply. The web\n * menu and native sheets both render from this.\n */\nimport type { ClientModel, LatencyMode, ReasoningEffort } from \"@opengeni/sdk\";\nimport {\n coerceReasoningEffortForModel,\n effortOptionsForModel,\n findPickerRow,\n groupPickerRowsByBillingClass,\n payerSummaryForModel,\n projectClientModelRows,\n runnableLatencyModesForModel,\n scopedBillingClassLabel,\n type PickerBillingClass,\n type PickerModelRow,\n} from \"./model-policy\";\n\ntype ClientPickerModelRow = PickerModelRow<ClientModel>;\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 claude_subscription: \"Claude plan\",\n byok: \"Billed to the connected provider account\",\n organization_byok: \"Billed to the connected provider account\",\n },\n};\n\n/** Host branding for one payment group; the icon type belongs to the renderer. */\nexport type ModelPickerGroupBranding<TIcon = unknown> = {\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?: TIcon | undefined;\n};\n\nexport type ModelPickerGroupPresentation<TIcon = unknown> = Partial<\n Record<PickerBillingClass, ModelPickerGroupBranding<TIcon>>\n>;\n\n/** The renderer-neutral inputs every picker surface shares. */\nexport type ModelPickerInput<TIcon = unknown> = {\n groupPresentation?: ModelPickerGroupPresentation<TIcon> | undefined;\n models?: ClientModel[] | undefined;\n rows?: PickerModelRow[] | undefined;\n hasImageAttachments?: boolean | undefined;\n model: string;\n effort: ReasoningEffort;\n latencyMode: LatencyMode;\n codexOnly?: boolean | undefined;\n collapseScopes?: boolean | undefined;\n allowLatencyMode?: boolean | undefined;\n messages?: Partial<ModelPolicyPickerMessages> | undefined;\n};\n\n/** Models settings keeps naming who is billed for a key. */\nexport const SCOPED_BILLING_HINTS: Partial<Record<PickerBillingClass, string>> = {\n byok: \"Billed to the workspace provider account\",\n organization_byok: \"Billed to the organization provider account\",\n};\n\nexport function isCodexPickerModel(model: ClientModel): boolean {\n return model.id.startsWith(\"codex/\") || model.source === \"codex\";\n}\n\n/** The payment group a selection the catalog no longer lists most likely belonged to. */\nexport function billingClassForMissingSelection(modelId: string): PickerBillingClass {\n if (modelId.startsWith(\"workspace-claude-subscription/\")) return \"claude_subscription\";\n if (modelId.startsWith(\"workspace-anthropic/\")) return \"byok\";\n if (modelId.startsWith(\"organization-claude-subscription/\")) return \"claude_subscription\";\n if (modelId.startsWith(\"organization-anthropic/\")) return \"organization_byok\";\n if (modelId.startsWith(\"workspace-gateway/\")) return \"byok\";\n if (modelId.startsWith(\"workspace-openrouter/\")) return \"byok\";\n if (modelId.startsWith(\"workspace-opper/\")) return \"byok\";\n // A deployment OpenRouter or Opper 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(\"opper/\")) 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 isCodexPickerModel(row.catalog)\n ? row\n : {\n ...row,\n selectable: false,\n unavailableReason: row.unavailableReason ?? unavailableReason,\n },\n );\n}\n\n/**\n * Host branding for a payment group. While scopes are collapsed, API keys are\n * one group, so either API-key presentation serves both.\n */\nexport function groupPresentationFor<TIcon>(\n props: {\n groupPresentation?: ModelPickerGroupPresentation<TIcon> | undefined;\n collapseScopes?: boolean | undefined;\n },\n billingClass: PickerBillingClass,\n): ModelPickerGroupBranding<TIcon> | undefined {\n const own = props.groupPresentation?.[billingClass];\n if (own !== undefined || props.collapseScopes === false) return own;\n if (billingClass === \"byok\") return props.groupPresentation?.organization_byok;\n if (billingClass === \"organization_byok\") return props.groupPresentation?.byok;\n return undefined;\n}\n\nexport function effectiveRows<TIcon>(props: ModelPickerInput<TIcon>): 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 scoped =\n props.collapseScopes === false\n ? {\n ...row,\n label: row.catalog.label,\n billingClassLabel: scopedBillingClassLabel(row.billingClass),\n }\n : row;\n if (props.collapseScopes === false) {\n if (row.catalog.shortLabel) scoped.shortLabel = row.catalog.shortLabel;\n else delete scoped.shortLabel;\n }\n const label = groupPresentationFor(props, row.billingClass)?.label;\n return label === undefined ? scoped : { ...scoped, billingClassLabel: label };\n });\n}\n\nexport type ModelPickerMenuGroup = {\n billingClass: PickerBillingClass;\n label: string;\n description: string | null;\n rows: ClientPickerModelRow[];\n};\n\nexport type ModelPickerThinking = {\n efforts: ReasoningEffort[];\n value: ReasoningEffort;\n showThinking: boolean;\n showFast: boolean;\n /** The selected row cannot run, so its controls are read-only. */\n disabled: boolean;\n};\n\nexport type ModelPickerMenuView = {\n messages: ModelPolicyPickerMessages;\n rows: ClientPickerModelRow[];\n selected: ClientPickerModelRow | null;\n /** Any row can run; otherwise the surface offers to connect models instead. */\n anySelectable: boolean;\n /** Whether the query is non-empty (decides \"no matches\" versus \"no models\"). */\n searching: boolean;\n groups: ModelPickerMenuGroup[];\n matchCount: number;\n /** Thinking and Fast controls for the selected model, or null when it has none. */\n thinking: ModelPickerThinking | null;\n /** The selected model cannot view images the draft carries. */\n unsupportedAttachments: boolean;\n};\n\n/** Everything a picker menu shows for this input and search query. */\nexport function modelPickerMenuView<TIcon>(\n props: ModelPickerInput<TIcon>,\n query: string,\n): ModelPickerMenuView {\n const messages = { ...defaultModelPolicyPickerMessages, ...props.messages };\n const rows = effectiveRows(props);\n const selected = findPickerRow(rows, props.model);\n const words = query.toLowerCase().trim().split(/\\s+/).filter(Boolean);\n const filtered = rows.filter((row) => {\n const description = groupPresentationFor(props, row.billingClass)?.description;\n const text =\n `${row.label} ${row.id} ${row.providerLabel} ${row.billingClassLabel} ${description === undefined ? payerSummaryForModel(row.catalog) : (description ?? \"\")}`.toLowerCase();\n return words.every((word) => text.includes(word));\n });\n const matchingIds = new Set(filtered.map((row) => row.id));\n const groups = groupPickerRowsByBillingClass(rows, {\n codexOnly: props.codexOnly === true,\n selectedId: props.model,\n collapseScopes: props.collapseScopes !== false,\n })\n .map((group) => {\n const presentation = groupPresentationFor(props, group.billingClass);\n const override = presentation?.description;\n const defaultHint =\n props.collapseScopes === false &&\n messages.billingHints[group.billingClass] ===\n defaultModelPolicyPickerMessages.billingHints[group.billingClass]\n ? (SCOPED_BILLING_HINTS[group.billingClass] ?? messages.billingHints[group.billingClass])\n : messages.billingHints[group.billingClass];\n return {\n billingClass: group.billingClass,\n label: presentation?.label ?? group.label,\n rows: group.rows.filter((row) => matchingIds.has(row.id)),\n description:\n override === undefined\n ? group.billingClass === \"opengeni_credits\"\n ? null\n : defaultHint\n : override,\n };\n })\n .filter((group) => group.rows.length > 0);\n const anySelectable = rows.some((row) => row.selectable);\n const unsupportedAttachments =\n props.hasImageAttachments === true &&\n selected?.catalog.capabilities?.inputModalities.includes(\"image\") === false;\n return {\n messages,\n rows,\n selected,\n anySelectable,\n searching: words.length > 0,\n groups,\n matchCount: filtered.length,\n thinking: selected ? modelPickerThinking(props, selected) : null,\n unsupportedAttachments,\n };\n}\n\nfunction modelPickerThinking(\n props: Pick<ModelPickerInput, \"effort\" | \"allowLatencyMode\">,\n selected: ClientPickerModelRow,\n): ModelPickerThinking | null {\n const efforts = effortOptionsForModel(selected.catalog);\n const showThinking =\n efforts.length > 1 && selected.catalog.capabilities?.reasoning.runnable !== false;\n const showFast =\n props.allowLatencyMode !== false &&\n runnableLatencyModesForModel(selected.catalog).includes(\"fast\");\n if (!showThinking && !showFast) return null;\n return {\n efforts,\n value: coerceReasoningEffortForModel(selected.catalog, props.effort),\n showThinking,\n showFast,\n disabled: !selected.selectable,\n };\n}\n\nexport type ModelPickerChoice = {\n /** The new model, or null when the row is already selected. */\n model: string | null;\n /** Always reported, so hosts can commit model and effort together. */\n effort: ReasoningEffort;\n /** Fast falls back to standard when the new model cannot run it. */\n latencyMode: LatencyMode | null;\n};\n\n/** What choosing a row changes, or null when the row cannot be chosen. */\nexport function modelPickerChoice(\n props: Pick<ModelPickerInput, \"model\" | \"effort\" | \"latencyMode\">,\n row: ClientPickerModelRow,\n): ModelPickerChoice | null {\n if (!row.selectable) return null;\n return {\n model: row.id === props.model ? null : row.id,\n effort: coerceReasoningEffortForModel(row.catalog, props.effort),\n latencyMode:\n props.latencyMode !== \"standard\" &&\n !runnableLatencyModesForModel(row.catalog).includes(props.latencyMode)\n ? \"standard\"\n : null,\n };\n}\n\n/** The web segmented control's short labels (\"X-high\" fits a phone row). */\nexport function compactEffortLabel(effort: ReasoningEffort, label: string): string {\n return effort === \"xhigh\" ? \"X-high\" : label;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/model-mark-paths.ts
|
|
4
|
+
import { modelVendor } from "@opengeni/sdk/model-display";
|
|
5
|
+
var CHATGPT_MARK_PATH = "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";
|
|
6
|
+
var CLAUDE_MARK_PATH = "m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z";
|
|
7
|
+
var GROK_MARK_PATH = "M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815";
|
|
8
|
+
var MODEL_MARK_PATHS = {
|
|
9
|
+
openai: CHATGPT_MARK_PATH,
|
|
10
|
+
anthropic: CLAUDE_MARK_PATH,
|
|
11
|
+
xai: GROK_MARK_PATH
|
|
12
|
+
};
|
|
13
|
+
function modelMarkVendor(model) {
|
|
14
|
+
const vendor = modelVendor(model);
|
|
15
|
+
return vendor === "openai" || vendor === "anthropic" || vendor === "xai" ? vendor : null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
CHATGPT_MARK_PATH,
|
|
20
|
+
CLAUDE_MARK_PATH,
|
|
21
|
+
GROK_MARK_PATH,
|
|
22
|
+
MODEL_MARK_PATHS,
|
|
23
|
+
modelMarkVendor
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=chunk-N7S72EXK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/model-mark-paths.ts"],"sourcesContent":["// Model maker marks as plain path data (24×24 viewBox, filled with the current\n// color), shared by the web SVG components and native renderers so both draw\n// identical geometry.\nimport { modelVendor, type ModelDisplayInput, type ModelVendor } from \"@opengeni/sdk/model-display\";\n\n/** ChatGPT / OpenAI mark (Simple Icons, CC0). */\nexport const CHATGPT_MARK_PATH =\n \"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\n/** Claude mark (Simple Icons, CC0; https://github.com/simple-icons/simple-icons). */\nexport const CLAUDE_MARK_PATH =\n \"m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z\";\n\n/**\n * MIT License\n *\n * Copyright (c) 2023 LobeHub\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n * Source: https://raw.githubusercontent.com/lobehub/lobe-icons/master/src/Grok/components/Mono.tsx\n */\nexport const GROK_MARK_PATH =\n \"M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815\";\n\nexport type MarkedModelVendor = Extract<ModelVendor, \"openai\" | \"anthropic\" | \"xai\">;\n\nexport const MODEL_MARK_PATHS: Record<MarkedModelVendor, string> = {\n openai: CHATGPT_MARK_PATH,\n anthropic: CLAUDE_MARK_PATH,\n xai: GROK_MARK_PATH,\n};\n\n/** The maker whose logo marks this model, or null for the neutral fallback. */\nexport function modelMarkVendor(model: ModelDisplayInput): MarkedModelVendor | null {\n const vendor = modelVendor(model);\n return vendor === \"openai\" || vendor === \"anthropic\" || vendor === \"xai\" ? vendor : null;\n}\n"],"mappings":";;;AAGA,SAAS,mBAA6D;AAG/D,IAAM,oBACX;AAGK,IAAM,mBACX;AA0BK,IAAM,iBACX;AAIK,IAAM,mBAAsD;AAAA,EACjE,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,KAAK;AACP;AAGO,SAAS,gBAAgB,OAAoD;AAClF,QAAM,SAAS,YAAY,KAAK;AAChC,SAAO,WAAW,YAAY,WAAW,eAAe,WAAW,QAAQ,SAAS;AACtF;","names":[]}
|
|
@@ -32,6 +32,23 @@ async function copyTextToClipboard(text) {
|
|
|
32
32
|
return false;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
async function copyPendingTextToClipboard(text) {
|
|
36
|
+
if (typeof ClipboardItem !== "undefined" && typeof navigator !== "undefined" && typeof navigator.clipboard?.write === "function") {
|
|
37
|
+
const blob = text.then((value) => new Blob([value], { type: "text/plain" }));
|
|
38
|
+
blob.catch(() => {
|
|
39
|
+
});
|
|
40
|
+
try {
|
|
41
|
+
await navigator.clipboard.write([new ClipboardItem({ "text/plain": blob })]);
|
|
42
|
+
return true;
|
|
43
|
+
} catch {
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
return await copyTextToClipboard(await text);
|
|
48
|
+
} catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
35
52
|
function tableElementToTsv(table) {
|
|
36
53
|
if (!table) {
|
|
37
54
|
return "";
|
|
@@ -50,6 +67,7 @@ function tableElementToTsv(table) {
|
|
|
50
67
|
|
|
51
68
|
export {
|
|
52
69
|
copyTextToClipboard,
|
|
70
|
+
copyPendingTextToClipboard,
|
|
53
71
|
tableElementToTsv
|
|
54
72
|
};
|
|
55
|
-
//# sourceMappingURL=chunk-
|
|
73
|
+
//# sourceMappingURL=chunk-PEHTX3V7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/clipboard.ts"],"sourcesContent":["/**\n * Copy plain text to the clipboard. Prefers the async Clipboard API; falls\n * back to a short-lived textarea for older embeds / denied permissions.\n */\nexport async function copyTextToClipboard(text: string): Promise<boolean> {\n const value = text.replace(/\\u00a0/g, \" \");\n if (value.length === 0) {\n return false;\n }\n try {\n if (typeof navigator !== \"undefined\" && navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(value);\n return true;\n }\n } catch {\n // Fall through to execCommand path.\n }\n if (typeof document === \"undefined\") {\n return false;\n }\n try {\n const area = document.createElement(\"textarea\");\n area.value = value;\n area.setAttribute(\"readonly\", \"\");\n area.style.position = \"fixed\";\n area.style.left = \"-9999px\";\n area.style.top = \"0\";\n document.body.appendChild(area);\n area.select();\n const ok = document.execCommand(\"copy\");\n document.body.removeChild(area);\n return ok;\n } catch {\n return false;\n }\n}\n\n/**\n * Copy text that is still being prepared, such as a command around a freshly\n * minted URL. Safari only allows a clipboard write during the click itself, so\n * hand the pending text to a `ClipboardItem` where supported; otherwise wait\n * for it and copy. Resolves false when the text failed or nothing was copied.\n */\nexport async function copyPendingTextToClipboard(text: Promise<string>): Promise<boolean> {\n if (\n typeof ClipboardItem !== \"undefined\" &&\n typeof navigator !== \"undefined\" &&\n typeof navigator.clipboard?.write === \"function\"\n ) {\n const blob = text.then((value) => new Blob([value], { type: \"text/plain\" }));\n // The caller observes a failed `text`; never leave this copy unhandled.\n blob.catch(() => {});\n try {\n await navigator.clipboard.write([new ClipboardItem({ \"text/plain\": blob })]);\n return true;\n } catch {\n // Fall through: some browsers reject promised clipboard items.\n }\n }\n try {\n return await copyTextToClipboard(await text);\n } catch {\n return false;\n }\n}\n\n/** Serialize an HTML table to tab-separated values (spreadsheet-friendly). */\nexport function tableElementToTsv(table: HTMLTableElement | null | undefined): string {\n if (!table) {\n return \"\";\n }\n const rows = Array.from(table.querySelectorAll(\"tr\"));\n return rows\n .map((row) =>\n Array.from(row.querySelectorAll(\"th,td\"))\n .map((cell) => {\n const raw = (cell.textContent ?? \"\").replace(/\\s+/g, \" \").trim();\n if (/[\\t\\n\"]/.test(raw)) {\n return `\"${raw.replace(/\"/g, '\"\"')}\"`;\n }\n return raw;\n })\n .join(\"\\t\"),\n )\n .filter((line) => line.length > 0)\n .join(\"\\n\");\n}\n"],"mappings":";;;AAIA,eAAsB,oBAAoB,MAAgC;AACxE,QAAM,QAAQ,KAAK,QAAQ,WAAW,GAAG;AACzC,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AACA,MAAI;AACF,QAAI,OAAO,cAAc,eAAe,UAAU,WAAW,WAAW;AACtE,YAAM,UAAU,UAAU,UAAU,KAAK;AACzC,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AACA,MAAI,OAAO,aAAa,aAAa;AACnC,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,OAAO,SAAS,cAAc,UAAU;AAC9C,SAAK,QAAQ;AACb,SAAK,aAAa,YAAY,EAAE;AAChC,SAAK,MAAM,WAAW;AACtB,SAAK,MAAM,OAAO;AAClB,SAAK,MAAM,MAAM;AACjB,aAAS,KAAK,YAAY,IAAI;AAC9B,SAAK,OAAO;AACZ,UAAM,KAAK,SAAS,YAAY,MAAM;AACtC,aAAS,KAAK,YAAY,IAAI;AAC9B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQA,eAAsB,2BAA2B,MAAyC;AACxF,MACE,OAAO,kBAAkB,eACzB,OAAO,cAAc,eACrB,OAAO,UAAU,WAAW,UAAU,YACtC;AACA,UAAM,OAAO,KAAK,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,KAAK,GAAG,EAAE,MAAM,aAAa,CAAC,CAAC;AAE3E,SAAK,MAAM,MAAM;AAAA,IAAC,CAAC;AACnB,QAAI;AACF,YAAM,UAAU,UAAU,MAAM,CAAC,IAAI,cAAc,EAAE,cAAc,KAAK,CAAC,CAAC,CAAC;AAC3E,aAAO;AAAA,IACT,QAAQ;AAAA,IAER;AAAA,EACF;AACA,MAAI;AACF,WAAO,MAAM,oBAAoB,MAAM,IAAI;AAAA,EAC7C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,kBAAkB,OAAoD;AACpF,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,QAAM,OAAO,MAAM,KAAK,MAAM,iBAAiB,IAAI,CAAC;AACpD,SAAO,KACJ;AAAA,IAAI,CAAC,QACJ,MAAM,KAAK,IAAI,iBAAiB,OAAO,CAAC,EACrC,IAAI,CAAC,SAAS;AACb,YAAM,OAAO,KAAK,eAAe,IAAI,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAC/D,UAAI,UAAU,KAAK,GAAG,GAAG;AACvB,eAAO,IAAI,IAAI,QAAQ,MAAM,IAAI,CAAC;AAAA,MACpC;AACA,aAAO;AAAA,IACT,CAAC,EACA,KAAK,GAAI;AAAA,EACd,EACC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,EAChC,KAAK,IAAI;AACd;","names":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
mcpToolLeaf
|
|
4
|
+
} from "./chunk-T46QZH3E.js";
|
|
5
|
+
|
|
6
|
+
// src/timeline/presented-image.ts
|
|
7
|
+
import { normalizeMcpOutput, parseSandboxFileArtifactReceipt } from "@opengeni/sdk";
|
|
8
|
+
function isRetainedImageContentType(contentType) {
|
|
9
|
+
return [
|
|
10
|
+
"image/png",
|
|
11
|
+
"image/jpeg",
|
|
12
|
+
"image/gif",
|
|
13
|
+
"image/webp",
|
|
14
|
+
"image/avif",
|
|
15
|
+
"image/svg+xml"
|
|
16
|
+
].includes(contentType);
|
|
17
|
+
}
|
|
18
|
+
function isPatchFilename(filename) {
|
|
19
|
+
return /\.(patch|diff)$/iu.test(filename.trim());
|
|
20
|
+
}
|
|
21
|
+
function activityPresentsImage(items) {
|
|
22
|
+
return items.some((item) => {
|
|
23
|
+
if (item.kind !== "tool-call") return false;
|
|
24
|
+
const name = mcpToolLeaf(item.name);
|
|
25
|
+
if (name === "generate_image" || name === "image_generation_call") return true;
|
|
26
|
+
if (item.status !== "complete" || name !== "sandbox_file_publish") return false;
|
|
27
|
+
const output = normalizeMcpOutput(item.output);
|
|
28
|
+
if (output.isError) return false;
|
|
29
|
+
const receipt = parseSandboxFileArtifactReceipt(output.text);
|
|
30
|
+
return receipt !== null && (isRetainedImageContentType(receipt.artifact.contentType) || // A published patch is the deliverable when there's no pull request:
|
|
31
|
+
// keep its card (with the apply command) visible like an image.
|
|
32
|
+
isPatchFilename(receipt.filename));
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function timelineGroupContainsPresentedImage(group) {
|
|
36
|
+
switch (group.kind) {
|
|
37
|
+
case "item":
|
|
38
|
+
return false;
|
|
39
|
+
case "activity":
|
|
40
|
+
return activityPresentsImage(group.items) || (group.work?.details?.some(timelineGroupContainsPresentedImage) ?? false);
|
|
41
|
+
case "turn":
|
|
42
|
+
return group.groups.some(timelineGroupContainsPresentedImage);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export {
|
|
47
|
+
isRetainedImageContentType,
|
|
48
|
+
isPatchFilename,
|
|
49
|
+
timelineGroupContainsPresentedImage
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=chunk-R5R5RQQD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/timeline/presented-image.ts"],"sourcesContent":["import { normalizeMcpOutput, parseSandboxFileArtifactReceipt } from \"@opengeni/sdk\";\nimport { mcpToolLeaf } from \"./tool-display-name\";\nimport type { ActivityItem, TimelineGroup } from \"./types\";\n\n/*\n * Pure presentation facts shared by the projection and the renderers. Kept\n * free of React so the session-only entry can inspect primary output without pulling\n * in rendering code.\n */\n\n/** Shared browser preview allowlist; other published files remain downloads. */\nexport function isRetainedImageContentType(contentType: string): boolean {\n return [\n \"image/png\",\n \"image/jpeg\",\n \"image/gif\",\n \"image/webp\",\n \"image/avif\",\n \"image/svg+xml\",\n ].includes(contentType);\n}\n\n/** A published patch, applied locally with `git apply`. */\nexport function isPatchFilename(filename: string): boolean {\n return /\\.(patch|diff)$/iu.test(filename.trim());\n}\n\n/**\n * Deliberately published images and patches are primary output, not\n * incidental screenshots or work files.\n */\nexport function activityPresentsImage(items: readonly ActivityItem[]): boolean {\n return items.some((item) => {\n if (item.kind !== \"tool-call\") return false;\n const name = mcpToolLeaf(item.name);\n if (name === \"generate_image\" || name === \"image_generation_call\") return true;\n if (item.status !== \"complete\" || name !== \"sandbox_file_publish\") return false;\n const output = normalizeMcpOutput(item.output);\n if (output.isError) return false;\n const receipt = parseSandboxFileArtifactReceipt(output.text);\n return (\n receipt !== null &&\n (isRetainedImageContentType(receipt.artifact.contentType) ||\n // A published patch is the deliverable when there's no pull request:\n // keep its card (with the apply command) visible like an image.\n isPatchFilename(receipt.filename))\n );\n });\n}\n\nexport function timelineGroupContainsPresentedImage(group: TimelineGroup): boolean {\n switch (group.kind) {\n case \"item\":\n return false;\n case \"activity\":\n return (\n activityPresentsImage(group.items) ||\n (group.work?.details?.some(timelineGroupContainsPresentedImage) ?? false)\n );\n case \"turn\":\n return group.groups.some(timelineGroupContainsPresentedImage);\n }\n}\n"],"mappings":";;;;;;AAAA,SAAS,oBAAoB,uCAAuC;AAW7D,SAAS,2BAA2B,aAA8B;AACvE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,SAAS,WAAW;AACxB;AAGO,SAAS,gBAAgB,UAA2B;AACzD,SAAO,oBAAoB,KAAK,SAAS,KAAK,CAAC;AACjD;AAMO,SAAS,sBAAsB,OAAyC;AAC7E,SAAO,MAAM,KAAK,CAAC,SAAS;AAC1B,QAAI,KAAK,SAAS,YAAa,QAAO;AACtC,UAAM,OAAO,YAAY,KAAK,IAAI;AAClC,QAAI,SAAS,oBAAoB,SAAS,wBAAyB,QAAO;AAC1E,QAAI,KAAK,WAAW,cAAc,SAAS,uBAAwB,QAAO;AAC1E,UAAM,SAAS,mBAAmB,KAAK,MAAM;AAC7C,QAAI,OAAO,QAAS,QAAO;AAC3B,UAAM,UAAU,gCAAgC,OAAO,IAAI;AAC3D,WACE,YAAY,SACX,2BAA2B,QAAQ,SAAS,WAAW;AAAA;AAAA,IAGtD,gBAAgB,QAAQ,QAAQ;AAAA,EAEtC,CAAC;AACH;AAEO,SAAS,oCAAoC,OAA+B;AACjF,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aACE,sBAAsB,MAAM,KAAK,MAChC,MAAM,MAAM,SAAS,KAAK,mCAAmC,KAAK;AAAA,IAEvE,KAAK;AACH,aAAO,MAAM,OAAO,KAAK,mCAAmC;AAAA,EAChE;AACF;","names":[]}
|
|
@@ -2,12 +2,8 @@
|
|
|
2
2
|
import {
|
|
3
3
|
BillingClassMark,
|
|
4
4
|
ModelMark,
|
|
5
|
-
PickerNavRow
|
|
6
|
-
|
|
7
|
-
defaultModelPolicyPickerMessages,
|
|
8
|
-
effectiveRows,
|
|
9
|
-
groupPresentationFor
|
|
10
|
-
} from "./chunk-L2J3PU7A.js";
|
|
5
|
+
PickerNavRow
|
|
6
|
+
} from "./chunk-VYIPNDUZ.js";
|
|
11
7
|
import {
|
|
12
8
|
MENU_CHECK_CLASS,
|
|
13
9
|
MENU_LABEL_CLASS,
|
|
@@ -15,14 +11,15 @@ import {
|
|
|
15
11
|
MENU_SURFACE_CLASS
|
|
16
12
|
} from "./chunk-PMV53IMM.js";
|
|
17
13
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
compactEffortLabel,
|
|
15
|
+
defaultModelPolicyPickerMessages,
|
|
16
|
+
groupPresentationFor,
|
|
17
|
+
modelPickerChoice,
|
|
18
|
+
modelPickerMenuView
|
|
19
|
+
} from "./chunk-LTKGTXUQ.js";
|
|
20
|
+
import {
|
|
21
|
+
labelReasoningEffort
|
|
22
|
+
} from "./chunk-4O7OE7ON.js";
|
|
26
23
|
import {
|
|
27
24
|
cn
|
|
28
25
|
} from "./chunk-TXS65BB2.js";
|
|
@@ -33,40 +30,17 @@ import { useRef, useState } from "react";
|
|
|
33
30
|
import { Popover, RadioGroup } from "radix-ui";
|
|
34
31
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
35
32
|
function ModelPolicyPickerMenu(props) {
|
|
36
|
-
const messages = { ...defaultModelPolicyPickerMessages, ...props.messages };
|
|
37
33
|
const [query, setQuery] = useState("");
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const filtered = rows.filter((row) => {
|
|
42
|
-
const description = groupPresentationFor(props, row.billingClass)?.description;
|
|
43
|
-
const text = `${row.label} ${row.id} ${row.providerLabel} ${row.billingClassLabel} ${description === void 0 ? payerSummaryForModel(row.catalog) : description ?? ""}`.toLowerCase();
|
|
44
|
-
return words.every((word) => text.includes(word));
|
|
45
|
-
});
|
|
46
|
-
const matchingIds = new Set(filtered.map((row) => row.id));
|
|
47
|
-
const groups = groupPickerRowsByBillingClass(rows, {
|
|
48
|
-
codexOnly: props.codexOnly === true,
|
|
49
|
-
selectedId: props.model,
|
|
50
|
-
collapseScopes: props.collapseScopes !== false
|
|
51
|
-
}).map((group) => {
|
|
52
|
-
const presentation = groupPresentationFor(props, group.billingClass);
|
|
53
|
-
const override = presentation?.description;
|
|
54
|
-
const defaultHint = props.collapseScopes === false && messages.billingHints[group.billingClass] === defaultModelPolicyPickerMessages.billingHints[group.billingClass] ? SCOPED_BILLING_HINTS[group.billingClass] ?? messages.billingHints[group.billingClass] : messages.billingHints[group.billingClass];
|
|
55
|
-
return {
|
|
56
|
-
...group,
|
|
57
|
-
label: presentation?.label ?? group.label,
|
|
58
|
-
rows: group.rows.filter((row) => matchingIds.has(row.id)),
|
|
59
|
-
description: override === void 0 ? group.billingClass === "opengeni_credits" ? null : defaultHint : override
|
|
60
|
-
};
|
|
61
|
-
}).filter((group) => group.rows.length > 0);
|
|
34
|
+
const view = modelPickerMenuView(props, query);
|
|
35
|
+
const { messages, rows, groups } = view;
|
|
36
|
+
const selected = view.selected;
|
|
62
37
|
const choose = (row) => {
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
props.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
38
|
+
if (props.disabled) return;
|
|
39
|
+
const choice = modelPickerChoice(props, row);
|
|
40
|
+
if (!choice) return;
|
|
41
|
+
if (choice.model !== null) props.onModelChange(choice.model);
|
|
42
|
+
props.onEffortChange(choice.effort);
|
|
43
|
+
if (choice.latencyMode !== null) props.onLatencyModeChange(choice.latencyMode);
|
|
70
44
|
};
|
|
71
45
|
const modelRow = (row) => /* @__PURE__ */ jsx(
|
|
72
46
|
PickerNavRow,
|
|
@@ -169,12 +143,12 @@ function ModelPolicyPickerMenu(props) {
|
|
|
169
143
|
},
|
|
170
144
|
group.billingClass
|
|
171
145
|
)),
|
|
172
|
-
|
|
146
|
+
view.matchCount === 0 ? /* @__PURE__ */ jsx("p", { className: MENU_NOTE_CLASS, children: view.searching ? messages.noMatches : messages.noModels }) : null
|
|
173
147
|
] }) : props.connectModelsHref || rows.length > 0 ? /* @__PURE__ */ jsx(ConnectModelsPanel, { href: props.connectModelsHref, messages }) : /* @__PURE__ */ jsx("p", { className: MENU_NOTE_CLASS, children: messages.noModels })
|
|
174
148
|
}
|
|
175
149
|
),
|
|
176
|
-
|
|
177
|
-
|
|
150
|
+
view.anySelectable && selected && (view.unsupportedAttachments || view.thinking) ? /* @__PURE__ */ jsxs("div", { className: "border-t border-og-border px-2.5 py-2.5", children: [
|
|
151
|
+
view.unsupportedAttachments ? /* @__PURE__ */ jsx("p", { className: "pb-1.5 text-og-control leading-relaxed text-og-fg-subtle", children: messages.unsupportedAttachments }) : null,
|
|
178
152
|
/* @__PURE__ */ jsx(ModelThinkingControls, { ...props })
|
|
179
153
|
] }) : null
|
|
180
154
|
]
|
|
@@ -225,14 +199,13 @@ function ConnectModelsPanel(props) {
|
|
|
225
199
|
] });
|
|
226
200
|
}
|
|
227
201
|
function ModelThinkingControls(props) {
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const messages =
|
|
232
|
-
const
|
|
233
|
-
const showThinking =
|
|
234
|
-
const showFast =
|
|
235
|
-
if (!showThinking && !showFast) return null;
|
|
202
|
+
const view = modelPickerMenuView(props, "");
|
|
203
|
+
const thinking = view.thinking;
|
|
204
|
+
if (!view.selected || !thinking) return null;
|
|
205
|
+
const messages = view.messages;
|
|
206
|
+
const efforts = thinking.efforts;
|
|
207
|
+
const showThinking = thinking.showThinking;
|
|
208
|
+
const showFast = thinking.showFast;
|
|
236
209
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2 text-og-control", "data-testid": "model-picker-reasoning", children: [
|
|
237
210
|
/* @__PURE__ */ jsxs("div", { className: "flex min-h-7 items-center justify-between gap-3", children: [
|
|
238
211
|
showThinking ? /* @__PURE__ */ jsx("span", { className: "text-og-fg-subtle", children: messages.thinking }) : /* @__PURE__ */ jsx("span", {}),
|
|
@@ -241,7 +214,7 @@ function ModelThinkingControls(props) {
|
|
|
241
214
|
{
|
|
242
215
|
type: "button",
|
|
243
216
|
"data-testid": "model-picker-fast",
|
|
244
|
-
disabled: props.disabled ||
|
|
217
|
+
disabled: props.disabled || thinking.disabled,
|
|
245
218
|
"aria-pressed": props.latencyMode === "fast",
|
|
246
219
|
title: messages.fast + " \xB7 " + messages.fastRateHint,
|
|
247
220
|
onClick: () => props.onLatencyModeChange(props.latencyMode === "fast" ? "standard" : "fast"),
|
|
@@ -258,8 +231,8 @@ function ModelThinkingControls(props) {
|
|
|
258
231
|
RadioGroup.Root,
|
|
259
232
|
{
|
|
260
233
|
"aria-label": messages.thinkingEffort,
|
|
261
|
-
value:
|
|
262
|
-
disabled: props.disabled ||
|
|
234
|
+
value: thinking.value,
|
|
235
|
+
disabled: props.disabled || thinking.disabled,
|
|
263
236
|
onValueChange: (value) => props.onEffortChange(value),
|
|
264
237
|
orientation: "horizontal",
|
|
265
238
|
className: "flex flex-wrap gap-0.5 rounded-og-md bg-og-surface-2 p-0.5",
|
|
@@ -270,7 +243,7 @@ function ModelThinkingControls(props) {
|
|
|
270
243
|
"aria-label": labelReasoningEffort(effort),
|
|
271
244
|
title: labelReasoningEffort(effort),
|
|
272
245
|
className: "min-h-8 min-w-10 flex-1 cursor-pointer whitespace-nowrap rounded-og-sm px-1.5 text-og-control text-og-fg-muted outline-hidden transition-colors hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40 data-[state=checked]:bg-og-surface-1 data-[state=checked]:text-og-fg data-[state=checked]:shadow-sm disabled:cursor-not-allowed disabled:opacity-50",
|
|
273
|
-
children: effort
|
|
246
|
+
children: compactEffortLabel(effort, labelReasoningEffort(effort))
|
|
274
247
|
},
|
|
275
248
|
effort
|
|
276
249
|
))
|
|
@@ -317,4 +290,4 @@ export {
|
|
|
317
290
|
ModelPolicyPickerMenu,
|
|
318
291
|
ModelPolicyPickerPopover
|
|
319
292
|
};
|
|
320
|
-
//# sourceMappingURL=chunk-
|
|
293
|
+
//# sourceMappingURL=chunk-RGTZ2VDR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/model-policy-picker-menu.tsx"],"sourcesContent":["import type { ClientModel, ReasoningEffort } from \"@opengeni/sdk\";\nimport { ArrowRightIcon, CheckIcon, SearchIcon, ZapIcon } from \"lucide-react\";\nimport { useRef, useState, type RefObject, type CSSProperties } from \"react\";\nimport { Popover, RadioGroup } from \"radix-ui\";\nimport { cn } from \"../lib/cn\";\nimport {\n MENU_CHECK_CLASS,\n MENU_LABEL_CLASS,\n MENU_NOTE_CLASS,\n MENU_SURFACE_CLASS,\n} from \"../lib/menu-styles\";\nimport { labelReasoningEffort, type PickerModelRow } from \"../model-policy\";\nimport {\n compactEffortLabel,\n groupPresentationFor,\n modelPickerChoice,\n modelPickerMenuView,\n} from \"../model-picker-model\";\nimport {\n BillingClassMark,\n defaultModelPolicyPickerMessages,\n PickerNavRow,\n type ModelPolicyPickerProps,\n} from \"./model-policy-picker\";\nimport { ModelMark } from \"./model-mark\";\ntype ClientPickerModelRow = PickerModelRow<ClientModel>;\n\n/** Model selection stays flat; reasoning never becomes a navigation destination. */\nexport function ModelPolicyPickerMenu(props: ModelPolicyPickerProps) {\n const [query, setQuery] = useState(\"\");\n const view = modelPickerMenuView(props, query);\n const { messages, rows, groups } = view;\n const selected = view.selected;\n const choose = (row: ClientPickerModelRow) => {\n if (props.disabled) return;\n const choice = modelPickerChoice(props, row);\n if (!choice) return;\n if (choice.model !== null) props.onModelChange(choice.model);\n // Hosts may commit the combined model/effort draft through this callback.\n props.onEffortChange(choice.effort);\n if (choice.latencyMode !== null) props.onLatencyModeChange(choice.latencyMode);\n };\n const modelRow = (row: ClientPickerModelRow) => (\n <PickerNavRow\n key={row.id}\n icon={\n props.collapseScopes === false ? undefined : (\n <ModelMark model={row.catalog} className=\"size-4 text-og-fg-muted\" />\n )\n }\n label={row.label}\n hint={row.unavailableReason ?? row.fundingHint}\n disabled={props.disabled || !row.selectable}\n title={[row.label, row.unavailableReason ?? row.fundingHint].filter(Boolean).join(\" · \")}\n active={row.selectable && row.id === props.model}\n showChevron={false}\n trailing={\n row.catalog.cost === \"free\" || row.id === props.model ? (\n <span className=\"flex items-center gap-2\">\n {row.catalog.cost === \"free\" ? (\n <span className=\"rounded-full bg-og-surface-2 px-1.5 py-0.5 text-og-control text-og-fg-muted\">\n {messages.free}\n </span>\n ) : null}\n {row.id === props.model ? (\n <CheckIcon className={MENU_CHECK_CLASS} aria-label={messages.selected} />\n ) : null}\n </span>\n ) : null\n }\n testId={`model-picker-choice-${row.id}`}\n onClick={() => choose(row)}\n />\n );\n return (\n <div\n data-testid=\"model-picker-menu\"\n className=\"flex min-h-0 flex-col\"\n onKeyDown={(event) => {\n if (\n !(event.target instanceof HTMLButtonElement) ||\n ![\"ArrowDown\", \"ArrowUp\", \"Home\", \"End\"].includes(event.key)\n )\n return;\n const buttons = Array.from(\n event.currentTarget.querySelectorAll<HTMLButtonElement>(\n '[data-testid^=\"model-picker-choice-\"]:not(:disabled)',\n ),\n );\n const index = buttons.indexOf(event.target);\n if (index < 0) return;\n event.preventDefault();\n const next =\n event.key === \"Home\"\n ? 0\n : event.key === \"End\"\n ? buttons.length - 1\n : (index + (event.key === \"ArrowDown\" ? 1 : -1) + buttons.length) % buttons.length;\n buttons[next]?.focus();\n }}\n >\n {rows.some((row) => row.selectable) ? (\n <div className=\"border-b border-og-border py-1\">\n <label className=\"og-model-policy-search flex items-center gap-2 px-2.5 py-0.5\">\n <SearchIcon className=\"size-4 shrink-0 text-og-fg-subtle\" aria-hidden />\n <input\n aria-label={messages.searchLabel}\n placeholder={messages.searchPlaceholder}\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n onKeyDown={(event) => {\n if (event.key !== \"Escape\" && event.key !== \"Tab\") event.stopPropagation();\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n event.currentTarget\n .closest('[data-testid=\"model-picker-menu\"]')\n ?.querySelector<HTMLButtonElement>(\"button:not(:disabled)\")\n ?.focus();\n }\n }}\n className=\"og-model-policy-search-input h-8 min-w-0 flex-1 bg-transparent text-og-menu text-og-fg outline-hidden placeholder:text-og-fg-subtle\"\n />\n </label>\n </div>\n ) : null}\n {props.error ? (\n <p className={cn(MENU_NOTE_CLASS, \"text-og-sm text-og-status-failed\")} role=\"alert\">\n {props.error}\n </p>\n ) : null}\n <div\n className=\"min-h-0 flex-1 overflow-y-auto overscroll-contain py-1\"\n data-testid=\"model-picker-models\"\n >\n {props.loading ? (\n // Rows at the menu's row height, never a sentence, so nothing jumps.\n <div role=\"status\" aria-label={messages.loading}>\n {[58, 44, 66, 50].map((width) => (\n <div key={width} aria-hidden=\"true\" className=\"flex h-8 items-center gap-3 px-2.5\">\n <span className=\"size-4 shrink-0 animate-pulse rounded bg-og-surface-2\" />\n <span\n className=\"h-2.5 animate-pulse rounded bg-og-surface-2\"\n style={{ width: `${width}%` }}\n />\n </div>\n ))}\n </div>\n ) : rows.some((row) => row.selectable) ? (\n <>\n {groups.map((group) => (\n <section\n key={group.billingClass}\n aria-label={group.label}\n className=\"[&+section]:mt-1.5 [&+section]:border-t [&+section]:border-og-border [&+section]:pt-1.5\"\n >\n <div className={cn(MENU_LABEL_CLASS, \"flex items-center gap-2\")}>\n <BillingClassMark\n billingClass={group.billingClass}\n presentation={groupPresentationFor(props, group.billingClass)}\n aria-label=\"\"\n />\n <span className=\"min-w-0 break-words\">{group.label}</span>\n </div>\n {group.description ? (\n <p className=\"break-words px-2.5 pb-1 text-og-sm text-og-fg-muted\">\n {group.description}\n </p>\n ) : null}\n {group.rows.map(modelRow)}\n </section>\n ))}\n {view.matchCount === 0 ? (\n <p className={MENU_NOTE_CLASS}>\n {view.searching ? messages.noMatches : messages.noModels}\n </p>\n ) : null}\n </>\n ) : props.connectModelsHref || rows.length > 0 ? (\n <ConnectModelsPanel href={props.connectModelsHref} messages={messages} />\n ) : (\n <p className={MENU_NOTE_CLASS}>{messages.noModels}</p>\n )}\n </div>\n {view.anySelectable && selected && (view.unsupportedAttachments || view.thinking) ? (\n <div className=\"border-t border-og-border px-2.5 py-2.5\">\n {view.unsupportedAttachments ? (\n <p className=\"pb-1.5 text-og-control leading-relaxed text-og-fg-subtle\">\n {messages.unsupportedAttachments}\n </p>\n ) : null}\n <ModelThinkingControls {...props} />\n </div>\n ) : null}\n </div>\n );\n}\n\nconst CONNECT_MODEL_OPTIONS: Array<{\n billingClass: \"codex_subscription\" | \"supergrok_subscription\" | \"byok\" | \"external\";\n title: string;\n detail: string;\n}> = [\n { billingClass: \"codex_subscription\", title: \"Codex\", detail: \"ChatGPT\" },\n { billingClass: \"supergrok_subscription\", title: \"SuperGrok\", detail: \"xAI\" },\n { billingClass: \"byok\", title: \"AI Gateway\", detail: \"Vercel\" },\n { billingClass: \"external\", title: \"OpenRouter\", detail: \"API key\" },\n];\n\nfunction ConnectModelsPanel(props: {\n href: string | undefined;\n messages: typeof defaultModelPolicyPickerMessages;\n}) {\n return (\n <div className=\"px-1.5 pb-1.5 pt-2\" data-testid=\"model-picker-connect\">\n <div className=\"px-1.5 pb-3\">\n <p className=\"text-og-menu font-medium tracking-tight text-og-fg\">\n {props.messages.connectTitle}\n </p>\n <p className=\"mt-1 text-og-control leading-snug text-og-fg-subtle\">\n {props.messages.connectBody}\n </p>\n </div>\n <div className=\"grid grid-cols-2 gap-1\">\n {CONNECT_MODEL_OPTIONS.map((option) => {\n const content = (\n <>\n <span className=\"flex size-8 shrink-0 items-center justify-center rounded-og-md bg-og-surface-2 text-og-fg\">\n <BillingClassMark\n billingClass={option.billingClass}\n aria-label=\"\"\n className=\"size-4 text-og-fg\"\n />\n </span>\n <span className=\"min-w-0\">\n <span className=\"block truncate text-og-control font-medium text-og-fg\">\n {option.title}\n </span>\n <span className=\"block truncate text-og-control text-og-fg-subtle\">\n {option.detail}\n </span>\n </span>\n </>\n );\n const className =\n \"flex min-w-0 items-center gap-2 rounded-og-md px-1.5 py-1.5 outline-hidden transition-colors hover:bg-og-hover focus-visible:ring-2 focus-visible:ring-og-accent/40\";\n return props.href ? (\n <a key={option.title} href={props.href} className={className}>\n {content}\n </a>\n ) : (\n <div key={option.title} className={className}>\n {content}\n </div>\n );\n })}\n </div>\n {props.href ? (\n <a\n href={props.href}\n className=\"mt-2 flex h-9 w-full items-center justify-center gap-1.5 rounded-og-md border border-og-primary-border bg-og-primary text-og-primary-fg hover:bg-og-primary-hover text-og-control font-medium outline-hidden transition-colors focus-visible:ring-2 focus-visible:ring-og-accent/40\"\n >\n {props.messages.connectAction}\n <ArrowRightIcon className=\"size-3.5\" aria-hidden />\n </a>\n ) : (\n <p className=\"px-1.5 pt-3 text-og-control text-og-fg-subtle\">{props.messages.noModels}</p>\n )}\n </div>\n );\n}\n\nfunction ModelThinkingControls(props: ModelPolicyPickerProps) {\n const view = modelPickerMenuView(props, \"\");\n const thinking = view.thinking;\n if (!view.selected || !thinking) return null;\n const messages = view.messages;\n const efforts = thinking.efforts;\n const showThinking = thinking.showThinking;\n const showFast = thinking.showFast;\n return (\n <div className=\"space-y-2 text-og-control\" data-testid=\"model-picker-reasoning\">\n <div className=\"flex min-h-7 items-center justify-between gap-3\">\n {showThinking ? <span className=\"text-og-fg-subtle\">{messages.thinking}</span> : <span />}\n {showFast ? (\n <button\n type=\"button\"\n data-testid=\"model-picker-fast\"\n disabled={props.disabled || thinking.disabled}\n aria-pressed={props.latencyMode === \"fast\"}\n title={messages.fast + \" · \" + messages.fastRateHint}\n onClick={() =>\n props.onLatencyModeChange(props.latencyMode === \"fast\" ? \"standard\" : \"fast\")\n }\n className=\"flex min-h-8 shrink-0 items-center gap-1.5 whitespace-nowrap rounded-og-sm px-2 text-og-fg-muted hover:bg-og-hover focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:opacity-50\"\n >\n <ZapIcon className={cn(\"size-3.5\", props.latencyMode === \"fast\" && \"fill-current\")} />\n {messages.fast}\n <span className=\"text-og-fg-subtle\">{messages.fastRateHint}</span>\n </button>\n ) : null}\n </div>\n {showThinking ? (\n <RadioGroup.Root\n aria-label={messages.thinkingEffort}\n value={thinking.value}\n disabled={props.disabled || thinking.disabled}\n onValueChange={(value) => props.onEffortChange(value as ReasoningEffort)}\n orientation=\"horizontal\"\n className=\"flex flex-wrap gap-0.5 rounded-og-md bg-og-surface-2 p-0.5\"\n >\n {efforts.map((effort) => (\n <RadioGroup.Item\n key={effort}\n value={effort}\n aria-label={labelReasoningEffort(effort)}\n title={labelReasoningEffort(effort)}\n className=\"min-h-8 min-w-10 flex-1 cursor-pointer whitespace-nowrap rounded-og-sm px-1.5 text-og-control text-og-fg-muted outline-hidden transition-colors hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40 data-[state=checked]:bg-og-surface-1 data-[state=checked]:text-og-fg data-[state=checked]:shadow-sm disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {compactEffortLabel(effort, labelReasoningEffort(effort))}\n </RadioGroup.Item>\n ))}\n </RadioGroup.Root>\n ) : null}\n </div>\n );\n}\n\nexport function ModelPolicyPickerPopover(\n props: ModelPolicyPickerProps & {\n anchor: RefObject<HTMLButtonElement | null>;\n contentId: string;\n portalStyle: CSSProperties;\n },\n) {\n const outside = useRef(false);\n const messages = { ...defaultModelPolicyPickerMessages, ...props.messages };\n return (\n <Popover.Root open onOpenChange={(open) => props.onOpenChange?.(open)}>\n <Popover.Anchor virtualRef={props.anchor} />\n <Popover.Portal>\n <Popover.Content\n id={props.contentId}\n aria-label={messages.label}\n align=\"start\"\n side={props.menuSide ?? \"bottom\"}\n sideOffset={8}\n collisionPadding={12}\n onInteractOutside={(event) => {\n if (props.anchor.current?.contains(event.target as Node)) event.preventDefault();\n else outside.current = true;\n }}\n onCloseAutoFocus={(event) => {\n event.preventDefault();\n if (!outside.current) props.anchor.current?.focus();\n }}\n className={cn(\n MENU_SURFACE_CLASS,\n \"og-root og-model-policy-menu z-50 flex max-h-[min(32rem,var(--radix-popover-content-available-height))] w-[22rem] max-w-[calc(100vw-16px)] flex-col overflow-hidden p-[var(--og-model-picker-menu-padding)]\",\n props.contentClassName,\n )}\n style={{ ...props.portalStyle, ...props.contentStyle }}\n data-testid=\"model-picker-content\"\n >\n <ModelPolicyPickerMenu {...props} />\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n );\n}\n"],"mappings":"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","names":[]}
|