@opengeni/react 3.3.2 → 3.7.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/artifacts.d.ts +1 -1
  2. package/dist/artifacts.js +241 -18
  3. package/dist/artifacts.js.map +1 -1
  4. package/dist/{browser-viewer-MKKFRRRV.js → browser-viewer-E5DDEFQ4.js} +3 -3
  5. package/dist/{chunk-2DZVYHVO.js → chunk-4JFUT22W.js} +39 -13
  6. package/dist/chunk-4JFUT22W.js.map +1 -0
  7. package/dist/{chunk-ELIYWBZR.js → chunk-BV5A4OTE.js} +4 -4
  8. package/dist/{chunk-3AGBGTRT.js → chunk-C6WDLHBA.js} +148 -26
  9. package/dist/chunk-C6WDLHBA.js.map +1 -0
  10. package/dist/{chunk-YG4QEQF5.js → chunk-DOK4KZF2.js} +7863 -7736
  11. package/dist/chunk-DOK4KZF2.js.map +1 -0
  12. package/dist/{chunk-JAQ5K7W6.js → chunk-FJBOU2TH.js} +167 -58
  13. package/dist/chunk-FJBOU2TH.js.map +1 -0
  14. package/dist/{chunk-XYRDDSXF.js → chunk-R55HFTT3.js} +80 -34
  15. package/dist/chunk-R55HFTT3.js.map +1 -0
  16. package/dist/{chunk-ZPBTI3TE.js → chunk-W2RGYBCV.js} +4 -4
  17. package/dist/{chunk-WSK7G5LE.js → chunk-W3OUAH6M.js} +80 -80
  18. package/dist/chunk-W3OUAH6M.js.map +1 -0
  19. package/dist/{chunk-X4A66EWZ.js → chunk-WMGF4Z7X.js} +41 -43
  20. package/dist/chunk-WMGF4Z7X.js.map +1 -0
  21. package/dist/client.d.ts +1 -1
  22. package/dist/components/artifacts/index.d.ts +1 -1
  23. package/dist/components/artifacts/published-html-artifact-frame.d.ts +45 -3
  24. package/dist/components/composer.d.ts +2 -0
  25. package/dist/components/session-chrome.d.ts +1 -1
  26. package/dist/composer.js +4 -4
  27. package/dist/{computer-viewer-FWEZISW4.js → computer-viewer-7TEZC6Y2.js} +3 -3
  28. package/dist/{fleet-decision-row-GGCAT4E4.js → fleet-decision-row-YZ3ZKWMM.js} +2 -1
  29. package/dist/fleet-decision-row-YZ3ZKWMM.js.map +1 -0
  30. package/dist/hooks/use-file-attachments.d.ts +8 -0
  31. package/dist/hooks/use-sandbox-files.d.ts +4 -1
  32. package/dist/hooks/use-session-events.d.ts +1 -1
  33. package/dist/hooks/use-workspace-edit.d.ts +4 -0
  34. package/dist/index.js +195 -141
  35. package/dist/index.js.map +1 -1
  36. package/dist/interaction.js +3 -3
  37. package/dist/model-policy.d.ts +2 -1
  38. package/dist/model-policy.js +1 -1
  39. package/dist/{queue-surface-implementation-BSKUWHRI.js → queue-surface-implementation-XL2A6PBM.js} +2 -2
  40. package/dist/realtime.js +2 -2
  41. package/dist/session-ui.js +6 -6
  42. package/dist/session.js +4 -4
  43. package/dist/timeline/registry.d.ts +2 -0
  44. package/dist/timeline/types.d.ts +3 -1
  45. package/package.json +2 -2
  46. package/src/artifacts.ts +3 -0
  47. package/src/client.ts +2 -1
  48. package/src/components/artifacts/index.ts +3 -0
  49. package/src/components/artifacts/published-html-artifact-frame.tsx +284 -4
  50. package/src/components/composer.tsx +103 -29
  51. package/src/components/message-timeline.tsx +48 -10
  52. package/src/components/model-policy-picker.tsx +37 -10
  53. package/src/components/sandbox-workspace.tsx +18 -7
  54. package/src/components/session-chrome.tsx +3 -3
  55. package/src/hooks/use-file-attachments.ts +62 -2
  56. package/src/hooks/use-sandbox-files.ts +68 -20
  57. package/src/hooks/use-session-events.ts +176 -21
  58. package/src/hooks/use-workspace-edit.ts +23 -5
  59. package/src/model-policy.ts +48 -53
  60. package/src/timeline/fleet-decision-projection.ts +2 -1
  61. package/src/timeline/fleet-decision-row.tsx +1 -0
  62. package/src/timeline/projection.ts +157 -8
  63. package/src/timeline/registry.ts +15 -3
  64. package/src/timeline/tool-renderers.tsx +117 -1
  65. package/src/timeline/types.ts +10 -1
  66. package/styles/compiled.css +5 -0
  67. package/dist/chunk-2DZVYHVO.js.map +0 -1
  68. package/dist/chunk-3AGBGTRT.js.map +0 -1
  69. package/dist/chunk-JAQ5K7W6.js.map +0 -1
  70. package/dist/chunk-WSK7G5LE.js.map +0 -1
  71. package/dist/chunk-X4A66EWZ.js.map +0 -1
  72. package/dist/chunk-XYRDDSXF.js.map +0 -1
  73. package/dist/chunk-YG4QEQF5.js.map +0 -1
  74. package/dist/fleet-decision-row-GGCAT4E4.js.map +0 -1
  75. /package/dist/{browser-viewer-MKKFRRRV.js.map → browser-viewer-E5DDEFQ4.js.map} +0 -0
  76. /package/dist/{chunk-ELIYWBZR.js.map → chunk-BV5A4OTE.js.map} +0 -0
  77. /package/dist/{chunk-ZPBTI3TE.js.map → chunk-W2RGYBCV.js.map} +0 -0
  78. /package/dist/{computer-viewer-FWEZISW4.js.map → computer-viewer-7TEZC6Y2.js.map} +0 -0
  79. /package/dist/{queue-surface-implementation-BSKUWHRI.js.map → queue-surface-implementation-XL2A6PBM.js.map} +0 -0
@@ -1,2 +1,2 @@
1
1
  /** Public artifact surfaces. Import from `@opengeni/react/artifacts`. */
