@datalayer/agent-runtimes 1.5.65 → 1.5.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. package/dist-embed/chunks/{AgentDetails-RIFH8RAg.js → AgentDetails-BriiIXid.js} +1 -1
  2. package/dist-embed/chunks/{AgentDetailsDialog-CK7jVPSc.js → AgentDetailsDialog-Bh3yhb7O.js} +1 -1
  3. package/dist-embed/chunks/{AgentInspector-DwZk4yjT.js → AgentInspector-Dd-G3TvL.js} +1 -1
  4. package/dist-embed/chunks/{AgentInspectorDialog-Ct12Hqc-.js → AgentInspectorDialog-CQEiBqOl.js} +1 -1
  5. package/dist-embed/chunks/{CellSidebarExtension-CbVVhhaO.js → CellSidebarExtension-DbbW8AJP.js} +1 -1
  6. package/dist-embed/chunks/ChatView-LzqHHAEe.js +32 -0
  7. package/dist-embed/chunks/{ContextPie-DLR5REbp.js → ContextPie-I90j658q.js} +1 -1
  8. package/dist-embed/chunks/{DeckComponent-C_ZaO_iF.js → DeckComponent-DAnUabRV.js} +2 -2
  9. package/dist-embed/chunks/{DocumentView-DP-dxfpu.js → DocumentView-BKFitqiB.js} +1 -1
  10. package/dist-embed/chunks/{EphemeralDocument-D3rfKBME.js → EphemeralDocument-BRzYMd8Z.js} +1 -1
  11. package/dist-embed/chunks/{EphemeralNotebook-Dn3ku5jr.js → EphemeralNotebook-COnqhW7Q.js} +1 -1
  12. package/dist-embed/chunks/{ExcalidrawComponent-B7I0SoHM.js → ExcalidrawComponent-VnKcai35.js} +1 -1
  13. package/dist-embed/chunks/{ExcalidrawModal-B2VIt9DT.js → ExcalidrawModal-DrntFjbe.js} +1 -1
  14. package/dist-embed/chunks/{JupyterLexicalExtension-LpJ6Rj9h.js → JupyterLexicalExtension-BBivQZvX.js} +9 -9
  15. package/dist-embed/chunks/{KernelVariables-ZFnygJ4R.js → KernelVariables-CNEfUsyt.js} +1 -1
  16. package/dist-embed/chunks/{LexicalToolRegistry-BRMKFkxC.js → LexicalToolRegistry-B8ccPURu.js} +4 -4
  17. package/dist-embed/chunks/{NotebookToolSurfaces-Dz_cxy8L.js → NotebookToolSurfaces-B8Rmjy_m.js} +1 -1
  18. package/dist-embed/chunks/{NotebookView-DG-pAyOq.js → NotebookView-BDChKuA9.js} +1 -1
  19. package/dist-embed/chunks/{Output-Cnq5i-bK.js → Output-CEoYDjwn.js} +1 -1
  20. package/dist-embed/chunks/{SandboxDetailsDialog-BzGdQmTQ.js → SandboxDetailsDialog-DuavSJSL.js} +1 -1
  21. package/dist-embed/chunks/SchemaForm-C6wDxDrg.js +1 -0
  22. package/dist-embed/chunks/{WidgetVariableView-kRHeKnmD.js → WidgetVariableView-Tm5SSEKf.js} +1 -1
  23. package/dist-embed/chunks/{YouTubePlugin-ChwsOfjj.js → YouTubePlugin-C209681s.js} +1 -1
  24. package/dist-embed/chunks/{abnfDiagram-VCTEODGH-sr3TJAkV.js → abnfDiagram-VCTEODGH-CsKFU4Ej.js} +1 -1
  25. package/dist-embed/chunks/{abnfDiagram-VCTEODGH-Byz1QYm8.js → abnfDiagram-VCTEODGH-m7LJLYga.js} +1 -1
  26. package/dist-embed/chunks/{ar-SA-G6X2FPQ2-D1OmbW2u.js → ar-SA-G6X2FPQ2-Dypu3IcK.js} +1 -1
  27. package/dist-embed/chunks/{architectureDiagram-5GKGNRK7-B7rDWQh9.js → architectureDiagram-5GKGNRK7-C22xzf-o.js} +1 -1
  28. package/dist-embed/chunks/{architectureDiagram-5GKGNRK7-DOxpBf54.js → architectureDiagram-5GKGNRK7-iDgRBR0a.js} +1 -1
  29. package/dist-embed/chunks/{az-AZ-76LH7QW2-CmSoFd5x.js → az-AZ-76LH7QW2-D8CzfKb1.js} +1 -1
  30. package/dist-embed/chunks/{bg-BG-XCXSNQG7-D7b2U9I0.js → bg-BG-XCXSNQG7-_NVFEM1_.js} +1 -1
  31. package/dist-embed/chunks/{blockDiagram-868be97b-CKmWpImQ.js → blockDiagram-868be97b-D3BurtSN.js} +1 -1
  32. package/dist-embed/chunks/{blockDiagram-I7D4REHJ-_fDDlpCe.js → blockDiagram-I7D4REHJ-CHicgYkf.js} +1 -1
  33. package/dist-embed/chunks/{blockDiagram-I7D4REHJ-bzZkd0c3.js → blockDiagram-I7D4REHJ-oDRNhSU2.js} +1 -1
  34. package/dist-embed/chunks/{bn-BD-2XOGV67Q-CG3iRJ8B.js → bn-BD-2XOGV67Q-DMgdNi-k.js} +1 -1
  35. package/dist-embed/chunks/{c4Diagram-3f4bdde3-zvlk6Xm2.js → c4Diagram-3f4bdde3-Dmbl9p6m.js} +1 -1
  36. package/dist-embed/chunks/{c4Diagram-7LVT6UL2-NpmtOeoK.js → c4Diagram-7LVT6UL2-CR3iQQ6O.js} +1 -1
  37. package/dist-embed/chunks/{c4Diagram-7LVT6UL2-vHp7kFMG.js → c4Diagram-7LVT6UL2-auJZQjpw.js} +1 -1
  38. package/dist-embed/chunks/{ca-ES-6MX7JW3Y-BW4zf4cd.js → ca-ES-6MX7JW3Y-DpOQhzr4.js} +1 -1
  39. package/dist-embed/chunks/{celltoolbartracker-DDVXLR_l.js → celltoolbartracker-DCR86wxV.js} +1 -1
  40. package/dist-embed/chunks/{chunk-2Q5K7J3B-Blqxrfai.js → chunk-2Q5K7J3B-DpFWUcsT.js} +1 -1
  41. package/dist-embed/chunks/{chunk-2Q5K7J3B-D26LTlFj.js → chunk-2Q5K7J3B-H_DA_jTG.js} +1 -1
  42. package/dist-embed/chunks/{chunk-5VM5RSS4-CdbSD_M8.js → chunk-5VM5RSS4-BhWUyelG.js} +1 -1
  43. package/dist-embed/chunks/{chunk-5VM5RSS4-BcO1XpWr.js → chunk-5VM5RSS4-CaowF8Al.js} +1 -1
  44. package/dist-embed/chunks/{chunk-F27PBJKO-BQ-ZIw-1.js → chunk-F27PBJKO-B9wgW70d.js} +1 -1
  45. package/dist-embed/chunks/{chunk-F27PBJKO-BRe2RwsD.js → chunk-F27PBJKO-D7PuEggc.js} +1 -1
  46. package/dist-embed/chunks/{chunk-IMKFNOWR-D-RO-dCd.js → chunk-IMKFNOWR-DhXkXQPV.js} +1 -1
  47. package/dist-embed/chunks/{chunk-IMKFNOWR-CLFrksv5.js → chunk-IMKFNOWR-jZNuNkCa.js} +1 -1
  48. package/dist-embed/chunks/{chunk-JWPE2WC7-wyMu098x.js → chunk-JWPE2WC7-BIShIUcJ.js} +1 -1
  49. package/dist-embed/chunks/{chunk-JWPE2WC7-DbtWvNSt.js → chunk-JWPE2WC7-DaBG37yC.js} +1 -1
  50. package/dist-embed/chunks/{chunk-POPQ4Y6H-OgpU0qcq.js → chunk-POPQ4Y6H-DG5Q2OKT.js} +1 -1
  51. package/dist-embed/chunks/{chunk-POPQ4Y6H-lwXXWwpD.js → chunk-POPQ4Y6H-WjTzJISs.js} +1 -1
  52. package/dist-embed/chunks/{chunk-SVP7TREG-CtOO_gz8.js → chunk-SVP7TREG-ERRaAh-x.js} +1 -1
  53. package/dist-embed/chunks/{chunk-SVP7TREG-C1pZJEUL.js → chunk-SVP7TREG-bq0J6tH_.js} +1 -1
  54. package/dist-embed/chunks/{chunk-TICWLB2K-BUeW_P5i.js → chunk-TICWLB2K-B91fA6Jd.js} +1 -1
  55. package/dist-embed/chunks/{chunk-TICWLB2K-B2id4fS-.js → chunk-TICWLB2K-BV_9f6ak.js} +1 -1
  56. package/dist-embed/chunks/{chunk-XXDRQBXY-6emV99Se.js → chunk-XXDRQBXY-BAy0lBJk.js} +1 -1
  57. package/dist-embed/chunks/{chunk-XXDRQBXY-DASCZDLb.js → chunk-XXDRQBXY-fV8doVJJ.js} +1 -1
  58. package/dist-embed/chunks/{classDiagram-ZZMXUADV-BUcYJSYu.js → classDiagram-ZZMXUADV-B0pbDswj.js} +1 -1
  59. package/dist-embed/chunks/{classDiagram-ZZMXUADV-DXK_VS6x.js → classDiagram-ZZMXUADV-CGdcKCOI.js} +1 -1
  60. package/dist-embed/chunks/{classDiagram-f62afe4f-D_XtspOB.js → classDiagram-f62afe4f-tD890DEl.js} +1 -1
  61. package/dist-embed/chunks/{classDiagram-v2-604399ef-DmVGURP4.js → classDiagram-v2-604399ef-DReIuoeI.js} +1 -1
  62. package/dist-embed/chunks/{classDiagram-v2-VYDZK3BY-BUcYJSYu.js → classDiagram-v2-VYDZK3BY-B0pbDswj.js} +1 -1
  63. package/dist-embed/chunks/{classDiagram-v2-VYDZK3BY-DXK_VS6x.js → classDiagram-v2-VYDZK3BY-CGdcKCOI.js} +1 -1
  64. package/dist-embed/chunks/{code-block-IT6T5CEO-CLFy43wi.js → code-block-IT6T5CEO-DD7hwbHA.js} +1 -1
  65. package/dist-embed/chunks/{component-BABP_IeE.js → component-BWDcVpKW.js} +1 -1
  66. package/dist-embed/chunks/{cose-bilkent-JH36ORCC-DkllT3uc.js → cose-bilkent-JH36ORCC-BS_pJML-.js} +1 -1
  67. package/dist-embed/chunks/{cose-bilkent-JH36ORCC-zloY56Dd.js → cose-bilkent-JH36ORCC-BsK2pWDL.js} +1 -1
  68. package/dist-embed/chunks/{createText-aed3d8b3-B_AmUgWn.js → createText-aed3d8b3-1eVJ8jxH.js} +2 -2
  69. package/dist-embed/chunks/{cs-CZ-2BRQDIVT-DzWWfN4P.js → cs-CZ-2BRQDIVT-Fr-SpqHD.js} +1 -1
  70. package/dist-embed/chunks/{cynefinDiagram-5FMLGOSQ-CT11o-tV.js → cynefinDiagram-5FMLGOSQ-AxJwZ7KT.js} +1 -1
  71. package/dist-embed/chunks/{cynefinDiagram-5FMLGOSQ-Benlx8nr.js → cynefinDiagram-5FMLGOSQ-vmheD_S2.js} +1 -1
  72. package/dist-embed/chunks/{da-DK-5WZEPLOC-CaeirLFF.js → da-DK-5WZEPLOC-DO_sAXvt.js} +1 -1
  73. package/dist-embed/chunks/{dagre-GXQ25YYZ-B2PPWFKB.js → dagre-GXQ25YYZ-B8Ip03td.js} +1 -1
  74. package/dist-embed/chunks/{dagre-GXQ25YYZ-qys4evHY.js → dagre-GXQ25YYZ-BgrGEY09.js} +1 -1
  75. package/dist-embed/chunks/{de-DE-XR44H4JA-DBkebtzo.js → de-DE-XR44H4JA-4JnXB_iM.js} +1 -1
  76. package/dist-embed/chunks/{diagram-S7CK7UJ4-C1EHbNes.js → diagram-S7CK7UJ4-BxRBCYVP.js} +1 -1
  77. package/dist-embed/chunks/{diagram-S7CK7UJ4-CBkf-BrM.js → diagram-S7CK7UJ4-hQvZziAN.js} +1 -1
  78. package/dist-embed/chunks/{diagram-UQ7AKVKN-CKsxaZCe.js → diagram-UQ7AKVKN-BFkOO3Wu.js} +1 -1
  79. package/dist-embed/chunks/{diagram-UQ7AKVKN-C9zuKZ5Y.js → diagram-UQ7AKVKN-BvgP6_rf.js} +1 -1
  80. package/dist-embed/chunks/{diagram-VSXAHHWV-Cd8pBAf-.js → diagram-VSXAHHWV-Cy8iWh4H.js} +1 -1
  81. package/dist-embed/chunks/{diagram-VSXAHHWV-Dd_PlC0S.js → diagram-VSXAHHWV-WVuzjdxU.js} +1 -1
  82. package/dist-embed/chunks/{diagram-VX7I27RA-DZTLEsKe.js → diagram-VX7I27RA-CCx8R8FK.js} +1 -1
  83. package/dist-embed/chunks/{diagram-VX7I27RA-D5qf5Kw-.js → diagram-VX7I27RA-_LUOsaBb.js} +1 -1
  84. package/dist-embed/chunks/{diagram-Z3DM3KII-DlsBShb0.js → diagram-Z3DM3KII-CY856Sry.js} +1 -1
  85. package/dist-embed/chunks/{diagram-Z3DM3KII-B2zosfsY.js → diagram-Z3DM3KII-Dqcrl8-1.js} +1 -1
  86. package/dist-embed/chunks/{ebnfDiagram-PWID7BFC-VhBXkHc8.js → ebnfDiagram-PWID7BFC-DC-Zam6d.js} +1 -1
  87. package/dist-embed/chunks/{ebnfDiagram-PWID7BFC-sUXnKXhD.js → ebnfDiagram-PWID7BFC-kqD9RLAA.js} +1 -1
  88. package/dist-embed/chunks/{edges-b2856ca0-cYsFYCgh.js → edges-b2856ca0-B3ybuHDU.js} +1 -1
  89. package/dist-embed/chunks/{el-GR-BZB4AONW-DkmsSwGL.js → el-GR-BZB4AONW-MydAlwHl.js} +1 -1
  90. package/dist-embed/chunks/{erDiagram-5d81789a-DHzqp69u.js → erDiagram-5d81789a-HZ-VLc2f.js} +1 -1
  91. package/dist-embed/chunks/{erDiagram-RLTQ6QDP-DPzcAUZq.js → erDiagram-RLTQ6QDP-CNO4pVhU.js} +1 -1
  92. package/dist-embed/chunks/{erDiagram-RLTQ6QDP-BRf7HEXF.js → erDiagram-RLTQ6QDP-zwXEFcAp.js} +1 -1
  93. package/dist-embed/chunks/{es-ES-U4NZUMDT-Dvnvh6dW.js → es-ES-U4NZUMDT-rQmnr_uu.js} +1 -1
  94. package/dist-embed/chunks/{eu-ES-A7QVB2H4-DYX6hpyz.js → eu-ES-A7QVB2H4-j5Hf8ngk.js} +1 -1
  95. package/dist-embed/chunks/{fa-IR-HGAKTJCU-Dmlm1ZjK.js → fa-IR-HGAKTJCU-DMJRRSBp.js} +1 -1
  96. package/dist-embed/chunks/{fi-FI-Z5N7JZ37-2ov9-9H3.js → fi-FI-Z5N7JZ37-BFLC0BFd.js} +1 -1
  97. package/dist-embed/chunks/{flowDb-185abca5-vnPYmNxZ.js → flowDb-185abca5-7Nn2obHG.js} +1 -1
  98. package/dist-embed/chunks/{flowDiagram-1629c991-D_P7IhnT.js → flowDiagram-1629c991-CnvM_psw.js} +1 -1
  99. package/dist-embed/chunks/{flowDiagram-HODETNUW-BUuZtbKx.js → flowDiagram-HODETNUW-BrbR1EkW.js} +1 -1
  100. package/dist-embed/chunks/{flowDiagram-HODETNUW-Dqms2kHK.js → flowDiagram-HODETNUW-Bsl5oOFb.js} +1 -1
  101. package/dist-embed/chunks/{flowDiagram-v2-1d953310-jyYNkbVD.js → flowDiagram-v2-1d953310-TkF25UVC.js} +1 -1
  102. package/dist-embed/chunks/{flowchart-elk-definition-6df44142-CkUTQpED.js → flowchart-elk-definition-6df44142-CwiGfEuJ.js} +1 -1
  103. package/dist-embed/chunks/{fr-FR-RHASNOE6-BUlHGdL2.js → fr-FR-RHASNOE6-CxjhSJC1.js} +1 -1
  104. package/dist-embed/chunks/{ganttDiagram-3b0b3873-CDk8PUcC.js → ganttDiagram-3b0b3873-DeouFDZE.js} +1 -1
  105. package/dist-embed/chunks/{ganttDiagram-EL5Y4UJY-D4fzILsk.js → ganttDiagram-EL5Y4UJY-BeK3rGHM.js} +1 -1
  106. package/dist-embed/chunks/{ganttDiagram-EL5Y4UJY-Tsk8dNyJ.js → ganttDiagram-EL5Y4UJY-DfJDZVnm.js} +1 -1
  107. package/dist-embed/chunks/{gitGraphDiagram-WWUBYQGX-DSJR8KGU.js → gitGraphDiagram-WWUBYQGX-BujqTwbf.js} +1 -1
  108. package/dist-embed/chunks/{gitGraphDiagram-WWUBYQGX-XOpfU7hY.js → gitGraphDiagram-WWUBYQGX-DkYi8eWr.js} +1 -1
  109. package/dist-embed/chunks/{gitGraphDiagram-f01e8bc2-C7QWh6IZ.js → gitGraphDiagram-f01e8bc2-mCCRVzIs.js} +1 -1
  110. package/dist-embed/chunks/{gl-ES-HMX3MZ6V-T3hKsmlm.js → gl-ES-HMX3MZ6V-BuuMpTaX.js} +1 -1
  111. package/dist-embed/chunks/{he-IL-6SHJWFNN-DoePgaFj.js → he-IL-6SHJWFNN-Cv3Nrcgu.js} +1 -1
  112. package/dist-embed/chunks/{hi-IN-IWLTKZ5I-B_E7TPlk.js → hi-IN-IWLTKZ5I-Sddst60F.js} +1 -1
  113. package/dist-embed/chunks/{hu-HU-A5ZG7DT2-Bu8X3BrR.js → hu-HU-A5ZG7DT2-ehrXVpD0.js} +1 -1
  114. package/dist-embed/chunks/{id-ID-SAP4L64H-jOs7pgj2.js → id-ID-SAP4L64H-Gfb1UYxZ.js} +1 -1
  115. package/dist-embed/chunks/{index-JF61_zqs.js → index-5NOGMVjz.js} +1 -1
  116. package/dist-embed/chunks/{index-BzgczmKp.js → index-6zxVHKca.js} +10 -10
  117. package/dist-embed/chunks/{index-9bae90f3-BywpAnlj.js → index-9bae90f3-CzUk5Hhq.js} +1 -1
  118. package/dist-embed/chunks/{index-DvHqo_Qj.js → index-AHAhJxOc.js} +1 -1
  119. package/dist-embed/chunks/{index-7hNcqUR-.js → index-B9Ya6z2n.js} +1 -1
  120. package/dist-embed/chunks/{index-BwyZ8O-M.js → index-BOEhatkt.js} +1 -1
  121. package/dist-embed/chunks/{index-BYo3uv0g.js → index-BOGJMsUN.js} +2 -2
  122. package/dist-embed/chunks/{index-Bmo-OFNb.js → index-BaBNw6X5.js} +4 -4
  123. package/dist-embed/chunks/{index-BR58wzgU.js → index-BfvZMC2B.js} +1 -1
  124. package/dist-embed/chunks/{index-DnqWNX5L.js → index-BiuABva5.js} +1 -1
  125. package/dist-embed/chunks/{index-0m4vhMAR.js → index-BjfpYq_l.js} +1 -1
  126. package/dist-embed/chunks/{index-BI_0cBab.js → index-BuXVVl_h.js} +7 -7
  127. package/dist-embed/chunks/{index-fBSCurWE.js → index-By5Ku2wm.js} +4 -4
  128. package/dist-embed/chunks/{index-Bw1BRX9C.js → index-CNpJ8Y2y.js} +1 -1
  129. package/dist-embed/chunks/{index-zrM_sbHt.js → index-Cw1r0WFc.js} +1 -1
  130. package/dist-embed/chunks/{index-CS3mm6qN.js → index-D8x0MQWQ.js} +1 -1
  131. package/dist-embed/chunks/{index-BqpOM6Mx.js → index-DDnf06e_.js} +1 -1
  132. package/dist-embed/chunks/{index-B3fpdUTu.js → index-DGefzKhT.js} +1 -1
  133. package/dist-embed/chunks/{index-CgCcVxV_.js → index-DN6Cori6.js} +1 -1
  134. package/dist-embed/chunks/{index-_z7rhr9l.js → index-DQ-v6JVz.js} +4 -4
  135. package/dist-embed/chunks/{index-C2JsK59r.js → index-DTYZzbES.js} +1 -1
  136. package/dist-embed/chunks/{index-MfJ2dN-o.js → index-DWkIO3YS.js} +1 -1
  137. package/dist-embed/chunks/{index-CL2J1VY_.js → index-DZwyICkp.js} +1 -1
  138. package/dist-embed/chunks/{index-CoVJiT-h.js → index-D_vehxcD.js} +1 -1
  139. package/dist-embed/chunks/{index-wqOJuJys.js → index-DiTcTB7Y.js} +1 -1
  140. package/dist-embed/chunks/{index-COPak822.js → index-DmpLE1d4.js} +1 -1
  141. package/dist-embed/chunks/{index-Ca5wn1F-.js → index-Do4nOAaR.js} +1 -1
  142. package/dist-embed/chunks/{index-DBRbrQr1.js → index-DobaF_Ee.js} +1 -1
  143. package/dist-embed/chunks/{index-BfuxhQsr.js → index-DvwQdrde.js} +1 -1
  144. package/dist-embed/chunks/{index-KC9furSU.js → index-DzMYyq8T.js} +1 -1
  145. package/dist-embed/chunks/{index-Cz0vwY93.js → index-QHmZQlKN.js} +6 -6
  146. package/dist-embed/chunks/{index-C00mEIpi.js → index-hxIHgkzg.js} +1 -1
  147. package/dist-embed/chunks/{index-B27olYsx.js → index-nMwnYxTd.js} +1 -1
  148. package/dist-embed/chunks/{index-NvC9D0Mh.js → index-umwkqggg.js} +1 -1
  149. package/dist-embed/chunks/{index-3JfFVSno.js → index-yMppJWrQ.js} +1 -1
  150. package/dist-embed/chunks/{index.esm-BbIi4n-Y.js → index.esm-CC457Cyg.js} +1 -1
  151. package/dist-embed/chunks/{index.esm-ePira_es.js → index.esm-DFDbLGof.js} +1 -1
  152. package/dist-embed/chunks/{infoDiagram-27XIBGKW-CvSw0Uqm.js → infoDiagram-27XIBGKW-C18Zz25F.js} +1 -1
  153. package/dist-embed/chunks/{infoDiagram-27XIBGKW-BagqSEKB.js → infoDiagram-27XIBGKW-DiC5_yjB.js} +1 -1
  154. package/dist-embed/chunks/{infoDiagram-a29d40f1-CY6P-RB2.js → infoDiagram-a29d40f1-DRVyx4Bf.js} +1 -1
  155. package/dist-embed/chunks/{ishikawaDiagram-5VMMS53U-CJjl4-N0.js → ishikawaDiagram-5VMMS53U-3WGbru46.js} +1 -1
  156. package/dist-embed/chunks/{ishikawaDiagram-5VMMS53U-DQfqd5pn.js → ishikawaDiagram-5VMMS53U-DrEzfSK9.js} +1 -1
  157. package/dist-embed/chunks/{it-IT-JPQ66NNP-CrGtxCjf.js → it-IT-JPQ66NNP-BehLHkar.js} +1 -1
  158. package/dist-embed/chunks/{ja-JP-DBVTYXUO-MhHoMhnM.js → ja-JP-DBVTYXUO-BZvqIigI.js} +1 -1
  159. package/dist-embed/chunks/{journeyDiagram-3NMN7TZE-B186toLf.js → journeyDiagram-3NMN7TZE-BZWmkUfk.js} +1 -1
  160. package/dist-embed/chunks/{journeyDiagram-3NMN7TZE-fMuL5yIV.js → journeyDiagram-3NMN7TZE-DpWKIFIN.js} +1 -1
  161. package/dist-embed/chunks/{journeyDiagram-95396277-Bt2VFr_f.js → journeyDiagram-95396277-D_QLiVq4.js} +1 -1
  162. package/dist-embed/chunks/{kaa-6HZHGXH3-otexWzw0.js → kaa-6HZHGXH3-DgAIF6rN.js} +1 -1
  163. package/dist-embed/chunks/{kab-KAB-ZGHBKWFO-Bk_pPM_n.js → kab-KAB-ZGHBKWFO-DW4thPSJ.js} +1 -1
  164. package/dist-embed/chunks/{kanban-definition-UXKFOSKX-tkyZOsyz.js → kanban-definition-UXKFOSKX-B84ZaZEy.js} +1 -1
  165. package/dist-embed/chunks/{kanban-definition-UXKFOSKX-DyX3lLGq.js → kanban-definition-UXKFOSKX-DxbTprYr.js} +1 -1
  166. package/dist-embed/chunks/{kk-KZ-P5N5QNE5-DuPx0Ivn.js → kk-KZ-P5N5QNE5-CCy_nSJ7.js} +1 -1
  167. package/dist-embed/chunks/{km-KH-HSX4SM5Z-DfW3Tv6Q.js → km-KH-HSX4SM5Z-kpXyoxjS.js} +1 -1
  168. package/dist-embed/chunks/{ko-KR-MTYHY66A-CWeM03UD.js → ko-KR-MTYHY66A-CFm6WtQG.js} +1 -1
  169. package/dist-embed/chunks/{ku-TR-6OUDTVRD-BpZVGVBG.js → ku-TR-6OUDTVRD-CKF85mOv.js} +1 -1
  170. package/dist-embed/chunks/{layout-i1FLEqsi.js → layout-DYytgC9r.js} +1 -1
  171. package/dist-embed/chunks/{layout-P_H-0ax9.js → layout-Dx5Hzkor.js} +1 -1
  172. package/dist-embed/chunks/{lexicalHooks-BjTCfdUi.js → lexicalHooks-DbTGOMyq.js} +1 -1
  173. package/dist-embed/chunks/{lt-LT-XHIRWOB4-LavcVuZR.js → lt-LT-XHIRWOB4-CO9Bo5qJ.js} +1 -1
  174. package/dist-embed/chunks/{lv-LV-5QDEKY6T-DWoheFP4.js → lv-LV-5QDEKY6T-CvZszc5p.js} +1 -1
  175. package/dist-embed/chunks/{mermaid.core-Cltl6__q.js → mermaid.core-D0955PCw.js} +5 -5
  176. package/dist-embed/chunks/{mermaid.core-Bd5egiDP.js → mermaid.core-D98kc0OO.js} +3 -3
  177. package/dist-embed/chunks/{mindmap-definition-YA3MSWOX-BmuUH3a3.js → mindmap-definition-YA3MSWOX-D86IPkt3.js} +1 -1
  178. package/dist-embed/chunks/{mindmap-definition-YA3MSWOX-Di0Xac42.js → mindmap-definition-YA3MSWOX-_1SBIPav.js} +1 -1
  179. package/dist-embed/chunks/{mindmap-definition-e4c1d938-D0Ep5LxZ.js → mindmap-definition-e4c1d938-UbbfpF-a.js} +1 -1
  180. package/dist-embed/chunks/{mr-IN-CRQNXWMA-G-1tBL4-.js → mr-IN-CRQNXWMA-Cio_dB9M.js} +1 -1
  181. package/dist-embed/chunks/{my-MM-5M5IBNSE-DpmzmQ2W.js → my-MM-5M5IBNSE-Z0RQ5Vbz.js} +1 -1
  182. package/dist-embed/chunks/{nb-NO-T6EIAALU-DFU_SPCx.js → nb-NO-T6EIAALU-BEQ0YP9J.js} +1 -1
  183. package/dist-embed/chunks/{nl-NL-IS3SIHDZ-Dlz_okxD.js → nl-NL-IS3SIHDZ-YtkJnS_J.js} +1 -1
  184. package/dist-embed/chunks/{nn-NO-6E72VCQL-D9E-BpHw.js → nn-NO-6E72VCQL-C1j2s3qO.js} +1 -1
  185. package/dist-embed/chunks/{oc-FR-POXYY2M6-CVonm6mx.js → oc-FR-POXYY2M6-CinnjccW.js} +1 -1
  186. package/dist-embed/chunks/{pa-IN-N4M65BXN-a5ExTB9v.js → pa-IN-N4M65BXN-c_6OtC6L.js} +1 -1
  187. package/dist-embed/chunks/{pegDiagram-XKGWAZYB-BYznG-ZK.js → pegDiagram-XKGWAZYB-BBVcHZ8T.js} +1 -1
  188. package/dist-embed/chunks/{pegDiagram-XKGWAZYB-Cptotyez.js → pegDiagram-XKGWAZYB-BJAdJVqh.js} +1 -1
  189. package/dist-embed/chunks/{percentages-BXMCSKIN-C2-svgs_.js → percentages-BXMCSKIN-VqMxh8LK.js} +5 -5
  190. package/dist-embed/chunks/{pieDiagram-E7YTZNPT-BYEkkWvq.js → pieDiagram-E7YTZNPT-C55wHgO0.js} +1 -1
  191. package/dist-embed/chunks/{pieDiagram-E7YTZNPT-D51avc4V.js → pieDiagram-E7YTZNPT-EvMxJb2S.js} +1 -1
  192. package/dist-embed/chunks/{pieDiagram-c941bede-Bcau8_Gm.js → pieDiagram-c941bede-DTmViAsB.js} +1 -1
  193. package/dist-embed/chunks/{pl-PL-T2D74RX3-BaHKKcOg.js → pl-PL-T2D74RX3-Cn_9xZgM.js} +1 -1
  194. package/dist-embed/chunks/{pt-BR-5N22H2LF-DZEHszX8.js → pt-BR-5N22H2LF-Da6r-Pp1.js} +1 -1
  195. package/dist-embed/chunks/{pt-PT-UZXXM6DQ-BbJKz8vE.js → pt-PT-UZXXM6DQ-D6lhcuX9.js} +1 -1
  196. package/dist-embed/chunks/{quadrantDiagram-AXDQQJYC-BfWK8wgJ.js → quadrantDiagram-AXDQQJYC-BCeMrGXB.js} +1 -1
  197. package/dist-embed/chunks/{quadrantDiagram-AXDQQJYC-CcMIo23m.js → quadrantDiagram-AXDQQJYC-rFaTvNlk.js} +1 -1
  198. package/dist-embed/chunks/{quadrantDiagram-cf8b8fe0-Db1y7cGB.js → quadrantDiagram-cf8b8fe0-BZAbhmbg.js} +1 -1
  199. package/dist-embed/chunks/{railroadDiagram-O6MQD6OU-BzqhRF47.js → railroadDiagram-O6MQD6OU-BAXhb26s.js} +1 -1
  200. package/dist-embed/chunks/{railroadDiagram-O6MQD6OU-DCRFdpxj.js → railroadDiagram-O6MQD6OU-bR7xXZGS.js} +1 -1
  201. package/dist-embed/chunks/{renderer-CM-Z_1Uj.js → renderer-DfML3j-s.js} +1 -1
  202. package/dist-embed/chunks/{requirementDiagram-53bda41b-Dj564NwS.js → requirementDiagram-53bda41b-DNqx3JRF.js} +1 -1
  203. package/dist-embed/chunks/{requirementDiagram-BXWQKSXE-dma0a-bN.js → requirementDiagram-BXWQKSXE-B0SL6Gqb.js} +1 -1
  204. package/dist-embed/chunks/{requirementDiagram-BXWQKSXE-CIFZt_cP.js → requirementDiagram-BXWQKSXE-DHLQ_9Lw.js} +1 -1
  205. package/dist-embed/chunks/{ro-RO-JPDTUUEW-szdAFgjr.js → ro-RO-JPDTUUEW-BFss9e8X.js} +1 -1
  206. package/dist-embed/chunks/{ru-RU-B4JR7IUQ-CbdtKkxy.js → ru-RU-B4JR7IUQ-DIruW2gS.js} +1 -1
  207. package/dist-embed/chunks/{sankeyDiagram-P5KCCOFB-8ur8k-HP.js → sankeyDiagram-P5KCCOFB-CktuQIU1.js} +1 -1
  208. package/dist-embed/chunks/{sankeyDiagram-P5KCCOFB-DRxZFl9I.js → sankeyDiagram-P5KCCOFB-Nk71fRsK.js} +1 -1
  209. package/dist-embed/chunks/{sankeyDiagram-c3ef121a-Da81kIDr.js → sankeyDiagram-c3ef121a-4-5C_fXA.js} +1 -1
  210. package/dist-embed/chunks/{sequenceDiagram-82a5b84f-DM8BTW5K.js → sequenceDiagram-82a5b84f-DedJ5qnD.js} +1 -1
  211. package/dist-embed/chunks/{sequenceDiagram-WJ2MYXX4-BH0Y4uG3.js → sequenceDiagram-WJ2MYXX4-BBGHED3s.js} +1 -1
  212. package/dist-embed/chunks/{sequenceDiagram-WJ2MYXX4-CNwXBdZi.js → sequenceDiagram-WJ2MYXX4-Dm3QM01Z.js} +1 -1
  213. package/dist-embed/chunks/{sessions-DlvFLGbP.js → sessions-lT1zQJEG.js} +2 -2
  214. package/dist-embed/chunks/{si-LK-N5RQ5JYF-DfCWfEQf.js → si-LK-N5RQ5JYF-Dom-aTTE.js} +1 -1
  215. package/dist-embed/chunks/{sizeCapture-INFHLROL-D-nX-7Hv.js → sizeCapture-INFHLROL-BNuVN7vX.js} +1 -1
  216. package/dist-embed/chunks/{sizeCapture-INFHLROL-Tw2tvJ1W.js → sizeCapture-INFHLROL-BW7unDBA.js} +1 -1
  217. package/dist-embed/chunks/{sk-SK-C5VTKIMK-CTeAwA1b.js → sk-SK-C5VTKIMK-CLRU9TNq.js} +1 -1
  218. package/dist-embed/chunks/{sl-SI-NN7IZMDC-eFw2lQcd.js → sl-SI-NN7IZMDC-BKLCNVXA.js} +1 -1
  219. package/dist-embed/chunks/{stateDiagram-43e79a5f-H8oVn7EH.js → stateDiagram-43e79a5f-C-TVhCrM.js} +1 -1
  220. package/dist-embed/chunks/{stateDiagram-D77RDMKH-DS-byRyy.js → stateDiagram-D77RDMKH-mLSMGpPQ.js} +1 -1
  221. package/dist-embed/chunks/{stateDiagram-D77RDMKH-CGEuq_3Z.js → stateDiagram-D77RDMKH-tqnmMQUf.js} +1 -1
  222. package/dist-embed/chunks/{stateDiagram-v2-2041ed4f-D7zd-PeH.js → stateDiagram-v2-2041ed4f-TVcKzajK.js} +1 -1
  223. package/dist-embed/chunks/{stateDiagram-v2-MP3YSRHH-Bbn7CxXx.js → stateDiagram-v2-MP3YSRHH-C3MNIg5B.js} +1 -1
  224. package/dist-embed/chunks/{stateDiagram-v2-MP3YSRHH-CllCmLuo.js → stateDiagram-v2-MP3YSRHH-C6TftAzE.js} +1 -1
  225. package/dist-embed/chunks/{styles-455b33cd-CYP0pxwM.js → styles-455b33cd-CIILXOoF.js} +1 -1
  226. package/dist-embed/chunks/{styles-f932cba9-dXHjU5Mc.js → styles-f932cba9-CVBMDsh6.js} +1 -1
  227. package/dist-embed/chunks/{styles-fcc2142b-CrgFTq7b.js → styles-fcc2142b-CTOmFTKK.js} +1 -1
  228. package/dist-embed/chunks/{subset-shared.chunk-BCNcfBdp.js → subset-shared.chunk-zIH7OLsP.js} +1 -1
  229. package/dist-embed/chunks/{subset-worker.chunk-nY71AE9b.js → subset-worker.chunk-b9j7PKPe.js} +1 -1
  230. package/dist-embed/chunks/{sv-SE-XGPEYMSR-B3BAd7ic.js → sv-SE-XGPEYMSR-D0UV0HV7.js} +1 -1
  231. package/dist-embed/chunks/{svgDrawCommon-148a3cd9-DY-6e2w2.js → svgDrawCommon-148a3cd9-BCgvh5nL.js} +1 -1
  232. package/dist-embed/chunks/{swimlanes-42K2YHIH-CpFqKR23.js → swimlanes-42K2YHIH-BQTDK2Ta.js} +1 -1
  233. package/dist-embed/chunks/{swimlanes-42K2YHIH-BoshoQYI.js → swimlanes-42K2YHIH-DHcV40DB.js} +1 -1
  234. package/dist-embed/chunks/{swimlanesDiagram-VR7AAH4N-BNalU-se.js → swimlanesDiagram-VR7AAH4N-BV8Vb5g2.js} +1 -1
  235. package/dist-embed/chunks/{swimlanesDiagram-VR7AAH4N-CUEoZUeR.js → swimlanesDiagram-VR7AAH4N-CQ7d-sbG.js} +1 -1
  236. package/dist-embed/chunks/{ta-IN-2NMHFXQM-Ch7Coorh.js → ta-IN-2NMHFXQM-C-EJ3jDE.js} +1 -1
  237. package/dist-embed/chunks/{th-TH-HPSO5L25-gmc7tguq.js → th-TH-HPSO5L25-CfQh62Qa.js} +1 -1
  238. package/dist-embed/chunks/{timeline-definition-24CTP7MA-BD_Hd7OM.js → timeline-definition-24CTP7MA-CKtubk73.js} +1 -1
  239. package/dist-embed/chunks/{timeline-definition-24CTP7MA-CLQC5Soj.js → timeline-definition-24CTP7MA-DJcFE1jT.js} +1 -1
  240. package/dist-embed/chunks/{timeline-definition-7545f45a-CBNPBc2S.js → timeline-definition-7545f45a-CLycxRtq.js} +1 -1
  241. package/dist-embed/chunks/{tr-TR-DEFEU3FU-DoKmjhCn.js → tr-TR-DEFEU3FU-Lz7Ka2Zr.js} +1 -1
  242. package/dist-embed/chunks/{uk-UA-QMV73CPH-uzMCDuv6.js → uk-UA-QMV73CPH-DU0hsGUJ.js} +1 -1
  243. package/dist-embed/chunks/{vennDiagram-4TSXK5OY-Clhmiu8L.js → vennDiagram-4TSXK5OY-BMmQ-DIV.js} +1 -1
  244. package/dist-embed/chunks/{vennDiagram-4TSXK5OY-BxbIHKUM.js → vennDiagram-4TSXK5OY-Bq0xMhnH.js} +1 -1
  245. package/dist-embed/chunks/{vi-VN-M7AON7JQ-UC9RyOt8.js → vi-VN-M7AON7JQ-CDvS0SiL.js} +1 -1
  246. package/dist-embed/chunks/{wardleyDiagram-VM6X3IG4-HuiHAtr-.js → wardleyDiagram-VM6X3IG4-C1VKw6YX.js} +1 -1
  247. package/dist-embed/chunks/{wardleyDiagram-VM6X3IG4-un-PuqHe.js → wardleyDiagram-VM6X3IG4-DL5LgQWr.js} +1 -1
  248. package/dist-embed/chunks/{xychartDiagram-3f383b91-3k3NdPbU.js → xychartDiagram-3f383b91-B-BTwetN.js} +1 -1
  249. package/dist-embed/chunks/{xychartDiagram-S5SC5T6Z-CIDOTVoZ.js → xychartDiagram-S5SC5T6Z-BQHFHk-x.js} +1 -1
  250. package/dist-embed/chunks/{xychartDiagram-S5SC5T6Z-CvZAV0KM.js → xychartDiagram-S5SC5T6Z-BXkM4beH.js} +1 -1
  251. package/dist-embed/chunks/{zh-CN-LNUGB5OW-DFA0PCzk.js → zh-CN-LNUGB5OW-CWE-bF0d.js} +1 -1
  252. package/dist-embed/chunks/{zh-HK-E62DVLB3-WzEwoBkd.js → zh-HK-E62DVLB3-pEfL2bds.js} +1 -1
  253. package/dist-embed/chunks/{zh-TW-RAJ6MFWO-B7w1h39x.js → zh-TW-RAJ6MFWO-Cp6UFUuD.js} +1 -1
  254. package/dist-embed/datalayer-app-main.js +107 -106
  255. package/lib/apps/apps/records.d.ts +21 -4
  256. package/lib/apps/apps/records.js +8 -6
  257. package/lib/apps/apps/threads.d.ts +11 -1
  258. package/lib/apps/apps/threads.js +17 -0
  259. package/lib/apps/core/index.d.ts +71 -0
  260. package/lib/apps/core/index.js +22 -0
  261. package/lib/apps/plugins/app-activity/AppActivity.js +10 -4
  262. package/lib/apps/plugins/chat/ChatView.js +123 -6
  263. package/lib/apps/plugins/chat/SessionActionsMenu.d.ts +40 -0
  264. package/lib/apps/plugins/chat/SessionActionsMenu.js +73 -0
  265. package/lib/apps/plugins/chat/SessionChooseDialog.d.ts +22 -0
  266. package/lib/apps/plugins/chat/SessionChooseDialog.js +39 -0
  267. package/lib/apps/plugins/chat/index.js +8 -1
  268. package/lib/apps/plugins/chat/sessionActions.d.ts +65 -0
  269. package/lib/apps/plugins/chat/sessionActions.js +184 -0
  270. package/lib/chat/Chat.d.ts +42 -2
  271. package/lib/chat/Chat.js +148 -2
  272. package/lib/chat/base/ChatBase.js +33 -6
  273. package/lib/chat/index.d.ts +1 -1
  274. package/lib/chat/messages/ChatMessageList.d.ts +3 -1
  275. package/lib/chat/messages/ChatMessageList.js +21 -2
  276. package/lib/portable/activity.d.ts +91 -2
  277. package/lib/portable/activity.js +143 -4
  278. package/lib/portable/fixtures.d.ts +1 -1
  279. package/lib/portable/fixtures.js +17 -7
  280. package/lib/portable/index.d.ts +1 -1
  281. package/lib/portable/index.js +3 -2
  282. package/lib/portable/sessions.d.ts +25 -1
  283. package/lib/portable/sessions.js +62 -4
  284. package/lib/specs/harnesses.js +96 -0
  285. package/lib/specs/index.d.ts +1 -0
  286. package/lib/specs/index.js +1 -0
  287. package/lib/specs/sessionFiles.d.ts +123 -0
  288. package/lib/specs/sessionFiles.js +578 -0
  289. package/lib/types/agentspecs.d.ts +26 -0
  290. package/lib/types/chat.d.ts +38 -0
  291. package/package.json +1 -1
  292. package/scripts/codegen/generate_agents.py +1 -0
  293. package/scripts/codegen/generate_harnesses.py +70 -0
  294. package/scripts/codegen/generate_session_files.py +296 -0
  295. package/dist-embed/chunks/ChatView-B_EEvtKi.js +0 -32
  296. package/dist-embed/chunks/SchemaForm-Dg9uk6m3.js +0 -1
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { FormControl, Select, Text } from '@primer/react';
4
+ import { Dialog } from '@primer/react/experimental';
5
+ import { Box } from '@datalayer/primer-addons';
6
+ export const CHOOSE_WORDS = {
7
+ confirm: 'Switch',
8
+ cancel: 'Keep it',
9
+ };
10
+ export function SessionChooseDialog({ question, onPick, }) {
11
+ const [picked, setPicked] = useState(question.options[0]?.id ?? '');
12
+ const [says, setSays] = useState('');
13
+ useEffect(() => {
14
+ let current = true;
15
+ if (!question.says || !picked) {
16
+ setSays('');
17
+ return undefined;
18
+ }
19
+ question.says(picked).then(sentence => current && setSays(sentence), () => current && setSays(''));
20
+ return () => {
21
+ current = false;
22
+ };
23
+ }, [picked, question]);
24
+ const chosen = question.options.find(option => option.id === picked);
25
+ return (_jsx(Dialog, { title: question.title, onClose: () => onPick(undefined), width: "medium", footerButtons: [
26
+ {
27
+ buttonType: 'default',
28
+ content: CHOOSE_WORDS.cancel,
29
+ onClick: () => onPick(undefined),
30
+ },
31
+ {
32
+ buttonType: 'primary',
33
+ content: CHOOSE_WORDS.confirm,
34
+ disabled: !picked,
35
+ onClick: () => onPick(picked || undefined),
36
+ },
37
+ ], children: _jsxs(Box, { display: "grid", gap: 3, "data-session-choose": "", children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: question.title }), _jsx(Select, { value: picked, onChange: event => setPicked(event.target.value), block: true, children: question.options.map(option => (_jsx(Select.Option, { value: option.id, children: option.label }, option.id))) })] }), chosen?.description ? (_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: chosen.description })) : null, says ? (_jsx(Text, { as: "p", sx: { m: 0, fontSize: 1, fontStyle: 'italic' }, "data-session-choose-says": "", children: says })) : null] }) }));
38
+ }
39
+ export default SessionChooseDialog;
@@ -9,8 +9,9 @@
9
9
  */
