@datalayer/agent-runtimes 1.3.84 → 1.3.86

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 (162) hide show
  1. package/lib/chat/ChatFloating.d.ts +5 -4
  2. package/lib/chat/ChatFloating.js +8 -6
  3. package/lib/chat/ChatLanguage.d.ts +17 -0
  4. package/lib/chat/ChatLanguage.js +29 -0
  5. package/lib/chat/assistant/AssistantStage.d.ts +4 -4
  6. package/lib/chat/assistant/AssistantStage.js +4 -2
  7. package/lib/chat/assistant/BalloonParts.d.ts +2 -1
  8. package/lib/chat/assistant/BalloonParts.js +12 -5
  9. package/lib/chat/assistant/BalloonVisual.js +3 -1
  10. package/lib/chat/assistant/ConversationBalloon.d.ts +1 -1
  11. package/lib/chat/assistant/ConversationBalloon.js +3 -2
  12. package/lib/chat/assistant/SpeechBalloon.d.ts +1 -1
  13. package/lib/chat/assistant/SpeechBalloon.js +10 -7
  14. package/lib/chat/assistant/toolLine.d.ts +8 -4
  15. package/lib/chat/assistant/toolLine.js +13 -9
  16. package/lib/chat/base/ChatBase.js +14 -11
  17. package/lib/chat/display/EmptyState.js +3 -1
  18. package/lib/chat/index.d.ts +2 -0
  19. package/lib/chat/index.js +3 -0
  20. package/lib/chat/messages/ChatMessages.js +3 -1
  21. package/lib/chat/messages/TurnFooter.js +3 -1
  22. package/lib/chat/prompt/InputPrompt.js +3 -1
  23. package/lib/chat/prompt/InputPromptLexical.js +3 -1
  24. package/lib/chat/prompt/footer/InPromptFooter.js +3 -1
  25. package/lib/chat/tools/ToolApprovalBanner.js +5 -3
  26. package/lib/chat/tools/ToolApprovalDialog.js +5 -3
  27. package/lib/chat/tools/ToolCallDisplay.js +29 -25
  28. package/lib/chat/words.d.ts +102 -0
  29. package/lib/chat/words.js +460 -0
  30. package/lib/components/a2ui/custom/index.d.ts +39 -0
  31. package/lib/components/a2ui/custom/index.js +95 -0
  32. package/lib/components/a2ui/custom/sandbox.d.ts +73 -0
  33. package/lib/components/a2ui/custom/sandbox.js +188 -0
  34. package/lib/components/a2ui/datalayer/index.d.ts +1 -1
  35. package/lib/components/a2ui/datalayer/index.js +1 -1
  36. package/lib/components/a2ui/datalayer/schema.d.ts +10 -0
  37. package/lib/components/a2ui/datalayer/schema.js +12 -1
  38. package/lib/components/a2ui/index.d.ts +1 -0
  39. package/lib/components/a2ui/index.js +1 -0
  40. package/lib/components/a2ui/visibleWhen.d.ts +12 -1
  41. package/lib/components/a2ui/visibleWhen.js +24 -3
  42. package/lib/components/inspector/AgentInspector.d.ts +25 -44
  43. package/lib/components/inspector/AgentInspector.js +27 -215
  44. package/lib/components/inspector/AgentInspectorDialog.d.ts +6 -6
  45. package/lib/components/inspector/AgentInspectorDialog.js +2 -2
  46. package/lib/components/inspector/a2aSpans.d.ts +51 -0
  47. package/lib/components/inspector/a2aSpans.js +373 -0
  48. package/lib/components/inspector/agentSpans.d.ts +120 -0
  49. package/lib/components/inspector/agentSpans.js +253 -0
  50. package/lib/components/inspector/chatSpans.d.ts +36 -0
  51. package/lib/components/inspector/chatSpans.js +50 -0
  52. package/lib/components/inspector/classify.d.ts +11 -8
  53. package/lib/components/inspector/classify.js +23 -24
  54. package/lib/components/inspector/index.d.ts +7 -7
  55. package/lib/components/inspector/index.js +7 -7
  56. package/lib/components/teams/A2ATeamGraph.d.ts +117 -22
  57. package/lib/components/teams/A2ATeamGraph.js +217 -97
  58. package/lib/components/teams/SceneTranscript.d.ts +29 -0
  59. package/lib/components/teams/SceneTranscript.js +54 -0
  60. package/lib/components/teams/SceneView.d.ts +41 -0
  61. package/lib/components/teams/SceneView.js +28 -0
  62. package/lib/components/teams/index.d.ts +4 -0
  63. package/lib/components/teams/index.js +4 -0
  64. package/lib/components/teams/sceneStage.d.ts +120 -0
  65. package/lib/components/teams/sceneStage.js +170 -0
  66. package/lib/components/teams/sceneTranscript.d.ts +74 -0
  67. package/lib/components/teams/sceneTranscript.js +294 -0
  68. package/lib/components/teams/teamConnections.d.ts +2 -2
  69. package/lib/components/teams/teamConnections.js +3 -3
  70. package/lib/components/teams/useA2ATeam.d.ts +94 -22
  71. package/lib/components/teams/useA2ATeam.js +356 -140
  72. package/lib/examples/AgentA2ATeamExample.d.ts +10 -9
  73. package/lib/examples/AgentA2ATeamExample.js +70 -60
  74. package/lib/examples/AssistantExample.js +2 -2
  75. package/lib/examples/ScenesExample.d.ts +26 -0
  76. package/lib/examples/ScenesExample.js +241 -0
  77. package/lib/examples/example-selector.js +1 -0
  78. package/lib/examples/exampleGroups.js +3 -0
  79. package/lib/examples/index.d.ts +1 -0
  80. package/lib/examples/index.js +1 -0
  81. package/lib/examples/main.js +4 -0
  82. package/lib/loop/apps/AppComposer.d.ts +2 -1
  83. package/lib/loop/apps/AppComposer.js +6 -3
  84. package/lib/loop/apps/AppRenderer.d.ts +2 -1
  85. package/lib/loop/apps/AppRenderer.js +34 -25
  86. package/lib/loop/apps/appspec.d.ts +11 -1
  87. package/lib/loop/apps/appspec.js +115 -1
  88. package/lib/loop/apps/checks.d.ts +8 -0
  89. package/lib/loop/apps/checks.js +106 -4
  90. package/lib/loop/apps/customComponents.d.ts +41 -0
  91. package/lib/loop/apps/customComponents.js +260 -0
  92. package/lib/loop/apps/hostTools.d.ts +8 -1
  93. package/lib/loop/apps/hostTools.js +9 -0
  94. package/lib/loop/apps/index.d.ts +1 -0
  95. package/lib/loop/apps/index.js +1 -0
  96. package/lib/loop/core/a2uiComponents.d.ts +10 -0
  97. package/lib/loop/core/a2uiComponents.js +15 -0
  98. package/lib/loop/core/index.d.ts +1 -0
  99. package/lib/loop/core/index.js +3 -0
  100. package/lib/loop/embed/AppEmbed.d.ts +11 -3
  101. package/lib/loop/embed/AppEmbed.js +42 -16
  102. package/lib/loop/embed/element.d.ts +5 -0
  103. package/lib/loop/embed/element.js +61 -5
  104. package/lib/loop/embed/embedConfig.d.ts +8 -0
  105. package/lib/loop/embed/embedConfig.js +18 -0
  106. package/lib/loop/embed/hostBridge.d.ts +28 -2
  107. package/lib/loop/embed/hostBridge.js +22 -2
  108. package/lib/loop/index.d.ts +4 -3
  109. package/lib/loop/index.js +4 -3
  110. package/lib/loop/plugins/a2ui-surface/InlineSurface.d.ts +7 -1
  111. package/lib/loop/plugins/a2ui-surface/InlineSurface.js +7 -2
  112. package/lib/loop/plugins/a2ui-surface/SurfaceToolResult.js +4 -1
  113. package/lib/loop/plugins/a2ui-surface/ownComponents.d.ts +6 -0
  114. package/lib/loop/plugins/a2ui-surface/ownComponents.js +30 -0
  115. package/lib/loop/plugins/app-components/index.d.ts +26 -0
  116. package/lib/loop/plugins/app-components/index.js +56 -0
  117. package/lib/loop/plugins/app-elements/AppElements.js +4 -1
  118. package/lib/loop/plugins/app-page/AppPage.d.ts +9 -0
  119. package/lib/loop/plugins/app-page/AppPage.js +106 -8
  120. package/lib/loop/plugins/app-page/appPageModel.d.ts +17 -1
  121. package/lib/loop/plugins/app-page/appPageModel.js +120 -4
  122. package/lib/loop/plugins/app-page/index.d.ts +1 -0
  123. package/lib/loop/plugins/app-page/index.js +1 -0
  124. package/lib/loop/plugins/app-page/pageRun.d.ts +46 -0
  125. package/lib/loop/plugins/app-page/pageRun.js +111 -0
  126. package/lib/loop/plugins/assistant/index.js +8 -6
  127. package/lib/loop/plugins/chat/ChatView.js +6 -4
  128. package/lib/loop/plugins/chat/index.d.ts +1 -1
  129. package/lib/loop/plugins/chat/index.js +2 -1
  130. package/lib/models/PageTag.d.ts +1 -1
  131. package/lib/runtimes/browser/a2aPeer.d.ts +2 -1
  132. package/lib/specs/actions.js +78 -1
  133. package/lib/specs/apps.d.ts +5 -0
  134. package/lib/specs/apps.js +1384 -231
  135. package/lib/specs/appspecSchema.js +191 -1
  136. package/lib/specs/index.d.ts +1 -0
  137. package/lib/specs/index.js +1 -0
  138. package/lib/specs/mcpServers.js +8 -2
  139. package/lib/specs/scenes.d.ts +21 -0
  140. package/lib/specs/scenes.js +1191 -0
  141. package/lib/specs/teams/teams.d.ts +3 -0
  142. package/lib/specs/teams/teams.js +249 -0
  143. package/lib/types/agentspecs.d.ts +70 -0
  144. package/lib/types/chat.d.ts +6 -5
  145. package/lib/types/index.d.ts +1 -0
  146. package/lib/types/index.js +1 -0
  147. package/lib/types/scenes.d.ts +207 -0
  148. package/lib/types/scenes.js +5 -0
  149. package/lib/types/teams.d.ts +13 -2
  150. package/package.json +4 -4
  151. package/scripts/codegen/generate_agents.py +1 -0
  152. package/scripts/codegen/generate_apps.py +4 -2
  153. package/scripts/codegen/generate_scenes.py +301 -0
  154. package/scripts/codegen/generate_teams.py +15 -2
  155. package/lib/components/inspector/JsonTree.d.ts +0 -24
  156. package/lib/components/inspector/JsonTree.js +0 -89
  157. package/lib/components/inspector/a2aInspect.d.ts +0 -56
  158. package/lib/components/inspector/a2aInspect.js +0 -478
  159. package/lib/components/inspector/agentInspector.d.ts +0 -179
  160. package/lib/components/inspector/agentInspector.js +0 -267
  161. package/lib/components/inspector/chatInspect.d.ts +0 -38
  162. package/lib/components/inspector/chatInspect.js +0 -65
