@datalayer/agent-runtimes 1.3.114 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/dist-embed/chunks/ChatView-CaBuPTyG.js +32 -0
  2. package/dist-embed/chunks/{DeckComponent-CuRWiARr.js → DeckComponent-cRJJMGgt.js} +1 -1
  3. package/dist-embed/chunks/{DocumentView-BYU2HREd.js → DocumentView-CiqN9ze6.js} +1 -1
  4. package/dist-embed/chunks/{EphemeralDocument-BjFSuQKH.js → EphemeralDocument-BjJfn7J-.js} +1 -1
  5. package/dist-embed/chunks/{ExcalidrawComponent-CFLnMPnf.js → ExcalidrawComponent-BtNXWUN8.js} +1 -1
  6. package/dist-embed/chunks/{ExcalidrawModal-CB9d5Vpk.js → ExcalidrawModal-C6SEKFlD.js} +1 -1
  7. package/dist-embed/chunks/{JupyterLexicalExtension-CYnZrelh.js → JupyterLexicalExtension-BuRLImy5.js} +5 -5
  8. package/dist-embed/chunks/{NotebookToolSurfaces-D62q-lbb.js → NotebookToolSurfaces-ktcGRm7d.js} +1 -1
  9. package/dist-embed/chunks/{Output-2KxoKu5F.js → Output-BscOPLqE.js} +10 -10
  10. package/dist-embed/chunks/{YouTubePlugin-CjODyxZ2.js → YouTubePlugin-xBjNr2Iu.js} +1 -1
  11. package/dist-embed/chunks/{ar-SA-G6X2FPQ2-C-zAYgA-.js → ar-SA-G6X2FPQ2-BB82iKLz.js} +1 -1
  12. package/dist-embed/chunks/{az-AZ-76LH7QW2-BHq5js6U.js → az-AZ-76LH7QW2-DsMRKXlw.js} +1 -1
  13. package/dist-embed/chunks/{bg-BG-XCXSNQG7-BTcNNcTc.js → bg-BG-XCXSNQG7-43Y1kPxa.js} +1 -1
  14. package/dist-embed/chunks/{bn-BD-2XOGV67Q-DXRk27u1.js → bn-BD-2XOGV67Q-CLqPJBll.js} +1 -1
  15. package/dist-embed/chunks/{ca-ES-6MX7JW3Y-D-0J9rqp.js → ca-ES-6MX7JW3Y-CDFGSEh3.js} +1 -1
  16. package/dist-embed/chunks/{cs-CZ-2BRQDIVT-CgN3I-57.js → cs-CZ-2BRQDIVT-ByNB8eZd.js} +1 -1
  17. package/dist-embed/chunks/{da-DK-5WZEPLOC-CHQloSoX.js → da-DK-5WZEPLOC-B7MrVwy8.js} +1 -1
  18. package/dist-embed/chunks/{de-DE-XR44H4JA-C-Hq84pe.js → de-DE-XR44H4JA-CN1cdk94.js} +1 -1
  19. package/dist-embed/chunks/{el-GR-BZB4AONW-MTzGcSsP.js → el-GR-BZB4AONW-DnaGhWD1.js} +1 -1
  20. package/dist-embed/chunks/{es-ES-U4NZUMDT-Thj-4Rwn.js → es-ES-U4NZUMDT-DE1vZzDE.js} +1 -1
  21. package/dist-embed/chunks/{eu-ES-A7QVB2H4-BEEyNQo-.js → eu-ES-A7QVB2H4-DmHB0zpm.js} +1 -1
  22. package/dist-embed/chunks/{fa-IR-HGAKTJCU-CtUGmNBZ.js → fa-IR-HGAKTJCU-CNzE8tJj.js} +1 -1
  23. package/dist-embed/chunks/{fi-FI-Z5N7JZ37-6GMgpkSu.js → fi-FI-Z5N7JZ37-Ca2vTFQC.js} +1 -1
  24. package/dist-embed/chunks/{fr-FR-RHASNOE6-BakNCbxj.js → fr-FR-RHASNOE6-B0yWFX3_.js} +1 -1
  25. package/dist-embed/chunks/{gl-ES-HMX3MZ6V-Cwkb9OPk.js → gl-ES-HMX3MZ6V-2_3FMVJq.js} +1 -1
  26. package/dist-embed/chunks/{he-IL-6SHJWFNN-BaMmvCkr.js → he-IL-6SHJWFNN-BW1lby00.js} +1 -1
  27. package/dist-embed/chunks/{hi-IN-IWLTKZ5I-1aWewhep.js → hi-IN-IWLTKZ5I-DTixfSwB.js} +1 -1
  28. package/dist-embed/chunks/{hu-HU-A5ZG7DT2-BIHI23BQ.js → hu-HU-A5ZG7DT2-DOfYwLWP.js} +1 -1
  29. package/dist-embed/chunks/{id-ID-SAP4L64H-CYpgmx8X.js → id-ID-SAP4L64H-Cwtdtkvg.js} +1 -1
  30. package/dist-embed/chunks/{index-BhSMzuKq.js → index--qMT5k1q.js} +1 -1
  31. package/dist-embed/chunks/{index-b1yzCiTq.js → index-B-UP9DlM.js} +1 -1
  32. package/dist-embed/chunks/{index-DMKsCn-y.js → index-BAwsCLGT.js} +1 -1
  33. package/dist-embed/chunks/{index-BUhqZVtg.js → index-BITOMOWN.js} +1 -1
  34. package/dist-embed/chunks/{index-1wTrAXI1.js → index-B_9UD0bt.js} +2 -2
  35. package/dist-embed/chunks/{index-DtlUttQj.js → index-BgFbP5P0.js} +1 -1
  36. package/dist-embed/chunks/{index-CC-Ht79i.js → index-CMUTS_sA.js} +1 -1
  37. package/dist-embed/chunks/{index-B7nmHsEo.js → index-Cgf7tlW3.js} +1 -1
  38. package/dist-embed/chunks/{index-CsZ2HycN.js → index-CrNfUmIU.js} +1 -1
  39. package/dist-embed/chunks/{index-DIOcQUrz.js → index-CzuLxFBK.js} +1 -1
  40. package/dist-embed/chunks/{index-EmZm7_bH.js → index-DEn5R18M.js} +1 -1
  41. package/dist-embed/chunks/{index-DeVZ-nmF.js → index-DFEBhySA.js} +1 -1
  42. package/dist-embed/chunks/{index-CMYyiALV.js → index-DYkwi0aX.js} +1 -1
  43. package/dist-embed/chunks/{index-Fzz2KjFM.js → index-DvpdAlVH.js} +1 -1
  44. package/dist-embed/chunks/{index-W7TVoWP5.js → index-Dyh5xopp.js} +1 -1
  45. package/dist-embed/chunks/{index-en9Yf1Yz.js → index-Jt4bWLoz.js} +1 -1
  46. package/dist-embed/chunks/{index-BbucLMre.js → index-S-sjhoD3.js} +1 -1
  47. package/dist-embed/chunks/{index-D18sf241.js → index-TRLGqZaF.js} +1 -1
  48. package/dist-embed/chunks/{index-ZZnjmFwm.js → index-YcqCoWJl.js} +1 -1
  49. package/dist-embed/chunks/{index-BFLtEBuP.js → index-sQy5cmWo.js} +1 -1
  50. package/dist-embed/chunks/{it-IT-JPQ66NNP-CLcqplyX.js → it-IT-JPQ66NNP-C3xZ61-6.js} +1 -1
  51. package/dist-embed/chunks/{ja-JP-DBVTYXUO-u8Qe6tR7.js → ja-JP-DBVTYXUO-CeTmglEb.js} +1 -1
  52. package/dist-embed/chunks/{kaa-6HZHGXH3-BG2kx50I.js → kaa-6HZHGXH3-D6Jr6B6Y.js} +1 -1
  53. package/dist-embed/chunks/{kab-KAB-ZGHBKWFO-CSYUpRxd.js → kab-KAB-ZGHBKWFO-pEXBqeuG.js} +1 -1
  54. package/dist-embed/chunks/{kk-KZ-P5N5QNE5-CpBMgHAz.js → kk-KZ-P5N5QNE5-BRJunmHm.js} +1 -1
  55. package/dist-embed/chunks/{km-KH-HSX4SM5Z-CoMUUQMb.js → km-KH-HSX4SM5Z--GJgT9rN.js} +1 -1
  56. package/dist-embed/chunks/{ko-KR-MTYHY66A-DwxY8CGI.js → ko-KR-MTYHY66A-Bjnez4qR.js} +1 -1
  57. package/dist-embed/chunks/{ku-TR-6OUDTVRD-UoNYUfm0.js → ku-TR-6OUDTVRD-DgOdYJrS.js} +1 -1
  58. package/dist-embed/chunks/{lt-LT-XHIRWOB4-Dr4uXaEj.js → lt-LT-XHIRWOB4-BMwhrtjM.js} +1 -1
  59. package/dist-embed/chunks/{lv-LV-5QDEKY6T-CNC56J-_.js → lv-LV-5QDEKY6T-0pxW7YE0.js} +1 -1
  60. package/dist-embed/chunks/{mr-IN-CRQNXWMA-BKWa9nzZ.js → mr-IN-CRQNXWMA-tndp8BXC.js} +1 -1
  61. package/dist-embed/chunks/{my-MM-5M5IBNSE-bwAzOWhV.js → my-MM-5M5IBNSE-sispDhO4.js} +1 -1
  62. package/dist-embed/chunks/{nb-NO-T6EIAALU-CkpsChor.js → nb-NO-T6EIAALU-CjBurOuS.js} +1 -1
  63. package/dist-embed/chunks/{nl-NL-IS3SIHDZ-COVk4rlb.js → nl-NL-IS3SIHDZ-B58EVmr3.js} +1 -1
  64. package/dist-embed/chunks/{nn-NO-6E72VCQL-DlyFF-C1.js → nn-NO-6E72VCQL-D1p7LZSq.js} +1 -1
  65. package/dist-embed/chunks/{oc-FR-POXYY2M6-CFDosV2C.js → oc-FR-POXYY2M6-C1M8sddP.js} +1 -1
  66. package/dist-embed/chunks/{pa-IN-N4M65BXN-BKRB3O0U.js → pa-IN-N4M65BXN-D8ESzASl.js} +1 -1
  67. package/dist-embed/chunks/{percentages-BXMCSKIN-D7pnqUsZ.js → percentages-BXMCSKIN-BihMTsFR.js} +3 -3
  68. package/dist-embed/chunks/{pl-PL-T2D74RX3-C5r2Tds7.js → pl-PL-T2D74RX3-DQGe6LHC.js} +1 -1
  69. package/dist-embed/chunks/{pt-BR-5N22H2LF-CDnT98bW.js → pt-BR-5N22H2LF-CvXBgZQs.js} +1 -1
  70. package/dist-embed/chunks/{pt-PT-UZXXM6DQ-C6c4SPk1.js → pt-PT-UZXXM6DQ-BMnnlIUJ.js} +1 -1
  71. package/dist-embed/chunks/{ro-RO-JPDTUUEW-CW6pbzEZ.js → ro-RO-JPDTUUEW-DZ-9UUH7.js} +1 -1
  72. package/dist-embed/chunks/{ru-RU-B4JR7IUQ-CbaAJG0w.js → ru-RU-B4JR7IUQ-JlRBwjob.js} +1 -1
  73. package/dist-embed/chunks/{si-LK-N5RQ5JYF-BZkUjpXF.js → si-LK-N5RQ5JYF-Bx8kHnkd.js} +1 -1
  74. package/dist-embed/chunks/{sk-SK-C5VTKIMK-DsfWgpPU.js → sk-SK-C5VTKIMK-xsfEfbZb.js} +1 -1
  75. package/dist-embed/chunks/{sl-SI-NN7IZMDC-Kx0FqxKU.js → sl-SI-NN7IZMDC-SQYUECnr.js} +1 -1
  76. package/dist-embed/chunks/{subset-shared.chunk-DM3l9OuH.js → subset-shared.chunk-Ch6j8nKC.js} +1 -1
  77. package/dist-embed/chunks/{subset-worker.chunk-4w4yibm3.js → subset-worker.chunk-pJjck5pR.js} +1 -1
  78. package/dist-embed/chunks/{sv-SE-XGPEYMSR-DY0ryO-L.js → sv-SE-XGPEYMSR-BxcjSHE2.js} +1 -1
  79. package/dist-embed/chunks/{ta-IN-2NMHFXQM-CWpIs0i0.js → ta-IN-2NMHFXQM-rItSkDUS.js} +1 -1
  80. package/dist-embed/chunks/{th-TH-HPSO5L25-Cwkcfb3u.js → th-TH-HPSO5L25-B7UzESFj.js} +1 -1
  81. package/dist-embed/chunks/{tr-TR-DEFEU3FU-BqJZZl-Y.js → tr-TR-DEFEU3FU-Ci6oNfEX.js} +1 -1
  82. package/dist-embed/chunks/{uk-UA-QMV73CPH-Dg213mG4.js → uk-UA-QMV73CPH-C9csqvO6.js} +1 -1
  83. package/dist-embed/chunks/{vi-VN-M7AON7JQ-DY94NKxF.js → vi-VN-M7AON7JQ-DRAj2kZj.js} +1 -1
  84. package/dist-embed/chunks/{zh-CN-LNUGB5OW-B6I9A7sA.js → zh-CN-LNUGB5OW-DLOyW8hH.js} +1 -1
  85. package/dist-embed/chunks/{zh-HK-E62DVLB3-D3oqgDOt.js → zh-HK-E62DVLB3-DwC6_2Ws.js} +1 -1
  86. package/dist-embed/chunks/{zh-TW-RAJ6MFWO-CYwgY0Jo.js → zh-TW-RAJ6MFWO-DEMugIwa.js} +1 -1
  87. package/dist-embed/datalayer-app-main.js +156 -156
  88. package/lib/apps/apps/appspec.d.ts +13 -0
  89. package/lib/apps/apps/appspec.js +93 -0
  90. package/lib/apps/apps/checks.d.ts +1 -1
  91. package/lib/apps/apps/checks.js +2 -2
  92. package/lib/apps/apps/customComponents.js +1 -1
  93. package/lib/apps/core/canvasBlocks.d.ts +3 -3
  94. package/lib/apps/core/canvasParts.d.ts +6 -4
  95. package/lib/apps/core/index.d.ts +8 -0
  96. package/lib/apps/embed/AppEmbed.js +13 -20
  97. package/lib/apps/embed/embedSession.d.ts +8 -4
  98. package/lib/apps/embed/embedSession.js +16 -9
  99. package/lib/apps/embed/hostBridge.d.ts +47 -13
  100. package/lib/apps/embed/hostBridge.js +135 -18
  101. package/lib/apps/index.d.ts +1 -1
  102. package/lib/apps/index.js +1 -1
  103. package/lib/apps/plugins/a2ui-surface/AnswerShows.d.ts +21 -0
  104. package/lib/apps/plugins/a2ui-surface/AnswerShows.js +29 -0
  105. package/lib/apps/plugins/a2ui-surface/SurfaceToolResult.js +4 -7
  106. package/lib/apps/plugins/a2ui-surface/index.d.ts +2 -1
  107. package/lib/apps/plugins/a2ui-surface/index.js +10 -1
  108. package/lib/apps/plugins/a2ui-surface/toolResult.d.ts +20 -11
  109. package/lib/apps/plugins/a2ui-surface/toolResult.js +27 -11
  110. package/lib/apps/plugins/app-components/index.d.ts +1 -1
  111. package/lib/apps/plugins/app-components/index.js +2 -2
  112. package/lib/apps/plugins/app-elements/AppElements.d.ts +3 -3
  113. package/lib/apps/plugins/app-elements/AppElements.js +5 -20
  114. package/lib/apps/plugins/app-elements/QuestionView.d.ts +30 -0
  115. package/lib/apps/plugins/app-elements/QuestionView.js +70 -0
  116. package/lib/apps/plugins/app-elements/index.d.ts +7 -4
  117. package/lib/apps/plugins/app-elements/index.js +14 -5
  118. package/lib/apps/plugins/app-page/appPageModel.d.ts +6 -8
  119. package/lib/apps/plugins/app-page/appPageModel.js +0 -2
  120. package/lib/apps/plugins/app-page/pageRun.d.ts +2 -2
  121. package/lib/apps/plugins/app-page/pageRun.js +3 -3
  122. package/lib/apps/plugins/canvas-blocks/index.d.ts +13 -13
  123. package/lib/apps/plugins/canvas-blocks/index.js +24 -24
  124. package/lib/apps/plugins/canvas-parts/index.d.ts +7 -1
  125. package/lib/apps/plugins/canvas-parts/index.js +36 -0
  126. package/lib/apps/plugins/chat/ChatView.js +29 -3
  127. package/lib/chat/base/ChatBase.js +264 -43
  128. package/lib/chat/base/loopElement.d.ts +16 -17
  129. package/lib/chat/base/loopElement.js +11 -27
  130. package/lib/chat/base/loopStep.d.ts +15 -15
  131. package/lib/chat/base/loopStep.js +10 -13
  132. package/lib/chat/base/loopWindow.d.ts +15 -20
  133. package/lib/chat/base/loopWindow.js +26 -27
  134. package/lib/chat/base/uiFiles.d.ts +29 -0
  135. package/lib/chat/base/uiFiles.js +69 -0
  136. package/lib/chat/base/uiOps.d.ts +96 -0
  137. package/lib/chat/base/uiOps.js +251 -0
  138. package/lib/chat/messages/ChatMessageList.d.ts +13 -1
  139. package/lib/chat/messages/ChatMessageList.js +4 -4
  140. package/lib/components/a2ui/datalayer/Chart.d.ts +1 -1
  141. package/lib/components/a2ui/datalayer/schema.js +1 -1
  142. package/lib/components/teams/AnswerSurfaces.d.ts +3 -2
  143. package/lib/components/teams/AnswerSurfaces.js +7 -7
  144. package/lib/components/teams/useA2ATeam.d.ts +1 -1
  145. package/lib/config/AgentConfiguration.d.ts +1 -1
  146. package/lib/examples/ProtocolSignedRequestsExample.d.ts +10 -0
  147. package/lib/examples/ProtocolSignedRequestsExample.js +41 -0
  148. package/lib/examples/ProtocolUcpCheckoutExample.d.ts +10 -0
  149. package/lib/examples/ProtocolUcpCheckoutExample.js +59 -0
  150. package/lib/examples/example-selector.js +2 -0
  151. package/lib/examples/exampleGroups.d.ts +1 -1
  152. package/lib/examples/exampleGroups.js +4 -0
  153. package/lib/examples/index.d.ts +2 -0
  154. package/lib/examples/index.js +2 -0
  155. package/lib/examples/protocols/signedRequestsDemo.d.ts +27 -0
  156. package/lib/examples/protocols/signedRequestsDemo.js +59 -0
  157. package/lib/examples/protocols/ucpCheckoutDemo.d.ts +36 -0
  158. package/lib/examples/protocols/ucpCheckoutDemo.js +68 -0
  159. package/lib/protocols/AGUIAdapter.d.ts +7 -0
  160. package/lib/protocols/AGUIAdapter.js +43 -3
  161. package/lib/protocols/a2a/index.js +1 -0
  162. package/lib/protocols/agentic-commerce/index.js +1 -0
  163. package/lib/protocols/core.d.ts +6 -0
  164. package/lib/protocols/mcp/index.js +1 -0
  165. package/lib/protocols/pact/index.js +1 -0
  166. package/lib/protocols/ucp/index.js +1 -0
  167. package/lib/protocols/ucp/merchant.d.ts +15 -0
  168. package/lib/protocols/ucp/merchant.js +257 -0
  169. package/lib/protocols/web-bot-auth/index.js +1 -0
  170. package/lib/specs/agents/agents.js +338 -169
  171. package/lib/specs/apps.js +134 -6
  172. package/lib/specs/appspecSchema.js +59 -0
  173. package/lib/specs/cogs.js +6 -3
  174. package/lib/specs/index.d.ts +2 -1
  175. package/lib/specs/index.js +2 -1
  176. package/lib/specs/protocols.d.ts +24 -0
  177. package/lib/specs/protocols.js +197 -0
  178. package/lib/specs/ui.d.ts +21 -0
  179. package/lib/specs/{uiPlugins.js → ui.js} +14 -14
  180. package/lib/types/agentspecs.d.ts +69 -5
  181. package/lib/types/messages.d.ts +7 -0
  182. package/lib/types/protocol.d.ts +15 -0
  183. package/package.json +2 -2
  184. package/scripts/codegen/generate_agents.py +43 -8
  185. package/scripts/codegen/generate_protocols.py +207 -0
  186. package/scripts/codegen/generate_sandbox_agents.py +1 -1
  187. package/scripts/codegen/{generate_ui_plugins.py → generate_ui.py} +40 -40
  188. package/scripts/gen_workers.py +2 -2
  189. package/dist-embed/chunks/ChatView-D41Nx5rC.js +0 -32
  190. package/lib/chat/base/loopMessage.d.ts +0 -37
  191. package/lib/chat/base/loopMessage.js +0 -37
  192. package/lib/specs/uiPlugins.d.ts +0 -21