10
10
  import { CommentDiscussionIcon, FoldIcon, SparkleFillIcon, SyncIcon, } from '@primer/octicons-react';
11
11
  import { contribution, definePlugin } from '@datalayer/reactor';
12
- import { LoopAgentGate, LoopChatComposer, LoopChatExtras, LoopChatHeader, LoopChatSuggestion, LoopChatTurn, LoopCommand, LoopFrontendTool, LoopDocumentToolbarItem, LoopNotebookToolbarItem, LoopViewType, } from '../../core';
12
+ import { LoopAgentGate, LoopChatComposer, LoopChatExtras, LoopChatHeader, LoopChatSuggestion, LoopChatTurn, LoopCommand, LoopFrontendTool, LoopDocumentToolbarItem, LoopNotebookToolbarItem, LoopSessionAction, LoopViewType, } from '../../core';
13
13
  import { createTurnFeed, feedWriters } from './turnState';
14
+ import { CHAT_SESSION_ACTIONS } from './sessionActions';
14
15
  /**
15
16
  * An editor toolbar button that asks an agent to do something.
16
17
  *
@@ -93,6 +94,12 @@ export const ChatPlugin = definePlugin({
93
94
  return {};
94
95
  },
95
96
  contributes: [
97
+ // The thread's menu entries (MH-F08): each says with `when` whether it
98
+ // applies; the chat draws what the registry holds, a host adds its own.
99
+ ...CHAT_SESSION_ACTIONS.map(entry => contribution(LoopSessionAction, entry, {
100
+ id: entry.id,
101
+ order: entry.order,
102
+ })),
96
103
  contribution(LoopViewType, {
97
104
  viewType: 'chat',
98
105
  title: 'Chat',
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The chat's entries on a thread's menu (`loop.session.action`): *Switch
3
+ * agent…*, *Clone from here*, *Export*, *Import…*, *Resume* — each saying
4
+ * with `when` whether it applies to the session as it stands, each doing
5
+ * its work through the runtime's session API and the page's ways (a
6
+ * picker, a file, a download, opening a thread). *Clone from here* is also
7
+ * on each turn's row, where it names the turn. A host adds its own entries
8
+ * by contributing to the same point; nothing here is copied.
9
+ *
10
+ * Every refusal of the runtime is said as it is — a turn still running, a
11
+ * turn the session does not have, a file this runtime does not read, an
12
+ * agent it lacks — and nothing falls back to a default.
13
+ *
14
+ * @module apps/plugins/chat/sessionActions
15
+ */
16
+ import type { SessionActionContext, SessionActionContribution, SessionFacts } from '../../core';
17
+ /** The file a session is exported as. */
18
+ export declare const sessionFileName: (session: Pick<SessionFacts, "uid">) => string;
19
+ /** What the entries say, in a person's words. */
20
+ export declare const SESSION_ACTION_WORDS: {
21
+ readonly switchAgent: "Switch agent…";
22
+ readonly switchTitle: (agent: string) => string;
23
+ readonly noPicker: "Switching the agent needs a picker this page has not: use `loop sessions swap`.";
24
+ readonly noAgents: "No other agent of the catalogue runs on a harness.";
25
+ readonly cloneFromHere: "Clone from here";
26
+ readonly cloned: (atTurn: number, uid: string) => string;
27
+ readonly export: "Export";
28
+ readonly exported: (turns: number, redactions: number, name: string) => string;
29
+ readonly import: "Import…";
30
+ readonly noFilePicker: "Importing a session needs a file picker this page has not: use `loop sessions import`.";
31
+ readonly imported: (uid: string, turns: number, redactions: number) => string;
32
+ readonly resume: "Resume";
33
+ readonly resumed: (uid: string) => string;
34
+ };
35
+ /** One agent a session may be switched to. */
36
+ export type AgentChoice = {
37
+ id: string;
38
+ label: string;
39
+ description?: string;
40
+ };
41
+ /**
42
+ * The agents a session may be switched to: the catalogue's harness agents
43
+ * — each harness offered by the catalogue agent that runs on it, as the
44
+ * Studio's toolbox offers them — the session's own agent left out. A swap
45
+ * may cross kinds (a model agent to a harness and back): what the person
46
+ * chooses among is what the catalogue has.
47
+ */
48
+ export declare function agentChoices(session: Pick<SessionFacts, 'agent'>): AgentChoice[];
49
+ /**
50
+ * What the new agent is told, shown before the swap is sent: the sentence
51
+ * the runtime says on the swap, in its first two clauses; the runtime's own
52
+ * `said` — whose last clause follows what the old harness can load again —
53
+ * is shown once the swap is done.
54
+ */
55
+ export declare function swapSentence(session: Pick<SessionFacts, 'agent' | 'harness' | 'turns'>, to: AgentChoice): string;
56
+ /** The redactions a session file's first line counts. */
57
+ export declare function redactionsOf(text: string): number;
58
+ export declare const SWITCH_AGENT: SessionActionContribution;
59
+ export declare const CLONE_FROM_HERE: SessionActionContribution;
60
+ export declare const EXPORT: SessionActionContribution;
61
+ export declare const IMPORT: SessionActionContribution;
62
+ export declare const RESUME: SessionActionContribution;
63
+ /** The chat's entries, in the order they are drawn. */
64
+ export declare const CHAT_SESSION_ACTIONS: readonly SessionActionContribution[];
65
+ export type { SessionActionContext };
@@ -0,0 +1,184 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ import { listAgentspecs } from '../../../specs/agents';
6
+ import { listHarnesses } from '../../../specs/harnesses';
7
+ /** The file a session is exported as. */
8
+ export const sessionFileName = (session) => `${session.uid}.session.jsonl`;
9
+ /** What the entries say, in a person's words. */
10
+ export const SESSION_ACTION_WORDS = {
11
+ switchAgent: 'Switch agent…',
12
+ switchTitle: (agent) => `Switch ${agent} to`,
13
+ noPicker: 'Switching the agent needs a picker this page has not: use `loop sessions swap`.',
14
+ noAgents: 'No other agent of the catalogue runs on a harness.',
15
+ cloneFromHere: 'Clone from here',
16
+ cloned: (atTurn, uid) => `Cloned from turn ${atTurn} as ${uid}: opened here, the source untouched.`,
17
+ export: 'Export',
18
+ exported: (turns, redactions, name) => `Exported ${turns} turn${turns === 1 ? '' : 's'}, ${redactions} redaction${redactions === 1 ? '' : 's'} → ${name}.`,
19
+ import: 'Import…',
20
+ noFilePicker: 'Importing a session needs a file picker this page has not: use `loop sessions import`.',
21
+ imported: (uid, turns, redactions) => `Imported as ${uid} (${turns} turn${turns === 1 ? '' : 's'}, ${redactions} redaction${redactions === 1 ? '' : 's'}): opened here.`,
22
+ resume: 'Resume',
23
+ resumed: (uid) => `Resumed ${uid}.`,
24
+ };
25
+ /**
26
+ * The agents a session may be switched to: the catalogue's harness agents
27
+ * — each harness offered by the catalogue agent that runs on it, as the
28
+ * Studio's toolbox offers them — the session's own agent left out. A swap
29
+ * may cross kinds (a model agent to a harness and back): what the person
30
+ * chooses among is what the catalogue has.
31
+ */
32
+ export function agentChoices(session) {
33
+ const specs = listAgentspecs();
34
+ return listHarnesses()
35
+ .filter(harness => harness.id !== 'custom' && harness.enabled)
36
+ .flatMap(harness => {
37
+ const agent = specs.find(spec => spec.harness === harness.id);
38
+ if (!agent || agent.id === session.agent) {
39
+ return [];
40
+ }
41
+ return [
42
+ {
43
+ id: agent.id,
44
+ label: `${agent.name} (${harness.name})`,
45
+ description: harness.description,
46
+ },
47
+ ];
48
+ });
49
+ }
50
+ /** A harness's name, or the agent's id when it runs on none. */
51
+ const spokenAs = (agent, harness) => {
52
+ const known = harness
53
+ ? listHarnesses().find(h => h.id === harness)
54
+ : undefined;
55
+ return known?.name ?? (harness || agent);
56
+ };
57
+ /**
58
+ * What the new agent is told, shown before the swap is sent: the sentence
59
+ * the runtime says on the swap, in its first two clauses; the runtime's own
60
+ * `said` — whose last clause follows what the old harness can load again —
61
+ * is shown once the swap is done.
62
+ */
63
+ export function swapSentence(session, to) {
64
+ const from = spokenAs(session.agent, session.harness);
65
+ const target = to.label.replace(/\s*\(.*\)$/, '');
66
+ return `This conversation was with ${from} until turn ${session.turns}; from here it is with ${target}. What was said stays.`;
67
+ }
68
+ /** An open session whose turn is idle: the only one whose agent is swapped. */
69
+ const idle = (session) => session.state === 'open' && session.turn === 'idle';
70
+ /** The redactions a session file's first line counts. */
71
+ export function redactionsOf(text) {
72
+ const head = text.split('\n')[0] ?? '';
73
+ try {
74
+ return Number(JSON.parse(head).redactions ?? 0) || 0;
75
+ }
76
+ catch {
77
+ return 0;
78
+ }
79
+ }
80
+ export const SWITCH_AGENT = {
81
+ id: 'switch-agent',
82
+ label: SESSION_ACTION_WORDS.switchAgent,
83
+ order: 10,
84
+ when: idle,
85
+ run: async (session, context) => {
86
+ if (!context.choose) {
87
+ context.say(SESSION_ACTION_WORDS.noPicker);
88
+ return;
89
+ }
90
+ const options = agentChoices(session);
91
+ if (options.length === 0) {
92
+ context.say(SESSION_ACTION_WORDS.noAgents);
93
+ return;
94
+ }
95
+ const chosen = await context.choose({
96
+ title: SESSION_ACTION_WORDS.switchTitle(session.agent),
97
+ options,
98
+ says: async (id) => {
99
+ const choice = options.find(option => option.id === id);
100
+ return choice ? swapSentence(session, choice) : '';
101
+ },
102
+ });
103
+ if (!chosen) {
104
+ return;
105
+ }
106
+ const answer = await context.client.swap(session.uid, chosen);
107
+ context.say(String(answer.said ?? `Swapped to ${chosen}.`));
108
+ },
109
+ };
110
+ export const CLONE_FROM_HERE = {
111
+ id: 'clone-from-here',
112
+ label: SESSION_ACTION_WORDS.cloneFromHere,
113
+ order: 20,
114
+ placement: 'both',
115
+ when: session => session.turns > 0,
116
+ run: async (session, context) => {
117
+ const upToTurn = context.atTurn ?? session.turns;
118
+ const answer = await context.client.clone(session.uid, { upToTurn });
119
+ const uid = String(answer.uid ?? '');
120
+ if (!uid) {
121
+ throw new Error(`The runtime cloned session ${session.uid} and named no new session.`);
122
+ }
123
+ context.say(SESSION_ACTION_WORDS.cloned(upToTurn, uid));
124
+ context.openThread?.(uid);
125
+ },
126
+ };
127
+ export const EXPORT = {
128
+ id: 'export',
129
+ label: SESSION_ACTION_WORDS.export,
130
+ order: 30,
131
+ when: session => session.turns > 0,
132
+ run: async (session, context) => {
133
+ const text = await context.client.exportFile(session.uid);
134
+ const name = sessionFileName(session);
135
+ context.download?.(name, text, 'application/x-ndjson');
136
+ context.say(SESSION_ACTION_WORDS.exported(session.turns, redactionsOf(text), name));
137
+ },
138
+ };
139
+ export const IMPORT = {
140
+ id: 'import',
141
+ label: SESSION_ACTION_WORDS.import,
142
+ order: 35,
143
+ when: () => true,
144
+ run: async (_session, context) => {
145
+ if (!context.pickFile) {
146
+ context.say(SESSION_ACTION_WORDS.noFilePicker);
147
+ return;
148
+ }
149
+ const text = await context.pickFile('.jsonl,application/x-ndjson');
150
+ if (!text) {
151
+ return;
152
+ }
153
+ const answer = await context.client.importFile(text);
154
+ const uid = String(answer.uid ?? '');
155
+ if (!uid) {
156
+ throw new Error('The runtime imported the file and named no session.');
157
+ }
158
+ context.say(SESSION_ACTION_WORDS.imported(uid, Number(answer.turns ?? 0) || 0, Number(answer.redactions ?? 0) || 0));
159
+ context.openThread?.(uid);
160
+ },
161
+ };
162
+ export const RESUME = {
163
+ id: 'resume',
164
+ label: SESSION_ACTION_WORDS.resume,
165
+ order: 40,
166
+ divider: true,
167
+ when: session => session.state === 'paused',
168
+ run: async (session, context) => {
169
+ await context.client.resume(session.uid, session.agent, {
170
+ onEvent: () => undefined,
171
+ });
172
+ context.say(SESSION_ACTION_WORDS.resumed(session.uid));
173
+ // Drawn again from the runtime, which holds it now.
174
+ context.openThread?.(session.uid);
175
+ },
176
+ };
177
+ /** The chat's entries, in the order they are drawn. */
178
+ export const CHAT_SESSION_ACTIONS = [
179
+ SWITCH_AGENT,
180
+ CLONE_FROM_HERE,
181
+ EXPORT,
182
+ IMPORT,
183
+ RESUME,
184
+ ];
@@ -1,9 +1,49 @@
1
1
  import type { OAuthProvider, OAuthProviderConfig, Identity } from '../identity';
