@opengeni/react 1.4.4 → 1.4.5-canary.37458084490001
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-3ZC6QPOM.js +174 -0
- package/dist/chunk-3ZC6QPOM.js.map +1 -0
- package/dist/{chunk-YVFRBXST.js → chunk-4BCVCJSU.js} +2 -2
- 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-I6OY3MWC.js → chunk-6FOTSVWU.js} +2 -2
- package/dist/{chunk-IUHHPMAX.js → chunk-7RRBX5EM.js} +14 -85
- package/dist/chunk-7RRBX5EM.js.map +1 -0
- package/dist/{chunk-L2J3PU7A.js → chunk-7ZB7I3KP.js} +24 -98
- package/dist/chunk-7ZB7I3KP.js.map +1 -0
- 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-IYQCWGU5.js → chunk-GHJU7XG7.js} +35 -62
- package/dist/chunk-GHJU7XG7.js.map +1 -0
- package/dist/{chunk-G6YRCIYJ.js → chunk-HNVWMDNN.js} +55 -60
- package/dist/chunk-HNVWMDNN.js.map +1 -0
- 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-XS67YG5R.js → chunk-IX3K4THH.js} +24 -3
- package/dist/chunk-IX3K4THH.js.map +1 -0
- 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-C5BF4L26.js → chunk-KHF2VRXF.js} +7 -7
- package/dist/{chunk-QMMCJGFI.js → chunk-L5OKM2VX.js} +2 -2
- package/dist/chunk-LHF6BVM4.js +83 -0
- package/dist/chunk-LHF6BVM4.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-RI42H5IU.js +326 -0
- package/dist/chunk-RI42H5IU.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-EAOSEIXB.js → chunk-TZQSHCZN.js} +692 -1996
- package/dist/chunk-TZQSHCZN.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-3ZFWWJ6O.js} +6 -4
- package/dist/{embedded-voice-NIL4RDX3.js.map → embedded-voice-3ZFWWJ6O.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/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-SWC6QEVN.js} +3 -3
- package/dist/lib/clipboard.d.ts +7 -0
- package/dist/lib/provider-recovery.d.ts +49 -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-NM4RPTY6.js} +6 -4
- package/dist/model-policy-picker-menu-NM4RPTY6.js.map +1 -0
- package/dist/model-policy.d.ts +10 -0
- package/dist/model-policy.js +5 -1
- 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-RCVCMXG7.js} +5 -5
- package/dist/sandbox-files-RCVCMXG7.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-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 +96 -0
- package/dist/session-list-model.js +219 -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 +47 -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 +4 -144
- 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 +15 -148
- 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/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/model-mark-paths.ts +53 -0
- package/src/model-picker-model.ts +330 -0
- package/src/model-policy.ts +43 -2
- 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-attention-model.ts +59 -0
- package/src/session-feedback-model.ts +95 -0
- package/src/session-list-model.ts +327 -0
- package/src/session-status-model.ts +62 -0
- package/src/testing/session-scenarios.ts +326 -0
- package/src/timeline/activity-rail.tsx +5 -17
- package/src/timeline/genie-copy.ts +19 -0
- package/src/timeline/genie-loading.tsx +13 -18
- 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/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 +226 -1025
- 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 +3 -0
- package/styles/connect.css +4 -0
- 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-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-YVFRBXST.js.map → chunk-4BCVCJSU.js.map} +0 -0
- /package/dist/{chunk-I6OY3MWC.js.map → chunk-6FOTSVWU.js.map} +0 -0
- /package/dist/{chunk-PBCZL4JP.js.map → chunk-INIZSNXT.js.map} +0 -0
- /package/dist/{chunk-C5BF4L26.js.map → chunk-KHF2VRXF.js.map} +0 -0
- /package/dist/{chunk-QMMCJGFI.js.map → chunk-L5OKM2VX.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-SWC6QEVN.js.map} +0 -0
- /package/dist/{sandbox-files-34CJJNOY.js.map → model-mark-paths.js.map} +0 -0
|
@@ -3,16 +3,25 @@ import {
|
|
|
3
3
|
MENU_CHEVRON_CLASS
|
|
4
4
|
} from "./chunk-PMV53IMM.js";
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
CHATGPT_MARK_PATH,
|
|
7
|
+
CLAUDE_MARK_PATH,
|
|
8
|
+
GROK_MARK_PATH
|
|
9
|
+
} from "./chunk-N7S72EXK.js";
|
|
10
|
+
import {
|
|
11
|
+
billingClassForMissingSelection,
|
|
12
|
+
defaultModelPolicyPickerMessages,
|
|
13
|
+
effectiveRows,
|
|
14
|
+
groupPresentationFor
|
|
15
|
+
} from "./chunk-3ZC6QPOM.js";
|
|
12
16
|
import {
|
|
13
17
|
usePortalTokenSource,
|
|
14
18
|
usePortalTokenStyle
|
|
15
19
|
} from "./chunk-XEA5BCMA.js";
|
|
20
|
+
import {
|
|
21
|
+
findPickerRow,
|
|
22
|
+
labelReasoningEffort,
|
|
23
|
+
modelOffersEffortChoice
|
|
24
|
+
} from "./chunk-IX3K4THH.js";
|
|
16
25
|
import {
|
|
17
26
|
cn
|
|
18
27
|
} from "./chunk-TXS65BB2.js";
|
|
@@ -20,13 +29,13 @@ import {
|
|
|
20
29
|
// src/components/claude-mark.tsx
|
|
21
30
|
import { jsx } from "react/jsx-runtime";
|
|
22
31
|
function ClaudeMark(props) {
|
|
23
|
-
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx("path", { d:
|
|
32
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx("path", { d: CLAUDE_MARK_PATH }) });
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
// src/components/grok-mark.tsx
|
|
27
36
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
28
37
|
function GrokMark(props) {
|
|
29
|
-
return /* @__PURE__ */ jsx2("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx2("path", { d:
|
|
38
|
+
return /* @__PURE__ */ jsx2("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx2("path", { d: GROK_MARK_PATH }) });
|
|
30
39
|
}
|
|
31
40
|
|
|
32
41
|
// src/components/model-mark.tsx
|
|
@@ -39,7 +48,7 @@ import { SparklesIcon } from "lucide-react";
|
|
|
39
48
|
import { useState } from "react";
|
|
40
49
|
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
41
50
|
function ChatGptMark(props) {
|
|
42
|
-
return /* @__PURE__ */ jsx3("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx3("path", { d:
|
|
51
|
+
return /* @__PURE__ */ jsx3("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx3("path", { d: CHATGPT_MARK_PATH }) });
|
|
43
52
|
}
|
|
44
53
|
var MARKED_VENDORS = /* @__PURE__ */ new Set(["openai", "anthropic", "xai"]);
|
|
45
54
|
function modelHasMark(model) {
|
|
@@ -103,39 +112,10 @@ import {
|
|
|
103
112
|
} from "react";
|
|
104
113
|
import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
105
114
|
var LazyModelPolicyPickerMenu = lazy(
|
|
106
|
-
() => import("./model-policy-picker-menu-
|
|
115
|
+
() => import("./model-policy-picker-menu-NM4RPTY6.js").then(({ ModelPolicyPickerPopover }) => ({
|
|
107
116
|
default: ModelPolicyPickerPopover
|
|
108
117
|
}))
|
|
109
118
|
);
|
|
110
|
-
var defaultModelPolicyPickerMessages = {
|
|
111
|
-
label: "Model and effort",
|
|
112
|
-
loading: "Loading model catalog\u2026",
|
|
113
|
-
noModels: "No models available.",
|
|
114
|
-
connectTitle: "Connect a model",
|
|
115
|
-
connectBody: "Use a subscription or a provider key you already have.",
|
|
116
|
-
connectAction: "Open Models",
|
|
117
|
-
thinking: "Thinking",
|
|
118
|
-
fast: "Fast",
|
|
119
|
-
fastRateHint: "2\xD7 rate",
|
|
120
|
-
codexOnly: "Codex-only session",
|
|
121
|
-
searchLabel: "Search models or providers",
|
|
122
|
-
searchPlaceholder: "Search models or providers\u2026",
|
|
123
|
-
currentModel: "Current model",
|
|
124
|
-
noMatches: "No matching models. Try a model or provider name.",
|
|
125
|
-
unsupportedAttachments: "This model cannot view the attached images.",
|
|
126
|
-
thinkingEffort: "Thinking effort",
|
|
127
|
-
selected: "Selected",
|
|
128
|
-
free: "Free",
|
|
129
|
-
billingHints: {
|
|
130
|
-
opengeni_credits: "Provided by Opengeni",
|
|
131
|
-
external: "Provider terms and limits apply",
|
|
132
|
-
codex_subscription: "ChatGPT / Codex plan",
|
|
133
|
-
supergrok_subscription: "SuperGrok / xAI plan",
|
|
134
|
-
claude_subscription: "Claude plan",
|
|
135
|
-
byok: "Billed to the connected provider account",
|
|
136
|
-
organization_byok: "Billed to the connected provider account"
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
119
|
var SLIDE_EASE = [0.22, 1, 0.36, 1];
|
|
140
120
|
function BillingClassMark(props) {
|
|
141
121
|
const labels = {
|
|
@@ -165,31 +145,6 @@ function BillingClassMark(props) {
|
|
|
165
145
|
}
|
|
166
146
|
);
|
|
167
147
|
}
|
|
168
|
-
function isCodexModel(model) {
|
|
169
|
-
return model.id.startsWith("codex/") || model.source === "codex";
|
|
170
|
-
}
|
|
171
|
-
function billingClassForMissingSelection(modelId) {
|
|
172
|
-
if (modelId.startsWith("workspace-claude-subscription/")) return "claude_subscription";
|
|
173
|
-
if (modelId.startsWith("workspace-anthropic/")) return "byok";
|
|
174
|
-
if (modelId.startsWith("organization-claude-subscription/")) return "claude_subscription";
|
|
175
|
-
if (modelId.startsWith("organization-anthropic/")) return "organization_byok";
|
|
176
|
-
if (modelId.startsWith("workspace-gateway/")) return "byok";
|
|
177
|
-
if (modelId.startsWith("workspace-openrouter/")) return "byok";
|
|
178
|
-
if (modelId.startsWith("openrouter/")) return "opengeni_credits";
|
|
179
|
-
if (modelId.startsWith("codex/")) return "codex_subscription";
|
|
180
|
-
if (modelId.startsWith("supergrok/")) return "supergrok_subscription";
|
|
181
|
-
return "opengeni_credits";
|
|
182
|
-
}
|
|
183
|
-
function applyCodexOnly(rows, codexOnly, unavailableReason) {
|
|
184
|
-
if (!codexOnly) return rows;
|
|
185
|
-
return rows.map(
|
|
186
|
-
(row) => isCodexModel(row.catalog) ? row : {
|
|
187
|
-
...row,
|
|
188
|
-
selectable: false,
|
|
189
|
-
unavailableReason: row.unavailableReason ?? unavailableReason
|
|
190
|
-
}
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
148
|
function SelectedModelMark(input) {
|
|
194
149
|
const billingClass = input.selected?.billingClass ?? billingClassForMissingSelection(input.props.model);
|
|
195
150
|
const presentation = groupPresentationFor(input.props, billingClass);
|
|
@@ -224,17 +179,6 @@ var SCOPED_MARK_LABELS = {
|
|
|
224
179
|
byok: "Workspace provider account",
|
|
225
180
|
organization_byok: "Organization provider account"
|
|
226
181
|
};
|
|
227
|
-
var SCOPED_BILLING_HINTS = {
|
|
228
|
-
byok: "Billed to the workspace provider account",
|
|
229
|
-
organization_byok: "Billed to the organization provider account"
|
|
230
|
-
};
|
|
231
|
-
function groupPresentationFor(props, billingClass) {
|
|
232
|
-
const own = props.groupPresentation?.[billingClass];
|
|
233
|
-
if (own !== void 0 || props.collapseScopes === false) return own;
|
|
234
|
-
if (billingClass === "byok") return props.groupPresentation?.organization_byok;
|
|
235
|
-
if (billingClass === "organization_byok") return props.groupPresentation?.byok;
|
|
236
|
-
return void 0;
|
|
237
|
-
}
|
|
238
182
|
function fallbackName(props) {
|
|
239
183
|
return props.collapseScopes === false ? props.model : modelDisplayName2(props.model);
|
|
240
184
|
}
|
|
@@ -243,22 +187,8 @@ var BRANDED_BILLING_CLASSES = /* @__PURE__ */ new Set([
|
|
|
243
187
|
"claude_subscription",
|
|
244
188
|
"supergrok_subscription"
|
|
245
189
|
]);
|
|
246
|
-
function
|
|
247
|
-
|
|
248
|
-
const messages = { ...defaultModelPolicyPickerMessages, ...props.messages };
|
|
249
|
-
return applyCodexOnly(rows, props.codexOnly === true, messages.codexOnly).map((row) => {
|
|
250
|
-
const scoped = props.collapseScopes === false ? {
|
|
251
|
-
...row,
|
|
252
|
-
label: row.catalog.label,
|
|
253
|
-
billingClassLabel: scopedBillingClassLabel(row.billingClass)
|
|
254
|
-
} : row;
|
|
255
|
-
if (props.collapseScopes === false) {
|
|
256
|
-
if (row.catalog.shortLabel) scoped.shortLabel = row.catalog.shortLabel;
|
|
257
|
-
else delete scoped.shortLabel;
|
|
258
|
-
}
|
|
259
|
-
const label = groupPresentationFor(props, row.billingClass)?.label;
|
|
260
|
-
return label === void 0 ? scoped : { ...scoped, billingClassLabel: label };
|
|
261
|
-
});
|
|
190
|
+
function effectiveRows2(props) {
|
|
191
|
+
return effectiveRows(props);
|
|
262
192
|
}
|
|
263
193
|
function PickerNavRow(props) {
|
|
264
194
|
return /* @__PURE__ */ jsxs2(
|
|
@@ -327,7 +257,7 @@ function useModelPolicyPickerState(props) {
|
|
|
327
257
|
if (props.open === void 0) setUncontrolledOpen(next);
|
|
328
258
|
props.onOpenChange?.(next);
|
|
329
259
|
};
|
|
330
|
-
return { open, setOpen, rows:
|
|
260
|
+
return { open, setOpen, rows: effectiveRows2(props) };
|
|
331
261
|
}
|
|
332
262
|
function ModelPolicyPicker(props) {
|
|
333
263
|
const contentId = useId();
|
|
@@ -420,7 +350,7 @@ function ModelPolicyPicker(props) {
|
|
|
420
350
|
needsModel ? /* @__PURE__ */ jsx4(SparklesIcon2, { className: "size-3.5 shrink-0", "aria-hidden": true }) : /* @__PURE__ */ jsx4(SelectedModelMark, { props, selected }),
|
|
421
351
|
/* @__PURE__ */ jsx4("span", { className: "og-model-policy-label-full min-w-0 truncate font-medium text-og-fg max-sm:hidden @max-[20rem]/model-controls:hidden", children: needsModel ? messages.connectTitle : selected?.label ?? fallbackName(props) }),
|
|
422
352
|
/* @__PURE__ */ jsx4("span", { className: "og-model-policy-label-short min-w-0 truncate font-medium text-og-fg sm:hidden @max-[20rem]/model-controls:block", children: needsModel ? messages.connectTitle : selected?.shortLabel ?? selected?.label ?? fallbackName(props) }),
|
|
423
|
-
selected && !needsModel &&
|
|
353
|
+
selected && !needsModel && modelOffersEffortChoice(selected.catalog) ? /* @__PURE__ */ jsx4(
|
|
424
354
|
"span",
|
|
425
355
|
{
|
|
426
356
|
className: "og-model-policy-effort min-w-0 shrink-[9999] truncate",
|
|
@@ -460,14 +390,10 @@ export {
|
|
|
460
390
|
modelHasMark,
|
|
461
391
|
ModelMark,
|
|
462
392
|
ModelName,
|
|
463
|
-
defaultModelPolicyPickerMessages,
|
|
464
393
|
BillingClassMark,
|
|
465
|
-
SCOPED_BILLING_HINTS,
|
|
466
|
-
groupPresentationFor,
|
|
467
|
-
effectiveRows,
|
|
468
394
|
PickerNavRow,
|
|
469
395
|
PickerBackHeader,
|
|
470
396
|
PickerAnimatedPage,
|
|
471
397
|
ModelPolicyPicker
|
|
472
398
|
};
|
|
473
|
-
//# sourceMappingURL=chunk-
|
|
399
|
+
//# sourceMappingURL=chunk-7ZB7I3KP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/claude-mark.tsx","../src/components/grok-mark.tsx","../src/components/model-mark.tsx","../src/components/model-policy-picker.tsx"],"sourcesContent":["import { CLAUDE_MARK_PATH } from \"../model-mark-paths\";\nimport type { SVGProps } from \"react\";\n\n/** ClaudeMark: Simple Icons, CC0; https://github.com/simple-icons/simple-icons */\nexport function ClaudeMark(props: SVGProps<SVGSVGElement>) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" {...props}>\n <path d={CLAUDE_MARK_PATH} />\n </svg>\n );\n}\n","import { GROK_MARK_PATH } from \"../model-mark-paths\";\nimport type { SVGProps } from \"react\";\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 function GrokMark(props: SVGProps<SVGSVGElement>) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" {...props}>\n <path d={GROK_MARK_PATH} />\n </svg>\n );\n}\n","import { CHATGPT_MARK_PATH } from \"../model-mark-paths\";\nimport {\n modelDisplayName,\n modelLogoUrl,\n modelVendor,\n type ModelDisplayInput,\n type ModelVendor,\n} from \"@opengeni/sdk/model-display\";\nimport { SparklesIcon } from \"lucide-react\";\nimport { useState, type ReactNode, type SVGProps } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { ClaudeMark } from \"./claude-mark\";\nimport { GrokMark } from \"./grok-mark\";\n\n/** ChatGPT / OpenAI mark (Simple Icons path), currentColor like the other marks. */\nexport function ChatGptMark(props: SVGProps<SVGSVGElement>) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" {...props}>\n <path d={CHATGPT_MARK_PATH} />\n </svg>\n );\n}\n\nconst MARKED_VENDORS: ReadonlySet<ModelVendor> = new Set([\"openai\", \"anthropic\", \"xai\"]);\n\n/** True when `ModelMark` has a real maker logo for this model (not the neutral fallback). */\nexport function modelHasMark(model: ModelDisplayInput): boolean {\n const vendor = modelVendor(model);\n return modelLogoUrl(model) !== null || (vendor !== null && MARKED_VENDORS.has(vendor));\n}\n\n/**\n * The catalog's maker logo, with bundled maker logos and a neutral fallback.\n * Makers without a configured or bundled logo get a neutral mark, so an org- and\n * a workspace-connected copy of one model always look the same.\n */\nexport function ModelMark(props: {\n model: ModelDisplayInput;\n className?: string | undefined;\n /** Shown when the maker has no bundled logo. Defaults to a neutral sparkle. */\n fallback?: ReactNode;\n \"aria-label\"?: string | undefined;\n}) {\n const logoUrl = modelLogoUrl(props.model);\n const [failedUrl, setFailedUrl] = useState<string | null>(null);\n const vendor = modelVendor(props.model);\n const className = cn(\"size-3.5 shrink-0\", props.className);\n const label = props[\"aria-label\"];\n const a11y = label ? { role: \"img\" as const, \"aria-label\": label } : { \"aria-hidden\": true };\n const mark =\n logoUrl && logoUrl !== failedUrl ? (\n <img\n src={logoUrl}\n alt=\"\"\n className=\"size-full object-contain\"\n referrerPolicy=\"no-referrer\"\n onError={() => setFailedUrl(logoUrl)}\n />\n ) : vendor === \"openai\" ? (\n <ChatGptMark className=\"size-full\" />\n ) : vendor === \"anthropic\" ? (\n <ClaudeMark className=\"size-full\" />\n ) : vendor === \"xai\" ? (\n <GrokMark className=\"size-full\" />\n ) : props.fallback !== undefined ? (\n props.fallback\n ) : (\n <SparklesIcon className=\"size-full\" aria-hidden />\n );\n if (mark === null) return null;\n return (\n <span\n className={cn(\"inline-flex items-center justify-center [&>svg]:size-full\", className)}\n data-model-vendor={vendor ?? \"unknown\"}\n {...a11y}\n >\n {mark}\n </span>\n );\n}\n\n/**\n * A model as people should see it outside model settings: the maker's mark and\n * the clean display name. Never a routing prefix, connection id or scope.\n */\nexport function ModelName(props: {\n model: ModelDisplayInput;\n /** Hide the maker mark for dense text-only contexts. */\n mark?: boolean | undefined;\n className?: string | undefined;\n markClassName?: string | undefined;\n}) {\n const name = modelDisplayName(props.model);\n return (\n <span className={cn(\"inline-flex min-w-0 items-center gap-1.5\", props.className)} title={name}>\n {props.mark === false ? null : (\n <ModelMark model={props.model} className={props.markClassName} />\n )}\n <span className=\"min-w-0 truncate\">{name}</span>\n </span>\n );\n}\n","import { ClaudeMark } from \"./claude-mark\";\nimport { GrokMark } from \"./grok-mark\";\nimport { ChatGptMark, ModelMark, modelHasMark } from \"./model-mark\";\nimport { modelDisplayName, modelLogoUrl } from \"@opengeni/sdk/model-display\";\nimport type { ClientModel, LatencyMode, ReasoningEffort } from \"@opengeni/sdk\";\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n Globe2Icon,\n KeyRoundIcon,\n SparklesIcon,\n ZapIcon,\n} from \"lucide-react\";\nimport { motion, useReducedMotion } from \"motion/react\";\nimport {\n Suspense,\n lazy,\n useMemo,\n useId,\n useState,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../lib/cn\";\nimport {\n billingClassForMissingSelection,\n defaultModelPolicyPickerMessages,\n effectiveRows as sharedEffectiveRows,\n groupPresentationFor,\n SCOPED_BILLING_HINTS,\n type ModelPickerGroupPresentation,\n type ModelPolicyPickerMessages,\n} from \"../model-picker-model\";\nimport { MENU_CHEVRON_CLASS } from \"../lib/menu-styles\";\nimport { usePortalTokenSource, usePortalTokenStyle } from \"../lib/use-portal-token-style\";\nimport {\n findPickerRow,\n labelReasoningEffort,\n modelOffersEffortChoice,\n type PickerBillingClass,\n type PickerModelRow,\n} from \"../model-policy\";\n\nconst LazyModelPolicyPickerMenu = lazy(() =>\n import(\"./model-policy-picker-menu\").then(({ ModelPolicyPickerPopover }) => ({\n default: ModelPolicyPickerPopover,\n })),\n);\n\ntype ClientPickerModelRow = PickerModelRow<ClientModel>;\n\n/** Presentation only; never changes model identity, billing or availability. */\nexport type ModelPolicyPickerGroupPresentation = ModelPickerGroupPresentation<ReactNode>;\n\nexport { defaultModelPolicyPickerMessages, groupPresentationFor, SCOPED_BILLING_HINTS };\nexport type { ModelPolicyPickerMessages };\n\nexport type ModelPolicyPickerProps = {\n /** Host branding for payment-source groups, shared by menu and trigger. */\n groupPresentation?: ModelPolicyPickerGroupPresentation | undefined;\n /** Lightweight deployment models. Catalog rows take precedence when supplied. */\n models?: ClientModel[] | undefined;\n /** Warn only when the draft actually contains images this model cannot view. */\n hasImageAttachments?: boolean | undefined;\n /** Catalog-backed rows with availability and billing-class truth. */\n rows?: PickerModelRow[] | undefined;\n model: string;\n effort: ReasoningEffort;\n latencyMode: LatencyMode;\n disabled?: boolean | undefined;\n loading?: boolean | undefined;\n error?: string | null | undefined;\n /** Controlled menu state. Omit for the built-in uncontrolled behavior. */\n open?: boolean | undefined;\n /** Initial menu state when `open` is uncontrolled. */\n defaultOpen?: boolean | undefined;\n onOpenChange?: ((open: boolean) => void) | undefined;\n /** Non-Codex models stay visible but cannot be selected. */\n codexOnly?: boolean | undefined;\n /** Identity of the current session scope. */\n sessionKey?: string | undefined;\n /** Prefer bottom on new-chat surfaces and top for bottom-docked composers. */\n menuSide?: \"top\" | \"bottom\" | undefined;\n /**\n * Default true: show models the way people choose them, with clean names,\n * maker marks, one \"API keys\" group for organization- and workspace-connected\n * keys, and one row for identical copies. Models settings passes false to\n * keep its scope-aware presentation (raw catalog labels, scoped groups).\n */\n collapseScopes?: boolean | undefined;\n /** Hide latency controls on surfaces whose saved policy does not include latency. */\n allowLatencyMode?: boolean | undefined;\n /** Settings → Models. Shown when the catalog has no model that can run. */\n connectModelsHref?: string | undefined;\n /** Classes for the portalled menu surface. Prefer --og-* tokens for theming. */\n contentClassName?: string | undefined;\n /** Inline styles for the portalled menu, applied after inherited --og-* tokens. */\n contentStyle?: CSSProperties | undefined;\n className?: string | undefined;\n /**\n * \"pill\" (default) is the composer's quiet rounded trigger with the effort.\n * \"field\" is a settings control: a bordered rectangle with the model name\n * and `triggerMeta` (for example the payer) in muted text. The effort stays\n * in the menu.\n */\n triggerStyle?: \"pill\" | \"field\" | undefined;\n /** Muted text after the model name in the \"field\" trigger. */\n triggerMeta?: ReactNode;\n messages?: Partial<ModelPolicyPickerMessages> | undefined;\n onModelChange: (modelId: string) => void;\n onEffortChange: (effort: ReasoningEffort) => void;\n onLatencyModeChange: (latencyMode: LatencyMode) => void;\n};\n\nconst SLIDE_EASE = [0.22, 1, 0.36, 1] as const;\n\nexport function BillingClassMark(props: {\n billingClass: PickerBillingClass;\n presentation?: ModelPolicyPickerGroupPresentation[PickerBillingClass] | undefined;\n className?: string | undefined;\n \"aria-label\"?: string | undefined;\n}) {\n const labels: Record<PickerBillingClass, string> = {\n opengeni_credits: \"Models\",\n external: \"External provider\",\n codex_subscription: \"Codex\",\n supergrok_subscription: \"SuperGrok\",\n claude_subscription: \"Claude\",\n byok: \"API key\",\n organization_byok: \"API key\",\n };\n if (props.presentation?.icon === null) return null;\n const label = props[\"aria-label\"] ?? props.presentation?.label ?? labels[props.billingClass];\n const accessibility =\n label.length === 0\n ? { \"aria-hidden\": true as const }\n : { role: \"img\" as const, \"aria-label\": label };\n const shell = cn(\n \"inline-flex size-3.5 shrink-0 items-center justify-center overflow-hidden text-og-fg-subtle [&>svg]:size-full [&>img]:size-full\",\n props.className,\n );\n const mark = \"size-3.5\";\n return (\n <span\n className={shell}\n data-testid={`billing-class-icon-${props.billingClass}`}\n {...accessibility}\n >\n {props.presentation?.icon !== undefined ? (\n props.presentation.icon\n ) : props.billingClass === \"opengeni_credits\" ? (\n <SparklesIcon className={mark} aria-hidden />\n ) : props.billingClass === \"external\" ? (\n <Globe2Icon className={mark} aria-hidden />\n ) : props.billingClass === \"codex_subscription\" ? (\n <ChatGptMark className={mark} />\n ) : props.billingClass === \"claude_subscription\" ? (\n <ClaudeMark className={mark} />\n ) : props.billingClass === \"supergrok_subscription\" ? (\n <GrokMark className={mark} />\n ) : (\n <KeyRoundIcon className={mark} aria-hidden />\n )}\n </span>\n );\n}\n\n/**\n * The trigger shows who makes the chosen model. Subscription rails already\n * carry their maker's mark (ChatGPT, Claude, Grok). Configured catalog logos win\n * in collapsed model presentation; otherwise explicit host branding wins and models show\n * the maker's logo instead of a generic key, falling back to the group mark.\n */\nfunction SelectedModelMark(input: {\n props: ModelPolicyPickerProps;\n selected: ClientPickerModelRow | null;\n}) {\n const billingClass =\n input.selected?.billingClass ?? billingClassForMissingSelection(input.props.model);\n const presentation = groupPresentationFor(input.props, billingClass);\n const model = input.selected?.catalog ?? input.props.model;\n if (input.props.collapseScopes === false) {\n return (\n <BillingClassMark\n billingClass={billingClass}\n presentation={presentation}\n aria-label={presentation?.label ?? SCOPED_MARK_LABELS[billingClass]}\n className=\"text-og-fg\"\n />\n );\n }\n if (modelLogoUrl(model)) {\n return <ModelMark model={model} className=\"text-og-fg\" />;\n }\n if (\n presentation?.icon !== undefined ||\n BRANDED_BILLING_CLASSES.has(billingClass) ||\n !modelHasMark(model)\n ) {\n return (\n <BillingClassMark\n billingClass={billingClass}\n presentation={presentation}\n className=\"text-og-fg\"\n />\n );\n }\n return <ModelMark model={model} className=\"text-og-fg\" />;\n}\n\nconst SCOPED_MARK_LABELS: Partial<Record<PickerBillingClass, string>> = {\n byok: \"Workspace provider account\",\n organization_byok: \"Organization provider account\",\n};\n\n/** A selection the catalog no longer lists: its clean name (settings keep the id). */\nfunction fallbackName(props: ModelPolicyPickerProps): string {\n return props.collapseScopes === false ? props.model : modelDisplayName(props.model);\n}\n\nconst BRANDED_BILLING_CLASSES: ReadonlySet<PickerBillingClass> = new Set([\n \"codex_subscription\",\n \"claude_subscription\",\n \"supergrok_subscription\",\n]);\n\nexport function effectiveRows(props: ModelPolicyPickerProps): ClientPickerModelRow[] {\n return sharedEffectiveRows(props);\n}\n\nexport function PickerNavRow(props: {\n label: string;\n hint?: string | undefined;\n icon?: ReactNode;\n trailing?: ReactNode;\n showChevron?: boolean | undefined;\n disabled?: boolean | undefined;\n title?: string | undefined;\n description?: string | undefined;\n active?: boolean | undefined;\n testId?: string | undefined;\n onClick: () => void;\n}) {\n return (\n <button\n type=\"button\"\n disabled={props.disabled}\n title={props.title}\n aria-description={props.description}\n onClick={props.onClick}\n data-testid={props.testId}\n className={cn(\n // The one menu row (lib/menu-styles.ts), with density tokens for embedders.\n \"flex min-h-8 w-full cursor-pointer items-center gap-2.5 rounded-og-md px-[var(--og-model-picker-row-padding-x)] py-[var(--og-model-picker-row-padding-y)] text-left text-og-fg outline-hidden transition-colors duration-[120ms] hover:bg-og-hover focus-visible:bg-og-hover focus-visible:outline-2 focus-visible:-outline-offset-2! focus-visible:outline-og-accent/55 pointer-coarse:min-h-11\",\n props.disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n {props.icon}\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-og-menu\">{props.label}</span>\n {props.hint ? (\n <span className=\"mt-0.5 block truncate text-og-sm text-og-fg-muted\">{props.hint}</span>\n ) : null}\n </span>\n {props.trailing ? <span className=\"ml-auto shrink-0\">{props.trailing}</span> : null}\n {props.showChevron === false ? null : <ChevronRightIcon className={MENU_CHEVRON_CLASS} />}\n </button>\n );\n}\n\nexport function PickerBackHeader(props: {\n label: string;\n icon?: ReactNode;\n onBack: () => void;\n trailing?: ReactNode;\n}) {\n return (\n <div className=\"mb-1.5 flex min-h-9 items-center gap-1 border-b border-og-border pb-1.5\">\n <button\n type=\"button\"\n onClick={props.onBack}\n data-testid=\"model-picker-back\"\n className=\"flex min-h-8 min-w-0 flex-1 cursor-pointer items-center gap-1 rounded-og-md pr-2.5 text-left text-og-fg outline-hidden transition-colors duration-[120ms] hover:bg-og-hover focus-visible:outline-2 focus-visible:-outline-offset-2! focus-visible:outline-og-accent/55 pointer-coarse:min-h-11\"\n >\n <span className=\"flex size-8 shrink-0 items-center justify-center text-og-fg-muted\">\n <ChevronLeftIcon className=\"size-4\" />\n </span>\n {props.icon}\n <span className=\"min-w-0 flex-1 truncate text-og-menu font-medium\">{props.label}</span>\n </button>\n {props.trailing ? <div className=\"relative z-10 shrink-0\">{props.trailing}</div> : null}\n </div>\n );\n}\n\nexport function PickerAnimatedPage(props: {\n pageKey: string;\n direction: 1 | -1;\n children: ReactNode;\n}) {\n const reduceMotion = useReducedMotion();\n return (\n <motion.div\n key={props.pageKey}\n initial={reduceMotion ? false : { x: props.direction * 14, opacity: 0 }}\n animate={{ x: 0, opacity: 1 }}\n transition={{ duration: reduceMotion ? 0 : 0.18, ease: SLIDE_EASE }}\n className=\"w-full\"\n >\n {props.children}\n </motion.div>\n );\n}\n\n/** @internal Shared controlled/uncontrolled state seam. */\nexport function useModelPolicyPickerState(props: ModelPolicyPickerProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(props.defaultOpen ?? false);\n const open = props.open ?? uncontrolledOpen;\n const setOpen = (next: boolean) => {\n if (props.open === undefined) setUncontrolledOpen(next);\n props.onOpenChange?.(next);\n };\n return { open, setOpen, rows: effectiveRows(props) };\n}\n\nexport function ModelPolicyPicker(props: ModelPolicyPickerProps) {\n const contentId = useId();\n const trigger = usePortalTokenSource<HTMLButtonElement>();\n const portalStyle = usePortalTokenStyle(trigger.source);\n const messages = useMemo(\n () => ({ ...defaultModelPolicyPickerMessages, ...props.messages }),\n [props.messages],\n );\n const { open, setOpen, rows } = useModelPolicyPickerState(props);\n const selected = findPickerRow(rows, props.model);\n const needsModel =\n !rows.some((row) => row.selectable) && (rows.length > 0 || Boolean(props.connectModelsHref));\n const selectedDescription = needsModel\n ? messages.connectTitle\n : [selected?.label ?? fallbackName(props), labelReasoningEffort(props.effort)].join(\" · \");\n\n if (props.loading) {\n return (\n <span\n className={cn(\n \"og-root inline-flex h-8 w-40 shrink-0 animate-pulse rounded-full bg-og-surface-2\",\n props.triggerStyle === \"field\" && \"w-[180px] rounded-og-md\",\n props.className,\n )}\n aria-label={messages.loading}\n data-testid=\"model-picker-loading\"\n />\n );\n }\n if (props.triggerStyle === \"field\") {\n return (\n <>\n <button\n ref={trigger.ref}\n type=\"button\"\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={open ? contentId : undefined}\n data-state={open ? \"open\" : \"closed\"}\n data-trigger-style=\"field\"\n onClick={() => setOpen(!open)}\n disabled={props.disabled}\n aria-label={messages.label}\n aria-description={selectedDescription}\n className={cn(\n \"og-root inline-flex h-8 min-w-[180px] max-w-full items-center gap-2 rounded-og-md border border-og-border bg-og-surface px-2.5 text-sm text-og-fg outline-hidden transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50\",\n props.className,\n )}\n >\n {needsModel ? (\n <SparklesIcon className=\"size-3.5 shrink-0\" aria-hidden />\n ) : (\n <SelectedModelMark props={props} selected={selected} />\n )}\n <span className=\"min-w-0 truncate font-medium\">\n {needsModel ? messages.connectTitle : (selected?.label ?? fallbackName(props))}\n </span>\n {props.triggerMeta && !needsModel ? (\n <span className=\"min-w-0 shrink-[9999] truncate text-og-fg-muted\">\n {props.triggerMeta}\n </span>\n ) : null}\n <ChevronDownIcon className=\"ml-auto size-3.5 shrink-0 text-og-fg-muted\" />\n </button>\n {open ? (\n <Suspense fallback={null}>\n <LazyModelPolicyPickerMenu\n {...props}\n anchor={trigger.currentRef}\n contentId={contentId}\n portalStyle={portalStyle}\n onOpenChange={setOpen}\n />\n </Suspense>\n ) : null}\n </>\n );\n }\n return (\n <>\n <button\n ref={trigger.ref}\n type=\"button\"\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={open ? contentId : undefined}\n data-state={open ? \"open\" : \"closed\"}\n onClick={() => setOpen(!open)}\n disabled={props.disabled}\n aria-label={messages.label}\n aria-description={selectedDescription}\n className={cn(\n \"og-root og-model-policy-trigger inline-flex h-[var(--og-model-picker-trigger-height)] min-w-0 max-w-64 items-center gap-1 rounded-full border px-2.5 text-og-control outline-hidden transition-colors focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50 max-sm:h-11 max-sm:max-w-[7.5rem] max-sm:px-2\",\n // With no usable model the pill is the one thing that unblocks the\n // composer, so it takes the primary wash.\n needsModel\n ? \"border-og-primary-border bg-og-primary text-og-primary-fg hover:bg-og-primary-hover\"\n : \"border-transparent text-og-fg-muted hover:border-og-border hover:bg-og-surface-2 hover:text-og-fg\",\n props.className,\n )}\n >\n {needsModel ? (\n <SparklesIcon className=\"size-3.5 shrink-0\" aria-hidden />\n ) : (\n <SelectedModelMark props={props} selected={selected} />\n )}\n <span className=\"og-model-policy-label-full min-w-0 truncate font-medium text-og-fg max-sm:hidden @max-[20rem]/model-controls:hidden\">\n {needsModel ? messages.connectTitle : (selected?.label ?? fallbackName(props))}\n </span>\n <span className=\"og-model-policy-label-short min-w-0 truncate font-medium text-og-fg sm:hidden @max-[20rem]/model-controls:block\">\n {needsModel\n ? messages.connectTitle\n : (selected?.shortLabel ?? selected?.label ?? fallbackName(props))}\n </span>\n {selected && !needsModel && modelOffersEffortChoice(selected.catalog) ? (\n <span\n className=\"og-model-policy-effort min-w-0 shrink-[9999] truncate\"\n title={labelReasoningEffort(props.effort)}\n >\n {labelReasoningEffort(props.effort)}\n </span>\n ) : null}\n {props.latencyMode === \"fast\" && !needsModel ? (\n <ZapIcon\n className=\"size-3.5 shrink-0 fill-current stroke-current text-og-fg\"\n aria-label={messages.fast}\n data-testid=\"model-picker-fast-icon\"\n />\n ) : null}\n <ChevronDownIcon className=\"size-3 shrink-0\" />\n </button>\n\n {open ? (\n <Suspense fallback={null}>\n <LazyModelPolicyPickerMenu\n {...props}\n anchor={trigger.currentRef}\n contentId={contentId}\n portalStyle={portalStyle}\n onOpenChange={setOpen}\n />\n </Suspense>\n ) : null}\n </>\n );\n}\n"],"mappings":"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","names":["jsx","jsx","modelDisplayName","modelLogoUrl","SparklesIcon","useState","jsx","jsxs","jsx","SparklesIcon","modelLogoUrl","modelDisplayName","effectiveRows","jsxs","useState"]}
|
|
@@ -1,5 +1,114 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
// src/lib/provider-recovery.ts
|
|
4
|
+
var MODEL_CODES = /* @__PURE__ */ new Set([
|
|
5
|
+
"provider_unavailable",
|
|
6
|
+
"provider_rate_limited",
|
|
7
|
+
"provider_unknown_finish_reason",
|
|
8
|
+
"post_compaction_continuation_empty"
|
|
9
|
+
]);
|
|
10
|
+
var RECOVERY_CODES = /* @__PURE__ */ new Set([
|
|
11
|
+
...MODEL_CODES,
|
|
12
|
+
"upstream_connectivity_unavailable",
|
|
13
|
+
"mcp_transport_timeout",
|
|
14
|
+
"mcp_transport_unavailable",
|
|
15
|
+
"sandbox_command_start_unavailable",
|
|
16
|
+
"turn_execution_policy_definition_mismatch"
|
|
17
|
+
]);
|
|
18
|
+
var DEFAULT_MAX_ATTEMPTS = 5;
|
|
19
|
+
function text(value, max = 120) {
|
|
20
|
+
if (typeof value !== "string") return null;
|
|
21
|
+
const normalized = value.replace(/\s+/g, " ").trim();
|
|
22
|
+
return normalized ? normalized.slice(0, max) : null;
|
|
23
|
+
}
|
|
24
|
+
function count(value) {
|
|
25
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
|
|
26
|
+
}
|
|
27
|
+
function condition(payload, code) {
|
|
28
|
+
const recorded = payload.providerCondition;
|
|
29
|
+
if (recorded === "overloaded" || recorded === "unavailable" || recorded === "unresponsive" || recorded === "rate_limited")
|
|
30
|
+
return recorded;
|
|
31
|
+
if (code === "provider_rate_limited") return "rate_limited";
|
|
32
|
+
if (code !== "provider_unavailable") return null;
|
|
33
|
+
return [payload.lastRetryableError, payload.detail, payload.error].some(
|
|
34
|
+
(value) => typeof value === "string" && /\boverload(?:ed)?(?:_error)?\b/i.test(value)
|
|
35
|
+
) ? "overloaded" : null;
|
|
36
|
+
}
|
|
37
|
+
function parseProviderRecovery(payload) {
|
|
38
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) return null;
|
|
39
|
+
const record = payload;
|
|
40
|
+
const code = text(record.code) ?? text(record.reason);
|
|
41
|
+
if (!code || !RECOVERY_CODES.has(code)) return null;
|
|
42
|
+
if (record.recoveryExhausted !== true && record.retryable === false) return null;
|
|
43
|
+
const attempt = count(record.providerRecoveryCount);
|
|
44
|
+
return {
|
|
45
|
+
code,
|
|
46
|
+
condition: condition(record, code),
|
|
47
|
+
modelLabel: text(record.modelLabel),
|
|
48
|
+
providerLabel: text(record.providerLabel),
|
|
49
|
+
attempt,
|
|
50
|
+
maxAttempts: count(record.maxProviderRecoveryCount) ?? DEFAULT_MAX_ATTEMPTS,
|
|
51
|
+
modelRoute: MODEL_CODES.has(code)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function providerRecoverySubject(facts) {
|
|
55
|
+
const model = facts.modelLabel ?? "The model";
|
|
56
|
+
const at = facts.providerLabel ? ` at the provider (${facts.providerLabel})` : " at the provider";
|
|
57
|
+
switch (facts.code) {
|
|
58
|
+
case "provider_rate_limited":
|
|
59
|
+
return `${model} is rate limited${at}`;
|
|
60
|
+
case "provider_unavailable":
|
|
61
|
+
return facts.condition === "overloaded" ? `${model} is overloaded${at}` : facts.condition === "unresponsive" ? `${model} stopped responding${at}` : `${model} is temporarily unavailable${at}`;
|
|
62
|
+
case "provider_unknown_finish_reason":
|
|
63
|
+
return `${model} ended its response unexpectedly`;
|
|
64
|
+
case "post_compaction_continuation_empty":
|
|
65
|
+
return `${model} stopped right after compacting the conversation`;
|
|
66
|
+
case "upstream_connectivity_unavailable":
|
|
67
|
+
return "Opengeni can't reach an upstream service";
|
|
68
|
+
case "mcp_transport_timeout":
|
|
69
|
+
return "A required MCP server isn't responding";
|
|
70
|
+
case "mcp_transport_unavailable":
|
|
71
|
+
return "A required MCP server is unreachable";
|
|
72
|
+
case "sandbox_command_start_unavailable":
|
|
73
|
+
return "The sandbox isn't ready yet";
|
|
74
|
+
case "turn_execution_policy_definition_mismatch":
|
|
75
|
+
return "Opengeni is applying a configuration update";
|
|
76
|
+
default:
|
|
77
|
+
return "A service this turn depends on is temporarily unavailable";
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function providerRecoveryRetryingText(facts) {
|
|
81
|
+
const progress = facts.attempt !== null && facts.maxAttempts !== null ? ` (attempt ${Math.min(facts.attempt, facts.maxAttempts)} of ${facts.maxAttempts})` : " automatically";
|
|
82
|
+
return `${providerRecoverySubject(facts)} \u2014 retrying${progress}\u2026`;
|
|
83
|
+
}
|
|
84
|
+
function providerRecoveryExhaustedText(facts) {
|
|
85
|
+
const spent = facts.attempt ?? facts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
86
|
+
const retried = `Opengeni retried ${spent} ${spent === 1 ? "time" : "times"} without success.`;
|
|
87
|
+
const remedy = facts.modelRoute ? "Try again in a few minutes, or switch to another model." : "Try again in a few minutes.";
|
|
88
|
+
return `${providerRecoverySubject(facts)}. ${retried} ${remedy}`;
|
|
89
|
+
}
|
|
90
|
+
var BOUNDARY_TYPES = /* @__PURE__ */ new Set([
|
|
91
|
+
"turn.recovery.requested",
|
|
92
|
+
"turn.started",
|
|
93
|
+
"turn.completed",
|
|
94
|
+
"turn.failed",
|
|
95
|
+
"turn.cancelled",
|
|
96
|
+
"turn.superseded"
|
|
97
|
+
]);
|
|
98
|
+
function currentProviderRecovery(session, events) {
|
|
99
|
+
if (session.status !== "recovering" || session.effectiveControl && session.effectiveControl.state !== "active" || !session.activeTurnId)
|
|
100
|
+
return null;
|
|
101
|
+
let latest;
|
|
102
|
+
for (const event of events) {
|
|
103
|
+
if (event.sessionId !== session.id || event.turnId !== session.activeTurnId || event.duplicateOfEventId || event.turnAssociation && event.turnAssociation !== "current" || !BOUNDARY_TYPES.has(event.type))
|
|
104
|
+
continue;
|
|
105
|
+
if (!latest || event.sequence > latest.sequence) latest = event;
|
|
106
|
+
}
|
|
107
|
+
if (latest?.type !== "turn.recovery.requested") return null;
|
|
108
|
+
const payload = latest.payload;
|
|
109
|
+
return payload?.recoveryExhausted === true ? null : parseProviderRecovery(payload);
|
|
110
|
+
}
|
|
111
|
+
|
|
3
112
|
// src/lib/format.ts
|
|
4
113
|
import { formatErrorMessage, OpenGeniApiError } from "@opengeni/sdk";
|
|
5
114
|
var clockTimeFormatter = new Intl.DateTimeFormat(void 0, {
|
|
@@ -55,8 +164,8 @@ function formatBytes(bytes) {
|
|
|
55
164
|
}
|
|
56
165
|
return `${bytes} B`;
|
|
57
166
|
}
|
|
58
|
-
function truncate(
|
|
59
|
-
const collapsed =
|
|
167
|
+
function truncate(text2, maxLength) {
|
|
168
|
+
const collapsed = text2.replace(/\s+/g, " ").trim();
|
|
60
169
|
if (collapsed.length <= maxLength) {
|
|
61
170
|
return collapsed;
|
|
62
171
|
}
|
|
@@ -79,8 +188,8 @@ function stringifyPayload(value) {
|
|
|
79
188
|
return String(value);
|
|
80
189
|
}
|
|
81
190
|
}
|
|
82
|
-
function tryParseJson(
|
|
83
|
-
const trimmed =
|
|
191
|
+
function tryParseJson(text2) {
|
|
192
|
+
const trimmed = text2.trim();
|
|
84
193
|
if (!trimmed.startsWith("{") && !trimmed.startsWith("[") && !trimmed.startsWith('"')) {
|
|
85
194
|
return void 0;
|
|
86
195
|
}
|
|
@@ -148,8 +257,8 @@ function isCreditExhaustion(input) {
|
|
|
148
257
|
if (input.segmentLimit === "budget_exhausted") {
|
|
149
258
|
return true;
|
|
150
259
|
}
|
|
151
|
-
for (const
|
|
152
|
-
if (typeof
|
|
260
|
+
for (const text2 of [input.error, input.detail]) {
|
|
261
|
+
if (typeof text2 === "string" && text2.toLowerCase().includes("insufficient opengeni credits")) {
|
|
153
262
|
return true;
|
|
154
263
|
}
|
|
155
264
|
}
|
|
@@ -178,12 +287,12 @@ function presentFailure(payload) {
|
|
|
178
287
|
if (databaseFailure) {
|
|
179
288
|
return { reason: "The service encountered a database error.", safetyRefusal: false };
|
|
180
289
|
}
|
|
181
|
-
const
|
|
290
|
+
const text2 = (key) => {
|
|
182
291
|
const value = payload[key];
|
|
183
292
|
return typeof value === "string" && value.trim() ? value : null;
|
|
184
293
|
};
|
|
185
|
-
const message =
|
|
186
|
-
const detail =
|
|
294
|
+
const message = text2("error") ?? text2("message");
|
|
295
|
+
const detail = text2("lastRetryableError") ?? text2("detail");
|
|
187
296
|
const safetyRefusal = payload.code === "provider_safety_refusal" || [message, detail].some(
|
|
188
297
|
(value) => value !== null && /\bthis request was blocked by our safety systems\b/i.test(value)
|
|
189
298
|
);
|
|
@@ -193,6 +302,10 @@ function presentFailure(payload) {
|
|
|
193
302
|
safetyRefusal: true
|
|
194
303
|
};
|
|
195
304
|
}
|
|
305
|
+
const recovery = parseProviderRecovery(payload);
|
|
306
|
+
if (recovery && payload.recoveryExhausted === true) {
|
|
307
|
+
return { reason: providerRecoveryExhaustedText(recovery), safetyRefusal: false };
|
|
308
|
+
}
|
|
196
309
|
return {
|
|
197
310
|
reason: detail && detail !== message ? [humanizeFailureReason(message), humanizeFailureReason(detail)].filter(Boolean).join(" ") : humanizeFailureReason(message),
|
|
198
311
|
safetyRefusal: false
|
|
@@ -200,6 +313,11 @@ function presentFailure(payload) {
|
|
|
200
313
|
}
|
|
201
314
|
|
|
202
315
|
export {
|
|
316
|
+
parseProviderRecovery,
|
|
317
|
+
providerRecoverySubject,
|
|
318
|
+
providerRecoveryRetryingText,
|
|
319
|
+
providerRecoveryExhaustedText,
|
|
320
|
+
currentProviderRecovery,
|
|
203
321
|
formatClockTime,
|
|
204
322
|
formatRelativeTime,
|
|
205
323
|
formatBytes,
|
|
@@ -219,4 +337,4 @@ export {
|
|
|
219
337
|
humanizeFailureReason,
|
|
220
338
|
presentFailure
|
|
221
339
|
};
|
|
222
|
-
//# sourceMappingURL=chunk-
|
|
340
|
+
//# sourceMappingURL=chunk-ATIRUHBZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/provider-recovery.ts","../src/lib/format.ts"],"sourcesContent":["import type { SessionEvent, SessionStatus } from \"@opengeni/sdk\";\n\n/**\n * Finite same-turn provider recovery, projected for people. Presentation only:\n * the worker owns retry authority, pacing and the recovery budget. The worker\n * (`apps/worker/src/activities/agent-turn/provider-recovery-copy.ts`) writes\n * the same exhausted sentence into `turn.failed.error`; keep the two in step.\n */\nexport type ProviderRecoveryCondition =\n | \"overloaded\"\n | \"unavailable\"\n | \"unresponsive\"\n | \"rate_limited\";\n\nexport type ProviderRecoveryFacts = {\n /** Recorded worker failure code (`provider_unavailable`, `mcp_transport_timeout`, ...). */\n code: string;\n condition: ProviderRecoveryCondition | null;\n /** Display label of the affected model, when the route was recorded. */\n modelLabel: string | null;\n /** Display label of the serving provider, when the route was recorded. */\n providerLabel: string | null;\n /** Automatic retries scheduled (live) or spent (exhausted). */\n attempt: number | null;\n /** Finite automatic retry budget. */\n maxAttempts: number | null;\n /** True when the model route itself is affected, so another model may help. */\n modelRoute: boolean;\n};\n\nconst MODEL_CODES: ReadonlySet<string> = new Set([\n \"provider_unavailable\",\n \"provider_rate_limited\",\n \"provider_unknown_finish_reason\",\n \"post_compaction_continuation_empty\",\n]);\n\nconst RECOVERY_CODES: ReadonlySet<string> = new Set([\n ...MODEL_CODES,\n \"upstream_connectivity_unavailable\",\n \"mcp_transport_timeout\",\n \"mcp_transport_unavailable\",\n \"sandbox_command_start_unavailable\",\n \"turn_execution_policy_definition_mismatch\",\n]);\n\n/** Matches the worker's default budget for legacy events that omit it. */\nconst DEFAULT_MAX_ATTEMPTS = 5;\n\nfunction text(value: unknown, max = 120): string | null {\n if (typeof value !== \"string\") return null;\n const normalized = value.replace(/\\s+/g, \" \").trim();\n return normalized ? normalized.slice(0, max) : null;\n}\n\nfunction count(value: unknown): number | null {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value > 0 ? value : null;\n}\n\nfunction condition(\n payload: Record<string, unknown>,\n code: string,\n): ProviderRecoveryCondition | null {\n const recorded = payload.providerCondition;\n if (\n recorded === \"overloaded\" ||\n recorded === \"unavailable\" ||\n recorded === \"unresponsive\" ||\n recorded === \"rate_limited\"\n )\n return recorded;\n if (code === \"provider_rate_limited\") return \"rate_limited\";\n if (code !== \"provider_unavailable\") return null;\n // Older events predate the typed condition; their provider text still says so.\n return [payload.lastRetryableError, payload.detail, payload.error].some(\n (value) => typeof value === \"string\" && /\\boverload(?:ed)?(?:_error)?\\b/i.test(value),\n )\n ? \"overloaded\"\n : null;\n}\n\n/**\n * Read a retryable `turn.recovery.requested` payload or an exhausted\n * `turn.failed` payload. Returns null for every other recovery reason (human\n * Retry, worker shutdown, credential rotation, capacity waits, ...).\n */\nexport function parseProviderRecovery(payload: unknown): ProviderRecoveryFacts | null {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) return null;\n const record = payload as Record<string, unknown>;\n const code = text(record.code) ?? text(record.reason);\n if (!code || !RECOVERY_CODES.has(code)) return null;\n // A live recovery request is retryable; a spent budget is explicitly marked.\n if (record.recoveryExhausted !== true && record.retryable === false) return null;\n const attempt = count(record.providerRecoveryCount);\n return {\n code,\n condition: condition(record, code),\n modelLabel: text(record.modelLabel),\n providerLabel: text(record.providerLabel),\n attempt,\n maxAttempts: count(record.maxProviderRecoveryCount) ?? DEFAULT_MAX_ATTEMPTS,\n modelRoute: MODEL_CODES.has(code),\n };\n}\n\n/** One present-tense clause naming what is unavailable, without a trailing period. */\nexport function providerRecoverySubject(facts: ProviderRecoveryFacts): string {\n const model = facts.modelLabel ?? \"The model\";\n const at = facts.providerLabel ? ` at the provider (${facts.providerLabel})` : \" at the provider\";\n switch (facts.code) {\n case \"provider_rate_limited\":\n return `${model} is rate limited${at}`;\n case \"provider_unavailable\":\n return facts.condition === \"overloaded\"\n ? `${model} is overloaded${at}`\n : facts.condition === \"unresponsive\"\n ? `${model} stopped responding${at}`\n : `${model} is temporarily unavailable${at}`;\n case \"provider_unknown_finish_reason\":\n return `${model} ended its response unexpectedly`;\n case \"post_compaction_continuation_empty\":\n return `${model} stopped right after compacting the conversation`;\n case \"upstream_connectivity_unavailable\":\n return \"Opengeni can't reach an upstream service\";\n case \"mcp_transport_timeout\":\n return \"A required MCP server isn't responding\";\n case \"mcp_transport_unavailable\":\n return \"A required MCP server is unreachable\";\n case \"sandbox_command_start_unavailable\":\n return \"The sandbox isn't ready yet\";\n case \"turn_execution_policy_definition_mismatch\":\n return \"Opengeni is applying a configuration update\";\n default:\n return \"A service this turn depends on is temporarily unavailable\";\n }\n}\n\n/** Live status while the same turn waits for its next automatic retry. */\nexport function providerRecoveryRetryingText(facts: ProviderRecoveryFacts): string {\n const progress =\n facts.attempt !== null && facts.maxAttempts !== null\n ? ` (attempt ${Math.min(facts.attempt, facts.maxAttempts)} of ${facts.maxAttempts})`\n : \" automatically\";\n return `${providerRecoverySubject(facts)} — retrying${progress}…`;\n}\n\n/** Terminal sentence once the automatic budget is spent. */\nexport function providerRecoveryExhaustedText(facts: ProviderRecoveryFacts): string {\n const spent = facts.attempt ?? facts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n const retried = `Opengeni retried ${spent} ${spent === 1 ? \"time\" : \"times\"} without success.`;\n const remedy = facts.modelRoute\n ? \"Try again in a few minutes, or switch to another model.\"\n : \"Try again in a few minutes.\";\n return `${providerRecoverySubject(facts)}. ${retried} ${remedy}`;\n}\n\nconst BOUNDARY_TYPES: ReadonlySet<string> = new Set([\n \"turn.recovery.requested\",\n \"turn.started\",\n \"turn.completed\",\n \"turn.failed\",\n \"turn.cancelled\",\n \"turn.superseded\",\n]);\n\n/**\n * The active turn's current automatic provider retry, or null. Only a\n * `recovering`, unpaused session qualifies, and only the newest boundary of its\n * exact active turn counts, so merged or replayed pages never borrow another\n * turn's diagnosis.\n */\nexport function currentProviderRecovery(\n session: {\n id: string;\n status: SessionStatus | null | undefined;\n activeTurnId: string | null | undefined;\n effectiveControl?: { state: string } | null | undefined;\n },\n events: readonly SessionEvent[],\n): ProviderRecoveryFacts | null {\n if (\n session.status !== \"recovering\" ||\n (session.effectiveControl && session.effectiveControl.state !== \"active\") ||\n !session.activeTurnId\n )\n return null;\n let latest: SessionEvent | undefined;\n for (const event of events) {\n if (\n event.sessionId !== session.id ||\n event.turnId !== session.activeTurnId ||\n event.duplicateOfEventId ||\n (event.turnAssociation && event.turnAssociation !== \"current\") ||\n !BOUNDARY_TYPES.has(event.type)\n )\n continue;\n if (!latest || event.sequence > latest.sequence) latest = event;\n }\n if (latest?.type !== \"turn.recovery.requested\") return null;\n const payload = latest.payload as Record<string, unknown> | null | undefined;\n return payload?.recoveryExhausted === true ? null : parseProviderRecovery(payload);\n}\n","import { formatErrorMessage, OpenGeniApiError } from \"@opengeni/sdk\";\nimport { parseProviderRecovery, providerRecoveryExhaustedText } from \"./provider-recovery\";\n\nconst clockTimeFormatter = new Intl.DateTimeFormat(undefined, {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n});\n\n/** Local finished-at stamp for message footers: \"Aug 2, 3:42 PM\" / locale-equivalent. */\nexport function formatClockTime(iso: string): string {\n const then = new Date(iso);\n if (Number.isNaN(then.getTime())) {\n return \"\";\n }\n return clockTimeFormatter.format(then);\n}\n\n/** Compact relative time: \"now\", \"42s\", \"7m\", \"3h\", \"2d\", then a date. */\nexport function formatRelativeTime(iso: string, now: Date = new Date()): string {\n const then = new Date(iso).getTime();\n if (Number.isNaN(then)) {\n return \"\";\n }\n const seconds = Math.max(0, Math.floor((now.getTime() - then) / 1000));\n if (seconds < 10) {\n return \"now\";\n }\n if (seconds < 60) {\n return `${seconds}s`;\n }\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) {\n return `${minutes}m`;\n }\n const hours = Math.floor(minutes / 60);\n if (hours < 24) {\n return `${hours}h`;\n }\n const days = Math.floor(hours / 24);\n if (days < 14) {\n return `${days}d`;\n }\n return new Date(iso).toLocaleDateString();\n}\n\n/** Human-readable byte size: \"512 B\", \"8.0 KB\", \"1.4 MB\", \"3 GB\". */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n const units = [\"KB\", \"MB\", \"GB\"] as const;\n let value = bytes / 1024;\n for (const unit of units) {\n if (value < 1024 || unit === \"GB\") {\n return `${value.toFixed(value < 10 ? 1 : 0)} ${unit}`;\n }\n value /= 1024;\n }\n return `${bytes} B`;\n}\n\n/** Single-line preview of arbitrary text, for tiles and collapsed rows. */\nexport function truncate(text: string, maxLength: number): string {\n const collapsed = text.replace(/\\s+/g, \" \").trim();\n if (collapsed.length <= maxLength) {\n return collapsed;\n }\n return `${collapsed.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;\n}\n\n/** Render an unknown payload as readable text (pretty JSON when possible). */\nexport function stringifyPayload(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n const parsed = tryParseJson(value);\n if (parsed !== undefined && typeof parsed === \"object\") {\n return stringifyPayload(parsed);\n }\n return value;\n }\n try {\n return JSON.stringify(value, null, 2) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\n/** JSON.parse that returns `undefined` instead of throwing. */\nexport function tryParseJson(text: string): unknown {\n const trimmed = text.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\") && !trimmed.startsWith('\"')) {\n return undefined;\n }\n try {\n return JSON.parse(trimmed) as unknown;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The canonical credit-death sentence. Credit exhaustion is the one failure a\n * user can fix themselves — the copy must say what happened (empty balance),\n * what to do (add credits), and what is safe (nothing was lost). Crucially it\n * must NOT say \"send a message to revive\": a revive turn burns credits the\n * workspace no longer has.\n */\nexport const CREDIT_EXHAUSTION_MESSAGE =\n \"Out of credits — this workspace's balance is empty. Add credits to continue; the conversation is preserved.\";\n\n/** A usage ceiling refused the send; the default allowance wording, plus what is safe. */\nexport const COMPOSER_MEMBER_ALLOWANCE_MESSAGE =\n \"Usage limit reached. A workspace admin can raise this limit. Your draft is preserved.\";\nexport const COMPOSER_WORKSPACE_ALLOWANCE_MESSAGE =\n \"Workspace usage limit reached. An organization admin can raise the workspace budget. Your draft is preserved.\";\n\n/**\n * Actionable composer copy for an edge rejection before a turn is accepted.\n * Unlike an in-flight credit exhaustion, this path has not consumed the\n * actor-private draft or any finalized attachment.\n */\nexport const COMPOSER_PAYMENT_REQUIRED_MESSAGE =\n \"Your organization doesn't have enough credits to send this message. Add credits or choose a model with another payment source. Your message and attachments are saved.\";\n\n/** Trusted, composer-owned guidance; unlike remote diagnostic prose, this is UI copy. */\nexport class ComposerStateError extends Error {}\n\n/** A restored request has omitted credentials and must be reconciled, not replayed. */\nexport class ComposerReconciliationRequiredError extends ComposerStateError {\n constructor() {\n super(\n \"Opengeni cannot safely retry this uncertain request after remount; reconcile the session before sending again.\",\n );\n }\n}\n\nexport class ComposerWorkspaceControlUnavailableError extends Error {\n constructor() {\n super(\"@opengeni/react: workspace-scoped resume requires setWorkspaceInferenceState.\");\n }\n}\n\n/**\n * The send named a model that is no longer in the live catalog (retired or\n * removed). Retrying the same send cannot succeed; the person must choose\n * another model, and the typed message stays recoverable via Edit message.\n */\nexport const COMPOSER_MODEL_UNAVAILABLE_MESSAGE =\n \"This chat's model is no longer available. Choose another model to continue. Your message is saved.\";\n\n/** `details.code` the API sets on a 422 for a model missing from the live catalog. */\nexport const MODEL_UNAVAILABLE_DETAIL_CODE = \"model_unavailable\";\n\n/**\n * Is this send refusal \"the model is no longer available\"? Reads the typed\n * `details.code`, and also the historical message so a refusal persisted\n * before a reload (only its text survives) or from an older API is recognized.\n */\nexport function isModelUnavailableSubmissionError(error: Error): boolean {\n if (error instanceof OpenGeniApiError && error.details?.code === MODEL_UNAVAILABLE_DETAIL_CODE) {\n return true;\n }\n return (\n error.message === COMPOSER_MODEL_UNAVAILABLE_MESSAGE ||\n /^OpenGeni API 422: model is not available: /.test(error.message)\n );\n}\n\nexport function composerSubmissionErrorMessage(error: Error): string {\n if (error instanceof ComposerReconciliationRequiredError) {\n return \"This client cannot safely retry this uncertain request after remount; reconcile the session before sending again.\";\n }\n if (error instanceof ComposerWorkspaceControlUnavailableError) {\n return \"This client cannot resume the workspace. Ask your administrator for a control-capable client.\";\n }\n if (error instanceof ComposerStateError) return error.message;\n if (error instanceof OpenGeniApiError && error.outcomeUnknown) return formatErrorMessage(error);\n if (isModelUnavailableSubmissionError(error)) return COMPOSER_MODEL_UNAVAILABLE_MESSAGE;\n if (error instanceof OpenGeniApiError && error.code === \"allowance_exhausted\") {\n // OpenGeniAllowanceExhaustedError carries the scope; read it structurally\n // so this startup-path helper adds no SDK or wording imports.\n const message =\n (error as { scope?: unknown }).scope === \"workspace\"\n ? COMPOSER_WORKSPACE_ALLOWANCE_MESSAGE\n : COMPOSER_MEMBER_ALLOWANCE_MESSAGE;\n return composerErrorReference(error, message);\n }\n return isComposerCreditRefusal(error)\n ? composerErrorReference(error, COMPOSER_PAYMENT_REQUIRED_MESSAGE)\n : formatErrorMessage(error);\n}\n\nfunction composerErrorReference(error: Error, message: string): string {\n return error instanceof OpenGeniApiError && error.correlationId\n ? `${message} Reference: ${error.correlationId}.`\n : message;\n}\n\n/** These definitive refusals need a payment, allowance or model change, not an unchanged retry. */\nexport function composerSubmissionCanRetry(error: Error): boolean {\n return !(\n isComposerCreditRefusal(error) ||\n isModelUnavailableSubmissionError(error) ||\n (error instanceof OpenGeniApiError && error.code === \"allowance_exhausted\")\n );\n}\n\nfunction isComposerCreditRefusal(error: Error): boolean {\n return (\n (error instanceof OpenGeniApiError &&\n error.status === 402 &&\n (error.code === \"payment_required\" || error.code === \"insufficient_credits\")) ||\n isCreditExhaustion(error.message)\n );\n}\n\n/**\n * Does this failure/completion payload (or raw error string) mean the\n * workspace ran out of OpenGeni credits? Matches the engine's\n * \"insufficient OpenGeni credits\" text (case-insensitive, substring — it\n * arrives both bare and wrapped in \"Activity task failed: …\") and the\n * budget-exhausted segment limit the engine stamps on a turn it ended early.\n */\nexport function isCreditExhaustion(\n input: { error?: string | null; detail?: string | null; segmentLimit?: string | null } | string,\n): boolean {\n if (typeof input === \"string\") {\n return input.toLowerCase().includes(\"insufficient opengeni credits\");\n }\n if (input.segmentLimit === \"budget_exhausted\") {\n return true;\n }\n for (const text of [input.error, input.detail]) {\n if (typeof text === \"string\" && text.toLowerCase().includes(\"insufficient opengeni credits\")) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Humanize engine/provider failure text before it reaches the timeline or a\n * failure banner. Raw provider errors leak the wrong audience's instructions —\n * \"Incorrect API key … find your API key at platform.openai.com\" tells a\n * managed-deployment USER to fix credentials only an OPERATOR controls (and is\n * flatly wrong for Azure or subscription-backed engines). Auth, quota, and\n * credit-exhaustion failures collapse to one neutral, honest sentence; every\n * other reason passes through untouched. Raw payloads stay available in the\n * debug surfaces.\n */\nexport function humanizeFailureReason(reason: string | null): string | null {\n if (!reason) {\n return reason;\n }\n if (isCreditExhaustion(reason)) {\n return CREDIT_EXHAUSTION_MESSAGE;\n }\n const normalized = reason.toLowerCase();\n const authFailure =\n normalized.includes(\"incorrect api key\") ||\n normalized.includes(\"invalid api key\") ||\n normalized.includes(\"invalid_api_key\") ||\n normalized.includes(\"platform.openai.com/account/api-keys\") ||\n (normalized.includes(\"401\") &&\n (normalized.includes(\"api key\") || normalized.includes(\"unauthorized\")));\n if (authFailure) {\n return \"The model provider rejected this deployment's engine credentials. Sending messages won't help until the deployment's engine configuration is fixed.\";\n }\n const quotaFailure =\n normalized.includes(\"insufficient_quota\") || normalized.includes(\"exceeded your current quota\");\n if (quotaFailure) {\n return \"The model provider refused the request: this deployment's provider quota is exhausted.\";\n }\n return reason;\n}\n\n/** Project failure diagnostics without changing the stored event, including legacy retry wrappers. */\nexport function presentFailure(payload: Record<string, unknown>): {\n reason: string | null;\n safetyRefusal: boolean;\n} {\n const databaseFailure =\n payload.code === \"db_deadlock\" ||\n payload.code === \"db_serialization_failure\" ||\n payload.code === \"db_failure\" ||\n (typeof payload.sqlState === \"string\" &&\n /^[0-9A-Z]{5}$/.test(payload.sqlState) &&\n payload.database !== null &&\n typeof payload.database === \"object\" &&\n !Array.isArray(payload.database));\n if (databaseFailure) {\n return { reason: \"The service encountered a database error.\", safetyRefusal: false };\n }\n const text = (key: string): string | null => {\n const value = payload[key];\n return typeof value === \"string\" && value.trim() ? value : null;\n };\n const message = text(\"error\") ?? text(\"message\");\n const detail = text(\"lastRetryableError\") ?? text(\"detail\");\n const safetyRefusal =\n payload.code === \"provider_safety_refusal\" ||\n [message, detail].some(\n (value) =>\n value !== null && /\\bthis request was blocked by our safety systems\\b/i.test(value),\n );\n if (safetyRefusal) {\n return {\n reason: `The model provider blocked this request.${detail || message ? ` ${detail ?? message}` : \"\"}`,\n safetyRefusal: true,\n };\n }\n // Spent automatic retries: name the model and the remedy instead of the\n // recorded wrapper plus raw provider text (still in the stored event).\n const recovery = parseProviderRecovery(payload);\n if (recovery && payload.recoveryExhausted === true) {\n return { reason: providerRecoveryExhaustedText(recovery), safetyRefusal: false };\n }\n return {\n reason:\n detail && detail !== message\n ? [humanizeFailureReason(message), humanizeFailureReason(detail)].filter(Boolean).join(\" \")\n : humanizeFailureReason(message),\n safetyRefusal: false,\n };\n}\n"],"mappings":"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","names":["text"]}
|