2
- export { ArtifactSurface, DocumentArtifactSurface, DocumentEditor, DocumentProjectionArtifactSurface, DocumentProjectionEditor, BrowserEditableArtifactWorkbench, EditableDocumentArtifactSurface, EditableArtifactWorkbench, EditableArtifactWorkbenchHost, EditablePresentationArtifactSurface, EditableSpreadsheetArtifactSurface, EditableSpreadsheetGrid, PresentationArtifactSurface, PresentationEditor, PresentationProjectionArtifactSurface, PresentationProjectionEditor, PublishedHtmlArtifactFrame, PUBLISHED_HTML_ARTIFACT_IFRAME_SANDBOX, SpreadsheetArtifactSurface, SpreadsheetGrid, SpreadsheetProjectionGrid, type ArtifactModality, type ArtifactSurfaceProps, type DocumentArtifactSurfaceProps, type DocumentCommit, type DocumentCommitHandler, type DocumentEditorProps, type DocumentEditorProjection, type DocumentLayoutMode, type DocumentProjectionArtifactSurfaceProps, type DocumentProjectionBlock, type DocumentProjectionChange, type DocumentProjectionComment, type DocumentProjectionEditorProps, type DocumentProjectionPageBreak, type DocumentProjectionPageGeometry, type DocumentProjectionParagraph, type DocumentProjectionParagraphStyle, type DocumentProjectionSection, type DocumentProjectionTable, type DocumentProjectionTextRun, type DocumentProjectionTextStyle, type DocumentSelection, type BrowserEditableArtifactWorkbenchOptions, type BrowserEditableArtifactWorkbenchProps, type EditableDocumentArtifactSurfaceProps, type EditableArtifactWorkbenchHostProps, type EditableArtifactWorkbenchProps, type EditablePresentationArtifactSurfaceProps, type EditableSpreadsheetArtifactSurfaceProps, type EditableSpreadsheetGridProps, type PresentationArtifactSurfaceProps, type PresentationCommit, type PresentationCommitHandler, type PresentationEditorProps, type PresentationEditorProjection, type PresentationProjectionArtifactSurfaceProps, type PresentationProjectionChart, type PresentationProjectionChartSeries, type PresentationProjectionConnector, type PresentationProjectionEditorProps, type PublishedHtmlArtifactFrameProps, type PresentationProjectionElementMetadata, type PresentationProjectionElement, type PresentationProjectionFill, type PresentationProjectionGroup, type PresentationProjectionImage, type PresentationProjectionLine, type PresentationProjectionPosition, type PresentationProjectionRichText, type PresentationProjectionShape, type PresentationProjectionTable, type PresentationProjectionTableCell, type PresentationProjectionTextParagraph, type PresentationProjectionTextRun, type PresentationProjectionTextStyle, type PresentationSlideProjection, type SpreadsheetArtifactSurfaceProps, type SpreadsheetCommit, type SpreadsheetRangeCommit, type SpreadsheetGridProps, type SpreadsheetGridProjection, type SpreadsheetProjectionCell, type SpreadsheetProjectionGridProps, type SpreadsheetSelection, type SpreadsheetViewport, } from "./components/artifacts/index.js";
2
+ export { ArtifactSurface, DocumentArtifactSurface, DocumentEditor, DocumentProjectionArtifactSurface, DocumentProjectionEditor, BrowserEditableArtifactWorkbench, EditableDocumentArtifactSurface, EditableArtifactWorkbench, EditableArtifactWorkbenchHost, EditablePresentationArtifactSurface, EditableSpreadsheetArtifactSurface, EditableSpreadsheetGrid, PresentationArtifactSurface, PresentationEditor, PresentationProjectionArtifactSurface, PresentationProjectionEditor, PublishedHtmlArtifactFrame, PUBLISHED_HTML_ARTIFACT_IFRAME_SANDBOX, openGeniSiteBridgePortFromBootstrap, publishedHtmlArtifactDocument, SpreadsheetArtifactSurface, SpreadsheetGrid, SpreadsheetProjectionGrid, type ArtifactModality, type ArtifactSurfaceProps, type DocumentArtifactSurfaceProps, type DocumentCommit, type DocumentCommitHandler, type DocumentEditorProps, type DocumentEditorProjection, type DocumentLayoutMode, type DocumentProjectionArtifactSurfaceProps, type DocumentProjectionBlock, type DocumentProjectionChange, type DocumentProjectionComment, type DocumentProjectionEditorProps, type DocumentProjectionPageBreak, type DocumentProjectionPageGeometry, type DocumentProjectionParagraph, type DocumentProjectionParagraphStyle, type DocumentProjectionSection, type DocumentProjectionTable, type DocumentProjectionTextRun, type DocumentProjectionTextStyle, type DocumentSelection, type BrowserEditableArtifactWorkbenchOptions, type BrowserEditableArtifactWorkbenchProps, type EditableDocumentArtifactSurfaceProps, type EditableArtifactWorkbenchHostProps, type EditableArtifactWorkbenchProps, type EditablePresentationArtifactSurfaceProps, type EditableSpreadsheetArtifactSurfaceProps, type EditableSpreadsheetGridProps, type PresentationArtifactSurfaceProps, type PresentationCommit, type PresentationCommitHandler, type PresentationEditorProps, type PresentationEditorProjection, type PresentationProjectionArtifactSurfaceProps, type PresentationProjectionChart, type PresentationProjectionChartSeries, type PresentationProjectionConnector, type PresentationProjectionEditorProps, type PublishedHtmlArtifactFrameProps, type PublishedHtmlArtifactToolBridge, type PresentationProjectionElementMetadata, type PresentationProjectionElement, type PresentationProjectionFill, type PresentationProjectionGroup, type PresentationProjectionImage, type PresentationProjectionLine, type PresentationProjectionPosition, type PresentationProjectionRichText, type PresentationProjectionShape, type PresentationProjectionTable, type PresentationProjectionTableCell, type PresentationProjectionTextParagraph, type PresentationProjectionTextRun, type PresentationProjectionTextStyle, type PresentationSlideProjection, type SpreadsheetArtifactSurfaceProps, type SpreadsheetCommit, type SpreadsheetRangeCommit, type SpreadsheetGridProps, type SpreadsheetGridProjection, type SpreadsheetProjectionCell, type SpreadsheetProjectionGridProps, type SpreadsheetSelection, type SpreadsheetViewport, } from "./components/artifacts/index.js";
package/dist/artifacts.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
- EditablePresentationArtifactSurface,
3
- PresentationArtifactSurface,
4
- PresentationEditor,
5
- PresentationProjectionArtifactSurface,
6
- PresentationProjectionEditor
7
- } from "./chunk-PEI6RANI.js";
2
+ DocumentArtifactSurface,
3
+ DocumentEditor,
4
+ DocumentProjectionArtifactSurface,
5
+ DocumentProjectionEditor,
6
+ EditableDocumentArtifactSurface
7
+ } from "./chunk-HUIKIDM5.js";
8
8
  import {
9
9
  EditableSpreadsheetArtifactSurface,
10
10
  EditableSpreadsheetGrid,
@@ -13,12 +13,12 @@ import {
13
13
  SpreadsheetProjectionGrid
14
14
  } from "./chunk-ICA6R6TW.js";
15
15
  import {
16
- DocumentArtifactSurface,
17
- DocumentEditor,
18
- DocumentProjectionArtifactSurface,
19
- DocumentProjectionEditor,
20
- EditableDocumentArtifactSurface
21
- } from "./chunk-HUIKIDM5.js";
16
+ EditablePresentationArtifactSurface,
17
+ PresentationArtifactSurface,
18
+ PresentationEditor,
19
+ PresentationProjectionArtifactSurface,
20
+ PresentationProjectionEditor
21
+ } from "./chunk-PEI6RANI.js";
22
22
  import {
23
23
  ArtifactSurface,
24
24
  EditableArtifactMessage
@@ -26,6 +26,17 @@ import {
26
26
  import "./chunk-22KP6LR5.js";
27
27
 
28
28
  // src/components/artifacts/published-html-artifact-frame.tsx
29
+ import {
30
+ OPENGENI_SITE_BRIDGE_BOOTSTRAP_GLOBAL,
31
+ OPENGENI_SITE_BRIDGE_READY,
32
+ OPENGENI_SITE_BRIDGE_RESPONSE,
33
+ OPENGENI_SITE_BRIDGE_VERSION,
34
+ isOpenGeniSiteBridgeCancelMessage,
35
+ isOpenGeniSiteBridgeConnectMessage,
36
+ isOpenGeniSiteBridgeRequestMessage,
37
+ sanitizeOpenGeniSiteToolCallRequest
38
+ } from "@opengeni/sdk/site";
39
+ import { useEffect, useRef } from "react";
29
40
  import { jsx } from "react/jsx-runtime";
30
41
  var PUBLISHED_HTML_ARTIFACT_IFRAME_SANDBOX = [
31
42
  "allow-downloads",
@@ -38,25 +49,235 @@ var PUBLISHED_HTML_ARTIFACT_IFRAME_SANDBOX = [
38
49
  "allow-presentation",
39
50
  "allow-scripts"
40
51
  ].join(" ");
52
+ var SITE_BRIDGE_BOOTSTRAP_SCRIPT = `<script>(()=>{const key=${JSON.stringify(
53
+ OPENGENI_SITE_BRIDGE_BOOTSTRAP_GLOBAL
54
+ )};const parentWindow=window.parent;if(parentWindow===window)return;window.addEventListener("message",event=>{const data=event.data;if(event.source!==parentWindow||!data||data.type!==${JSON.stringify(
55
+ OPENGENI_SITE_BRIDGE_READY
56
+ )}||data.version!==${OPENGENI_SITE_BRIDGE_VERSION}||event.ports.length!==1)return;const port=event.ports[0];const previous=window[key]?.port;if(previous&&previous!==port)previous.close();Object.defineProperty(window,key,{configurable:true,value:{port}});port.start();});})();</script>`;
57
+ function publishedHtmlArtifactDocument(html, toolBridgeEnabled) {
58
+ if (!toolBridgeEnabled) return html;
59
+ const doctypeEnd = leadingDoctypeEnd(html);
60
+ if (doctypeEnd >= 0) {
61
+ return `${html.slice(0, doctypeEnd + 1)}${SITE_BRIDGE_BOOTSTRAP_SCRIPT}${html.slice(doctypeEnd + 1)}`;
62
+ }
63
+ return `${SITE_BRIDGE_BOOTSTRAP_SCRIPT}${html}`;
64
+ }
65
+ function leadingDoctypeEnd(html) {
66
+ const lower = html.toLowerCase();
67
+ let cursor = html.charCodeAt(0) === 65279 ? 1 : 0;
68
+ while (cursor < html.length) {
69
+ while (/\s/.test(html[cursor] ?? "")) cursor += 1;
70
+ if (!html.startsWith("<!--", cursor)) break;
71
+ const commentEnd = html.indexOf("-->", cursor + 4);
72
+ if (commentEnd < 0) return -1;
73
+ cursor = commentEnd + 3;
74
+ }
75
+ if (!lower.startsWith("<!doctype", cursor)) return -1;
76
+ return html.indexOf(">", cursor + 9);
77
+ }
41
78
  function PublishedHtmlArtifactFrame(props) {
79
+ const frameRef = useRef(null);
80
+ const bridgeRef = useRef(props.toolBridge);
81
+ const onFrameLoadRef = useRef(() => void 0);
82
+ const frameLoadPendingRef = useRef(false);
83
+ const toolBridgeEnabled = props.toolBridge !== void 0;
84
+ useEffect(() => {
85
+ bridgeRef.current = props.toolBridge;
86
+ }, [props.toolBridge]);
87
+ useEffect(() => {
88
+ if (!toolBridgeEnabled || typeof window === "undefined") return;
89
+ const requests = new SiteBridgeRequestRegistry();
90
+ const attachToolPort = (data, ports) => {
91
+ const port = openGeniSiteBridgePortFromBootstrap(data, ports);
92
+ if (!port) return;
93
+ requests.replacePort(port);
94
+ port.addEventListener("message", (portEvent) => {
95
+ const message = portEvent.data;
96
+ if (isOpenGeniSiteBridgeCancelMessage(message)) {
97
+ requests.cancel(port, message.requestId);
98
+ return;
99
+ }
100
+ if (!isOpenGeniSiteBridgeRequestMessage(message)) return;
101
+ const controller = requests.start(port, message.requestId);
102
+ if (!controller) {
103
+ port.postMessage({
104
+ type: OPENGENI_SITE_BRIDGE_RESPONSE,
105
+ version: OPENGENI_SITE_BRIDGE_VERSION,
106
+ requestId: message.requestId,
107
+ ok: false,
108
+ error: {
109
+ code: "duplicate_request_id",
110
+ message: "A Site tool request with this id is already running",
111
+ retryable: false
112
+ }
113
+ });
114
+ return;
115
+ }
116
+ void handleSiteBridgeRequest(bridgeRef.current, message, controller.signal).then((value) => {
117
+ if (!controller.signal.aborted) {
118
+ port.postMessage({
119
+ type: OPENGENI_SITE_BRIDGE_RESPONSE,
120
+ version: OPENGENI_SITE_BRIDGE_VERSION,
121
+ requestId: message.requestId,
122
+ ok: true,
123
+ value
124
+ });
125
+ }
126
+ }).catch((error) => {
127
+ if (!controller.signal.aborted) {
128
+ port.postMessage({
129
+ type: OPENGENI_SITE_BRIDGE_RESPONSE,
130
+ version: OPENGENI_SITE_BRIDGE_VERSION,
131
+ requestId: message.requestId,
132
+ ok: false,
133
+ error: siteBridgeError(error)
134
+ });
135
+ }
136
+ }).finally(() => requests.complete(port, message.requestId, controller));
137
+ });
138
+ port.addEventListener("messageerror", () => requests.closePort(port));
139
+ port.start();
140
+ port.postMessage({
141
+ type: OPENGENI_SITE_BRIDGE_READY,
142
+ version: OPENGENI_SITE_BRIDGE_VERSION
143
+ });
144
+ };
145
+ const documentLease = new SiteBridgeDocumentLease(attachToolPort, () => requests.closeAll());
146
+ const onFrameLoad = () => {
147
+ frameLoadPendingRef.current = false;
148
+ const frameWindow = frameRef.current?.contentWindow ?? null;
149
+ if (!frameWindow) return;
150
+ documentLease.load(frameWindow);
151
+ };
152
+ onFrameLoadRef.current = onFrameLoad;
153
+ if (frameLoadPendingRef.current) {
154
+ frameLoadPendingRef.current = false;
155
+ onFrameLoad();
156
+ }
157
+ return () => {
158
+ onFrameLoadRef.current = () => void 0;
159
+ documentLease.close();
160
+ };
161
+ }, [props.html, toolBridgeEnabled]);
42
162
  return /* @__PURE__ */ jsx(
43
163
  "iframe",
44
164
  {
165
+ ref: frameRef,
45
166
  title: props.title,
46
167
  sandbox: PUBLISHED_HTML_ARTIFACT_IFRAME_SANDBOX,
47
168
  referrerPolicy: "no-referrer",
48
- srcDoc: props.html,
169
+ srcDoc: publishedHtmlArtifactDocument(props.html, toolBridgeEnabled),
170
+ onLoad: () => {
171
+ frameLoadPendingRef.current = true;
172
+ onFrameLoadRef.current();
173
+ },
49
174
  className: props.className,
50
175
  style: props.style
51
176
  }
52
177
  );
53
178
  }
179
+ var SiteBridgeRequestRegistry = class {
180
+ controllersByPort = /* @__PURE__ */ new Map();
181
+ replacePort(port) {
182
+ this.closeAll();
183
+ this.controllersByPort.set(port, /* @__PURE__ */ new Map());
184
+ }
185
+ start(port, requestId) {
186
+ const controllers = this.controllersByPort.get(port);
187
+ if (!controllers || controllers.has(requestId)) return null;
188
+ const controller = new AbortController();
189
+ controllers.set(requestId, controller);
190
+ return controller;
191
+ }
192
+ cancel(port, requestId) {
193
+ const controllers = this.controllersByPort.get(port);
194
+ const controller = controllers?.get(requestId);
195
+ if (!controller) return;
196
+ controller.abort(new Error("Site tool request cancelled"));
197
+ controllers.delete(requestId);
198
+ }
199
+ complete(port, requestId, controller) {
200
+ const controllers = this.controllersByPort.get(port);
201
+ if (controllers?.get(requestId) === controller) controllers.delete(requestId);
202
+ }
203
+ closePort(port) {
204
+ const controllers = this.controllersByPort.get(port);
205
+ if (!controllers) return;
206
+ for (const controller of controllers.values()) {
207
+ controller.abort(new Error("Site tool bridge port closed"));
208
+ }
209
+ controllers.clear();
210
+ this.controllersByPort.delete(port);
211
+ port.close();
212
+ }
213
+ closeAll() {
214
+ for (const port of [...this.controllersByPort.keys()]) this.closePort(port);
215
+ }
216
+ };
217
+ var SiteBridgeDocumentLease = class {
218
+ constructor(attachToolPort, closeActivePorts, createMessageChannel = () => new MessageChannel()) {
219
+ this.attachToolPort = attachToolPort;
220
+ this.closeActivePorts = closeActivePorts;
221
+ this.createMessageChannel = createMessageChannel;
222
+ }
223
+ loaded = false;
224
+ bootstrapPort = null;
225
+ load(frameWindow) {
226
+ if (this.loaded) {
227
+ this.close();
228
+ return false;
229
+ }
230
+ this.loaded = true;
231
+ const channel = this.createMessageChannel();
232
+ this.bootstrapPort = channel.port1;
233
+ channel.port1.addEventListener("message", (event) => {
234
+ this.attachToolPort(event.data, event.ports);
235
+ });
236
+ channel.port1.start();
237
+ frameWindow.postMessage(
238
+ {
239
+ type: OPENGENI_SITE_BRIDGE_READY,
240
+ version: OPENGENI_SITE_BRIDGE_VERSION
241
+ },
242
+ "*",
243
+ [channel.port2]
244
+ );
245
+ return true;
246
+ }
247
+ close() {
248
+ this.bootstrapPort?.close();
249
+ this.bootstrapPort = null;
250
+ this.closeActivePorts();
251
+ }
252
+ };
253
+ function openGeniSiteBridgePortFromBootstrap(data, ports) {
254
+ if (!isOpenGeniSiteBridgeConnectMessage(data)) return null;
255
+ return ports.length === 1 ? ports[0] : null;
256
+ }
257
+ async function handleSiteBridgeRequest(bridge, message, signal) {
258
+ if (!bridge) throw new Error("Site tool bridge is unavailable");
259
+ if (message.method === "catalog") return await bridge.catalog({ signal });
260
+ if (message.method === "declarations") {
261
+ if (!bridge.declarations) throw new Error("Site tool declarations are unavailable");
262
+ return await bridge.declarations({ signal });
263
+ }
264
+ return await bridge.call(sanitizeOpenGeniSiteToolCallRequest(message.payload), { signal });
265
+ }
266
+ function siteBridgeError(error) {
267
+ const candidate = error;
268
+ return {
269
+ code: typeof candidate?.code === "string" ? candidate.code : "site_tool_call_failed",
270
+ message: typeof candidate?.message === "string" ? candidate.message : "Site tool request failed",
271
+ retryable: candidate?.retryable === true,
272
+ outcomeUnknown: candidate?.outcomeUnknown === true
273
+ };
274
+ }
54
275
 
55
276
  // src/components/artifacts/editable-artifact-workbench.tsx
56
277
  import {
57
278
  createBrowserEditableArtifactSession
58
279
  } from "@opengeni/sdk/editable-artifacts";
59
- import { useCallback, useEffect, useRef, useState } from "react";
280
+ import { useCallback, useEffect as useEffect2, useRef as useRef2, useState } from "react";
60
281
  import { jsx as jsx2 } from "react/jsx-runtime";
61
282
  function EditableArtifactWorkbench({
62
283
  session,
@@ -87,13 +308,13 @@ function EditableArtifactWorkbenchHost({
87
308
  spreadsheet,
88
309
  presentation
89
310
  }) {
90
- const createSessionRef = useRef(createSession);
311
+ const createSessionRef = useRef2(createSession);
91
312
  const [retryEpoch, setRetryEpoch] = useState(0);
92
313
  const [state, setState] = useState({ key: null, session: null, error: null });
93
- useEffect(() => {
314
+ useEffect2(() => {
94
315
  createSessionRef.current = createSession;
95
316
  }, [createSession]);
96
- useEffect(() => {
317
+ useEffect2(() => {
97
318
  let owned = null;
98
319
  setState({ key: sessionKey, session: null, error: null });
99
320
  try {
@@ -194,6 +415,8 @@ export {
194
415
  PublishedHtmlArtifactFrame,
195
416
  SpreadsheetArtifactSurface,
196
417
  SpreadsheetGrid,
197
- SpreadsheetProjectionGrid
418
+ SpreadsheetProjectionGrid,
419
+ openGeniSiteBridgePortFromBootstrap,
420
+ publishedHtmlArtifactDocument
198
421
  };
199
422
  //# sourceMappingURL=artifacts.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/artifacts/published-html-artifact-frame.tsx","../src/components/artifacts/editable-artifact-workbench.tsx"],"sourcesContent":["import type { CSSProperties } from \"react\";\n\nexport const PUBLISHED_HTML_ARTIFACT_IFRAME_SANDBOX = [\n \"allow-downloads\",\n \"allow-forms\",\n \"allow-modals\",\n \"allow-orientation-lock\",\n \"allow-pointer-lock\",\n \"allow-popups\",\n \"allow-popups-to-escape-sandbox\",\n \"allow-presentation\",\n \"allow-scripts\",\n].join(\" \");\n\nexport type PublishedHtmlArtifactFrameProps = {\n html: string;\n title: string;\n className?: string;\n style?: CSSProperties;\n};\n\n/**\n * Render exact published HTML in an opaque-origin iframe. Artifact scripts,\n * external resources, forms, popups, and downloads work without granting\n * parent-origin authority, shared cookies/storage, or top-level navigation.\n */\nexport function PublishedHtmlArtifactFrame(props: PublishedHtmlArtifactFrameProps) {\n return (\n <iframe\n title={props.title}\n sandbox={PUBLISHED_HTML_ARTIFACT_IFRAME_SANDBOX}\n referrerPolicy=\"no-referrer\"\n srcDoc={props.html}\n className={props.className}\n style={props.style}\n />\n );\n}\n","import {\n createBrowserEditableArtifactSession,\n type CreateBrowserEditableArtifactSessionOptions,\n type EditableArtifactBrowserRuntime,\n type EditableArtifactSession,\n} from \"@opengeni/sdk/editable-artifacts\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { EditableArtifactMessage } from \"./editable-artifact-ui\";\nimport {\n EditableDocumentArtifactSurface,\n type EditableDocumentArtifactSurfaceProps,\n} from \"./editable-document\";\nimport {\n EditablePresentationArtifactSurface,\n type EditablePresentationArtifactSurfaceProps,\n} from \"./editable-presentation\";\nimport {\n EditableSpreadsheetArtifactSurface,\n type EditableSpreadsheetArtifactSurfaceProps,\n} from \"./editable-spreadsheet\";\n\nexport type EditableArtifactWorkbenchProps = Readonly<{\n session: EditableArtifactSession;\n document?: Omit<EditableDocumentArtifactSurfaceProps, \"session\">;\n spreadsheet?: Omit<EditableSpreadsheetArtifactSurfaceProps, \"session\">;\n presentation?: Omit<EditablePresentationArtifactSurfaceProps, \"session\">;\n}>;\n\nexport type EditableArtifactWorkbenchHostProps = Omit<EditableArtifactWorkbenchProps, \"session\"> &\n Readonly<{\n /**\n * Complete identity of the browser session authority. Change this when the\n * artifact, deployment, principal, or authorization epoch changes.\n */\n sessionKey: string;\n /** Called for the active keyed lifecycle and again only after replacement or retry. */\n createSession: () => EditableArtifactSession;\n }>;\n\ntype DefaultBrowserArtifactTransport = Omit<\n NonNullable<CreateBrowserEditableArtifactSessionOptions[\"transport\"]>,\n \"apiKey\" | \"fetch\" | \"headers\" | \"webSocketFactory\"\n> &\n Readonly<{\n /** Static deployment auth headers; rotate authorizationEpoch when they change. */\n headers?: Readonly<Record<string, string>>;\n }>;\n\nexport type BrowserEditableArtifactWorkbenchOptions = Omit<\n CreateBrowserEditableArtifactSessionOptions,\n \"runtime\" | \"storage\" | \"transport\"\n> &\n Readonly<{\n /** Default module Worker only; custom Worker hosts use EditableArtifactWorkbenchHost. */\n runtime: Omit<EditableArtifactBrowserRuntime, \"workerFactory\">;\n /** Default fetch/WebSocket only; static deployment auth headers are supported. */\n transport?: DefaultBrowserArtifactTransport;\n }>;\n\nexport type BrowserEditableArtifactWorkbenchProps = Omit<\n EditableArtifactWorkbenchProps,\n \"session\"\n> &\n Readonly<{ options: BrowserEditableArtifactWorkbenchOptions }>;\n\n/**\n * One modality-neutral SDK workbench. Embedding hosts keep one route/component;\n * each artifact still renders through its complete first-party editor surface.\n */\nexport function EditableArtifactWorkbench({\n session,\n document,\n spreadsheet,\n presentation,\n}: EditableArtifactWorkbenchProps) {\n switch (session.modality) {\n case \"document\":\n return (\n <EditableDocumentArtifactSurface\n {...document}\n session={session}\n title={document?.title ?? \"Document\"}\n />\n );\n case \"spreadsheet\":\n return <EditableSpreadsheetArtifactSurface {...spreadsheet} session={session} />;\n case \"presentation\":\n return <EditablePresentationArtifactSurface {...presentation} session={session} />;\n }\n}\n\n/**\n * Route/embed composition that owns exactly one SDK session. The host supplies\n * the authenticated SDK factory; React guarantees replacement and teardown.\n */\nexport function EditableArtifactWorkbenchHost({\n sessionKey,\n createSession,\n document,\n spreadsheet,\n presentation,\n}: EditableArtifactWorkbenchHostProps) {\n const createSessionRef = useRef(createSession);\n const [retryEpoch, setRetryEpoch] = useState(0);\n const [state, setState] = useState<\n | Readonly<{ key: string; session: EditableArtifactSession; error: null }>\n | Readonly<{ key: string | null; session: null; error: Error | null }>\n >({ key: null, session: null, error: null });\n\n useEffect(() => {\n createSessionRef.current = createSession;\n }, [createSession]);\n\n useEffect(() => {\n let owned: EditableArtifactSession | null = null;\n setState({ key: sessionKey, session: null, error: null });\n try {\n owned = createSessionRef.current();\n setState({ key: sessionKey, session: owned, error: null });\n } catch (cause) {\n setState({\n key: sessionKey,\n session: null,\n error: cause instanceof Error ? cause : new Error(\"Could not create artifact session\"),\n });\n }\n return () => {\n const closing = owned;\n owned = null;\n if (closing) void closing.close().catch(() => undefined);\n };\n }, [retryEpoch, sessionKey]);\n\n const retry = useCallback(() => setRetryEpoch((value) => value + 1), []);\n const currentError = state.key === sessionKey ? state.error : null;\n if (state.key === sessionKey && state.session) {\n return (\n <EditableArtifactWorkbench\n session={state.session}\n {...(document ? { document } : {})}\n {...(spreadsheet ? { spreadsheet } : {})}\n {...(presentation ? { presentation } : {})}\n />\n );\n }\n return (\n <EditableArtifactMessage\n title={currentError ? \"Could not open this artifact\" : \"Opening artifact\"}\n detail={currentError?.message ?? \"Starting the secure editing session…\"}\n retry={currentError ? retry : undefined}\n />\n );\n}\n\n/**\n * Complete default-browser composition for embedders: verified WASM Worker,\n * durable IndexedDB state, authenticated live sync, teardown, and the matching\n * first-party editor. Advanced/custom transports compose the lower-level host.\n */\nexport function BrowserEditableArtifactWorkbench({\n options,\n document,\n spreadsheet,\n presentation,\n}: BrowserEditableArtifactWorkbenchProps) {\n const sessionKey = browserSessionKey(options);\n const createSession = useCallback(() => createBrowserEditableArtifactSession(options), [options]);\n return (\n <EditableArtifactWorkbenchHost\n sessionKey={sessionKey}\n createSession={createSession}\n {...(document ? { document } : {})}\n {...(spreadsheet ? { spreadsheet } : {})}\n {...(presentation ? { presentation } : {})}\n />\n );\n}\n\nfunction browserSessionKey(options: BrowserEditableArtifactWorkbenchOptions): string {\n const transport = options.transport\n ? {\n ...options.transport,\n // Credentials must not be copied into React lifecycle keys. The\n // authorization epoch is the explicit credential/grant rotation fence.\n headers: options.transport.headers\n ? Object.keys(options.transport.headers).sort()\n : undefined,\n }\n : null;\n return JSON.stringify(\n {\n baseUrl: options.baseUrl,\n workspaceId: options.workspaceId,\n artifact: { id: options.artifact.id, modality: options.artifact.modality },\n storageAuthority: options.storageAuthority,\n runtime: options.runtime,\n replicaId: options.replicaId ?? null,\n transport,\n },\n (_key, value: unknown) => (value instanceof URL ? value.href : value),\n );\n}\n"],"mappings":"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","names":["jsx"]}
1
+ {"version":3,"sources":["../src/components/artifacts/published-html-artifact-frame.tsx","../src/components/artifacts/editable-artifact-workbench.tsx"],"sourcesContent":["import {\n OPENGENI_SITE_BRIDGE_BOOTSTRAP_GLOBAL,\n OPENGENI_SITE_BRIDGE_READY,\n OPENGENI_SITE_BRIDGE_RESPONSE,\n OPENGENI_SITE_BRIDGE_VERSION,\n isOpenGeniSiteBridgeCancelMessage,\n isOpenGeniSiteBridgeConnectMessage,\n isOpenGeniSiteBridgeRequestMessage,\n sanitizeOpenGeniSiteToolCallRequest,\n type OpenGeniSiteBridgeResponseMessage,\n type OpenGeniSiteToolCatalog,\n} from \"@opengeni/sdk/site\";\nimport type {\n ToolGatewayCallRequest,\n ToolGatewayCallResponse,\n ToolGatewayDeclarationsResponse,\n} from \"@opengeni/sdk\";\nimport { useEffect, useRef, type CSSProperties } from \"react\";\n\nexport const PUBLISHED_HTML_ARTIFACT_IFRAME_SANDBOX = [\n \"allow-downloads\",\n \"allow-forms\",\n \"allow-modals\",\n \"allow-orientation-lock\",\n \"allow-pointer-lock\",\n \"allow-popups\",\n \"allow-popups-to-escape-sandbox\",\n \"allow-presentation\",\n \"allow-scripts\",\n].join(\" \");\n\nexport type PublishedHtmlArtifactFrameProps = {\n html: string;\n title: string;\n className?: string;\n style?: CSSProperties;\n toolBridge?: PublishedHtmlArtifactToolBridge;\n};\n\nexport type PublishedHtmlArtifactToolBridge = {\n catalog: (options: { signal: AbortSignal }) => Promise<OpenGeniSiteToolCatalog>;\n call: (\n request: ToolGatewayCallRequest,\n options: { signal: AbortSignal },\n ) => Promise<ToolGatewayCallResponse>;\n declarations?: (options: { signal: AbortSignal }) => Promise<ToolGatewayDeclarationsResponse>;\n};\n\nconst SITE_BRIDGE_BOOTSTRAP_SCRIPT = `<script>(()=>{const key=${JSON.stringify(\n OPENGENI_SITE_BRIDGE_BOOTSTRAP_GLOBAL,\n)};const parentWindow=window.parent;if(parentWindow===window)return;window.addEventListener(\"message\",event=>{const data=event.data;if(event.source!==parentWindow||!data||data.type!==${JSON.stringify(\n OPENGENI_SITE_BRIDGE_READY,\n)}||data.version!==${OPENGENI_SITE_BRIDGE_VERSION}||event.ports.length!==1)return;const port=event.ports[0];const previous=window[key]?.port;if(previous&&previous!==port)previous.close();Object.defineProperty(window,key,{configurable:true,value:{port}});port.start();});})();</script>`;\n\nexport function publishedHtmlArtifactDocument(html: string, toolBridgeEnabled: boolean): string {\n if (!toolBridgeEnabled) return html;\n const doctypeEnd = leadingDoctypeEnd(html);\n if (doctypeEnd >= 0) {\n return `${html.slice(0, doctypeEnd + 1)}${SITE_BRIDGE_BOOTSTRAP_SCRIPT}${html.slice(doctypeEnd + 1)}`;\n }\n return `${SITE_BRIDGE_BOOTSTRAP_SCRIPT}${html}`;\n}\n\nfunction leadingDoctypeEnd(html: string): number {\n const lower = html.toLowerCase();\n let cursor = html.charCodeAt(0) === 0xfeff ? 1 : 0;\n while (cursor < html.length) {\n while (/\\s/.test(html[cursor] ?? \"\")) cursor += 1;\n if (!html.startsWith(\"<!--\", cursor)) break;\n const commentEnd = html.indexOf(\"-->\", cursor + 4);\n if (commentEnd < 0) return -1;\n cursor = commentEnd + 3;\n }\n if (!lower.startsWith(\"<!doctype\", cursor)) return -1;\n return html.indexOf(\">\", cursor + 9);\n}\n\n/**\n * Render exact published HTML in an opaque-origin iframe. Artifact scripts,\n * external resources, forms, popups, downloads, and the host-filtered tool\n * bridge work without granting parent-origin authority, shared cookies/storage,\n * or top-level navigation.\n */\nexport function PublishedHtmlArtifactFrame(props: PublishedHtmlArtifactFrameProps) {\n const frameRef = useRef<HTMLIFrameElement | null>(null);\n const bridgeRef = useRef(props.toolBridge);\n const onFrameLoadRef = useRef<() => void>(() => undefined);\n const frameLoadPendingRef = useRef(false);\n const toolBridgeEnabled = props.toolBridge !== undefined;\n useEffect(() => {\n bridgeRef.current = props.toolBridge;\n }, [props.toolBridge]);\n useEffect(() => {\n if (!toolBridgeEnabled || typeof window === \"undefined\") return;\n const requests = new SiteBridgeRequestRegistry();\n const attachToolPort = (data: unknown, ports: readonly MessagePort[]) => {\n const port = openGeniSiteBridgePortFromBootstrap(data, ports);\n if (!port) return;\n requests.replacePort(port);\n port.addEventListener(\"message\", (portEvent: MessageEvent<unknown>) => {\n const message = portEvent.data;\n if (isOpenGeniSiteBridgeCancelMessage(message)) {\n requests.cancel(port, message.requestId);\n return;\n }\n if (!isOpenGeniSiteBridgeRequestMessage(message)) return;\n const controller = requests.start(port, message.requestId);\n if (!controller) {\n port.postMessage({\n type: OPENGENI_SITE_BRIDGE_RESPONSE,\n version: OPENGENI_SITE_BRIDGE_VERSION,\n requestId: message.requestId,\n ok: false,\n error: {\n code: \"duplicate_request_id\",\n message: \"A Site tool request with this id is already running\",\n retryable: false,\n },\n } satisfies OpenGeniSiteBridgeResponseMessage);\n return;\n }\n void handleSiteBridgeRequest(bridgeRef.current, message, controller.signal)\n .then((value) => {\n if (!controller.signal.aborted) {\n port.postMessage({\n type: OPENGENI_SITE_BRIDGE_RESPONSE,\n version: OPENGENI_SITE_BRIDGE_VERSION,\n requestId: message.requestId,\n ok: true,\n value,\n } satisfies OpenGeniSiteBridgeResponseMessage);\n }\n })\n .catch((error) => {\n if (!controller.signal.aborted) {\n port.postMessage({\n type: OPENGENI_SITE_BRIDGE_RESPONSE,\n version: OPENGENI_SITE_BRIDGE_VERSION,\n requestId: message.requestId,\n ok: false,\n error: siteBridgeError(error),\n } satisfies OpenGeniSiteBridgeResponseMessage);\n }\n })\n .finally(() => requests.complete(port, message.requestId, controller));\n });\n port.addEventListener(\"messageerror\", () => requests.closePort(port));\n port.start();\n port.postMessage({\n type: OPENGENI_SITE_BRIDGE_READY,\n version: OPENGENI_SITE_BRIDGE_VERSION,\n });\n };\n const documentLease = new SiteBridgeDocumentLease(attachToolPort, () => requests.closeAll());\n const onFrameLoad = () => {\n frameLoadPendingRef.current = false;\n const frameWindow = frameRef.current?.contentWindow ?? null;\n if (!frameWindow) return;\n documentLease.load(frameWindow);\n };\n onFrameLoadRef.current = onFrameLoad;\n if (frameLoadPendingRef.current) {\n frameLoadPendingRef.current = false;\n onFrameLoad();\n }\n return () => {\n onFrameLoadRef.current = () => undefined;\n documentLease.close();\n };\n }, [props.html, toolBridgeEnabled]);\n return (\n <iframe\n ref={frameRef}\n title={props.title}\n sandbox={PUBLISHED_HTML_ARTIFACT_IFRAME_SANDBOX}\n referrerPolicy=\"no-referrer\"\n srcDoc={publishedHtmlArtifactDocument(props.html, toolBridgeEnabled)}\n onLoad={() => {\n frameLoadPendingRef.current = true;\n onFrameLoadRef.current();\n }}\n className={props.className}\n style={props.style}\n />\n );\n}\n\nexport class SiteBridgeRequestRegistry {\n private readonly controllersByPort = new Map<MessagePort, Map<string, AbortController>>();\n\n replacePort(port: MessagePort): void {\n this.closeAll();\n this.controllersByPort.set(port, new Map());\n }\n\n start(port: MessagePort, requestId: string): AbortController | null {\n const controllers = this.controllersByPort.get(port);\n if (!controllers || controllers.has(requestId)) return null;\n const controller = new AbortController();\n controllers.set(requestId, controller);\n return controller;\n }\n\n cancel(port: MessagePort, requestId: string): void {\n const controllers = this.controllersByPort.get(port);\n const controller = controllers?.get(requestId);\n if (!controller) return;\n controller.abort(new Error(\"Site tool request cancelled\"));\n controllers!.delete(requestId);\n }\n\n complete(port: MessagePort, requestId: string, controller: AbortController): void {\n const controllers = this.controllersByPort.get(port);\n if (controllers?.get(requestId) === controller) controllers.delete(requestId);\n }\n\n closePort(port: MessagePort): void {\n const controllers = this.controllersByPort.get(port);\n if (!controllers) return;\n for (const controller of controllers.values()) {\n controller.abort(new Error(\"Site tool bridge port closed\"));\n }\n controllers.clear();\n this.controllersByPort.delete(port);\n port.close();\n }\n\n closeAll(): void {\n for (const port of [...this.controllersByPort.keys()]) this.closePort(port);\n }\n}\n\nexport class SiteBridgeDocumentLease {\n private loaded = false;\n private bootstrapPort: MessagePort | null = null;\n\n constructor(\n private readonly attachToolPort: (data: unknown, ports: readonly MessagePort[]) => void,\n private readonly closeActivePorts: () => void,\n private readonly createMessageChannel: () => MessageChannel = () => new MessageChannel(),\n ) {}\n\n load(frameWindow: Pick<Window, \"postMessage\">): boolean {\n if (this.loaded) {\n this.close();\n return false;\n }\n this.loaded = true;\n const channel = this.createMessageChannel();\n this.bootstrapPort = channel.port1;\n channel.port1.addEventListener(\"message\", (event: MessageEvent<unknown>) => {\n this.attachToolPort(event.data, event.ports);\n });\n channel.port1.start();\n frameWindow.postMessage(\n {\n type: OPENGENI_SITE_BRIDGE_READY,\n version: OPENGENI_SITE_BRIDGE_VERSION,\n },\n \"*\",\n [channel.port2],\n );\n return true;\n }\n\n close(): void {\n this.bootstrapPort?.close();\n this.bootstrapPort = null;\n this.closeActivePorts();\n }\n}\n\nexport function openGeniSiteBridgePortFromBootstrap(\n data: unknown,\n ports: readonly MessagePort[],\n): MessagePort | null {\n if (!isOpenGeniSiteBridgeConnectMessage(data)) return null;\n return ports.length === 1 ? ports[0]! : null;\n}\n\nasync function handleSiteBridgeRequest(\n bridge: PublishedHtmlArtifactToolBridge | undefined,\n message: Parameters<typeof isOpenGeniSiteBridgeRequestMessage>[0] & {\n method: \"catalog\" | \"call\" | \"declarations\";\n requestId: string;\n payload?: ToolGatewayCallRequest;\n },\n signal: AbortSignal,\n): Promise<OpenGeniSiteToolCatalog | ToolGatewayCallResponse | ToolGatewayDeclarationsResponse> {\n if (!bridge) throw new Error(\"Site tool bridge is unavailable\");\n if (message.method === \"catalog\") return await bridge.catalog({ signal });\n if (message.method === \"declarations\") {\n if (!bridge.declarations) throw new Error(\"Site tool declarations are unavailable\");\n return await bridge.declarations({ signal });\n }\n return await bridge.call(sanitizeOpenGeniSiteToolCallRequest(message.payload!), { signal });\n}\n\nexport function siteBridgeError(error: unknown): {\n code: string;\n message: string;\n retryable: boolean;\n outcomeUnknown: boolean;\n} {\n const candidate = error as {\n code?: unknown;\n message?: unknown;\n retryable?: unknown;\n outcomeUnknown?: unknown;\n };\n return {\n code: typeof candidate?.code === \"string\" ? candidate.code : \"site_tool_call_failed\",\n message:\n typeof candidate?.message === \"string\" ? candidate.message : \"Site tool request failed\",\n retryable: candidate?.retryable === true,\n outcomeUnknown: candidate?.outcomeUnknown === true,\n };\n}\n","import {\n createBrowserEditableArtifactSession,\n type CreateBrowserEditableArtifactSessionOptions,\n type EditableArtifactBrowserRuntime,\n type EditableArtifactSession,\n} from \"@opengeni/sdk/editable-artifacts\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { EditableArtifactMessage } from \"./editable-artifact-ui\";\nimport {\n EditableDocumentArtifactSurface,\n type EditableDocumentArtifactSurfaceProps,\n} from \"./editable-document\";\nimport {\n EditablePresentationArtifactSurface,\n type EditablePresentationArtifactSurfaceProps,\n} from \"./editable-presentation\";\nimport {\n EditableSpreadsheetArtifactSurface,\n type EditableSpreadsheetArtifactSurfaceProps,\n} from \"./editable-spreadsheet\";\n\nexport type EditableArtifactWorkbenchProps = Readonly<{\n session: EditableArtifactSession;\n document?: Omit<EditableDocumentArtifactSurfaceProps, \"session\">;\n spreadsheet?: Omit<EditableSpreadsheetArtifactSurfaceProps, \"session\">;\n presentation?: Omit<EditablePresentationArtifactSurfaceProps, \"session\">;\n}>;\n\nexport type EditableArtifactWorkbenchHostProps = Omit<EditableArtifactWorkbenchProps, \"session\"> &\n Readonly<{\n /**\n * Complete identity of the browser session authority. Change this when the\n * artifact, deployment, principal, or authorization epoch changes.\n */\n sessionKey: string;\n /** Called for the active keyed lifecycle and again only after replacement or retry. */\n createSession: () => EditableArtifactSession;\n }>;\n\ntype DefaultBrowserArtifactTransport = Omit<\n NonNullable<CreateBrowserEditableArtifactSessionOptions[\"transport\"]>,\n \"apiKey\" | \"fetch\" | \"headers\" | \"webSocketFactory\"\n> &\n Readonly<{\n /** Static deployment auth headers; rotate authorizationEpoch when they change. */\n headers?: Readonly<Record<string, string>>;\n }>;\n\nexport type BrowserEditableArtifactWorkbenchOptions = Omit<\n CreateBrowserEditableArtifactSessionOptions,\n \"runtime\" | \"storage\" | \"transport\"\n> &\n Readonly<{\n /** Default module Worker only; custom Worker hosts use EditableArtifactWorkbenchHost. */\n runtime: Omit<EditableArtifactBrowserRuntime, \"workerFactory\">;\n /** Default fetch/WebSocket only; static deployment auth headers are supported. */\n transport?: DefaultBrowserArtifactTransport;\n }>;\n\nexport type BrowserEditableArtifactWorkbenchProps = Omit<\n EditableArtifactWorkbenchProps,\n \"session\"\n> &\n Readonly<{ options: BrowserEditableArtifactWorkbenchOptions }>;\n\n/**\n * One modality-neutral SDK workbench. Embedding hosts keep one route/component;\n * each artifact still renders through its complete first-party editor surface.\n */\nexport function EditableArtifactWorkbench({\n session,\n document,\n spreadsheet,\n presentation,\n}: EditableArtifactWorkbenchProps) {\n switch (session.modality) {\n case \"document\":\n return (\n <EditableDocumentArtifactSurface\n {...document}\n session={session}\n title={document?.title ?? \"Document\"}\n />\n );\n case \"spreadsheet\":\n return <EditableSpreadsheetArtifactSurface {...spreadsheet} session={session} />;\n case \"presentation\":\n return <EditablePresentationArtifactSurface {...presentation} session={session} />;\n }\n}\n\n/**\n * Route/embed composition that owns exactly one SDK session. The host supplies\n * the authenticated SDK factory; React guarantees replacement and teardown.\n */\nexport function EditableArtifactWorkbenchHost({\n sessionKey,\n createSession,\n document,\n spreadsheet,\n presentation,\n}: EditableArtifactWorkbenchHostProps) {\n const createSessionRef = useRef(createSession);\n const [retryEpoch, setRetryEpoch] = useState(0);\n const [state, setState] = useState<\n | Readonly<{ key: string; session: EditableArtifactSession; error: null }>\n | Readonly<{ key: string | null; session: null; error: Error | null }>\n >({ key: null, session: null, error: null });\n\n useEffect(() => {\n createSessionRef.current = createSession;\n }, [createSession]);\n\n useEffect(() => {\n let owned: EditableArtifactSession | null = null;\n setState({ key: sessionKey, session: null, error: null });\n try {\n owned = createSessionRef.current();\n setState({ key: sessionKey, session: owned, error: null });\n } catch (cause) {\n setState({\n key: sessionKey,\n session: null,\n error: cause instanceof Error ? cause : new Error(\"Could not create artifact session\"),\n });\n }\n return () => {\n const closing = owned;\n owned = null;\n if (closing) void closing.close().catch(() => undefined);\n };\n }, [retryEpoch, sessionKey]);\n\n const retry = useCallback(() => setRetryEpoch((value) => value + 1), []);\n const currentError = state.key === sessionKey ? state.error : null;\n if (state.key === sessionKey && state.session) {\n return (\n <EditableArtifactWorkbench\n session={state.session}\n {...(document ? { document } : {})}\n {...(spreadsheet ? { spreadsheet } : {})}\n {...(presentation ? { presentation } : {})}\n />\n );\n }\n return (\n <EditableArtifactMessage\n title={currentError ? \"Could not open this artifact\" : \"Opening artifact\"}\n detail={currentError?.message ?? \"Starting the secure editing session…\"}\n retry={currentError ? retry : undefined}\n />\n );\n}\n\n/**\n * Complete default-browser composition for embedders: verified WASM Worker,\n * durable IndexedDB state, authenticated live sync, teardown, and the matching\n * first-party editor. Advanced/custom transports compose the lower-level host.\n */\nexport function BrowserEditableArtifactWorkbench({\n options,\n document,\n spreadsheet,\n presentation,\n}: BrowserEditableArtifactWorkbenchProps) {\n const sessionKey = browserSessionKey(options);\n const createSession = useCallback(() => createBrowserEditableArtifactSession(options), [options]);\n return (\n <EditableArtifactWorkbenchHost\n sessionKey={sessionKey}\n createSession={createSession}\n {...(document ? { document } : {})}\n {...(spreadsheet ? { spreadsheet } : {})}\n {...(presentation ? { presentation } : {})}\n />\n );\n}\n\nfunction browserSessionKey(options: BrowserEditableArtifactWorkbenchOptions): string {\n const transport = options.transport\n ? {\n ...options.transport,\n // Credentials must not be copied into React lifecycle keys. The\n // authorization epoch is the explicit credential/grant rotation fence.\n headers: options.transport.headers\n ? Object.keys(options.transport.headers).sort()\n : undefined,\n }\n : null;\n return JSON.stringify(\n {\n baseUrl: options.baseUrl,\n workspaceId: options.workspaceId,\n artifact: { id: options.artifact.id, modality: options.artifact.modality },\n storageAuthority: options.storageAuthority,\n runtime: options.runtime,\n replicaId: options.replicaId ?? null,\n transport,\n },\n (_key, value: unknown) => (value instanceof URL ? value.href : value),\n );\n}\n"],"mappings":"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","names":["useEffect","useRef","jsx","useRef","useEffect"]}
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  BrowserViewer
3
- } from "./chunk-ZPBTI3TE.js";
3
+ } from "./chunk-W2RGYBCV.js";
4
4
  import "./chunk-H5YGYNXS.js";
5
5
  import "./chunk-5YK2ZDIG.js";
6
+ import "./chunk-JVYQRRC4.js";
6
7
  import "./chunk-KZ73RL76.js";
7
8
  import "./chunk-NEXLLTP4.js";
8
- import "./chunk-JVYQRRC4.js";
9
9
  import "./chunk-VTOREEXF.js";
10
10
  import "./chunk-22KP6LR5.js";
11
11
  export {
12
12
  BrowserViewer
13
13
  };
14
- //# sourceMappingURL=browser-viewer-MKKFRRRV.js.map
14
+ //# sourceMappingURL=browser-viewer-E5DDEFQ4.js.map
@@ -1,15 +1,16 @@
1
+ import {
2
+ usePortalTokenSource,
3
+ usePortalTokenStyle
4
+ } from "./chunk-VZTQ73XT.js";
1
5
  import {
2
6
  effortOptionsForModel,
3
7
  findPickerRow,
4
8
  groupPickerRowsByBillingClass,
5
9
  labelReasoningEffort,
10
+ payerSummaryForModel,
6
11
  projectClientModelRows,
7
12
  runnableLatencyModesForModel
8
- } from "./chunk-X4A66EWZ.js";
9
- import {
10
- usePortalTokenSource,
11
- usePortalTokenStyle
12
- } from "./chunk-VZTQ73XT.js";
13
+ } from "./chunk-WMGF4Z7X.js";
13
14
  import {
14
15
  cn
15
16
  } from "./chunk-22KP6LR5.js";
@@ -46,7 +47,8 @@ var defaultModelPolicyPickerMessages = {
46
47
  external: "Provider terms and limits apply",
47
48
  codex_subscription: "ChatGPT / Codex plan",
48
49
  supergrok_subscription: "SuperGrok / xAI plan",
49
- byok: "Billed to your AI Gateway"
50
+ byok: "Billed to the workspace provider account",
51
+ organization_byok: "Billed to the organization provider account"
50
52
  }
51
53
  };
52
54
  var SLIDE_EASE = [0.22, 1, 0.36, 1];
@@ -82,7 +84,8 @@ function BillingClassMark(props) {
82
84
  external: "External provider",
83
85
  codex_subscription: "Codex",
84
86
  supergrok_subscription: "SuperGrok",
85
- byok: "Bring your own key"
87
+ byok: "Workspace provider account",
88
+ organization_byok: "Organization provider account"
86
89
  };
87
90
  const label = props["aria-label"] ?? labels[props.billingClass];
88
91
  const accessibility = label.length === 0 ? { "aria-hidden": true } : { role: "img", "aria-label": label };
@@ -104,6 +107,14 @@ function BillingClassMark(props) {
104
107
  function isCodexModel(model) {
105
108
  return model.id.startsWith("codex/") || model.source === "codex";
106
109
  }
110
+ function billingClassForMissingSelection(modelId) {
111
+ if (modelId.startsWith("workspace-gateway/")) return "byok";
112
+ if (modelId.startsWith("workspace-openrouter/")) return "byok";
113
+ if (modelId.startsWith("openrouter/")) return "opengeni_credits";
114
+ if (modelId.startsWith("codex/")) return "codex_subscription";
115
+ if (modelId.startsWith("supergrok/")) return "supergrok_subscription";
116
+ return "opengeni_credits";
117
+ }
107
118
  function applyCodexOnly(rows, codexOnly, unavailableReason) {
108
119
  if (!codexOnly) return rows;
109
120
  return rows.map(
@@ -126,7 +137,11 @@ function defaultNavState(rows, modelId) {
126
137
  const onlyRail = rails.size === 1 ? rows[0]?.billingClass : null;
127
138
  return onlyRail ? { level: "models", rail: onlyRail, modelId: null } : { level: "providers", rail: null, modelId: null };
128
139
  }
129
- return { level: "thinking", rail: selected.billingClass, modelId: selected.id };
140
+ return {
141
+ level: "thinking",
142
+ rail: selected.billingClass,
143
+ modelId: selected.id
144
+ };
130
145
  }
131
146
  function usePickerNavState(sessionKey, rows, model) {
132
147
  const [state, setState] = useState(() => defaultNavState(rows, model));
@@ -208,7 +223,11 @@ function ModelPolicyPickerMenu(props) {
208
223
  const nav = props.nav ?? localNav;
209
224
  const setNav = props.onNavChange ?? setLocalNav;
210
225
  const [direction, setDirection] = useState(1);
211
- const effectiveNav = nav.level === "providers" && groups.length === 1 ? { level: "models", rail: groups[0].billingClass, modelId: null } : nav;
226
+ const effectiveNav = nav.level === "providers" && groups.length === 1 ? {
227
+ level: "models",
228
+ rail: groups[0].billingClass,
229
+ modelId: null
230
+ } : nav;
212
231
  const activeGroup = effectiveNav.rail === null ? void 0 : groups.find((group) => group.billingClass === effectiveNav.rail);
213
232
  const focusModel = effectiveNav.modelId === null ? void 0 : findPickerRow(rows, effectiveNav.modelId);
214
233
  const selectedRow = findPickerRow(rows, props.model);
@@ -254,14 +273,21 @@ function ModelPolicyPickerMenu(props) {
254
273
  PickerNavRow,
255
274
  {
256
275
  label: row.label,
257
- hint: row.unavailableReason ?? void 0,
276
+ hint: row.unavailableReason ?? payerSummaryForModel(row.catalog),
258
277
  disabled: !row.selectable,
259
278
  title: row.unavailableReason ?? void 0,
260
279
  active: row.id === props.model,
261
280
  testId: `model-picker-choice-${row.id}`,
262
281
  onClick: () => {
263
282
  if (row.selectable) {
264
- go({ level: "thinking", rail: row.billingClass, modelId: row.id }, 1);
283
+ go(
284
+ {
285
+ level: "thinking",
286
+ rail: row.billingClass,
287
+ modelId: row.id
288
+ },
289
+ 1
290
+ );
265
291
  }
266
292
  }
267
293
  },
@@ -419,7 +445,7 @@ function ModelPolicyPicker(props) {
419
445
  /* @__PURE__ */ jsx(
420
446
  BillingClassMark,
421
447
  {
422
- billingClass: selected?.billingClass ?? (props.model.startsWith("codex/") ? "codex_subscription" : "opengeni_credits"),
448
+ billingClass: selected?.billingClass ?? billingClassForMissingSelection(props.model),
423
449
  className: "text-og-fg"
424
450
  }
425
451
  ),
@@ -467,4 +493,4 @@ export {
467
493
  ModelPolicyPickerMenu,
468
494
  ModelPolicyPicker
469
495
  };
470
- //# sourceMappingURL=chunk-2DZVYHVO.js.map
496
+ //# sourceMappingURL=chunk-4JFUT22W.js.map