2
- import type { ChatCommonProps, Extension, Protocol, ProtocolConfig } from '../types';
2
+ import type { ChatBaseProps, ChatCommonProps, Extension, Protocol, ProtocolConfig, ResumedThread } from '../types';
3
+ import type { SessionActionContext } from '../apps/core';
4
+ /**
5
+ * What a host lends the thread's `⋯` menu (VSCODE VS-24): the ways an
6
+ * entry may use that only the page has — a file saved, a pick, a file
7
+ * picked — and what it is told. The menu itself is drawn from the
8
+ * `loop.session.action` registry of the Reactor registered on the page
9
+ * (`SessionActionsMenu`, the one the apps' chat view draws): nothing of it
10
+ * is copied here, and no Reactor registered means no menu.
11
+ */
12
+ export interface ChatSessionActions {
13
+ /** Hand the person a file to save, when the host can. */
14
+ download?: SessionActionContext['download'];
15
+ /** Ask the person to pick one of several, when the host can. */
16
+ choose?: SessionActionContext['choose'];
17
+ /** Ask the person for a file, when the host can. */
18
+ pickFile?: SessionActionContext['pickFile'];
19
+ /** Told what an entry said: a swap's sentence, a refusal as the runtime said it. */
20
+ onSaid?: (sentence: string) => void;
21
+ /**
22
+ * Told the thread an entry opened (a clone's, an import's, a resumed
23
+ * one's) — which this chat opens in place too.
24
+ */
25
+ onOpenThread?: (uid: string) => void;
26
+ }
3
27
  /**
4
28
  * Chat props — extends ChatCommonProps with transport-specific configuration.
5
29
  */
