@opengeni/react 1.4.0 → 1.4.2

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 (212) hide show
  1. package/README.md +8 -0
  2. package/dist/accounts.js +2 -0
  3. package/dist/accounts.js.map +1 -1
  4. package/dist/artifacts-document.js +5 -4
  5. package/dist/artifacts-presentation.js +5 -4
  6. package/dist/artifacts-spreadsheet.js +4 -3
  7. package/dist/artifacts.js +14 -13
  8. package/dist/artifacts.js.map +1 -1
  9. package/dist/browser-viewer-WGJ43YGI.js +17 -0
  10. package/dist/chat-interactive-block-ZFHOKTMS.js +12 -0
  11. package/dist/{chunk-WEHMPOXK.js → chunk-2DDJ6YH6.js} +3 -1
  12. package/dist/{chunk-WEHMPOXK.js.map → chunk-2DDJ6YH6.js.map} +1 -1
  13. package/dist/{chunk-C5X5AJXK.js → chunk-2HVLQ26H.js} +5 -4
  14. package/dist/{chunk-C5X5AJXK.js.map → chunk-2HVLQ26H.js.map} +1 -1
  15. package/dist/{chunk-A4UJB2MM.js → chunk-32CGLXW2.js} +4 -3
  16. package/dist/{chunk-A4UJB2MM.js.map → chunk-32CGLXW2.js.map} +1 -1
  17. package/dist/{chunk-5CVXZA3Y.js → chunk-45NUOSXQ.js} +3 -2
  18. package/dist/{chunk-5CVXZA3Y.js.map → chunk-45NUOSXQ.js.map} +1 -1
  19. package/dist/{chunk-WUISZ3WU.js → chunk-53KJBGPZ.js} +5 -4
  20. package/dist/{chunk-WUISZ3WU.js.map → chunk-53KJBGPZ.js.map} +1 -1
  21. package/dist/{chunk-MBMPHOMA.js → chunk-55DXD22O.js} +3 -2
  22. package/dist/{chunk-MBMPHOMA.js.map → chunk-55DXD22O.js.map} +1 -1
  23. package/dist/{chunk-JT4JW7BC.js → chunk-5I4VRWBB.js} +3 -1
  24. package/dist/{chunk-JT4JW7BC.js.map → chunk-5I4VRWBB.js.map} +1 -1
  25. package/dist/{chunk-UK4TINKT.js → chunk-B27E3V37.js} +3 -1
  26. package/dist/{chunk-UK4TINKT.js.map → chunk-B27E3V37.js.map} +1 -1
  27. package/dist/{chunk-J6DBS4T3.js → chunk-BNKV5ZLF.js} +5 -4
  28. package/dist/{chunk-J6DBS4T3.js.map → chunk-BNKV5ZLF.js.map} +1 -1
  29. package/dist/{chunk-YM2DE7BQ.js → chunk-C5BF4L26.js} +13 -12
  30. package/dist/{chunk-YM2DE7BQ.js.map → chunk-C5BF4L26.js.map} +1 -1
  31. package/dist/{chunk-YBXQDQFX.js → chunk-C7CMD56T.js} +6 -5
  32. package/dist/{chunk-YBXQDQFX.js.map → chunk-C7CMD56T.js.map} +1 -1
  33. package/dist/{chunk-UGLEYEMP.js → chunk-CM7LVUKC.js} +3 -1
  34. package/dist/{chunk-UGLEYEMP.js.map → chunk-CM7LVUKC.js.map} +1 -1
  35. package/dist/{chunk-LJ2UTJJE.js → chunk-CREMJMVN.js} +181 -96
  36. package/dist/chunk-CREMJMVN.js.map +1 -0
  37. package/dist/{chunk-JVYQRRC4.js → chunk-CVYCLFMH.js} +3 -1
  38. package/dist/{chunk-JVYQRRC4.js.map → chunk-CVYCLFMH.js.map} +1 -1
  39. package/dist/{chunk-Y2PRMYLC.js → chunk-G3U2A6GS.js} +3 -2
  40. package/dist/{chunk-Y2PRMYLC.js.map → chunk-G3U2A6GS.js.map} +1 -1
  41. package/dist/{chunk-WZMYFJD3.js → chunk-G6YRCIYJ.js} +16 -7
  42. package/dist/{chunk-WZMYFJD3.js.map → chunk-G6YRCIYJ.js.map} +1 -1
  43. package/dist/{chunk-B3V6TG77.js → chunk-GC3PH6N7.js} +3 -1
  44. package/dist/{chunk-B3V6TG77.js.map → chunk-GC3PH6N7.js.map} +1 -1
  45. package/dist/{chunk-CJUO7J5Z.js → chunk-HXYOSSQO.js} +3 -2
  46. package/dist/{chunk-CJUO7J5Z.js.map → chunk-HXYOSSQO.js.map} +1 -1
  47. package/dist/{chunk-BRM6FVZA.js → chunk-IEE7WCLN.js} +4 -3
  48. package/dist/{chunk-BRM6FVZA.js.map → chunk-IEE7WCLN.js.map} +1 -1
  49. package/dist/{chunk-DYWBUX5Q.js → chunk-IMSUVYQB.js} +6 -5
  50. package/dist/{chunk-DYWBUX5Q.js.map → chunk-IMSUVYQB.js.map} +1 -1
  51. package/dist/{chunk-LN6TCXD3.js → chunk-IUHHPMAX.js} +184 -48
  52. package/dist/chunk-IUHHPMAX.js.map +1 -0
  53. package/dist/{chunk-SGKD2OCN.js → chunk-IYQCWGU5.js} +6 -5
  54. package/dist/{chunk-SGKD2OCN.js.map → chunk-IYQCWGU5.js.map} +1 -1
  55. package/dist/{chunk-J2QWVSQY.js → chunk-JH7V627O.js} +8 -7
  56. package/dist/{chunk-J2QWVSQY.js.map → chunk-JH7V627O.js.map} +1 -1
  57. package/dist/{chunk-EESD3PY3.js → chunk-JHTIMBOL.js} +6 -5
  58. package/dist/{chunk-EESD3PY3.js.map → chunk-JHTIMBOL.js.map} +1 -1
  59. package/dist/{chunk-LNIRAOA3.js → chunk-L2J3PU7A.js} +7 -6
  60. package/dist/{chunk-LNIRAOA3.js.map → chunk-L2J3PU7A.js.map} +1 -1
  61. package/dist/{chunk-ZYRGEKWS.js → chunk-LJUMYUBO.js} +3 -1
  62. package/dist/{chunk-ZYRGEKWS.js.map → chunk-LJUMYUBO.js.map} +1 -1
  63. package/dist/{chunk-4RVYOY4O.js → chunk-LSW2OJVV.js} +4 -3
  64. package/dist/{chunk-4RVYOY4O.js.map → chunk-LSW2OJVV.js.map} +1 -1
  65. package/dist/{chunk-UTRTG6LH.js → chunk-LVS3MH5T.js} +3 -1
  66. package/dist/{chunk-UTRTG6LH.js.map → chunk-LVS3MH5T.js.map} +1 -1
  67. package/dist/chunk-M357MHH3.js +2 -0
  68. package/dist/{chunk-GYVRFZDY.js → chunk-MDIXFKA3.js} +9 -8
  69. package/dist/{chunk-GYVRFZDY.js.map → chunk-MDIXFKA3.js.map} +1 -1
  70. package/dist/{chunk-WRHIZYZF.js → chunk-MEQM4LI3.js} +6 -5
  71. package/dist/{chunk-WRHIZYZF.js.map → chunk-MEQM4LI3.js.map} +1 -1
  72. package/dist/chunk-NX4ADH73.js +14 -0
  73. package/dist/chunk-NX4ADH73.js.map +1 -0
  74. package/dist/{chunk-XCHWDJ22.js → chunk-OGTTUYNT.js} +3 -1
  75. package/dist/{chunk-XCHWDJ22.js.map → chunk-OGTTUYNT.js.map} +1 -1
  76. package/dist/{chunk-GIMRELBW.js → chunk-OYQQJL3J.js} +3 -1
  77. package/dist/{chunk-GIMRELBW.js.map → chunk-OYQQJL3J.js.map} +1 -1
  78. package/dist/{chunk-RSI7XYXL.js → chunk-PBCZL4JP.js} +6 -5
  79. package/dist/{chunk-RSI7XYXL.js.map → chunk-PBCZL4JP.js.map} +1 -1
  80. package/dist/{chunk-I7IWRQLN.js → chunk-PHBFJCEU.js} +17 -11
  81. package/dist/chunk-PHBFJCEU.js.map +1 -0
  82. package/dist/{chunk-3CTRFMAK.js → chunk-PKCAYHDC.js} +5 -4
  83. package/dist/{chunk-3CTRFMAK.js.map → chunk-PKCAYHDC.js.map} +1 -1
  84. package/dist/{chunk-K3HQAKQX.js → chunk-PMV53IMM.js} +3 -1
  85. package/dist/{chunk-K3HQAKQX.js.map → chunk-PMV53IMM.js.map} +1 -1
  86. package/dist/{chunk-YQEAA6LT.js → chunk-QHUE7E4N.js} +3 -2
  87. package/dist/{chunk-YQEAA6LT.js.map → chunk-QHUE7E4N.js.map} +1 -1
  88. package/dist/{chunk-OA6HFRQP.js → chunk-QMMCJGFI.js} +4 -3
  89. package/dist/{chunk-OA6HFRQP.js.map → chunk-QMMCJGFI.js.map} +1 -1
  90. package/dist/{chunk-YV4L3ILF.js → chunk-QV3DJVRZ.js} +3 -1
  91. package/dist/{chunk-YV4L3ILF.js.map → chunk-QV3DJVRZ.js.map} +1 -1
  92. package/dist/{chunk-447JLCBU.js → chunk-S2QH6EZ5.js} +3 -1
  93. package/dist/{chunk-447JLCBU.js.map → chunk-S2QH6EZ5.js.map} +1 -1
  94. package/dist/{chunk-PNY3JKBJ.js → chunk-SFH43JT2.js} +5 -4
  95. package/dist/{chunk-PNY3JKBJ.js.map → chunk-SFH43JT2.js.map} +1 -1
  96. package/dist/{chunk-AWZLIMKX.js → chunk-T46QZH3E.js} +3 -1
  97. package/dist/{chunk-AWZLIMKX.js.map → chunk-T46QZH3E.js.map} +1 -1
  98. package/dist/{chunk-5J4FOW6Q.js → chunk-TNEZNMSN.js} +3 -1
  99. package/dist/{chunk-5J4FOW6Q.js.map → chunk-TNEZNMSN.js.map} +1 -1
  100. package/dist/{chunk-22KP6LR5.js → chunk-TXS65BB2.js} +3 -1
  101. package/dist/{chunk-22KP6LR5.js.map → chunk-TXS65BB2.js.map} +1 -1
  102. package/dist/{chunk-H5X55XH7.js → chunk-UDPH5SLV.js} +4 -3
  103. package/dist/{chunk-H5X55XH7.js.map → chunk-UDPH5SLV.js.map} +1 -1
  104. package/dist/{chunk-HDJWDK7W.js → chunk-VCSERYXH.js} +10 -9
  105. package/dist/{chunk-HDJWDK7W.js.map → chunk-VCSERYXH.js.map} +1 -1
  106. package/dist/{chunk-VZTQ73XT.js → chunk-XEA5BCMA.js} +3 -1
  107. package/dist/{chunk-VZTQ73XT.js.map → chunk-XEA5BCMA.js.map} +1 -1
  108. package/dist/{chunk-5F4WR7X7.js → chunk-XS67YG5R.js} +3 -1
  109. package/dist/{chunk-5F4WR7X7.js.map → chunk-XS67YG5R.js.map} +1 -1
  110. package/dist/{chunk-TKOTKRWY.js → chunk-XTD7TZHW.js} +3 -1
  111. package/dist/{chunk-TKOTKRWY.js.map → chunk-XTD7TZHW.js.map} +1 -1
  112. package/dist/{chunk-A2PI6UMY.js → chunk-YSRBFJMQ.js} +3 -1
  113. package/dist/{chunk-A2PI6UMY.js.map → chunk-YSRBFJMQ.js.map} +1 -1
  114. package/dist/chunk-YVFRBXST.js +1420 -0
  115. package/dist/chunk-YVFRBXST.js.map +1 -0
  116. package/dist/{chunk-SCOTPE2I.js → chunk-YYLBXXTE.js} +3 -1
  117. package/dist/{chunk-SCOTPE2I.js.map → chunk-YYLBXXTE.js.map} +1 -1
  118. package/dist/{chunk-RHREZ7BO.js → chunk-ZUWF4NF7.js} +3 -1
  119. package/dist/{chunk-RHREZ7BO.js.map → chunk-ZUWF4NF7.js.map} +1 -1
  120. package/dist/clipboard.js +3 -2
  121. package/dist/components/composer-transcription-control.d.ts +4 -0
  122. package/dist/components/session-conversation.d.ts +6 -0
  123. package/dist/composer-voice-events.d.ts +8 -0
  124. package/dist/composer.js +15 -13
  125. package/dist/computer-viewer-46UIN7F3.js +20 -0
  126. package/dist/connect.js +15 -12
  127. package/dist/connect.js.map +1 -1
  128. package/dist/desktop.js +6 -5
  129. package/dist/desktop.js.map +1 -1
  130. package/dist/diffs.js +2 -1
  131. package/dist/diffs.js.map +1 -1
  132. package/dist/editor.js +4 -3
  133. package/dist/editor.js.map +1 -1
  134. package/dist/embedded-voice-NIL4RDX3.js +69 -0
  135. package/dist/embedded-voice-NIL4RDX3.js.map +1 -0
  136. package/dist/{fleet-decision-row-YZ3ZKWMM.js → fleet-decision-row-SI63O5V4.js} +3 -1
  137. package/dist/{fleet-decision-row-YZ3ZKWMM.js.map → fleet-decision-row-SI63O5V4.js.map} +1 -1
  138. package/dist/hooks/use-client-config-flags.d.ts +6 -0
  139. package/dist/hooks/use-realtime-voice-models.d.ts +9 -0
  140. package/dist/hooks/use-voice-input.d.ts +8 -1
  141. package/dist/index.js +47 -45
  142. package/dist/index.js.map +1 -1
  143. package/dist/interaction.js +14 -13
  144. package/dist/interaction.js.map +1 -1
  145. package/dist/{latest-question-GPYM2JNU.js → latest-question-2POFPYNB.js} +5 -4
  146. package/dist/{latest-question-GPYM2JNU.js.map → latest-question-2POFPYNB.js.map} +1 -1
  147. package/dist/machines.js +8 -7
  148. package/dist/{markdown-table-layout-QXSLK4BY.js → markdown-table-layout-DQ4DRNVT.js} +3 -1
  149. package/dist/{markdown-table-layout-QXSLK4BY.js.map → markdown-table-layout-DQ4DRNVT.js.map} +1 -1
  150. package/dist/model-policy-picker-menu-WRNSRFQC.js +15 -0
  151. package/dist/model-policy.js +2 -1
  152. package/dist/{noto-sans-arabic-loader-IA2T4X2A.js → noto-sans-arabic-loader-XSH2KYWJ.js} +3 -1
  153. package/dist/{noto-sans-arabic-loader-IA2T4X2A.js.map → noto-sans-arabic-loader-XSH2KYWJ.js.map} +1 -1
  154. package/dist/{noto-sans-jp-loader.generated-HFGLYBR3.js → noto-sans-jp-loader.generated-MR5L6V7K.js} +3 -1
  155. package/dist/{noto-sans-jp-loader.generated-HFGLYBR3.js.map → noto-sans-jp-loader.generated-MR5L6V7K.js.map} +1 -1
  156. package/dist/{platform-activity-row-627BFZ46.js → platform-activity-row-PJJVATTZ.js} +3 -1
  157. package/dist/{platform-activity-row-627BFZ46.js.map → platform-activity-row-PJJVATTZ.js.map} +1 -1
  158. package/dist/{queue-surface-implementation-ZHFI5JBP.js → queue-surface-implementation-67FS7FUI.js} +10 -9
  159. package/dist/{queue-surface-implementation-ZHFI5JBP.js.map → queue-surface-implementation-67FS7FUI.js.map} +1 -1
  160. package/dist/realtime/embedded-voice.d.ts +20 -0
  161. package/dist/realtime.js +22 -1353
  162. package/dist/realtime.js.map +1 -1
  163. package/dist/sandbox-files-34CJJNOY.js +21 -0
  164. package/dist/session-ui.js +32 -30
  165. package/dist/session-ui.js.map +1 -1
  166. package/dist/session.js +10 -9
  167. package/dist/sites.js +2 -1
  168. package/dist/terminal.js +6 -5
  169. package/dist/terminal.js.map +1 -1
  170. package/dist/{timeline-annotation-markers-GNDHTGBD.js → timeline-annotation-markers-U3G66KUD.js} +5 -4
  171. package/dist/{timeline-annotation-markers-GNDHTGBD.js.map → timeline-annotation-markers-U3G66KUD.js.map} +1 -1
  172. package/dist/{timeline-annotation-selection-DMLMM2TX.js → timeline-annotation-selection-BI7QTPTZ.js} +4 -3
  173. package/dist/{timeline-annotation-selection-DMLMM2TX.js.map → timeline-annotation-selection-BI7QTPTZ.js.map} +1 -1
  174. package/dist/{timeline-annotations-dialog-ELRDBHTS.js → timeline-annotations-dialog-FOMHSDTE.js} +7 -6
  175. package/dist/{timeline-annotations-dialog-ELRDBHTS.js.map → timeline-annotations-dialog-FOMHSDTE.js.map} +1 -1
  176. package/dist/usage.js +6 -5
  177. package/dist/usage.js.map +1 -1
  178. package/dist/voice-recording-owner.d.ts +7 -0
  179. package/package.json +3 -3
  180. package/src/components/composer-transcription-control.tsx +109 -27
  181. package/src/components/markdown.tsx +7 -2
  182. package/src/components/message-timeline.tsx +10 -1
  183. package/src/components/session-conversation.tsx +44 -0
  184. package/src/components/session-proxy-scope.tsx +26 -5
  185. package/src/composer-voice-events.ts +12 -0
  186. package/src/connection-discovery.tsx +4 -1
  187. package/src/hooks/use-client-config-flags.ts +8 -0
  188. package/src/hooks/use-goal.ts +12 -1
  189. package/src/hooks/use-realtime-voice-models.ts +67 -0
  190. package/src/hooks/use-voice-input.ts +109 -18
  191. package/src/realtime/embedded-voice.tsx +81 -0
  192. package/src/realtime/realtime-control.tsx +82 -17
  193. package/src/voice-recording-owner.ts +22 -0
  194. package/styles/compiled.css +72 -18
  195. package/styles/index.css +49 -0
  196. package/styles/responsive.css +61 -4
  197. package/styles/session-capability.css +1 -1
  198. package/dist/browser-viewer-SHYKQRNX.js +0 -16
  199. package/dist/chat-interactive-block-UGBTNB3L.js +0 -11
  200. package/dist/chunk-I7IWRQLN.js.map +0 -1
  201. package/dist/chunk-IWIDV7SB.js +0 -1
  202. package/dist/chunk-LJ2UTJJE.js.map +0 -1
  203. package/dist/chunk-LN6TCXD3.js.map +0 -1
  204. package/dist/computer-viewer-6SRGWRUX.js +0 -19
  205. package/dist/model-policy-picker-menu-DXHUL73H.js +0 -14
  206. package/dist/sandbox-files-GORZOUUJ.js +0 -20
  207. /package/dist/{browser-viewer-SHYKQRNX.js.map → browser-viewer-WGJ43YGI.js.map} +0 -0
  208. /package/dist/{chat-interactive-block-UGBTNB3L.js.map → chat-interactive-block-ZFHOKTMS.js.map} +0 -0
  209. /package/dist/{chunk-IWIDV7SB.js.map → chunk-M357MHH3.js.map} +0 -0
  210. /package/dist/{computer-viewer-6SRGWRUX.js.map → computer-viewer-46UIN7F3.js.map} +0 -0
  211. /package/dist/{model-policy-picker-menu-DXHUL73H.js.map → model-policy-picker-menu-WRNSRFQC.js.map} +0 -0
  212. /package/dist/{sandbox-files-GORZOUUJ.js.map → sandbox-files-34CJJNOY.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/realtime/realtime-control.tsx","../src/realtime/dropdown-menu.tsx"],"sourcesContent":["import {\n COMPOSER_VOICE_INPUT_START_EVENT,\n composerVoiceEventScope,\n} from \"../composer-voice-events\";\nimport { type EffectiveSessionControl, type SessionEvent, type SessionStatus } from \"@opengeni/sdk\";\nimport {\n hasStoredSessionRealtimeOwnerProof,\n projectSessionRealtimeLifecycle,\n type SessionRealtimeClientLike,\n type SessionRealtimeController,\n type SessionRealtimeControllerSnapshot,\n type CreateSessionRealtimeControllerOptions,\n type SessionRealtimeLifecycleProjection,\n type SessionRealtimeModel,\n type WorkspaceRealtimeModelCatalogItem,\n} from \"@opengeni/sdk/realtime\";\nimport {\n AudioLinesIcon,\n CheckIcon,\n ChevronDownIcon,\n CircleAlertIcon,\n LoaderCircleIcon,\n MicIcon,\n MicOffIcon,\n RotateCcwIcon,\n SquareIcon,\n Volume2Icon,\n VolumeXIcon,\n XIcon,\n} from \"lucide-react\";\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\";\nimport {\n type ReactNode,\n type RefObject,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport {\n BillingClassMark,\n PickerAnimatedPage,\n PickerBackHeader,\n PickerNavRow,\n} from \"../components/model-policy-picker\";\nimport type { EmbeddedRealtimeSessionClientLike } from \"../client\";\nimport { cn } from \"../lib/cn\";\nimport type { PickerBillingClass as BillingClass } from \"../model-policy\";\nimport { useEmbeddedRealtimeSession } from \"../session-context\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"./dropdown-menu\";\nimport { MENU_CHECK_CLASS } from \"../lib/menu-styles\";\n\nexport type RealtimeModelOption = {\n id: SessionRealtimeModel;\n label: string;\n provider: \"OpenGeni\" | \"Connected Codex\" | \"Connected SuperGrok\" | \"Your Gateway\";\n description: string;\n available: boolean;\n unavailableReason: string | null;\n /** Machine-readable reason, e.g. `insufficient_credits` (same codes as voice input). */\n unavailableCode?: string | null | undefined;\n recommended: boolean;\n};\n\n/** Short status label for a credit/availability refusal (shared with the model menu). */\nfunction realtimeRefusalLabel(code: string | null | undefined): string | null {\n switch (code) {\n case \"insufficient_credits\":\n return \"Credits needed\";\n case \"allowance_exhausted\":\n case \"monthly_model_cost_limit\":\n return \"Usage limit reached\";\n case \"realtime_voice_unavailable\":\n return \"Voice unavailable\";\n default:\n return null;\n }\n}\n\nconst CODEX_LIVE_MODEL: RealtimeModelOption = {\n id: \"gpt-live-1-boulder-alpha\",\n label: \"Codex Live\",\n provider: \"Connected Codex\",\n description: \"Deep session integration\",\n available: false,\n unavailableReason: \"Connect Codex to use this voice model\",\n recommended: false,\n};\n\nconst REALTIME_MODEL_PROVIDERS = [\n \"OpenGeni\",\n \"Connected Codex\",\n \"Connected SuperGrok\",\n \"Your Gateway\",\n] as const;\ntype RealtimeModelProvider = (typeof REALTIME_MODEL_PROVIDERS)[number];\n\nconst REALTIME_PROVIDER_META: Record<\n RealtimeModelProvider,\n { billingClass: BillingClass; label: string; hint: string }\n> = {\n // The wire value keeps its historical spelling; the product name is Opengeni.\n OpenGeni: { billingClass: \"opengeni_credits\", label: \"Opengeni\", hint: \"Uses Opengeni credits\" },\n \"Connected Codex\": {\n billingClass: \"codex_subscription\",\n label: \"Connected Codex\",\n hint: \"ChatGPT / Codex plan\",\n },\n \"Connected SuperGrok\": {\n billingClass: \"supergrok_subscription\",\n label: \"Connected SuperGrok\",\n hint: \"SuperGrok / xAI plan\",\n },\n \"Your Gateway\": {\n billingClass: \"byok\",\n label: \"Your Gateway\",\n hint: \"Billed to your AI Gateway\",\n },\n};\n/** Display name; the catalog's `provider` value stays the wire identifier. */\nfunction realtimeProviderLabel(provider: RealtimeModelProvider): string {\n return provider === \"OpenGeni\" ? \"Opengeni\" : provider;\n}\nconst REALTIME_MODEL_STORAGE_PREFIX = \"opengeni:realtime-model\";\nconst REALTIME_MODEL_CATALOG_CACHE_TTL_MS = 60_000;\nconst REALTIME_MODEL_CATALOG_CACHE_MAX_WORKSPACES = 64;\n\ntype RealtimeControllerClient = EmbeddedRealtimeSessionClientLike & SessionRealtimeClientLike;\n\ntype RealtimeModelCatalogCacheEntry =\n | {\n state: \"loading\";\n promise: Promise<RealtimeModelOption[]>;\n controller: AbortController;\n consumers: number;\n }\n | { state: \"ready\"; models: RealtimeModelOption[]; expiresAt: number };\n\n// Scope advisory availability to the exact client object and workspace. The\n// server still authorizes every realtime operation; changing principals should\n// replace the client just as it does for the rest of the SDK state.\nconst realtimeModelCatalogCache = new WeakMap<\n RealtimeControllerClient,\n Map<string, RealtimeModelCatalogCacheEntry>\n>();\n\nfunction realtimeModelFallback(codexConnected: boolean): RealtimeModelOption[] {\n return [\n {\n ...CODEX_LIVE_MODEL,\n available: codexConnected,\n unavailableReason: codexConnected ? null : CODEX_LIVE_MODEL.unavailableReason,\n },\n ];\n}\n\nfunction realtimeModelCatalogCacheFor(\n client: RealtimeControllerClient,\n): Map<string, RealtimeModelCatalogCacheEntry> {\n const existing = realtimeModelCatalogCache.get(client);\n if (existing) return existing;\n const created = new Map<string, RealtimeModelCatalogCacheEntry>();\n realtimeModelCatalogCache.set(client, created);\n return created;\n}\n\nfunction readCachedRealtimeModelCatalog(\n client: RealtimeControllerClient,\n workspaceId: string,\n now = Date.now(),\n): RealtimeModelOption[] | null {\n const cache = realtimeModelCatalogCache.get(client);\n const entry = cache?.get(workspaceId);\n if (!entry || entry.state === \"loading\") return null;\n if (entry.expiresAt > now) return entry.models;\n cache?.delete(workspaceId);\n return null;\n}\n\nfunction pruneRealtimeModelCatalogCache(\n cache: Map<string, RealtimeModelCatalogCacheEntry>,\n now: number,\n): void {\n for (const [workspaceId, entry] of cache) {\n if (entry.state === \"ready\" && entry.expiresAt <= now) cache.delete(workspaceId);\n }\n while (cache.size >= REALTIME_MODEL_CATALOG_CACHE_MAX_WORKSPACES) {\n const oldestWorkspaceId = cache.keys().next().value;\n if (oldestWorkspaceId === undefined) return;\n cache.delete(oldestWorkspaceId);\n }\n}\n\nfunction loadRealtimeModelCatalog(\n client: RealtimeControllerClient,\n workspaceId: string,\n signal?: AbortSignal,\n): Promise<RealtimeModelOption[]> | null {\n const load = client.getWorkspaceRealtimeModelCatalog;\n if (!load) return null;\n if (signal?.aborted) {\n return Promise.reject(signal.reason ?? new DOMException(\"Request aborted\", \"AbortError\"));\n }\n const now = Date.now();\n const cache = realtimeModelCatalogCacheFor(client);\n const entry = cache.get(workspaceId);\n if (entry?.state === \"loading\" && !entry.controller.signal.aborted) {\n return consumeRealtimeModelCatalog(entry, signal);\n }\n if (entry?.state === \"ready\" && entry.expiresAt > now) return Promise.resolve(entry.models);\n if (entry) cache.delete(workspaceId);\n pruneRealtimeModelCatalogCache(cache, now);\n\n const controller = new AbortController();\n const promise = load\n .call(client, workspaceId, { signal: controller.signal })\n .then((response) => response.models.map(toRealtimeModelOption))\n .then((models) => {\n const current = cache.get(workspaceId);\n if (current?.state === \"loading\" && current.promise === promise) {\n cache.delete(workspaceId);\n cache.set(workspaceId, {\n state: \"ready\",\n models,\n expiresAt: Date.now() + REALTIME_MODEL_CATALOG_CACHE_TTL_MS,\n });\n }\n return models;\n })\n .catch((error: unknown) => {\n const current = cache.get(workspaceId);\n if (current?.state === \"loading\" && current.promise === promise) cache.delete(workspaceId);\n throw error;\n });\n const loading: RealtimeModelCatalogCacheEntry & { state: \"loading\" } = {\n state: \"loading\",\n promise,\n controller,\n consumers: 0,\n };\n cache.set(workspaceId, loading);\n return consumeRealtimeModelCatalog(loading, signal);\n}\n\nfunction consumeRealtimeModelCatalog(\n entry: RealtimeModelCatalogCacheEntry & { state: \"loading\" },\n signal?: AbortSignal,\n): Promise<RealtimeModelOption[]> {\n entry.consumers += 1;\n return new Promise((resolve, reject) => {\n let released = false;\n const release = (abandoned: boolean) => {\n if (released) return;\n released = true;\n entry.consumers = Math.max(0, entry.consumers - 1);\n if (abandoned && entry.consumers === 0) {\n entry.controller.abort(\n signal?.reason ?? new DOMException(\"Request abandoned\", \"AbortError\"),\n );\n }\n };\n const onAbort = () => {\n release(true);\n reject(signal?.reason ?? new DOMException(\"Request aborted\", \"AbortError\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n void entry.promise.then(resolve, reject).finally(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n release(false);\n });\n });\n}\n\nexport type SessionRealtimeControllerFactory = (\n options: CreateSessionRealtimeControllerOptions,\n) => SessionRealtimeController;\n\ntype AdmissionInput = {\n sessionStatus: SessionStatus;\n controlState: \"active\" | \"paused\";\n settlement: { state: string } | null;\n codexConnected: boolean;\n lifecycleActive: boolean;\n};\n\nexport function codexRealtimeAdmissionAllowed(input: AdmissionInput): boolean {\n return codexRealtimeAdmissionBlocker(input) === null;\n}\n\nexport function codexRealtimeAdmissionBlocker(input: AdmissionInput): string | null {\n if (input.sessionStatus === \"cancelled\") return \"This session was cancelled.\";\n if (input.controlState !== \"active\") return \"Resume this session before starting voice.\";\n if (input.settlement !== null) return \"Wait for the current session transition to finish.\";\n if (!input.codexConnected) return \"Connect Codex to use this voice model.\";\n if (input.lifecycleActive) return \"Voice is already active for this session.\";\n return null;\n}\n\nexport function useSessionRealtime(options: {\n client?: RealtimeControllerClient | undefined;\n workspaceId?: string | undefined;\n sessionId: string;\n sessionStatus: SessionStatus;\n effectiveControl: EffectiveSessionControl;\n events: SessionEvent[];\n eventsReady: boolean;\n codexConnected: boolean;\n model?: SessionRealtimeModel | undefined;\n modelAvailable?: boolean | undefined;\n modelUnavailableReason?: string | null | undefined;\n /** Model-visible application context captured with each durable realtime message. */\n getModelContext?: (() => string | undefined) | undefined;\n /** Deterministic browser-test/demo seam. Production hosts should use the SDK default. */\n controllerFactory?: SessionRealtimeControllerFactory | undefined;\n}) {\n const { client, workspaceId } = useEmbeddedRealtimeSession({\n client: options.client,\n workspaceId: options.workspaceId,\n });\n const model = options.model ?? CODEX_LIVE_MODEL.id;\n const audioRef = useRef<HTMLAudioElement>(null);\n const controllerRef = useRef<SessionRealtimeController | null>(null);\n const controllerModelRef = useRef<SessionRealtimeModel | null>(null);\n const modelContextProviderRef = useRef(options.getModelContext);\n modelContextProviderRef.current = options.getModelContext;\n const [snapshot, setSnapshot] = useState<SessionRealtimeControllerSnapshot>(() => ({\n status: hasStoredSessionRealtimeOwnerProof({\n workspaceId,\n sessionId: options.sessionId,\n model,\n })\n ? \"recovering\"\n : \"idle\",\n realtimeId: null,\n mode: null,\n bridge: null,\n microphone: \"inactive\",\n inputMuted: false,\n audibleOutput: \"inactive\",\n outputMuted: false,\n connectionGeneration: 0,\n reconnectAttempt: 0,\n diagnostic: null,\n error: null,\n }));\n const lifecycle = useMemo(\n () => projectSessionRealtimeLifecycle(options.events),\n [options.events],\n );\n const lifecycleRef = useRef(lifecycle);\n const eventsReadyRef = useRef(options.eventsReady);\n lifecycleRef.current = lifecycle;\n eventsReadyRef.current = options.eventsReady;\n const lifecycleActive = sessionRealtimeLifecycleIsActive(lifecycle);\n\n useEffect(() => {\n let disposed = false;\n let controller: SessionRealtimeController | null = null;\n let unsubscribe: (() => void) | null = null;\n void import(\"@opengeni/sdk/realtime\")\n .then(({ createSessionRealtimeController }) => {\n if (disposed) return;\n const controllerFactory = options.controllerFactory ?? createSessionRealtimeController;\n controller = controllerFactory({\n client,\n workspaceId,\n sessionId: options.sessionId,\n ...(audioRef.current ? { remoteAudio: audioRef.current } : {}),\n model,\n getModelContext: () => modelContextProviderRef.current?.(),\n });\n controllerRef.current = controller;\n controllerModelRef.current = model;\n unsubscribe = controller.subscribe(setSnapshot);\n if (eventsReadyRef.current) {\n void controller.observeLifecycle(lifecycleRef.current).catch(() => undefined);\n }\n })\n .catch((error: unknown) => {\n if (disposed) return;\n setSnapshot({\n status: \"error\",\n realtimeId: null,\n mode: null,\n bridge: null,\n microphone: \"inactive\",\n inputMuted: false,\n audibleOutput: \"inactive\",\n outputMuted: false,\n connectionGeneration: 0,\n reconnectAttempt: 0,\n diagnostic: {\n kind: \"negotiation_failure\",\n message:\n error instanceof Error ? error.message : \"Codex realtime controller failed to load\",\n recoverable: false,\n connectionGeneration: 0,\n attempt: 0,\n },\n error:\n error instanceof Error ? error.message : \"Codex realtime controller failed to load\",\n });\n });\n return () => {\n disposed = true;\n unsubscribe?.();\n controller?.close();\n if (controllerRef.current === controller) {\n controllerRef.current = null;\n controllerModelRef.current = null;\n }\n };\n }, [client, model, options.controllerFactory, options.sessionId, workspaceId]);\n\n useEffect(() => {\n if (!options.eventsReady) return;\n void controllerRef.current?.observeLifecycle(lifecycle).catch(() => undefined);\n }, [lifecycle, options.eventsReady]);\n\n const start = useCallback(async () => {\n const controller = controllerRef.current;\n if (!controller || controllerModelRef.current !== model) {\n throw new Error(\"The selected voice model is still preparing\");\n }\n await controller.start();\n }, [model]);\n const stop = useCallback(async () => {\n await controllerRef.current?.stop();\n }, []);\n const retry = useCallback(async () => {\n await controllerRef.current?.retry();\n }, []);\n const retryAudibleOutput = useCallback(async () => {\n await controllerRef.current?.retryAudibleOutput();\n }, []);\n const setInputMuted = useCallback((muted: boolean) => {\n controllerRef.current?.setInputMuted(muted);\n }, []);\n const setOutputMuted = useCallback((muted: boolean) => {\n controllerRef.current?.setOutputMuted(muted);\n }, []);\n const admissionInput = {\n sessionStatus: options.sessionStatus,\n controlState: options.effectiveControl.state,\n settlement: options.effectiveControl.settlement,\n codexConnected: options.modelAvailable ?? options.codexConnected,\n lifecycleActive,\n } satisfies AdmissionInput;\n const admissionBlocker =\n options.modelAvailable === false\n ? (options.modelUnavailableReason ?? \"This voice model is unavailable.\")\n : codexRealtimeAdmissionBlocker(admissionInput);\n const canStart =\n controllerRef.current !== null &&\n controllerModelRef.current === model &&\n [\"idle\", \"error\"].includes(snapshot.status) &&\n admissionBlocker === null;\n\n return {\n snapshot,\n lifecycleActive,\n canStart,\n admissionBlocker,\n codexConnected: options.codexConnected,\n audioRef,\n start,\n stop,\n retry,\n retryAudibleOutput,\n setInputMuted,\n setOutputMuted,\n };\n}\n\nfunction sessionRealtimeLifecycleIsActive(\n lifecycle: SessionRealtimeLifecycleProjection | null,\n): boolean {\n if (lifecycle?.state !== \"active\") return false;\n const leaseExpiresAt = Date.parse(lifecycle.leaseExpiresAt);\n return !Number.isFinite(leaseExpiresAt) || leaseExpiresAt > Date.now();\n}\n\nexport function SessionRealtimeControl(props: {\n client?: RealtimeControllerClient | undefined;\n workspaceId?: string | undefined;\n sessionId: string;\n sessionStatus: SessionStatus;\n effectiveControl: EffectiveSessionControl;\n events: SessionEvent[];\n eventsReady: boolean;\n codexConnected: boolean;\n /** Model-visible application context captured with each durable realtime message. */\n getModelContext?: (() => string | undefined) | undefined;\n realtimeAutostartModel?: SessionRealtimeModel | undefined;\n onRealtimeAutostartConsumed?: (() => void) | undefined;\n /** Host hides dictate (and can choreograph layout) while realtime voice is live. */\n onVoiceActiveChange?: ((active: boolean) => void) | undefined;\n /**\n * `split` attaches the model chevron at every breakpoint (public default).\n * `split-desktop` hides it below `sm` when the host owns mobile selection.\n * Inside a container-responsive Composer.Root, `sm` follows that composer.\n * `none` never attaches a model menu to the bar button.\n */\n modelMenu?: \"split\" | \"split-desktop\" | \"none\" | undefined;\n /** Explicitly expose low-level controller diagnostics; disabled by default. */\n showDiagnostics?: boolean | undefined;\n /** Deterministic browser-test/demo seam. Production hosts should use the SDK default. */\n controllerFactory?: SessionRealtimeControllerFactory | undefined;\n}) {\n const lifecycle = useMemo(() => projectSessionRealtimeLifecycle(props.events), [props.events]);\n const lifecycleActive = sessionRealtimeLifecycleIsActive(lifecycle);\n const selection = useRealtimeModelSelection({\n client: props.client,\n workspaceId: props.workspaceId,\n codexConnected: props.codexConnected,\n activeModel: lifecycleActive && lifecycle?.state === \"active\" ? lifecycle.model : null,\n });\n const selectedModel = selection.selectedModel;\n const realtime = useSessionRealtime({\n ...props,\n model: selectedModel.id,\n modelAvailable: selectedModel.available,\n modelUnavailableReason: selectedModel.unavailableReason,\n });\n const autostartModelRef = useRef(props.realtimeAutostartModel ?? null);\n const autostartStartedRef = useRef(false);\n\n const { models, selectedModel: selectedRealtimeModel, selectModel } = selection;\n const { canStart, start } = realtime;\n const onRealtimeAutostartConsumed = props.onRealtimeAutostartConsumed;\n const onVoiceActiveChange = props.onVoiceActiveChange;\n const voiceActive = realtime.snapshot.mode?.state === \"active\";\n\n useEffect(() => {\n onVoiceActiveChange?.(voiceActive);\n }, [onVoiceActiveChange, voiceActive]);\n\n useEffect(() => {\n const pending = autostartModelRef.current;\n if (!pending || autostartStartedRef.current || lifecycleActive) return;\n const available = models.some((model) => model.id === pending && model.available);\n if (!available) return;\n if (selectedRealtimeModel.id !== pending) {\n selectModel(pending);\n return;\n }\n if (!canStart) return;\n autostartStartedRef.current = true;\n // One automatic attempt. A failed start stays visible with its reason and\n // the user retries explicitly; re-arming would loop on a definitive refusal.\n const consume = () => {\n autostartModelRef.current = null;\n onRealtimeAutostartConsumed?.();\n };\n void start().then(consume, consume);\n }, [\n canStart,\n lifecycleActive,\n models,\n props.sessionId,\n props.workspaceId,\n onRealtimeAutostartConsumed,\n selectModel,\n selectedRealtimeModel.id,\n start,\n ]);\n\n return (\n <RealtimeVoiceControl\n snapshot={realtime.snapshot}\n canStart={realtime.canStart}\n admissionBlocker={realtime.admissionBlocker}\n modelAvailable={selectedModel.available}\n menuSide=\"top\"\n modelMenu={props.modelMenu ?? \"split\"}\n showDiagnostics={props.showDiagnostics}\n audioRef={realtime.audioRef}\n selectedModel={selectedModel}\n models={selection.models}\n onSelectModel={realtime.lifecycleActive ? undefined : selection.selectModel}\n onStart={realtime.start}\n onStop={realtime.stop}\n onRetry={realtime.retry}\n onRetryAudibleOutput={realtime.retryAudibleOutput}\n onSetInputMuted={realtime.setInputMuted}\n onSetOutputMuted={realtime.setOutputMuted}\n />\n );\n}\n\n/**\n * First available model; otherwise the model whose blocker the user can act on\n * (for example adding credits) rather than an unrelated \"connect\" prompt.\n */\nfunction fallbackRealtimeModelId(models: readonly RealtimeModelOption[]): SessionRealtimeModel {\n return (\n models.find((model) => model.available)?.id ??\n models.find((model) => model.unavailableCode)?.id ??\n CODEX_LIVE_MODEL.id\n );\n}\n\nexport function useRealtimeModelSelection(options: {\n client?: RealtimeControllerClient | undefined;\n workspaceId?: string | undefined;\n codexConnected: boolean;\n activeModel?: SessionRealtimeModel | null | undefined;\n}) {\n const { client, workspaceId } = useEmbeddedRealtimeSession({\n client: options.client,\n workspaceId: options.workspaceId,\n });\n const activeModel = options.activeModel;\n const initialCachedCatalog = readCachedRealtimeModelCatalog(client, workspaceId);\n const [catalog, setCatalog] = useState<RealtimeModelOption[]>(\n () => initialCachedCatalog ?? realtimeModelFallback(options.codexConnected),\n );\n const catalogScopeRef = useRef({\n client,\n workspaceId,\n source: initialCachedCatalog ? (\"cache\" as const) : (\"fallback\" as const),\n });\n const [selectedModelId, setSelectedModelId] = useState<SessionRealtimeModel>(() => {\n const preferred = readRealtimeModelPreference(workspaceId) ?? CODEX_LIVE_MODEL.id;\n if (!initialCachedCatalog) return preferred;\n if (initialCachedCatalog.some((model) => model.id === preferred && model.available)) {\n return preferred;\n }\n return fallbackRealtimeModelId(initialCachedCatalog);\n });\n\n useEffect(() => {\n let disposed = false;\n const requestAbort = new AbortController();\n const applyCatalog = (models: RealtimeModelOption[]) => {\n catalogScopeRef.current = { client, workspaceId, source: \"cache\" };\n setCatalog(models);\n setSelectedModelId((current) => {\n if (models.some((model) => model.id === current && model.available)) return current;\n return fallbackRealtimeModelId(models);\n });\n };\n const cached = readCachedRealtimeModelCatalog(client, workspaceId);\n if (cached) {\n const scope = catalogScopeRef.current;\n if (\n scope.client !== client ||\n scope.workspaceId !== workspaceId ||\n scope.source !== \"cache\"\n ) {\n applyCatalog(cached);\n }\n return;\n }\n const loading = loadRealtimeModelCatalog(client, workspaceId, requestAbort.signal);\n if (!loading) return;\n void loading\n .then((models) => {\n if (disposed) return;\n applyCatalog(models);\n })\n .catch(() => undefined);\n return () => {\n disposed = true;\n requestAbort.abort();\n };\n }, [client, workspaceId]);\n\n useEffect(() => {\n if (activeModel) setSelectedModelId(activeModel);\n }, [activeModel]);\n\n const selectedModel =\n catalog.find((model) => model.id === selectedModelId) ??\n ({\n ...CODEX_LIVE_MODEL,\n available: options.codexConnected,\n unavailableReason: options.codexConnected ? null : CODEX_LIVE_MODEL.unavailableReason,\n } satisfies RealtimeModelOption);\n const selectModel = useCallback(\n (value: string) => {\n const model = catalog.find((candidate) => candidate.id === value);\n if (!model || !model.available || activeModel) return;\n setSelectedModelId(model.id);\n writeRealtimeModelPreference(workspaceId, model.id);\n },\n [activeModel, catalog, workspaceId],\n );\n\n return { models: catalog, selectedModel, selectModel };\n}\n\nconst IDLE_REALTIME_SNAPSHOT: SessionRealtimeControllerSnapshot = {\n status: \"idle\",\n realtimeId: null,\n mode: null,\n bridge: null,\n microphone: \"inactive\",\n inputMuted: false,\n audibleOutput: \"inactive\",\n outputMuted: false,\n connectionGeneration: 0,\n reconnectAttempt: 0,\n diagnostic: null,\n error: null,\n};\n\ntype NewSessionRealtimeControlProps = {\n client?: RealtimeControllerClient | undefined;\n workspaceId?: string | undefined;\n codexConnected: boolean;\n disabled?: boolean | undefined;\n disabledReason?: string | null | undefined;\n onStart: (model: SessionRealtimeModel) => Promise<boolean>;\n /** Parent-owned selection (e.g. shared with the mobile “+” voice-model panel). */\n models?: readonly RealtimeModelOption[] | undefined;\n selectedModel?: RealtimeModelOption | undefined;\n onSelectModel?: ((modelId: string) => void) | undefined;\n /**\n * `split` attaches the model chevron at every breakpoint (public default).\n * `split-desktop` hides it below `sm` when the host owns mobile selection (e.g. “+”).\n * Inside a container-responsive Composer.Root, `sm` follows that composer.\n * `none` never attaches a model menu to the bar button.\n */\n modelMenu?: \"split\" | \"split-desktop\" | \"none\" | undefined;\n};\n\ntype NewSessionRealtimeSelection = {\n models: readonly RealtimeModelOption[];\n selectedModel: RealtimeModelOption;\n selectModel: (modelId: string) => void;\n};\n\nexport function NewSessionRealtimeControl(props: NewSessionRealtimeControlProps) {\n if (props.models && props.selectedModel && props.onSelectModel) {\n return (\n <NewSessionRealtimeControlView\n {...props}\n selection={{\n models: props.models,\n selectedModel: props.selectedModel,\n selectModel: props.onSelectModel,\n }}\n />\n );\n }\n return <NewSessionRealtimeControlWithInternalSelection {...props} />;\n}\n\nfunction NewSessionRealtimeControlWithInternalSelection(props: NewSessionRealtimeControlProps) {\n const selection = useRealtimeModelSelection({\n client: props.client,\n workspaceId: props.workspaceId,\n codexConnected: props.codexConnected,\n });\n return <NewSessionRealtimeControlView {...props} selection={selection} />;\n}\n\nfunction NewSessionRealtimeControlView(\n props: NewSessionRealtimeControlProps & { selection: NewSessionRealtimeSelection },\n) {\n const selection = props.selection;\n const audioRef = useRef<HTMLAudioElement>(null);\n const [starting, setStarting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const snapshot = useMemo<SessionRealtimeControllerSnapshot>(\n () =>\n starting\n ? { ...IDLE_REALTIME_SNAPSHOT, status: \"starting\" }\n : error\n ? { ...IDLE_REALTIME_SNAPSHOT, status: \"error\", error }\n : IDLE_REALTIME_SNAPSHOT,\n [error, starting],\n );\n const canStart = selection.selectedModel.available && props.disabled !== true && !starting;\n const onStart = props.onStart;\n const selectedModelId = selection.selectedModel.id;\n const start = useCallback(async () => {\n if (!canStart) return;\n setStarting(true);\n setError(null);\n try {\n const started = await onStart(selectedModelId);\n if (!started) setError(\"The voice session could not be created.\");\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause));\n } finally {\n setStarting(false);\n }\n }, [canStart, onStart, selectedModelId]);\n\n return (\n <RealtimeVoiceControl\n snapshot={snapshot}\n canStart={canStart}\n admissionBlocker={selection.selectedModel.unavailableReason ?? props.disabledReason ?? null}\n modelAvailable={selection.selectedModel.available}\n selectionDisabled={starting}\n menuSide=\"bottom\"\n modelMenu={props.modelMenu ?? \"split\"}\n showDiagnostics={false}\n audioRef={audioRef}\n selectedModel={selection.selectedModel}\n models={selection.models}\n onSelectModel={selection.selectModel}\n onStart={start}\n onStop={async () => undefined}\n onRetry={start}\n onRetryAudibleOutput={async () => undefined}\n onSetInputMuted={() => undefined}\n onSetOutputMuted={() => undefined}\n />\n );\n}\n\nexport function RealtimeVoiceControl(props: {\n snapshot: SessionRealtimeControllerSnapshot;\n canStart: boolean;\n admissionBlocker?: string | null | undefined;\n modelAvailable: boolean;\n selectionDisabled?: boolean | undefined;\n /** Prefer `bottom` on home/new-session; `top` for the docked session composer. */\n menuSide?: \"top\" | \"bottom\" | undefined;\n /**\n * `split` = start + model chevron at every breakpoint (public SDK default).\n * `split-desktop` = chevron from `sm` up; below that the host owns selection.\n * Inside a container-responsive Composer.Root, `sm` follows that composer.\n * `none` = start button only.\n */\n modelMenu?: \"split\" | \"split-desktop\" | \"none\" | undefined;\n showDiagnostics?: boolean | undefined;\n /** Extra classes on the in-bar mute cluster (e.g. `max-sm:hidden` when mutes live in “+”). */\n muteControlsClassName?: string | undefined;\n audioRef: RefObject<HTMLAudioElement | null>;\n selectedModel?: RealtimeModelOption | undefined;\n models?: readonly RealtimeModelOption[] | undefined;\n onSelectModel?: ((modelId: string) => void) | undefined;\n onStart: () => Promise<void>;\n onStop: () => Promise<void>;\n onRetry: () => Promise<void>;\n onRetryAudibleOutput: () => Promise<void>;\n onSetInputMuted: (muted: boolean) => void;\n onSetOutputMuted: (muted: boolean) => void;\n}) {\n const reduceMotion = useReducedMotion();\n const selectedModel = props.selectedModel ?? {\n ...CODEX_LIVE_MODEL,\n available: props.modelAvailable,\n unavailableReason: props.modelAvailable ? null : CODEX_LIVE_MODEL.unavailableReason,\n };\n const models = props.models ?? [selectedModel];\n const status = statusContent(\n props.snapshot,\n props.modelAvailable,\n props.canStart,\n props.admissionBlocker ?? null,\n selectedModel.label,\n selectedModel.unavailableCode ?? null,\n );\n const modeOwned = props.snapshot.mode?.state === \"active\";\n const retryConnection =\n modeOwned &&\n props.snapshot.status !== \"stopping\" &&\n props.snapshot.status !== \"active\" &&\n props.snapshot.diagnostic?.recoverable === true;\n const audioBlocked = props.snapshot.audibleOutput === \"blocked\" && !props.snapshot.outputMuted;\n // A call that ended in a failure keeps its reason on screen, not only in a\n // tooltip or the model menu, until the user starts again or changes model.\n const startFailed = props.snapshot.status === \"error\" && !modeOwned;\n const failureText =\n status.label === \"Voice unavailable\" ? status.detail : `${status.label}. ${status.detail}`;\n const mainDisabled =\n props.snapshot.status === \"stopping\" ||\n props.snapshot.status === \"lost_owner\" ||\n (!modeOwned && !props.canStart) ||\n (props.snapshot.status === \"starting\" && !modeOwned);\n const mainLabel = audioBlocked\n ? \"Resume voice audio\"\n : retryConnection\n ? \"Retry voice connection\"\n : modeOwned\n ? \"End voice conversation\"\n : !props.canStart && status.phase === \"unavailable\"\n ? `${status.label}: ${status.detail}`\n : startFailed\n ? `Try voice again with ${selectedModel.label}`\n : `Start voice with ${selectedModel.label}`;\n const runMainAction = audioBlocked\n ? props.onRetryAudibleOutput\n : retryConnection\n ? props.onRetry\n : modeOwned\n ? props.onStop\n : props.onStart;\n const diagnosticsVisible = props.showDiagnostics ?? false;\n const modelMenu = props.modelMenu ?? \"split\";\n const showAttachedModelMenu = modelMenu === \"split\" || modelMenu === \"split-desktop\";\n const desktopOnlyModelMenu = modelMenu === \"split-desktop\";\n const [pickerOpen, setPickerOpen] = useState(false);\n const [pickerProvider, setPickerProvider] = useState<RealtimeModelProvider | null>(\n selectedModel.provider,\n );\n const [pickerDirection, setPickerDirection] = useState<1 | -1>(1);\n const [failureDismissed, setFailureDismissed] = useState(false);\n useEffect(() => {\n if (!startFailed) setFailureDismissed(false);\n }, [startFailed]);\n const rootRef = useRef<HTMLDivElement>(null);\n useEffect(() => {\n if (!startFailed) return;\n // Starting dictation in this composer supersedes a stale start failure.\n const scope = composerVoiceEventScope(rootRef.current);\n if (!scope) return;\n const dismiss = () => setFailureDismissed(true);\n scope.addEventListener(COMPOSER_VOICE_INPUT_START_EVENT, dismiss);\n return () => scope.removeEventListener(COMPOSER_VOICE_INPUT_START_EVENT, dismiss);\n }, [startFailed]);\n\n useEffect(() => {\n if (!pickerOpen) setPickerProvider(selectedModel.provider);\n }, [pickerOpen, selectedModel.provider]);\n\n return (\n <div\n ref={rootRef}\n role=\"group\"\n aria-label=\"Realtime voice\"\n data-picker-side={props.menuSide ?? \"top\"}\n data-model-menu={modelMenu}\n className=\"og-realtime-control inline-flex shrink-0 items-center\"\n >\n <audio ref={props.audioRef} autoPlay className=\"hidden\" aria-hidden=\"true\" />\n <RealtimeComposerGlow phase={status.phase} reduceMotion={reduceMotion === true} />\n <AnimatePresence initial={false}>\n {modeOwned ? (\n <motion.div\n key=\"realtime-mute-controls\"\n data-testid=\"realtime-mute-controls\"\n // After dictate collapses and the model slides left, bloom mutes\n // out from the primary voice control. Exit is immediate (no delay).\n initial={reduceMotion ? false : { opacity: 0, width: 0 }}\n animate={{\n opacity: 1,\n width: \"auto\",\n transition: reduceMotion\n ? { duration: 0 }\n : { delay: 0.3, duration: 0.48, ease: [0.22, 1, 0.36, 1] },\n }}\n {...(reduceMotion\n ? {}\n : {\n exit: {\n opacity: 0,\n width: 0,\n transition: { duration: 0.28, ease: [0.4, 0, 1, 1] },\n },\n })}\n className={cn(\n \"inline-flex shrink-0 items-center overflow-hidden\",\n props.muteControlsClassName,\n )}\n >\n <motion.div\n className=\"inline-flex items-center gap-0.5 pr-1\"\n initial={reduceMotion ? false : { x: 18, opacity: 0 }}\n animate={{\n x: 0,\n opacity: 1,\n transition: reduceMotion\n ? { duration: 0 }\n : {\n delay: 0.32,\n type: \"spring\",\n stiffness: 320,\n damping: 30,\n mass: 0.8,\n },\n }}\n {...(reduceMotion\n ? {}\n : {\n exit: {\n x: 14,\n opacity: 0,\n transition: { duration: 0.22, ease: [0.4, 0, 1, 1] },\n },\n })}\n >\n <RealtimeMuteButton\n muted={props.snapshot.inputMuted}\n kind=\"microphone\"\n reduceMotion={reduceMotion === true}\n enterDelay={reduceMotion ? 0 : 0.34}\n onToggle={() => props.onSetInputMuted(!props.snapshot.inputMuted)}\n />\n <RealtimeMuteButton\n muted={props.snapshot.outputMuted}\n kind=\"output\"\n reduceMotion={reduceMotion === true}\n enterDelay={reduceMotion ? 0 : 0.4}\n onToggle={() => props.onSetOutputMuted(!props.snapshot.outputMuted)}\n />\n </motion.div>\n </motion.div>\n ) : null}\n </AnimatePresence>\n {startFailed && !failureDismissed ? (\n <button\n type=\"button\"\n data-realtime-attention=\"\"\n data-testid=\"realtime-failure-reason\"\n title=\"Dismiss\"\n aria-label={`Dismiss: ${failureText}`}\n onClick={() => setFailureDismissed(true)}\n className=\"og-realtime-failure mr-1.5 inline-flex min-w-0 items-center gap-1 rounded-og-sm text-right text-og-xs leading-tight text-og-status-failed outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent/45\"\n >\n <span className=\"og-realtime-failure-label line-clamp-2 max-w-56\">{failureText}</span>\n <XIcon className=\"size-3 shrink-0 opacity-70\" aria-hidden />\n </button>\n ) : null}\n <div className=\"inline-flex shrink-0 items-center\">\n <motion.button\n type=\"button\"\n data-testid=\"realtime-primary-action\"\n data-phase={status.phase}\n aria-label={mainLabel}\n aria-pressed={modeOwned}\n title={mainLabel}\n disabled={mainDisabled}\n {...(reduceMotion ? {} : { whileTap: { scale: 0.92 } })}\n transition={{ type: \"spring\", stiffness: 520, damping: 30 }}\n onClick={() => void runMainAction().catch(() => undefined)}\n className={cn(\n // Match transcription mic: ghost icon when idle; filled only when live.\n // Public contract: coarse pointers keep a 44px target; split menu uses\n // left-only rounding at `sm+` where the chevron attaches.\n \"og-realtime-primary relative inline-flex size-8 items-center justify-center outline-hidden\",\n \"rounded-og-md transition-[background-color,border-color,color,box-shadow] duration-200 ease-og-out\",\n \"focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-og-accent/45\",\n \"disabled:cursor-not-allowed disabled:opacity-45 pointer-coarse:size-11\",\n showAttachedModelMenu &&\n (desktopOnlyModelMenu\n ? \"sm:rounded-l-og-md sm:rounded-r-none\"\n : \"rounded-l-og-md rounded-r-none\"),\n voiceButtonTone(status.phase),\n )}\n >\n <RealtimeActionGlyph\n phase={status.phase}\n audioBlocked={audioBlocked}\n reduceMotion={reduceMotion === true}\n />\n </motion.button>\n\n {showAttachedModelMenu ? (\n <DropdownMenu open={pickerOpen} onOpenChange={setPickerOpen}>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n aria-label=\"Choose voice model and options\"\n title={`Voice model: ${selectedModel.label}`}\n disabled={props.selectionDisabled}\n className={cn(\n // Keep the split trigger compact on desktop while preserving a\n // full 44px mobile target independent of pointer-media support.\n \"og-realtime-model-trigger inline-flex h-11 w-11 items-center justify-center rounded-r-og-md outline-hidden sm:h-8 sm:w-6\",\n \"transition-[background-color,border-color,color] duration-200 ease-og-out\",\n \"focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-og-accent/45\",\n desktopOnlyModelMenu && \"hidden sm:inline-flex\",\n voiceChevronTone(status.phase),\n )}\n >\n <ChevronDownIcon className=\"size-3\" aria-hidden />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n side={props.menuSide ?? \"top\"}\n align=\"end\"\n sideOffset={8}\n collisionPadding={12}\n className=\"og-realtime-menu flex w-72 max-h-[min(20rem,var(--radix-dropdown-menu-content-available-height))] flex-col overflow-hidden\"\n onCloseAutoFocus={(event) => event.preventDefault()}\n >\n <div className=\"min-h-0 flex-1 overflow-y-auto overscroll-contain\">\n <RealtimeModelPickerMenu\n models={models}\n selectedModel={selectedModel}\n provider={pickerProvider}\n direction={pickerDirection}\n disabled={\n props.selectionDisabled === true || props.snapshot.mode?.state === \"active\"\n }\n onProviderChange={(provider, direction) => {\n setPickerDirection(direction);\n setPickerProvider(provider);\n }}\n onSelect={(modelId) => {\n props.onSelectModel?.(modelId);\n setPickerOpen(false);\n }}\n />\n </div>\n\n {status.phase !== \"idle\" &&\n // Say it once: the selected model's row already carries its reason.\n !(\n status.phase === \"unavailable\" &&\n pickerProvider === selectedModel.provider &&\n selectedModel.unavailableReason === status.detail\n ) ? (\n <>\n <DropdownMenuSeparator />\n <div className=\"px-2.5 py-2\" role=\"status\" aria-live=\"polite\">\n <div className=\"flex items-center gap-2 text-og-sm font-medium text-og-fg\">\n <RealtimeStatusDot\n phase={status.phase}\n reduceMotion={reduceMotion === true}\n />\n {status.label}\n </div>\n <p className=\"mt-1 text-og-xs leading-5 text-og-fg-subtle\">{status.detail}</p>\n </div>\n </>\n ) : null}\n\n {audioBlocked ? (\n <DropdownMenuItem\n onSelect={() => void props.onRetryAudibleOutput().catch(() => undefined)}\n >\n <Volume2Icon />\n Resume audio\n </DropdownMenuItem>\n ) : null}\n {retryConnection ? (\n <DropdownMenuItem onSelect={() => void props.onRetry().catch(() => undefined)}>\n <RotateCcwIcon />\n Retry connection\n </DropdownMenuItem>\n ) : null}\n {modeOwned && props.snapshot.status !== \"lost_owner\" ? (\n <DropdownMenuItem\n variant=\"destructive\"\n disabled={props.snapshot.status === \"stopping\"}\n onSelect={() => void props.onStop().catch(() => undefined)}\n >\n <SquareIcon />\n End voice conversation\n </DropdownMenuItem>\n ) : null}\n\n {diagnosticsVisible ? <RealtimeDiagnosticsMenu snapshot={props.snapshot} /> : null}\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n </div>\n\n <span className=\"sr-only\" role=\"status\" aria-live=\"polite\">\n {status.label}. {status.detail}\n </span>\n {props.snapshot.error ? (\n <span className=\"sr-only\" role=\"alert\">\n {props.snapshot.error}\n </span>\n ) : null}\n </div>\n );\n}\n\n/** Drill-in body for the mobile composer “+” menu — same catalog as the desktop chevron. */\nexport function RealtimeVoiceModelPanel(props: {\n models: readonly RealtimeModelOption[];\n selectedModel: RealtimeModelOption;\n disabled?: boolean | undefined;\n leading?: ReactNode | undefined;\n onSelect: (modelId: SessionRealtimeModel) => void;\n}) {\n const [provider, setProvider] = useState<RealtimeModelProvider | null>(null);\n const [direction, setDirection] = useState<1 | -1>(1);\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col\" data-testid=\"realtime-voice-model-panel\">\n <div className=\"flex min-h-10 shrink-0 items-center gap-2 border-b border-og-border px-2 pb-2\">\n {props.leading}\n <div className=\"min-w-0 flex-1 text-og-menu font-medium text-og-fg\">Voice model</div>\n </div>\n <div className=\"min-h-0 flex-1 overflow-y-auto overscroll-contain p-2\">\n <p className=\"mb-3 text-og-control text-og-fg-muted\">\n Used when you start a voice conversation.\n </p>\n <RealtimeModelPickerMenu\n models={props.models}\n selectedModel={props.selectedModel}\n provider={provider}\n direction={direction}\n disabled={props.disabled === true}\n onProviderChange={(next, nextDirection) => {\n setDirection(nextDirection);\n setProvider(next);\n }}\n onSelect={props.onSelect}\n />\n </div>\n </div>\n );\n}\n\nfunction RealtimeMuteButton(props: {\n muted: boolean;\n kind: \"microphone\" | \"output\";\n reduceMotion: boolean;\n enterDelay?: number | undefined;\n onToggle(): void;\n}) {\n const microphone = props.kind === \"microphone\";\n const label = microphone\n ? props.muted\n ? \"Unmute microphone\"\n : \"Mute microphone\"\n : props.muted\n ? \"Unmute voice audio\"\n : \"Mute voice audio\";\n const Icon = microphone\n ? props.muted\n ? MicOffIcon\n : MicIcon\n : props.muted\n ? VolumeXIcon\n : Volume2Icon;\n\n return (\n <motion.button\n type=\"button\"\n aria-label={label}\n aria-pressed={props.muted}\n title={label}\n initial={props.reduceMotion ? false : { scale: 0.72, opacity: 0 }}\n animate={{ scale: 1, opacity: 1 }}\n transition={{\n delay: props.enterDelay ?? 0,\n type: \"spring\",\n stiffness: 420,\n damping: 26,\n mass: 0.7,\n }}\n {...(props.reduceMotion ? {} : { whileTap: { scale: 0.92 } })}\n onClick={props.onToggle}\n className={cn(\n \"inline-flex size-8 shrink-0 items-center justify-center rounded-og-md outline-hidden\",\n \"transition-[background-color,border-color,color] duration-150 ease-og-out\",\n \"focus-visible:ring-2 focus-visible:ring-og-accent/45 pointer-coarse:size-11\",\n props.muted\n ? \"border border-og-accent/35 bg-og-accent-soft text-og-accent\"\n : \"text-og-fg-muted hover:bg-og-surface-2 hover:text-og-fg\",\n )}\n >\n <Icon className=\"size-3.5\" aria-hidden />\n </motion.button>\n );\n}\n\nexport function RealtimeModelPickerMenu(props: {\n models: readonly RealtimeModelOption[];\n selectedModel: RealtimeModelOption;\n provider: RealtimeModelProvider | null;\n direction: 1 | -1;\n disabled: boolean;\n onProviderChange: (provider: RealtimeModelProvider | null, direction: 1 | -1) => void;\n onSelect: (modelId: SessionRealtimeModel) => void;\n}) {\n const providers = REALTIME_MODEL_PROVIDERS.filter((provider) =>\n props.models.some((model) => model.provider === provider),\n );\n const pageKey = props.provider ? `voice-models:${props.provider}` : \"voice-providers\";\n const body = props.provider ? (\n <div data-testid=\"realtime-model-picker-models\">\n <PickerBackHeader\n label={realtimeProviderLabel(props.provider)}\n icon={\n <BillingClassMark\n billingClass={REALTIME_PROVIDER_META[props.provider].billingClass}\n aria-label=\"\"\n />\n }\n onBack={() => props.onProviderChange(null, -1)}\n />\n <div className=\"flex flex-col gap-0.5\">\n {props.models\n .filter((model) => model.provider === props.provider)\n .map((model) => {\n const selected = model.id === props.selectedModel.id;\n return (\n <PickerNavRow\n key={model.id}\n label={model.label}\n hint={\n model.unavailableReason ??\n (model.recommended ? `Recommended · ${model.description}` : model.description)\n }\n disabled={props.disabled || !model.available}\n title={model.unavailableReason ?? model.description}\n active={selected}\n showChevron={false}\n trailing={\n selected ? <CheckIcon className={MENU_CHECK_CLASS} aria-hidden /> : undefined\n }\n testId={`realtime-model-choice-${model.id}`}\n onClick={() => props.onSelect(model.id)}\n />\n );\n })}\n </div>\n </div>\n ) : (\n <div className=\"flex flex-col gap-0.5\" data-testid=\"realtime-model-picker-providers\">\n {providers.map((provider) => {\n const meta = REALTIME_PROVIDER_META[provider];\n return (\n <PickerNavRow\n key={provider}\n label={realtimeProviderLabel(provider)}\n hint={meta.hint}\n icon={<BillingClassMark billingClass={meta.billingClass} aria-label=\"\" />}\n active={props.selectedModel.provider === provider}\n testId={`realtime-model-provider-${meta.billingClass}`}\n onClick={() => props.onProviderChange(provider, 1)}\n />\n );\n })}\n </div>\n );\n\n return (\n <div className=\"relative overflow-hidden\" data-testid=\"realtime-model-picker-menu\">\n <PickerAnimatedPage pageKey={pageKey} direction={props.direction}>\n {body}\n </PickerAnimatedPage>\n </div>\n );\n}\n\nfunction RealtimeDiagnosticsMenu({ snapshot }: { snapshot: SessionRealtimeControllerSnapshot }) {\n const bridge = snapshot.bridge;\n const rows = [\n [\"controller\", snapshot.status],\n [\"microphone\", snapshot.microphone],\n [\"microphone muted\", String(snapshot.inputMuted)],\n [\"audio\", snapshot.audibleOutput],\n [\"audio muted\", String(snapshot.outputMuted)],\n [\"generation\", String(snapshot.connectionGeneration)],\n [\"reconnect attempt\", String(snapshot.reconnectAttempt)],\n [\"mode\", snapshot.mode?.state ?? \"none\"],\n [\"mode version\", snapshot.mode ? String(snapshot.mode.version) : \"—\"],\n [\"connection epoch\", snapshot.mode ? String(snapshot.mode.connectionEpoch) : \"—\"],\n [\"provider started\", bridge ? String(bridge.providerStarted) : \"false\"],\n [\"provider speaking\", bridge ? String(bridge.speaking) : \"false\"],\n [\"delegation\", bridge?.activeDelegationId ? \"active\" : \"none\"],\n [\"pending durable events\", bridge ? String(bridge.pendingInbound) : \"0\"],\n [\"pending bytes\", bridge ? String(bridge.pendingInboundBytes) : \"0\"],\n [\"client ack\", bridge?.clientAckThroughSequence?.toString() ?? \"—\"],\n [\"ignored provider events\", bridge ? String(bridge.ignoredEventCount) : \"0\"],\n [\"last ignored event\", bridge?.lastIgnoredEventType ?? \"none\"],\n [\"bridge error\", bridge?.lastError ?? \"none\"],\n [\"diagnostic\", snapshot.diagnostic?.kind ?? \"none\"],\n ] as const;\n\n return (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuSub>\n <DropdownMenuSubTrigger className=\"text-og-fg-muted\">\n Realtime diagnostics\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent className=\"max-h-80 w-72 overflow-y-auto\">\n {rows.map(([label, value]) => (\n <DropdownMenuItem\n key={label}\n disabled\n className=\"grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)] gap-3 rounded-og-md font-mono text-[11px] opacity-100\"\n >\n <span className=\"truncate text-og-fg-subtle\">{label}</span>\n <span className=\"truncate text-right text-og-fg\">{value}</span>\n </DropdownMenuItem>\n ))}\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n </>\n );\n}\n\ntype RealtimeVisualPhase =\n | \"idle\"\n | \"connecting\"\n | \"listening\"\n | \"speaking\"\n | \"reconnecting\"\n | \"blocked\"\n | \"unavailable\"\n | \"error\"\n | \"elsewhere\"\n | \"stopping\";\n\nfunction statusContent(\n snapshot: SessionRealtimeControllerSnapshot,\n modelAvailable: boolean,\n canStart: boolean,\n admissionBlocker: string | null,\n modelLabel: string,\n unavailableCode: string | null = null,\n): { phase: RealtimeVisualPhase; label: string; detail: string } {\n if (snapshot.audibleOutput === \"blocked\" && !snapshot.outputMuted) {\n return {\n phase: \"blocked\",\n label: \"Audio output blocked\",\n detail: \"Resume audio to hear the existing voice connection.\",\n };\n }\n switch (snapshot.status) {\n case \"starting\":\n return {\n phase: \"connecting\",\n label: \"Connecting…\",\n detail: \"Preparing your microphone and live voice.\",\n };\n case \"active\":\n return snapshot.bridge?.speaking\n ? {\n phase: \"speaking\",\n label: \"Speaking\",\n detail: \"Interrupt naturally whenever you want.\",\n }\n : {\n phase: \"listening\",\n label: \"Listening\",\n detail: \"Voice and typed messages share this session.\",\n };\n case \"stopping\":\n return {\n phase: \"stopping\",\n label: \"Ending voice…\",\n detail: \"Saving the remaining conversation context.\",\n };\n case \"recovering\":\n return {\n phase: \"reconnecting\",\n label: \"Reconnecting…\",\n detail: snapshot.error ?? \"Keeping this voice conversation connected.\",\n };\n case \"lost_owner\":\n return {\n phase: \"elsewhere\",\n label: \"Voice active elsewhere\",\n detail: \"Return to the browser that started it, or wait for that connection to expire.\",\n };\n case \"error\":\n if (snapshot.refusal) {\n return {\n phase: \"unavailable\",\n label: realtimeRefusalLabel(snapshot.refusal.code) ?? \"Voice unavailable\",\n detail: snapshot.refusal.message,\n };\n }\n return {\n phase: \"error\",\n label: \"Voice unavailable\",\n detail: snapshot.error ?? \"The connection could not be started.\",\n };\n case \"idle\":\n if (!modelAvailable) {\n return {\n phase: \"unavailable\",\n label: realtimeRefusalLabel(unavailableCode) ?? \"Voice model unavailable\",\n detail: admissionBlocker ?? \"Choose another voice model.\",\n };\n }\n if (!canStart && admissionBlocker) {\n return {\n phase: \"unavailable\",\n label: \"Voice unavailable\",\n detail: admissionBlocker,\n };\n }\n return {\n phase: \"idle\",\n label: \"Start voice\",\n detail: `Talk live with ${modelLabel}.`,\n };\n }\n}\n\nfunction RealtimeComposerGlow(props: { phase: RealtimeVisualPhase; reduceMotion: boolean }) {\n const visible = [\n \"connecting\",\n \"listening\",\n \"speaking\",\n \"reconnecting\",\n \"blocked\",\n \"error\",\n \"stopping\",\n ].includes(props.phase);\n return (\n <AnimatePresence initial={false}>\n {visible ? (\n <motion.span\n aria-hidden\n key={props.phase}\n initial={{ opacity: 0 }}\n animate={\n props.reduceMotion\n ? { opacity: 0.48 }\n : props.phase === \"speaking\"\n ? { opacity: [0.42, 0.82, 0.52] }\n : props.phase === \"listening\"\n ? { opacity: [0.34, 0.62, 0.42] }\n : { opacity: [0.28, 0.58, 0.28] }\n }\n exit={{ opacity: 0 }}\n transition={\n props.reduceMotion\n ? { duration: 0.12 }\n : {\n duration: props.phase === \"speaking\" ? 1.15 : 2.1,\n ease: \"easeInOut\",\n repeat: Number.POSITIVE_INFINITY,\n }\n }\n className={cn(\n \"pointer-events-none absolute -inset-px z-[1] rounded-og-lg ring-1 ring-inset shadow-og-glow\",\n props.phase === \"speaking\"\n ? \"ring-og-status-running/50\"\n : props.phase === \"blocked\" || props.phase === \"error\"\n ? \"ring-og-status-waiting/45\"\n : \"ring-og-accent/45\",\n )}\n />\n ) : null}\n </AnimatePresence>\n );\n}\n\nfunction RealtimeActionGlyph(props: {\n phase: RealtimeVisualPhase;\n audioBlocked: boolean;\n reduceMotion: boolean;\n}) {\n if ([\"connecting\", \"reconnecting\", \"stopping\"].includes(props.phase)) {\n return <LoaderCircleIcon className=\"size-3.5 animate-og-spin\" aria-hidden />;\n }\n if (props.phase === \"blocked\") {\n return props.audioBlocked ? (\n <Volume2Icon className=\"size-3.5\" aria-hidden />\n ) : (\n <CircleAlertIcon className=\"size-3.5\" aria-hidden />\n );\n }\n if (props.phase === \"error\" || props.phase === \"elsewhere\" || props.phase === \"unavailable\") {\n return <CircleAlertIcon className=\"size-3.5\" aria-hidden />;\n }\n if (props.phase === \"listening\" || props.phase === \"speaking\") {\n return (\n <span className=\"relative inline-flex size-4 items-center justify-center\">\n {!props.reduceMotion ? (\n <motion.span\n aria-hidden\n className=\"absolute inset-0 rounded-full border border-current\"\n animate={{ opacity: [0.65, 0], scale: [0.65, 1.45] }}\n transition={{\n duration: props.phase === \"speaking\" ? 0.9 : 1.5,\n ease: \"easeOut\",\n repeat: Number.POSITIVE_INFINITY,\n }}\n />\n ) : null}\n <SquareIcon className=\"relative size-2.5 fill-current\" aria-hidden />\n </span>\n );\n }\n return <AudioLinesIcon className=\"size-4\" aria-hidden />;\n}\n\nfunction RealtimeStatusDot(props: { phase: RealtimeVisualPhase; reduceMotion: boolean }) {\n const live = props.phase === \"listening\" || props.phase === \"speaking\";\n return (\n <span className=\"relative inline-flex size-2 shrink-0\" aria-hidden>\n {live && !props.reduceMotion ? (\n <motion.span\n className=\"absolute inset-0 rounded-full bg-og-status-running\"\n animate={{ opacity: [0.45, 0], scale: [1, 2.2] }}\n transition={{\n duration: 1.4,\n ease: \"easeOut\",\n repeat: Number.POSITIVE_INFINITY,\n }}\n />\n ) : null}\n <span\n className={cn(\n \"relative size-2 rounded-full\",\n live\n ? \"bg-og-status-running\"\n : props.phase === \"blocked\" || props.phase === \"error\"\n ? \"bg-og-status-waiting\"\n : props.phase === \"elsewhere\" || props.phase === \"unavailable\"\n ? \"bg-og-fg-subtle\"\n : \"bg-og-accent\",\n )}\n />\n </span>\n );\n}\n\nfunction voiceButtonTone(phase: RealtimeVisualPhase): string {\n if (phase === \"listening\" || phase === \"speaking\") {\n return \"border border-og-primary-border bg-og-primary text-og-primary-fg hover:bg-og-primary-hover\";\n }\n if (phase === \"blocked\" || phase === \"error\") {\n return \"border border-og-status-waiting/35 bg-og-status-waiting/10 text-og-status-waiting hover:bg-og-status-waiting/15\";\n }\n if (phase === \"connecting\" || phase === \"reconnecting\" || phase === \"stopping\") {\n return \"border border-og-accent/35 bg-og-accent-soft text-og-accent\";\n }\n // Idle: same ghost treatment as the composer transcription mic — no box.\n return \"text-og-fg-muted hover:bg-og-surface-2 hover:text-og-fg\";\n}\n\nfunction voiceChevronTone(phase: RealtimeVisualPhase): string {\n if (phase === \"listening\" || phase === \"speaking\") {\n return \"border border-l-0 border-og-primary-border bg-og-primary text-og-primary-fg hover:bg-og-primary-hover\";\n }\n if (phase === \"blocked\" || phase === \"error\") {\n return \"border border-l-0 border-og-status-waiting/35 bg-og-status-waiting/10 text-og-status-waiting hover:bg-og-status-waiting/15\";\n }\n if (phase === \"connecting\" || phase === \"reconnecting\" || phase === \"stopping\") {\n return \"border border-l-0 border-og-accent/35 bg-og-accent-soft text-og-accent\";\n }\n return \"text-og-fg-muted hover:bg-og-surface-2 hover:text-og-fg\";\n}\n\nfunction toRealtimeModelOption(model: WorkspaceRealtimeModelCatalogItem): RealtimeModelOption {\n return { ...model };\n}\n\nfunction readRealtimeModelPreference(workspaceId: string): SessionRealtimeModel | null {\n if (typeof localStorage === \"undefined\") return null;\n try {\n const value = localStorage.getItem(`${REALTIME_MODEL_STORAGE_PREFIX}:${workspaceId}`);\n return isRealtimeModel(value) ? value : null;\n } catch {\n return null;\n }\n}\n\nfunction writeRealtimeModelPreference(workspaceId: string, model: SessionRealtimeModel): void {\n if (typeof localStorage === \"undefined\") return;\n try {\n localStorage.setItem(`${REALTIME_MODEL_STORAGE_PREFIX}:${workspaceId}`, model);\n } catch {\n // Voice selection still works when browser storage is unavailable.\n }\n}\n\nfunction isRealtimeModel(value: string | null): value is SessionRealtimeModel {\n return (\n value === \"opengeni-azure/gpt-live-1\" ||\n value === \"gpt-live-1-boulder-alpha\" ||\n value === \"opengeni-gateway/openai/gpt-realtime-2.1\" ||\n value === \"opengeni-gateway/openai/gpt-realtime-mini\" ||\n value === \"opengeni-gateway/xai/grok-voice-think-fast-2.0\" ||\n value === \"supergrok/grok-voice-think-fast-2.0\" ||\n value === \"workspace-gateway/openai/gpt-realtime-2.1\" ||\n value === \"workspace-gateway/openai/gpt-realtime-mini\" ||\n value === \"workspace-gateway/xai/grok-voice-think-fast-2.0\"\n );\n}\n\n/** @deprecated Use the provider-neutral realtime names. */\nexport const useSessionCodexRealtime = useSessionRealtime;\n/** @deprecated Use the provider-neutral realtime names. */\nexport const useWorkspaceRealtimeModelSelection = useRealtimeModelSelection;\n/** @deprecated Use the provider-neutral realtime names. */\nexport const SessionCodexRealtimeControl = SessionRealtimeControl;\n/** @deprecated Use the provider-neutral realtime names. */\nexport const CodexRealtimeControl = RealtimeVoiceControl;\n","\"use client\";\n\nimport { ChevronRightIcon } from \"lucide-react\";\nimport { DropdownMenu as DropdownMenuPrimitive } from \"radix-ui\";\nimport { createContext, useContext, type ComponentProps, type Ref } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport {\n MENU_CHEVRON_CLASS,\n MENU_ITEM_CLASS,\n MENU_SEPARATOR_CLASS,\n MENU_SURFACE_CLASS,\n} from \"../lib/menu-styles\";\n\nconst MENU_MOTION_CLASS =\n \"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95\";\nimport { usePortalTokenSource, usePortalTokenStyle } from \"../lib/use-portal-token-style\";\n\ntype DropdownMenuSourceContextValue = {\n source: HTMLElement | null;\n ref: (node: HTMLElement | null) => void;\n};\n\nconst DropdownMenuSourceContext = createContext<DropdownMenuSourceContextValue | null>(null);\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (typeof ref === \"function\") ref(value);\n else if (ref) ref.current = value;\n}\n\nfunction DropdownMenu(props: ComponentProps<typeof DropdownMenuPrimitive.Root>) {\n const source = usePortalTokenSource<HTMLElement>();\n return (\n <DropdownMenuSourceContext.Provider value={source}>\n <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n </DropdownMenuSourceContext.Provider>\n );\n}\n\nfunction DropdownMenuTrigger({\n ref,\n ...props\n}: ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {\n const sourceRef = useContext(DropdownMenuSourceContext);\n return (\n <DropdownMenuPrimitive.Trigger\n data-slot=\"dropdown-menu-trigger\"\n ref={(node) => {\n sourceRef?.ref(node);\n assignRef(ref, node);\n }}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuContent({\n className,\n sideOffset = 4,\n style,\n ...props\n}: ComponentProps<typeof DropdownMenuPrimitive.Content>) {\n const source = useContext(DropdownMenuSourceContext);\n const portalStyle = usePortalTokenStyle(source?.source ?? null);\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n \"og-root z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto\",\n MENU_SURFACE_CLASS,\n MENU_MOTION_CLASS,\n className,\n )}\n style={{ ...portalStyle, ...style }}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n variant?: \"default\" | \"destructive\";\n}) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(MENU_ITEM_CLASS, \"data-[inset]:pl-9\", className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n return (\n <DropdownMenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(MENU_SEPARATOR_CLASS, className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSub(props: ComponentProps<typeof DropdownMenuPrimitive.Sub>) {\n return <DropdownMenuPrimitive.Sub data-slot=\"dropdown-menu-sub\" {...props} />;\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & { inset?: boolean }) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(MENU_ITEM_CLASS, \"data-[inset]:pl-9\", className)}\n {...props}\n >\n {children}\n <ChevronRightIcon aria-hidden=\"true\" className={cn(MENU_CHEVRON_CLASS, \"ml-auto\")} />\n </DropdownMenuPrimitive.SubTrigger>\n );\n}\n\nfunction DropdownMenuSubContent({\n className,\n style,\n ...props\n}: ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {\n const source = useContext(DropdownMenuSourceContext);\n const portalStyle = usePortalTokenStyle(source?.source ?? null);\n return (\n <DropdownMenuPrimitive.SubContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n \"og-root z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden\",\n MENU_SURFACE_CLASS,\n MENU_MOTION_CLASS,\n className,\n )}\n style={{ ...portalStyle, ...style }}\n {...props}\n />\n );\n}\n\nexport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n};\n"],"mappings":"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","names":["jsx","jsxs"]}
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  // src/components/artifacts/published-html-artifact-frame.tsx
2
4
  import {
3
5
  OPENGENI_SITE_BRIDGE_BOOTSTRAP_GLOBAL,
@@ -586,4 +588,4 @@ export {
586
588
  SiteList,
587
589
  SiteDetail
588
590
  };
589
- //# sourceMappingURL=chunk-SCOTPE2I.js.map
591
+ //# sourceMappingURL=chunk-YYLBXXTE.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/artifacts/published-html-artifact-frame.tsx","../src/sites-ui.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 isSiteHttpRequest,\n serveSiteHttp,\n type SiteHttpRequest,\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, useState, type CSSProperties } from \"react\";\nimport { resolveSiteClientScript } from \"@opengeni/sdk/site-document\";\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 autoHeight?: boolean;\n theme?: \"light\" | \"dark\";\n title: string;\n className?: string;\n style?: CSSProperties;\n toolBridge?: PublishedHtmlArtifactToolBridge;\n};\n\nexport type PublishedHtmlArtifactToolBridge = {\n fetch?: (request: SiteHttpRequest, signal: AbortSignal) => Promise<Response>;\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 html = resolveSiteClientScript(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 [height, setHeight] = useState<number>();\n useEffect(() => {\n if (!props.autoHeight) return;\n const receive = (event: MessageEvent) => {\n if (\n event.source !== frameRef.current?.contentWindow ||\n event.data?.type !== \"opengeni.preview.height\"\n )\n return;\n const value = event.data.height;\n if (typeof value === \"number\" && Number.isFinite(value))\n setHeight(Math.min(1200, Math.max(80, value)));\n };\n window.addEventListener(\"message\", receive);\n return () => window.removeEventListener(\"message\", receive);\n }, [props.autoHeight]);\n useEffect(() => {\n frameRef.current?.contentWindow?.postMessage(\n { type: \"opengeni.preview.theme\", theme: props.theme },\n \"*\",\n );\n }, [props.theme]);\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.addPort(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 (isSiteHttpRequest(message) && portEvent.ports.length === 1) {\n const controller = requests.start(port, message.requestId);\n if (!controller) {\n portEvent.ports[0]!.close();\n return;\n }\n void serveSiteHttp(\n message,\n portEvent.ports[0]!,\n async (request, signal) => {\n const fetch = bridgeRef.current?.fetch;\n if (!fetch) throw new Error(\"This Site host does not support the session SDK\");\n return fetch(request, signal);\n },\n controller.signal,\n ).finally(() => requests.complete(port, message.requestId, controller));\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 frameRef.current?.contentWindow?.postMessage(\n { type: \"opengeni.preview.theme\", theme: props.theme },\n \"*\",\n );\n frameLoadPendingRef.current = true;\n onFrameLoadRef.current();\n }}\n className={props.className}\n style={{ ...props.style, ...(props.autoHeight && height ? { height } : {}) }}\n />\n );\n}\n\nexport class SiteBridgeRequestRegistry {\n private readonly controllersByPort = new Map<MessagePort, Map<string, AbortController>>();\n\n addPort(port: MessagePort): void {\n // Several SDK clients may share one document bootstrap. Document teardown,\n // not another client connecting, revokes all of that document's ports.\n if (!this.controllersByPort.has(port)) 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 { useEffect, useRef, useState } from \"react\";\nimport type {\n OpenGeniClient,\n WorkspaceArtifact,\n WorkspaceArtifactContentResponse,\n WorkspaceArtifactDetailResponse,\n WorkspaceArtifactListResponse,\n} from \"@opengeni/sdk\";\nimport {\n PublishedHtmlArtifactFrame,\n type PublishedHtmlArtifactToolBridge,\n} from \"./components/artifacts/published-html-artifact-frame\";\n\n/** Implement with an authenticated host proxy. Never put an organization key\n * in browser props; replace the client object when the host actor changes. */\nexport type SiteClient = Pick<\n OpenGeniClient,\n | \"listWorkspaceArtifacts\"\n | \"getWorkspaceArtifact\"\n | \"getWorkspaceArtifactHtml\"\n | \"rollbackWorkspaceArtifact\"\n | \"setWorkspaceArtifactStatus\"\n>;\ntype SiteDisplayContent = Pick<\n WorkspaceArtifactContentResponse,\n \"artifactId\" | \"versionId\" | \"html\" | \"requestedTools\"\n>;\ntype SiteScope = { client: SiteClient; workspaceId: string; className?: string };\n/** Shared native/embedded read boundary: pin content to the observed version,\n * and never accept a response belonging to another workspace or Site. */\nexport async function loadSiteSnapshot(\n client: Pick<SiteClient, \"getWorkspaceArtifact\" | \"getWorkspaceArtifactHtml\"> &\n Partial<Pick<OpenGeniClient, \"getWorkspaceArtifactContent\">>,\n workspaceId: string,\n siteId: string,\n options: { signal?: AbortSignal; includeArchivedContent?: boolean; versionId?: string } = {},\n): Promise<{\n detail: WorkspaceArtifactDetailResponse;\n content: SiteDisplayContent | null;\n}> {\n const requestOptions = options.signal ? { signal: options.signal } : {};\n const detail = await client.getWorkspaceArtifact(workspaceId, siteId, requestOptions);\n options.signal?.throwIfAborted();\n if (detail.artifact.id !== siteId || detail.artifact.workspaceId !== workspaceId)\n throw new Error(\"Site scope mismatch\");\n const selectedVersion = options.versionId\n ? detail.versions.find((version) => version.id === options.versionId)\n : detail.artifact.currentVersion;\n const versionId = options.versionId ?? selectedVersion?.id;\n let content: SiteDisplayContent | null =\n selectedVersion &&\n versionId &&\n (detail.artifact.status === \"active\" || options.includeArchivedContent)\n ? {\n artifactId: siteId,\n versionId,\n requestedTools: selectedVersion!.requestedTools,\n html: await client.getWorkspaceArtifactHtml(workspaceId, siteId, {\n ...requestOptions,\n versionId,\n }),\n }\n : null;\n if (\n versionId &&\n !selectedVersion &&\n (detail.artifact.status === \"active\" || options.includeArchivedContent)\n ) {\n if (!client.getWorkspaceArtifactContent) throw new Error(\"Site version unavailable\");\n content = await client.getWorkspaceArtifactContent(workspaceId, siteId, {\n ...requestOptions,\n versionId,\n });\n }\n options.signal?.throwIfAborted();\n if (content && (content.artifactId !== siteId || content.versionId !== versionId))\n throw new Error(\"Site content mismatch\");\n return { detail: structuredClone(detail), content: content ? structuredClone(content) : null };\n}\nexport type SiteListProps = SiteScope & {\n status?: \"active\" | \"archived\";\n onOpen: (site: WorkspaceArtifact) => void;\n};\nexport type SiteDetailProps = SiteScope & {\n siteId: string;\n /** Presentation hint only: the backend still enforces artifacts:publish. */\n canPublish?: boolean;\n toolBridge?: PublishedHtmlArtifactToolBridge;\n};\n\nfunction useScopeKey(values: readonly unknown[]) {\n const [scope, setScope] = useState(values);\n const [generation, setGeneration] = useState(0);\n if (values.some((value, index) => value !== scope[index])) {\n setScope(values);\n setGeneration(generation + 1);\n }\n return generation;\n}\n\nexport function SiteList(props: SiteListProps) {\n const key = useScopeKey([props.client, props.workspaceId, props.status]);\n return <ScopedSiteList key={key} {...props} />;\n}\nfunction ScopedSiteList({\n client,\n workspaceId,\n status = \"active\",\n onOpen,\n className,\n}: SiteListProps) {\n const [page, setPage] = useState<WorkspaceArtifactListResponse | null>(null);\n const [cursor, setCursor] = useState<string | undefined>();\n const [error, setError] = useState(false);\n const [reload, setReload] = useState(0);\n useEffect(() => {\n const abort = new AbortController();\n setPage(null);\n setError(false);\n void Promise.resolve()\n .then(() =>\n client.listWorkspaceArtifacts(workspaceId, {\n status,\n ...(cursor ? { cursor } : {}),\n limit: 50,\n signal: abort.signal,\n }),\n )\n .then((result) => {\n if (!abort.signal.aborted) setPage(structuredClone(result));\n })\n .catch(() => {\n if (!abort.signal.aborted) setError(true);\n });\n return () => abort.abort();\n }, [client, workspaceId, status, cursor, reload]);\n return (\n <section className={className} aria-label=\"Sites\" aria-busy={!page && !error}>\n {error ? (\n <p role=\"alert\">Sites are unavailable or access has changed. Refresh to check access.</p>\n ) : !page ? (\n <p role=\"status\">Loading Sites…</p>\n ) : page.artifacts.length === 0 ? (\n <p role=\"status\">No {status} Sites.</p>\n ) : (\n <ul>\n {page.artifacts.map((site) => (\n <li key={site.id}>\n <button type=\"button\" onClick={() => onOpen(structuredClone(site))}>\n {site.title}\n </button>\n <p>{site.description}</p>\n <span>\n {site.status} · revision {site.currentVersion?.revision ?? \"unpublished\"}\n </span>\n </li>\n ))}\n </ul>\n )}\n {page?.nextCursor && (\n <button type=\"button\" onClick={() => setCursor(page.nextCursor!)}>\n Next page\n </button>\n )}\n {cursor && (\n <button type=\"button\" onClick={() => setCursor(undefined)}>\n First page\n </button>\n )}\n <button type=\"button\" onClick={() => setReload((value) => value + 1)}>\n Refresh Sites\n </button>\n </section>\n );\n}\n\nexport function SiteDetail(props: SiteDetailProps) {\n const key = useScopeKey([props.client, props.workspaceId, props.siteId]);\n return <ScopedSiteDetail key={key} {...props} />;\n}\nfunction ScopedSiteDetail({\n client,\n workspaceId,\n siteId,\n canPublish = false,\n toolBridge,\n className,\n}: SiteDetailProps) {\n const [loaded, setLoaded] = useState<{\n detail: WorkspaceArtifactDetailResponse;\n content: SiteDisplayContent | null;\n } | null>(null);\n const [error, setError] = useState(false);\n const [reload, setReload] = useState(0);\n const [busy, setBusy] = useState(false);\n const [rollbackId, setRollbackId] = useState(\"\");\n const [confirmation, setConfirmation] = useState<\"status\" | \"rollback\" | null>(null);\n const mutation = useRef<AbortController | null>(null);\n useEffect(() => () => mutation.current?.abort(), []);\n useEffect(() => {\n const abort = new AbortController();\n setLoaded(null);\n setError(false);\n setConfirmation(null);\n setRollbackId(\"\");\n void Promise.resolve()\n .then(async () => {\n const snapshot = await loadSiteSnapshot(client, workspaceId, siteId, {\n signal: abort.signal,\n });\n if (!abort.signal.aborted) setLoaded(snapshot);\n })\n .catch(() => {\n if (!abort.signal.aborted) {\n setLoaded(null);\n setError(true);\n }\n });\n return () => abort.abort();\n }, [client, workspaceId, siteId, reload]);\n // Recheck live read authority without rebuilding the iframe on every tick.\n // No overlapping polls, and failures remove the document and tool bridge.\n useEffect(() => {\n if (!loaded || busy) return;\n const abort = new AbortController();\n let checking = false;\n const timer = setInterval(() => {\n if (checking) return;\n checking = true;\n void Promise.resolve()\n .then(() => client.getWorkspaceArtifact(workspaceId, siteId, { signal: abort.signal }))\n .then((detail) => {\n if (abort.signal.aborted) return;\n if (detail.artifact.id !== siteId || detail.artifact.workspaceId !== workspaceId)\n throw new Error(\"Site scope mismatch\");\n if (\n detail.artifact.currentVersion?.id !== loaded.detail.artifact.currentVersion?.id ||\n detail.artifact.status !== loaded.detail.artifact.status\n ) {\n setLoaded(null);\n setReload((value) => value + 1);\n }\n })\n .catch(() => {\n if (!abort.signal.aborted) {\n setLoaded(null);\n setError(true);\n }\n })\n .finally(() => {\n checking = false;\n });\n }, 15_000);\n return () => {\n abort.abort();\n clearInterval(timer);\n };\n }, [client, workspaceId, siteId, loaded, busy]);\n const commit = async () => {\n const current = loaded?.detail.artifact.currentVersion;\n if (!canPublish || !loaded || !current || !confirmation || mutation.current) return;\n const abort = new AbortController();\n mutation.current = abort;\n setBusy(true);\n try {\n const common = { expectedCurrentVersionId: current.id, idempotencyKey: crypto.randomUUID() };\n if (confirmation === \"rollback\") {\n if (!loaded.detail.versions.some((version) => version.id === rollbackId))\n throw new Error(\"Unknown version\");\n await client.rollbackWorkspaceArtifact(\n workspaceId,\n siteId,\n { ...common, versionId: rollbackId, reason: \"Restore explicitly selected Site version\" },\n { signal: abort.signal },\n );\n } else {\n await client.setWorkspaceArtifactStatus(\n workspaceId,\n siteId,\n {\n ...common,\n status: loaded.detail.artifact.status === \"active\" ? \"archived\" : \"active\",\n reason: \"Explicit Site status change\",\n },\n { signal: abort.signal },\n );\n }\n if (!abort.signal.aborted) {\n setLoaded(null);\n setReload((value) => value + 1);\n }\n } catch {\n if (!abort.signal.aborted) {\n setLoaded(null);\n setError(true);\n }\n } finally {\n if (!abort.signal.aborted) {\n mutation.current = null;\n setBusy(false);\n setConfirmation(null);\n }\n }\n };\n const site = loaded?.detail.artifact;\n return (\n <section\n className={className}\n aria-label=\"Site details\"\n aria-busy={busy || (!loaded && !error)}\n >\n {error && (\n <p role=\"alert\">\n Site state could not be confirmed or access has changed. Refresh before continuing.\n </p>\n )}\n {!loaded && !error && <p role=\"status\">Loading Site…</p>}\n {site && (\n <>\n <h2>{site.title}</h2>\n <p>{site.description}</p>\n <p>\n {site.status} · revision {site.currentVersion?.revision ?? \"unpublished\"}\n </p>\n {loaded.content && (\n <PublishedHtmlArtifactFrame\n html={loaded.content.html}\n title={site.title}\n {...(toolBridge ? { toolBridge } : {})}\n />\n )}\n <h3>Versions</h3>\n <ul>\n {loaded.detail.versions.map((version) => (\n <li key={version.id}>\n Revision {version.revision} · {version.createdAt}\n {version.id === site.currentVersion?.id ? \" · current\" : \"\"}\n </li>\n ))}\n </ul>\n {loaded.detail.versionsTruncated && (\n <p>Older versions are not included in this response.</p>\n )}\n {canPublish && site.currentVersion && (\n <fieldset disabled={busy}>\n <legend>Manage Site</legend>\n <button type=\"button\" onClick={() => setConfirmation(\"status\")}>\n {site.status === \"active\" ? \"Archive Site\" : \"Restore Site\"}\n </button>\n <label>\n Version to restore\n <select\n value={rollbackId}\n onChange={(event) => {\n setRollbackId(event.target.value);\n setConfirmation(null);\n }}\n >\n <option value=\"\">Choose a version</option>\n {loaded.detail.versions\n .filter((version) => version.id !== site.currentVersion?.id)\n .map((version) => (\n <option key={version.id} value={version.id}>\n Revision {version.revision}\n </option>\n ))}\n </select>\n </label>\n <button\n type=\"button\"\n disabled={!rollbackId}\n onClick={() => setConfirmation(\"rollback\")}\n >\n Review rollback\n </button>\n {confirmation && (\n <div role=\"group\" aria-label=\"Confirm Site change\">\n <p>\n {confirmation === \"rollback\"\n ? \"Make the selected version current?\"\n : site.status === \"active\"\n ? \"Archive this Site for workspace users?\"\n : \"Restore this Site for workspace users?\"}\n </p>\n <button type=\"button\" onClick={() => void commit()}>\n Confirm change\n </button>\n <button type=\"button\" onClick={() => setConfirmation(null)}>\n Keep current state\n </button>\n </div>\n )}\n </fieldset>\n )}\n </>\n )}\n <button type=\"button\" disabled={busy} onClick={() => setReload((value) => value + 1)}>\n Refresh Site\n </button>\n </section>\n );\n}\n"],"mappings":"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","names":["controller","useEffect","useRef","useState","jsx","useState","useEffect","useRef"]}
1
+ {"version":3,"sources":["../src/components/artifacts/published-html-artifact-frame.tsx","../src/sites-ui.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 isSiteHttpRequest,\n serveSiteHttp,\n type SiteHttpRequest,\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, useState, type CSSProperties } from \"react\";\nimport { resolveSiteClientScript } from \"@opengeni/sdk/site-document\";\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 autoHeight?: boolean;\n theme?: \"light\" | \"dark\";\n title: string;\n className?: string;\n style?: CSSProperties;\n toolBridge?: PublishedHtmlArtifactToolBridge;\n};\n\nexport type PublishedHtmlArtifactToolBridge = {\n fetch?: (request: SiteHttpRequest, signal: AbortSignal) => Promise<Response>;\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 html = resolveSiteClientScript(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 [height, setHeight] = useState<number>();\n useEffect(() => {\n if (!props.autoHeight) return;\n const receive = (event: MessageEvent) => {\n if (\n event.source !== frameRef.current?.contentWindow ||\n event.data?.type !== \"opengeni.preview.height\"\n )\n return;\n const value = event.data.height;\n if (typeof value === \"number\" && Number.isFinite(value))\n setHeight(Math.min(1200, Math.max(80, value)));\n };\n window.addEventListener(\"message\", receive);\n return () => window.removeEventListener(\"message\", receive);\n }, [props.autoHeight]);\n useEffect(() => {\n frameRef.current?.contentWindow?.postMessage(\n { type: \"opengeni.preview.theme\", theme: props.theme },\n \"*\",\n );\n }, [props.theme]);\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.addPort(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 (isSiteHttpRequest(message) && portEvent.ports.length === 1) {\n const controller = requests.start(port, message.requestId);\n if (!controller) {\n portEvent.ports[0]!.close();\n return;\n }\n void serveSiteHttp(\n message,\n portEvent.ports[0]!,\n async (request, signal) => {\n const fetch = bridgeRef.current?.fetch;\n if (!fetch) throw new Error(\"This Site host does not support the session SDK\");\n return fetch(request, signal);\n },\n controller.signal,\n ).finally(() => requests.complete(port, message.requestId, controller));\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 frameRef.current?.contentWindow?.postMessage(\n { type: \"opengeni.preview.theme\", theme: props.theme },\n \"*\",\n );\n frameLoadPendingRef.current = true;\n onFrameLoadRef.current();\n }}\n className={props.className}\n style={{ ...props.style, ...(props.autoHeight && height ? { height } : {}) }}\n />\n );\n}\n\nexport class SiteBridgeRequestRegistry {\n private readonly controllersByPort = new Map<MessagePort, Map<string, AbortController>>();\n\n addPort(port: MessagePort): void {\n // Several SDK clients may share one document bootstrap. Document teardown,\n // not another client connecting, revokes all of that document's ports.\n if (!this.controllersByPort.has(port)) 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 { useEffect, useRef, useState } from \"react\";\nimport type {\n OpenGeniClient,\n WorkspaceArtifact,\n WorkspaceArtifactContentResponse,\n WorkspaceArtifactDetailResponse,\n WorkspaceArtifactListResponse,\n} from \"@opengeni/sdk\";\nimport {\n PublishedHtmlArtifactFrame,\n type PublishedHtmlArtifactToolBridge,\n} from \"./components/artifacts/published-html-artifact-frame\";\n\n/** Implement with an authenticated host proxy. Never put an organization key\n * in browser props; replace the client object when the host actor changes. */\nexport type SiteClient = Pick<\n OpenGeniClient,\n | \"listWorkspaceArtifacts\"\n | \"getWorkspaceArtifact\"\n | \"getWorkspaceArtifactHtml\"\n | \"rollbackWorkspaceArtifact\"\n | \"setWorkspaceArtifactStatus\"\n>;\ntype SiteDisplayContent = Pick<\n WorkspaceArtifactContentResponse,\n \"artifactId\" | \"versionId\" | \"html\" | \"requestedTools\"\n>;\ntype SiteScope = { client: SiteClient; workspaceId: string; className?: string };\n/** Shared native/embedded read boundary: pin content to the observed version,\n * and never accept a response belonging to another workspace or Site. */\nexport async function loadSiteSnapshot(\n client: Pick<SiteClient, \"getWorkspaceArtifact\" | \"getWorkspaceArtifactHtml\"> &\n Partial<Pick<OpenGeniClient, \"getWorkspaceArtifactContent\">>,\n workspaceId: string,\n siteId: string,\n options: { signal?: AbortSignal; includeArchivedContent?: boolean; versionId?: string } = {},\n): Promise<{\n detail: WorkspaceArtifactDetailResponse;\n content: SiteDisplayContent | null;\n}> {\n const requestOptions = options.signal ? { signal: options.signal } : {};\n const detail = await client.getWorkspaceArtifact(workspaceId, siteId, requestOptions);\n options.signal?.throwIfAborted();\n if (detail.artifact.id !== siteId || detail.artifact.workspaceId !== workspaceId)\n throw new Error(\"Site scope mismatch\");\n const selectedVersion = options.versionId\n ? detail.versions.find((version) => version.id === options.versionId)\n : detail.artifact.currentVersion;\n const versionId = options.versionId ?? selectedVersion?.id;\n let content: SiteDisplayContent | null =\n selectedVersion &&\n versionId &&\n (detail.artifact.status === \"active\" || options.includeArchivedContent)\n ? {\n artifactId: siteId,\n versionId,\n requestedTools: selectedVersion!.requestedTools,\n html: await client.getWorkspaceArtifactHtml(workspaceId, siteId, {\n ...requestOptions,\n versionId,\n }),\n }\n : null;\n if (\n versionId &&\n !selectedVersion &&\n (detail.artifact.status === \"active\" || options.includeArchivedContent)\n ) {\n if (!client.getWorkspaceArtifactContent) throw new Error(\"Site version unavailable\");\n content = await client.getWorkspaceArtifactContent(workspaceId, siteId, {\n ...requestOptions,\n versionId,\n });\n }\n options.signal?.throwIfAborted();\n if (content && (content.artifactId !== siteId || content.versionId !== versionId))\n throw new Error(\"Site content mismatch\");\n return { detail: structuredClone(detail), content: content ? structuredClone(content) : null };\n}\nexport type SiteListProps = SiteScope & {\n status?: \"active\" | \"archived\";\n onOpen: (site: WorkspaceArtifact) => void;\n};\nexport type SiteDetailProps = SiteScope & {\n siteId: string;\n /** Presentation hint only: the backend still enforces artifacts:publish. */\n canPublish?: boolean;\n toolBridge?: PublishedHtmlArtifactToolBridge;\n};\n\nfunction useScopeKey(values: readonly unknown[]) {\n const [scope, setScope] = useState(values);\n const [generation, setGeneration] = useState(0);\n if (values.some((value, index) => value !== scope[index])) {\n setScope(values);\n setGeneration(generation + 1);\n }\n return generation;\n}\n\nexport function SiteList(props: SiteListProps) {\n const key = useScopeKey([props.client, props.workspaceId, props.status]);\n return <ScopedSiteList key={key} {...props} />;\n}\nfunction ScopedSiteList({\n client,\n workspaceId,\n status = \"active\",\n onOpen,\n className,\n}: SiteListProps) {\n const [page, setPage] = useState<WorkspaceArtifactListResponse | null>(null);\n const [cursor, setCursor] = useState<string | undefined>();\n const [error, setError] = useState(false);\n const [reload, setReload] = useState(0);\n useEffect(() => {\n const abort = new AbortController();\n setPage(null);\n setError(false);\n void Promise.resolve()\n .then(() =>\n client.listWorkspaceArtifacts(workspaceId, {\n status,\n ...(cursor ? { cursor } : {}),\n limit: 50,\n signal: abort.signal,\n }),\n )\n .then((result) => {\n if (!abort.signal.aborted) setPage(structuredClone(result));\n })\n .catch(() => {\n if (!abort.signal.aborted) setError(true);\n });\n return () => abort.abort();\n }, [client, workspaceId, status, cursor, reload]);\n return (\n <section className={className} aria-label=\"Sites\" aria-busy={!page && !error}>\n {error ? (\n <p role=\"alert\">Sites are unavailable or access has changed. Refresh to check access.</p>\n ) : !page ? (\n <p role=\"status\">Loading Sites…</p>\n ) : page.artifacts.length === 0 ? (\n <p role=\"status\">No {status} Sites.</p>\n ) : (\n <ul>\n {page.artifacts.map((site) => (\n <li key={site.id}>\n <button type=\"button\" onClick={() => onOpen(structuredClone(site))}>\n {site.title}\n </button>\n <p>{site.description}</p>\n <span>\n {site.status} · revision {site.currentVersion?.revision ?? \"unpublished\"}\n </span>\n </li>\n ))}\n </ul>\n )}\n {page?.nextCursor && (\n <button type=\"button\" onClick={() => setCursor(page.nextCursor!)}>\n Next page\n </button>\n )}\n {cursor && (\n <button type=\"button\" onClick={() => setCursor(undefined)}>\n First page\n </button>\n )}\n <button type=\"button\" onClick={() => setReload((value) => value + 1)}>\n Refresh Sites\n </button>\n </section>\n );\n}\n\nexport function SiteDetail(props: SiteDetailProps) {\n const key = useScopeKey([props.client, props.workspaceId, props.siteId]);\n return <ScopedSiteDetail key={key} {...props} />;\n}\nfunction ScopedSiteDetail({\n client,\n workspaceId,\n siteId,\n canPublish = false,\n toolBridge,\n className,\n}: SiteDetailProps) {\n const [loaded, setLoaded] = useState<{\n detail: WorkspaceArtifactDetailResponse;\n content: SiteDisplayContent | null;\n } | null>(null);\n const [error, setError] = useState(false);\n const [reload, setReload] = useState(0);\n const [busy, setBusy] = useState(false);\n const [rollbackId, setRollbackId] = useState(\"\");\n const [confirmation, setConfirmation] = useState<\"status\" | \"rollback\" | null>(null);\n const mutation = useRef<AbortController | null>(null);\n useEffect(() => () => mutation.current?.abort(), []);\n useEffect(() => {\n const abort = new AbortController();\n setLoaded(null);\n setError(false);\n setConfirmation(null);\n setRollbackId(\"\");\n void Promise.resolve()\n .then(async () => {\n const snapshot = await loadSiteSnapshot(client, workspaceId, siteId, {\n signal: abort.signal,\n });\n if (!abort.signal.aborted) setLoaded(snapshot);\n })\n .catch(() => {\n if (!abort.signal.aborted) {\n setLoaded(null);\n setError(true);\n }\n });\n return () => abort.abort();\n }, [client, workspaceId, siteId, reload]);\n // Recheck live read authority without rebuilding the iframe on every tick.\n // No overlapping polls, and failures remove the document and tool bridge.\n useEffect(() => {\n if (!loaded || busy) return;\n const abort = new AbortController();\n let checking = false;\n const timer = setInterval(() => {\n if (checking) return;\n checking = true;\n void Promise.resolve()\n .then(() => client.getWorkspaceArtifact(workspaceId, siteId, { signal: abort.signal }))\n .then((detail) => {\n if (abort.signal.aborted) return;\n if (detail.artifact.id !== siteId || detail.artifact.workspaceId !== workspaceId)\n throw new Error(\"Site scope mismatch\");\n if (\n detail.artifact.currentVersion?.id !== loaded.detail.artifact.currentVersion?.id ||\n detail.artifact.status !== loaded.detail.artifact.status\n ) {\n setLoaded(null);\n setReload((value) => value + 1);\n }\n })\n .catch(() => {\n if (!abort.signal.aborted) {\n setLoaded(null);\n setError(true);\n }\n })\n .finally(() => {\n checking = false;\n });\n }, 15_000);\n return () => {\n abort.abort();\n clearInterval(timer);\n };\n }, [client, workspaceId, siteId, loaded, busy]);\n const commit = async () => {\n const current = loaded?.detail.artifact.currentVersion;\n if (!canPublish || !loaded || !current || !confirmation || mutation.current) return;\n const abort = new AbortController();\n mutation.current = abort;\n setBusy(true);\n try {\n const common = { expectedCurrentVersionId: current.id, idempotencyKey: crypto.randomUUID() };\n if (confirmation === \"rollback\") {\n if (!loaded.detail.versions.some((version) => version.id === rollbackId))\n throw new Error(\"Unknown version\");\n await client.rollbackWorkspaceArtifact(\n workspaceId,\n siteId,\n { ...common, versionId: rollbackId, reason: \"Restore explicitly selected Site version\" },\n { signal: abort.signal },\n );\n } else {\n await client.setWorkspaceArtifactStatus(\n workspaceId,\n siteId,\n {\n ...common,\n status: loaded.detail.artifact.status === \"active\" ? \"archived\" : \"active\",\n reason: \"Explicit Site status change\",\n },\n { signal: abort.signal },\n );\n }\n if (!abort.signal.aborted) {\n setLoaded(null);\n setReload((value) => value + 1);\n }\n } catch {\n if (!abort.signal.aborted) {\n setLoaded(null);\n setError(true);\n }\n } finally {\n if (!abort.signal.aborted) {\n mutation.current = null;\n setBusy(false);\n setConfirmation(null);\n }\n }\n };\n const site = loaded?.detail.artifact;\n return (\n <section\n className={className}\n aria-label=\"Site details\"\n aria-busy={busy || (!loaded && !error)}\n >\n {error && (\n <p role=\"alert\">\n Site state could not be confirmed or access has changed. Refresh before continuing.\n </p>\n )}\n {!loaded && !error && <p role=\"status\">Loading Site…</p>}\n {site && (\n <>\n <h2>{site.title}</h2>\n <p>{site.description}</p>\n <p>\n {site.status} · revision {site.currentVersion?.revision ?? \"unpublished\"}\n </p>\n {loaded.content && (\n <PublishedHtmlArtifactFrame\n html={loaded.content.html}\n title={site.title}\n {...(toolBridge ? { toolBridge } : {})}\n />\n )}\n <h3>Versions</h3>\n <ul>\n {loaded.detail.versions.map((version) => (\n <li key={version.id}>\n Revision {version.revision} · {version.createdAt}\n {version.id === site.currentVersion?.id ? \" · current\" : \"\"}\n </li>\n ))}\n </ul>\n {loaded.detail.versionsTruncated && (\n <p>Older versions are not included in this response.</p>\n )}\n {canPublish && site.currentVersion && (\n <fieldset disabled={busy}>\n <legend>Manage Site</legend>\n <button type=\"button\" onClick={() => setConfirmation(\"status\")}>\n {site.status === \"active\" ? \"Archive Site\" : \"Restore Site\"}\n </button>\n <label>\n Version to restore\n <select\n value={rollbackId}\n onChange={(event) => {\n setRollbackId(event.target.value);\n setConfirmation(null);\n }}\n >\n <option value=\"\">Choose a version</option>\n {loaded.detail.versions\n .filter((version) => version.id !== site.currentVersion?.id)\n .map((version) => (\n <option key={version.id} value={version.id}>\n Revision {version.revision}\n </option>\n ))}\n </select>\n </label>\n <button\n type=\"button\"\n disabled={!rollbackId}\n onClick={() => setConfirmation(\"rollback\")}\n >\n Review rollback\n </button>\n {confirmation && (\n <div role=\"group\" aria-label=\"Confirm Site change\">\n <p>\n {confirmation === \"rollback\"\n ? \"Make the selected version current?\"\n : site.status === \"active\"\n ? \"Archive this Site for workspace users?\"\n : \"Restore this Site for workspace users?\"}\n </p>\n <button type=\"button\" onClick={() => void commit()}>\n Confirm change\n </button>\n <button type=\"button\" onClick={() => setConfirmation(null)}>\n Keep current state\n </button>\n </div>\n )}\n </fieldset>\n )}\n </>\n )}\n <button type=\"button\" disabled={busy} onClick={() => setReload((value) => value + 1)}>\n Refresh Site\n </button>\n </section>\n );\n}\n"],"mappings":"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","names":["controller","useEffect","useRef","useState","jsx","useState","useEffect","useRef"]}
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  // src/lib/host-platform.ts
2
4
  function interactionHostPlatform() {
3
5
  if (typeof navigator === "undefined") return "other";
@@ -8,4 +10,4 @@ function interactionHostPlatform() {
8
10
  export {
9
11
  interactionHostPlatform
10
12
  };
11
- //# sourceMappingURL=chunk-RHREZ7BO.js.map
13
+ //# sourceMappingURL=chunk-ZUWF4NF7.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/host-platform.ts"],"sourcesContent":["export type InteractionHostPlatform = \"mac\" | \"other\";\n\n/** Physical client platform. Remote input adapters use this only to identify\n * the user's primary shortcut modifier; the target platform is resolved\n * separately. */\nexport function interactionHostPlatform(): InteractionHostPlatform {\n if (typeof navigator === \"undefined\") return \"other\";\n const platform = navigator.platform || navigator.userAgent;\n return /Mac|iPhone|iPad|iPod/u.test(platform) ? \"mac\" : \"other\";\n}\n"],"mappings":";AAKO,SAAS,0BAAmD;AACjE,MAAI,OAAO,cAAc,YAAa,QAAO;AAC7C,QAAM,WAAW,UAAU,YAAY,UAAU;AACjD,SAAO,wBAAwB,KAAK,QAAQ,IAAI,QAAQ;AAC1D;","names":[]}
1
+ {"version":3,"sources":["../src/lib/host-platform.ts"],"sourcesContent":["export type InteractionHostPlatform = \"mac\" | \"other\";\n\n/** Physical client platform. Remote input adapters use this only to identify\n * the user's primary shortcut modifier; the target platform is resolved\n * separately. */\nexport function interactionHostPlatform(): InteractionHostPlatform {\n if (typeof navigator === \"undefined\") return \"other\";\n const platform = navigator.platform || navigator.userAgent;\n return /Mac|iPhone|iPad|iPod/u.test(platform) ? \"mac\" : \"other\";\n}\n"],"mappings":";;;AAKO,SAAS,0BAAmD;AACjE,MAAI,OAAO,cAAc,YAAa,QAAO;AAC7C,QAAM,WAAW,UAAU,YAAY,UAAU;AACjD,SAAO,wBAAwB,KAAK,QAAQ,IAAI,QAAQ;AAC1D;","names":[]}
package/dist/clipboard.js CHANGED
@@ -1,7 +1,8 @@
1
- import "./chunk-IWIDV7SB.js";
1
+ "use client";
2
+ import "./chunk-M357MHH3.js";
2
3
  import {
3
4
  copyTextToClipboard
4
- } from "./chunk-JVYQRRC4.js";
5
+ } from "./chunk-CVYCLFMH.js";
5
6
  export {
6
7
  copyTextToClipboard
7
8
  };
@@ -5,6 +5,10 @@ export type ComposerTranscriptionMessages = {
5
5
  stop: string;
6
6
  cancel: string;
7
7
  retry: string;
8
+ /** Transcribe a recording that was stopped without transcribing or recovered. */
9
+ transcribeSaved: string;
10
+ /** Shown near the automatic stop; `{seconds}` is replaced. */
11
+ timeRemaining: string;
8
12
  pauseRetrying: string;
9
13
  requestingPermission: string;
10
14
  recording: string;
@@ -68,6 +68,12 @@ export type SessionConversationProps = ClientOverride & SessionProxyBaseUrl & {
68
68
  * (`createSessionProxyHandler({ voiceInput: false })` turns it off).
69
69
  */
70
70
  voiceInput?: boolean | undefined;
71
+ /**
72
+ * Live speech-to-speech voice in the composer. Defaults to true; the voice
73
+ * button appears only when the workspace offers an available voice model
74
+ * and the proxy has not turned it off (`realtimeVoice: false`).
75
+ */
76
+ realtimeVoice?: boolean | undefined;
71
77
  /**
72
78
  * Show the model/reasoning picker. End users of an embedded product rarely
73
79
  * choose models, so it is hidden unless this is `true` or the client config
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Internal DOM signal between the composer's two voice controls: dictation
3
+ * starting supersedes a stale live-voice start failure in the same composer.
4
+ * Not part of the public package surface.
5
+ */
6
+ export declare const COMPOSER_VOICE_INPUT_START_EVENT = "opengeni:composer-voice-input-start";
7
+ /** Closest composer root shared by both voice controls (falls back to the document). */
8
+ export declare function composerVoiceEventScope(element: Element | null): EventTarget | null;
package/dist/composer.js CHANGED
@@ -1,6 +1,7 @@
1
+ "use client";
1
2
  import {
2
3
  ModelPolicyPickerMenu
3
- } from "./chunk-SGKD2OCN.js";
4
+ } from "./chunk-IYQCWGU5.js";
4
5
  import {
5
6
  Actions,
6
7
  AttachButton,
@@ -41,9 +42,10 @@ import {
41
42
  useChatComposer,
42
43
  useChatComposerController,
43
44
  useVoiceInput
44
- } from "./chunk-LN6TCXD3.js";
45
- import "./chunk-RSI7XYXL.js";
46
- import "./chunk-BRM6FVZA.js";
45
+ } from "./chunk-IUHHPMAX.js";
46
+ import "./chunk-PBCZL4JP.js";
47
+ import "./chunk-IEE7WCLN.js";
48
+ import "./chunk-NX4ADH73.js";
47
49
  import {
48
50
  BillingClassMark,
49
51
  ModelPolicyPicker,
@@ -51,15 +53,15 @@ import {
51
53
  PickerBackHeader,
52
54
  PickerNavRow,
53
55
  defaultModelPolicyPickerMessages
54
- } from "./chunk-LNIRAOA3.js";
55
- import "./chunk-K3HQAKQX.js";
56
- import "./chunk-5F4WR7X7.js";
57
- import "./chunk-VZTQ73XT.js";
58
- import "./chunk-UTRTG6LH.js";
59
- import "./chunk-YQEAA6LT.js";
60
- import "./chunk-UGLEYEMP.js";
61
- import "./chunk-TKOTKRWY.js";
62
- import "./chunk-22KP6LR5.js";
56
+ } from "./chunk-L2J3PU7A.js";
57
+ import "./chunk-PMV53IMM.js";
58
+ import "./chunk-XS67YG5R.js";
59
+ import "./chunk-XEA5BCMA.js";
60
+ import "./chunk-LVS3MH5T.js";
61
+ import "./chunk-QHUE7E4N.js";
62
+ import "./chunk-CM7LVUKC.js";
63
+ import "./chunk-XTD7TZHW.js";
64
+ import "./chunk-TXS65BB2.js";
63
65
  export {
64
66
  Actions,
65
67
  AttachButton,