@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
@@ -29,7 +29,7 @@ export interface LibraryAgentspec {
29
29
  welcomeDocument?: string | null;
30
30
  sandboxVariant?: string | null;
31
31
  protocol?: string | null;
32
- uiPlugin?: string | null;
32
+ ui?: string | null;
33
33
  trigger?: Record<string, unknown> | null;
34
34
  modelConfig?: Record<string, unknown> | null;
35
35
  mcpServerTools?: Array<Record<string, unknown>> | null;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Signed requests (Web Bot Auth) in the browser (AGENT_PROTOCOLS EX-10): a
3
+ * key generated in the page signs one request; the page shows the three
4
+ * headers, the signature base the key signed, and what a website's check
5
+ * finds — verified, then the same request replayed and one with its path
6
+ * changed, both refused. The key never leaves the page and is never shown.
7
+ */
8
+ import React from 'react';
9
+ declare const ProtocolSignedRequestsExample: React.FC;
10
+ export default ProtocolSignedRequestsExample;
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2025-2026 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ /**
7
+ * Signed requests (Web Bot Auth) in the browser (AGENT_PROTOCOLS EX-10): a
8
+ * key generated in the page signs one request; the page shows the three
9
+ * headers, the signature base the key signed, and what a website's check
10
+ * finds — verified, then the same request replayed and one with its path
11
+ * changed, both refused. The key never leaves the page and is never shown.
12
+ */
13
+ import { useCallback, useEffect, useState } from 'react';
14
+ import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
15
+ import { Button, Flash, Heading, Label, Text } from '@primer/react';
16
+ import { ThemedProvider } from './utils/themedProvider';
17
+ import { signedRequestDemo, } from './protocols/signedRequestsDemo';
18
+ setupPrimerPortals();
19
+ const Mono = ({ children, label, }) => (_jsxs(Box, { mb: 3, children: [_jsx(Text, { as: "div", sx: { fontWeight: 'semibold', fontSize: 1, mb: 1 }, children: label }), _jsx(Box, { as: "pre", p: 2, m: 0, bg: "canvas.subtle", borderRadius: 2, sx: { fontSize: 0, whiteSpace: 'pre-wrap', overflowWrap: 'anywhere' }, children: children })] }));
20
+ const OUTCOME_VARIANT = {
21
+ verified: 'success',
22
+ invalid: 'danger',
23
+ unverified: 'attention',
24
+ };
25
+ const ProtocolSignedRequestsExample = () => {
26
+ const [demo, setDemo] = useState(null);
27
+ const [error, setError] = useState('');
28
+ const run = useCallback(() => {
29
+ setError('');
30
+ signedRequestDemo()
31
+ .then(setDemo)
32
+ .catch(failure => setError(String(failure?.message ?? failure)));
33
+ }, []);
34
+ useEffect(run, [run]);
35
+ return (_jsx(ThemedProvider, { children: _jsxs(Box, { p: 4, maxWidth: 880, mx: "auto", children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Signed requests" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', mt: 0 }, children: "Web Bot Auth (draft-ietf-webbotauth-httpsig-protocol-00): a key generated in this page signs a request to a shop; the shop checks it against the agent's key directory. The private key is never shown." }), _jsx(Button, { onClick: run, sx: { mb: 3 }, children: "Sign again with a new key" }), error ? _jsx(Flash, { variant: "danger", children: error }) : null, demo ? (_jsxs(_Fragment, { children: [_jsxs(Mono, { label: "Request", children: ["GET ", demo.url] }), _jsx(Mono, { label: "Signature-Agent", children: demo.headers['Signature-Agent'] }), _jsx(Mono, { label: "Signature-Input", children: demo.headers['Signature-Input'] }), _jsx(Mono, { label: "Signature", children: demo.headers.Signature }), _jsx(Mono, { label: "Signature base (what the key signed)", children: demo.base }), _jsx(Mono, { label: "Public key in the directory (keyid: its thumbprint)", children: JSON.stringify(demo.publicJwk, null, 2) }), _jsx(Box, { display: "grid", gap: 2, children: [
36
+ ['The shop checks it', demo.verified],
37
+ ['The same request again', demo.replayed],
38
+ ['Its path changed', demo.tampered],
39
+ ].map(([what, found]) => (_jsxs(Box, { display: "flex", gap: 2, alignItems: "baseline", children: [_jsx(Label, { variant: OUTCOME_VARIANT[found.outcome], children: found.outcome }), _jsxs(Text, { sx: { fontSize: 1 }, children: [what, found.reason ? `: ${found.reason}` : ''] })] }, what))) })] })) : null] }) }));
40
+ };
41
+ export default ProtocolSignedRequestsExample;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * A UCP checkout approved as a card (AGENT_PROTOCOLS EX-10, after EX-04):
3
+ * the UCP client buys from *Example Store*, the local test merchant running
4
+ * in the page. The exact purchase is proposed; completing it asks the
5
+ * approver — the card below — once; approving buys once, and the same
6
+ * proposal is refused after. The test payment's token is never shown.
7
+ */
8
+ import React from 'react';
9
+ declare const ProtocolUcpCheckoutExample: React.FC;
10
+ export default ProtocolUcpCheckoutExample;
@@ -0,0 +1,59 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2025-2026 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ /**
7
+ * A UCP checkout approved as a card (AGENT_PROTOCOLS EX-10, after EX-04):
8
+ * the UCP client buys from *Example Store*, the local test merchant running
9
+ * in the page. The exact purchase is proposed; completing it asks the
10
+ * approver — the card below — once; approving buys once, and the same
11
+ * proposal is refused after. The test payment's token is never shown.
12
+ */
13
+ import { useMemo, useRef, useState } from 'react';
14
+ import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
15
+ import { Button, Flash, Heading, Text } from '@primer/react';
16
+ import { ThemedProvider } from './utils/themedProvider';
17
+ import { buy, proposeTea, ucpCheckoutDemo } from './protocols/ucpCheckoutDemo';
18
+ setupPrimerPortals();
19
+ const ProtocolUcpCheckoutExample = () => {
20
+ const answer = useRef(null);
21
+ const [asking, setAsking] = useState(false);
22
+ const demo = useMemo(() => ucpCheckoutDemo(() => new Promise(resolve => {
23
+ answer.current = resolve;
24
+ setAsking(true);
25
+ })), []);
26
+ const [proposal, setProposal] = useState(null);
27
+ const [said, setSaid] = useState([]);
28
+ const [working, setWorking] = useState(false);
29
+ const propose = async () => {
30
+ setWorking(true);
31
+ try {
32
+ setProposal(await proposeTea(demo));
33
+ }
34
+ catch (error) {
35
+ setSaid(s => [
36
+ ...s,
37
+ { ok: false, says: String(error.message) },
38
+ ]);
39
+ }
40
+ finally {
41
+ setWorking(false);
42
+ }
43
+ };
44
+ const complete = async () => {
45
+ if (!proposal)
46
+ return;
47
+ setWorking(true);
48
+ const outcome = await buy(demo, proposal.proposal);
49
+ setSaid(s => [...s, outcome]);
50
+ setWorking(false);
51
+ };
52
+ const decide = (approved) => {
53
+ setAsking(false);
54
+ answer.current?.(approved);
55
+ answer.current = null;
56
+ };
57
+ return (_jsx(ThemedProvider, { children: _jsxs(Box, { p: 4, maxWidth: 720, mx: "auto", children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "UCP checkout" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', mt: 0 }, children: "Universal Commerce Protocol 2026-08-25, against Example Store, a test merchant running in this page. Nothing is bought without the card below, and a proposal buys once." }), _jsxs(Box, { display: "flex", gap: 2, mb: 3, flexWrap: "wrap", children: [_jsx(Button, { onClick: propose, disabled: working || asking, children: "Propose 2 \u00D7 Sencha green tea" }), _jsx(Button, { variant: "primary", onClick: complete, disabled: !proposal || working, children: "Complete the purchase" })] }), proposal && asking ? (_jsxs(Box, { p: 3, mb: 3, border: "1px solid", borderColor: "attention.emphasis", borderRadius: 2, role: "dialog", "aria-label": "Approve this purchase", children: [_jsx(Text, { as: "p", sx: { fontWeight: 'semibold', mt: 0 }, children: "Approve this purchase?" }), _jsx(Text, { as: "p", children: proposal.says }), _jsxs(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 0 }, children: ["Revision ", proposal.proposal.revision.slice(0, 12), "\u2026 \u2014 if the basket changes, it is proposed again."] }), _jsxs(Box, { display: "flex", gap: 2, children: [_jsx(Button, { variant: "primary", onClick: () => decide(true), children: "Approve" }), _jsx(Button, { onClick: () => decide(false), children: "Decline" })] })] })) : proposal ? (_jsxs(Text, { as: "p", sx: { fontSize: 1 }, children: ["Proposed: ", proposal.says] })) : null, said.map((each, index) => (_jsx(Flash, { variant: each.ok ? 'success' : 'warning', sx: { mb: 2 }, children: each.says }, index))), _jsxs(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 0 }, children: ["Orders at the store: ", demo.orders.length] })] }) }));
58
+ };
59
+ export default ProtocolUcpCheckoutExample;
@@ -131,6 +131,8 @@ export const EXAMPLE_ENTRIES = [
131
131
  makeEntry('AgentSubagentsExample', () => import('./AgentSubagentsExample'), 'Multi-agent delegation with the in-repo subagents capability.'),
132
132
  makeEntry('AgentA2AExample', () => import('./AgentA2AExample'), 'Delegation to separate agents over the A2A protocol, launched locally or on Datalayer runtimes.'),
133
133
  makeEntry('AgentA2ATeamExample', () => import('./AgentA2ATeamExample'), 'Two applications as a team over A2A: Sales in the browser (@a2a-js/sdk) asks Accounting on a runtime (fasta2a, Odoo read only), each an Office Assistant character.'),
134
+ makeEntry('ProtocolSignedRequestsExample', () => import('./ProtocolSignedRequestsExample'), 'Web Bot Auth in the browser: a key made in the page signs a request — its three headers and the signature base — verified, then a replay and a changed path refused.'),
135
+ makeEntry('ProtocolUcpCheckoutExample', () => import('./ProtocolUcpCheckoutExample'), 'A UCP checkout at a test store in the page: the exact purchase proposed, approved on a card once, bought once.'),
134
136
  makeEntry('PapCompanyDiscoveryExample', () => import('./PapCompanyDiscoveryExample'), 'Validate a PAP company document and reduce it to the public capabilities safe for an agent or UI.'),
135
137
  makeEntry('PapAgentIdentityExample', () => import('./PapAgentIdentityExample'), 'Verify personal-agent client metadata and signing policy without exposing JWK coordinates.'),
136
138
  makeEntry('PapAuthorizationBoundaryExample', () => import('./PapAuthorizationBoundaryExample'), 'Generate real Session and Direct Sign-In security material while showing only safe policy status.'),
@@ -5,5 +5,5 @@
5
5
  *
6
6
  * @module examples/exampleGroups
7
7
  */
8
- export declare const EXAMPLE_GROUP_ORDER: readonly ["Apps", "Assistant", "A2UI", "A2A", "Personal Agent Protocol", "AG-UI", "Chat", "Document", "Notebook", "Capabilities", "Cell", "CopilotKit"];
8
+ export declare const EXAMPLE_GROUP_ORDER: readonly ["Apps", "Assistant", "A2UI", "A2A", "Personal Agent Protocol", "Agent protocols", "AG-UI", "Chat", "Document", "Notebook", "Capabilities", "Cell", "CopilotKit"];
9
9
  export declare const getExampleGroup: (id: string) => string;
@@ -15,6 +15,7 @@ export const EXAMPLE_GROUP_ORDER = [
15
15
  'A2UI',
16
16
  'A2A',
17
17
  'Personal Agent Protocol',
18
+ 'Agent protocols',
18
19
  'AG-UI',
19
20
  'Chat',
20
21
  'Document',
@@ -39,6 +40,9 @@ export const getExampleGroup = (id) => {
39
40
  return 'A2A';
40
41
  if (id.startsWith('Pap'))
41
42
  return 'Personal Agent Protocol';
43
+ // The other agent protocols' examples: signed requests, commerce (AGENT_PROTOCOLS EX-10).
44
+ if (id.startsWith('Protocol'))
45
+ return 'Agent protocols';
42
46
  if (id.startsWith('AgUi'))
43
47
  return 'AG-UI';
44
48
  if (id.startsWith('CopilotKit'))
@@ -27,6 +27,8 @@ export { default as AgentCodemodeExample } from './AgentCodemodeExample';
27
27
  export { default as AgentCodeSandboxesExample } from './AgentCodeSandboxesExample';
28
28
  export { default as AgentDecideExample } from './AgentDecideExample';
29
29
  export { default as AgentA2ATeamExample } from './AgentA2ATeamExample';
30
+ export { default as ProtocolSignedRequestsExample } from './ProtocolSignedRequestsExample';
31
+ export { default as ProtocolUcpCheckoutExample } from './ProtocolUcpCheckoutExample';
30
32
  export { default as PapCompanyDiscoveryExample } from './PapCompanyDiscoveryExample';
31
33
  export { default as PapAgentIdentityExample } from './PapAgentIdentityExample';
32
34
  export { default as PapAuthorizationBoundaryExample } from './PapAuthorizationBoundaryExample';
@@ -33,6 +33,8 @@ export { default as AgentCodemodeExample } from './AgentCodemodeExample';
33
33
  export { default as AgentCodeSandboxesExample } from './AgentCodeSandboxesExample';
34
34
  export { default as AgentDecideExample } from './AgentDecideExample';
35
35
  export { default as AgentA2ATeamExample } from './AgentA2ATeamExample';
36
+ export { default as ProtocolSignedRequestsExample } from './ProtocolSignedRequestsExample';
37
+ export { default as ProtocolUcpCheckoutExample } from './ProtocolUcpCheckoutExample';
36
38
  export { default as PapCompanyDiscoveryExample } from './PapCompanyDiscoveryExample';
37
39
  export { default as PapAgentIdentityExample } from './PapAgentIdentityExample';
38
40
  export { default as PapAuthorizationBoundaryExample } from './PapAuthorizationBoundaryExample';
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The *Signed requests* gallery example's work (AGENT_PROTOCOLS EX-10): a
3
+ * fresh Ed25519 key generated in the page, one request signed with it
4
+ * (`signRequest`), the three headers and the signature base the signer was
5
+ * handed, then the request verified against the key's directory — and the
6
+ * same request replayed, and one with its path changed, both refused.
7
+ *
8
+ * The key never leaves the page and is never shown: only its public JWK and
9
+ * thumbprint are. No network: the directory is read from memory.
10
+ *
11
+ * @module examples/protocols/signedRequestsDemo
12
+ */
13
+ import { type PublicJwk, type SignedHeaders, type Verification } from '../../protocols/web-bot-auth';
14
+ export interface SignedRequestDemo {
15
+ /** The key's thumbprint, the `keyid` of the signature. */
16
+ keyid: string;
17
+ publicJwk: PublicJwk;
18
+ url: string;
19
+ headers: SignedHeaders;
20
+ /** The signature base, exactly as the signer signed it. */
21
+ base: string;
22
+ verified: Verification;
23
+ replayed: Verification;
24
+ tampered: Verification;
25
+ }
26
+ /** Sign one request with a fresh key, and verify it three ways. */
27
+ export declare function signedRequestDemo(url?: string, agent?: string): Promise<SignedRequestDemo>;
@@ -0,0 +1,59 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * The *Signed requests* gallery example's work (AGENT_PROTOCOLS EX-10): a
7
+ * fresh Ed25519 key generated in the page, one request signed with it
8
+ * (`signRequest`), the three headers and the signature base the signer was
9
+ * handed, then the request verified against the key's directory — and the
10
+ * same request replayed, and one with its path changed, both refused.
11
+ *
12
+ * The key never leaves the page and is never shown: only its public JWK and
13
+ * thumbprint are. No network: the directory is read from memory.
14
+ *
15
+ * @module examples/protocols/signedRequestsDemo
16
+ */
17
+ import { InMemoryNonceStore, generateLocalSigner, keyResolver, signRequest, verifyRequest, } from '../../protocols/web-bot-auth';
18
+ /** A signer that keeps what it was asked to sign: the signature base. */
19
+ function recording(signer) {
20
+ const bases = [];
21
+ return {
22
+ keyid: signer.keyid,
23
+ algorithm: signer.algorithm,
24
+ bases,
25
+ async sign(data) {
26
+ bases.push(new TextDecoder().decode(data));
27
+ return signer.sign(data);
28
+ },
29
+ };
30
+ }
31
+ /** Sign one request with a fresh key, and verify it three ways. */
32
+ export async function signedRequestDemo(url = 'https://shop.example/products?q=tea', agent = 'https://agent.example') {
33
+ const { signer, publicJwk } = await generateLocalSigner();
34
+ const keeping = recording(signer);
35
+ const headers = await signRequest(new Request(url), keeping, { agent });
36
+ // The shop finds the agent's keys in its directory: here, in memory.
37
+ const resolver = keyResolver({
38
+ directory: { keys: async () => [publicJwk] },
39
+ });
40
+ const nonceStore = new InMemoryNonceStore();
41
+ const sent = (to) => new Request(to, { headers: { ...headers } });
42
+ const verified = await verifyRequest(sent(url), resolver, { nonceStore });
43
+ const replayed = await verifyRequest(sent(url), resolver, { nonceStore });
44
+ const changed = new URL(url);
45
+ changed.pathname = '/checkout';
46
+ const tampered = await verifyRequest(sent(changed.toString()), resolver, {
47
+ nonceStore: new InMemoryNonceStore(),
48
+ });
49
+ return {
50
+ keyid: signer.keyid,
51
+ publicJwk,
52
+ url,
53
+ headers,
54
+ base: keeping.bases[0] ?? '',
55
+ verified,
56
+ replayed,
57
+ tampered,
58
+ };
59
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The *UCP checkout* gallery example's work (AGENT_PROTOCOLS EX-10, after
3
+ * EX-04): the UCP client buying from *Example Store*, the local test
4
+ * merchant running in the page (`protocols/ucp/merchant`). A checkout is
5
+ * proposed as an exact, revisioned purchase; completing it asks the host's
6
+ * approver — the page's card — once, and the proposal is spent whatever the
7
+ * answer. The payment is the test handler's; its token is never shown.
8
+ *
9
+ * @module examples/protocols/ucpCheckoutDemo
10
+ */
11
+ import { type ReactorPlatform } from '@datalayer/reactor';
12
+ import { UcpClient, type CheckoutProposal } from '../../protocols/ucp';
13
+ export declare const STORE = "https://store.example";
14
+ export declare const AGENT_PROFILE = "https://agent.example/.well-known/ucp";
15
+ /** The test payment's token: held by the host, never in a summary or a proposal. */
16
+ export declare const TEST_TOKEN = "tok_test_gallery_never_shown";
17
+ export interface UcpCheckoutDemo {
18
+ client: UcpClient;
19
+ reactor: ReactorPlatform;
20
+ orders: Array<{
21
+ order: string;
22
+ checkout: string;
23
+ }>;
24
+ }
25
+ /** The client, the store, and a host whose approver is `decide`. */
26
+ export declare function ucpCheckoutDemo(decide: (proposal: CheckoutProposal) => Promise<boolean>): UcpCheckoutDemo;
27
+ /** Find the tea, put `quantity` in a checkout with the buyer's email, and propose it. */
28
+ export declare function proposeTea(demo: UcpCheckoutDemo, quantity?: number, email?: string): Promise<{
29
+ proposal: CheckoutProposal;
30
+ says: string;
31
+ }>;
32
+ /** Complete the proposal: the approver is asked; the order, or why not. */
33
+ export declare function buy(demo: UcpCheckoutDemo, proposal: CheckoutProposal): Promise<{
34
+ ok: boolean;
35
+ says: string;
36
+ }>;
@@ -0,0 +1,68 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * The *UCP checkout* gallery example's work (AGENT_PROTOCOLS EX-10, after
7
+ * EX-04): the UCP client buying from *Example Store*, the local test
8
+ * merchant running in the page (`protocols/ucp/merchant`). A checkout is
9
+ * proposed as an exact, revisioned purchase; completing it asks the host's
10
+ * approver — the page's card — once, and the proposal is spent whatever the
11
+ * answer. The payment is the test handler's; its token is never shown.
12
+ *
13
+ * @module examples/protocols/ucpCheckoutDemo
14
+ */
15
+ import { contribution, definePlugin, } from '@datalayer/reactor';
16
+ import { buildProtocolsReactor } from '../../protocols/agentProtocols';
17
+ import { UcpApprovers, UcpClient, UcpPaymentInstruments, checkoutSummary, proposalSummary, } from '../../protocols/ucp';
18
+ import { EXAMPLE_STORE_HANDLER_ID, exampleStore, } from '../../protocols/ucp/merchant';
19
+ export const STORE = 'https://store.example';
20
+ export const AGENT_PROFILE = 'https://agent.example/.well-known/ucp';
21
+ /** The test payment's token: held by the host, never in a summary or a proposal. */
22
+ export const TEST_TOKEN = 'tok_test_gallery_never_shown';
23
+ /** The client, the store, and a host whose approver is `decide`. */
24
+ export function ucpCheckoutDemo(decide) {
25
+ const store = exampleStore(STORE);
26
+ const host = definePlugin({
27
+ name: 'gallery-host',
28
+ contributes: [
29
+ contribution(UcpApprovers, { approve: decide }, { id: 'person', order: 10 }),
30
+ contribution(UcpPaymentInstruments, {
31
+ instrument: async () => ({
32
+ id: 'pi_1',
33
+ handler_id: EXAMPLE_STORE_HANDLER_ID,
34
+ type: 'card',
35
+ credential: { type: 'PAYMENT_GATEWAY', token: TEST_TOKEN },
36
+ }),
37
+ }, { id: 'custody', order: 10 }),
38
+ ],
39
+ });
40
+ return {
41
+ client: new UcpClient(STORE, AGENT_PROFILE, store.fetch),
42
+ reactor: buildProtocolsReactor([host]),
43
+ orders: store.orders,
44
+ };
45
+ }
46
+ /** Find the tea, put `quantity` in a checkout with the buyer's email, and propose it. */
47
+ export async function proposeTea(demo, quantity = 2, email = 'ana@example.com') {
48
+ const [product] = await demo.client.search('sencha');
49
+ const created = await demo.client.createCheckout([
50
+ { id: product.id, quantity },
51
+ ]);
52
+ await demo.client.updateCheckout(created.id, { buyer: { email } });
53
+ const proposal = await demo.client.proposeCompletion(created.id);
54
+ return { proposal, says: proposalSummary(proposal) };
55
+ }
56
+ /** Complete the proposal: the approver is asked; the order, or why not. */
57
+ export async function buy(demo, proposal) {
58
+ try {
59
+ const done = checkoutSummary(await demo.client.complete(proposal, demo.reactor));
60
+ return {
61
+ ok: true,
62
+ says: `Bought: order ${done.order?.id}, ${done.status}.`,
63
+ };
64
+ }
65
+ catch (error) {
66
+ return { ok: false, says: `Not bought: ${error.message}.` };
67
+ }
68
+ }
@@ -7,6 +7,8 @@ import type { ProtocolAdapterConfig } from '../types';
7
7
  import type { ChatMessage } from '../types/messages';
8
8
  import type { ToolDefinition, ToolExecutionResult } from '../types/tools';
9
9
  import { BaseProtocolAdapter } from './BaseProtocolAdapter';
10
+ /** What the page says when a run's stream closes before the run said how it ended. */
11
+ export declare const RUN_CUT_SHORT = "The run stopped before it finished, without an answer or an error: send it again.";
10
12
  /**
11
13
  * AG-UI specific configuration
12
14
  */
@@ -110,6 +112,11 @@ export declare class AGUIAdapter extends BaseProtocolAdapter {
110
112
  * Parse SSE stream from AG-UI response
111
113
  */
112
114
  private parseSSEStream;
115
+ /**
116
+ * A `reactor.ui` op on the run stream: refused, and said as an error. The
117
+ * ops come over the conversation's ui socket (REACTOR_UI RU-W).
118
+ */
119
+ private refuseUiOnRun;
113
120
  /**
114
121
  * Handle individual AG-UI events
115
122
  *
@@ -5,6 +5,9 @@
5
5
  import { generateMessageId, createAssistantMessage } from '../types/messages';
6
6
  import { agUiRefusal, refusalBody } from './agUiRefusal';
7
7
  import { BaseProtocolAdapter } from './BaseProtocolAdapter';
8
+ import { AGUI_NAME } from '@datalayer/reactor/ui';
9
+ /** What the page says when a run's stream closes before the run said how it ended. */
10
+ export const RUN_CUT_SHORT = 'The run stopped before it finished, without an answer or an error: send it again.';
8
11
  /**
9
12
  * AG-UI protocol adapter
10
13
  * Uses HTTP POST with SSE streaming for responses
@@ -426,11 +429,20 @@ export class AGUIAdapter extends BaseProtocolAdapter {
426
429
  });
427
430
  }
428
431
  this._streamParsingDepth++;
432
+ // Whether the run said how it ended. A stream that closes without
433
+ // RUN_FINISHED or RUN_ERROR is a run cut short — by the runtime, a proxy
434
+ // or the network — and the page says so instead of waiting for an answer
435
+ // that is not coming (a Preview gave no answer for minutes, 2026-10-12).
436
+ let ended = false;
429
437
  try {
430
438
  while (true) {
431
439
  const { done, value } = await reader.read();
432
- if (done)
440
+ if (done) {
441
+ if (!ended) {
442
+ throw new Error(RUN_CUT_SHORT);
443
+ }
433
444
  break;
445
+ }
434
446
  buffer += decoder.decode(value, { stream: true });
435
447
  const lines = buffer.split('\n');
436
448
  buffer = lines.pop() || '';
@@ -444,6 +456,10 @@ export class AGUIAdapter extends BaseProtocolAdapter {
444
456
  const data = line.slice(6);
445
457
  try {
446
458
  const event = JSON.parse(data);
459
+ const kind = event.type;
460
+ if (kind === 'RUN_FINISHED' || kind === 'RUN_ERROR') {
461
+ ended = true;
462
+ }
447
463
  this.handleAGUIEvent(event, {
448
464
  getCurrentMessageId: () => currentMessageId,
449
465
  setCurrentMessageId: id => {
@@ -483,6 +499,17 @@ export class AGUIAdapter extends BaseProtocolAdapter {
483
499
  }
484
500
  }
485
501
  }
502
+ /**
503
+ * A `reactor.ui` op on the run stream: refused, and said as an error. The
504
+ * ops come over the conversation's ui socket (REACTOR_UI RU-W).
505
+ */
506
+ refuseUiOnRun() {
507
+ this.emit({
508
+ type: 'error',
509
+ error: new Error('A reactor.ui op came on the run stream: it comes over the ui socket (REACTOR_UI RU-W).'),
510
+ timestamp: new Date(),
511
+ });
512
+ }
486
513
  /**
487
514
  * Handle individual AG-UI events
488
515
  *
@@ -684,14 +711,27 @@ export class AGUIAdapter extends BaseProtocolAdapter {
684
711
  });
685
712
  break;
686
713
  }
714
+ case 'ACTIVITY_SNAPSHOT':
715
+ case 'ACTIVITY_DELTA': {
716
+ // `reactor.ui` ops come over the conversation's ui socket, never
717
+ // the run stream (REACTOR_UI RU-W): one here is refused. Any other
718
+ // activity is nobody's here.
719
+ if (event.activityType === AGUI_NAME) {
720
+ this.refuseUiOnRun();
721
+ }
722
+ break;
723
+ }
687
724
  case 'CUSTOM': {
688
725
  const name = event.name;
689
- const value = event.value;
726
+ if (name === AGUI_NAME) {
727
+ this.refuseUiOnRun();
728
+ break;
729
+ }
690
730
  this.emit({
691
731
  type: 'activity',
692
732
  activity: {
693
733
  type: name || 'custom',
694
- data: value,
734
+ data: event.value,
695
735
  },
696
736
  timestamp: new Date(),
697
737
  });
@@ -56,6 +56,7 @@ export const A2APlugin = definePlugin({
56
56
  status: 'implemented',
57
57
  specification: 'https://a2a-protocol.org/latest/specification/',
58
58
  plugin: A2A_PLUGIN,
59
+ catalogue: 'a2a',
59
60
  points: EXTENSION_POINTS.map(point => point.id),
60
61
  }, { id: 'a2a', order: DEFAULT_ORDER }),
61
62
  contribution(A2AOrchestrationExtensions, orchestration, {
@@ -59,6 +59,7 @@ export const AgenticCommercePlugin = definePlugin({
59
59
  status: 'partial',
60
60
  specification: `https://github.com/agentic-commerce-protocol/agentic-commerce-protocol/tree/main/spec/${AGENTIC_COMMERCE_VERSION}`,
61
61
  plugin: AGENTIC_COMMERCE_PLUGIN,
62
+ catalogue: 'acp',
62
63
  points: POINTS.map(point => point.id),
63
64
  }, { id: 'agentic_commerce', order: DEFAULT_ORDER }),
64
65
  ],
@@ -26,6 +26,12 @@ export interface ProtocolDescription {
26
26
  status: 'implemented' | 'partial' | 'planned';
27
27
  specification: string;
28
28
  plugin: string;
29
+ /**
30
+ * Its id in the agentspecs protocols catalogue (`agentspecs/protocols`,
31
+ * AGENT_PROTOCOLS PS-01): `web-bot-auth`, `acp`… — how Studio reads a
32
+ * runtime's answer against the catalogue (PR-50).
33
+ */
34
+ catalogue: string;
29
35
  /** The contribution points its plugin declares, its extensions' included. */
30
36
  points: string[];
31
37
  }
@@ -31,6 +31,7 @@ export const McpPlugin = definePlugin({
31
31
  status: 'implemented',
32
32
  specification: 'https://modelcontextprotocol.io/specification',
33
33
  plugin: MCP_PLUGIN,
34
+ catalogue: 'mcp',
34
35
  points: [],
35
36
  }, { id: 'mcp', order: DEFAULT_ORDER }),
36
37
  ],
@@ -69,6 +69,7 @@ export const PactPlugin = definePlugin({
69
69
  status: 'partial',
70
70
  specification: 'https://github.com/openpactprotocol/openpactprotocol/blob/main/docs/spec.md',
71
71
  plugin: PACT_PLUGIN,
72
+ catalogue: 'pact',
72
73
  points: POINTS.map(point => point.id),
73
74
  }, { id: 'pact', order: DEFAULT_ORDER }),
74
75
  contribution(PactDelegatedProfiles, { grantType: DEVICE_CODE_GRANT }, { id: 'device-code', order: DEFAULT_ORDER }),
@@ -64,6 +64,7 @@ export const UcpPlugin = definePlugin({
64
64
  status: 'partial',
65
65
  specification: `https://ucp.dev/${UCP_VERSION}/specification/overview`,
66
66
  plugin: UCP_PLUGIN,
67
+ catalogue: 'ucp',
67
68
  points: UCP_POINTS.map(point => point.id),
68
69
  }, { id: 'ucp', order: DEFAULT_ORDER }),
69
70
  ],
@@ -0,0 +1,15 @@
1
+ /** The store's products, as the Python store lists them. */
2
+ export declare const EXAMPLE_STORE_CATALOG: Record<string, {
3
+ title: string;
4
+ price: number;
5
+ }>;
6
+ /** The one payment handler it takes, and the prefix of its test tokens. */
7
+ export declare const EXAMPLE_STORE_HANDLER_ID = "test_pay_1";
8
+ /** The store: its `fetch`, and the orders it took. */
9
+ export declare function exampleStore(base?: string): {
10
+ fetch: typeof fetch;
11
+ orders: Array<{
12
+ order: string;
13
+ checkout: string;
14
+ }>;
15
+ };