@datalayer/agent-runtimes 1.5.20 → 1.5.21
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/dist-embed/chunks/{AgentDetails-DZyyuD5F.js → AgentDetails-C7tCazwB.js} +1 -1
- package/dist-embed/chunks/{AgentDetailsDialog-DaQyQxlm.js → AgentDetailsDialog-Cwps4GeH.js} +1 -1
- package/dist-embed/chunks/{AgentInspector-CBNiiRtv.js → AgentInspector-Gk7jbg8t.js} +1 -1
- package/dist-embed/chunks/{AgentInspectorDialog-BxMOAc7K.js → AgentInspectorDialog-BSSDOFrT.js} +1 -1
- package/dist-embed/chunks/{CellSidebarExtension-Dwe7PfXi.js → CellSidebarExtension-p2BAkwis.js} +9 -9
- package/dist-embed/chunks/ChatView-fHb_i4kH.js +32 -0
- package/dist-embed/chunks/{ContextPie-n1y886z-.js → ContextPie-bd_YOjzP.js} +1 -1
- package/dist-embed/chunks/{DeckComponent-BSeEBNHt.js → DeckComponent-4gxuEH4A.js} +2 -2
- package/dist-embed/chunks/{DocumentView-OIdQEk_n.js → DocumentView-BZSYqTh_.js} +1 -1
- package/dist-embed/chunks/{EphemeralDocument-C-uLD1W7.js → EphemeralDocument-Cevnk5OF.js} +1 -1
- package/dist-embed/chunks/{EphemeralNotebook-C_peDfqf.js → EphemeralNotebook-JvALIbK2.js} +1 -1
- package/dist-embed/chunks/{ExcalidrawComponent-DHSxnPc9.js → ExcalidrawComponent-CbghNk-F.js} +1 -1
- package/dist-embed/chunks/{ExcalidrawModal-BpsfNG-u.js → ExcalidrawModal-BOVvWzYQ.js} +1 -1
- package/dist-embed/chunks/{JupyterLexicalExtension-BUSLnJVL.js → JupyterLexicalExtension-CRccZ2h7.js} +29 -29
- package/dist-embed/chunks/{KernelVariables-Cu7UeFhT.js → KernelVariables-ompObBEM.js} +1 -1
- package/dist-embed/chunks/{LexicalToolRegistry-CNg1T5sQ.js → LexicalToolRegistry-BlBEZPP4.js} +4 -4
- package/dist-embed/chunks/{NotebookToolSurfaces-Cm6-oE_W.js → NotebookToolSurfaces-DP8sWqVy.js} +1 -1
- package/dist-embed/chunks/{NotebookView-Be2lNZjS.js → NotebookView-DC6BDVEp.js} +1 -1
- package/dist-embed/chunks/{Output-OIgTyxpD.js → Output-C4hBhZ5k.js} +1 -1
- package/dist-embed/chunks/{SandboxDetailsDialog-BMq0tlcE.js → SandboxDetailsDialog-CX8wvCLJ.js} +1 -1
- package/dist-embed/chunks/{SchemaForm-D3mmq2C1.js → SchemaForm-BuhXDyz6.js} +1 -1
- package/dist-embed/chunks/{WidgetVariableView-DnuwkCHl.js → WidgetVariableView-C2X5Ehcg.js} +1 -1
- package/dist-embed/chunks/{YouTubePlugin-Bum16ua6.js → YouTubePlugin-CjgOnMCz.js} +1 -1
- package/dist-embed/chunks/{abnfDiagram-VCTEODGH-BMkFygW4.js → abnfDiagram-VCTEODGH-kzVu7pzT.js} +1 -1
- package/dist-embed/chunks/{abnfDiagram-VCTEODGH-Dac38D-P.js → abnfDiagram-VCTEODGH-wvUaPpVC.js} +1 -1
- package/dist-embed/chunks/{ar-SA-G6X2FPQ2-JDFjD_Dk.js → ar-SA-G6X2FPQ2-ArgZTGSp.js} +1 -1
- package/dist-embed/chunks/{architectureDiagram-5GKGNRK7-DXJTBh9S.js → architectureDiagram-5GKGNRK7-CwbfxDHw.js} +1 -1
- package/dist-embed/chunks/{architectureDiagram-5GKGNRK7-D7VBU0uf.js → architectureDiagram-5GKGNRK7-DVZUrWEx.js} +1 -1
- package/dist-embed/chunks/{az-AZ-76LH7QW2-AbN1w5Zy.js → az-AZ-76LH7QW2-DQgz6n32.js} +1 -1
- package/dist-embed/chunks/{bg-BG-XCXSNQG7-BULkJsTf.js → bg-BG-XCXSNQG7-Cx0dPt6-.js} +1 -1
- package/dist-embed/chunks/{blockDiagram-868be97b-Bk9MNjmt.js → blockDiagram-868be97b-DEQh5CUO.js} +1 -1
- package/dist-embed/chunks/{blockDiagram-I7D4REHJ-CKjKQ6Dq.js → blockDiagram-I7D4REHJ-C6gbEBfg.js} +1 -1
- package/dist-embed/chunks/{blockDiagram-I7D4REHJ-BwenaP7n.js → blockDiagram-I7D4REHJ-DUIcpkIN.js} +1 -1
- package/dist-embed/chunks/{bn-BD-2XOGV67Q-B6EtUyIk.js → bn-BD-2XOGV67Q-BkekmuYO.js} +1 -1
- package/dist-embed/chunks/{c4Diagram-3f4bdde3-BGoSdP5p.js → c4Diagram-3f4bdde3-CUcRctJE.js} +1 -1
- package/dist-embed/chunks/{c4Diagram-7LVT6UL2-DlkcVfDa.js → c4Diagram-7LVT6UL2-DSQiEaxC.js} +1 -1
- package/dist-embed/chunks/{c4Diagram-7LVT6UL2-BZRokUDB.js → c4Diagram-7LVT6UL2-f7UaZWVg.js} +1 -1
- package/dist-embed/chunks/{ca-ES-6MX7JW3Y-BZ0wzUck.js → ca-ES-6MX7JW3Y-Yr14RtMP.js} +1 -1
- package/dist-embed/chunks/{celltoolbartracker-CCRqu43G.js → celltoolbartracker-Bx9x9aeh.js} +1 -1
- package/dist-embed/chunks/{chunk-2Q5K7J3B-CfYiHpfd.js → chunk-2Q5K7J3B-BBPiCQqO.js} +1 -1
- package/dist-embed/chunks/{chunk-2Q5K7J3B-DLu9zZx0.js → chunk-2Q5K7J3B-DbzMjK_L.js} +1 -1
- package/dist-embed/chunks/{chunk-5VM5RSS4-yHAygNq4.js → chunk-5VM5RSS4-CcNPo9qP.js} +1 -1
- package/dist-embed/chunks/{chunk-5VM5RSS4-dV5IUPYK.js → chunk-5VM5RSS4-rEZEdbpi.js} +1 -1
- package/dist-embed/chunks/{chunk-F27PBJKO-BeY8iI19.js → chunk-F27PBJKO-BH7lDumP.js} +1 -1
- package/dist-embed/chunks/{chunk-F27PBJKO-BArvzx7H.js → chunk-F27PBJKO-DTgjd0wN.js} +1 -1
- package/dist-embed/chunks/{chunk-IMKFNOWR-iUeFNxCU.js → chunk-IMKFNOWR-BA-vmq_V.js} +1 -1
- package/dist-embed/chunks/{chunk-IMKFNOWR-BJRUyuXy.js → chunk-IMKFNOWR-DuzpuE1w.js} +1 -1
- package/dist-embed/chunks/{chunk-JWPE2WC7-BDUBU4vN.js → chunk-JWPE2WC7-BfRI4eJ2.js} +1 -1
- package/dist-embed/chunks/{chunk-JWPE2WC7-Djk-1JPJ.js → chunk-JWPE2WC7-CAdvd3EQ.js} +1 -1
- package/dist-embed/chunks/{chunk-POPQ4Y6H-E4731IOt.js → chunk-POPQ4Y6H-B7pT6rUf.js} +1 -1
- package/dist-embed/chunks/{chunk-POPQ4Y6H-CibXbz_c.js → chunk-POPQ4Y6H-Dw1h_9lT.js} +1 -1
- package/dist-embed/chunks/{chunk-SVP7TREG-DeRyA6Ek.js → chunk-SVP7TREG-BxpYXJab.js} +1 -1
- package/dist-embed/chunks/{chunk-SVP7TREG-o7JviCXQ.js → chunk-SVP7TREG-VsO48dck.js} +1 -1
- package/dist-embed/chunks/{chunk-TICWLB2K-BIhZcpwn.js → chunk-TICWLB2K-CU2oQRJ9.js} +1 -1
- package/dist-embed/chunks/{chunk-TICWLB2K-Zk_gUXIu.js → chunk-TICWLB2K-LCiyX33a.js} +1 -1
- package/dist-embed/chunks/{chunk-XXDRQBXY-DATpHkZD.js → chunk-XXDRQBXY-CL1cUI4w.js} +1 -1
- package/dist-embed/chunks/{chunk-XXDRQBXY-Cp6f69YK.js → chunk-XXDRQBXY-islJGiCO.js} +1 -1
- package/dist-embed/chunks/{classDiagram-ZZMXUADV-DcutslOq.js → classDiagram-ZZMXUADV-C7-Ca_nP.js} +1 -1
- package/dist-embed/chunks/{classDiagram-ZZMXUADV-BfpWJKcC.js → classDiagram-ZZMXUADV-Ctw7VU-m.js} +1 -1
- package/dist-embed/chunks/{classDiagram-f62afe4f-BVLyWZwA.js → classDiagram-f62afe4f-BaJUb6H9.js} +1 -1
- package/dist-embed/chunks/{classDiagram-v2-604399ef-CgcAzr_L.js → classDiagram-v2-604399ef-s6LKeK41.js} +1 -1
- package/dist-embed/chunks/{classDiagram-v2-VYDZK3BY-DcutslOq.js → classDiagram-v2-VYDZK3BY-C7-Ca_nP.js} +1 -1
- package/dist-embed/chunks/{classDiagram-v2-VYDZK3BY-BfpWJKcC.js → classDiagram-v2-VYDZK3BY-Ctw7VU-m.js} +1 -1
- package/dist-embed/chunks/{code-block-IT6T5CEO-D5_yhrdD.js → code-block-IT6T5CEO-BieLU8ls.js} +1 -1
- package/dist-embed/chunks/{component-DoyMsR16.js → component-p2xkjXeh.js} +3 -3
- package/dist-embed/chunks/{cose-bilkent-JH36ORCC-B-LvsoyE.js → cose-bilkent-JH36ORCC-BkezndW_.js} +1 -1
- package/dist-embed/chunks/{cose-bilkent-JH36ORCC-DhPsWJev.js → cose-bilkent-JH36ORCC-DrOmRWVI.js} +1 -1
- package/dist-embed/chunks/{createText-aed3d8b3-CnP7VdTn.js → createText-aed3d8b3-Dw8k7JC8.js} +1 -1
- package/dist-embed/chunks/{cs-CZ-2BRQDIVT-CHIiQJ-9.js → cs-CZ-2BRQDIVT-DYR-S6bD.js} +1 -1
- package/dist-embed/chunks/{cynefinDiagram-5FMLGOSQ-D4zzGd7W.js → cynefinDiagram-5FMLGOSQ-DqoI6t3s.js} +1 -1
- package/dist-embed/chunks/{cynefinDiagram-5FMLGOSQ-B4k-OykO.js → cynefinDiagram-5FMLGOSQ-qZ6StjuY.js} +1 -1
- package/dist-embed/chunks/{da-DK-5WZEPLOC-dfN2SAKQ.js → da-DK-5WZEPLOC-DhaHIgKI.js} +1 -1
- package/dist-embed/chunks/{dagre-GXQ25YYZ-DUrWhbsC.js → dagre-GXQ25YYZ-Bb0_WA3x.js} +1 -1
- package/dist-embed/chunks/{dagre-GXQ25YYZ-BlWkzzlo.js → dagre-GXQ25YYZ-pcAHu_bK.js} +1 -1
- package/dist-embed/chunks/{de-DE-XR44H4JA-BKsKfmfo.js → de-DE-XR44H4JA-CJpRH2Fy.js} +1 -1
- package/dist-embed/chunks/{diagram-S7CK7UJ4-FxHXDIYr.js → diagram-S7CK7UJ4-CwINt91M.js} +1 -1
- package/dist-embed/chunks/{diagram-S7CK7UJ4-BuRBzTwI.js → diagram-S7CK7UJ4-W17wgXHY.js} +1 -1
- package/dist-embed/chunks/{diagram-UQ7AKVKN-FxYHrvzF.js → diagram-UQ7AKVKN-CXRpfLBt.js} +1 -1
- package/dist-embed/chunks/{diagram-UQ7AKVKN-CeDT8Vz4.js → diagram-UQ7AKVKN-mH7QBO8y.js} +1 -1
- package/dist-embed/chunks/{diagram-VSXAHHWV-Cv0WAiv8.js → diagram-VSXAHHWV-Bg68Bv82.js} +1 -1
- package/dist-embed/chunks/{diagram-VSXAHHWV-C2icUdkA.js → diagram-VSXAHHWV-CFHqpDaB.js} +1 -1
- package/dist-embed/chunks/{diagram-VX7I27RA-D6VPVMhu.js → diagram-VX7I27RA-BEO0D7jE.js} +1 -1
- package/dist-embed/chunks/{diagram-VX7I27RA-AoxkG7BW.js → diagram-VX7I27RA-DQ6XlKLw.js} +1 -1
- package/dist-embed/chunks/{diagram-Z3DM3KII-DxunLDOr.js → diagram-Z3DM3KII-BLJQK61P.js} +1 -1
- package/dist-embed/chunks/{diagram-Z3DM3KII-CHxtPQ6F.js → diagram-Z3DM3KII-Cenqf76m.js} +1 -1
- package/dist-embed/chunks/{ebnfDiagram-PWID7BFC-CfsTBJc5.js → ebnfDiagram-PWID7BFC-6H6OSebp.js} +1 -1
- package/dist-embed/chunks/{ebnfDiagram-PWID7BFC-CmJlfM6d.js → ebnfDiagram-PWID7BFC-Cqmnghct.js} +1 -1
- package/dist-embed/chunks/{edges-b2856ca0-Cl5rq6T8.js → edges-b2856ca0-ChO7JKaP.js} +1 -1
- package/dist-embed/chunks/{el-GR-BZB4AONW-Cs0zPSU1.js → el-GR-BZB4AONW-DPGB1p8K.js} +1 -1
- package/dist-embed/chunks/{erDiagram-5d81789a-C0jmz-br.js → erDiagram-5d81789a-jzhAXdZi.js} +1 -1
- package/dist-embed/chunks/{erDiagram-RLTQ6QDP-Dyljy6tN.js → erDiagram-RLTQ6QDP-DEAWMrMT.js} +1 -1
- package/dist-embed/chunks/{erDiagram-RLTQ6QDP-FFD_URlX.js → erDiagram-RLTQ6QDP-hAbP0vV0.js} +1 -1
- package/dist-embed/chunks/{es-ES-U4NZUMDT-fGOqRf0o.js → es-ES-U4NZUMDT-CLztgM3g.js} +1 -1
- package/dist-embed/chunks/{eu-ES-A7QVB2H4-CLZ09rVe.js → eu-ES-A7QVB2H4--ffZf65_.js} +1 -1
- package/dist-embed/chunks/{fa-IR-HGAKTJCU-Cjimbc8n.js → fa-IR-HGAKTJCU-Cwwej6FC.js} +1 -1
- package/dist-embed/chunks/{fi-FI-Z5N7JZ37-ZXNEW916.js → fi-FI-Z5N7JZ37-Tw-dUSxy.js} +1 -1
- package/dist-embed/chunks/{flowDb-185abca5-Cden9aoH.js → flowDb-185abca5-DDUaXZ_Q.js} +1 -1
- package/dist-embed/chunks/{flowDiagram-1629c991-Bar9YxSW.js → flowDiagram-1629c991-DpvDtFPK.js} +1 -1
- package/dist-embed/chunks/{flowDiagram-HODETNUW-bg09n0_F.js → flowDiagram-HODETNUW-DENY4Bvt.js} +1 -1
- package/dist-embed/chunks/{flowDiagram-HODETNUW-02Xo2-6n.js → flowDiagram-HODETNUW-Hr-elwWq.js} +1 -1
- package/dist-embed/chunks/{flowDiagram-v2-1d953310-C6FnOAb2.js → flowDiagram-v2-1d953310-TxFSXMN7.js} +1 -1
- package/dist-embed/chunks/{flowchart-elk-definition-6df44142-DcmMV2Wi.js → flowchart-elk-definition-6df44142-BGFxwidp.js} +1 -1
- package/dist-embed/chunks/{fr-FR-RHASNOE6-DQaq_g67.js → fr-FR-RHASNOE6-CT1NyjSV.js} +1 -1
- package/dist-embed/chunks/{ganttDiagram-3b0b3873-BN61xNrz.js → ganttDiagram-3b0b3873-DJqKtGUz.js} +1 -1
- package/dist-embed/chunks/{ganttDiagram-EL5Y4UJY-BCLyiaOJ.js → ganttDiagram-EL5Y4UJY-3bErrKpg.js} +1 -1
- package/dist-embed/chunks/{ganttDiagram-EL5Y4UJY-JviVPOnF.js → ganttDiagram-EL5Y4UJY-Ddh9hVkO.js} +1 -1
- package/dist-embed/chunks/{gitGraphDiagram-WWUBYQGX-CzBMuAvA.js → gitGraphDiagram-WWUBYQGX-B3BVHs36.js} +1 -1
- package/dist-embed/chunks/{gitGraphDiagram-WWUBYQGX-CNc3l-2t.js → gitGraphDiagram-WWUBYQGX-BiEolUQH.js} +1 -1
- package/dist-embed/chunks/{gitGraphDiagram-f01e8bc2-7ecaKDp7.js → gitGraphDiagram-f01e8bc2-vOvP_sU8.js} +1 -1
- package/dist-embed/chunks/{gl-ES-HMX3MZ6V-BlrLF7Sk.js → gl-ES-HMX3MZ6V-BKTaXj_2.js} +1 -1
- package/dist-embed/chunks/{he-IL-6SHJWFNN-DLfo2nov.js → he-IL-6SHJWFNN-BJ5SwTG5.js} +1 -1
- package/dist-embed/chunks/{hi-IN-IWLTKZ5I-BcbS0I1h.js → hi-IN-IWLTKZ5I-D5ZQxogx.js} +1 -1
- package/dist-embed/chunks/{hu-HU-A5ZG7DT2-B_-3TehM.js → hu-HU-A5ZG7DT2-CoAAAzpy.js} +1 -1
- package/dist-embed/chunks/{id-ID-SAP4L64H-C920eBs5.js → id-ID-SAP4L64H-DFWbGjYj.js} +1 -1
- package/dist-embed/chunks/{index-D_-7qr4x.js → index-1MXuxaax.js} +1 -1
- package/dist-embed/chunks/{index-CGhVy6OJ.js → index-6feFd5AZ.js} +1 -1
- package/dist-embed/chunks/{index-MNZ1LVAM.js → index-8Jy3Vws8.js} +6 -6
- package/dist-embed/chunks/{index-9bae90f3-_mZDJyzh.js → index-9bae90f3-YA-Pbv-C.js} +1 -1
- package/dist-embed/chunks/{index-C2UmIEOV.js → index-B0MhQWhs.js} +1 -1
- package/dist-embed/chunks/{index-DcbXB4Ou.js → index-B0omKuYl.js} +1 -1
- package/dist-embed/chunks/{index-CLojGXLe.js → index-B8y71UkT.js} +1 -1
- package/dist-embed/chunks/{index-DmKOrT_f.js → index-B9vBhR-p.js} +1 -1
- package/dist-embed/chunks/{index-B3qU5V3s.js → index-BL4KuFQP.js} +1 -1
- package/dist-embed/chunks/{index-BMqDh5WU.js → index-BNFZYAJT.js} +1 -1
- package/dist-embed/chunks/{index-BVkaRzYN.js → index-BTeNnRc_.js} +1 -1
- package/dist-embed/chunks/{index-W-qUA31l.js → index-BVzIb3Wy.js} +1 -1
- package/dist-embed/chunks/{index-D1CRwrf9.js → index-BfMo5nXi.js} +2 -2
- package/dist-embed/chunks/{index-C3p2Hbbg.js → index-BgWf1G8H.js} +1 -1
- package/dist-embed/chunks/{index-C3zGthUI.js → index-BuyZwxeT.js} +1 -1
- package/dist-embed/chunks/{index-7V4MgoX0.js → index-BzQxauhZ.js} +1 -1
- package/dist-embed/chunks/{index-Dyv67BU9.js → index-C7os26P7.js} +2 -2
- package/dist-embed/chunks/{index-BbtA7ppb.js → index-CCA_V9Td.js} +1 -1
- package/dist-embed/chunks/{index-oJ3M8HYJ.js → index-CIDdX0nc.js} +1 -1
- package/dist-embed/chunks/{index-C8N5z7FZ.js → index-CkOZcvYl.js} +1 -1
- package/dist-embed/chunks/{index-DV2fNvY7.js → index-CxIZHPCc.js} +1 -1
- package/dist-embed/chunks/{index-BST3vALX.js → index-D62kZnWZ.js} +3 -3
- package/dist-embed/chunks/{index-CuqMWXgT.js → index-DMf0f7ny.js} +3 -3
- package/dist-embed/chunks/{index-OZDJ7kli.js → index-DPzPvDBn.js} +1 -1
- package/dist-embed/chunks/{index-B0VC_nl2.js → index-DSgHh0-i.js} +1 -1
- package/dist-embed/chunks/{index-DmYrjwOw.js → index-DTCcg1ap.js} +1 -1
- package/dist-embed/chunks/{index-D95mZTII.js → index-DTbF6Y7O.js} +1 -1
- package/dist-embed/chunks/{index-DbHMJ-IM.js → index-Db1qHC1a.js} +1 -1
- package/dist-embed/chunks/{index--rbc1jdS.js → index-DiBcWu6d.js} +1 -1
- package/dist-embed/chunks/{index-DSts8s_N.js → index-DpJpQnPn.js} +1 -1
- package/dist-embed/chunks/{index-DqwL86GY.js → index-Dw1P-H6s.js} +12 -12
- package/dist-embed/chunks/{index-k3ISgWrJ.js → index-FbZJIbu_.js} +1 -1
- package/dist-embed/chunks/{index-DMTXHmrU.js → index-JhvHCMRQ.js} +1 -1
- package/dist-embed/chunks/{index-BVdp0AG7.js → index-TDpnbl90.js} +4 -4
- package/dist-embed/chunks/{index-CW0DxnfF.js → index-fQxrRXLD.js} +1 -1
- package/dist-embed/chunks/{index.esm-Dy7cyZyH.js → index.esm-B6P80s3J.js} +1 -1
- package/dist-embed/chunks/{index.esm-jFa95d0B.js → index.esm-z-R1Ypx2.js} +1 -1
- package/dist-embed/chunks/{infoDiagram-27XIBGKW-CuQ0a02I.js → infoDiagram-27XIBGKW-8DlnjSdf.js} +1 -1
- package/dist-embed/chunks/{infoDiagram-27XIBGKW-CDc0DV-6.js → infoDiagram-27XIBGKW-CZPNcDbH.js} +1 -1
- package/dist-embed/chunks/{infoDiagram-a29d40f1-BKWmVk4B.js → infoDiagram-a29d40f1-Di_kmyTC.js} +1 -1
- package/dist-embed/chunks/{isEqual-SWNqZJZT.js → isEqual-D0eOPSLC.js} +1 -1
- package/dist-embed/chunks/{ishikawaDiagram-5VMMS53U-BY7eKNmA.js → ishikawaDiagram-5VMMS53U-DD5TaPvH.js} +1 -1
- package/dist-embed/chunks/{ishikawaDiagram-5VMMS53U-CPu6wHAG.js → ishikawaDiagram-5VMMS53U-ri4cvaWs.js} +1 -1
- package/dist-embed/chunks/{it-IT-JPQ66NNP-CsJELR-H.js → it-IT-JPQ66NNP-C7p9bCWQ.js} +1 -1
- package/dist-embed/chunks/{ja-JP-DBVTYXUO-Bh4bW0cv.js → ja-JP-DBVTYXUO-DupAM7Cv.js} +1 -1
- package/dist-embed/chunks/{journeyDiagram-3NMN7TZE-6CRYfcQL.js → journeyDiagram-3NMN7TZE-1NqbTyL4.js} +1 -1
- package/dist-embed/chunks/{journeyDiagram-3NMN7TZE-Cv_KZqY3.js → journeyDiagram-3NMN7TZE-BpYgEBLO.js} +1 -1
- package/dist-embed/chunks/{journeyDiagram-95396277-yJruA0Fm.js → journeyDiagram-95396277-xr9Xk_mL.js} +1 -1
- package/dist-embed/chunks/{kaa-6HZHGXH3-BmDtc0g0.js → kaa-6HZHGXH3-DrthOcPY.js} +1 -1
- package/dist-embed/chunks/{kab-KAB-ZGHBKWFO-Bluox3dD.js → kab-KAB-ZGHBKWFO-C4hr0kbU.js} +1 -1
- package/dist-embed/chunks/{kanban-definition-UXKFOSKX-Dps45ZlJ.js → kanban-definition-UXKFOSKX-B5nUu45Q.js} +1 -1
- package/dist-embed/chunks/{kanban-definition-UXKFOSKX-Biauy1A4.js → kanban-definition-UXKFOSKX-DlSwjr3b.js} +1 -1
- package/dist-embed/chunks/{kk-KZ-P5N5QNE5-EZjFhsK8.js → kk-KZ-P5N5QNE5-CrjDkh9r.js} +1 -1
- package/dist-embed/chunks/{km-KH-HSX4SM5Z-BpZu76AC.js → km-KH-HSX4SM5Z-JHWf7VZ6.js} +1 -1
- package/dist-embed/chunks/{ko-KR-MTYHY66A-C5JZPTHd.js → ko-KR-MTYHY66A-CJ4JxKMG.js} +1 -1
- package/dist-embed/chunks/{ku-TR-6OUDTVRD-BUaf6TOB.js → ku-TR-6OUDTVRD-YSlLPag_.js} +1 -1
- package/dist-embed/chunks/{layout-C8INuwYa.js → layout-5FOjTADt.js} +1 -1
- package/dist-embed/chunks/{layout-CEbgEIwd.js → layout-Bdtul_rg.js} +1 -1
- package/dist-embed/chunks/{lexicalHooks-DFMSPigW.js → lexicalHooks-eqXJbnX9.js} +1 -1
- package/dist-embed/chunks/{lt-LT-XHIRWOB4-CuGmKRQr.js → lt-LT-XHIRWOB4-2v6r2YYq.js} +1 -1
- package/dist-embed/chunks/{lv-LV-5QDEKY6T-EYERw_NP.js → lv-LV-5QDEKY6T-DVGd68q4.js} +1 -1
- package/dist-embed/chunks/{mermaid.core-hzdTpjmh.js → mermaid.core-BU1Nkb56.js} +5 -5
- package/dist-embed/chunks/{mermaid.core-BeAq5EQp.js → mermaid.core-DY5DKOtx.js} +3 -3
- package/dist-embed/chunks/{mindmap-definition-YA3MSWOX--O06aygF.js → mindmap-definition-YA3MSWOX-CEuIjXO2.js} +1 -1
- package/dist-embed/chunks/{mindmap-definition-YA3MSWOX-iB7eW5x9.js → mindmap-definition-YA3MSWOX-sSfUfKt8.js} +1 -1
- package/dist-embed/chunks/{mindmap-definition-e4c1d938-DCwgMhNw.js → mindmap-definition-e4c1d938-btrk6STt.js} +1 -1
- package/dist-embed/chunks/{mr-IN-CRQNXWMA-SKx4bMeU.js → mr-IN-CRQNXWMA-D1q8zjMr.js} +1 -1
- package/dist-embed/chunks/{my-MM-5M5IBNSE-BG-vgEXz.js → my-MM-5M5IBNSE-CCWuEpIN.js} +1 -1
- package/dist-embed/chunks/{nb-NO-T6EIAALU-BbW-11AI.js → nb-NO-T6EIAALU-eJ92wx2h.js} +1 -1
- package/dist-embed/chunks/{nl-NL-IS3SIHDZ-CSKGpuSJ.js → nl-NL-IS3SIHDZ-DmkMgsvp.js} +1 -1
- package/dist-embed/chunks/{nn-NO-6E72VCQL-P1tnp9TQ.js → nn-NO-6E72VCQL-CWYEaXBn.js} +1 -1
- package/dist-embed/chunks/{oc-FR-POXYY2M6-vpu8tuQT.js → oc-FR-POXYY2M6-CayriaEZ.js} +1 -1
- package/dist-embed/chunks/{pa-IN-N4M65BXN-CIpdGll2.js → pa-IN-N4M65BXN-CydiKcR8.js} +1 -1
- package/dist-embed/chunks/{pegDiagram-XKGWAZYB-ZPizxhEX.js → pegDiagram-XKGWAZYB--dcG-x2B.js} +1 -1
- package/dist-embed/chunks/{pegDiagram-XKGWAZYB-Bon6jQ3L.js → pegDiagram-XKGWAZYB-CqRRvKft.js} +1 -1
- package/dist-embed/chunks/{percentages-BXMCSKIN-hVEpOtFm.js → percentages-BXMCSKIN-fzYCDL7m.js} +5 -5
- package/dist-embed/chunks/{pieDiagram-E7YTZNPT-C0Pc9GUi.js → pieDiagram-E7YTZNPT-CkHpKSua.js} +1 -1
- package/dist-embed/chunks/{pieDiagram-E7YTZNPT-Di8dEHt9.js → pieDiagram-E7YTZNPT-D-uncTun.js} +1 -1
- package/dist-embed/chunks/{pieDiagram-c941bede-C--hwbRv.js → pieDiagram-c941bede-BoVaJIdw.js} +1 -1
- package/dist-embed/chunks/{pl-PL-T2D74RX3-Ckyj0Mzv.js → pl-PL-T2D74RX3-DhiK4YSC.js} +1 -1
- package/dist-embed/chunks/{pt-BR-5N22H2LF-3jDc9_Aa.js → pt-BR-5N22H2LF-CwSVxIqs.js} +1 -1
- package/dist-embed/chunks/{pt-PT-UZXXM6DQ-lhLbXf7Q.js → pt-PT-UZXXM6DQ-BnxquNJT.js} +1 -1
- package/dist-embed/chunks/{quadrantDiagram-AXDQQJYC-Ffo3hgR0.js → quadrantDiagram-AXDQQJYC-ClE_bWPS.js} +1 -1
- package/dist-embed/chunks/{quadrantDiagram-AXDQQJYC-D0QYtpIp.js → quadrantDiagram-AXDQQJYC-nOA8Q9nG.js} +1 -1
- package/dist-embed/chunks/{quadrantDiagram-cf8b8fe0-Bqmed-0s.js → quadrantDiagram-cf8b8fe0-V_e2KgDu.js} +1 -1
- package/dist-embed/chunks/{railroadDiagram-O6MQD6OU-BMC9Ldnh.js → railroadDiagram-O6MQD6OU-CkhmY0tS.js} +1 -1
- package/dist-embed/chunks/{railroadDiagram-O6MQD6OU-aTc7bF4I.js → railroadDiagram-O6MQD6OU-D-SNyKIn.js} +1 -1
- package/dist-embed/chunks/{renderer-CR6Lxa3d.js → renderer-BwlsmtXF.js} +1 -1
- package/dist-embed/chunks/{requirementDiagram-53bda41b-DExdw0ey.js → requirementDiagram-53bda41b-BZw7Ipej.js} +1 -1
- package/dist-embed/chunks/{requirementDiagram-BXWQKSXE-mBFLHcqA.js → requirementDiagram-BXWQKSXE-1A97ivzl.js} +1 -1
- package/dist-embed/chunks/{requirementDiagram-BXWQKSXE-DBj1iVv5.js → requirementDiagram-BXWQKSXE-BXwXUXrr.js} +1 -1
- package/dist-embed/chunks/{ro-RO-JPDTUUEW-Dy9oeW3b.js → ro-RO-JPDTUUEW-D3G2f_fQ.js} +1 -1
- package/dist-embed/chunks/{ru-RU-B4JR7IUQ-CK16-wfD.js → ru-RU-B4JR7IUQ-SnVfNwaW.js} +1 -1
- package/dist-embed/chunks/{sankeyDiagram-P5KCCOFB-DzaadHXz.js → sankeyDiagram-P5KCCOFB-0B_Kvjm2.js} +1 -1
- package/dist-embed/chunks/{sankeyDiagram-P5KCCOFB-9W9X5V7a.js → sankeyDiagram-P5KCCOFB-ktT6v9aY.js} +1 -1
- package/dist-embed/chunks/{sankeyDiagram-c3ef121a-B6u8wnkU.js → sankeyDiagram-c3ef121a-e1QLivkZ.js} +1 -1
- package/dist-embed/chunks/{sequenceDiagram-82a5b84f-Bq8bvLh8.js → sequenceDiagram-82a5b84f-N-16oABv.js} +1 -1
- package/dist-embed/chunks/{sequenceDiagram-WJ2MYXX4-BNfJw8_y.js → sequenceDiagram-WJ2MYXX4-CtbkJYCv.js} +1 -1
- package/dist-embed/chunks/{sequenceDiagram-WJ2MYXX4-B76NTf4c.js → sequenceDiagram-WJ2MYXX4-DYY-dZgX.js} +1 -1
- package/dist-embed/chunks/{sessions-XxjScqnJ.js → sessions-C9DBCyZI.js} +1 -1
- package/dist-embed/chunks/{si-LK-N5RQ5JYF-AJdaUbzl.js → si-LK-N5RQ5JYF-Da7Bfexz.js} +1 -1
- package/dist-embed/chunks/{sizeCapture-INFHLROL-KZBUxNmb.js → sizeCapture-INFHLROL-B3xt8UaI.js} +1 -1
- package/dist-embed/chunks/{sizeCapture-INFHLROL-DQ5s0TIW.js → sizeCapture-INFHLROL-DJOph387.js} +1 -1
- package/dist-embed/chunks/{sk-SK-C5VTKIMK-Bk82hIVU.js → sk-SK-C5VTKIMK-BB-Ks1b-.js} +1 -1
- package/dist-embed/chunks/{sl-SI-NN7IZMDC-DSFcvf6W.js → sl-SI-NN7IZMDC-DF3fUKHX.js} +1 -1
- package/dist-embed/chunks/{stateDiagram-43e79a5f-BiTTNI1Z.js → stateDiagram-43e79a5f-BJcJNr41.js} +1 -1
- package/dist-embed/chunks/{stateDiagram-D77RDMKH-D4hQpdZ2.js → stateDiagram-D77RDMKH-DVd0MOrg.js} +1 -1
- package/dist-embed/chunks/{stateDiagram-D77RDMKH-lndPMO3D.js → stateDiagram-D77RDMKH-LjWP-fRB.js} +1 -1
- package/dist-embed/chunks/{stateDiagram-v2-2041ed4f-BbFiQEfG.js → stateDiagram-v2-2041ed4f-DTEruWg2.js} +1 -1
- package/dist-embed/chunks/{stateDiagram-v2-MP3YSRHH-pqcRT12A.js → stateDiagram-v2-MP3YSRHH-CJD5_Eji.js} +1 -1
- package/dist-embed/chunks/{stateDiagram-v2-MP3YSRHH-C-kIBdBJ.js → stateDiagram-v2-MP3YSRHH-_xCQcvgo.js} +1 -1
- package/dist-embed/chunks/{styles-455b33cd-U9lx7mAf.js → styles-455b33cd-OIhmfs6N.js} +1 -1
- package/dist-embed/chunks/{styles-f932cba9-S-lYZYdK.js → styles-f932cba9-CwLjreIv.js} +1 -1
- package/dist-embed/chunks/{styles-fcc2142b-DfudfB3j.js → styles-fcc2142b-DP74dQpR.js} +1 -1
- package/dist-embed/chunks/{subset-shared.chunk-f2gmZjeG.js → subset-shared.chunk-Cf9zgTA9.js} +1 -1
- package/dist-embed/chunks/{subset-worker.chunk-De1CPIQ6.js → subset-worker.chunk-WYW3AHku.js} +1 -1
- package/dist-embed/chunks/{sv-SE-XGPEYMSR-BbGfLHIi.js → sv-SE-XGPEYMSR-CeR-pJHy.js} +1 -1
- package/dist-embed/chunks/{svgDrawCommon-148a3cd9-ClgHG0vb.js → svgDrawCommon-148a3cd9-CgE5QJIv.js} +1 -1
- package/dist-embed/chunks/{swimlanes-42K2YHIH-OqZ4t-07.js → swimlanes-42K2YHIH-CZyflHYJ.js} +1 -1
- package/dist-embed/chunks/{swimlanes-42K2YHIH-CjV1bdPk.js → swimlanes-42K2YHIH-Cj4fdAYa.js} +1 -1
- package/dist-embed/chunks/{swimlanesDiagram-VR7AAH4N-9twpvQtj.js → swimlanesDiagram-VR7AAH4N-B2gk37ys.js} +1 -1
- package/dist-embed/chunks/{swimlanesDiagram-VR7AAH4N-BdS4NGOx.js → swimlanesDiagram-VR7AAH4N-Bmr6N4fj.js} +1 -1
- package/dist-embed/chunks/{ta-IN-2NMHFXQM-BWMJgnI2.js → ta-IN-2NMHFXQM-lmsodGuU.js} +1 -1
- package/dist-embed/chunks/{th-TH-HPSO5L25-DiP_CZXl.js → th-TH-HPSO5L25-DQCWr96I.js} +1 -1
- package/dist-embed/chunks/{timeline-definition-24CTP7MA-Cs4Bwobu.js → timeline-definition-24CTP7MA-D5dMAy5U.js} +1 -1
- package/dist-embed/chunks/{timeline-definition-24CTP7MA-B7uSaXDu.js → timeline-definition-24CTP7MA-DqY5EM6p.js} +1 -1
- package/dist-embed/chunks/{timeline-definition-7545f45a-CHrBluu1.js → timeline-definition-7545f45a-B8wMEyZY.js} +1 -1
- package/dist-embed/chunks/{tr-TR-DEFEU3FU-CKMBvOkr.js → tr-TR-DEFEU3FU-CqnvlGZW.js} +1 -1
- package/dist-embed/chunks/{uk-UA-QMV73CPH-CQL0E0jU.js → uk-UA-QMV73CPH-DdWFjbHe.js} +1 -1
- package/dist-embed/chunks/{vennDiagram-4TSXK5OY-uwWpr4uC.js → vennDiagram-4TSXK5OY-63-O_xI8.js} +1 -1
- package/dist-embed/chunks/{vennDiagram-4TSXK5OY-CHSyRZN_.js → vennDiagram-4TSXK5OY-BMg6wc5A.js} +1 -1
- package/dist-embed/chunks/{vi-VN-M7AON7JQ-BpvEBNJo.js → vi-VN-M7AON7JQ-CydTT0Fi.js} +1 -1
- package/dist-embed/chunks/{wardleyDiagram-VM6X3IG4-0UuvD-IO.js → wardleyDiagram-VM6X3IG4-C5wMQ_qe.js} +1 -1
- package/dist-embed/chunks/{wardleyDiagram-VM6X3IG4-zIfOyYBf.js → wardleyDiagram-VM6X3IG4-C9vLUvHf.js} +1 -1
- package/dist-embed/chunks/{xychartDiagram-3f383b91-ChbRPzo8.js → xychartDiagram-3f383b91-BfoQg8n9.js} +1 -1
- package/dist-embed/chunks/{xychartDiagram-S5SC5T6Z-hCGgyjir.js → xychartDiagram-S5SC5T6Z-BZr3T3n_.js} +1 -1
- package/dist-embed/chunks/{xychartDiagram-S5SC5T6Z-q9gcUSF1.js → xychartDiagram-S5SC5T6Z-DthHDnAV.js} +1 -1
- package/dist-embed/chunks/{zh-CN-LNUGB5OW-DWmzAIjK.js → zh-CN-LNUGB5OW-DEn1TFfK.js} +1 -1
- package/dist-embed/chunks/{zh-HK-E62DVLB3-CQ-xPzHX.js → zh-HK-E62DVLB3-DJQRmOHH.js} +1 -1
- package/dist-embed/chunks/{zh-TW-RAJ6MFWO-DvlSTykD.js → zh-TW-RAJ6MFWO-B7s9vmSf.js} +1 -1
- package/dist-embed/datalayer-app-main.js +52 -52
- package/lib/apps/embed/visitorApp.d.ts +1 -1
- package/lib/apps/embed/visitorApp.js +1 -1
- package/lib/apps/plugins/chat/ChatView.js +13 -2
- package/lib/chat/ChatFloating.js +4 -1
- package/lib/chat/base/ChatBase.js +11 -3
- package/lib/chat/prompt/InputPrompt.d.ts +6 -1
- package/lib/chat/prompt/InputPrompt.js +12 -2
- package/lib/voice/ComposerVoice.d.ts +15 -2
- package/lib/voice/ComposerVoice.js +23 -17
- package/lib/voice/VoiceMenu.d.ts +27 -0
- package/lib/voice/VoiceMenu.js +32 -0
- package/lib/voice/chatVoice.js +2 -2
- package/lib/voice/choices.d.ts +33 -0
- package/lib/voice/choices.js +70 -0
- package/lib/voice/index.d.ts +4 -0
- package/lib/voice/index.js +3 -0
- package/lib/voice/settings.d.ts +17 -1
- package/lib/voice/settings.js +64 -1
- package/lib/voice/useVoiceSettings.d.ts +6 -0
- package/lib/voice/useVoiceSettings.js +25 -0
- package/package.json +1 -1
- package/dist-embed/chunks/ChatView-C2La9033.js +0 -32
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
import type { AppSpec } from '../../types/agentspecs';
|
|
36
36
|
import type { DatalayerVisitors } from '../apps/visitorToken';
|
|
37
37
|
/** Where the visitors' runtime is published, on ai-agents' host (its chart). */
|
|
38
|
-
export declare const VISITORS_PATH = "/api/
|
|
38
|
+
export declare const VISITORS_PATH = "/api/runtime-visitors";
|
|
39
39
|
/** The examples the visitors' runtime keeps warm (its chart's `AGENT_RUNTIMES_VISITORS`). */
|
|
40
40
|
export declare const VISITOR_EXAMPLES: readonly string[];
|
|
41
41
|
/** The key of an application at its address, as a visitor's token names it. */
|
|
@@ -6,7 +6,7 @@ import { getApp } from '../../specs/apps';
|
|
|
6
6
|
import { parseAppspec } from '../apps/appspec';
|
|
7
7
|
import { runnable } from './embedConfig';
|
|
8
8
|
/** Where the visitors' runtime is published, on ai-agents' host (its chart). */
|
|
9
|
-
export const VISITORS_PATH = '/api/
|
|
9
|
+
export const VISITORS_PATH = '/api/runtime-visitors';
|
|
10
10
|
/** The examples the visitors' runtime keeps warm (its chart's `AGENT_RUNTIMES_VISITORS`). */
|
|
11
11
|
export const VISITOR_EXAMPLES = [
|
|
12
12
|
'web-research',
|
|
@@ -56,6 +56,7 @@ import { latestSaying, newestIsAnswer, } from '../../../chat/assistant/state';
|
|
|
56
56
|
import { useChatWords } from '../../../chat/ChatLanguage';
|
|
57
57
|
import { ComposerVoice } from '../../../voice/ComposerVoice';
|
|
58
58
|
import { settledVoice, voiceAskedAs } from '../../../voice/chatVoice';
|
|
59
|
+
import { useVoiceSettings } from '../../../voice/useVoiceSettings';
|
|
59
60
|
/** No editor: the conversation on its own. */
|
|
60
61
|
const NO_SURFACE = '';
|
|
61
62
|
/**
|
|
@@ -1177,7 +1178,11 @@ export default function ChatView({ workspace }) {
|
|
|
1177
1178
|
* workspace's composer, which this view holds — the words written in it as
|
|
1178
1179
|
* they are heard. The chat speaks its answers itself (`voice` below).
|
|
1179
1180
|
*/
|
|
1180
|
-
|
|
1181
|
+
// The person's own settings, followed as the voice menu changes them (VO-30).
|
|
1182
|
+
const [personVoice] = useVoiceSettings();
|
|
1183
|
+
const voice = useMemo(() => (config?.voice ? settledVoice(config.voice, personVoice) : undefined), [config?.voice, personVoice]);
|
|
1184
|
+
// The words in the box are still being heard: greyed until final (VO-11).
|
|
1185
|
+
const [voiceInterim, setVoiceInterim] = useState(false);
|
|
1181
1186
|
/*
|
|
1182
1187
|
* The model this conversation is on.
|
|
1183
1188
|
*
|
|
@@ -1672,6 +1677,7 @@ export default function ChatView({ workspace }) {
|
|
|
1672
1677
|
suggestions: chatSuggestions,
|
|
1673
1678
|
disableInputPrompt: chatDisabled,
|
|
1674
1679
|
connectionConfirmed: !chatDisabled,
|
|
1680
|
+
interim: voiceInterim,
|
|
1675
1681
|
// Tighter on top: every pixel of the composer is a pixel of the editor
|
|
1676
1682
|
// under it pushed down, and the bar reads as a command line at this size.
|
|
1677
1683
|
// Both of the page layout's placements are that bar — one floating over
|
|
@@ -1693,7 +1699,12 @@ export default function ChatView({ workspace }) {
|
|
|
1693
1699
|
footerExtras: promptActions.length > 0 || (voice && voice.input !== 'off') ? (_jsxs(_Fragment, { children: [promptActions.length > 0 ? (_jsx(ReactorSlot, { slot: LoopSlots.promptAction, props: { workspace } })) : null, voice && voice.input !== 'off' ? (_jsx(ComposerVoice, { voice: voice, input: draft, setInput: setDraft, disabled: chatDisabled,
|
|
1694
1700
|
// The chat's own speaker, never a second one: the microphone
|
|
1695
1701
|
// opening stops it, and *Stop speaking* while it speaks.
|
|
1696
|
-
speaking: speaking, onStopSpeaking: () => controlsRef.current?.stopSpeaking?.(),
|
|
1702
|
+
speaking: speaking, onStopSpeaking: () => controlsRef.current?.stopSpeaking?.(), onInterimChange: setVoiceInterim,
|
|
1703
|
+
// The menu offers when answers are heard where the
|
|
1704
|
+
// application lets them be (VO-21, VO-30).
|
|
1705
|
+
answers: Boolean(config?.voice?.output &&
|
|
1706
|
+
config.voice.output !== 'off' &&
|
|
1707
|
+
config.voice.speechUrl), onSpoken: metadata => {
|
|
1697
1708
|
spokenRef.current = metadata;
|
|
1698
1709
|
}, send: (text, metadata) => {
|
|
1699
1710
|
spokenRef.current = metadata;
|
package/lib/chat/ChatFloating.js
CHANGED
|
@@ -36,6 +36,7 @@ import { DecisionAsk } from './assistant/DecisionAsk';
|
|
|
36
36
|
import { useSpokenAnswers } from '../voice/useSpokenAnswers';
|
|
37
37
|
import { useVoiceSpeaker } from '../voice/useVoiceSpeaker';
|
|
38
38
|
import { settledVoice } from '../voice/chatVoice';
|
|
39
|
+
import { useVoiceSettings } from '../voice/useVoiceSettings';
|
|
39
40
|
import { BalloonApprovalMessage, CONVERSATION_BALLOON_WIDTH, ConversationBalloonClose, balloonTailAt, conversationBalloonHeight, conversationBalloonSx, CURRENT_BALLOON_HEIGHT, peekLine, } from './assistant/ConversationBalloon';
|
|
40
41
|
import { ConversationBalloonHeader, CurrentBalloonBody, } from './assistant/BalloonParts';
|
|
41
42
|
import { DEFAULT_BALLOON_DISPLAY, conversationCount, newestToolLine, toolLineText, } from './assistant/toolLine';
|
|
@@ -163,7 +164,9 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
|
|
|
163
164
|
* they are written (VO-20), the state following the sound (VO-22).
|
|
164
165
|
*/
|
|
165
166
|
const [voiceItems, setVoiceItems] = useState([]);
|
|
166
|
-
|
|
167
|
+
// The person's own settings, followed as the voice menu changes them (VO-30).
|
|
168
|
+
const [personVoice] = useVoiceSettings();
|
|
169
|
+
const settledVoiceOf = useMemo(() => (voice ? settledVoice(voice, personVoice) : undefined), [voice, personVoice]);
|
|
167
170
|
const { speaker, state: speakerState, stop: stopSpeaking, read: readAnswerAloud, level: mouthLevel, } = useVoiceSpeaker(settledVoiceOf);
|
|
168
171
|
// `always`: each answer heard as it is written; `on_request`: a *Read
|
|
169
172
|
// aloud* under each (VO-21).
|
|
@@ -51,6 +51,7 @@ import { InputPrompt } from '../prompt/InputPrompt';
|
|
|
51
51
|
import { ComposerVoice, spokenOf } from '../../voice/ComposerVoice';
|
|
52
52
|
import { ReadAloud, readsAloud } from '../../voice/ReadAloud';
|
|
53
53
|
import { settledVoice } from '../../voice/chatVoice';
|
|
54
|
+
import { useVoiceSettings } from '../../voice/useVoiceSettings';
|
|
54
55
|
import { useVoiceSpeaker } from '../../voice/useVoiceSpeaker';
|
|
55
56
|
import { useSpokenAnswers } from '../../voice/useSpokenAnswers';
|
|
56
57
|
import { isFloatingChatViewMode } from '../viewModes';
|
|
@@ -3014,7 +3015,11 @@ showToolApprovalBanner = true, pendingApprovals: pendingApprovalsProp, onApprove
|
|
|
3014
3015
|
// Voice (VOICE.md V1): what was said and put in the composer, until sent.
|
|
3015
3016
|
const spokenRef = useRef(undefined);
|
|
3016
3017
|
// Its voice with what it leaves unsaid filled in: Datalayer's models and packages.
|
|
3017
|
-
|
|
3018
|
+
// The person's own settings, followed as the voice menu changes them (VO-30).
|
|
3019
|
+
const [personVoice] = useVoiceSettings();
|
|
3020
|
+
const settled = useMemo(() => (voice ? settledVoice(voice, personVoice) : undefined), [voice, personVoice]);
|
|
3021
|
+
// The words in the box are still being heard: greyed until final (VO-11).
|
|
3022
|
+
const [voiceInterim, setVoiceInterim] = useState(false);
|
|
3018
3023
|
/*
|
|
3019
3024
|
* Its answers heard (VO-20, VO-21), by Datalayer's speech service: the
|
|
3020
3025
|
* host's speaker when it gives one (`ChatFloating`, whose assistant's mouth
|
|
@@ -3802,12 +3807,15 @@ showToolApprovalBanner = true, pendingApprovals: pendingApprovalsProp, onApprove
|
|
|
3802
3807
|
// so every chat with a headless notebook gets the same transcript.
|
|
3803
3808
|
notebookToolSurfacesId: notebookToolSurfacesId, approvalConfig: approvalConfig, messagesEndRef: messagesEndRef, onRespond: handleRespond, showTurnFooters: showTurnFooter, renderMessageFooter: readAloudFooter, agentUsage: agentUsage, onRemoveItems: handleRemoveItems, mcpServers: filteredMcpServers, emptyContent: launching ? null : (_jsx(ChatEmptyState, { emptyState: emptyState, brandIcon: brandIcon, description: resolvedDescription, suggestions: resolvedSuggestions, submitOnSuggestionClick: submitOnSuggestionClick, onSuggestionSubmit: handleSuggestionSubmit, onSuggestionFill: handleSuggestionFill })) }), trailingContent] }));
|
|
3804
3809
|
// The microphone, in the composer's footer (VO-10, VO-11).
|
|
3805
|
-
const voiceControl = settled && settled.input !== 'off' ? (_jsx(ComposerVoice, { voice: settled, input: input, setInput: setInput, disabled: disabled || launching, speaking: speakingNow, onStopSpeaking: stopSpeaking,
|
|
3810
|
+
const voiceControl = settled && settled.input !== 'off' ? (_jsx(ComposerVoice, { voice: settled, input: input, setInput: setInput, disabled: disabled || launching, speaking: speakingNow, onStopSpeaking: stopSpeaking, onInterimChange: setVoiceInterim,
|
|
3811
|
+
// The menu offers when answers are heard where the application
|
|
3812
|
+
// lets them be (VO-21, VO-30).
|
|
3813
|
+
answers: Boolean(voice?.output && voice.output !== 'off' && voice.speechUrl), onSpoken: metadata => {
|
|
3806
3814
|
spokenRef.current = metadata;
|
|
3807
3815
|
}, send: (text, metadata) => void handleSend(text, undefined, metadata) })) : undefined;
|
|
3808
3816
|
// Why an answer could not be heard, in a sentence, by the composer.
|
|
3809
3817
|
const voiceRefused = !hostSpeaks && ownVoice.state.refused ? (_jsx(Text, { role: "alert", sx: { fontSize: 0, color: 'danger.fg', maxWidth: 260 }, "data-voice-refused": "", children: ownVoice.state.refused })) : null;
|
|
3810
|
-
const inputToolbar = showInput ? (_jsx(InputPrompt, { footerExtras: voiceRefused ? (_jsxs(_Fragment, { children: [voiceRefused, voiceControl] })) : (voiceControl), input: input, setInput: setInput, isLoading: isLoading, kernelStatus: liveKernelStatus, connectionConfirmed: connectionConfirmed, placeholder: placeholder,
|
|
3818
|
+
const inputToolbar = showInput ? (_jsx(InputPrompt, { footerExtras: voiceRefused ? (_jsxs(_Fragment, { children: [voiceRefused, voiceControl] })) : (voiceControl), interim: voiceInterim, input: input, setInput: setInput, isLoading: isLoading, kernelStatus: liveKernelStatus, connectionConfirmed: connectionConfirmed, placeholder: placeholder,
|
|
3811
3819
|
/*
|
|
3812
3820
|
The same openers the empty state offers, typed into the box they would
|
|
3813
3821
|
be typed into.
|
|
@@ -50,6 +50,11 @@ export interface InputPromptProps {
|
|
|
50
50
|
* additions rather than reshuffling the controls people know.
|
|
51
51
|
*/
|
|
52
52
|
footerExtras?: ReactNode;
|
|
53
|
+
/**
|
|
54
|
+
* The words in the box are still being heard by the microphone (VOICE.md
|
|
55
|
+
* VO-11): shown greyed, in italics, until they are final.
|
|
56
|
+
*/
|
|
57
|
+
interim?: boolean;
|
|
53
58
|
/**
|
|
54
59
|
* Panels inside the prompt's card, above and below the composer itself.
|
|
55
60
|
*
|
|
@@ -226,4 +231,4 @@ export interface InputPromptProps {
|
|
|
226
231
|
/** Pre-fetched MCP status from WebSocket — bypasses REST polling */
|
|
227
232
|
mcpStatusData?: McpToolsetsStatusResponse | null;
|
|
228
233
|
}
|
|
229
|
-
export declare function InputPrompt({ input, setInput, isLoading, kernelStatus, connectionConfirmed, placeholder, typingSuggestions, autoFocus, focusTrigger, padding, placement, floatingAnchor, draggable, container, footerExtras, leadingPanel, trailingPanel, onSend, onStop, disableInputPrompt, promptVariant, mentionableAgents, promptCommands, promptHistory, headerContent, showAgentsMenu, showInlineAgentsMenu, agents, selectedAgentId, onSelectAgent, showTokenUsage, showContextRing, agentUsage, showModelSelector, showToolsMenu, showSkillsMenu, showSuggestionsMenu, suggestions, codemodeEnabled, onToggleCodemode, isA2AProtocol, hasConfigData, hasSkillsData, configLoading, models, decisions, selectedModel, onModelSelect, availableTools, availableFrontendTools, mcpServers, enabledMcpTools, enabledMcpToolCount, onToggleMcpTool, onToggleAllMcpServerTools, approvedMcpTools, onToggleMcpToolApproval, skills, skillsLoading, enabledSkills, onToggleSkill, onToggleAllSkills, approvedSkills, onToggleSkillApproval, apiBase, authToken, mcpStatusData, }: InputPromptProps): import("react").JSX.Element;
|
|
234
|
+
export declare function InputPrompt({ input, setInput, isLoading, kernelStatus, connectionConfirmed, placeholder, typingSuggestions, autoFocus, focusTrigger, padding, placement, floatingAnchor, draggable, container, footerExtras, interim, leadingPanel, trailingPanel, onSend, onStop, disableInputPrompt, promptVariant, mentionableAgents, promptCommands, promptHistory, headerContent, showAgentsMenu, showInlineAgentsMenu, agents, selectedAgentId, onSelectAgent, showTokenUsage, showContextRing, agentUsage, showModelSelector, showToolsMenu, showSkillsMenu, showSuggestionsMenu, suggestions, codemodeEnabled, onToggleCodemode, isA2AProtocol, hasConfigData, hasSkillsData, configLoading, models, decisions, selectedModel, onModelSelect, availableTools, availableFrontendTools, mcpServers, enabledMcpTools, enabledMcpToolCount, onToggleMcpTool, onToggleAllMcpServerTools, approvedMcpTools, onToggleMcpToolApproval, skills, skillsLoading, enabledSkills, onToggleSkill, onToggleAllSkills, approvedSkills, onToggleSkillApproval, apiBase, authToken, mcpStatusData, }: InputPromptProps): import("react").JSX.Element;
|
|
@@ -30,7 +30,7 @@ const EMPTY_ID_SET = new Set();
|
|
|
30
30
|
// ---------------------------------------------------------------------------
|
|
31
31
|
// Component
|
|
32
32
|
// ---------------------------------------------------------------------------
|
|
33
|
-
export function InputPrompt({ input, setInput, isLoading, kernelStatus, connectionConfirmed, placeholder, typingSuggestions, autoFocus, focusTrigger, padding, placement, floatingAnchor = 'bottom', draggable = false, container, footerExtras, leadingPanel, trailingPanel, onSend, onStop, disableInputPrompt = false, promptVariant, mentionableAgents, promptCommands, promptHistory, headerContent, showAgentsMenu = false, showInlineAgentsMenu = true, agents = [], selectedAgentId, onSelectAgent, showTokenUsage, showContextRing = false, agentUsage, showModelSelector, showToolsMenu, showSkillsMenu, showSuggestionsMenu = true, suggestions, codemodeEnabled, onToggleCodemode, isA2AProtocol, hasConfigData, hasSkillsData, configLoading = false, models = [], decisions, selectedModel = '', onModelSelect = () => { }, availableTools = [], availableFrontendTools = [], mcpServers = [], enabledMcpTools = EMPTY_TOOL_MAP, enabledMcpToolCount = 0, onToggleMcpTool = () => { }, onToggleAllMcpServerTools = () => { }, approvedMcpTools = EMPTY_TOOL_MAP, onToggleMcpToolApproval = () => { }, skills = [], skillsLoading = false, enabledSkills = EMPTY_ID_SET, onToggleSkill = () => { }, onToggleAllSkills = () => { }, approvedSkills = EMPTY_ID_SET, onToggleSkillApproval = () => { }, apiBase, authToken, mcpStatusData, }) {
|
|
33
|
+
export function InputPrompt({ input, setInput, isLoading, kernelStatus, connectionConfirmed, placeholder, typingSuggestions, autoFocus, focusTrigger, padding, placement, floatingAnchor = 'bottom', draggable = false, container, footerExtras, interim = false, leadingPanel, trailingPanel, onSend, onStop, disableInputPrompt = false, promptVariant, mentionableAgents, promptCommands, promptHistory, headerContent, showAgentsMenu = false, showInlineAgentsMenu = true, agents = [], selectedAgentId, onSelectAgent, showTokenUsage, showContextRing = false, agentUsage, showModelSelector, showToolsMenu, showSkillsMenu, showSuggestionsMenu = true, suggestions, codemodeEnabled, onToggleCodemode, isA2AProtocol, hasConfigData, hasSkillsData, configLoading = false, models = [], decisions, selectedModel = '', onModelSelect = () => { }, availableTools = [], availableFrontendTools = [], mcpServers = [], enabledMcpTools = EMPTY_TOOL_MAP, enabledMcpToolCount = 0, onToggleMcpTool = () => { }, onToggleAllMcpServerTools = () => { }, approvedMcpTools = EMPTY_TOOL_MAP, onToggleMcpToolApproval = () => { }, skills = [], skillsLoading = false, enabledSkills = EMPTY_ID_SET, onToggleSkill = () => { }, onToggleAllSkills = () => { }, approvedSkills = EMPTY_ID_SET, onToggleSkillApproval = () => { }, apiBase, authToken, mcpStatusData, }) {
|
|
34
34
|
const chatText = useChatWords();
|
|
35
35
|
const isKernelBusy = kernelStatus === 'busy';
|
|
36
36
|
/*
|
|
@@ -107,7 +107,17 @@ export function InputPrompt({ input, setInput, isLoading, kernelStatus, connecti
|
|
|
107
107
|
* from the start; this shows it.
|
|
108
108
|
*/
|
|
109
109
|
const hasContext = Boolean(agentUsage && !agentUsage.error);
|
|
110
|
-
const body = (_jsxs(Box
|
|
110
|
+
const body = (_jsxs(Box
|
|
111
|
+
// Words still being heard, greyed until final (VO-11); the same Box
|
|
112
|
+
// either way, so the editor is never mounted again.
|
|
113
|
+
, { "data-voice-interim": interim ? '' : undefined, sx: interim
|
|
114
|
+
? {
|
|
115
|
+
'& [contenteditable="true"], & textarea': {
|
|
116
|
+
color: 'fg.muted',
|
|
117
|
+
fontStyle: 'italic',
|
|
118
|
+
},
|
|
119
|
+
}
|
|
120
|
+
: undefined, children: [leadingPanel, _jsx(InputPromptBase, { variant: promptVariant, mentionableAgents: mentionableAgents, promptCommands: promptCommands, promptHistory: promptHistory,
|
|
111
121
|
/*
|
|
112
122
|
Whatever the host puts inside the prompt, and the agent chip beside
|
|
113
123
|
it. Both, rather than either: a host contributing its own controls
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
* whose composer is a plugin of its own). What the box held when the
|
|
5
5
|
* microphone opened stays; the words heard go after it as they come, and the
|
|
6
6
|
* whole of what was heard replaces them once it stops. Put there for the
|
|
7
|
-
* person to edit and send — or sent at once with *Send what I say*.
|
|
7
|
+
* person to edit and send — or sent at once with *Send what I say*. While
|
|
8
|
+
* the words are still being heard the host is told (`onInterimChange`), to
|
|
9
|
+
* grey them until they are final (VO-11). Beside the microphone, the
|
|
10
|
+
* person's voice menu (`VoiceMenu`, VO-30).
|
|
8
11
|
*
|
|
9
12
|
* @module voice/ComposerVoice
|
|
10
13
|
*/
|
|
@@ -26,8 +29,18 @@ export interface ComposerVoiceProps {
|
|
|
26
29
|
speaking?: boolean;
|
|
27
30
|
/** Stops the agent's voice, also when the microphone opens (VO-13). */
|
|
28
31
|
onStopSpeaking?: () => void;
|
|
32
|
+
/**
|
|
33
|
+
* The words in the box are still being heard (`true`), or final
|
|
34
|
+
* (`false`): the host greys them until they are (VO-11).
|
|
35
|
+
*/
|
|
36
|
+
onInterimChange?: (interim: boolean) => void;
|
|
37
|
+
/**
|
|
38
|
+
* The application lets its answers be heard: the voice menu offers when,
|
|
39
|
+
* the voice, its speed and loudness (VO-21, VO-25, VO-30).
|
|
40
|
+
*/
|
|
41
|
+
answers?: boolean;
|
|
29
42
|
}
|
|
30
43
|
/** Whether something rides on a run as a spoken message's metadata (VO-27). */
|
|
31
44
|
export declare function spokenOf(value: unknown): SpokenMetadata | undefined;
|
|
32
|
-
export declare function ComposerVoice({ voice, input, setInput, onSpoken, send, disabled, speaking, onStopSpeaking, }: ComposerVoiceProps): JSX.Element | null;
|
|
45
|
+
export declare function ComposerVoice({ voice, input, setInput, onSpoken, send, disabled, speaking, onStopSpeaking, onInterimChange, answers, }: ComposerVoiceProps): JSX.Element | null;
|
|
33
46
|
export default ComposerVoice;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo, useRef } from 'react';
|
|
3
3
|
import { DeviceHearing } from './hearing';
|
|
4
4
|
import { VoiceInput } from './VoiceInput';
|
|
5
|
+
import { VoiceMenu } from './VoiceMenu';
|
|
5
6
|
/** Whether something rides on a run as a spoken message's metadata (VO-27). */
|
|
6
7
|
export function spokenOf(value) {
|
|
7
8
|
const said = value;
|
|
@@ -12,7 +13,7 @@ export function spokenOf(value) {
|
|
|
12
13
|
? said
|
|
13
14
|
: undefined;
|
|
14
15
|
}
|
|
15
|
-
export function ComposerVoice({ voice, input, setInput, onSpoken, send, disabled = false, speaking = false, onStopSpeaking, }) {
|
|
16
|
+
export function ComposerVoice({ voice, input, setInput, onSpoken, send, disabled = false, speaking = false, onStopSpeaking, onInterimChange, answers = false, }) {
|
|
16
17
|
const hearing = useMemo(() => voice.input !== 'off'
|
|
17
18
|
? new DeviceHearing(voice.modelsUrl, voice.engines)
|
|
18
19
|
: undefined, [voice.input, voice.modelsUrl, voice.engines]);
|
|
@@ -22,20 +23,25 @@ export function ComposerVoice({ voice, input, setInput, onSpoken, send, disabled
|
|
|
22
23
|
if (!hearing) {
|
|
23
24
|
return null;
|
|
24
25
|
}
|
|
25
|
-
return (_jsx(VoiceInput, { hearing: hearing, language: voice.language, consentKey: voice.consentKey ?? 'chat', silenceMs: voice.silenceMs, microphoneId: voice.microphoneId, disabled: disabled, speaking: speaking, onStopSpeaking: onStopSpeaking, onListen: () => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
26
|
+
return (_jsxs("span", { "data-composer-voice": "", style: { display: 'inline-flex', alignItems: 'center', gap: 2 }, children: [_jsx(VoiceMenu, { voice: voice, answers: answers, disabled: disabled }), _jsx(VoiceInput, { hearing: hearing, language: voice.language, consentKey: voice.consentKey ?? 'chat', silenceMs: voice.silenceMs, microphoneId: voice.microphoneId, disabled: disabled, speaking: speaking, onStopSpeaking: onStopSpeaking, onListen: () => {
|
|
27
|
+
base.current = input.trim();
|
|
28
|
+
onStopSpeaking?.();
|
|
29
|
+
},
|
|
30
|
+
// The words as they are heard, in the box (VO-11), greyed until
|
|
31
|
+
// final; '' gives it back.
|
|
32
|
+
onInterim: (words) => {
|
|
33
|
+
setInput(afterBase(words));
|
|
34
|
+
onInterimChange?.(words !== '');
|
|
35
|
+
}, onTranscript: (transcript) => {
|
|
36
|
+
onInterimChange?.(false);
|
|
37
|
+
if (voice.sendWhatISay) {
|
|
38
|
+
setInput(base.current);
|
|
39
|
+
send(transcript.text, transcript.metadata);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// In the box, for the person to edit and send: never sent here.
|
|
43
|
+
onSpoken(transcript.metadata);
|
|
44
|
+
setInput(afterBase(transcript.text));
|
|
45
|
+
} })] }));
|
|
40
46
|
}
|
|
41
47
|
export default ComposerVoice;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The composer's voice menu (VOICE.md VO-14, VO-21, VO-25, VO-30): beside
|
|
3
|
+
* the microphone, what a person chooses for themselves — the language they
|
|
4
|
+
* speak and hear, when answers are heard, the voice, its speed and loudness,
|
|
5
|
+
* *Send what I say*, the microphone, and *Keep speech on this device*. Each
|
|
6
|
+
* choice is kept in the person's settings and heard at once by every chat
|
|
7
|
+
* on the page; *Use the application's* forgets them all.
|
|
8
|
+
*
|
|
9
|
+
* When answers are heard is offered only where the application lets them be
|
|
10
|
+
* heard: a menu may not turn on what the application turned off.
|
|
11
|
+
*
|
|
12
|
+
* @module voice/VoiceMenu
|
|
13
|
+
*/
|
|
14
|
+
import type { JSX } from 'react';
|
|
15
|
+
import type { SettledVoice } from './chatVoice';
|
|
16
|
+
export interface VoiceMenuProps {
|
|
17
|
+
/** The chat's voice as it is heard now (`settledVoice`). */
|
|
18
|
+
voice: SettledVoice;
|
|
19
|
+
/**
|
|
20
|
+
* The application lets its answers be heard (its own `output` is not
|
|
21
|
+
* `off`, and it names the speech service): the menu offers when.
|
|
22
|
+
*/
|
|
23
|
+
answers: boolean;
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export declare function VoiceMenu({ voice, answers, disabled, }: VoiceMenuProps): JSX.Element;
|
|
27
|
+
export default VoiceMenu;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { ActionList, ActionMenu, IconButton } from '@primer/react';
|
|
4
|
+
import { GearIcon } from '@primer/octicons-react';
|
|
5
|
+
import { OUTPUT_CHOICES, RATE_CHOICES, VOLUME_CHOICES, catalogueVoiceSpeaks, voiceLanguages, voicesSpeaking, } from './choices';
|
|
6
|
+
import { withVoiceSetting } from './settings';
|
|
7
|
+
import { useVoiceSettings } from './useVoiceSettings';
|
|
8
|
+
/** The microphones the browser lists; named only once one was allowed. */
|
|
9
|
+
async function microphones() {
|
|
10
|
+
try {
|
|
11
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
12
|
+
return devices.filter(device => device.kind === 'audioinput');
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function VoiceMenu({ voice, answers, disabled = false, }) {
|
|
19
|
+
const [settings, keep] = useVoiceSettings();
|
|
20
|
+
const [devices, setDevices] = useState([]);
|
|
21
|
+
const choose = (key, value) => keep(withVoiceSetting(settings, key, value, catalogueVoiceSpeaks));
|
|
22
|
+
const onDevice = Boolean(settings.onDeviceOnly);
|
|
23
|
+
const voices = voicesSpeaking(voice.language);
|
|
24
|
+
const named = devices.filter(device => device.label);
|
|
25
|
+
return (_jsxs(ActionMenu, { onOpenChange: open => {
|
|
26
|
+
if (open) {
|
|
27
|
+
void microphones().then(setDevices);
|
|
28
|
+
}
|
|
29
|
+
}, children: [_jsx(ActionMenu.Anchor, { children: _jsx(IconButton, { icon: GearIcon, size: "small", variant: "invisible", "aria-label": "Voice settings", "data-voice-menu": "", disabled: disabled }) }), _jsx(ActionMenu.Overlay, { width: "medium", children: _jsxs(ActionList, { children: [_jsxs(ActionList.Group, { selectionVariant: "single", children: [_jsx(ActionList.GroupHeading, { children: "Language" }), voiceLanguages().map(language => (_jsx(ActionList.Item, { selected: language.value === voice.language, onSelect: () => choose('language', language.value), "data-voice-language": language.value, children: language.label }, language.value)))] }), answers && !onDevice ? (_jsxs(_Fragment, { children: [_jsx(ActionList.Divider, {}), _jsxs(ActionList.Group, { selectionVariant: "single", children: [_jsx(ActionList.GroupHeading, { children: "Answers heard" }), OUTPUT_CHOICES.map(output => (_jsx(ActionList.Item, { selected: output.value === voice.output, onSelect: () => choose('output', output.value), "data-voice-output": output.value, children: output.label }, output.value)))] }), voices.length > 0 ? (_jsxs(ActionList.Group, { selectionVariant: "single", children: [_jsx(ActionList.GroupHeading, { children: "Voice" }), voices.map(spoken => (_jsx(ActionList.Item, { selected: spoken.id === voice.voice, onSelect: () => choose('voice', spoken.id), "data-voice-voice": spoken.id, children: spoken.name }, spoken.id)))] })) : null, _jsxs(ActionList.Group, { selectionVariant: "single", children: [_jsx(ActionList.GroupHeading, { children: "Speed" }), RATE_CHOICES.map(rate => (_jsx(ActionList.Item, { selected: rate.value === (voice.rate ?? 1), onSelect: () => choose('rate', rate.value), "data-voice-rate": rate.value, children: rate.label }, rate.value)))] }), _jsxs(ActionList.Group, { selectionVariant: "single", children: [_jsx(ActionList.GroupHeading, { children: "Loudness" }), VOLUME_CHOICES.map(volume => (_jsx(ActionList.Item, { selected: volume.value === (voice.volume ?? 1), onSelect: () => choose('volume', volume.value), "data-voice-volume": volume.value, children: volume.label }, volume.value)))] })] })) : null, named.length > 1 ? (_jsxs(_Fragment, { children: [_jsx(ActionList.Divider, {}), _jsxs(ActionList.Group, { selectionVariant: "single", children: [_jsx(ActionList.GroupHeading, { children: "Microphone" }), named.map(device => (_jsx(ActionList.Item, { selected: device.deviceId ===
|
|
30
|
+
(voice.microphoneId ?? named[0].deviceId), onSelect: () => choose('microphoneId', device.deviceId), "data-voice-microphone": device.deviceId, children: device.label }, device.deviceId)))] })] })) : null, _jsx(ActionList.Divider, {}), _jsxs(ActionList.Group, { selectionVariant: "multiple", children: [_jsxs(ActionList.Item, { selected: Boolean(voice.sendWhatISay), onSelect: () => choose('sendWhatISay', !voice.sendWhatISay), "data-voice-send-what-i-say": "", children: ["Send what I say", _jsx(ActionList.Description, { variant: "block", children: "Sent as soon as it is heard, not left in the box." })] }), _jsxs(ActionList.Item, { selected: onDevice, onSelect: () => choose('onDeviceOnly', !onDevice), "data-voice-on-device": "", children: ["Keep speech on this device", _jsx(ActionList.Description, { variant: "block", children: "Nothing is sent to Datalayer\u2019s speech service: you are heard in the browser, answers are not spoken." })] })] }), Object.keys(settings).length > 0 ? (_jsxs(_Fragment, { children: [_jsx(ActionList.Divider, {}), _jsx(ActionList.Item, { onSelect: () => keep({}), "data-voice-settings-reset": "", children: "Use the application\u2019s" })] })) : null] }) })] }));
|
|
31
|
+
}
|
|
32
|
+
export default VoiceMenu;
|
package/lib/voice/chatVoice.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* @module voice/chatVoice
|
|
12
12
|
*/
|
|
13
13
|
import { voiceFor } from '../specs/voices';
|
|
14
|
-
import {
|
|
14
|
+
import { heldVoiceSettings, voiceForPerson, } from './settings';
|
|
15
15
|
/**
|
|
16
16
|
* Datalayer's origin for the browser's speech models, as pinned
|
|
17
17
|
* (`s3://datalayer-models-speech` behind its CDN; VO-48, VO-49): each model
|
|
@@ -88,7 +88,7 @@ export const SILENCE_MS = 1500;
|
|
|
88
88
|
* Datalayer's models and packages, a silence of 1.5 s. Answers heard need
|
|
89
89
|
* the speech service's address: refused without.
|
|
90
90
|
*/
|
|
91
|
-
export function settledVoice(given, person =
|
|
91
|
+
export function settledVoice(given, person = heldVoiceSettings()) {
|
|
92
92
|
const voice = voiceForPerson(given, person);
|
|
93
93
|
const output = voice.output ?? 'off';
|
|
94
94
|
if (output !== 'off' && !voice.speechUrl) {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a person may choose for their voice (VOICE.md VO-14, VO-21, VO-25,
|
|
3
|
+
* VO-30), from the catalogue: the languages a voice speaks and the device
|
|
4
|
+
* hears, the voices of each, the speeds and loudnesses offered, and when
|
|
5
|
+
* answers are heard. Read by the composer's menu (`VoiceMenu`) and by a
|
|
6
|
+
* settings page, so both offer the same.
|
|
7
|
+
*
|
|
8
|
+
* @module voice/choices
|
|
9
|
+
*/
|
|
10
|
+
import { type VoiceSpec } from '../specs/voices';
|
|
11
|
+
import type { ChatVoice } from './index';
|
|
12
|
+
/** A choice as a menu or a page lists it. */
|
|
13
|
+
export interface VoiceChoice<T> {
|
|
14
|
+
value: T;
|
|
15
|
+
label: string;
|
|
16
|
+
}
|
|
17
|
+
/** A language's name, in English, as the menu says it: `en-GB` is *British English*. */
|
|
18
|
+
export declare function languageName(language: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* The languages a person may speak and hear: each a voice of the catalogue
|
|
21
|
+
* speaks and a model on the device hears, in the catalogue's order.
|
|
22
|
+
*/
|
|
23
|
+
export declare function voiceLanguages(): VoiceChoice<string>[];
|
|
24
|
+
/** The voices that speak a language, in the catalogue's order. */
|
|
25
|
+
export declare function voicesSpeaking(language: string): VoiceSpec[];
|
|
26
|
+
/** Whether a voice of the catalogue speaks a language: what a new language keeps of a chosen voice. */
|
|
27
|
+
export declare function catalogueVoiceSpeaks(voice: string, language: string): boolean;
|
|
28
|
+
/** The speeds offered, as multipliers of the voice's own. */
|
|
29
|
+
export declare const RATE_CHOICES: VoiceChoice<number>[];
|
|
30
|
+
/** The loudnesses offered, 0 to 1. */
|
|
31
|
+
export declare const VOLUME_CHOICES: VoiceChoice<number>[];
|
|
32
|
+
/** When answers are heard (VO-21): what a person may choose where the application speaks. */
|
|
33
|
+
export declare const OUTPUT_CHOICES: VoiceChoice<NonNullable<ChatVoice['output']>>[];
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* What a person may choose for their voice (VOICE.md VO-14, VO-21, VO-25,
|
|
7
|
+
* VO-30), from the catalogue: the languages a voice speaks and the device
|
|
8
|
+
* hears, the voices of each, the speeds and loudnesses offered, and when
|
|
9
|
+
* answers are heard. Read by the composer's menu (`VoiceMenu`) and by a
|
|
10
|
+
* settings page, so both offer the same.
|
|
11
|
+
*
|
|
12
|
+
* @module voice/choices
|
|
13
|
+
*/
|
|
14
|
+
import { VOICE_CATALOGUE, transcriberFor, voiceSpeaks, } from '../specs/voices';
|
|
15
|
+
/** A language's name, in English, as the menu says it: `en-GB` is *British English*. */
|
|
16
|
+
export function languageName(language) {
|
|
17
|
+
try {
|
|
18
|
+
const names = new Intl.DisplayNames(['en'], { type: 'language' });
|
|
19
|
+
return names.of(language) ?? language;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return language;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The languages a person may speak and hear: each a voice of the catalogue
|
|
27
|
+
* speaks and a model on the device hears, in the catalogue's order.
|
|
28
|
+
*/
|
|
29
|
+
export function voiceLanguages() {
|
|
30
|
+
const seen = new Set();
|
|
31
|
+
const languages = [];
|
|
32
|
+
for (const voice of Object.values(VOICE_CATALOGUE)) {
|
|
33
|
+
for (const language of voice.languages) {
|
|
34
|
+
if (!seen.has(language) && transcriberFor(language)) {
|
|
35
|
+
seen.add(language);
|
|
36
|
+
languages.push({ value: language, label: languageName(language) });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return languages;
|
|
41
|
+
}
|
|
42
|
+
/** The voices that speak a language, in the catalogue's order. */
|
|
43
|
+
export function voicesSpeaking(language) {
|
|
44
|
+
return Object.values(VOICE_CATALOGUE).filter(voice => voiceSpeaks(voice, language) ||
|
|
45
|
+
voiceSpeaks(voice, language.split('-')[0]));
|
|
46
|
+
}
|
|
47
|
+
/** Whether a voice of the catalogue speaks a language: what a new language keeps of a chosen voice. */
|
|
48
|
+
export function catalogueVoiceSpeaks(voice, language) {
|
|
49
|
+
return voicesSpeaking(language).some(spoken => spoken.id === voice);
|
|
50
|
+
}
|
|
51
|
+
/** The speeds offered, as multipliers of the voice's own. */
|
|
52
|
+
export const RATE_CHOICES = [
|
|
53
|
+
{ value: 0.75, label: 'Slower' },
|
|
54
|
+
{ value: 1, label: 'Normal' },
|
|
55
|
+
{ value: 1.25, label: 'Faster' },
|
|
56
|
+
{ value: 1.5, label: 'Fastest' },
|
|
57
|
+
];
|
|
58
|
+
/** The loudnesses offered, 0 to 1. */
|
|
59
|
+
export const VOLUME_CHOICES = [
|
|
60
|
+
{ value: 0.25, label: 'Quiet' },
|
|
61
|
+
{ value: 0.5, label: 'Half' },
|
|
62
|
+
{ value: 0.75, label: 'Loud' },
|
|
63
|
+
{ value: 1, label: 'Full' },
|
|
64
|
+
];
|
|
65
|
+
/** When answers are heard (VO-21): what a person may choose where the application speaks. */
|
|
66
|
+
export const OUTPUT_CHOICES = [
|
|
67
|
+
{ value: 'off', label: 'Never' },
|
|
68
|
+
{ value: 'on_request', label: 'When I ask (Read aloud)' },
|
|
69
|
+
{ value: 'always', label: 'Always, as they are written' },
|
|
70
|
+
];
|
package/lib/voice/index.d.ts
CHANGED
|
@@ -16,6 +16,10 @@ export * from './hearing';
|
|
|
16
16
|
export * from './speaker';
|
|
17
17
|
export * from './consent';
|
|
18
18
|
export * from './settings';
|
|
19
|
+
export * from './choices';
|
|
20
|
+
export { useVoiceSettings } from './useVoiceSettings';
|
|
21
|
+
export { VoiceMenu } from './VoiceMenu';
|
|
22
|
+
export type { VoiceMenuProps } from './VoiceMenu';
|
|
19
23
|
export * from './useSpokenAnswers';
|
|
20
24
|
export { VoiceInput } from './VoiceInput';
|
|
21
25
|
export type { VoiceInputProps, ListeningState } from './VoiceInput';
|
package/lib/voice/index.js
CHANGED
|
@@ -10,6 +10,9 @@ export * from './hearing';
|
|
|
10
10
|
export * from './speaker';
|
|
11
11
|
export * from './consent';
|
|
12
12
|
export * from './settings';
|
|
13
|
+
export * from './choices';
|
|
14
|
+
export { useVoiceSettings } from './useVoiceSettings';
|
|
15
|
+
export { VoiceMenu } from './VoiceMenu';
|
|
13
16
|
export * from './useSpokenAnswers';
|
|
14
17
|
export { VoiceInput } from './VoiceInput';
|
|
15
18
|
export { ReadAloud, readAloud, readsAloud } from './ReadAloud';
|
package/lib/voice/settings.d.ts
CHANGED
|
@@ -62,8 +62,24 @@ export interface VoiceSettings {
|
|
|
62
62
|
export declare function saneVoiceSettings(settings: VoiceSettings | null | undefined): VoiceSettings;
|
|
63
63
|
/** What was kept, or nothing. Storage may be refused, or hold nonsense. */
|
|
64
64
|
export declare function keptVoiceSettings(): VoiceSettings;
|
|
65
|
-
/**
|
|
65
|
+
/** The person's settings as the page holds them (VO-30). */
|
|
66
|
+
export declare function heldVoiceSettings(): VoiceSettings;
|
|
67
|
+
/**
|
|
68
|
+
* Be told when the person's settings change — from a menu on this page, or
|
|
69
|
+
* from another tab, whose storage event is read here. Returns the unsubscribe.
|
|
70
|
+
*/
|
|
71
|
+
export declare function onVoiceSettingsChange(listener: (settings: VoiceSettings) => void): () => void;
|
|
72
|
+
/**
|
|
73
|
+
* Keep what the person chose; an empty choice forgets it. Every chat on the
|
|
74
|
+
* page is told, so the menu's choice is heard at once (VO-30).
|
|
75
|
+
*/
|
|
66
76
|
export declare function keepVoiceSettings(settings: VoiceSettings): VoiceSettings;
|
|
77
|
+
/**
|
|
78
|
+
* The settings with one choice changed (VO-30): `undefined` forgets that
|
|
79
|
+
* choice, giving it back to the application. A new language drops a voice
|
|
80
|
+
* the person chose that does not speak it, for the language's own.
|
|
81
|
+
*/
|
|
82
|
+
export declare function withVoiceSetting<K extends keyof VoiceSettings>(settings: VoiceSettings, key: K, value: VoiceSettings[K] | undefined, speaks?: (voice: string, language: string) => boolean): VoiceSettings;
|
|
67
83
|
/** The language the browser says the person reads, or nothing. */
|
|
68
84
|
export declare function browserLanguage(): string | undefined;
|
|
69
85
|
/**
|
package/lib/voice/settings.js
CHANGED
|
@@ -54,7 +54,47 @@ export function keptVoiceSettings() {
|
|
|
54
54
|
return {};
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* What the page holds: the kept settings, or the choice made on this page
|
|
59
|
+
* when storage refused it. Read once, then told of each change.
|
|
60
|
+
*/
|
|
61
|
+
let held;
|
|
62
|
+
/** Who is told when the person's settings change: every chat on the page (VO-30). */
|
|
63
|
+
const listeners = new Set();
|
|
64
|
+
/** The person's settings as the page holds them (VO-30). */
|
|
65
|
+
export function heldVoiceSettings() {
|
|
66
|
+
if (held === undefined) {
|
|
67
|
+
held = keptVoiceSettings();
|
|
68
|
+
}
|
|
69
|
+
return held;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Be told when the person's settings change — from a menu on this page, or
|
|
73
|
+
* from another tab, whose storage event is read here. Returns the unsubscribe.
|
|
74
|
+
*/
|
|
75
|
+
export function onVoiceSettingsChange(listener) {
|
|
76
|
+
listeners.add(listener);
|
|
77
|
+
return () => {
|
|
78
|
+
listeners.delete(listener);
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function told(settings) {
|
|
82
|
+
held = settings;
|
|
83
|
+
for (const listener of [...listeners]) {
|
|
84
|
+
listener(settings);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (typeof window !== 'undefined') {
|
|
88
|
+
window.addEventListener('storage', event => {
|
|
89
|
+
if (event.key === VOICE_SETTINGS_KEY || event.key === null) {
|
|
90
|
+
told(keptVoiceSettings());
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Keep what the person chose; an empty choice forgets it. Every chat on the
|
|
96
|
+
* page is told, so the menu's choice is heard at once (VO-30).
|
|
97
|
+
*/
|
|
58
98
|
export function keepVoiceSettings(settings) {
|
|
59
99
|
const sane = saneVoiceSettings(settings);
|
|
60
100
|
try {
|
|
@@ -68,8 +108,31 @@ export function keepVoiceSettings(settings) {
|
|
|
68
108
|
catch {
|
|
69
109
|
// Without storage the choice holds for the page.
|
|
70
110
|
}
|
|
111
|
+
told(sane);
|
|
71
112
|
return sane;
|
|
72
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* The settings with one choice changed (VO-30): `undefined` forgets that
|
|
116
|
+
* choice, giving it back to the application. A new language drops a voice
|
|
117
|
+
* the person chose that does not speak it, for the language's own.
|
|
118
|
+
*/
|
|
119
|
+
export function withVoiceSetting(settings, key, value, speaks) {
|
|
120
|
+
const next = { ...saneVoiceSettings(settings) };
|
|
121
|
+
if (value === undefined) {
|
|
122
|
+
delete next[key];
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
next[key] = value;
|
|
126
|
+
}
|
|
127
|
+
if (key === 'language' &&
|
|
128
|
+
typeof value === 'string' &&
|
|
129
|
+
next.voice &&
|
|
130
|
+
speaks &&
|
|
131
|
+
!speaks(next.voice, value)) {
|
|
132
|
+
delete next.voice;
|
|
133
|
+
}
|
|
134
|
+
return saneVoiceSettings(next);
|
|
135
|
+
}
|
|
73
136
|
/** The language the browser says the person reads, or nothing. */
|
|
74
137
|
export function browserLanguage() {
|
|
75
138
|
try {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* A person's voice settings, as a React state that follows every change —
|
|
7
|
+
* the composer's menu, a settings page, another tab (VOICE.md VO-30).
|
|
8
|
+
*
|
|
9
|
+
* @module voice/useVoiceSettings
|
|
10
|
+
*/
|
|
11
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
12
|
+
import { heldVoiceSettings, keepVoiceSettings, onVoiceSettingsChange, } from './settings';
|
|
13
|
+
/** The person's settings, and a setter that keeps them and tells every chat. */
|
|
14
|
+
export function useVoiceSettings() {
|
|
15
|
+
const [settings, setSettings] = useState(heldVoiceSettings);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
// A change between the first draw and this subscription is read here.
|
|
18
|
+
setSettings(heldVoiceSettings());
|
|
19
|
+
return onVoiceSettingsChange(setSettings);
|
|
20
|
+
}, []);
|
|
21
|
+
const keep = useCallback((next) => {
|
|
22
|
+
keepVoiceSettings(next);
|
|
23
|
+
}, []);
|
|
24
|
+
return [settings, keep];
|
|
25
|
+
}
|