6
30
  export interface ChatProps extends ChatCommonProps {
31
+ /**
32
+ * The conversation to go on with (D-13, VS-24): an application's session,
33
+ * read from its runtime by uid when `fromRuntime` is set (`GET
34
+ * …/apps/sessions/{uid}/messages`, else resumed from its record), and
35
+ * drawn in place of the runtime's history. The chat is remounted on
36
+ * another thread's id; a thread that cannot be opened is said, and a
37
+ * new one starts.
38
+ */
39
+ thread?: ResumedThread;
40
+ /**
41
+ * The thread's `⋯` menu, drawn when a Reactor is registered on the page:
42
+ * what the host lends its entries. Absent, no menu is drawn.
43
+ */
44
+ sessionActions?: ChatSessionActions;
45
+ /** Hands the chat's send, stop, new-chat and thread to the host (`ChatBase`'s). */
46
+ onSendReady?: ChatBaseProps['onSendReady'];
7
47
  /**
8
48
  * Transport to use — REQUIRED.
9
49
  *
@@ -119,5 +159,5 @@ export interface ChatProps extends ChatCommonProps {
119
159
  * />
120
160
  * ```
121
161
  */
122
- export declare function Chat({ protocol: transport, extensions: _extensions, baseUrl, endpoint: endpointProp, configEndpoint: configEndpointProp, enableConfigQuery: enableConfigQueryProp, wsUrl, agentId, authToken: authTokenProp, placeholder, title, subtitle, brandIcon, autoConnect, streaming: _streaming, onMessageSent: _onMessageSent, onMessageReceived: _onMessageReceived, onDisconnect, onLogout: _onLogout, onCollapsePanel: _onCollapsePanel, className, height, showHeader, showNewChatButton, showClearButton, showModelSelector, showToolsMenu, showInput, disableInputPrompt, disabled, disableReason, overlay, launching, launchingMessage, showSkillsMenu, codemodeEnabled, onToggleCodemode, showTokenUsage, initialModel, availableModels, mcpServers, initialSkills, clearOnMount: _clearOnMount, suggestions, submitOnSuggestionClick, description, headerContent, headerActions, autoFocus, identityProviders, onIdentityConnect, onIdentityDisconnect, runtimeId, historyEndpoint, pendingPrompt, errorBanner, showInformation, chatViewMode, onChatViewModeChange, frontendTools, enableEphemeralNotebook, initialEphemeralNotebookOpen, onEphemeralNotebookOpenChange, enableEphemeralDocument, initialEphemeralSurfaceMode, onEphemeralSurfaceModeChange, collapsed, onExpandFromCollapsed, ephemeralNotebookToolbar, ephemeralNotebookToolbarExtraItems, ephemeralDocumentToolbarExtraItems, ephemeralNotebookCollaborationProvider, ephemeralNotebookCollaborationDocumentId, ephemeralDocumentCollaboration, ephemeralRuntimeOverride, onToolCallStart, onToolCallComplete, hideMessagesAfterToolUI, contextSnapshot, mcpStatusData, codemodeStatusData, sandboxStatusData, kernel, kernelIndicatorPlacement, kernelEnvironmentName, kernelCpu, kernelMemory, kernelGpu, themeVariant, colorMode, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, disableInternalJupyterTheme, }: ChatProps): import("react").JSX.Element;
162
+ export declare function Chat({ protocol: transport, extensions: _extensions, baseUrl, endpoint: endpointProp, configEndpoint: configEndpointProp, enableConfigQuery: enableConfigQueryProp, wsUrl, agentId, authToken: authTokenProp, placeholder, title, subtitle, brandIcon, autoConnect, streaming: _streaming, onMessageSent: _onMessageSent, onMessageReceived: _onMessageReceived, onDisconnect, onLogout: _onLogout, onCollapsePanel: _onCollapsePanel, className, height, showHeader, showNewChatButton, showClearButton, showModelSelector, showToolsMenu, showInput, disableInputPrompt, disabled, disableReason, overlay, launching, launchingMessage, showSkillsMenu, codemodeEnabled, onToggleCodemode, showTokenUsage, initialModel, availableModels, mcpServers, initialSkills, clearOnMount: _clearOnMount, suggestions, submitOnSuggestionClick, description, headerContent, headerActions, autoFocus, identityProviders, onIdentityConnect, onIdentityDisconnect, runtimeId, historyEndpoint, pendingPrompt, errorBanner, showInformation, chatViewMode, onChatViewModeChange, frontendTools, enableEphemeralNotebook, initialEphemeralNotebookOpen, onEphemeralNotebookOpenChange, enableEphemeralDocument, initialEphemeralSurfaceMode, onEphemeralSurfaceModeChange, collapsed, onExpandFromCollapsed, ephemeralNotebookToolbar, ephemeralNotebookToolbarExtraItems, ephemeralDocumentToolbarExtraItems, ephemeralNotebookCollaborationProvider, ephemeralNotebookCollaborationDocumentId, ephemeralDocumentCollaboration, ephemeralRuntimeOverride, onToolCallStart, onToolCallComplete, hideMessagesAfterToolUI, contextSnapshot, mcpStatusData, codemodeStatusData, sandboxStatusData, kernel, kernelIndicatorPlacement, kernelEnvironmentName, kernelCpu, kernelMemory, kernelGpu, themeVariant, colorMode, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, disableInternalJupyterTheme, thread: givenThread, sessionActions, onSendReady, onToolCallUpdate, }: ChatProps): import("react").JSX.Element;
123
163
  export default Chat;
package/lib/chat/Chat.js CHANGED
@@ -24,8 +24,13 @@ import { Text, Button, Spinner, ThemeProvider } from '@primer/react';
24
24
  import { AlertIcon, SyncIcon } from '@primer/octicons-react';
25
25
  import { Box } from '@datalayer/primer-addons';
26
26
  import { useConnectedIdentities } from '../identity';
27
+ import { useOptionalReactorPlatform } from '@datalayer/reactor/react';
27
28
  import { ChatBase } from './base/ChatBase';
28
29
  import { AgentDetails } from '../agents/AgentDetails';
30
+ import { SessionActionsMenu } from '../apps/plugins/chat/SessionActionsMenu';
31
+ import { appSessionsClient } from '../portable/sessions';
32
+ import { openThread, THREAD_WORDS } from '../portable/thread';
33
+ import { generateMessageId } from '../types/messages';
29
34
  // Try to get Jupyter settings if available
30
35
  let getJupyterSettings;
31
36
  try {
@@ -140,7 +145,7 @@ function getProtocolType(protocol) {
140
145
  * />
141
146
  * ```
142
147
  */
143
- export function Chat({ protocol: transport, extensions: _extensions, baseUrl = 'http://localhost:8765', endpoint: endpointProp, configEndpoint: configEndpointProp, enableConfigQuery: enableConfigQueryProp, wsUrl, agentId, authToken: authTokenProp, placeholder = 'Type your message...', title, subtitle, brandIcon, autoConnect = true, streaming: _streaming = true, onMessageSent: _onMessageSent, onMessageReceived: _onMessageReceived, onDisconnect, onLogout: _onLogout, onCollapsePanel: _onCollapsePanel, className, height = '600px', showHeader = true, showNewChatButton = true, showClearButton = true, showModelSelector = true, showToolsMenu = true, showInput = true, disableInputPrompt = false, disabled, disableReason, overlay, launching = false, launchingMessage, showSkillsMenu = true, codemodeEnabled = false, onToggleCodemode, showTokenUsage = true, initialModel, availableModels, mcpServers, initialSkills, clearOnMount: _clearOnMount = true, suggestions, submitOnSuggestionClick = true, description, headerContent, headerActions, autoFocus = false, identityProviders, onIdentityConnect, onIdentityDisconnect, runtimeId, historyEndpoint, pendingPrompt, errorBanner, showInformation = true, chatViewMode, onChatViewModeChange, frontendTools, enableEphemeralNotebook, initialEphemeralNotebookOpen, onEphemeralNotebookOpenChange, enableEphemeralDocument, initialEphemeralSurfaceMode, onEphemeralSurfaceModeChange, collapsed = false, onExpandFromCollapsed, ephemeralNotebookToolbar, ephemeralNotebookToolbarExtraItems, ephemeralDocumentToolbarExtraItems, ephemeralNotebookCollaborationProvider, ephemeralNotebookCollaborationDocumentId, ephemeralDocumentCollaboration, ephemeralRuntimeOverride, onToolCallStart, onToolCallComplete, hideMessagesAfterToolUI = false, contextSnapshot, mcpStatusData, codemodeStatusData, sandboxStatusData, kernel, kernelIndicatorPlacement, kernelEnvironmentName, kernelCpu, kernelMemory, kernelGpu, themeVariant, colorMode, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, disableInternalJupyterTheme = false, }) {
148
+ export function Chat({ protocol: transport, extensions: _extensions, baseUrl = 'http://localhost:8765', endpoint: endpointProp, configEndpoint: configEndpointProp, enableConfigQuery: enableConfigQueryProp, wsUrl, agentId, authToken: authTokenProp, placeholder = 'Type your message...', title, subtitle, brandIcon, autoConnect = true, streaming: _streaming = true, onMessageSent: _onMessageSent, onMessageReceived: _onMessageReceived, onDisconnect, onLogout: _onLogout, onCollapsePanel: _onCollapsePanel, className, height = '600px', showHeader = true, showNewChatButton = true, showClearButton = true, showModelSelector = true, showToolsMenu = true, showInput = true, disableInputPrompt = false, disabled, disableReason, overlay, launching = false, launchingMessage, showSkillsMenu = true, codemodeEnabled = false, onToggleCodemode, showTokenUsage = true, initialModel, availableModels, mcpServers, initialSkills, clearOnMount: _clearOnMount = true, suggestions, submitOnSuggestionClick = true, description, headerContent, headerActions, autoFocus = false, identityProviders, onIdentityConnect, onIdentityDisconnect, runtimeId, historyEndpoint, pendingPrompt, errorBanner, showInformation = true, chatViewMode, onChatViewModeChange, frontendTools, enableEphemeralNotebook, initialEphemeralNotebookOpen, onEphemeralNotebookOpenChange, enableEphemeralDocument, initialEphemeralSurfaceMode, onEphemeralSurfaceModeChange, collapsed = false, onExpandFromCollapsed, ephemeralNotebookToolbar, ephemeralNotebookToolbarExtraItems, ephemeralDocumentToolbarExtraItems, ephemeralNotebookCollaborationProvider, ephemeralNotebookCollaborationDocumentId, ephemeralDocumentCollaboration, ephemeralRuntimeOverride, onToolCallStart, onToolCallComplete, hideMessagesAfterToolUI = false, contextSnapshot, mcpStatusData, codemodeStatusData, sandboxStatusData, kernel, kernelIndicatorPlacement, kernelEnvironmentName, kernelCpu, kernelMemory, kernelGpu, themeVariant, colorMode, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, disableInternalJupyterTheme = false, thread: givenThread, sessionActions, onSendReady, onToolCallUpdate, }) {
144
149
  const resolvedAgentId = typeof agentId === 'string' && agentId.trim().length > 0
145
150
  ? agentId.trim()
146
151
  : 'default';
@@ -312,6 +317,142 @@ export function Chat({ protocol: transport, extensions: _extensions, baseUrl = '
312
317
  lastMessageCountRef.current = nextCount;
313
318
  setMessageCount(nextCount);
314
319
  }, []);
320
+ /*
321
+ * The thread (VS-24): the host's, or the one a menu entry opened in its
322
+ * place (a clone's, an import's). One read from its runtime is opened
323
+ * here first — held there, else resumed from its record — and drawn in
324
+ * place of the runtime's history; one that cannot be opened is said, and
325
+ * a new one starts.
326
+ */
327
+ const [actionThread, setActionThread] = useState(undefined);
328
+ const wantedThread = actionThread ?? givenThread;
329
+ const [openedThread, setOpenedThread] = useState(null);
330
+ const opening = Boolean(wantedThread?.fromRuntime && openedThread?.given !== wantedThread.id);
331
+ useEffect(() => {
332
+ if (!wantedThread?.fromRuntime) {
333
+ return undefined;
334
+ }
335
+ let current = true;
336
+ void (async () => {
337
+ let failure = '';
338
+ for (let attempt = 0; attempt < 4 && current; attempt += 1) {
339
+ try {
340
+ const messages = await openThread({
341
+ agentBaseUrl: baseUrl,
342
+ agentId: resolvedAgentId,
343
+ uid: wantedThread.id,
344
+ token: authTokenProp,
345
+ });
346
+ if (current) {
347
+ setOpenedThread({
348
+ given: wantedThread.id,
349
+ thread: { ...wantedThread, fromRuntime: false, messages },
350
+ said: '',
351
+ });
352
+ }
353
+ return;
354
+ }
355
+ catch (error) {
356
+ failure = error instanceof Error ? error.message : String(error);
357
+ // The runtime may still be making the application's agent.
358
+ await new Promise(resolve => setTimeout(resolve, 1500));
359
+ }
360
+ }
361
+ if (current) {
362
+ setOpenedThread({
363
+ given: wantedThread.id,
364
+ thread: {
365
+ id: generateMessageId(),
366
+ messages: [],
367
+ onStarted: wantedThread.onStarted,
368
+ },
369
+ said: THREAD_WORDS.notOpened(failure),
370
+ });
371
+ }
372
+ })();
373
+ return () => {
374
+ current = false;
375
+ };
376
+ // By the thread's id: its object is the host's.
377
+ // eslint-disable-next-line react-hooks/exhaustive-deps
378
+ }, [
379
+ wantedThread?.id,
380
+ wantedThread?.fromRuntime,
381
+ baseUrl,
382
+ resolvedAgentId,
383
+ authTokenProp,
384
+ ]);
385
+ const chatThread = wantedThread?.fromRuntime
386
+ ? openedThread?.given === wantedThread.id
387
+ ? openedThread.thread
388
+ : undefined
389
+ : wantedThread;
390
+ const threadSaid = wantedThread?.fromRuntime && openedThread?.given === wantedThread.id
391
+ ? openedThread.said
392
+ : '';
393
+ /*
394
+ * The thread's menu (VS-24): the `loop.session.action` entries of the
395
+ * Reactor registered on the page, for the session the thread is — the
396
+ * uid the next message goes to, as the chat says it (`onSendReady`'s
397
+ * `thread`), kept here so the menu follows the header's +.
398
+ */
399
+ const reactor = useOptionalReactorPlatform();
400
+ const [threadId, setThreadId] = useState(chatThread?.id ?? '');
401
+ const hostSendReadyRef = useRef(onSendReady);
402
+ hostSendReadyRef.current = onSendReady;
403
+ const handleSendReady = useCallback(controls => {
404
+ if (controls) {
405
+ setThreadId(controls.thread());
406
+ }
407
+ hostSendReadyRef.current?.(controls);
408
+ }, []);
409
+ const threadForBase = useMemo(() => chatThread
410
+ ? {
411
+ ...chatThread,
412
+ onStarted: started => {
413
+ setThreadId(started);
414
+ chatThread.onStarted?.(started);
415
+ },
416
+ }
417
+ : undefined, [chatThread]);
418
+ const [actionSaid, setActionSaid] = useState('');
419
+ const sessionsClient = useMemo(() => appSessionsClient({
420
+ baseUrl,
421
+ getAccessToken: () => authTokenProp,
422
+ fetch: (input, init) => fetch(input, init),
423
+ }), [baseUrl, authTokenProp]);
424
+ const sessionActionsRef = useRef(sessionActions);
425
+ sessionActionsRef.current = sessionActions;
426
+ const sessionContext = useMemo(() => ({
427
+ client: sessionsClient,
428
+ say: sentence => {
429
+ setActionSaid(sentence);
430
+ sessionActionsRef.current?.onSaid?.(sentence);
431
+ },
432
+ openThread: uid => {
433
+ setActionThread({ id: uid, messages: [], fromRuntime: true });
434
+ sessionActionsRef.current?.onOpenThread?.(uid);
435
+ },
436
+ ...(sessionActionsRef.current?.download
437
+ ? { download: sessionActionsRef.current.download }
438
+ : {}),
439
+ ...(sessionActionsRef.current?.choose
440
+ ? { choose: sessionActionsRef.current.choose }
441
+ : {}),
442
+ ...(sessionActionsRef.current?.pickFile
443
+ ? { pickFile: sessionActionsRef.current.pickFile }
444
+ : {}),
445
+ }), [sessionsClient]);
446
+ const describeSession = useCallback((uid) => sessionsClient.described(uid), [sessionsClient]);
447
+ const menuDrawn = Boolean(sessionActions && reactor);
448
+ const mergedHeaderActions = useMemo(() => menuDrawn ? (_jsxs(Box, { display: "inline-flex", alignItems: "center", gap: 2, children: [headerActions, _jsx(SessionActionsMenu, { uid: threadId || chatThread?.id || undefined, describe: describeSession, context: sessionContext })] })) : (headerActions), [
449
+ menuDrawn,
450
+ headerActions,
451
+ threadId,
452
+ chatThread?.id,
453
+ describeSession,
454
+ sessionContext,
455
+ ]);
315
456
  const headerButtons = useMemo(() => ({
316
457
  showNewChat: showNewChatButton,
317
458
  showClear: showClearButton,
@@ -338,6 +479,11 @@ export function Chat({ protocol: transport, extensions: _extensions, baseUrl = '
338
479
  ? 'attention.fg'
339
480
  : 'danger.fg',
340
481
  flex: 1,
341
- }, children: errorBanner.message })] })), _jsx(ChatBase, { title: title, subtitle: subtitle, brandIcon: brandIcon, showHeader: showHeader, protocol: protocolConfig, placeholder: placeholder, description: description, suggestions: suggestions, submitOnSuggestionClick: submitOnSuggestionClick, autoFocus: autoFocus, runtimeId: runtimeId, historyEndpoint: historyEndpoint, pendingPrompt: pendingPrompt, showInformation: showInformation, onInformationClick: handleInformationClick, headerContent: headerContent, headerActions: headerActions, showModelSelector: showModelSelector, showToolsMenu: showToolsMenu, showInput: showInput, disableInputPrompt: disableInputPrompt, disabled: disabled, disableReason: disableReason, overlay: overlay, launching: launching, launchingMessage: launchingMessage, autoConnect: autoConnect, showSkillsMenu: showSkillsMenu, showTokenUsage: showTokenUsage, codemodeEnabled: codemodeEnabled, onToggleCodemode: onToggleCodemode, initialModel: initialModel, availableModels: availableModels, mcpServers: mcpServers, initialSkills: initialSkills, connectedIdentities: identitiesForChat, onNewChat: handleNewChat, onMessagesChange: handleMessagesChange, headerButtons: headerButtons, avatarConfig: avatarConfig, backgroundColor: "canvas.default", focusTrigger: focusTrigger, chatViewMode: chatViewMode, onChatViewModeChange: onChatViewModeChange, frontendTools: frontendTools, enableEphemeralNotebook: enableEphemeralNotebook, initialEphemeralNotebookOpen: initialEphemeralNotebookOpen, onEphemeralNotebookOpenChange: onEphemeralNotebookOpenChange, enableEphemeralDocument: enableEphemeralDocument, initialEphemeralSurfaceMode: initialEphemeralSurfaceMode, onEphemeralSurfaceModeChange: onEphemeralSurfaceModeChange, collapsed: collapsed, onExpandFromCollapsed: onExpandFromCollapsed, ephemeralNotebookToolbar: ephemeralNotebookToolbar, ephemeralNotebookToolbarExtraItems: ephemeralNotebookToolbarExtraItems, ephemeralDocumentToolbarExtraItems: ephemeralDocumentToolbarExtraItems, ephemeralNotebookCollaborationProvider: ephemeralNotebookCollaborationProvider, ephemeralNotebookCollaborationDocumentId: ephemeralNotebookCollaborationDocumentId, ephemeralDocumentCollaboration: ephemeralDocumentCollaboration, ephemeralRuntimeOverride: ephemeralRuntimeOverride, onToolCallStart: onToolCallStart, onToolCallComplete: onToolCallComplete, hideMessagesAfterToolUI: hideMessagesAfterToolUI, contextSnapshot: contextSnapshot, mcpStatusData: mcpStatusData, sandboxStatusData: sandboxStatusData, kernel: kernel, kernelIndicatorPlacement: kernelIndicatorPlacement, kernelEnvironmentName: kernelEnvironmentName, kernelCpu: kernelCpu, kernelMemory: kernelMemory, kernelGpu: kernelGpu, themeVariant: themeVariant, colorMode: colorMode, showToolApprovalBanner: showToolApprovalBanner, pendingApprovals: pendingApprovals, onApproveApproval: onApproveApproval, onRejectApproval: onRejectApproval, disableInternalJupyterTheme: disableInternalJupyterTheme })] })] }) }) }));
482
+ }, children: errorBanner.message })] })), threadSaid || actionSaid ? (
483
+ // What opening the thread, or a menu entry, said: a refusal
484
+ // as the runtime said it, a swap's sentence — until dismissed.
485
+ _jsxs(Box, { display: "flex", alignItems: "center", gap: 2, px: 3, py: 2, bg: "attention.subtle", borderBottom: "1px solid", borderColor: "attention.muted", "data-testid": "chat-thread-said", children: [_jsx(Text, { sx: { fontSize: 1, color: 'attention.fg', flex: 1 }, children: actionSaid || threadSaid }), _jsx(Button, { size: "small", variant: "invisible", onClick: () => setActionSaid(''), children: "Dismiss" })] })) : null, opening ? (_jsx(Text, { as: "p", role: "status", sx: { m: 0, p: 3, fontSize: 1, color: 'fg.muted' }, children: THREAD_WORDS.opening })) : (_jsx(ChatBase
486
+ // Another thread is another conversation: remounted on its id.
487
+ , { thread: threadForBase, onSendReady: handleSendReady, onToolCallUpdate: onToolCallUpdate, title: title, subtitle: subtitle, brandIcon: brandIcon, showHeader: showHeader, protocol: protocolConfig, placeholder: placeholder, description: description, suggestions: suggestions, submitOnSuggestionClick: submitOnSuggestionClick, autoFocus: autoFocus, runtimeId: runtimeId, historyEndpoint: historyEndpoint, pendingPrompt: pendingPrompt, showInformation: showInformation, onInformationClick: handleInformationClick, headerContent: headerContent, headerActions: mergedHeaderActions, showModelSelector: showModelSelector, showToolsMenu: showToolsMenu, showInput: showInput, disableInputPrompt: disableInputPrompt, disabled: disabled, disableReason: disableReason, overlay: overlay, launching: launching, launchingMessage: launchingMessage, autoConnect: autoConnect, showSkillsMenu: showSkillsMenu, showTokenUsage: showTokenUsage, codemodeEnabled: codemodeEnabled, onToggleCodemode: onToggleCodemode, initialModel: initialModel, availableModels: availableModels, mcpServers: mcpServers, initialSkills: initialSkills, connectedIdentities: identitiesForChat, onNewChat: handleNewChat, onMessagesChange: handleMessagesChange, headerButtons: headerButtons, avatarConfig: avatarConfig, backgroundColor: "canvas.default", focusTrigger: focusTrigger, chatViewMode: chatViewMode, onChatViewModeChange: onChatViewModeChange, frontendTools: frontendTools, enableEphemeralNotebook: enableEphemeralNotebook, initialEphemeralNotebookOpen: initialEphemeralNotebookOpen, onEphemeralNotebookOpenChange: onEphemeralNotebookOpenChange, enableEphemeralDocument: enableEphemeralDocument, initialEphemeralSurfaceMode: initialEphemeralSurfaceMode, onEphemeralSurfaceModeChange: onEphemeralSurfaceModeChange, collapsed: collapsed, onExpandFromCollapsed: onExpandFromCollapsed, ephemeralNotebookToolbar: ephemeralNotebookToolbar, ephemeralNotebookToolbarExtraItems: ephemeralNotebookToolbarExtraItems, ephemeralDocumentToolbarExtraItems: ephemeralDocumentToolbarExtraItems, ephemeralNotebookCollaborationProvider: ephemeralNotebookCollaborationProvider, ephemeralNotebookCollaborationDocumentId: ephemeralNotebookCollaborationDocumentId, ephemeralDocumentCollaboration: ephemeralDocumentCollaboration, ephemeralRuntimeOverride: ephemeralRuntimeOverride, onToolCallStart: onToolCallStart, onToolCallComplete: onToolCallComplete, hideMessagesAfterToolUI: hideMessagesAfterToolUI, contextSnapshot: contextSnapshot, mcpStatusData: mcpStatusData, sandboxStatusData: sandboxStatusData, kernel: kernel, kernelIndicatorPlacement: kernelIndicatorPlacement, kernelEnvironmentName: kernelEnvironmentName, kernelCpu: kernelCpu, kernelMemory: kernelMemory, kernelGpu: kernelGpu, themeVariant: themeVariant, colorMode: colorMode, showToolApprovalBanner: showToolApprovalBanner, pendingApprovals: pendingApprovals, onApproveApproval: onApproveApproval, onRejectApproval: onRejectApproval, disableInternalJupyterTheme: disableInternalJupyterTheme }, chatThread?.id ?? 'own'))] })] }) }) }));
342
488
  }
343
489
  export default Chat;
@@ -37,7 +37,7 @@ import { extractChatMessagesFromFullContext } from './fullContextMessages';
37
37
  import { generateMessageId, createUserMessage } from '../../types/messages';
38
38
  import { AI_MODEL_CATALOGUE, DEFAULT_MODEL, isChatModel, } from '../../specs/models';
39
39
  import { internalQueryClient, isToolCallMessage, getMessageText, createProtocolAdapter, getApiBaseFromConfig, sanitizeAssistantContent, } from '../../utils';
40
- import { BROWSER_LIMITS, emptyConversation, reduceConversation, withError, withoutItems, withPrompt, withTurnEnded, } from '../../portable/conversation';
40
+ import { BROWSER_LIMITS, emptyConversation, HARNESS_TOOL_CALL, reduceConversation, withError, withoutItems, withPrompt, withTurnEnded, } from '../../portable/conversation';
41
41
  import { conversationEventsOf, snapshotOfMessages, } from '../../portable/adapterEvents';
42
42
  import { conversationDrawer, emptyChatLayer, rowIdOf, toolCallOf, } from './conversationItems';
43
43
  import { useConfig, useSkills, useSkillActions, useContextSnapshot, useSandbox, } from '../../hooks';
@@ -426,9 +426,9 @@ function ChatBaseInner({ title, subtitle, showHeader = false, showTokenUsage = t
426
426
  // Mode selection
427
427
  useStore: useStoreMode = true, protocol: protocolRaw, onSendMessage, onSendReady, onLoadingChange, onSpeakingChange, onContextSnapshot, enableStreaming = false,
428
428
  // Extended props
429
- brandIcon, avatarConfig, headerButtons, showPoweredBy = false, poweredByProps, emptyState, renderHeader, showTurnFooter = true, notebookToolSurfacesId, footerContent, welcome, trailingContent, voice, voiceSpeaking = false, voiceSentence, onStopSpeaking, voiceLevel, onReadAloud, showInformation = false, onInformationClick, headerContent, children, borderRadius, backgroundColor, border, boxShadow, compact = false, placeholder, description = 'Start a conversation with the AI agent.', onStateUpdate, onNewChat, onClear, onMessagesChange, onItemsChange, onDisplayItemsChange, autoFocus = false, suggestions, submitOnSuggestionClick = true, hideMessagesAfterToolUI = false, focusTrigger, frontendTools: frontendToolsProp, enableEphemeralNotebook = false, initialEphemeralNotebookOpen = true, onEphemeralNotebookOpenChange, enableEphemeralDocument = false, initialEphemeralSurfaceMode, onEphemeralSurfaceModeChange, collapsed = false, onExpandFromCollapsed, ephemeralNotebookToolbar, ephemeralNotebookToolbarExtraItems, ephemeralDocumentToolbarExtraItems, ephemeralNotebookCollaborationProvider, ephemeralNotebookCollaborationDocumentId, ephemeralDocumentCollaboration, ephemeralRuntimeOverride,
429
+ brandIcon, avatarConfig, headerButtons, showPoweredBy = false, poweredByProps, emptyState, renderHeader, showTurnFooter = true, renderMessageFooter, notebookToolSurfacesId, footerContent, welcome, trailingContent, voice, voiceSpeaking = false, voiceSentence, onStopSpeaking, voiceLevel, onReadAloud, showInformation = false, onInformationClick, headerContent, children, borderRadius, backgroundColor, border, boxShadow, compact = false, placeholder, description = 'Start a conversation with the AI agent.', onStateUpdate, onNewChat, onClear, onMessagesChange, onItemsChange, onDisplayItemsChange, autoFocus = false, suggestions, submitOnSuggestionClick = true, hideMessagesAfterToolUI = false, focusTrigger, frontendTools: frontendToolsProp, enableEphemeralNotebook = false, initialEphemeralNotebookOpen = true, onEphemeralNotebookOpenChange, enableEphemeralDocument = false, initialEphemeralSurfaceMode, onEphemeralSurfaceModeChange, collapsed = false, onExpandFromCollapsed, ephemeralNotebookToolbar, ephemeralNotebookToolbarExtraItems, ephemeralDocumentToolbarExtraItems, ephemeralNotebookCollaborationProvider, ephemeralNotebookCollaborationDocumentId, ephemeralDocumentCollaboration, ephemeralRuntimeOverride,
430
430
  // Tool invocation hooks
431
- onToolCallStart, onToolCallComplete, inspector: inspectorGiven,
431
+ onToolCallStart, onToolCallComplete, onToolCallUpdate, inspector: inspectorGiven,
432
432
  // Identity/Authorization props
433
433
  onAuthorizationRequired: _onAuthorizationRequired, connectedIdentities,
434
434
  // Conversation persistence
@@ -1803,6 +1803,8 @@ showToolApprovalBanner = true, pendingApprovals: pendingApprovalsProp, onApprove
1803
1803
  onToolCallStartRef.current = onToolCallStart;
1804
1804
  const onToolCallCompleteRef = useRef(onToolCallComplete);
1805
1805
  onToolCallCompleteRef.current = onToolCallComplete;
1806
+ const onToolCallUpdateRef = useRef(onToolCallUpdate);
1807
+ onToolCallUpdateRef.current = onToolCallUpdate;
1806
1808
  // The Agent Inspector: the turns and tool calls, as spans, as they happen.
1807
1809
  const inspectorFromContext = useAgentInspectorTracer();
1808
1810
  const inspectorTracer = inspectorGiven ?? inspectorFromContext;
@@ -2810,6 +2812,24 @@ showToolApprovalBanner = true, pendingApprovals: pendingApprovalsProp, onApprove
2810
2812
  voiceSayRef.current?.(event.activity);
2811
2813
  }
2812
2814
  read();
2815
+ // A running row said again with its display (VS-24): the host
2816
+ // drawing it elsewhere follows it as it streams.
2817
+ if (event.activity?.type === HARNESS_TOOL_CALL &&
2818
+ onToolCallUpdateRef.current) {
2819
+ const data = event.activity.data;
2820
+ const toolCallId = data && typeof data === 'object' && 'id' in data
2821
+ ? String(data.id ?? '')
2822
+ : '';
2823
+ const row = conversationRef.current.items.find(item => item.kind === 'tool' && item.id === toolCallId);
2824
+ if (row && row.kind === 'tool' && row.display) {
2825
+ onToolCallUpdateRef.current({
2826
+ toolName: row.name,
2827
+ toolCallId,
2828
+ args: row.input ?? {},
2829
+ display: row.display,
2830
+ });
2831
+ }
2832
+ }
2813
2833
  break;
2814
2834
  case 'done':
2815
2835
  /*
@@ -3808,10 +3828,17 @@ showToolApprovalBanner = true, pendingApprovals: pendingApprovalsProp, onApprove
3808
3828
  .reverse()
3809
3829
  .find((item) => !isToolCallMessage(item) && item.role === 'assistant')?.id
3810
3830
  : undefined;
3811
- const readAloudFooter = readAnswerAloud || interruptedIds.size
3812
- ? (message) => {
3831
+ const readAloudFooter = readAnswerAloud || interruptedIds.size || renderMessageFooter
3832
+ ? (message, at) => {
3813
3833
  const text = getMessageText(message);
3814
- return (_jsxs(_Fragment, { children: [interruptedIds.has(message.id) ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontStyle: 'italic' }, "data-interrupted": "", children: "interrupted" })) : null, readAnswerAloud && readsAloud(message, text, writingId) ? (_jsx(ReadAloud, { onRead: () => readAnswerAloud(text) })) : null] }));
3834
+ // The host's row, asked once: nothing when it draws nothing.
3835
+ const hosts = renderMessageFooter?.(message, at) ?? null;
3836
+ const interrupted = interruptedIds.has(message.id);
3837
+ const reads = Boolean(readAnswerAloud && readsAloud(message, text, writingId));
3838
+ if (!hosts && !interrupted && !reads) {
3839
+ return null;
3840
+ }
3841
+ return (_jsxs(_Fragment, { children: [interrupted ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontStyle: 'italic' }, "data-interrupted": "", children: "interrupted" })) : null, reads && readAnswerAloud ? (_jsx(ReadAloud, { onRead: () => readAnswerAloud(text) })) : null, hosts] }));
3815
3842
  }
3816
3843
  : undefined;
3817
3844
  const messagesContent = children ? (children) : (_jsxs(Box, { ref: saidConversationRef, display: "flex", flexDirection: "column", minHeight: 0,