@@ -6,21 +6,25 @@
6
6
  * Window messages (LOOP P-25): what an application's code tells the page it
7
7
  * sits in, outside the conversation — ``session.send_window_message(data)``.
8
8
  *
9
- * The session API says it with a `CUSTOM` event named `loop.window` —
10
- * `{data}` — which the AG-UI adapter hands on as an `activity`. The chat
11
- * does not draw it: it hands it to whoever listens here — the embed's host
12
- * bridge, which raises it on the element as its `window-message` event.
9
+ * The session says it with a `reactor.ui` `window` op named `message`, its
10
+ * `args` `{data}` (REACTOR_UI RU-3), on the conversation's ui socket (RU-W). The chat does not draw it: it hands
11
+ * it to whoever listens here — the embed's host bridge, which raises it on
12
+ * the element as its `window-message` event. A window op of another name is
13
+ * not one this page acts on: refused, it throws.
13
14
  */
14
- /** The `CUSTOM` event's name. */
15
- export const LOOP_WINDOW = 'loop.window';
16
- /** What an activity says to the page, or `null` when it is not a window message. */
17
- export function loopWindowMessage(activity) {
18
- if (!activity || activity.type !== LOOP_WINDOW)
19
- return null;
20
- const said = activity.data;
21
- if (!said || typeof said !== 'object' || !('data' in said))
22
- return null;
23
- return { data: said.data };
15
+ import { AGUI_NAME } from '@datalayer/reactor/ui';
16
+ /** The name of the window op that hands the page a message. */
17
+ export const WINDOW_MESSAGE = 'message';
18
+ /** What a window op hands the page. Throws for a window op of another name. */
19
+ export function windowMessageOf(op) {
20
+ if (op.body.name !== WINDOW_MESSAGE) {
21
+ throw new Error(`A window op named ${op.body.name} is not one this page acts on`);
22
+ }
23
+ const args = op.body.args;
24
+ if (!args || !('data' in args)) {
25
+ throw new Error('A window message says no data');
26
+ }
27
+ return args.data;
24
28
  }
25
29
  const listeners = new Set();
26
30
  /** Hand a window message to whoever listens. */
@@ -36,12 +40,12 @@ export function onLoopWindowMessage(listener) {
36
40
  };
37
41
  }
