@elabs-ai/components-ai 4.2.0 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{_audio-player-media-chrome-T3XVXWRZ.js → _audio-player-media-chrome.js} +1 -1
- package/dist/_code-block-theme.js +12 -0
- package/dist/_code-block-theme.js.map +1 -0
- package/dist/{_flow-boundary-SHNWLQG5.js → _flow-boundary.js} +1 -1
- package/dist/_flow-boundary.js.map +1 -0
- package/dist/_flow-lazy.js +8 -0
- package/dist/_flow-lazy.js.map +1 -0
- package/dist/_lazy-boundary-conformance.js +2 -0
- package/dist/_lazy-boundary-conformance.js.map +1 -0
- package/dist/_lazy-cjk.js +13 -0
- package/dist/_lazy-cjk.js.map +1 -0
- package/dist/_lazy-engine-boundary.js +9 -0
- package/dist/_lazy-engine-boundary.js.map +1 -0
- package/dist/_lazy-math.js +13 -0
- package/dist/_lazy-math.js.map +1 -0
- package/dist/_lazy-mermaid.js +12 -0
- package/dist/_lazy-mermaid.js.map +1 -0
- package/dist/_mermaid-error-panel.js +9 -0
- package/dist/_mermaid-error-panel.js.map +1 -0
- package/dist/{_persona-rive-JEG44YHX.js → _persona-rive.js} +19 -24
- package/dist/_persona-rive.js.map +1 -0
- package/dist/_streamdown-i18n.js +21 -0
- package/dist/_streamdown-i18n.js.map +1 -0
- package/dist/_streamdown-safety.js +10 -0
- package/dist/_streamdown-safety.js.map +1 -0
- package/dist/_theme-scope-store.js +13 -0
- package/dist/_theme-scope-store.js.map +1 -0
- package/dist/a2ui/a2ui-surface.js +17 -0
- package/dist/a2ui/a2ui-surface.js.map +1 -0
- package/dist/a2ui/core/catalog.generated.js +10 -0
- package/dist/a2ui/core/catalog.generated.js.map +1 -0
- package/dist/a2ui/core/complete-json.js +10 -0
- package/dist/a2ui/core/complete-json.js.map +1 -0
- package/dist/a2ui/core/index.js +37 -0
- package/dist/a2ui/core/index.js.map +1 -0
- package/dist/a2ui/core/schema.js +11 -0
- package/dist/a2ui/core/schema.js.map +1 -0
- package/dist/a2ui/core/spec.js +10 -0
- package/dist/a2ui/core/spec.js.map +1 -0
- package/dist/a2ui/core/validate.js +16 -0
- package/dist/a2ui/core/validate.js.map +1 -0
- package/dist/a2ui/index.js +54 -0
- package/dist/a2ui/index.js.map +1 -0
- package/dist/a2ui/ui-catalog.js +18 -0
- package/dist/a2ui/ui-catalog.js.map +1 -0
- package/dist/agent-event.js +10 -0
- package/dist/agent-event.js.map +1 -0
- package/dist/agent-timeline.js +11 -0
- package/dist/agent-timeline.js.map +1 -0
- package/dist/agent.js +25 -0
- package/dist/agent.js.map +1 -0
- package/dist/artifact.js +23 -0
- package/dist/artifact.js.map +1 -0
- package/dist/asset-preview.js +22 -0
- package/dist/asset-preview.js.map +1 -0
- package/dist/attachments.js +33 -0
- package/dist/attachments.js.map +1 -0
- package/dist/audio-player.js +30 -0
- package/dist/audio-player.js.map +1 -0
- package/dist/audio-visualizer.js +9 -0
- package/dist/audio-visualizer.js.map +1 -0
- package/dist/canvas.js +10 -0
- package/dist/canvas.js.map +1 -0
- package/dist/chain-of-thought.js +22 -0
- package/dist/chain-of-thought.js.map +1 -0
- package/dist/chat-greeting.js +8 -0
- package/dist/chat-greeting.js.map +1 -0
- package/dist/chat-shell.js +9 -0
- package/dist/chat-shell.js.map +1 -0
- package/dist/checkpoint.js +13 -0
- package/dist/checkpoint.js.map +1 -0
- package/dist/chunk-2XOIG5TG.js +72 -0
- package/dist/chunk-2XOIG5TG.js.map +1 -0
- package/dist/chunk-34CQ2VHM.js +172 -0
- package/dist/chunk-34CQ2VHM.js.map +1 -0
- package/dist/chunk-3TDHPXZZ.js +60 -0
- package/dist/chunk-3TDHPXZZ.js.map +1 -0
- package/dist/chunk-3XNPMDZY.js +478 -0
- package/dist/chunk-3XNPMDZY.js.map +1 -0
- package/dist/chunk-3YPT3V7L.js +56 -0
- package/dist/chunk-3YPT3V7L.js.map +1 -0
- package/dist/chunk-475UEU2Q.js +87 -0
- package/dist/chunk-475UEU2Q.js.map +1 -0
- package/dist/chunk-4CBTII2I.js +95 -0
- package/dist/chunk-4CBTII2I.js.map +1 -0
- package/dist/chunk-4XRNIZMG.js +22 -0
- package/dist/chunk-4XRNIZMG.js.map +1 -0
- package/dist/chunk-5NNWUKK5.js +2 -0
- package/dist/chunk-5NNWUKK5.js.map +1 -0
- package/dist/chunk-5UOMU27Z.js +164 -0
- package/dist/chunk-5UOMU27Z.js.map +1 -0
- package/dist/chunk-5VGYZ62I.js +264 -0
- package/dist/chunk-5VGYZ62I.js.map +1 -0
- package/dist/chunk-6IQPH2OS.js +21 -0
- package/dist/chunk-6IQPH2OS.js.map +1 -0
- package/dist/chunk-6PB2MXCI.js +482 -0
- package/dist/chunk-6PB2MXCI.js.map +1 -0
- package/dist/chunk-7FD5CZEU.js +215 -0
- package/dist/chunk-7FD5CZEU.js.map +1 -0
- package/dist/chunk-7RL6KZDF.js +266 -0
- package/dist/chunk-7RL6KZDF.js.map +1 -0
- package/dist/chunk-ADOYAGGK.js +482 -0
- package/dist/chunk-ADOYAGGK.js.map +1 -0
- package/dist/chunk-BA3AEMOU.js +21 -0
- package/dist/chunk-BA3AEMOU.js.map +1 -0
- package/dist/chunk-BBHFOYML.js +336 -0
- package/dist/chunk-BBHFOYML.js.map +1 -0
- package/dist/chunk-BHUVISIY.js +221 -0
- package/dist/chunk-BHUVISIY.js.map +1 -0
- package/dist/chunk-BM2LWERA.js +100 -0
- package/dist/chunk-BM2LWERA.js.map +1 -0
- package/dist/chunk-CMOYXNPJ.js +211 -0
- package/dist/chunk-CMOYXNPJ.js.map +1 -0
- package/dist/chunk-CZP3RHC4.js +74 -0
- package/dist/chunk-CZP3RHC4.js.map +1 -0
- package/dist/chunk-DDG5JHQT.js +112 -0
- package/dist/chunk-DDG5JHQT.js.map +1 -0
- package/dist/chunk-DJODXO7I.js +38 -0
- package/dist/chunk-DJODXO7I.js.map +1 -0
- package/dist/chunk-DWJDJLPU.js +192 -0
- package/dist/chunk-DWJDJLPU.js.map +1 -0
- package/dist/chunk-DZW6LM22.js +45 -0
- package/dist/chunk-DZW6LM22.js.map +1 -0
- package/dist/chunk-ELGCZLZF.js +305 -0
- package/dist/chunk-ELGCZLZF.js.map +1 -0
- package/dist/chunk-EV3U6ZZB.js +209 -0
- package/dist/chunk-EV3U6ZZB.js.map +1 -0
- package/dist/chunk-EY7LVUKQ.js +87 -0
- package/dist/chunk-EY7LVUKQ.js.map +1 -0
- package/dist/chunk-F4C74F7M.js +230 -0
- package/dist/chunk-F4C74F7M.js.map +1 -0
- package/dist/chunk-FERYDFZA.js +108 -0
- package/dist/chunk-FERYDFZA.js.map +1 -0
- package/dist/chunk-FUIYG2DS.js +166 -0
- package/dist/chunk-FUIYG2DS.js.map +1 -0
- package/dist/chunk-GA7M34KU.js +236 -0
- package/dist/chunk-GA7M34KU.js.map +1 -0
- package/dist/chunk-GKYZT3LA.js +136 -0
- package/dist/chunk-GKYZT3LA.js.map +1 -0
- package/dist/chunk-H42LRUQ4.js +102 -0
- package/dist/chunk-H42LRUQ4.js.map +1 -0
- package/dist/chunk-HVXM2G5F.js +222 -0
- package/dist/chunk-HVXM2G5F.js.map +1 -0
- package/dist/chunk-I4RDAGVY.js +53 -0
- package/dist/chunk-I4RDAGVY.js.map +1 -0
- package/dist/chunk-IQJG4IDX.js +208 -0
- package/dist/chunk-IQJG4IDX.js.map +1 -0
- package/dist/chunk-IX2PXG4Y.js +144 -0
- package/dist/chunk-IX2PXG4Y.js.map +1 -0
- package/dist/chunk-IXICSOOP.js +287 -0
- package/dist/chunk-IXICSOOP.js.map +1 -0
- package/dist/chunk-JY5HSN4D.js +84 -0
- package/dist/chunk-JY5HSN4D.js.map +1 -0
- package/dist/chunk-L4SU3QJV.js +174 -0
- package/dist/chunk-L4SU3QJV.js.map +1 -0
- package/dist/chunk-LMNSBOBG.js +19 -0
- package/dist/chunk-LMNSBOBG.js.map +1 -0
- package/dist/chunk-MBI7D6IL.js +42 -0
- package/dist/chunk-MBI7D6IL.js.map +1 -0
- package/dist/chunk-MLFMYCPH.js +192 -0
- package/dist/chunk-MLFMYCPH.js.map +1 -0
- package/dist/chunk-MOK66734.js +33 -0
- package/dist/chunk-MOK66734.js.map +1 -0
- package/dist/chunk-MXTAWPYM.js +196 -0
- package/dist/chunk-MXTAWPYM.js.map +1 -0
- package/dist/chunk-NCL2UZKI.js +96 -0
- package/dist/chunk-NCL2UZKI.js.map +1 -0
- package/dist/chunk-NET4YLRY.js +107 -0
- package/dist/chunk-NET4YLRY.js.map +1 -0
- package/dist/chunk-NIG67CFM.js +329 -0
- package/dist/chunk-NIG67CFM.js.map +1 -0
- package/dist/chunk-NMVNNO3L.js +10 -0
- package/dist/chunk-NMVNNO3L.js.map +1 -0
- package/dist/chunk-NP7VID4K.js +2 -0
- package/dist/chunk-NP7VID4K.js.map +1 -0
- package/dist/chunk-NPUCMAG2.js +382 -0
- package/dist/chunk-NPUCMAG2.js.map +1 -0
- package/dist/chunk-NSCLRHES.js +102 -0
- package/dist/chunk-NSCLRHES.js.map +1 -0
- package/dist/chunk-OEUXHVFW.js +86 -0
- package/dist/chunk-OEUXHVFW.js.map +1 -0
- package/dist/chunk-ONBHFIMZ.js +137 -0
- package/dist/chunk-ONBHFIMZ.js.map +1 -0
- package/dist/chunk-OPH2HHL2.js +228 -0
- package/dist/chunk-OPH2HHL2.js.map +1 -0
- package/dist/chunk-OQERHIQP.js +287 -0
- package/dist/chunk-OQERHIQP.js.map +1 -0
- package/dist/chunk-P6YJAZFG.js +103 -0
- package/dist/chunk-P6YJAZFG.js.map +1 -0
- package/dist/chunk-PG7ERDOD.js +65 -0
- package/dist/chunk-PG7ERDOD.js.map +1 -0
- package/dist/chunk-PIB5JBMA.js +90 -0
- package/dist/chunk-PIB5JBMA.js.map +1 -0
- package/dist/chunk-PQ5BPIWQ.js +22 -0
- package/dist/chunk-PQ5BPIWQ.js.map +1 -0
- package/dist/chunk-PQBF6ZIQ.js +55 -0
- package/dist/chunk-PQBF6ZIQ.js.map +1 -0
- package/dist/chunk-PTWCTSZL.js +173 -0
- package/dist/chunk-PTWCTSZL.js.map +1 -0
- package/dist/chunk-QJUNPVOS.js +101 -0
- package/dist/chunk-QJUNPVOS.js.map +1 -0
- package/dist/chunk-QOBSEGCG.js +996 -0
- package/dist/chunk-QOBSEGCG.js.map +1 -0
- package/dist/chunk-QUDZOTRV.js +43 -0
- package/dist/chunk-QUDZOTRV.js.map +1 -0
- package/dist/chunk-RB7G65JC.js +213 -0
- package/dist/chunk-RB7G65JC.js.map +1 -0
- package/dist/chunk-RPHAOR7P.js +45 -0
- package/dist/chunk-RPHAOR7P.js.map +1 -0
- package/dist/chunk-RTCSH2AN.js +331 -0
- package/dist/chunk-RTCSH2AN.js.map +1 -0
- package/dist/chunk-S3ISPW3A.js +28 -0
- package/dist/chunk-S3ISPW3A.js.map +1 -0
- package/dist/chunk-SEVN656N.js +36 -0
- package/dist/chunk-SEVN656N.js.map +1 -0
- package/dist/chunk-SKVG672B.js +64 -0
- package/dist/chunk-SKVG672B.js.map +1 -0
- package/dist/chunk-SSGJ6MEM.js +1076 -0
- package/dist/chunk-SSGJ6MEM.js.map +1 -0
- package/dist/chunk-SSKZ2AED.js +118 -0
- package/dist/chunk-SSKZ2AED.js.map +1 -0
- package/dist/chunk-T56JFGXI.js +561 -0
- package/dist/chunk-T56JFGXI.js.map +1 -0
- package/dist/chunk-TCB6O74A.js +137 -0
- package/dist/chunk-TCB6O74A.js.map +1 -0
- package/dist/chunk-TTEYPO6X.js +57 -0
- package/dist/chunk-TTEYPO6X.js.map +1 -0
- package/dist/chunk-TWPHAJNM.js +462 -0
- package/dist/chunk-TWPHAJNM.js.map +1 -0
- package/dist/chunk-TXJJLP4O.js +336 -0
- package/dist/chunk-TXJJLP4O.js.map +1 -0
- package/dist/chunk-TZ6TB7VM.js +245 -0
- package/dist/chunk-TZ6TB7VM.js.map +1 -0
- package/dist/chunk-UBLKJJ7K.js +278 -0
- package/dist/chunk-UBLKJJ7K.js.map +1 -0
- package/dist/chunk-UCJ6IUFS.js +52 -0
- package/dist/chunk-UCJ6IUFS.js.map +1 -0
- package/dist/chunk-UCKFJ3QF.js +197 -0
- package/dist/chunk-UCKFJ3QF.js.map +1 -0
- package/dist/chunk-UPXSLILN.js +20 -0
- package/dist/chunk-UPXSLILN.js.map +1 -0
- package/dist/chunk-V4DORGWJ.js +92 -0
- package/dist/chunk-V4DORGWJ.js.map +1 -0
- package/dist/chunk-V6E5DYZD.js +80 -0
- package/dist/chunk-V6E5DYZD.js.map +1 -0
- package/dist/chunk-VLLYKF3P.js +96 -0
- package/dist/chunk-VLLYKF3P.js.map +1 -0
- package/dist/chunk-VLNBTOH6.js +43 -0
- package/dist/chunk-VLNBTOH6.js.map +1 -0
- package/dist/chunk-WMDSMSPL.js +303 -0
- package/dist/chunk-WMDSMSPL.js.map +1 -0
- package/dist/chunk-WU5BLGTF.js +149 -0
- package/dist/chunk-WU5BLGTF.js.map +1 -0
- package/dist/chunk-WYTZVSGK.js +245 -0
- package/dist/chunk-WYTZVSGK.js.map +1 -0
- package/dist/chunk-X47QMM6K.js +187 -0
- package/dist/chunk-X47QMM6K.js.map +1 -0
- package/dist/chunk-YHUSW7D2.js +40 -0
- package/dist/chunk-YHUSW7D2.js.map +1 -0
- package/dist/chunk-YSKD7UXX.js +126 -0
- package/dist/chunk-YSKD7UXX.js.map +1 -0
- package/dist/chunk-YYRDGWOU.js +72 -0
- package/dist/chunk-YYRDGWOU.js.map +1 -0
- package/dist/chunk-ZIGZMWM7.js +19 -0
- package/dist/chunk-ZIGZMWM7.js.map +1 -0
- package/dist/chunk-ZKRTUKNP.js +40 -0
- package/dist/chunk-ZKRTUKNP.js.map +1 -0
- package/dist/code-block.js +38 -0
- package/dist/code-block.js.map +1 -0
- package/dist/commit.js +51 -0
- package/dist/commit.js.map +1 -0
- package/dist/composer.js +15 -0
- package/dist/composer.js.map +1 -0
- package/dist/confirmation.js +53 -0
- package/dist/confirmation.js.map +1 -0
- package/dist/connection.js +8 -0
- package/dist/connection.js.map +1 -0
- package/dist/context-panel.js +25 -0
- package/dist/context-panel.js.map +1 -0
- package/dist/controls.js +10 -0
- package/dist/controls.js.map +1 -0
- package/dist/conversation.js +19 -0
- package/dist/conversation.js.map +1 -0
- package/dist/diff-view.js +15 -0
- package/dist/diff-view.js.map +1 -0
- package/dist/edge.js +10 -0
- package/dist/edge.js.map +1 -0
- package/dist/environment-variables.js +29 -0
- package/dist/environment-variables.js.map +1 -0
- package/dist/file-tree.js +23 -0
- package/dist/file-tree.js.map +1 -0
- package/dist/gallery.js +9 -0
- package/dist/gallery.js.map +1 -0
- package/dist/grouped-parts.js +21 -0
- package/dist/grouped-parts.js.map +1 -0
- package/dist/image.js +9 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +366 -98
- package/dist/index.js +672 -13577
- package/dist/index.js.map +1 -1
- package/dist/inline-citation.js +39 -0
- package/dist/inline-citation.js.map +1 -0
- package/dist/jsx-preview.js +17 -0
- package/dist/jsx-preview.js.map +1 -0
- package/dist/markdown-view.js +17 -0
- package/dist/markdown-view.js.map +1 -0
- package/dist/message-compare.js +12 -0
- package/dist/message-compare.js.map +1 -0
- package/dist/message-edit.js +19 -0
- package/dist/message-edit.js.map +1 -0
- package/dist/message-feedback.js +11 -0
- package/dist/message-feedback.js.map +1 -0
- package/dist/message-form-spec.js +38 -0
- package/dist/message-form-spec.js.map +1 -0
- package/dist/message-form.js +26 -0
- package/dist/message-form.js.map +1 -0
- package/dist/message-table-spec.js +26 -0
- package/dist/message-table-spec.js.map +1 -0
- package/dist/message-table.js +12 -0
- package/dist/message-table.js.map +1 -0
- package/dist/message.js +51 -0
- package/dist/message.js.map +1 -0
- package/dist/mic-selector.js +27 -0
- package/dist/mic-selector.js.map +1 -0
- package/dist/model-provider-logo.js +13 -0
- package/dist/model-provider-logo.js.map +1 -0
- package/dist/motion-config.js +9 -0
- package/dist/motion-config.js.map +1 -0
- package/dist/node.js +22 -0
- package/dist/node.js.map +1 -0
- package/dist/open-in-chat.js +31 -0
- package/dist/open-in-chat.js.map +1 -0
- package/dist/package-info.js +25 -0
- package/dist/package-info.js.map +1 -0
- package/dist/panel.js +10 -0
- package/dist/panel.js.map +1 -0
- package/dist/part-groups.js +18 -0
- package/dist/part-groups.js.map +1 -0
- package/dist/permission-mode-select.js +9 -0
- package/dist/permission-mode-select.js.map +1 -0
- package/dist/persona-sources.js +8 -0
- package/dist/persona-sources.js.map +1 -0
- package/dist/persona.js +14 -0
- package/dist/persona.js.map +1 -0
- package/dist/plan.js +32 -0
- package/dist/plan.js.map +1 -0
- package/dist/prompt-input-effort.js +9 -0
- package/dist/prompt-input-effort.js.map +1 -0
- package/dist/prompt-input-mode.js +10 -0
- package/dist/prompt-input-mode.js.map +1 -0
- package/dist/prompt-input-slash.js +12 -0
- package/dist/prompt-input-slash.js.map +1 -0
- package/dist/prompt-input.js +89 -0
- package/dist/prompt-input.js.map +1 -0
- package/dist/queue.js +37 -0
- package/dist/queue.js.map +1 -0
- package/dist/reasoning.js +23 -0
- package/dist/reasoning.js.map +1 -0
- package/dist/sandbox.js +28 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/schema-display.js +33 -0
- package/dist/schema-display.js.map +1 -0
- package/dist/selection-toolbar.js +11 -0
- package/dist/selection-toolbar.js.map +1 -0
- package/dist/session-header.js +9 -0
- package/dist/session-header.js.map +1 -0
- package/dist/session-status-bar.js +9 -0
- package/dist/session-status-bar.js.map +1 -0
- package/dist/shimmer.js +9 -0
- package/dist/shimmer.js.map +1 -0
- package/dist/snippet.js +17 -0
- package/dist/snippet.js.map +1 -0
- package/dist/sources.js +17 -0
- package/dist/sources.js.map +1 -0
- package/dist/speech-input.js +9 -0
- package/dist/speech-input.js.map +1 -0
- package/dist/stack-trace.js +27 -0
- package/dist/stack-trace.js.map +1 -0
- package/dist/suggestion.js +16 -0
- package/dist/suggestion.js.map +1 -0
- package/dist/task.js +18 -0
- package/dist/task.js.map +1 -0
- package/dist/test-results.js +43 -0
- package/dist/test-results.js.map +1 -0
- package/dist/token-usage.js +27 -0
- package/dist/token-usage.js.map +1 -0
- package/dist/tool-result-card.js +9 -0
- package/dist/tool-result-card.js.map +1 -0
- package/dist/tool.js +27 -0
- package/dist/tool.js.map +1 -0
- package/dist/toolbar.js +10 -0
- package/dist/toolbar.js.map +1 -0
- package/dist/transcription.js +11 -0
- package/dist/transcription.js.map +1 -0
- package/dist/turn-status.js +9 -0
- package/dist/turn-status.js.map +1 -0
- package/dist/use-audio-level.js +9 -0
- package/dist/use-audio-level.js.map +1 -0
- package/dist/voice-selector.js +47 -0
- package/dist/voice-selector.js.map +1 -0
- package/dist/web-preview.js +19 -0
- package/dist/web-preview.js.map +1 -0
- package/package.json +11 -9
- package/schemas/a2ui-surface.v1.schema.json +5434 -0
- package/src/_chat-shell-rail.tsx +3 -1
- package/src/_flow-boundary.tsx +2 -2
- package/src/_persona-rive.tsx +27 -41
- package/src/a2ui/a2ui-surface.stories.tsx +662 -0
- package/src/a2ui/a2ui-surface.test.tsx +201 -0
- package/src/a2ui/a2ui-surface.tsx +354 -0
- package/src/a2ui/catalog.source.json +772 -0
- package/src/a2ui/core/a2ui-core.test.ts +178 -0
- package/src/a2ui/core/catalog.generated.ts +1019 -0
- package/src/a2ui/core/complete-json.ts +81 -0
- package/src/a2ui/core/index.ts +10 -0
- package/src/a2ui/core/schema.ts +111 -0
- package/src/a2ui/core/spec.ts +148 -0
- package/src/a2ui/core/validate.ts +266 -0
- package/src/a2ui/index.ts +7 -0
- package/src/a2ui/ui-catalog.tsx +225 -0
- package/src/a2ui/wave1-chart-spec.test.ts +87 -0
- package/src/a2ui/wave2-chart-spec.test.ts +108 -0
- package/src/agentic-workspace.stories.tsx +6 -45
- package/src/chat-shell.test.tsx +40 -10
- package/src/chat-shell.tsx +90 -44
- package/src/chat.stories.tsx +47 -42
- package/src/composer.stories.tsx +4 -5
- package/src/composer.test.tsx +45 -0
- package/src/composer.tsx +104 -21
- package/src/context-panel.stories.tsx +1 -1
- package/src/context-panel.tsx +1 -1
- package/src/conversation.stories.tsx +1 -0
- package/src/conversation.test.tsx +16 -0
- package/src/conversation.tsx +16 -2
- package/src/diff-view.stories.tsx +79 -0
- package/src/diff-view.tsx +3 -2
- package/src/file-tree.tsx +24 -17
- package/src/gallery.stories.tsx +42 -0
- package/src/gallery.tsx +2 -2
- package/src/grouped-parts.stories.tsx +23 -0
- package/src/grouped-parts.tsx +1 -1
- package/src/index.ts +1 -0
- package/src/message-compare.stories.tsx +40 -0
- package/src/message-compare.tsx +2 -1
- package/src/message-form.tsx +1 -1
- package/src/message-table.stories.tsx +24 -0
- package/src/message-table.tsx +1 -1
- package/src/package-info.tsx +12 -9
- package/src/reasoning.stories.tsx +27 -0
- package/src/reasoning.tsx +1 -1
- package/src/session-header.stories.tsx +35 -1
- package/src/session-header.tsx +1 -1
- package/src/sources.stories.tsx +30 -0
- package/src/sources.tsx +4 -1
- package/src/templates-ai-assistant.stories.tsx +151 -87
- package/src/tool.stories.tsx +39 -0
- package/src/tool.tsx +3 -3
- package/src/toolbar.tsx +0 -10
- package/dist/_flow-boundary-SHNWLQG5.js.map +0 -1
- package/dist/_persona-rive-JEG44YHX.js.map +0 -1
- /package/dist/{_audio-player-media-chrome-T3XVXWRZ.js.map → _audio-player-media-chrome.js.map} +0 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/mic-selector.tsx
|
|
4
|
+
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
5
|
+
import { Button } from "@elabs-ai/components-ui";
|
|
6
|
+
import {
|
|
7
|
+
Command,
|
|
8
|
+
CommandEmpty,
|
|
9
|
+
CommandInput,
|
|
10
|
+
CommandItem,
|
|
11
|
+
CommandList
|
|
12
|
+
} from "@elabs-ai/components-ui";
|
|
13
|
+
import { Popover, PopoverContent, PopoverTrigger } from "@elabs-ai/components-ui";
|
|
14
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
15
|
+
import { useLocale } from "@elabs-ai/components-ui";
|
|
16
|
+
import { ChevronsUpDownIcon } from "lucide-react";
|
|
17
|
+
import {
|
|
18
|
+
createContext,
|
|
19
|
+
useCallback,
|
|
20
|
+
useContext,
|
|
21
|
+
useEffect,
|
|
22
|
+
useMemo,
|
|
23
|
+
useRef,
|
|
24
|
+
useState
|
|
25
|
+
} from "react";
|
|
26
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
27
|
+
var deviceIdRegex = /\(([\da-fA-F]{4}:[\da-fA-F]{4})\)$/;
|
|
28
|
+
var MicSelectorContext = createContext({
|
|
29
|
+
data: [],
|
|
30
|
+
onOpenChange: void 0,
|
|
31
|
+
onValueChange: void 0,
|
|
32
|
+
open: false,
|
|
33
|
+
setWidth: void 0,
|
|
34
|
+
value: void 0,
|
|
35
|
+
width: 200
|
|
36
|
+
});
|
|
37
|
+
var useAudioDevices = () => {
|
|
38
|
+
const [devices, setDevices] = useState([]);
|
|
39
|
+
const [loading, setLoading] = useState(true);
|
|
40
|
+
const [error, setError] = useState(null);
|
|
41
|
+
const [hasPermission, setHasPermission] = useState(false);
|
|
42
|
+
const loadDevicesWithoutPermission = useCallback(async () => {
|
|
43
|
+
try {
|
|
44
|
+
setLoading(true);
|
|
45
|
+
setError(null);
|
|
46
|
+
const deviceList = await navigator.mediaDevices.enumerateDevices();
|
|
47
|
+
const audioInputs = deviceList.filter((device) => device.kind === "audioinput");
|
|
48
|
+
setDevices(audioInputs);
|
|
49
|
+
} catch (caughtError) {
|
|
50
|
+
const message = caughtError instanceof Error ? caughtError.message : "Failed to get audio devices";
|
|
51
|
+
setError(message);
|
|
52
|
+
console.error("Error getting audio devices:", message);
|
|
53
|
+
} finally {
|
|
54
|
+
setLoading(false);
|
|
55
|
+
}
|
|
56
|
+
}, []);
|
|
57
|
+
const loadDevicesWithPermission = useCallback(async () => {
|
|
58
|
+
if (loading) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
setLoading(true);
|
|
63
|
+
setError(null);
|
|
64
|
+
const tempStream = await navigator.mediaDevices.getUserMedia({
|
|
65
|
+
audio: true
|
|
66
|
+
});
|
|
67
|
+
for (const track of tempStream.getTracks()) {
|
|
68
|
+
track.stop();
|
|
69
|
+
}
|
|
70
|
+
const deviceList = await navigator.mediaDevices.enumerateDevices();
|
|
71
|
+
const audioInputs = deviceList.filter((device) => device.kind === "audioinput");
|
|
72
|
+
setDevices(audioInputs);
|
|
73
|
+
setHasPermission(true);
|
|
74
|
+
} catch (caughtError) {
|
|
75
|
+
const message = caughtError instanceof Error ? caughtError.message : "Failed to get audio devices";
|
|
76
|
+
setError(message);
|
|
77
|
+
console.error("Error getting audio devices:", message);
|
|
78
|
+
} finally {
|
|
79
|
+
setLoading(false);
|
|
80
|
+
}
|
|
81
|
+
}, [loading]);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
loadDevicesWithoutPermission();
|
|
84
|
+
}, [loadDevicesWithoutPermission]);
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
const handleDeviceChange = () => {
|
|
87
|
+
if (hasPermission) {
|
|
88
|
+
loadDevicesWithPermission();
|
|
89
|
+
} else {
|
|
90
|
+
loadDevicesWithoutPermission();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
navigator.mediaDevices.addEventListener("devicechange", handleDeviceChange);
|
|
94
|
+
return () => {
|
|
95
|
+
navigator.mediaDevices.removeEventListener("devicechange", handleDeviceChange);
|
|
96
|
+
};
|
|
97
|
+
}, [hasPermission, loadDevicesWithPermission, loadDevicesWithoutPermission]);
|
|
98
|
+
return {
|
|
99
|
+
devices,
|
|
100
|
+
error,
|
|
101
|
+
hasPermission,
|
|
102
|
+
loadDevices: loadDevicesWithPermission,
|
|
103
|
+
loading
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
var MicSelector = ({
|
|
107
|
+
defaultValue,
|
|
108
|
+
value: controlledValue,
|
|
109
|
+
onValueChange: controlledOnValueChange,
|
|
110
|
+
defaultOpen = false,
|
|
111
|
+
open: controlledOpen,
|
|
112
|
+
onOpenChange: controlledOnOpenChange,
|
|
113
|
+
...props
|
|
114
|
+
}) => {
|
|
115
|
+
const [value, onValueChange] = useControllableState({
|
|
116
|
+
defaultProp: defaultValue,
|
|
117
|
+
onChange: controlledOnValueChange,
|
|
118
|
+
prop: controlledValue
|
|
119
|
+
});
|
|
120
|
+
const [open, onOpenChange] = useControllableState({
|
|
121
|
+
defaultProp: defaultOpen,
|
|
122
|
+
onChange: controlledOnOpenChange,
|
|
123
|
+
prop: controlledOpen
|
|
124
|
+
});
|
|
125
|
+
const [width, setWidth] = useState(200);
|
|
126
|
+
const { devices, loading, hasPermission, loadDevices } = useAudioDevices();
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
if (open && !hasPermission && !loading) {
|
|
129
|
+
loadDevices();
|
|
130
|
+
}
|
|
131
|
+
}, [open, hasPermission, loading, loadDevices]);
|
|
132
|
+
const contextValue = useMemo(
|
|
133
|
+
() => ({
|
|
134
|
+
data: devices,
|
|
135
|
+
onOpenChange,
|
|
136
|
+
onValueChange,
|
|
137
|
+
open,
|
|
138
|
+
setWidth,
|
|
139
|
+
value,
|
|
140
|
+
width
|
|
141
|
+
}),
|
|
142
|
+
[devices, onOpenChange, onValueChange, open, setWidth, value, width]
|
|
143
|
+
);
|
|
144
|
+
return /* @__PURE__ */ jsx(MicSelectorContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(Popover, { ...props, onOpenChange, open }) });
|
|
145
|
+
};
|
|
146
|
+
var MicSelectorTrigger = ({ children, ...props }) => {
|
|
147
|
+
const { setWidth } = useContext(MicSelectorContext);
|
|
148
|
+
const ref = useRef(null);
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
151
|
+
for (const entry of entries) {
|
|
152
|
+
const newWidth = entry.target.offsetWidth;
|
|
153
|
+
if (newWidth) {
|
|
154
|
+
setWidth?.(newWidth);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
if (ref.current) {
|
|
159
|
+
resizeObserver.observe(ref.current);
|
|
160
|
+
}
|
|
161
|
+
return () => {
|
|
162
|
+
resizeObserver.disconnect();
|
|
163
|
+
};
|
|
164
|
+
}, [setWidth]);
|
|
165
|
+
return /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "outline", ...props, ref, children: [
|
|
166
|
+
children,
|
|
167
|
+
/* @__PURE__ */ jsx(ChevronsUpDownIcon, { className: "shrink-0 text-muted-foreground", size: 16 })
|
|
168
|
+
] }) });
|
|
169
|
+
};
|
|
170
|
+
var MicSelectorContent = ({
|
|
171
|
+
className,
|
|
172
|
+
popoverOptions,
|
|
173
|
+
...props
|
|
174
|
+
}) => {
|
|
175
|
+
const { width, onValueChange, value } = useContext(MicSelectorContext);
|
|
176
|
+
return /* @__PURE__ */ jsx(PopoverContent, { className: cn("p-0", className), style: { width }, ...popoverOptions, children: /* @__PURE__ */ jsx(Command, { onValueChange, value, ...props }) });
|
|
177
|
+
};
|
|
178
|
+
var MicSelectorInput = ({ ...props }) => {
|
|
179
|
+
const { t } = useLocale();
|
|
180
|
+
return /* @__PURE__ */ jsx(CommandInput, { placeholder: t("ai.micSelector.searchPlaceholder"), ...props });
|
|
181
|
+
};
|
|
182
|
+
var MicSelectorList = ({ children, ...props }) => {
|
|
183
|
+
const { data } = useContext(MicSelectorContext);
|
|
184
|
+
return /* @__PURE__ */ jsx(CommandList, { ...props, children: children(data) });
|
|
185
|
+
};
|
|
186
|
+
var MicSelectorEmpty = ({
|
|
187
|
+
children = "No microphone found.",
|
|
188
|
+
...props
|
|
189
|
+
}) => /* @__PURE__ */ jsx(CommandEmpty, { ...props, children });
|
|
190
|
+
var MicSelectorItem = (props) => {
|
|
191
|
+
const { onValueChange, onOpenChange } = useContext(MicSelectorContext);
|
|
192
|
+
const handleSelect = useCallback(
|
|
193
|
+
(currentValue) => {
|
|
194
|
+
onValueChange?.(currentValue);
|
|
195
|
+
onOpenChange?.(false);
|
|
196
|
+
},
|
|
197
|
+
[onValueChange, onOpenChange]
|
|
198
|
+
);
|
|
199
|
+
return /* @__PURE__ */ jsx(CommandItem, { onSelect: handleSelect, ...props });
|
|
200
|
+
};
|
|
201
|
+
var MicSelectorLabel = ({ device, className, ...props }) => {
|
|
202
|
+
const matches = device.label.match(deviceIdRegex);
|
|
203
|
+
if (!matches) {
|
|
204
|
+
return /* @__PURE__ */ jsx("span", { className, ...props, children: device.label });
|
|
205
|
+
}
|
|
206
|
+
const [, deviceId] = matches;
|
|
207
|
+
const name = device.label.replace(deviceIdRegex, "");
|
|
208
|
+
return /* @__PURE__ */ jsxs("span", { className, ...props, children: [
|
|
209
|
+
/* @__PURE__ */ jsx("span", { children: name }),
|
|
210
|
+
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
211
|
+
" (",
|
|
212
|
+
deviceId,
|
|
213
|
+
")"
|
|
214
|
+
] })
|
|
215
|
+
] });
|
|
216
|
+
};
|
|
217
|
+
var MicSelectorValue = ({ className, ...props }) => {
|
|
218
|
+
const { data, value } = useContext(MicSelectorContext);
|
|
219
|
+
const currentDevice = data.find((d) => d.deviceId === value);
|
|
220
|
+
if (!currentDevice) {
|
|
221
|
+
return /* @__PURE__ */ jsx("span", { className: cn("flex-1 text-start", className), ...props, children: "Select microphone..." });
|
|
222
|
+
}
|
|
223
|
+
return /* @__PURE__ */ jsx(
|
|
224
|
+
MicSelectorLabel,
|
|
225
|
+
{
|
|
226
|
+
className: cn("flex-1 text-start", className),
|
|
227
|
+
device: currentDevice,
|
|
228
|
+
...props
|
|
229
|
+
}
|
|
230
|
+
);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
export {
|
|
234
|
+
useAudioDevices,
|
|
235
|
+
MicSelector,
|
|
236
|
+
MicSelectorTrigger,
|
|
237
|
+
MicSelectorContent,
|
|
238
|
+
MicSelectorInput,
|
|
239
|
+
MicSelectorList,
|
|
240
|
+
MicSelectorEmpty,
|
|
241
|
+
MicSelectorItem,
|
|
242
|
+
MicSelectorLabel,
|
|
243
|
+
MicSelectorValue
|
|
244
|
+
};
|
|
245
|
+
//# sourceMappingURL=chunk-WYTZVSGK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mic-selector.tsx"],"sourcesContent":["\"use client\";\n\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { Button } from \"@elabs-ai/components-ui\";\nimport {\n Command,\n CommandEmpty,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"@elabs-ai/components-ui\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { useLocale } from \"@elabs-ai/components-ui\";\nimport { ChevronsUpDownIcon } from \"lucide-react\";\nimport type { ComponentProps, ReactNode } from \"react\";\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nconst deviceIdRegex = /\\(([\\da-fA-F]{4}:[\\da-fA-F]{4})\\)$/;\n\ninterface MicSelectorContextType {\n data: MediaDeviceInfo[];\n value: string | undefined;\n onValueChange?: (value: string) => void;\n open: boolean;\n onOpenChange?: (open: boolean) => void;\n width: number;\n setWidth?: (width: number) => void;\n}\n\nconst MicSelectorContext = createContext<MicSelectorContextType>({\n data: [],\n onOpenChange: undefined,\n onValueChange: undefined,\n open: false,\n setWidth: undefined,\n value: undefined,\n width: 200,\n});\n\nexport const useAudioDevices = () => {\n const [devices, setDevices] = useState<MediaDeviceInfo[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [hasPermission, setHasPermission] = useState(false);\n\n const loadDevicesWithoutPermission = useCallback(async () => {\n try {\n setLoading(true);\n setError(null);\n\n const deviceList = await navigator.mediaDevices.enumerateDevices();\n const audioInputs = deviceList.filter((device) => device.kind === \"audioinput\");\n\n setDevices(audioInputs);\n } catch (caughtError) {\n const message =\n caughtError instanceof Error ? caughtError.message : \"Failed to get audio devices\";\n\n setError(message);\n console.error(\"Error getting audio devices:\", message);\n } finally {\n setLoading(false);\n }\n }, []);\n\n const loadDevicesWithPermission = useCallback(async () => {\n if (loading) {\n return;\n }\n\n try {\n setLoading(true);\n setError(null);\n\n const tempStream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n });\n\n for (const track of tempStream.getTracks()) {\n track.stop();\n }\n\n const deviceList = await navigator.mediaDevices.enumerateDevices();\n const audioInputs = deviceList.filter((device) => device.kind === \"audioinput\");\n\n setDevices(audioInputs);\n setHasPermission(true);\n } catch (caughtError) {\n const message =\n caughtError instanceof Error ? caughtError.message : \"Failed to get audio devices\";\n\n setError(message);\n console.error(\"Error getting audio devices:\", message);\n } finally {\n setLoading(false);\n }\n }, [loading]);\n\n useEffect(() => {\n loadDevicesWithoutPermission();\n }, [loadDevicesWithoutPermission]);\n\n useEffect(() => {\n const handleDeviceChange = () => {\n if (hasPermission) {\n loadDevicesWithPermission();\n } else {\n loadDevicesWithoutPermission();\n }\n };\n\n navigator.mediaDevices.addEventListener(\"devicechange\", handleDeviceChange);\n\n return () => {\n navigator.mediaDevices.removeEventListener(\"devicechange\", handleDeviceChange);\n };\n }, [hasPermission, loadDevicesWithPermission, loadDevicesWithoutPermission]);\n\n return {\n devices,\n error,\n hasPermission,\n loadDevices: loadDevicesWithPermission,\n loading,\n };\n};\n\nexport type MicSelectorProps = ComponentProps<typeof Popover> & {\n defaultValue?: string;\n value?: string | undefined;\n onValueChange?: (value: string | undefined) => void;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n};\n\nexport const MicSelector = ({\n defaultValue,\n value: controlledValue,\n onValueChange: controlledOnValueChange,\n defaultOpen = false,\n open: controlledOpen,\n onOpenChange: controlledOnOpenChange,\n ...props\n}: MicSelectorProps) => {\n const [value, onValueChange] = useControllableState<string | undefined>({\n defaultProp: defaultValue,\n onChange: controlledOnValueChange,\n prop: controlledValue,\n });\n const [open, onOpenChange] = useControllableState({\n defaultProp: defaultOpen,\n onChange: controlledOnOpenChange,\n prop: controlledOpen,\n });\n const [width, setWidth] = useState(200);\n const { devices, loading, hasPermission, loadDevices } = useAudioDevices();\n\n useEffect(() => {\n if (open && !hasPermission && !loading) {\n loadDevices();\n }\n }, [open, hasPermission, loading, loadDevices]);\n\n const contextValue = useMemo(\n () => ({\n data: devices,\n onOpenChange,\n onValueChange,\n open,\n setWidth,\n value,\n width,\n }),\n [devices, onOpenChange, onValueChange, open, setWidth, value, width],\n );\n\n return (\n <MicSelectorContext.Provider value={contextValue}>\n <Popover {...props} onOpenChange={onOpenChange} open={open} />\n </MicSelectorContext.Provider>\n );\n};\n\nexport type MicSelectorTriggerProps = ComponentProps<typeof Button>;\n\nexport const MicSelectorTrigger = ({ children, ...props }: MicSelectorTriggerProps) => {\n const { setWidth } = useContext(MicSelectorContext);\n const ref = useRef<HTMLButtonElement>(null);\n\n useEffect(() => {\n // Create a ResizeObserver to detect width changes\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const newWidth = (entry.target as HTMLElement).offsetWidth;\n if (newWidth) {\n setWidth?.(newWidth);\n }\n }\n });\n\n if (ref.current) {\n resizeObserver.observe(ref.current);\n }\n\n // Clean up the observer when component unmounts\n return () => {\n resizeObserver.disconnect();\n };\n }, [setWidth]);\n\n return (\n <PopoverTrigger asChild>\n <Button variant=\"outline\" {...props} ref={ref}>\n {children}\n <ChevronsUpDownIcon className=\"shrink-0 text-muted-foreground\" size={16} />\n </Button>\n </PopoverTrigger>\n );\n};\n\nexport type MicSelectorContentProps = ComponentProps<typeof Command> & {\n popoverOptions?: ComponentProps<typeof PopoverContent>;\n};\n\nexport const MicSelectorContent = ({\n className,\n popoverOptions,\n ...props\n}: MicSelectorContentProps) => {\n const { width, onValueChange, value } = useContext(MicSelectorContext);\n\n return (\n <PopoverContent className={cn(\"p-0\", className)} style={{ width }} {...popoverOptions}>\n <Command onValueChange={onValueChange} value={value} {...props} />\n </PopoverContent>\n );\n};\n\nexport type MicSelectorInputProps = ComponentProps<typeof CommandInput> & {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n};\n\nexport const MicSelectorInput = ({ ...props }: MicSelectorInputProps) => {\n const { t } = useLocale();\n return <CommandInput placeholder={t(\"ai.micSelector.searchPlaceholder\")} {...props} />;\n};\n\nexport type MicSelectorListProps = Omit<ComponentProps<typeof CommandList>, \"children\"> & {\n children: (devices: MediaDeviceInfo[]) => ReactNode;\n};\n\nexport const MicSelectorList = ({ children, ...props }: MicSelectorListProps) => {\n const { data } = useContext(MicSelectorContext);\n\n return <CommandList {...props}>{children(data)}</CommandList>;\n};\n\nexport type MicSelectorEmptyProps = ComponentProps<typeof CommandEmpty>;\n\nexport const MicSelectorEmpty = ({\n children = \"No microphone found.\",\n ...props\n}: MicSelectorEmptyProps) => <CommandEmpty {...props}>{children}</CommandEmpty>;\n\nexport type MicSelectorItemProps = ComponentProps<typeof CommandItem>;\n\nexport const MicSelectorItem = (props: MicSelectorItemProps) => {\n const { onValueChange, onOpenChange } = useContext(MicSelectorContext);\n\n const handleSelect = useCallback(\n (currentValue: string) => {\n onValueChange?.(currentValue);\n onOpenChange?.(false);\n },\n [onValueChange, onOpenChange],\n );\n\n return <CommandItem onSelect={handleSelect} {...props} />;\n};\n\nexport type MicSelectorLabelProps = ComponentProps<\"span\"> & {\n device: MediaDeviceInfo;\n};\n\nexport const MicSelectorLabel = ({ device, className, ...props }: MicSelectorLabelProps) => {\n const matches = device.label.match(deviceIdRegex);\n\n if (!matches) {\n return (\n <span className={className} {...props}>\n {device.label}\n </span>\n );\n }\n\n const [, deviceId] = matches;\n const name = device.label.replace(deviceIdRegex, \"\");\n\n return (\n <span className={className} {...props}>\n <span>{name}</span>\n <span className=\"text-muted-foreground\"> ({deviceId})</span>\n </span>\n );\n};\n\nexport type MicSelectorValueProps = ComponentProps<\"span\">;\n\nexport const MicSelectorValue = ({ className, ...props }: MicSelectorValueProps) => {\n const { data, value } = useContext(MicSelectorContext);\n const currentDevice = data.find((d) => d.deviceId === value);\n\n if (!currentDevice) {\n return (\n <span className={cn(\"flex-1 text-start\", className)} {...props}>\n Select microphone...\n </span>\n );\n }\n\n return (\n <MicSelectorLabel\n className={cn(\"flex-1 text-start\", className)}\n device={currentDevice}\n {...props}\n />\n );\n};\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
Shimmer
|
|
4
|
+
} from "./chunk-3YPT3V7L.js";
|
|
5
|
+
import {
|
|
6
|
+
getStreamdownPluginsKey,
|
|
7
|
+
useStreamdownMermaidOptions,
|
|
8
|
+
useStreamdownPlugins,
|
|
9
|
+
useStreamdownTranslations
|
|
10
|
+
} from "./chunk-PQBF6ZIQ.js";
|
|
11
|
+
|
|
12
|
+
// src/reasoning.tsx
|
|
13
|
+
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
14
|
+
import {
|
|
15
|
+
Collapsible,
|
|
16
|
+
CollapsibleContent,
|
|
17
|
+
CollapsibleTrigger,
|
|
18
|
+
useLocale
|
|
19
|
+
} from "@elabs-ai/components-ui";
|
|
20
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
21
|
+
import { BrainIcon, ChevronDownIcon } from "lucide-react";
|
|
22
|
+
import {
|
|
23
|
+
createContext,
|
|
24
|
+
memo,
|
|
25
|
+
useCallback,
|
|
26
|
+
useContext,
|
|
27
|
+
useEffect,
|
|
28
|
+
useMemo,
|
|
29
|
+
useRef,
|
|
30
|
+
useState
|
|
31
|
+
} from "react";
|
|
32
|
+
import { Streamdown } from "streamdown";
|
|
33
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
34
|
+
var ReasoningContext = createContext(null);
|
|
35
|
+
var useReasoning = () => {
|
|
36
|
+
const context = useContext(ReasoningContext);
|
|
37
|
+
if (!context) {
|
|
38
|
+
throw new Error("Reasoning components must be used within Reasoning");
|
|
39
|
+
}
|
|
40
|
+
return context;
|
|
41
|
+
};
|
|
42
|
+
var AUTO_CLOSE_DELAY = 1e3;
|
|
43
|
+
var MS_IN_S = 1e3;
|
|
44
|
+
var Reasoning = memo(
|
|
45
|
+
({
|
|
46
|
+
className,
|
|
47
|
+
isStreaming = false,
|
|
48
|
+
open,
|
|
49
|
+
defaultOpen,
|
|
50
|
+
onOpenChange,
|
|
51
|
+
duration: durationProp,
|
|
52
|
+
children,
|
|
53
|
+
...props
|
|
54
|
+
}) => {
|
|
55
|
+
const resolvedDefaultOpen = defaultOpen ?? isStreaming;
|
|
56
|
+
const isExplicitlyClosed = defaultOpen === false;
|
|
57
|
+
const [isOpen, setIsOpen] = useControllableState({
|
|
58
|
+
defaultProp: resolvedDefaultOpen,
|
|
59
|
+
onChange: onOpenChange,
|
|
60
|
+
prop: open
|
|
61
|
+
});
|
|
62
|
+
const [duration, setDuration] = useControllableState({
|
|
63
|
+
defaultProp: void 0,
|
|
64
|
+
prop: durationProp
|
|
65
|
+
});
|
|
66
|
+
const hasEverStreamedRef = useRef(isStreaming);
|
|
67
|
+
const [hasAutoClosed, setHasAutoClosed] = useState(false);
|
|
68
|
+
const startTimeRef = useRef(null);
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (isStreaming) {
|
|
71
|
+
hasEverStreamedRef.current = true;
|
|
72
|
+
if (startTimeRef.current === null) {
|
|
73
|
+
startTimeRef.current = Date.now();
|
|
74
|
+
}
|
|
75
|
+
} else if (startTimeRef.current !== null) {
|
|
76
|
+
setDuration(Math.ceil((Date.now() - startTimeRef.current) / MS_IN_S));
|
|
77
|
+
startTimeRef.current = null;
|
|
78
|
+
}
|
|
79
|
+
}, [isStreaming, setDuration]);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
if (isStreaming && !isOpen && !isExplicitlyClosed) {
|
|
82
|
+
setIsOpen(true);
|
|
83
|
+
}
|
|
84
|
+
}, [isStreaming, isOpen, setIsOpen, isExplicitlyClosed]);
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (hasEverStreamedRef.current && !isStreaming && isOpen && !hasAutoClosed) {
|
|
87
|
+
const timer = setTimeout(() => {
|
|
88
|
+
setIsOpen(false);
|
|
89
|
+
setHasAutoClosed(true);
|
|
90
|
+
}, AUTO_CLOSE_DELAY);
|
|
91
|
+
return () => clearTimeout(timer);
|
|
92
|
+
}
|
|
93
|
+
}, [isStreaming, isOpen, setIsOpen, hasAutoClosed]);
|
|
94
|
+
const handleOpenChange = useCallback(
|
|
95
|
+
(newOpen) => {
|
|
96
|
+
setIsOpen(newOpen);
|
|
97
|
+
},
|
|
98
|
+
[setIsOpen]
|
|
99
|
+
);
|
|
100
|
+
const contextValue = useMemo(
|
|
101
|
+
() => ({ duration, isOpen, isStreaming, setIsOpen }),
|
|
102
|
+
[duration, isOpen, isStreaming, setIsOpen]
|
|
103
|
+
);
|
|
104
|
+
return /* @__PURE__ */ jsx(ReasoningContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
|
|
105
|
+
Collapsible,
|
|
106
|
+
{
|
|
107
|
+
className: cn("not-prose mb-4", className),
|
|
108
|
+
onOpenChange: handleOpenChange,
|
|
109
|
+
open: isOpen,
|
|
110
|
+
...props,
|
|
111
|
+
children
|
|
112
|
+
}
|
|
113
|
+
) });
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
var defaultGetThinkingMessage = (isStreaming, duration, t) => {
|
|
117
|
+
if (isStreaming || duration === 0) {
|
|
118
|
+
return /* @__PURE__ */ jsx(Shimmer, { duration: 1, children: t("ai.reasoning.thinking") });
|
|
119
|
+
}
|
|
120
|
+
if (duration === void 0) {
|
|
121
|
+
return /* @__PURE__ */ jsx("p", { children: t("ai.reasoning.thoughtDefault") });
|
|
122
|
+
}
|
|
123
|
+
return /* @__PURE__ */ jsx("p", { children: t("ai.reasoning.thoughtForDuration", { duration }) });
|
|
124
|
+
};
|
|
125
|
+
var ReasoningTrigger = memo(
|
|
126
|
+
({ className, children, getThinkingMessage, ...props }) => {
|
|
127
|
+
const { isStreaming, isOpen, duration } = useReasoning();
|
|
128
|
+
const { t } = useLocale();
|
|
129
|
+
return /* @__PURE__ */ jsx(
|
|
130
|
+
CollapsibleTrigger,
|
|
131
|
+
{
|
|
132
|
+
className: cn(
|
|
133
|
+
"flex w-full items-center gap-2 text-muted-foreground text-body transition-colors hover:text-foreground focus-ring",
|
|
134
|
+
className
|
|
135
|
+
),
|
|
136
|
+
...props,
|
|
137
|
+
children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
138
|
+
/* @__PURE__ */ jsx(BrainIcon, { className: "size-4" }),
|
|
139
|
+
getThinkingMessage ? getThinkingMessage(isStreaming, duration) : defaultGetThinkingMessage(isStreaming, duration, t),
|
|
140
|
+
/* @__PURE__ */ jsx(
|
|
141
|
+
ChevronDownIcon,
|
|
142
|
+
{
|
|
143
|
+
className: cn("size-4 transition-transform", isOpen ? "rotate-180" : "rotate-0")
|
|
144
|
+
}
|
|
145
|
+
)
|
|
146
|
+
] })
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
var ReasoningContent = memo(({ className, children, ...props }) => {
|
|
152
|
+
const translations = useStreamdownTranslations();
|
|
153
|
+
const plugins = useStreamdownPlugins(typeof children === "string" ? children : "");
|
|
154
|
+
const mermaidOptions = useStreamdownMermaidOptions();
|
|
155
|
+
return /* @__PURE__ */ jsx(
|
|
156
|
+
CollapsibleContent,
|
|
157
|
+
{
|
|
158
|
+
className: cn(
|
|
159
|
+
"mt-4 text-body",
|
|
160
|
+
"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in data-[state=open]:[--tw-ease:var(--ease-entrance)] data-[state=closed]:[--tw-ease:var(--ease-exit)]",
|
|
161
|
+
className
|
|
162
|
+
),
|
|
163
|
+
...props,
|
|
164
|
+
children: typeof children === "string" ? /* @__PURE__ */ jsx(
|
|
165
|
+
Streamdown,
|
|
166
|
+
{
|
|
167
|
+
plugins,
|
|
168
|
+
translations,
|
|
169
|
+
mermaid: mermaidOptions,
|
|
170
|
+
children
|
|
171
|
+
},
|
|
172
|
+
getStreamdownPluginsKey(plugins)
|
|
173
|
+
) : children
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
});
|
|
177
|
+
Reasoning.displayName = "Reasoning";
|
|
178
|
+
ReasoningTrigger.displayName = "ReasoningTrigger";
|
|
179
|
+
ReasoningContent.displayName = "ReasoningContent";
|
|
180
|
+
|
|
181
|
+
export {
|
|
182
|
+
useReasoning,
|
|
183
|
+
Reasoning,
|
|
184
|
+
ReasoningTrigger,
|
|
185
|
+
ReasoningContent
|
|
186
|
+
};
|
|
187
|
+
//# sourceMappingURL=chunk-X47QMM6K.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/reasoning.tsx"],"sourcesContent":["\"use client\";\n\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n useLocale,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport {\n getStreamdownPluginsKey,\n useStreamdownMermaidOptions,\n useStreamdownPlugins,\n useStreamdownTranslations,\n} from \"./_streamdown-i18n\";\nimport { BrainIcon, ChevronDownIcon } from \"lucide-react\";\nimport type { ComponentProps, ReactNode } from \"react\";\nimport {\n createContext,\n memo,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { Streamdown } from \"streamdown\";\n\nimport { Shimmer } from \"./shimmer\";\n\ninterface ReasoningContextValue {\n isStreaming: boolean;\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n duration: number | undefined;\n}\n\nconst ReasoningContext = createContext<ReasoningContextValue | null>(null);\n\nexport const useReasoning = () => {\n const context = useContext(ReasoningContext);\n if (!context) {\n throw new Error(\"Reasoning components must be used within Reasoning\");\n }\n return context;\n};\n\nexport type ReasoningProps = ComponentProps<typeof Collapsible> & {\n isStreaming?: boolean;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n duration?: number;\n};\n\nconst AUTO_CLOSE_DELAY = 1000;\nconst MS_IN_S = 1000;\n\nexport const Reasoning = memo(\n ({\n className,\n isStreaming = false,\n open,\n defaultOpen,\n onOpenChange,\n duration: durationProp,\n children,\n ...props\n }: ReasoningProps) => {\n const resolvedDefaultOpen = defaultOpen ?? isStreaming;\n // Track if defaultOpen was explicitly set to false (to prevent auto-open)\n const isExplicitlyClosed = defaultOpen === false;\n\n const [isOpen, setIsOpen] = useControllableState<boolean>({\n defaultProp: resolvedDefaultOpen,\n onChange: onOpenChange,\n prop: open,\n });\n const [duration, setDuration] = useControllableState<number | undefined>({\n defaultProp: undefined,\n prop: durationProp,\n });\n\n const hasEverStreamedRef = useRef(isStreaming);\n const [hasAutoClosed, setHasAutoClosed] = useState(false);\n const startTimeRef = useRef<number | null>(null);\n\n // Track when streaming starts and compute duration\n useEffect(() => {\n if (isStreaming) {\n hasEverStreamedRef.current = true;\n if (startTimeRef.current === null) {\n startTimeRef.current = Date.now();\n }\n } else if (startTimeRef.current !== null) {\n setDuration(Math.ceil((Date.now() - startTimeRef.current) / MS_IN_S));\n startTimeRef.current = null;\n }\n }, [isStreaming, setDuration]);\n\n // Auto-open when streaming starts (unless explicitly closed)\n useEffect(() => {\n if (isStreaming && !isOpen && !isExplicitlyClosed) {\n setIsOpen(true);\n }\n }, [isStreaming, isOpen, setIsOpen, isExplicitlyClosed]);\n\n // Auto-close when streaming ends (once only, and only if it ever streamed)\n useEffect(() => {\n if (hasEverStreamedRef.current && !isStreaming && isOpen && !hasAutoClosed) {\n const timer = setTimeout(() => {\n setIsOpen(false);\n setHasAutoClosed(true);\n }, AUTO_CLOSE_DELAY);\n\n return () => clearTimeout(timer);\n }\n }, [isStreaming, isOpen, setIsOpen, hasAutoClosed]);\n\n const handleOpenChange = useCallback(\n (newOpen: boolean) => {\n setIsOpen(newOpen);\n },\n [setIsOpen],\n );\n\n const contextValue = useMemo(\n () => ({ duration, isOpen, isStreaming, setIsOpen }),\n [duration, isOpen, isStreaming, setIsOpen],\n );\n\n return (\n <ReasoningContext.Provider value={contextValue}>\n <Collapsible\n className={cn(\"not-prose mb-4\", className)}\n onOpenChange={handleOpenChange}\n open={isOpen}\n {...props}\n >\n {children}\n </Collapsible>\n </ReasoningContext.Provider>\n );\n },\n);\n\nexport type ReasoningTriggerProps = ComponentProps<typeof CollapsibleTrigger> & {\n getThinkingMessage?: (isStreaming: boolean, duration?: number) => ReactNode;\n};\n\nconst defaultGetThinkingMessage = (\n isStreaming: boolean,\n duration: number | undefined,\n t: (key: string, vars?: Record<string, string | number>) => string,\n) => {\n if (isStreaming || duration === 0) {\n return <Shimmer duration={1}>{t(\"ai.reasoning.thinking\")}</Shimmer>;\n }\n if (duration === undefined) {\n return <p>{t(\"ai.reasoning.thoughtDefault\")}</p>;\n }\n return <p>{t(\"ai.reasoning.thoughtForDuration\", { duration })}</p>;\n};\n\nexport const ReasoningTrigger = memo(\n ({ className, children, getThinkingMessage, ...props }: ReasoningTriggerProps) => {\n const { isStreaming, isOpen, duration } = useReasoning();\n const { t } = useLocale();\n\n return (\n <CollapsibleTrigger\n className={cn(\n \"flex w-full items-center gap-2 text-muted-foreground text-body transition-colors hover:text-foreground focus-ring\",\n className,\n )}\n {...props}\n >\n {children ?? (\n <>\n <BrainIcon className=\"size-4\" />\n {getThinkingMessage\n ? getThinkingMessage(isStreaming, duration)\n : defaultGetThinkingMessage(isStreaming, duration, t)}\n <ChevronDownIcon\n className={cn(\"size-4 transition-transform\", isOpen ? \"rotate-180\" : \"rotate-0\")}\n />\n </>\n )}\n </CollapsibleTrigger>\n );\n },\n);\n\nexport type ReasoningContentProps = Omit<ComponentProps<typeof CollapsibleContent>, \"children\"> & {\n /**\n * The reasoning body.\n *\n * A **string** is rendered as streamed markdown (Streamdown) — the default for\n * model reasoning text. Any other node renders **as-is**, so a structured live\n * ledger (a timeline, per-step status) can live inside the disclosure without\n * being handed to a markdown parser. Mirrors the `getThinkingMessage` /\n * `children` override seam on `ReasoningTrigger`.\n *\n * Note an **array** of strings is not a `string` — `{[\"a\", \"b\"]}` renders raw.\n * Pass one string if you want it parsed as markdown.\n */\n children: ReactNode;\n};\n\nexport const ReasoningContent = memo(({ className, children, ...props }: ReasoningContentProps) => {\n // Streamdown's own chrome (code copy, table menus) reads the locale seam (#310).\n const translations = useStreamdownTranslations();\n // Brand-token-derived `code` plugin, not the package's static github-*\n // default (#315 follow-up) — re-derives when the active theme changes.\n // `math`/`cjk` are lazy-loaded off the raw text (#perf-5, see\n // `_streamdown-i18n.ts`) — pass `children` so they load only when this\n // reasoning block actually needs them.\n const plugins = useStreamdownPlugins(typeof children === \"string\" ? children : \"\");\n // The TOP-LEVEL Streamdown `mermaid` prop — catches a failed diagram\n // render, including a missing `mermaid` optional peer (issue #33).\n const mermaidOptions = useStreamdownMermaidOptions();\n\n return (\n <CollapsibleContent\n className={cn(\n \"mt-4 text-body\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in data-[state=open]:[--tw-ease:var(--ease-entrance)] data-[state=closed]:[--tw-ease:var(--ease-exit)]\",\n className,\n )}\n {...props}\n >\n {typeof children === \"string\" ? (\n <Streamdown\n // Forces a remount the first time the lazy math/cjk slot resolves —\n // see `getStreamdownPluginsKey`'s doc in `_streamdown-i18n.ts` for why.\n key={getStreamdownPluginsKey(plugins)}\n plugins={plugins}\n translations={translations}\n mermaid={mermaidOptions}\n >\n {children}\n </Streamdown>\n ) : (\n children\n )}\n </CollapsibleContent>\n );\n});\n\nReasoning.displayName = \"Reasoning\";\nReasoningTrigger.displayName = \"ReasoningTrigger\";\nReasoningContent.displayName = \"ReasoningContent\";\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/persona-sources.ts
|
|
4
|
+
var PERSONA_SOURCES = {
|
|
5
|
+
command: {
|
|
6
|
+
dynamicColor: true,
|
|
7
|
+
hasModel: true,
|
|
8
|
+
source: "https://ejiidnob33g9ap1r.public.blob.vercel-storage.com/command-2.0.riv"
|
|
9
|
+
},
|
|
10
|
+
glint: {
|
|
11
|
+
dynamicColor: true,
|
|
12
|
+
hasModel: true,
|
|
13
|
+
source: "https://ejiidnob33g9ap1r.public.blob.vercel-storage.com/glint-2.0.riv"
|
|
14
|
+
},
|
|
15
|
+
halo: {
|
|
16
|
+
dynamicColor: true,
|
|
17
|
+
hasModel: true,
|
|
18
|
+
source: "https://ejiidnob33g9ap1r.public.blob.vercel-storage.com/halo-2.0.riv"
|
|
19
|
+
},
|
|
20
|
+
mana: {
|
|
21
|
+
dynamicColor: false,
|
|
22
|
+
hasModel: true,
|
|
23
|
+
source: "https://ejiidnob33g9ap1r.public.blob.vercel-storage.com/mana-2.0.riv"
|
|
24
|
+
},
|
|
25
|
+
obsidian: {
|
|
26
|
+
dynamicColor: true,
|
|
27
|
+
hasModel: true,
|
|
28
|
+
source: "https://ejiidnob33g9ap1r.public.blob.vercel-storage.com/obsidian-2.0.riv"
|
|
29
|
+
},
|
|
30
|
+
opal: {
|
|
31
|
+
dynamicColor: false,
|
|
32
|
+
hasModel: false,
|
|
33
|
+
source: "https://ejiidnob33g9ap1r.public.blob.vercel-storage.com/orb-1.2.riv"
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
PERSONA_SOURCES
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=chunk-YHUSW7D2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/persona-sources.ts"],"sourcesContent":["/**\n * Persona artwork sources — a plain data module shared by `persona.tsx` (the\n * public shell) and `_persona-rive.tsx` (the lazily-loaded Rive half), so\n * neither has to import the other.\n */\n\nexport type PersonaState = \"idle\" | \"listening\" | \"thinking\" | \"speaking\" | \"asleep\";\n\nexport interface PersonaSource {\n /** The artwork exposes a colour view-model that follows the light/dark theme. */\n dynamicColor: boolean;\n /** The artwork has a Rive view-model (vs. a plain state machine). */\n hasModel: boolean;\n /** Absolute URL of the `.riv` artwork. */\n source: string;\n}\n\n/**\n * Where the shipped `.riv` artwork is fetched from.\n *\n * ⚠️ These are REMOTE origins fetched at runtime by the Rive runtime — a\n * deployment with a restrictive `connect-src` blocks them, and the component\n * falls back to a token-driven orb. Self-host the six files and pass\n * `<Persona src={…}>` to point at your own copies. See `docs/CSP-AND-NETWORK.md`.\n */\nexport const PERSONA_SOURCES = {\n command: {\n dynamicColor: true,\n hasModel: true,\n source: \"https://ejiidnob33g9ap1r.public.blob.vercel-storage.com/command-2.0.riv\",\n },\n glint: {\n dynamicColor: true,\n hasModel: true,\n source: \"https://ejiidnob33g9ap1r.public.blob.vercel-storage.com/glint-2.0.riv\",\n },\n halo: {\n dynamicColor: true,\n hasModel: true,\n source: \"https://ejiidnob33g9ap1r.public.blob.vercel-storage.com/halo-2.0.riv\",\n },\n mana: {\n dynamicColor: false,\n hasModel: true,\n source: \"https://ejiidnob33g9ap1r.public.blob.vercel-storage.com/mana-2.0.riv\",\n },\n obsidian: {\n dynamicColor: true,\n hasModel: true,\n source: \"https://ejiidnob33g9ap1r.public.blob.vercel-storage.com/obsidian-2.0.riv\",\n },\n opal: {\n dynamicColor: false,\n hasModel: false,\n source: \"https://ejiidnob33g9ap1r.public.blob.vercel-storage.com/orb-1.2.riv\",\n },\n} as const satisfies Record<string, PersonaSource>;\n\nexport type PersonaVariant = keyof typeof PERSONA_SOURCES;\n"],"mappings":";;;AAyBO,IAAM,kBAAkB;AAAA,EAC7B,SAAS;AAAA,IACP,cAAc;AAAA,IACd,UAAU;AAAA,IACV,QAAQ;AAAA,EACV;AAAA,EACA,OAAO;AAAA,IACL,cAAc;AAAA,IACd,UAAU;AAAA,IACV,QAAQ;AAAA,EACV;AAAA,EACA,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,UAAU;AAAA,IACV,QAAQ;AAAA,EACV;AAAA,EACA,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,UAAU;AAAA,IACV,QAAQ;AAAA,EACV;AAAA,EACA,UAAU;AAAA,IACR,cAAc;AAAA,IACd,UAAU;AAAA,IACV,QAAQ;AAAA,EACV;AAAA,EACA,MAAM;AAAA,IACJ,cAAc;AAAA,IACd,UAAU;AAAA,IACV,QAAQ;AAAA,EACV;AACF;","names":[]}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/part-groups.ts
|
|
4
|
+
var RUNNING_STATES = /* @__PURE__ */ new Set([
|
|
5
|
+
"input-streaming",
|
|
6
|
+
"input-available",
|
|
7
|
+
"approval-requested",
|
|
8
|
+
"approval-responded",
|
|
9
|
+
"calling",
|
|
10
|
+
"streaming",
|
|
11
|
+
"in-progress"
|
|
12
|
+
]);
|
|
13
|
+
var ERROR_STATES = /* @__PURE__ */ new Set(["output-error", "error", "failed"]);
|
|
14
|
+
var COMPLETE_STATES = /* @__PURE__ */ new Set(["output-available", "output-denied", "done", "complete"]);
|
|
15
|
+
function defaultPartStatus(part) {
|
|
16
|
+
if (part.isStreaming === true) return "running";
|
|
17
|
+
const state = typeof part.state === "string" ? part.state : void 0;
|
|
18
|
+
if (state) {
|
|
19
|
+
if (ERROR_STATES.has(state)) return "error";
|
|
20
|
+
if (RUNNING_STATES.has(state)) return "running";
|
|
21
|
+
if (COMPLETE_STATES.has(state)) return "complete";
|
|
22
|
+
}
|
|
23
|
+
if (part.errorText || part.error) return "error";
|
|
24
|
+
return "complete";
|
|
25
|
+
}
|
|
26
|
+
function rollupStatus(statuses) {
|
|
27
|
+
if (statuses.some((s) => s === "running")) return "running";
|
|
28
|
+
if (statuses.some((s) => s === "error")) return "error";
|
|
29
|
+
if (statuses.some((s) => s === "pending")) return "pending";
|
|
30
|
+
return "complete";
|
|
31
|
+
}
|
|
32
|
+
function leafKey(part, index) {
|
|
33
|
+
const id = typeof part.id === "string" && part.id || typeof part.toolCallId === "string" && part.toolCallId || null;
|
|
34
|
+
return id ?? `${part.type}#${index}`;
|
|
35
|
+
}
|
|
36
|
+
function buildLevel(entries, statusOf) {
|
|
37
|
+
const out = [];
|
|
38
|
+
let i = 0;
|
|
39
|
+
while (i < entries.length) {
|
|
40
|
+
const entry = entries[i];
|
|
41
|
+
if (entry.path.length === 0) {
|
|
42
|
+
out.push({
|
|
43
|
+
kind: "leaf",
|
|
44
|
+
key: leafKey(entry.part, entry.index),
|
|
45
|
+
index: entry.index,
|
|
46
|
+
part: entry.part
|
|
47
|
+
});
|
|
48
|
+
i += 1;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const key0 = entry.path[0];
|
|
52
|
+
const run = [];
|
|
53
|
+
let j = i;
|
|
54
|
+
while (j < entries.length && entries[j].path.length > 0 && entries[j].path[0] === key0) {
|
|
55
|
+
run.push(entries[j]);
|
|
56
|
+
j += 1;
|
|
57
|
+
}
|
|
58
|
+
const childEntries = run.map((r) => ({
|
|
59
|
+
part: r.part,
|
|
60
|
+
index: r.index,
|
|
61
|
+
path: r.path.slice(1)
|
|
62
|
+
}));
|
|
63
|
+
const children = buildLevel(childEntries, statusOf);
|
|
64
|
+
const indices = run.map((r) => r.index);
|
|
65
|
+
const status = rollupStatus(run.map((r) => statusOf(r.part)));
|
|
66
|
+
out.push({
|
|
67
|
+
kind: "group",
|
|
68
|
+
// First member index keeps the group key stable across append-only streams.
|
|
69
|
+
key: `${key0}@${run[0].index}`,
|
|
70
|
+
group: { type: key0, status, indices },
|
|
71
|
+
children
|
|
72
|
+
});
|
|
73
|
+
i = j;
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
function buildPartGroups(parts, groupBy, getStatus) {
|
|
78
|
+
const statusOf = (part) => getStatus?.(part) ?? defaultPartStatus(part);
|
|
79
|
+
const entries = parts.map((part, index) => {
|
|
80
|
+
let path = [];
|
|
81
|
+
try {
|
|
82
|
+
path = groupBy(part, { index, parts }) ?? [];
|
|
83
|
+
} catch {
|
|
84
|
+
path = [];
|
|
85
|
+
}
|
|
86
|
+
return { part, index, path };
|
|
87
|
+
});
|
|
88
|
+
return buildLevel(entries, statusOf);
|
|
89
|
+
}
|
|
90
|
+
function partsFingerprint(parts, getStatus) {
|
|
91
|
+
return parts.map((part, index) => {
|
|
92
|
+
const status = getStatus?.(part) ?? defaultPartStatus(part);
|
|
93
|
+
return `${leafKey(part, index)}:${part.type}:${status}`;
|
|
94
|
+
}).join("|");
|
|
95
|
+
}
|
|
96
|
+
var DEFAULT_INLINE = [/^reasoning$/, /^tool-/, "dynamic-tool", "step-start"];
|
|
97
|
+
var DEFAULT_STANDALONE = [/approval/i, /human/i, "confirmation"];
|
|
98
|
+
function matchesAny(type, patterns) {
|
|
99
|
+
return patterns.some((p) => typeof p === "string" ? p === type : p.test(type));
|
|
100
|
+
}
|
|
101
|
+
function groupPartByType(options = {}) {
|
|
102
|
+
const groupKey = options.groupKey ?? "group-work";
|
|
103
|
+
const inline = options.inline ?? DEFAULT_INLINE;
|
|
104
|
+
const standalone = options.standalone ?? DEFAULT_STANDALONE;
|
|
105
|
+
return (part) => {
|
|
106
|
+
const explicit = options.classify?.(part);
|
|
107
|
+
if (explicit === "standalone") return [];
|
|
108
|
+
if (explicit === "inline") return [groupKey];
|
|
109
|
+
if (matchesAny(part.type, standalone)) return [];
|
|
110
|
+
if (matchesAny(part.type, inline)) return [groupKey];
|
|
111
|
+
return [];
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function isGroupNode(part) {
|
|
115
|
+
return part.type.startsWith("group-");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export {
|
|
119
|
+
defaultPartStatus,
|
|
120
|
+
rollupStatus,
|
|
121
|
+
buildPartGroups,
|
|
122
|
+
partsFingerprint,
|
|
123
|
+
groupPartByType,
|
|
124
|
+
isGroupNode
|
|
125
|
+
};
|
|
126
|
+
//# sourceMappingURL=chunk-YSKD7UXX.js.map
|