@@ -0,0 +1,460 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * The chat's own words in the person's language (LOOP P-26): the composer's
7
+ * placeholder and buttons, its error sentences, the tool lines and the tool
8
+ * cards, the approvals, and the assistant's balloon — said in the six
9
+ * languages the application's composer is said in (`interfaceWords`).
10
+ *
11
+ * The chat reads them in the language its host says (`ChatLanguage`, which
12
+ * `AppRenderer` and the embed set from their `language`), else in the first
13
+ * the browser prefers that is here, else in English: as an application's own
14
+ * words are picked (`loop/apps/language`).
15
+ *
16
+ * Pure: no React ({@link useChatWords} is in `ChatLanguage`).
17
+ *
18
+ * @module chat/words
19
+ */
20
+ import { pickLanguage } from '../loop/apps/language';
21
+ /** The chat's words, by language. Another language reads English. */
22
+ export const CHAT_WORDS = {
23
+ en: {
24
+ placeholder: 'Ask anything, type / for commands or @ for mention',
25
+ typeMessage: 'Type a message...',
26
+ messageInput: 'Message input',
27
+ send: 'Send',
28
+ stop: 'Stop',
29
+ pauseKernelBusy: 'Pause (kernel busy)',
30
+ suggestedPrompts: 'Suggested prompts',
31
+ demoKeyExpired: 'This demo runs on a shared key, and its time is up. Sign in to keep going.',
32
+ keyExpired: 'Your key has expired. Sign in to keep going.',
33
+ startConversation: 'Start a conversation',
34
+ sendToBegin: 'Send a message to begin chatting',
35
+ copyTurn: 'Copy this turn',
36
+ removeTurn: 'Remove this turn',
37
+ error: message => `Error: ${message}`,
38
+ thinking: 'Thinking…',
39
+ toolPreparing: 'Preparing...',
40
+ toolExecuting: 'Executing...',
41
+ toolComplete: 'Complete',
42
+ toolExecutionFailed: 'Execution Failed',
43
+ toolCodeError: 'Code Error',
44
+ toolExited: 'Exited',
45
+ toolFailed: 'Failed',
46
+ awaitingApproval: 'Awaiting Approval',
47
+ noParameters: 'No parameters',
48
+ moreArguments: count => `(+${count} more)`,
49
+ parameters: 'Parameters',
50
+ result: 'Result',
51
+ executionError: 'Execution Error',
52
+ executionErrorWhy: 'The sandbox or execution environment failed to run the code.',
53
+ errorHeading: 'Error',
54
+ processExited: 'Process Exited',
55
+ exitedWithCode: code => `Process exited with code ${code}`,
56
+ nonZeroExit: 'The code called sys.exit() with a non-zero exit code.',
57
+ toolRunning: { before: 'Using ', after: '…' },
58
+ toolDone: { before: 'Done: ', after: '' },
59
+ toolFailedLine: { before: '', after: ' failed' },
60
+ approve: 'Approve',
61
+ deny: 'Deny',
62
+ approveAll: 'Approve all',
63
+ approvalNeeded: 'This tool requires your approval to run.',
64
+ approvedRunning: 'Approved. Executing tool.',
65
+ approvedElsewhere: 'Approved from sidebar.',
66
+ deniedWontRun: 'Denied. Tool will not run.',
67
+ decidedElsewhere: 'Decision came from sidebar.',
68
+ approvalsPending: count => `${count} tool ${count === 1 ? 'approval' : 'approvals'} pending`,
69
+ toolApprovalsPending: 'Tool approvals pending',
70
+ collapse: 'Collapse',
71
+ review: 'Review',
72
+ dismiss: 'Dismiss',
73
+ approvalTitle: 'Tool Approval Required',
74
+ arguments: 'Arguments:',
75
+ approvalWarning: 'This tool will perform an action on your behalf. Please review the arguments before approving.',
76
+ rememberChoice: 'Remember my choice for this tool',
77
+ waitingOpen: 'Waiting for you — open the conversation to answer.',
78
+ waitingForYou: 'Waiting for you',
79
+ paused: 'Paused — it answers again once it is resumed.',
80
+ moreWaiting: count => `${count} more`,
81
+ showMore: 'more',
82
+ showLess: 'less',
83
+ now: 'Now',
84
+ conversation: 'Conversation',
85
+ suggestions: 'Suggestions',
86
+ expandConversation: 'Expand the conversation',
87
+ expand: 'Expand',
88
+ expandWhat: what => `Expand ${what}`,
89
+ theVisual: 'the visual',
90
+ talkTo: name => `Talk to ${name}`,
91
+ },
92
+ fr: {
93
+ placeholder: 'Demandez ce que vous voulez, tapez / pour les commandes ou @ pour mentionner',
94
+ typeMessage: 'Écrivez un message...',
95
+ messageInput: 'Saisie du message',
96
+ send: 'Envoyer',
97
+ stop: 'Arrêter',
98
+ pauseKernelBusy: 'Pause (noyau occupé)',
99
+ suggestedPrompts: 'Suggestions de questions',
100
+ demoKeyExpired: 'Cette démo utilise une clé partagée, et son temps est écoulé. Connectez-vous pour continuer.',
101
+ keyExpired: 'Votre clé a expiré. Connectez-vous pour continuer.',
102
+ startConversation: 'Commencer une conversation',
103
+ sendToBegin: 'Envoyez un message pour commencer',
104
+ copyTurn: 'Copier cet échange',
105
+ removeTurn: 'Supprimer cet échange',
106
+ error: message => `Erreur : ${message}`,
107
+ thinking: 'Réflexion…',
108
+ toolPreparing: 'Préparation...',
109
+ toolExecuting: 'Exécution...',
110
+ toolComplete: 'Terminé',
111
+ toolExecutionFailed: 'Échec de l’exécution',
112
+ toolCodeError: 'Erreur dans le code',
113
+ toolExited: 'Arrêté',
114
+ toolFailed: 'Échec',
115
+ awaitingApproval: 'En attente d’approbation',
116
+ noParameters: 'Aucun paramètre',
117
+ moreArguments: count => `(+${count} de plus)`,
118
+ parameters: 'Paramètres',
119
+ result: 'Résultat',
120
+ executionError: 'Erreur d’exécution',
121
+ executionErrorWhy: 'Le bac à sable ou l’environnement d’exécution n’a pas pu exécuter le code.',
122
+ errorHeading: 'Erreur',
123
+ processExited: 'Processus arrêté',
124
+ exitedWithCode: code => `Le processus s’est arrêté avec le code ${code}`,
125
+ nonZeroExit: 'Le code a appelé sys.exit() avec un code de sortie non nul.',
126
+ toolRunning: { before: 'Utilise ', after: '…' },
127
+ toolDone: { before: 'Terminé : ', after: '' },
128
+ toolFailedLine: { before: '', after: ' a échoué' },
129
+ approve: 'Approuver',
130
+ deny: 'Refuser',
131
+ approveAll: 'Tout approuver',
132
+ approvalNeeded: 'Cet outil a besoin de votre approbation pour s’exécuter.',
133
+ approvedRunning: 'Approuvé. Exécution de l’outil.',
134
+ approvedElsewhere: 'Approuvé depuis le panneau latéral.',
135
+ deniedWontRun: 'Refusé. L’outil ne s’exécutera pas.',
136
+ decidedElsewhere: 'Décision prise depuis le panneau latéral.',
137
+ approvalsPending: count => count === 1
138
+ ? '1 approbation d’outil en attente'
139
+ : `${count} approbations d’outil en attente`,
140
+ toolApprovalsPending: 'Approbations d’outil en attente',
141
+ collapse: 'Réduire',
142
+ review: 'Examiner',
143
+ dismiss: 'Fermer',
144
+ approvalTitle: 'Approbation d’outil requise',
145
+ arguments: 'Arguments :',
146
+ approvalWarning: 'Cet outil va agir en votre nom. Vérifiez ses arguments avant de l’approuver.',
147
+ rememberChoice: 'Mémoriser mon choix pour cet outil',
148
+ waitingOpen: 'Il vous attend — ouvrez la conversation pour répondre.',
149
+ waitingForYou: 'Il vous attend',
150
+ paused: 'En pause — il répondra de nouveau une fois relancé.',
151
+ moreWaiting: count => `${count} de plus`,
152
+ showMore: 'plus',
153
+ showLess: 'moins',
154
+ now: 'Maintenant',
155
+ conversation: 'Conversation',
156
+ suggestions: 'Suggestions',
157
+ expandConversation: 'Agrandir la conversation',
158
+ expand: 'Agrandir',
159
+ expandWhat: what => `Agrandir ${what}`,
160
+ theVisual: 'le visuel',
161
+ talkTo: name => `Parler à ${name}`,
162
+ },
163
+ es: {
164
+ placeholder: 'Pregunta lo que quieras, escribe / para comandos o @ para mencionar',
165
+ typeMessage: 'Escribe un mensaje...',
166
+ messageInput: 'Entrada del mensaje',
167
+ send: 'Enviar',
168
+ stop: 'Detener',
169
+ pauseKernelBusy: 'Pausa (kernel ocupado)',
170
+ suggestedPrompts: 'Preguntas sugeridas',
171
+ demoKeyExpired: 'Esta demo usa una clave compartida y su tiempo se ha agotado. Inicia sesión para continuar.',
172
+ keyExpired: 'Tu clave ha caducado. Inicia sesión para continuar.',
173
+ startConversation: 'Empieza una conversación',
174
+ sendToBegin: 'Envía un mensaje para empezar',
175
+ copyTurn: 'Copiar este turno',
176
+ removeTurn: 'Eliminar este turno',
177
+ error: message => `Error: ${message}`,
178
+ thinking: 'Pensando…',
179
+ toolPreparing: 'Preparando...',
180
+ toolExecuting: 'Ejecutando...',
181
+ toolComplete: 'Completado',
182
+ toolExecutionFailed: 'Falló la ejecución',
183
+ toolCodeError: 'Error en el código',
184
+ toolExited: 'Terminado',
185
+ toolFailed: 'Falló',
186
+ awaitingApproval: 'Esperando aprobación',
187
+ noParameters: 'Sin parámetros',
188
+ moreArguments: count => `(+${count} más)`,
189
+ parameters: 'Parámetros',
190
+ result: 'Resultado',
191
+ executionError: 'Error de ejecución',
192
+ executionErrorWhy: 'El sandbox o el entorno de ejecución no pudo ejecutar el código.',
193
+ errorHeading: 'Error',
194
+ processExited: 'Proceso terminado',
195
+ exitedWithCode: code => `El proceso terminó con el código ${code}`,
196
+ nonZeroExit: 'El código llamó a sys.exit() con un código de salida distinto de cero.',
197
+ toolRunning: { before: 'Usando ', after: '…' },
198
+ toolDone: { before: 'Hecho: ', after: '' },
199
+ toolFailedLine: { before: '', after: ' falló' },
200
+ approve: 'Aprobar',
201
+ deny: 'Rechazar',
202
+ approveAll: 'Aprobar todo',
203
+ approvalNeeded: 'Esta herramienta necesita tu aprobación para ejecutarse.',
204
+ approvedRunning: 'Aprobado. Ejecutando la herramienta.',
205
+ approvedElsewhere: 'Aprobado desde el panel lateral.',
206
+ deniedWontRun: 'Rechazado. La herramienta no se ejecutará.',
207
+ decidedElsewhere: 'Decisión tomada desde el panel lateral.',
208
+ approvalsPending: count => count === 1
209
+ ? '1 aprobación de herramienta pendiente'
210
+ : `${count} aprobaciones de herramientas pendientes`,
211
+ toolApprovalsPending: 'Aprobaciones de herramientas pendientes',
212
+ collapse: 'Contraer',
213
+ review: 'Revisar',
214
+ dismiss: 'Cerrar',
215
+ approvalTitle: 'Se necesita aprobar la herramienta',
216
+ arguments: 'Argumentos:',
217
+ approvalWarning: 'Esta herramienta actuará en tu nombre. Revisa sus argumentos antes de aprobarla.',
218
+ rememberChoice: 'Recordar mi elección para esta herramienta',
219
+ waitingOpen: 'Te está esperando: abre la conversación para responder.',
220
+ waitingForYou: 'Te está esperando',
221
+ paused: 'En pausa: responderá de nuevo cuando se reanude.',
222
+ moreWaiting: count => `${count} más`,
223
+ showMore: 'más',
224
+ showLess: 'menos',
225
+ now: 'Ahora',
226
+ conversation: 'Conversación',
227
+ suggestions: 'Sugerencias',
228
+ expandConversation: 'Ampliar la conversación',
229
+ expand: 'Ampliar',
230
+ expandWhat: what => `Ampliar ${what}`,
231
+ theVisual: 'el visual',
232
+ talkTo: name => `Hablar con ${name}`,
233
+ },
234
+ de: {
235
+ placeholder: 'Frag, was du willst – / für Befehle, @ zum Erwähnen',
236
+ typeMessage: 'Nachricht schreiben...',
237
+ messageInput: 'Nachrichteneingabe',
238
+ send: 'Senden',
239
+ stop: 'Stoppen',
240
+ pauseKernelBusy: 'Pause (Kernel beschäftigt)',
241
+ suggestedPrompts: 'Vorgeschlagene Fragen',
242
+ demoKeyExpired: 'Diese Demo läuft mit einem geteilten Schlüssel, und ihre Zeit ist abgelaufen. Melde dich an, um weiterzumachen.',
243
+ keyExpired: 'Dein Schlüssel ist abgelaufen. Melde dich an, um weiterzumachen.',
244
+ startConversation: 'Ein Gespräch beginnen',
245
+ sendToBegin: 'Sende eine Nachricht, um zu beginnen',
246
+ copyTurn: 'Diesen Austausch kopieren',
247
+ removeTurn: 'Diesen Austausch entfernen',
248
+ error: message => `Fehler: ${message}`,
249
+ thinking: 'Denkt nach…',
250
+ toolPreparing: 'Wird vorbereitet...',
251
+ toolExecuting: 'Wird ausgeführt...',
252
+ toolComplete: 'Fertig',
253
+ toolExecutionFailed: 'Ausführung fehlgeschlagen',
254
+ toolCodeError: 'Fehler im Code',
255
+ toolExited: 'Beendet',
256
+ toolFailed: 'Fehlgeschlagen',
257
+ awaitingApproval: 'Wartet auf Freigabe',
258
+ noParameters: 'Keine Parameter',
259
+ moreArguments: count => `(+${count} weitere)`,
260
+ parameters: 'Parameter',
261
+ result: 'Ergebnis',
262
+ executionError: 'Ausführungsfehler',
263
+ executionErrorWhy: 'Die Sandbox oder die Ausführungsumgebung konnte den Code nicht ausführen.',
264
+ errorHeading: 'Fehler',
265
+ processExited: 'Prozess beendet',
266
+ exitedWithCode: code => `Der Prozess wurde mit Code ${code} beendet`,
267
+ nonZeroExit: 'Der Code hat sys.exit() mit einem Exit-Code ungleich null aufgerufen.',
268
+ toolRunning: { before: 'Verwendet ', after: '…' },
269
+ toolDone: { before: 'Fertig: ', after: '' },
270
+ toolFailedLine: { before: '', after: ' fehlgeschlagen' },
271
+ approve: 'Freigeben',
272
+ deny: 'Ablehnen',
273
+ approveAll: 'Alle freigeben',
274
+ approvalNeeded: 'Dieses Werkzeug braucht deine Freigabe, um zu laufen.',
275
+ approvedRunning: 'Freigegeben. Das Werkzeug wird ausgeführt.',
276
+ approvedElsewhere: 'In der Seitenleiste freigegeben.',
277
+ deniedWontRun: 'Abgelehnt. Das Werkzeug wird nicht ausgeführt.',
278
+ decidedElsewhere: 'In der Seitenleiste entschieden.',
279
+ approvalsPending: count => count === 1
280
+ ? '1 Werkzeugfreigabe ausstehend'
281
+ : `${count} Werkzeugfreigaben ausstehend`,
282
+ toolApprovalsPending: 'Werkzeugfreigaben ausstehend',
283
+ collapse: 'Einklappen',
284
+ review: 'Prüfen',
285
+ dismiss: 'Schließen',
286
+ approvalTitle: 'Werkzeugfreigabe erforderlich',
287
+ arguments: 'Argumente:',
288
+ approvalWarning: 'Dieses Werkzeug handelt in deinem Namen. Prüfe seine Argumente, bevor du es freigibst.',
289
+ rememberChoice: 'Meine Wahl für dieses Werkzeug merken',
290
+ waitingOpen: 'Wartet auf dich – öffne das Gespräch, um zu antworten.',
291
+ waitingForYou: 'Wartet auf dich',
292
+ paused: 'Pausiert – antwortet wieder, sobald es fortgesetzt wird.',
293
+ moreWaiting: count => `${count} weitere`,
294
+ showMore: 'mehr',
295
+ showLess: 'weniger',
296
+ now: 'Jetzt',
297
+ conversation: 'Gespräch',
298
+ suggestions: 'Vorschläge',
299
+ expandConversation: 'Gespräch vergrößern',
300
+ expand: 'Vergrößern',
301
+ expandWhat: what => `${what} vergrößern`,
302
+ theVisual: 'die Darstellung',
303
+ talkTo: name => `Mit ${name} sprechen`,
304
+ },
305
+ it: {
306
+ placeholder: 'Chiedi quello che vuoi, digita / per i comandi o @ per menzionare',
307
+ typeMessage: 'Scrivi un messaggio...',
308
+ messageInput: 'Campo del messaggio',
309
+ send: 'Invia',
310
+ stop: 'Interrompi',
311
+ pauseKernelBusy: 'Pausa (kernel occupato)',
312
+ suggestedPrompts: 'Domande suggerite',
313
+ demoKeyExpired: 'Questa demo usa una chiave condivisa e il suo tempo è scaduto. Accedi per continuare.',
314
+ keyExpired: 'La tua chiave è scaduta. Accedi per continuare.',
315
+ startConversation: 'Inizia una conversazione',
316
+ sendToBegin: 'Invia un messaggio per iniziare',
317
+ copyTurn: 'Copia questo scambio',
318
+ removeTurn: 'Rimuovi questo scambio',
319
+ error: message => `Errore: ${message}`,
320
+ thinking: 'Sta pensando…',
321
+ toolPreparing: 'Preparazione...',
322
+ toolExecuting: 'Esecuzione...',
323
+ toolComplete: 'Completato',
324
+ toolExecutionFailed: 'Esecuzione non riuscita',
325
+ toolCodeError: 'Errore nel codice',
326
+ toolExited: 'Terminato',
327
+ toolFailed: 'Non riuscito',
328
+ awaitingApproval: 'In attesa di approvazione',
329
+ noParameters: 'Nessun parametro',
330
+ moreArguments: count => `(+${count} altri)`,
331
+ parameters: 'Parametri',
332
+ result: 'Risultato',
333
+ executionError: 'Errore di esecuzione',
334
+ executionErrorWhy: 'La sandbox o l’ambiente di esecuzione non è riuscito a eseguire il codice.',
335
+ errorHeading: 'Errore',
336
+ processExited: 'Processo terminato',
337
+ exitedWithCode: code => `Il processo è terminato con il codice ${code}`,
338
+ nonZeroExit: 'Il codice ha chiamato sys.exit() con un codice di uscita diverso da zero.',
339
+ toolRunning: { before: 'Usa ', after: '…' },
340
+ toolDone: { before: 'Fatto: ', after: '' },
341
+ toolFailedLine: { before: '', after: ' non riuscito' },
342
+ approve: 'Approva',
343
+ deny: 'Rifiuta',
344
+ approveAll: 'Approva tutto',
345
+ approvalNeeded: 'Questo strumento ha bisogno della tua approvazione per essere eseguito.',
346
+ approvedRunning: 'Approvato. Esecuzione dello strumento.',
347
+ approvedElsewhere: 'Approvato dal pannello laterale.',
348
+ deniedWontRun: 'Rifiutato. Lo strumento non verrà eseguito.',
349
+ decidedElsewhere: 'Decisione presa dal pannello laterale.',
350
+ approvalsPending: count => count === 1
351
+ ? '1 approvazione di strumento in attesa'
352
+ : `${count} approvazioni di strumenti in attesa`,
353
+ toolApprovalsPending: 'Approvazioni di strumenti in attesa',
354
+ collapse: 'Comprimi',
355
+ review: 'Esamina',
356
+ dismiss: 'Chiudi',
357
+ approvalTitle: 'Approvazione dello strumento richiesta',
358
+ arguments: 'Argomenti:',
359
+ approvalWarning: 'Questo strumento agirà per tuo conto. Controlla i suoi argomenti prima di approvarlo.',
360
+ rememberChoice: 'Ricorda la mia scelta per questo strumento',
361
+ waitingOpen: 'Ti sta aspettando: apri la conversazione per rispondere.',
362
+ waitingForYou: 'Ti sta aspettando',
363
+ paused: 'In pausa: risponderà di nuovo quando verrà ripreso.',
364
+ moreWaiting: count => `altri ${count}`,
365
+ showMore: 'altro',
366
+ showLess: 'meno',
367
+ now: 'Ora',
368
+ conversation: 'Conversazione',
369
+ suggestions: 'Suggerimenti',
370
+ expandConversation: 'Espandi la conversazione',
371
+ expand: 'Espandi',
372
+ expandWhat: what => `Espandi ${what}`,
373
+ theVisual: 'la visualizzazione',
374
+ talkTo: name => `Parla con ${name}`,
375
+ },
376
+ pt: {
377
+ placeholder: 'Pergunte o que quiser, digite / para comandos ou @ para mencionar',
378
+ typeMessage: 'Escreva uma mensagem...',
379
+ messageInput: 'Campo da mensagem',
380
+ send: 'Enviar',
381
+ stop: 'Parar',
382
+ pauseKernelBusy: 'Pausar (kernel ocupado)',
383
+ suggestedPrompts: 'Perguntas sugeridas',
384
+ demoKeyExpired: 'Esta demonstração usa uma chave compartilhada e o tempo dela acabou. Entre para continuar.',
385
+ keyExpired: 'Sua chave expirou. Entre para continuar.',
386
+ startConversation: 'Comece uma conversa',
387
+ sendToBegin: 'Envie uma mensagem para começar',
388
+ copyTurn: 'Copiar esta troca',
389
+ removeTurn: 'Remover esta troca',
390
+ error: message => `Erro: ${message}`,
391
+ thinking: 'Pensando…',
392
+ toolPreparing: 'Preparando...',
393
+ toolExecuting: 'Executando...',
394
+ toolComplete: 'Concluído',
395
+ toolExecutionFailed: 'Falha na execução',
396
+ toolCodeError: 'Erro no código',
397
+ toolExited: 'Encerrado',
398
+ toolFailed: 'Falhou',
399
+ awaitingApproval: 'Aguardando aprovação',
400
+ noParameters: 'Sem parâmetros',
401
+ moreArguments: count => `(+${count} mais)`,
402
+ parameters: 'Parâmetros',
403
+ result: 'Resultado',
404
+ executionError: 'Erro de execução',
405
+ executionErrorWhy: 'O sandbox ou o ambiente de execução não conseguiu executar o código.',
406
+ errorHeading: 'Erro',
407
+ processExited: 'Processo encerrado',
408
+ exitedWithCode: code => `O processo terminou com o código ${code}`,
409
+ nonZeroExit: 'O código chamou sys.exit() com um código de saída diferente de zero.',
410
+ toolRunning: { before: 'Usando ', after: '…' },
411
+ toolDone: { before: 'Concluído: ', after: '' },
412
+ toolFailedLine: { before: '', after: ' falhou' },
413
+ approve: 'Aprovar',
414
+ deny: 'Recusar',
415
+ approveAll: 'Aprovar tudo',
416
+ approvalNeeded: 'Esta ferramenta precisa da sua aprovação para ser executada.',
417
+ approvedRunning: 'Aprovado. Executando a ferramenta.',
418
+ approvedElsewhere: 'Aprovado pelo painel lateral.',
419
+ deniedWontRun: 'Recusado. A ferramenta não será executada.',
420
+ decidedElsewhere: 'Decisão tomada pelo painel lateral.',
421
+ approvalsPending: count => count === 1
422
+ ? '1 aprovação de ferramenta pendente'
423
+ : `${count} aprovações de ferramentas pendentes`,
424
+ toolApprovalsPending: 'Aprovações de ferramentas pendentes',
425
+ collapse: 'Recolher',
426
+ review: 'Revisar',
427
+ dismiss: 'Fechar',
428
+ approvalTitle: 'Aprovação da ferramenta necessária',
429
+ arguments: 'Argumentos:',
430
+ approvalWarning: 'Esta ferramenta vai agir em seu nome. Revise os argumentos antes de aprovar.',
431
+ rememberChoice: 'Lembrar minha escolha para esta ferramenta',
432
+ waitingOpen: 'Esperando por você — abra a conversa para responder.',
433
+ waitingForYou: 'Esperando por você',
434
+ paused: 'Em pausa — volta a responder quando for retomado.',
435
+ moreWaiting: count => `mais ${count}`,
436
+ showMore: 'mais',
437
+ showLess: 'menos',
438
+ now: 'Agora',
439
+ conversation: 'Conversa',
440
+ suggestions: 'Sugestões',
441
+ expandConversation: 'Ampliar a conversa',
442
+ expand: 'Ampliar',
443
+ expandWhat: what => `Ampliar ${what}`,
444
+ theVisual: 'o visual',
445
+ talkTo: name => `Falar com ${name}`,
446
+ },
447
+ };
448
+ /** The English words: what the chat says when nothing says a language. */
449
+ export const ENGLISH_CHAT_WORDS = CHAT_WORDS.en;
450
+ /**
451
+ * The language the chat speaks to a person who prefers these, as BCP 47
452
+ * tags them: the first it is said in (`fr-CA` reads `fr`), else English.
453
+ */
454
+ export function chatLanguage(preferred) {
455
+ return pickLanguage(Object.keys(CHAT_WORDS), preferred) ?? 'en';
456
+ }
457
+ /** The chat's words in a language: its own, else its language's, else English. */
458
+ export function chatWords(language) {
459
+ return CHAT_WORDS[chatLanguage(language ? [language] : [])];
460
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Components an application's developer wrote, drawn (LOOP P-17): an A2UI
3
+ * component of that application only, made as Datalayer's own are — its
4
+ * schema from its declaration (`componentSchemaOf`), its view by A2UI's own
5
+ * factory — so that it binds and acts as a Table does, and drawn in a
6
+ * sandboxed frame of no origin (`./sandbox`): its properties and what it
7
+ * shows go in, what it sends comes out, written where its binding points and
8
+ * then its action dispatched.
9
+ *
10
+ * Never global: `customImplementations(app)` is handed to the catalog of
11
+ * that application's page (`catalogOfBlocks`), and to no other.
12
+ *
13
+ * @module components/a2ui/custom
14
+ */
15
+ import type { JSX } from 'react';
16
+ import { type ReactComponentImplementation } from '@a2ui/react/v0_9';
17
+ import type { AppCustomComponentSpec, AppSpec } from '../../../types/agentspecs';
18
+ type CustomProps = Record<string, unknown> & {
19
+ action?: () => void;
20
+ weight?: number;
21
+ };
22
+ /** What the frame is given: its declared properties and what it shows, nothing else. */
23
+ export declare function givenToFrame(component: AppCustomComponentSpec, props: Record<string, unknown>): Record<string, unknown>;
24
+ /** A component its developer wrote, in its frame. */
25
+ export declare function CustomComponentView({ component, props, fetcher, }: {
26
+ component: AppCustomComponentSpec;
27
+ props: CustomProps;
28
+ /** How its module is fetched; the page's `fetch` unless given (tests). */
29
+ fetcher?: typeof fetch;
30
+ }): JSX.Element;
31
+ /**
32
+ * A component its developer wrote as A2UI's renderer registers one: its
33
+ * schema from its declaration, its view by A2UI's own factory, drawn in its
34
+ * frame.
35
+ */
36
+ export declare function customImplementation(component: AppCustomComponentSpec, version?: string, fetcher?: typeof fetch): ReactComponentImplementation;
37
+ /** The renderers of the components an application's developer wrote, for its page alone. */
38
+ export declare function customImplementations(app: Pick<AppSpec, 'interface' | 'version'>, fetcher?: typeof fetch): ReactComponentImplementation[];
39
+ export { CUSTOM_FRAME_SANDBOX, customFrameDocument, customFramePolicy, customModule, fromFrame, integrityHolds, } from './sandbox';
@@ -0,0 +1,95 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef, useState } from 'react';
3
+ import { createComponentImplementation, } from '@a2ui/react/v0_9';
4
+ import { customComponentEntry } from '../../../loop/apps/customComponents';
5
+ import { componentSchemaOf } from '../datalayer/schema';
6
+ import { BlockFrame, Problem } from '../datalayer/parts';
7
+ import { CUSTOM_FRAME_SANDBOX, FRAME_TAG, customFrameDocument, customModule, frameNonce, fromFrame, } from './sandbox';
8
+ /** What the frame is given: its declared properties and what it shows, nothing else. */
9
+ export function givenToFrame(component, props) {
10
+ const declared = Object.keys((component.props.properties ?? {}));
11
+ const names = new Set([...declared, ...component.shows, ...component.sends]);
12
+ return Object.fromEntries(Object.entries(props).filter(([name, value]) => names.has(name) && typeof value !== 'function'));
13
+ }
14
+ /** The setter A2UI gives a binding: `setValue` for `value`. */
15
+ const setterOf = (name) => `set${name.charAt(0).toUpperCase()}${name.slice(1)}`;
16
+ /** A component its developer wrote, in its frame. */
17
+ export function CustomComponentView({ component, props, fetcher, }) {
18
+ const frame = useRef(null);
19
+ const [problem, setProblem] = useState(null);
20
+ const [ready, setReady] = useState(false);
21
+ const srcDoc = useMemo(() => customFrameDocument(frameNonce(), component.name), [component.name]);
22
+ // What it is given, told again only when a value of it changes.
23
+ const givenKey = JSON.stringify(givenToFrame(component, props));
24
+ const given = useMemo(() => JSON.parse(givenKey), [givenKey]);
25
+ const propsRef = useRef(props);
26
+ propsRef.current = props;
27
+ const tell = (message) => frame.current?.contentWindow?.postMessage(message, '*');
28
+ useEffect(() => {
29
+ const listen = (event) => {
30
+ const said = fromFrame(event, frame.current?.contentWindow);
31
+ if (!said) {
32
+ return;
33
+ }
34
+ if (said.kind === 'ready') {
35
+ customModule(component.source, component.integrity, fetcher)
36
+ .then(code => {
37
+ tell({
38
+ tag: FRAME_TAG,
39
+ kind: 'props',
40
+ props: givenToFrame(component, propsRef.current),
41
+ });
42
+ tell({ tag: FRAME_TAG, kind: 'module', code });
43
+ setReady(true);
44
+ })
45
+ .catch((error) => setProblem(error instanceof Error ? error.message : String(error)));
46
+ }
47
+ else if (said.kind === 'failed') {
48
+ setProblem(`It could not be drawn: ${said.message}.`);
49
+ }
50
+ else if (said.kind === 'send') {
51
+ // What it sends is what it declares, and nothing else.
52
+ if (!component.sends.includes(said.name)) {
53
+ setProblem(`It sent “${said.name}”, which it does not declare under \`sends\`.`);
54
+ return;
55
+ }
56
+ const set = propsRef.current[setterOf(said.name)];
57
+ if (typeof set === 'function') {
58
+ set(said.value);
59
+ }
60
+ propsRef.current.action?.();
61
+ }
62
+ };
63
+ window.addEventListener('message', listen);
64
+ return () => window.removeEventListener('message', listen);
65
+ // eslint-disable-next-line react-hooks/exhaustive-deps
66
+ }, [component, fetcher]);
67
+ useEffect(() => {
68
+ if (ready) {
69
+ tell({ tag: FRAME_TAG, kind: 'props', props: given });
70
+ }
71
+ // eslint-disable-next-line react-hooks/exhaustive-deps
72
+ }, [ready, given]);
73
+ return (_jsxs(BlockFrame, { label: component.description || component.name, weight: props.weight, testId: `custom-${component.name}`, children: [problem ? _jsx(Problem, { children: problem }) : null, _jsx("iframe", { ref: frame, title: component.description || component.name, sandbox: CUSTOM_FRAME_SANDBOX, srcDoc: srcDoc, referrerPolicy: "no-referrer", style: {
74
+ width: '100%',
75
+ height: `${component.height}px`,
76
+ border: 0,
77
+ display: 'block',
78
+ } })] }));
79
+ }
80
+ /**
81
+ * A component its developer wrote as A2UI's renderer registers one: its
82
+ * schema from its declaration, its view by A2UI's own factory, drawn in its
83
+ * frame.
84
+ */
85
+ export function customImplementation(component, version = '0.0.0', fetcher) {
86
+ const entry = customComponentEntry(component, version);
87
+ const api = { name: component.name, schema: componentSchemaOf(entry) };
88
+ const Render = ({ props }) => (_jsx(CustomComponentView, { component: component, props: props, fetcher: fetcher }));
89
+ return createComponentImplementation(api, Render);
90
+ }
91
+ /** The renderers of the components an application's developer wrote, for its page alone. */
92
+ export function customImplementations(app, fetcher) {
93
+ return (app.interface.customComponents ?? []).map(component => customImplementation(component, app.version, fetcher));
94
+ }
95
+ export { CUSTOM_FRAME_SANDBOX, customFrameDocument, customFramePolicy, customModule, fromFrame, integrityHolds, } from './sandbox';
@@ -0,0 +1,73 @@
1
+ /**
2
+ * The frame a component its developer wrote is drawn in (LOOP P-17), and
3
+ * what passes between it and the page.
4
+ *
5
+ * A hosted application lives on the origin where people are signed in, and
6
+ * no script an application supplies reaches that page (LOOP D-22). A custom
7
+ * component's module is such a script, so it never runs in the page: it runs
8
+ * in an `<iframe sandbox="allow-scripts">` — no `allow-same-origin`, so the
9
+ * frame has an origin of its own that is no one's: no cookie, no storage, no
10
+ * access to the page, its DOM or its tokens — whose document allows nothing
11
+ * but its own bootstrap and the module it is handed (`default-src 'none'`):
12
+ * no request leaves the frame, no form, no navigation of the page.
13
+ *
14
+ * The page fetches the module — without credentials — checks it against the
15
+ * hash it was reviewed with when the spec gives one (`integrity`), and hands
16
+ * its text to the frame, which imports it from a `blob:` address. Its
17
+ * default export draws it: `export default function (root, {props, send})`,
18
+ * returning `{update(props)}` to be told of new properties. What it is given
19
+ * is its properties and what it shows; what it gives back is what it sends,
20
+ * by name, each refused unless declared.
21
+ *
22
+ * @module components/a2ui/custom/sandbox
23
+ */
24
+ /** What the frame of a custom component may do: run scripts, nothing else. */
25
+ export declare const CUSTOM_FRAME_SANDBOX = "allow-scripts";
26
+ /** The largest module the page hands to a frame, in bytes. */
27
+ export declare const MAX_MODULE_BYTES: number;
28
+ /** The tag every message between the page and a frame carries. */
29
+ export declare const FRAME_TAG = "loop.component";
30
+ /** What the page tells the frame. */
31
+ export type ToFrame = {
32
+ tag: typeof FRAME_TAG;
33
+ kind: 'module';
34
+ code: string;
35
+ } | {
36
+ tag: typeof FRAME_TAG;
37
+ kind: 'props';
38
+ props: Record<string, unknown>;
39
+ };
40
+ /** What the frame tells the page. */
41
+ export type FromFrame = {
42
+ kind: 'ready';
43
+ } | {
44
+ kind: 'drawn';
45
+ } | {
46
+ kind: 'failed';
47
+ message: string;
48
+ } | {
49
+ kind: 'send';
50
+ name: string;
51
+ value: unknown;
52
+ };
53
+ /** The policy of the frame's document: its bootstrap, the module it is handed, nothing else. */
54
+ export declare function customFramePolicy(nonce: string): string;
55
+ /** A nonce for one frame's bootstrap. */
56
+ export declare function frameNonce(): string;
57
+ /**
58
+ * The document of a custom component's frame (its `srcdoc`): the policy,
59
+ * the root it draws into, and the bootstrap that imports the module it is
60
+ * handed and passes properties in and what it sends out.
61
+ */
62
+ export declare function customFrameDocument(nonce: string, label: string): string;
63
+ /** What a frame said, when it is a message of the frame drawn here; null otherwise. */
64
+ export declare function fromFrame(event: Pick<MessageEvent, 'source' | 'data'>, frame: Window | null | undefined): FromFrame | null;
65
+ /** Whether a module's bytes are the ones its Subresource Integrity hash names. */
66
+ export declare function integrityHolds(bytes: ArrayBuffer, integrity: string): Promise<boolean>;
67
+ /**
68
+ * The text of a custom component's module, fetched without credentials and
69
+ * checked against its hash when one is given. It throws, with a sentence,
70
+ * for a module that cannot be fetched, is too large, or is not the one
71
+ * reviewed.
72
+ */
73
+ export declare function customModule(source: string, integrity: string, fetcher?: typeof fetch): Promise<string>;