38
42
  /**
39
- * What a turn's stream says to the page — the `loop.window` events of the
40
- * turn a window message posted by the page ran — and the sentence its
41
- * `RUN_ERROR` said, if it failed.
43
+ * Why the turn a window message posted by the page ran failed — its
44
+ * `RUN_ERROR`'s sentence — or `null`. What its code tells the page back comes
45
+ * on the conversation's ui socket (REACTOR_UI RU-W), never on this stream: a
46
+ * `reactor.ui` event here is refused.
42
47
  */
43
- export function windowTurnOf(stream) {
44
- const said = [];
48
+ export function windowTurnErrorOf(stream) {
45
49
  let error = null;
46
50
  for (const block of stream.split('\n\n')) {
47
51
  const data = block
@@ -61,14 +65,9 @@ export function windowTurnOf(stream) {
61
65
  if (event.type === 'RUN_ERROR') {
62
66
  error = String(event.message ?? 'The turn failed.');
63
67
  }
64
- else if (event.type === 'CUSTOM') {
65
- const message = loopWindowMessage({
66
- type: String(event.name),
67
- data: event.value,
68
- });
69
- if (message)
70
- said.push(message.data);
68
+ else if (event.type === 'CUSTOM' && event.name === AGUI_NAME) {
69
+ throw new Error('A reactor.ui op came on the run stream: it comes over the ui socket.');
71
70
  }
72
71
  }
73
- return { said, error };
72
+ return error;
74
73
  }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * A conversation's files as references (REACTOR_UI RU-6).
3
+ *
4
+ * What the page holds of a file it was given — File upload and the composer
5
+ * read it as `{name, type, data_url}` — is uploaded to the application's
6
+ * runtime before the run that names it (Reactor's `uploadFile`), and the run
7
+ * carries the ref it answers (`forwardedProps.loop.files`): a file's bytes
8
+ * never ride in the run.
9
+ *
10
+ * @module chat/base/uiFiles
11
+ */
12
+ import { type FileRef } from '@datalayer/reactor/ui';
13
+ /** How a file is uploaded to the conversation: its ref. */
14
+ export type UploadToConversation = (file: Blob & {
15
+ name: string;
16
+ }) => Promise<FileRef>;
17
+ /** A file's bytes from the data URL the page read it as. */
18
+ export declare function blobOfDataUrl(dataUrl: string, name: string, type?: string): Blob & {
19
+ name: string;
20
+ };
21
+ /** Whether a run's `forwardedProps` names files. */
22
+ export declare function namesFiles(forwardedProps: Record<string, unknown> | undefined): boolean;
23
+ /**
24
+ * The run's `forwardedProps` with its files uploaded: each file the page
25
+ * holds replaced by the ref its upload answered, a ref kept as it is.
26
+ *
27
+ * @throws for a file that is neither, or an upload refused (its sentence).
28
+ */
29
+ export declare function withUploadedFiles(forwardedProps: Record<string, unknown>, upload: UploadToConversation): Promise<Record<string, unknown>>;
@@ -0,0 +1,69 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * A conversation's files as references (REACTOR_UI RU-6).
7
+ *
8
+ * What the page holds of a file it was given — File upload and the composer
9
+ * read it as `{name, type, data_url}` — is uploaded to the application's
10
+ * runtime before the run that names it (Reactor's `uploadFile`), and the run
11
+ * carries the ref it answers (`forwardedProps.loop.files`): a file's bytes
12
+ * never ride in the run.
13
+ *
14
+ * @module chat/base/uiFiles
15
+ */
16
+ import { isFileRef } from '@datalayer/reactor/ui';
17
+ /** A file's bytes from the data URL the page read it as. */
18
+ export function blobOfDataUrl(dataUrl, name, type) {
19
+ const [head, body] = [
20
+ dataUrl.slice(0, dataUrl.indexOf(',')),
21
+ dataUrl.slice(dataUrl.indexOf(',') + 1),
22
+ ];
23
+ if (!head.startsWith('data:') || dataUrl.indexOf(',') < 0) {
24
+ throw new Error(`${name} could not be read: it is not a data URL.`);
25
+ }
26
+ const mediaType = type || head.slice('data:'.length).split(';')[0];
27
+ // Backed by an ArrayBuffer, as Blob takes it (a SharedArrayBuffer-backed view it refuses).
28
+ let bytes;
29
+ if (head.endsWith(';base64')) {
30
+ const binary = atob(body);
31
+ bytes = new Uint8Array(binary.length);
32
+ for (let index = 0; index < binary.length; index += 1) {
33
+ bytes[index] = binary.charCodeAt(index);
34
+ }
35
+ }
36
+ else {
37
+ bytes = new TextEncoder().encode(decodeURIComponent(body));
38
+ }
39
+ return Object.assign(new Blob([bytes], { type: mediaType }), { name });
40
+ }
41
+ /** Whether a run's `forwardedProps` names files. */
42
+ export function namesFiles(forwardedProps) {
43
+ const files = forwardedProps?.loop
44
+ ?.files;
45
+ return Array.isArray(files) && files.length > 0;
46
+ }
47
+ /**
48
+ * The run's `forwardedProps` with its files uploaded: each file the page
49
+ * holds replaced by the ref its upload answered, a ref kept as it is.
50
+ *
51
+ * @throws for a file that is neither, or an upload refused (its sentence).
52
+ */
53
+ export async function withUploadedFiles(forwardedProps, upload) {
54
+ const loop = forwardedProps.loop;
55
+ const files = loop.files;
56
+ const refs = [];
57
+ for (const given of files) {
58
+ if (isFileRef(given)) {
59
+ refs.push(given);
60
+ continue;
61
+ }
62
+ const held = given;
63
+ if (typeof held.name !== 'string' || typeof held.data_url !== 'string') {
64
+ throw new Error('A file given is neither the page’s nor a ref.');
65
+ }
66
+ refs.push(await upload(blobOfDataUrl(held.data_url, held.name, typeof held.type === 'string' ? held.type : undefined)));
67
+ }
68
+ return { ...forwardedProps, loop: { ...loop, files: refs } };
69
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * What a server says to a conversation's page, as `reactor.ui` ops
3
+ * (REACTOR_UI RU-2, RU-3), and what the page presses back (RU-W).
4
+ *
5
+ * The ops arrive on the conversation's ui socket (Reactor's `UiSocket`,
6
+ * one per session, beside the run stream that carries the conversation's
7
+ * text); `routeUiOp` says where each goes:
8
+ *
9
+ * - a `window` op to the page the conversation sits in (`loopWindow`);
10
+ * - a step's display to its row (`loopStep`), patched as it streams;
11
+ * - a display that says it shows in a panel or on a page to the elements
12
+ * open (`loopElement`), a `remove` of its id closing it;
13
+ * - everything else to the messages (`withUiOp`): a display under a message
14
+ * (`data.message_id`) kept on it (`ChatMessage.displays`) and drawn by the
15
+ * renderer a plugin contributed for its type; a `meta` op's `author` the
16
+ * message's voice; a `remove` of a message's id the message gone.
17
+ *
18
+ * An op about a message that has not arrived on the run stream yet — the
19
+ * two are separate connections — waits until it has (`placeable`). A press
20
+ * of what a display offered goes up the socket (`displayPressOf`), and the
21
+ * run that answers it names it only (`withPress`).
22
+ *
23
+ * Pure: the chat applies it to what it draws, and to its store. Nothing it
24
+ * was not told to expect is guessed at: an op it cannot place throws.
25
+ *
26
+ * @module chat/base/uiOps
27
+ */
28
+ import { type Display, type UiAction, type UiModel, type UiOp } from '@datalayer/reactor/ui';
29
+ import type { MessageSpeaker } from '../../types/messages';
30
+ import { type LoopElementChange } from './loopElement';
31
+ import { type LoopStep } from './loopStep';
32
+ /** The message a display is under: its `data.message_id`. */
33
+ export declare function messageOfDisplay(display: Display): string;
34
+ /** Who a message is by, as the chat draws a named voice. */
35
+ export declare function speakerOf(author: string): MessageSpeaker;
36
+ type WithDisplays = {
37
+ id?: string;
38
+ displays?: Display[];
39
+ speaker?: MessageSpeaker;
40
+ };
41
+ /**
42
+ * The messages with an op applied: a display shown (or asked) kept on its
43
+ * message, replacing one of its id; patched, appended to or removed where it
44
+ * is. A `remove` of a message's own id takes the message away, with what it
45
+ * showed; a `meta` op about a message gives it its `author`. `state` ops are
46
+ * not about the messages: they come back as they were.
47
+ *
48
+ * Throws for a display under no message here, for a change to a display no
49
+ * message shows, for a removal of nothing here, and for a `meta` op that
50
+ * says anything but a message's author: the server said something the page
51
+ * never saw, or does not read.
52
+ */
53
+ export declare function withUiOp<T extends WithDisplays>(items: T[], op: UiOp): T[];
54
+ /** Where an op goes (`routeUiOp`). */
55
+ export type RoutedUiOp = {
56
+ to: 'window';
57
+ data: unknown;
58
+ } | {
59
+ to: 'step';
60
+ step: LoopStep;
61
+ } | {
62
+ to: 'element';
63
+ change: LoopElementChange;
64
+ } | {
65
+ to: 'messages';
66
+ op: UiOp;
67
+ };
68
+ /**
69
+ * Where an op goes, and the steps kept after it: a step's display is kept
70
+ * (in a Reactor `UiModel`) so a patch of its output applies to it.
71
+ *
72
+ * `elements` is the ids of the elements shown in this conversation: a
73
+ * `remove` of one closes it (a no-op when the person closed it already).
74
+ */
75
+ export declare function routeUiOp(op: UiOp, steps: UiModel, elements: ReadonlySet<string>): {
76
+ routed: RoutedUiOp;
77
+ steps: UiModel;
78
+ };
79
+ /**
80
+ * Whether the messages hold what an op is about: the message a display is
81
+ * under, the message a `meta` op names, the display a change is to, what a
82
+ * `remove` takes away. An op about what has not arrived yet waits.
83
+ */
84
+ export declare function placeable<T extends WithDisplays>(items: readonly T[], op: UiOp): boolean;
85
+ /**
86
+ * The press a run's `forwardedProps` carries for a display's button — what
87
+ * `AnswerShowsView` hands the chat — or `null` for a run that presses
88
+ * nothing of a display's. It goes up the ui socket, never in the run.
89
+ */
90
+ export declare function displayPressOf(forwardedProps: Record<string, unknown> | undefined): UiAction | null;
91
+ /**
92
+ * The run's `forwardedProps` once its press was checked on the socket: the
93
+ * press named by the id the runtime answered, the action itself gone.
94
+ */
95
+ export declare function withPress(forwardedProps: Record<string, unknown>, answered: unknown): Record<string, unknown>;
96
+ export {};
@@ -0,0 +1,251 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * What a server says to a conversation's page, as `reactor.ui` ops
7
+ * (REACTOR_UI RU-2, RU-3), and what the page presses back (RU-W).
8
+ *
9
+ * The ops arrive on the conversation's ui socket (Reactor's `UiSocket`,
10
+ * one per session, beside the run stream that carries the conversation's
11
+ * text); `routeUiOp` says where each goes:
12
+ *
13
+ * - a `window` op to the page the conversation sits in (`loopWindow`);
14
+ * - a step's display to its row (`loopStep`), patched as it streams;
15
+ * - a display that says it shows in a panel or on a page to the elements
16
+ * open (`loopElement`), a `remove` of its id closing it;
17
+ * - everything else to the messages (`withUiOp`): a display under a message
18
+ * (`data.message_id`) kept on it (`ChatMessage.displays`) and drawn by the
19
+ * renderer a plugin contributed for its type; a `meta` op's `author` the
20
+ * message's voice; a `remove` of a message's id the message gone.
21
+ *
22
+ * An op about a message that has not arrived on the run stream yet — the
23
+ * two are separate connections — waits until it has (`placeable`). A press
24
+ * of what a display offered goes up the socket (`displayPressOf`), and the
25
+ * run that answers it names it only (`withPress`).
26
+ *
27
+ * Pure: the chat applies it to what it draws, and to its store. Nothing it
28
+ * was not told to expect is guessed at: an op it cannot place throws.
29
+ *
30
+ * @module chat/base/uiOps
31
+ */
32
+ import { applyPatch, applyUiOp, } from '@datalayer/reactor/ui';
33
+ import { elementOfDisplay } from './loopElement';
34
+ import { isStepDisplay, stepOfDisplay } from './loopStep';
35
+ import { windowMessageOf } from './loopWindow';
36
+ /** The message a display is under: its `data.message_id`. */
37
+ export function messageOfDisplay(display) {
38
+ const id = display.data?.message_id;
39
+ if (typeof id !== 'string' || !id) {
40
+ throw new Error(`Display ${display.id} says no message it is under`);
41
+ }
42
+ return id;
43
+ }
44
+ /** Who a message is by, as the chat draws a named voice. */
45
+ export function speakerOf(author) {
46
+ return { id: `author:${author}`, name: author };
47
+ }
48
+ /** The messages with one display changed by `change`, or taken away when it answers nothing. */
49
+ function changed(items, id, change) {
50
+ const at = items.findIndex(item => (item.displays ?? []).some(display => display.id === id));
51
+ if (at < 0) {
52
+ throw new Error(`Display ${id} is shown under no message here`);
53
+ }
54
+ return items.map((item, index) => {
55
+ if (index !== at)
56
+ return item;
57
+ const displays = [];
58
+ for (const display of item.displays ?? []) {
59
+ if (display.id !== id) {
60
+ displays.push(display);
61
+ continue;
62
+ }
63
+ const next = change(display);
64
+ if (next)
65
+ displays.push({ ...next, id });
66
+ }
67
+ return { ...item, displays };
68
+ });
69
+ }
70
+ function replaced(displays, display) {
71
+ const at = displays.findIndex(one => one.id === display.id);
72
+ return at < 0
73
+ ? [...displays, display]
74
+ : displays.map((one, index) => (index === at ? display : one));
75
+ }
76
+ /**
77
+ * The messages with an op applied: a display shown (or asked) kept on its
78
+ * message, replacing one of its id; patched, appended to or removed where it
79
+ * is. A `remove` of a message's own id takes the message away, with what it
80
+ * showed; a `meta` op about a message gives it its `author`. `state` ops are
81
+ * not about the messages: they come back as they were.
82
+ *
83
+ * Throws for a display under no message here, for a change to a display no
84
+ * message shows, for a removal of nothing here, and for a `meta` op that
85
+ * says anything but a message's author: the server said something the page
86
+ * never saw, or does not read.
87
+ */
88
+ export function withUiOp(items, op) {
89
+ switch (op.op) {
90
+ case 'show':
91
+ case 'ask': {
92
+ const shown = op.body;
93
+ const messageId = messageOfDisplay(shown);
94
+ if (!items.some(item => item.id === messageId)) {
95
+ throw new Error(`Display ${shown.id} is under message ${messageId}, which is not here`);
96
+ }
97
+ return items.map(item => item.id === messageId
98
+ ? { ...item, displays: replaced(item.displays ?? [], shown) }
99
+ : item);
100
+ }
101
+ case 'remove': {
102
+ const showsIt = items.some(item => (item.displays ?? []).some(display => display.id === op.id));
103
+ if (showsIt)
104
+ return changed(items, op.id, () => undefined);
105
+ if (!items.some(item => item.id === op.id)) {
106
+ throw new Error(`Nothing here is ${op.id}: it cannot be removed`);
107
+ }
108
+ return items.filter(item => item.id !== op.id);
109
+ }
110
+ case 'patch': {
111
+ const operations = op.body;
112
+ return changed(items, op.id, display => applyPatch(display, operations));
113
+ }
114
+ case 'append': {
115
+ const { path, value } = op.body;
116
+ return changed(items, op.id, display => applyPatch(display, [{ op: 'add', path: `${path}/-`, value }]));
117
+ }
118
+ case 'meta': {
119
+ const author = op.body.author;
120
+ const keys = Object.keys(op.body);
121
+ if (!op.id ||
122
+ keys.length !== 1 ||
123
+ typeof author !== 'string' ||
124
+ !author.trim()) {
125
+ throw new Error(`A meta op says ${JSON.stringify(op.body)}: only a message's author is read`);
126
+ }
127
+ if (!items.some(item => item.id === op.id)) {
128
+ throw new Error(`Message ${op.id} is not here: it has no author to say`);
129
+ }
130
+ return items.map(item => item.id === op.id
131
+ ? { ...item, speaker: speakerOf(author.trim()) }
132
+ : item);
133
+ }
134
+ case 'window':
135
+ throw new Error('A window op is for the page, not the messages');
136
+ default:
137
+ return items;
138
+ }
139
+ }
140
+ /**
141
+ * Where an op goes, and the steps kept after it: a step's display is kept
142
+ * (in a Reactor `UiModel`) so a patch of its output applies to it.
143
+ *
144
+ * `elements` is the ids of the elements shown in this conversation: a
145
+ * `remove` of one closes it (a no-op when the person closed it already).
146
+ */
147
+ export function routeUiOp(op, steps, elements) {
148
+ switch (op.op) {
149
+ case 'window':
150
+ return { routed: { to: 'window', data: windowMessageOf(op) }, steps };
151
+ case 'show':
152
+ case 'ask': {
153
+ if (isStepDisplay(op.body)) {
154
+ const kept = applyUiOp(steps, op);
155
+ return {
156
+ routed: { to: 'step', step: stepOfDisplay(op.body) },
157
+ steps: kept,
158
+ };
159
+ }
160
+ const element = elementOfDisplay(op.body);
161
+ if (element) {
162
+ return { routed: { to: 'element', change: element }, steps };
163
+ }
164
+ return { routed: { to: 'messages', op }, steps };
165
+ }
166
+ case 'patch':
167
+ case 'append': {
168
+ if (op.id in steps.displays) {
169
+ const kept = applyUiOp(steps, op);
170
+ return {
171
+ routed: { to: 'step', step: stepOfDisplay(kept.displays[op.id]) },
172
+ steps: kept,
173
+ };
174
+ }
175
+ return { routed: { to: 'messages', op }, steps };
176
+ }
177
+ case 'remove': {
178
+ if (op.id in steps.displays) {
179
+ throw new Error(`Step ${op.id} is never removed: it ends`);
180
+ }
181
+ if (elements.has(op.id)) {
182
+ return {
183
+ routed: { to: 'element', change: { id: op.id, closed: true } },
184
+ steps,
185
+ };
186
+ }
187
+ return { routed: { to: 'messages', op }, steps };
188
+ }
189
+ default:
190
+ return { routed: { to: 'messages', op }, steps };
191
+ }
192
+ }
193
+ /**
194
+ * Whether the messages hold what an op is about: the message a display is
195
+ * under, the message a `meta` op names, the display a change is to, what a
196
+ * `remove` takes away. An op about what has not arrived yet waits.
197
+ */
198
+ export function placeable(items, op) {
199
+ const hasItem = (id) => !!id && items.some(item => item.id === id);
200
+ const hasDisplay = (id) => !!id &&
201
+ items.some(item => (item.displays ?? []).some(display => display.id === id));
202
+ switch (op.op) {
203
+ case 'show':
204
+ case 'ask': {
205
+ const under = op.body.data?.message_id;
206
+ return typeof under === 'string' && hasItem(under);
207
+ }
208
+ case 'meta':
209
+ return hasItem(op.id);
210
+ case 'patch':
211
+ case 'append':
212
+ return hasDisplay(op.id);
213
+ case 'remove':
214
+ return hasDisplay(op.id) || hasItem(op.id);
215
+ default:
216
+ return true;
217
+ }
218
+ }
219
+ /**
220
+ * The press a run's `forwardedProps` carries for a display's button — what
221
+ * `AnswerShowsView` hands the chat — or `null` for a run that presses
222
+ * nothing of a display's. It goes up the ui socket, never in the run.
223
+ */
224
+ export function displayPressOf(forwardedProps) {
225
+ const loop = forwardedProps?.loop;
226
+ const action = loop?.action;
227
+ if (!action || typeof action.display_id !== 'string')
228
+ return null;
229
+ if (typeof action.name !== 'string' || typeof action.token !== 'string') {
230
+ throw new Error('A press of a display says its action and its token');
231
+ }
232
+ return {
233
+ action: action.name,
234
+ display_id: action.display_id,
235
+ token: action.token,
236
+ payload: action.payload ?? {},
237
+ };
238
+ }
239
+ /**
240
+ * The run's `forwardedProps` once its press was checked on the socket: the
241
+ * press named by the id the runtime answered, the action itself gone.
242
+ */
243
+ export function withPress(forwardedProps, answered) {
244
+ const press = answered?.press;
245
+ if (typeof press !== 'string' || !press) {
246
+ throw new Error('The runtime checked the press but named none');
247
+ }
248
+ const loop = { ...forwardedProps.loop };
249
+ delete loop.action;
250
+ return { ...forwardedProps, loop: { ...loop, press } };
251
+ }
@@ -1,4 +1,5 @@
1
1
  import { type ReactNode, type RefObject } from 'react';
2
+ import { type Display, type UiAct, type UiUpload } from '@datalayer/reactor/ui';
2
3
  import { type ChatDensity } from './ChatMarkdown';
3
4
  import { type MarkedMcpServer } from '../marks';
4
5
  import type { DisplayItem, AvatarConfig } from '../../types/chat';
@@ -13,6 +14,17 @@ export interface ToolApprovalConfig {
13
14
  export interface ChatMessageListProps {
14
15
  /** All display items (messages + tool calls) */
15
16
  displayItems: DisplayItem[];
17
+ /**
18
+ * How a message's display presses what it offered (REACTOR_UI RU-4, RU-W):
19
+ * the chat sends it up the conversation's ui socket. Absent, its
20
+ * displays offer nothing to press.
21
+ */
22
+ actOn?: (display: Display) => UiAct;
23
+ /**
24
+ * How a message's display uploads a file the person chose (REACTOR_UI
25
+ * RU-6): its ref, to press with. Absent, nothing is uploaded.
26
+ */
27
+ upload?: UiUpload;
16
28
  /** Whether the agent is loading */
17
29
  isLoading: boolean;
18
30
  /** Whether the agent is currently streaming */
@@ -97,5 +109,5 @@ export interface SubagentChatPanelProps {
97
109
  * approval decisions are sent over the shared monitoring socket.
98
110
  */
99
111
  export declare function SubagentChatPanel({ toolCallId, subagentName: subagentNameHint, height, avatarConfig, }: SubagentChatPanelProps): React.ReactElement | null;
100
- export declare function ChatMessageList({ displayItems, isLoading, isStreaming, showLoadingIndicator, hideMessagesAfterToolUI, avatarConfig, padding, notebookToolSurfacesId, emptyContent, messagesEndRef, onRespond, approvalConfig, showTurnFooters, agentUsage, onRemoveItems, renderMessageFooter, mcpServers, density, }: ChatMessageListProps): import("react").JSX.Element;
112
+ export declare function ChatMessageList({ displayItems, actOn, upload, isLoading, isStreaming, showLoadingIndicator, hideMessagesAfterToolUI, avatarConfig, padding, notebookToolSurfacesId, emptyContent, messagesEndRef, onRespond, approvalConfig, showTurnFooters, agentUsage, onRemoveItems, renderMessageFooter, mcpServers, density, }: ChatMessageListProps): import("react").JSX.Element;
101
113
  export {};
@@ -12,8 +12,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
12
12
  import { MicrophoneIcon } from '@datalayer/icons-react';
13
13
  import { Fragment, lazy, Suspense, useState, useCallback, useEffect, useMemo, useRef, useSyncExternalStore, } from 'react';
14
14
  import { useOptionalReactorPlatform } from '@datalayer/reactor/react';
15
- import { resolveToolResult } from '@datalayer/reactor/ui';
16
- import { ReactorDisplay } from '@datalayer/reactor/ui/react';
15
+ import { resolveToolResult, } from '@datalayer/reactor/ui';
16
+ import { DisplayText, ReactorDisplay } from '@datalayer/reactor/ui/react';
17
17
  import { Text, Spinner, Link, Label, RelativeTime } from '@primer/react';
18
18
  import { ArrowRightIcon, BroadcastIcon, ClockIcon, DependabotIcon, PersonIcon, SkipIcon, ToolsIcon, XCircleFillIcon, } from '@primer/octicons-react';
19
19
  import { Box } from '@datalayer/primer-addons';
@@ -366,7 +366,7 @@ function DefaultToolCallRenderer({ item, onRespond, mcpServers, density, }) {
366
366
  // ---------------------------------------------------------------------------
367
367
  // Component
368
368
  // ---------------------------------------------------------------------------
369
- export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoadingIndicator, hideMessagesAfterToolUI, avatarConfig, padding, notebookToolSurfacesId, emptyContent, messagesEndRef, onRespond, approvalConfig, showTurnFooters = false, agentUsage, onRemoveItems, renderMessageFooter, mcpServers, density = 'comfortable', }) {
369
+ export function ChatMessageList({ displayItems, actOn, upload, isLoading, isStreaming, showLoadingIndicator, hideMessagesAfterToolUI, avatarConfig, padding, notebookToolSurfacesId, emptyContent, messagesEndRef, onRespond, approvalConfig, showTurnFooters = false, agentUsage, onRemoveItems, renderMessageFooter, mcpServers, density = 'comfortable', }) {
370
370
  /*
371
371
  * Who draws a tool call: the Reactor plugins of the page, when it has a
372
372
  * platform. Each plugin binds its own tools (`ToolBindings`) and renders its
@@ -611,7 +611,7 @@ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoad
611
611
  whiteSpace: 'pre-wrap',
612
612
  wordBreak: 'break-word',
613
613
  }, children: [message.metadata?.input === 'voice' ? (_jsx(Box, { as: "span", "data-spoken": "", title: "Said aloud", "aria-label": "Said aloud:", display: "inline-flex", verticalAlign: "text-bottom", mr: 1, opacity: 0.85, children: _jsx(MicrophoneIcon, { size: 14, "aria-hidden": "true" }) })) : null, text] }));
614
- })()) : message.live && !getMessageText(message) ? (_jsx(TypingDots, { size: 6 })) : (_jsx(ChatMarkdown, { density: density, text: getMessageText(message) || (isStreaming ? '...' : '') }))] }), renderMessageFooter ? (_jsx(Box, { display: "flex", gap: 2, alignItems: "center", mt: 1, flexWrap: "wrap", flexDirection: isUser ? 'row-reverse' : 'row', children: renderMessageFooter(message) })) : null] })] }) }, message.id));
614
+ })()) : message.live && !getMessageText(message) ? (_jsx(TypingDots, { size: 6 })) : (_jsx(ChatMarkdown, { density: density, text: getMessageText(message) || (isStreaming ? '...' : '') }))] }), message.displays?.length ? (_jsx(Box, { "data-chat-displays": "", display: "flex", flexDirection: "column", gap: 2, mt: 2, width: "100%", children: message.displays.map(display => platform ? (_jsx(ReactorDisplay, { display: display, act: actOn?.(display), upload: upload }, display.id)) : (_jsx(DisplayText, { display: display }, display.id))) })) : null, renderMessageFooter ? (_jsx(Box, { display: "flex", gap: 2, alignItems: "center", mt: 1, flexWrap: "wrap", flexDirection: isUser ? 'row-reverse' : 'row', children: renderMessageFooter(message) })) : null] })] }) }, message.id));
615
615
  };
616
616
  return (_jsxs(_Fragment, { children: [displayItems.map((item, index) => {
617
617
  const itemUI = renderItem(item, index);
@@ -121,7 +121,7 @@ export declare function chartOption(points: Record<string, unknown>[], props: Pi
121
121
  };
122
122
  series: {
123
123
  name: string;
124
- type: "line" | "bar" | "scatter";
124
+ type: "bar" | "line" | "scatter";
125
125
  areaStyle: {} | undefined;
126
126
  data: number[][] | (number | null)[];
127
127
  }[];
@@ -19,7 +19,7 @@
19
19
  */
20
20
  import { z } from 'zod/v3';
21
21
  import { ActionSchema, DataBindingSchema } from '@a2ui/web_core/v0_9';
22
- import { COMPONENT_CATALOGUE } from '../../../specs/uiPlugins';
22
+ import { COMPONENT_CATALOGUE } from '../../../specs/ui';
23
23
  /** The components of Datalayer's own the catalog has, by id. */
24
24
  export const OWN_COMPONENT_IDS = Object.values(COMPONENT_CATALOGUE)
25
25
  .filter(component => !component.standard)
@@ -30,8 +30,9 @@ export type AnswerPressed = {
30
30
  does: string;
31
31
  };
32
32
  /**
33
- * What a button pressed on an answer's surface sends back, or `null` for an
34
- * action that is not one of an answer's buttons (a form's submission).
33
+ * What a button pressed on a member's surface sends back, or `null` for an
34
+ * action that is not one of its buttons (a form's submission). A member's
35
+ * surface is an answer by how it came — an A2A artifact — not by its id.
35
36
  */
36
37
  export declare function pressedOf(action: {
37
38
  name: string;
@@ -1,21 +1,21 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Suspense, lazy } from 'react';
3
3
  import { Text } from '@primer/react';
4
- import { answerAction } from '../../apps/plugins/a2ui-surface/toolResult';
5
4
  /** The renderer itself: A2UI and the catalog, loaded when a surface is drawn. */
6
5
  const AnswerSurfacesView = lazy(() => import('./AnswerSurfacesView'));
7
6
  /**
8
- * What a button pressed on an answer's surface sends back, or `null` for an
9
- * action that is not one of an answer's buttons (a form's submission).
7
+ * What a button pressed on a member's surface sends back, or `null` for an
8
+ * action that is not one of its buttons (a form's submission). A member's
9
+ * surface is an answer by how it came — an A2A artifact — not by its id.
10
10
  */
11
11
  export function pressedOf(action) {
12
- const pressed = answerAction(action);
13
- if (!pressed) {
12
+ const name = action.name.trim();
13
+ if (!name || name === 'submit_a2ui_form') {
14
14
  return null;
15
15
  }
16
- const { name, payload } = pressed.forwardedProps.loop.action;
16
+ const payload = { ...action.context };
17
17
  const does = typeof payload.does === 'string' ? payload.does : 'read';
18
- return { message: pressed.message, action: { name, payload }, does };
18
+ return { message: name, action: { name, payload }, does };
19
19
  }
20
20
  /** The surfaces the members showed, each under who showed it; nothing when there is none. */
21
21
  export function AnswerSurfaces(props) {
@@ -59,7 +59,7 @@ export declare const NOTEBOOK_AND_WORDS: readonly string[];
59
59
  export declare const COMPONENTS_NOTEBOOK_AND_WORDS: readonly string[];
60
60
  /** A surface of components a member showed with an answer: who gave it, and the surface. */
61
61
  export type A2ATeamSurface = {
62
- /** Its surface's id: `answer-…`. */
62
+ /** Its surface's id. */
63
63
  id: string;
64
64
  /** The member that showed it, by its id. */
65
65
  giver: string;