@datalayer/agent-runtimes 1.3.83 → 1.3.85

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 (168) 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 +30 -11
  17. package/lib/chat/base/loopElement.d.ts +53 -0
  18. package/lib/chat/base/loopElement.js +78 -0
  19. package/lib/chat/base/loopWindow.d.ts +31 -0
  20. package/lib/chat/base/loopWindow.js +74 -0
  21. package/lib/chat/display/EmptyState.js +3 -1
  22. package/lib/chat/index.d.ts +2 -0
  23. package/lib/chat/index.js +3 -0
  24. package/lib/chat/messages/ChatMessages.js +3 -1
  25. package/lib/chat/messages/TurnFooter.js +3 -1
  26. package/lib/chat/prompt/InputPrompt.js +3 -1
  27. package/lib/chat/prompt/InputPromptLexical.js +3 -1
  28. package/lib/chat/prompt/footer/InPromptFooter.js +3 -1
  29. package/lib/chat/tools/ToolApprovalBanner.js +5 -3
  30. package/lib/chat/tools/ToolApprovalDialog.js +5 -3
  31. package/lib/chat/tools/ToolCallDisplay.js +29 -25
  32. package/lib/chat/words.d.ts +102 -0
  33. package/lib/chat/words.js +460 -0
  34. package/lib/components/a2ui/custom/index.d.ts +39 -0
  35. package/lib/components/a2ui/custom/index.js +95 -0
  36. package/lib/components/a2ui/custom/sandbox.d.ts +73 -0
  37. package/lib/components/a2ui/custom/sandbox.js +188 -0
  38. package/lib/components/a2ui/datalayer/FileUpload.d.ts +10 -2
  39. package/lib/components/a2ui/datalayer/FileUpload.js +10 -7
  40. package/lib/components/a2ui/datalayer/Form.d.ts +2 -0
  41. package/lib/components/a2ui/datalayer/Form.js +9 -2
  42. package/lib/components/a2ui/datalayer/formWidgets.d.ts +19 -0
  43. package/lib/components/a2ui/datalayer/formWidgets.js +51 -0
  44. package/lib/components/a2ui/datalayer/index.d.ts +1 -1
  45. package/lib/components/a2ui/datalayer/index.js +1 -1
  46. package/lib/components/a2ui/datalayer/schema.d.ts +10 -0
  47. package/lib/components/a2ui/datalayer/schema.js +12 -1
  48. package/lib/components/a2ui/index.d.ts +1 -0
  49. package/lib/components/a2ui/index.js +1 -0
  50. package/lib/components/a2ui/visibleWhen.d.ts +12 -1
  51. package/lib/components/a2ui/visibleWhen.js +24 -3
  52. package/lib/components/inspector/AgentInspector.d.ts +25 -44
  53. package/lib/components/inspector/AgentInspector.js +27 -215
  54. package/lib/components/inspector/AgentInspectorDialog.d.ts +6 -6
  55. package/lib/components/inspector/AgentInspectorDialog.js +2 -2
  56. package/lib/components/inspector/a2aSpans.d.ts +51 -0
  57. package/lib/components/inspector/a2aSpans.js +373 -0
  58. package/lib/components/inspector/agentSpans.d.ts +120 -0
  59. package/lib/components/inspector/agentSpans.js +253 -0
  60. package/lib/components/inspector/chatSpans.d.ts +36 -0
  61. package/lib/components/inspector/chatSpans.js +50 -0
  62. package/lib/components/inspector/classify.d.ts +11 -8
  63. package/lib/components/inspector/classify.js +23 -24
  64. package/lib/components/inspector/index.d.ts +7 -7
  65. package/lib/components/inspector/index.js +7 -7
  66. package/lib/components/teams/A2ATeamGraph.d.ts +4 -4
  67. package/lib/components/teams/SceneTranscript.d.ts +29 -0
  68. package/lib/components/teams/SceneTranscript.js +54 -0
  69. package/lib/components/teams/SceneView.d.ts +41 -0
  70. package/lib/components/teams/SceneView.js +28 -0
  71. package/lib/components/teams/index.d.ts +3 -0
  72. package/lib/components/teams/index.js +3 -0
  73. package/lib/components/teams/sceneTranscript.d.ts +74 -0
  74. package/lib/components/teams/sceneTranscript.js +294 -0
  75. package/lib/components/teams/teamConnections.d.ts +2 -2
  76. package/lib/components/teams/teamConnections.js +3 -3
  77. package/lib/components/teams/useA2ATeam.d.ts +4 -4
  78. package/lib/components/teams/useA2ATeam.js +50 -46
  79. package/lib/examples/AgentA2ATeamExample.d.ts +10 -9
  80. package/lib/examples/AgentA2ATeamExample.js +70 -60
  81. package/lib/examples/AssistantExample.js +2 -2
  82. package/lib/loop/apps/AppComposer.d.ts +40 -4
  83. package/lib/loop/apps/AppComposer.js +194 -19
  84. package/lib/loop/apps/AppRenderer.d.ts +21 -3
  85. package/lib/loop/apps/AppRenderer.js +88 -48
  86. package/lib/loop/apps/appspec.d.ts +13 -1
  87. package/lib/loop/apps/appspec.js +305 -12
  88. package/lib/loop/apps/checks.d.ts +14 -0
  89. package/lib/loop/apps/checks.js +276 -5
  90. package/lib/loop/apps/composer.d.ts +21 -10
  91. package/lib/loop/apps/composer.js +41 -8
  92. package/lib/loop/apps/customComponents.d.ts +41 -0
  93. package/lib/loop/apps/customComponents.js +260 -0
  94. package/lib/loop/apps/hostTools.d.ts +8 -1
  95. package/lib/loop/apps/hostTools.js +9 -0
  96. package/lib/loop/apps/index.d.ts +1 -0
  97. package/lib/loop/apps/index.js +1 -0
  98. package/lib/loop/apps/language.d.ts +68 -0
  99. package/lib/loop/apps/language.js +275 -0
  100. package/lib/loop/apps/settingsInputs.d.ts +29 -0
  101. package/lib/loop/apps/settingsInputs.js +147 -0
  102. package/lib/loop/apps/uploads.d.ts +43 -0
  103. package/lib/loop/apps/uploads.js +66 -0
  104. package/lib/loop/core/a2uiComponents.d.ts +10 -0
  105. package/lib/loop/core/a2uiComponents.js +15 -0
  106. package/lib/loop/core/index.d.ts +15 -1
  107. package/lib/loop/core/index.js +3 -0
  108. package/lib/loop/embed/AppEmbed.d.ts +25 -3
  109. package/lib/loop/embed/AppEmbed.js +106 -18
  110. package/lib/loop/embed/element.d.ts +5 -0
  111. package/lib/loop/embed/element.js +84 -5
  112. package/lib/loop/embed/embedConfig.d.ts +8 -0
  113. package/lib/loop/embed/embedConfig.js +18 -0
  114. package/lib/loop/embed/embedSession.d.ts +14 -0
  115. package/lib/loop/embed/embedSession.js +34 -0
  116. package/lib/loop/embed/hostBridge.d.ts +50 -3
  117. package/lib/loop/embed/hostBridge.js +22 -2
  118. package/lib/loop/index.d.ts +4 -3
  119. package/lib/loop/index.js +4 -3
  120. package/lib/loop/plugins/a2ui-surface/InlineSurface.d.ts +7 -1
  121. package/lib/loop/plugins/a2ui-surface/InlineSurface.js +7 -2
  122. package/lib/loop/plugins/a2ui-surface/SurfaceToolResult.js +4 -1
  123. package/lib/loop/plugins/a2ui-surface/ownComponents.d.ts +6 -0
  124. package/lib/loop/plugins/a2ui-surface/ownComponents.js +30 -0
  125. package/lib/loop/plugins/app-components/index.d.ts +26 -0
  126. package/lib/loop/plugins/app-components/index.js +56 -0
  127. package/lib/loop/plugins/app-elements/AppElements.d.ts +27 -0
  128. package/lib/loop/plugins/app-elements/AppElements.js +79 -0
  129. package/lib/loop/plugins/app-elements/index.d.ts +20 -0
  130. package/lib/loop/plugins/app-elements/index.js +43 -0
  131. package/lib/loop/plugins/app-page/AppPage.d.ts +9 -0
  132. package/lib/loop/plugins/app-page/AppPage.js +106 -8
  133. package/lib/loop/plugins/app-page/appPageModel.d.ts +17 -1
  134. package/lib/loop/plugins/app-page/appPageModel.js +122 -4
  135. package/lib/loop/plugins/app-page/index.d.ts +1 -0
  136. package/lib/loop/plugins/app-page/index.js +1 -0
  137. package/lib/loop/plugins/app-page/pageRun.d.ts +46 -0
  138. package/lib/loop/plugins/app-page/pageRun.js +111 -0
  139. package/lib/loop/plugins/assistant/index.js +8 -6
  140. package/lib/loop/plugins/chat/ChatView.js +16 -6
  141. package/lib/loop/plugins/chat/index.d.ts +1 -1
  142. package/lib/loop/plugins/chat/index.js +2 -1
  143. package/lib/models/PageTag.d.ts +1 -1
  144. package/lib/protocols/BrowserAgentAdapter.d.ts +8 -6
  145. package/lib/protocols/BrowserAgentAdapter.js +13 -10
  146. package/lib/runtimes/browser/a2aPeer.d.ts +2 -1
  147. package/lib/runtimes/browser/protocol.d.ts +1 -1
  148. package/lib/specs/actions.js +78 -1
  149. package/lib/specs/apps.d.ts +5 -0
  150. package/lib/specs/apps.js +1518 -216
  151. package/lib/specs/appspecSchema.js +630 -3
  152. package/lib/specs/teams/teams.d.ts +3 -0
  153. package/lib/specs/teams/teams.js +249 -0
  154. package/lib/specs/uiPlugins.js +6 -1
  155. package/lib/types/agentspecs.d.ts +200 -1
  156. package/lib/types/chat.d.ts +6 -5
  157. package/lib/types/teams.d.ts +13 -2
  158. package/package.json +2 -2
  159. package/scripts/codegen/generate_apps.py +20 -2
  160. package/scripts/codegen/generate_teams.py +15 -2
  161. package/lib/components/inspector/JsonTree.d.ts +0 -24
  162. package/lib/components/inspector/JsonTree.js +0 -89
  163. package/lib/components/inspector/a2aInspect.d.ts +0 -56
  164. package/lib/components/inspector/a2aInspect.js +0 -478
  165. package/lib/components/inspector/agentInspector.d.ts +0 -179
  166. package/lib/components/inspector/agentInspector.js +0 -267
  167. package/lib/components/inspector/chatInspect.d.ts +0 -38
  168. package/lib/components/inspector/chatInspect.js +0 -65
package/lib/specs/apps.js CHANGED
@@ -16,6 +16,7 @@ export const ACCOUNTING_APP_0_0_1 = {
16
16
  model: '',
17
17
  skills: [],
18
18
  backendTools: [],
19
+ tools: [],
19
20
  context: [],
20
21
  contents: [],
21
22
  connections: [
@@ -66,6 +67,9 @@ export const ACCOUNTING_APP_0_0_1 = {
66
67
  ],
67
68
  commands: [],
68
69
  modes: [],
70
+ profiles: [],
71
+ language: 'en',
72
+ translations: {},
69
73
  components: [],
70
74
  assistant: 'wizard',
71
75
  voice: {
@@ -119,6 +123,7 @@ export const ACCOUNTING_APP_0_0_1 = {
119
123
  guards: [],
120
124
  gates: [],
121
125
  track: '',
126
+ code: [],
122
127
  },
123
128
  deployment: {
124
129
  hosted: {
@@ -142,6 +147,302 @@ export const ACCOUNTING_APP_0_0_1 = {
142
147
  "The MCP server 'odoo-accounting:0.0.1' is not enabled.",
143
148
  ],
144
149
  };
150
+ export const CHANGE_DETECTION_APP_0_0_1 = {
151
+ schema: 'loop.app/v1',
152
+ id: 'change-detection',
153
+ version: '0.0.1',
154
+ name: 'Change detection',
155
+ kind: 'chat',
156
+ description: 'Finds what changed on the ground between two dates — land use, vegetation, water, built-up area — from the satellite imagery NASA Earthdata holds, which it searches and reads, with the granules behind each change it reports.',
157
+ owner: 'Datalayer <info@datalayer.io>',
158
+ agent: 'worker-change-detection:0.0.1',
159
+ team: '',
160
+ instructions: 'You detect change from satellite imagery. Requests usually come from the Event response application over A2A, and you answer them from NASA Earthdata, which you reach through the earthdata tools: search the datasets that observe the surface at the place asked, then the granules at the first date and at the second, and compare what they show. You download nothing: when data must be fetched, describe it and write the script a person would run. Answer with the change itself: the place and the two dates, each change you read — where, what kind, how large — and how confident you are, the dataset and granule behind each one. When a request does not say the place or the dates, say what you need. When Earthdata holds nothing for it, say so plainly and do not fill the gap.',
161
+ model: '',
162
+ skills: [],
163
+ backendTools: [],
164
+ tools: [],
165
+ context: [],
166
+ contents: [],
167
+ connections: [
168
+ {
169
+ server: 'earthdata:0.0.1',
170
+ access: 'read',
171
+ as: 'owner',
172
+ only: [],
173
+ },
174
+ ],
175
+ rules: [
176
+ {
177
+ action: 'Search and read the imagery',
178
+ appliesTo: ['read'],
179
+ behaviour: 'do_it',
180
+ },
181
+ {
182
+ action: 'Download files to the runtime',
183
+ appliesTo: ['write'],
184
+ behaviour: 'ask_first',
185
+ },
186
+ ],
187
+ permissions: {
188
+ spaces: [],
189
+ computer: {
190
+ browse: false,
191
+ files: false,
192
+ shell: false,
193
+ },
194
+ },
195
+ interface: {
196
+ layout: 'chat',
197
+ accent: 'violet',
198
+ welcome: "Give me a place and two dates, and I'll tell you what changed on the ground between them from the satellite imagery NASA Earthdata holds. I search and read; I download nothing.",
199
+ starters: [
200
+ {
201
+ label: 'Change between two dates',
202
+ message: 'What changed around 39.5N, 0.4W between 1 October and 15 November 2024?',
203
+ },
204
+ {
205
+ label: 'Water extent',
206
+ message: 'How did the water extent change around the Ahr valley between 10 and 20 July 2021?',
207
+ },
208
+ {
209
+ label: 'Imagery at two dates',
210
+ message: 'Which granules cover Los Angeles on 1 January and 15 January 2025?',
211
+ },
212
+ ],
213
+ commands: [],
214
+ modes: [],
215
+ profiles: [],
216
+ language: 'en',
217
+ translations: {},
218
+ components: [],
219
+ assistant: 'cat',
220
+ voice: {
221
+ enabled: false,
222
+ input: 'push_to_talk',
223
+ output: 'on_request',
224
+ voice: '',
225
+ language: '',
226
+ where: 'auto',
227
+ },
228
+ outputs: ['text/markdown', 'application/x-ipynb+json'],
229
+ },
230
+ tests: {
231
+ readyAt: 0.8,
232
+ evalset: '',
233
+ cases: [
234
+ {
235
+ ask: 'What changed around 39.5N, 0.4W between 1 October and 15 November 2024?',
236
+ expect: 'It searches the datasets and the granules at both dates with the earthdata tools and answers with each change it read, its kind and its size, and the granules behind it.',
237
+ },
238
+ {
239
+ ask: 'Which granules cover Los Angeles on 1 January and 15 January 2025?',
240
+ expect: 'It lists the granules at both dates, with their datasets, and downloads nothing.',
241
+ },
242
+ {
243
+ ask: 'Download the granules at both dates.',
244
+ expect: 'It does not download them. It writes the script a person would run, and says what it would fetch.',
245
+ },
246
+ {
247
+ ask: 'What changed?',
248
+ expect: 'It asks where and between which dates, before it searches.',
249
+ },
250
+ ],
251
+ verified: {
252
+ live: [],
253
+ recorded: [],
254
+ unverified: [
255
+ 'It has not been asked live over A2A yet: its agent is set up, not enabled, on this machine; the earthdata server is enabled.',
256
+ 'Its tests have not been run as a set: no validation run is attached to it.',
257
+ ],
258
+ },
259
+ },
260
+ record: {
261
+ keepFor: '30_days',
262
+ include: ['conversations'],
263
+ suggestTests: false,
264
+ retentionDays: 30,
265
+ },
266
+ checks: {
267
+ guards: [],
268
+ gates: [],
269
+ track: '',
270
+ code: [],
271
+ },
272
+ deployment: {
273
+ hosted: {
274
+ visibility: 'private',
275
+ slug: '',
276
+ },
277
+ },
278
+ goal: '',
279
+ triggers: [],
280
+ memory: '',
281
+ notifications: [],
282
+ enabled: true,
283
+ unavailable_because: '',
284
+ tags: [
285
+ 'example',
286
+ 'earth-observation',
287
+ 'change-detection',
288
+ 'earthdata',
289
+ 'a2a',
290
+ 'scene',
291
+ ],
292
+ icon: 'telescope',
293
+ emoji: '🔍',
294
+ avatar: '',
295
+ banner: '',
296
+ setup: ["The agent 'worker-change-detection:0.0.1' is not enabled."],
297
+ };
298
+ export const CROP_MONITORING_APP_0_0_1 = {
299
+ schema: 'loop.app/v1',
300
+ id: 'crop-monitoring',
301
+ version: '0.0.1',
302
+ name: 'Crop monitoring',
303
+ kind: 'chat',
304
+ description: 'Tracks crop vigour and growth over time from the satellite imagery NASA Earthdata holds, which it searches and reads, and flags the fields that need attention, with the datasets and granules behind each finding.',
305
+ owner: 'Datalayer <info@datalayer.io>',
306
+ agent: 'worker-crop-monitoring:0.0.1',
307
+ team: '',
308
+ instructions: 'You monitor crops from satellite imagery. You work from NASA Earthdata, which you reach through the earthdata tools: search the datasets that observe vegetation, land surface and moisture, then the granules that cover the field and the period asked, and say what each one shows — its dataset, its dates, its resolution, its cloud cover when it is given. You download nothing: when a person wants the data, describe what to fetch and write the script that fetches it for them to run. Answer with the monitoring itself: the field and the period, the vigour and growth you read across the dates, the fields or the parcels that need attention and why, and the dataset and granule behind each finding. When a request does not say the field or the period, ask before you search. When Earthdata holds nothing for it, say so plainly and do not fill the gap.',
309
+ model: '',
310
+ skills: [],
311
+ backendTools: [],
312
+ tools: [],
313
+ context: [],
314
+ contents: [],
315
+ connections: [
316
+ {
317
+ server: 'earthdata:0.0.1',
318
+ access: 'read',
319
+ as: 'owner',
320
+ only: [],
321
+ },
322
+ ],
323
+ rules: [
324
+ {
325
+ action: 'Search and read the imagery',
326
+ appliesTo: ['read'],
327
+ behaviour: 'do_it',
328
+ },
329
+ {
330
+ action: 'Download files to the runtime',
331
+ appliesTo: ['write'],
332
+ behaviour: 'ask_first',
333
+ },
334
+ ],
335
+ permissions: {
336
+ spaces: [],
337
+ computer: {
338
+ browse: false,
339
+ files: false,
340
+ shell: false,
341
+ },
342
+ },
343
+ interface: {
344
+ layout: 'chat',
345
+ accent: 'lime',
346
+ welcome: "Give me a field and a period, and I'll follow its crops across the satellite imagery NASA Earthdata holds: vigour, growth and what needs attention. I search and read; I download nothing.",
347
+ starters: [
348
+ {
349
+ label: 'Vigour this season',
350
+ message: 'How has crop vigour evolved over the last three months around 45.5N, 10.2E?',
351
+ },
352
+ {
353
+ label: 'Fields to watch',
354
+ message: 'Which fields around 41.9N, 12.5E show a drop in vegetation this month compared with last?',
355
+ },
356
+ {
357
+ label: 'Imagery available',
358
+ message: 'Which datasets and granules cover the Po valley for June 2026?',
359
+ },
360
+ ],
361
+ commands: [],
362
+ modes: [],
363
+ profiles: [],
364
+ language: 'en',
365
+ translations: {},
366
+ components: [],
367
+ assistant: 'eyes',
368
+ voice: {
369
+ enabled: false,
370
+ input: 'push_to_talk',
371
+ output: 'on_request',
372
+ voice: '',
373
+ language: '',
374
+ where: 'auto',
375
+ },
376
+ outputs: ['text/markdown', 'application/x-ipynb+json'],
377
+ },
378
+ tests: {
379
+ readyAt: 0.8,
380
+ evalset: '',
381
+ cases: [
382
+ {
383
+ ask: 'How has crop vigour evolved over the last three months around 45.5N, 10.2E?',
384
+ expect: 'It searches the vegetation datasets and their granules over the period with the earthdata tools and answers with what the imagery shows across the dates, naming each dataset and granule.',
385
+ },
386
+ {
387
+ ask: 'Which datasets and granules cover the Po valley for June 2026?',
388
+ expect: 'It lists the datasets and granules it found, with their dates, and downloads nothing.',
389
+ },
390
+ {
391
+ ask: 'Download the granules for me.',
392
+ expect: 'It does not download them. It writes the script a person would run, and says what it would fetch.',
393
+ },
394
+ {
395
+ ask: 'Which fields are at risk on Mars?',
396
+ expect: 'It says Earthdata holds no such imagery, and invents nothing.',
397
+ },
398
+ ],
399
+ verified: {
400
+ live: [],
401
+ recorded: [],
402
+ unverified: [
403
+ 'It has not run live yet: its agent is set up, not enabled, on this machine; the earthdata server is enabled.',
404
+ 'Its tests have not been run as a set: no validation run is attached to it.',
405
+ ],
406
+ },
407
+ },
408
+ record: {
409
+ keepFor: '30_days',
410
+ include: ['conversations'],
411
+ suggestTests: false,
412
+ retentionDays: 30,
413
+ },
414
+ checks: {
415
+ guards: [],
416
+ gates: [],
417
+ track: '',
418
+ code: [],
419
+ },
420
+ deployment: {
421
+ hosted: {
422
+ visibility: 'private',
423
+ slug: '',
424
+ },
425
+ },
426
+ goal: '',
427
+ triggers: [],
428
+ memory: '',
429
+ notifications: [],
430
+ enabled: true,
431
+ unavailable_because: '',
432
+ tags: [
433
+ 'example',
434
+ 'earth-observation',
435
+ 'agriculture',
436
+ 'earthdata',
437
+ 'a2a',
438
+ 'scene',
439
+ ],
440
+ icon: 'telescope',
441
+ emoji: '🌾',
442
+ avatar: '',
443
+ banner: '',
444
+ setup: ["The agent 'worker-crop-monitoring:0.0.1' is not enabled."],
445
+ };
145
446
  export const CUSTOMER_INTERVIEW_APP_0_0_1 = {
146
447
  schema: 'loop.app/v1',
147
448
  id: 'customer-interview',
@@ -156,6 +457,7 @@ export const CUSTOMER_INTERVIEW_APP_0_0_1 = {
156
457
  model: '',
157
458
  skills: [],
158
459
  backendTools: [],
460
+ tools: [],
159
461
  context: ['customer-research:0.0.1'],
160
462
  contents: [],
161
463
  connections: [],
@@ -190,6 +492,7 @@ export const CUSTOMER_INTERVIEW_APP_0_0_1 = {
190
492
  ],
191
493
  commands: [],
192
494
  modes: [],
495
+ profiles: [],
193
496
  settings: {
194
497
  type: 'object',
195
498
  properties: {
@@ -208,6 +511,8 @@ export const CUSTOMER_INTERVIEW_APP_0_0_1 = {
208
511
  },
209
512
  },
210
513
  },
514
+ language: 'en',
515
+ translations: {},
211
516
  components: [],
212
517
  assistant: 'cat',
213
518
  voice: {
@@ -263,6 +568,7 @@ export const CUSTOMER_INTERVIEW_APP_0_0_1 = {
263
568
  guards: [],
264
569
  gates: [],
265
570
  track: '',
571
+ code: [],
266
572
  },
267
573
  deployment: {
268
574
  hosted: {
@@ -297,6 +603,7 @@ export const DATA_QUALITY_APP_0_0_1 = {
297
603
  model: '',
298
604
  skills: [],
299
605
  backendTools: [],
606
+ tools: [],
300
607
  context: [],
301
608
  contents: ['The dataset under investigation'],
302
609
  connections: [],
@@ -316,18 +623,320 @@ export const DATA_QUALITY_APP_0_0_1 = {
316
623
  starters: [],
317
624
  commands: [],
318
625
  modes: [],
319
- components: [
320
- 'Card',
321
- 'Column',
322
- 'Row',
323
- 'List',
324
- 'Tabs',
325
- 'Text',
326
- 'Slider',
327
- 'ChoicePicker',
328
- 'TextField',
329
- 'Button',
330
- ],
626
+ profiles: [],
627
+ language: 'en',
628
+ translations: {},
629
+ components: [
630
+ 'Card',
631
+ 'Column',
632
+ 'Row',
633
+ 'List',
634
+ 'Tabs',
635
+ 'Text',
636
+ 'Slider',
637
+ 'ChoicePicker',
638
+ 'TextField',
639
+ 'Button',
640
+ ],
641
+ voice: {
642
+ enabled: false,
643
+ input: 'push_to_talk',
644
+ output: 'on_request',
645
+ voice: '',
646
+ language: '',
647
+ where: 'auto',
648
+ },
649
+ outputs: [],
650
+ },
651
+ tests: {
652
+ readyAt: 0.8,
653
+ evalset: '',
654
+ cases: [],
655
+ verified: {
656
+ live: [],
657
+ recorded: [],
658
+ unverified: [
659
+ 'It has not decided live: no dataset has been measured for it.',
660
+ 'It has no test yet: what a good decision looks like has not been written down.',
661
+ ],
662
+ },
663
+ },
664
+ record: {
665
+ keepFor: '1_years',
666
+ include: ['decisions', 'sources', 'checks'],
667
+ suggestTests: false,
668
+ retentionDays: 365,
669
+ },
670
+ checks: {
671
+ guards: [],
672
+ gates: [],
673
+ track: '',
674
+ code: [],
675
+ },
676
+ deployment: {
677
+ hosted: {
678
+ visibility: 'private',
679
+ slug: '',
680
+ },
681
+ },
682
+ goal: '',
683
+ triggers: [],
684
+ memory: '',
685
+ notifications: [],
686
+ decision: {
687
+ question: 'Which anomalies in this dataset should we fix first?',
688
+ alternatives: [],
689
+ criteria: [
690
+ {
691
+ name: 'Rows affected',
692
+ kind: 'metric',
693
+ weight: 2.0,
694
+ instructions: 'How many rows the anomaly touches, from a validation run in the sandbox.',
695
+ options: [],
696
+ direction: 'higher',
697
+ measure: '',
698
+ },
699
+ {
700
+ name: 'Effect on the result',
701
+ kind: 'metric',
702
+ weight: 3.0,
703
+ instructions: 'How far the headline figures move when the anomaly is corrected.',
704
+ options: [],
705
+ direction: 'higher',
706
+ measure: '',
707
+ },
708
+ {
709
+ name: 'Kind of anomaly',
710
+ kind: 'choice',
711
+ weight: 0.0,
712
+ instructions: 'What is this anomaly?',
713
+ options: [
714
+ 'Genuine: a real extreme, to keep',
715
+ 'Outlier: a value far from the rest, to check',
716
+ 'Unit: a unit mismatch',
717
+ 'Missing: a missing value',
718
+ 'Duplicate: the same row twice',
719
+ ],
720
+ direction: 'higher',
721
+ measure: '',
722
+ },
723
+ {
724
+ name: 'Safe to correct automatically',
725
+ kind: 'noul',
726
+ weight: 1.0,
727
+ instructions: 'Can the proposed correction be applied without a person checking each row?',
728
+ options: [],
729
+ direction: 'higher',
730
+ measure: '',
731
+ },
732
+ ],
733
+ minConfidence: 0.0,
734
+ scenarios: [],
735
+ decisionModel: 'cloudflare:gtw/typesafe/jev',
736
+ },
737
+ enabled: true,
738
+ unavailable_because: '',
739
+ tags: ['example', 'decision', 'data-quality'],
740
+ icon: 'filter',
741
+ emoji: '🧹',
742
+ avatar: '',
743
+ banner: '',
744
+ setup: [],
745
+ };
746
+ export const DECIDE_APP_0_0_1 = {
747
+ schema: 'loop.app/v1',
748
+ id: 'decide',
749
+ version: '0.0.1',
750
+ name: 'Decide',
751
+ kind: 'chat',
752
+ description: 'Answers a question about a text — a ticket, a message, a review — by asking Jev a typed decision: yes or no, one of named options, or a score, each with its confidence.',
753
+ owner: 'Datalayer <info@datalayer.io>',
754
+ agent: 'example-simple:0.0.1',
755
+ team: '',
756
+ instructions: 'Answer every question about a text by asking a typed decision with the decide tool: the text as it was given is the state, and the question is one of noul (does a statement hold: yes or no), choice (which of the options named) or score (which step of a scale, lowest first). Then say the answer in plain words with its probability or its confidence, for example "Urgent: yes (0.87)". When the question names no options for a choice or no scale for a score, ask for them rather than inventing them. When nothing was decided, say why in a sentence.',
757
+ model: '',
758
+ skills: [],
759
+ backendTools: ['decide:0.0.1'],
760
+ tools: [],
761
+ context: [],
762
+ contents: [],
763
+ connections: [],
764
+ rules: [
765
+ {
766
+ action: 'Ask a decision',
767
+ appliesTo: ['decide'],
768
+ behaviour: 'do_it',
769
+ },
770
+ ],
771
+ permissions: {
772
+ spaces: [],
773
+ computer: {
774
+ browse: false,
775
+ files: false,
776
+ shell: false,
777
+ },
778
+ },
779
+ interface: {
780
+ layout: 'chat',
781
+ accent: 'sun',
782
+ welcome: 'Give me a text and a question about it. I ask Jev a typed decision — yes or no, a choice, or a score — and tell you the answer with its confidence.',
783
+ starters: [
784
+ {
785
+ label: 'Is it urgent?',
786
+ message: "Is this ticket urgent? 'Help! My payouts have been failing for 3 days.'",
787
+ },
788
+ {
789
+ label: 'Which team?',
790
+ message: "Which team should handle this: 'I was charged twice this month'? Billing, Tech or Sales.",
791
+ },
792
+ {
793
+ label: 'Score a review',
794
+ message: "Score how positive this review is from 1 to 5: 'Setup took an hour, but support answered fast and it works.'",
795
+ },
796
+ ],
797
+ commands: [],
798
+ modes: [],
799
+ profiles: [],
800
+ language: 'en',
801
+ translations: {},
802
+ components: [],
803
+ assistant: 'wizard',
804
+ voice: {
805
+ enabled: false,
806
+ input: 'push_to_talk',
807
+ output: 'on_request',
808
+ voice: '',
809
+ language: '',
810
+ where: 'auto',
811
+ },
812
+ outputs: [],
813
+ },
814
+ tests: {
815
+ readyAt: 0.8,
816
+ evalset: '',
817
+ cases: [
818
+ {
819
+ ask: "Is this ticket urgent? 'Help! My payouts have been failing for 3 days.'",
820
+ expect: 'It calls decide with a noul question and answers yes, with its probability.',
821
+ },
822
+ {
823
+ ask: "Which team should handle this: 'I was charged twice this month'? Billing, Tech or Sales.",
824
+ expect: 'It calls decide with a choice among the three and answers Billing, with its confidence.',
825
+ },
826
+ {
827
+ ask: 'Score this review.',
828
+ expect: 'It asks for the review and the scale rather than inventing them.',
829
+ },
830
+ ],
831
+ verified: {
832
+ live: [],
833
+ recorded: [],
834
+ unverified: [
835
+ 'Its tests have not been run as a set: no validation run is attached to it.',
836
+ ],
837
+ },
838
+ },
839
+ record: {
840
+ keepFor: '30_days',
841
+ include: ['conversations', 'decisions'],
842
+ suggestTests: false,
843
+ retentionDays: 30,
844
+ },
845
+ checks: {
846
+ guards: [],
847
+ gates: [],
848
+ track: '',
849
+ code: [],
850
+ },
851
+ deployment: {
852
+ hosted: {
853
+ visibility: 'private',
854
+ slug: '',
855
+ },
856
+ },
857
+ goal: '',
858
+ triggers: [],
859
+ memory: '',
860
+ notifications: [],
861
+ enabled: true,
862
+ unavailable_because: '',
863
+ tags: ['example', 'decisions', 'jev'],
864
+ icon: 'law',
865
+ emoji: '⚖️',
866
+ avatar: '',
867
+ banner: '',
868
+ setup: [],
869
+ };
870
+ export const DISASTER_ASSESSMENT_APP_0_0_1 = {
871
+ schema: 'loop.app/v1',
872
+ id: 'disaster-assessment',
873
+ version: '0.0.1',
874
+ name: 'Disaster assessment',
875
+ kind: 'chat',
876
+ description: 'Estimates the area a natural disaster affected and the extent of the damage from the satellite imagery NASA Earthdata holds before and after the event, which it searches and reads, with the granules behind each figure.',
877
+ owner: 'Datalayer <info@datalayer.io>',
878
+ agent: 'worker-disaster-assessment:0.0.1',
879
+ team: '',
880
+ instructions: 'You assess disasters from satellite imagery. Requests usually come from the Event response application over A2A, and you answer them from NASA Earthdata, which you reach through the earthdata tools: search the datasets that observe the surface at the place asked, then the granules before the event and after it, and compare what they show. You download nothing: when data must be fetched, describe it and write the script a person would run. Answer with the assessment itself: the event, the place and the dates, the area affected and how you bounded it, the extent of the damage you read and how confident you are, the dataset and granule behind each figure. When a request does not say the event, the place or its date, say what you need. When Earthdata holds nothing for it, say so plainly and do not fill the gap.',
881
+ model: '',
882
+ skills: [],
883
+ backendTools: [],
884
+ tools: [],
885
+ context: [],
886
+ contents: [],
887
+ connections: [
888
+ {
889
+ server: 'earthdata:0.0.1',
890
+ access: 'read',
891
+ as: 'owner',
892
+ only: [],
893
+ },
894
+ ],
895
+ rules: [
896
+ {
897
+ action: 'Search and read the imagery',
898
+ appliesTo: ['read'],
899
+ behaviour: 'do_it',
900
+ },
901
+ {
902
+ action: 'Download files to the runtime',
903
+ appliesTo: ['write'],
904
+ behaviour: 'ask_first',
905
+ },
906
+ ],
907
+ permissions: {
908
+ spaces: [],
909
+ computer: {
910
+ browse: false,
911
+ files: false,
912
+ shell: false,
913
+ },
914
+ },
915
+ interface: {
916
+ layout: 'chat',
917
+ accent: 'rose',
918
+ welcome: "Name an event, a place and a date, and I'll compare the satellite imagery NASA Earthdata holds before and after it: the area affected and the extent of the damage. I search and read; I download nothing.",
919
+ starters: [
920
+ {
921
+ label: 'Flood extent',
922
+ message: 'Assess the flooding around Valencia, Spain, after 29 October 2024.',
923
+ },
924
+ {
925
+ label: 'Wildfire damage',
926
+ message: 'How much area burned around Los Angeles in the fires of January 2025?',
927
+ },
928
+ {
929
+ label: 'Imagery before and after',
930
+ message: 'Which granules show the Ahr valley before and after 14 July 2021?',
931
+ },
932
+ ],
933
+ commands: [],
934
+ modes: [],
935
+ profiles: [],
936
+ language: 'en',
937
+ translations: {},
938
+ components: [],
939
+ assistant: 'wizard',
331
940
  voice: {
332
941
  enabled: false,
333
942
  input: 'push_to_talk',
@@ -336,31 +945,49 @@ export const DATA_QUALITY_APP_0_0_1 = {
336
945
  language: '',
337
946
  where: 'auto',
338
947
  },
339
- outputs: [],
948
+ outputs: ['text/markdown', 'application/x-ipynb+json'],
340
949
  },
341
950
  tests: {
342
951
  readyAt: 0.8,
343
952
  evalset: '',
344
- cases: [],
953
+ cases: [
954
+ {
955
+ ask: 'Assess the flooding around Valencia, Spain, after 29 October 2024.',
956
+ expect: 'It searches the datasets and the granules before and after the date with the earthdata tools and answers with the area affected, the extent it read and the granules behind each figure.',
957
+ },
958
+ {
959
+ ask: 'Which granules show the Ahr valley before and after 14 July 2021?',
960
+ expect: 'It lists the granules on either side of the date, with their datasets, and downloads nothing.',
961
+ },
962
+ {
963
+ ask: 'Download everything you found.',
964
+ expect: 'It does not download it. It writes the script a person would run, and says what it would fetch.',
965
+ },
966
+ {
967
+ ask: 'Assess the earthquake.',
968
+ expect: 'It asks which event, where and when, before it searches.',
969
+ },
970
+ ],
345
971
  verified: {
346
972
  live: [],
347
973
  recorded: [],
348
974
  unverified: [
349
- 'It has not decided live: no dataset has been measured for it.',
350
- 'It has no test yet: what a good decision looks like has not been written down.',
975
+ 'It has not been asked live over A2A yet: its agent is set up, not enabled, on this machine; the earthdata server is enabled.',
976
+ 'Its tests have not been run as a set: no validation run is attached to it.',
351
977
  ],
352
978
  },
353
979
  },
354
980
  record: {
355
- keepFor: '1_years',
356
- include: ['decisions', 'sources', 'checks'],
981
+ keepFor: '30_days',
982
+ include: ['conversations'],
357
983
  suggestTests: false,
358
- retentionDays: 365,
984
+ retentionDays: 30,
359
985
  },
360
986
  checks: {
361
987
  guards: [],
362
988
  gates: [],
363
989
  track: '',
990
+ code: [],
364
991
  },
365
992
  deployment: {
366
993
  hosted: {
@@ -372,90 +999,41 @@ export const DATA_QUALITY_APP_0_0_1 = {
372
999
  triggers: [],
373
1000
  memory: '',
374
1001
  notifications: [],
375
- decision: {
376
- question: 'Which anomalies in this dataset should we fix first?',
377
- alternatives: [],
378
- criteria: [
379
- {
380
- name: 'Rows affected',
381
- kind: 'metric',
382
- weight: 2.0,
383
- instructions: 'How many rows the anomaly touches, from a validation run in the sandbox.',
384
- options: [],
385
- direction: 'higher',
386
- measure: '',
387
- },
388
- {
389
- name: 'Effect on the result',
390
- kind: 'metric',
391
- weight: 3.0,
392
- instructions: 'How far the headline figures move when the anomaly is corrected.',
393
- options: [],
394
- direction: 'higher',
395
- measure: '',
396
- },
397
- {
398
- name: 'Kind of anomaly',
399
- kind: 'choice',
400
- weight: 0.0,
401
- instructions: 'What is this anomaly?',
402
- options: [
403
- 'Genuine: a real extreme, to keep',
404
- 'Outlier: a value far from the rest, to check',
405
- 'Unit: a unit mismatch',
406
- 'Missing: a missing value',
407
- 'Duplicate: the same row twice',
408
- ],
409
- direction: 'higher',
410
- measure: '',
411
- },
412
- {
413
- name: 'Safe to correct automatically',
414
- kind: 'noul',
415
- weight: 1.0,
416
- instructions: 'Can the proposed correction be applied without a person checking each row?',
417
- options: [],
418
- direction: 'higher',
419
- measure: '',
420
- },
421
- ],
422
- minConfidence: 0.0,
423
- scenarios: [],
424
- decisionModel: 'cloudflare:gtw/typesafe/jev',
425
- },
426
1002
  enabled: true,
427
1003
  unavailable_because: '',
428
- tags: ['example', 'decision', 'data-quality'],
429
- icon: 'filter',
430
- emoji: '🧹',
1004
+ tags: [
1005
+ 'example',
1006
+ 'earth-observation',
1007
+ 'disaster',
1008
+ 'earthdata',
1009
+ 'a2a',
1010
+ 'scene',
1011
+ ],
1012
+ icon: 'pulse',
1013
+ emoji: '🌊',
431
1014
  avatar: '',
432
1015
  banner: '',
433
- setup: [],
1016
+ setup: ["The agent 'worker-disaster-assessment:0.0.1' is not enabled."],
434
1017
  };
435
- export const DECIDE_APP_0_0_1 = {
1018
+ export const EVENT_RESPONSE_APP_0_0_1 = {
436
1019
  schema: 'loop.app/v1',
437
- id: 'decide',
1020
+ id: 'event-response',
438
1021
  version: '0.0.1',
439
- name: 'Decide',
1022
+ name: 'Event response',
440
1023
  kind: 'chat',
441
- description: 'Answers a question about a text — a ticket, a message, a review — by asking Jev a typed decision: yes or no, one of named options, or a score, each with its confidence.',
1024
+ description: 'Takes word of a live event — a flood, a fire, a storm — asks Disaster assessment for the area affected and the damage and Change detection for what changed on the ground, each over A2A, and reports what they answered, adding no figure of its own.',
442
1025
  owner: 'Datalayer <info@datalayer.io>',
443
- agent: 'example-simple:0.0.1',
1026
+ agent: 'worker-event-response:0.0.1',
444
1027
  team: '',
445
- instructions: 'Answer every question about a text by asking a typed decision with the decide tool: the text as it was given is the state, and the question is one of noul (does a statement hold: yes or no), choice (which of the options named) or score (which step of a scale, lowest first). Then say the answer in plain words with its probability or its confidence, for example "Urgent: yes (0.87)". When the question names no options for a choice or no scale for a score, ask for them rather than inventing them. When nothing was decided, say why in a sentence.',
1028
+ instructions: 'You respond to events. You read no imagery yourself: Disaster assessment and Change detection do. When the person tells you of an event, call ask_disaster_assessment once with one request the assessor can act on without the rest of this conversation — the event, the place and the date — and ask_change_detection once with the place and the two dates to compare, before and after. Then report what each answered, as it answered it: the area affected, the extent of the damage, each change on the ground, their confidence and their caveats, and which member each figure came from. Never invent, estimate, round or complete a figure, and never fill a gap from what you know. When a member cannot answer, or answers only in part, say so and repeat what it said. When the request does not say the event, the place or its date, ask the person before you ask anyone. You change nothing anywhere: you ask, and you report.',
446
1029
  model: '',
447
1030
  skills: [],
448
- backendTools: ['decide:0.0.1'],
1031
+ backendTools: [],
1032
+ tools: [],
449
1033
  context: [],
450
1034
  contents: [],
451
1035
  connections: [],
452
- rules: [
453
- {
454
- action: 'Ask a decision',
455
- appliesTo: ['decide'],
456
- behaviour: 'do_it',
457
- },
458
- ],
1036
+ rules: [],
459
1037
  permissions: {
460
1038
  spaces: [],
461
1039
  computer: {
@@ -466,26 +1044,29 @@ export const DECIDE_APP_0_0_1 = {
466
1044
  },
467
1045
  interface: {
468
1046
  layout: 'chat',
469
- accent: 'sun',
470
- welcome: 'Give me a text and a question about it. I ask Jev a typed decision — yes or no, a choice, or a score — and tell you the answer with its confidence.',
1047
+ accent: 'rose',
1048
+ welcome: "Tell me of an event — a flood, a fire, a storm — where and when, and I'll get the area affected and the damage from Disaster assessment and what changed on the ground from Change detection.",
471
1049
  starters: [
472
1050
  {
473
- label: 'Is it urgent?',
474
- message: "Is this ticket urgent? 'Help! My payouts have been failing for 3 days.'",
1051
+ label: 'Flood',
1052
+ message: 'Valencia, Spain, was flooded on 29 October 2024. What was affected, and what changed?',
475
1053
  },
476
1054
  {
477
- label: 'Which team?',
478
- message: "Which team should handle this: 'I was charged twice this month'? Billing, Tech or Sales.",
1055
+ label: 'Wildfire',
1056
+ message: 'Fires burned around Los Angeles from 7 January 2025. What was affected, and what changed?',
479
1057
  },
480
1058
  {
481
- label: 'Score a review',
482
- message: "Score how positive this review is from 1 to 5: 'Setup took an hour, but support answered fast and it works.'",
1059
+ label: 'Storm',
1060
+ message: 'The Ahr valley was hit by a storm on 14 July 2021. What was affected, and what changed?',
483
1061
  },
484
1062
  ],
485
1063
  commands: [],
486
1064
  modes: [],
1065
+ profiles: [],
1066
+ language: 'en',
1067
+ translations: {},
487
1068
  components: [],
488
- assistant: 'wizard',
1069
+ assistant: 'paperclip',
489
1070
  voice: {
490
1071
  enabled: false,
491
1072
  input: 'push_to_talk',
@@ -501,29 +1082,34 @@ export const DECIDE_APP_0_0_1 = {
501
1082
  evalset: '',
502
1083
  cases: [
503
1084
  {
504
- ask: "Is this ticket urgent? 'Help! My payouts have been failing for 3 days.'",
505
- expect: 'It calls decide with a noul question and answers yes, with its probability.',
1085
+ ask: 'Valencia, Spain, was flooded on 29 October 2024. What was affected, and what changed?',
1086
+ expect: 'It calls ask_disaster_assessment once with the event, the place and the date, and ask_change_detection once with the place and the dates before and after, and reports what each answered, adding no figure.',
506
1087
  },
507
1088
  {
508
- ask: "Which team should handle this: 'I was charged twice this month'? Billing, Tech or Sales.",
509
- expect: 'It calls decide with a choice among the three and answers Billing, with its confidence.',
1089
+ ask: 'There was a flood. What was affected?',
1090
+ expect: 'It asks where and when before asking anyone.',
510
1091
  },
511
1092
  {
512
- ask: 'Score this review.',
513
- expect: 'It asks for the review and the scale rather than inventing them.',
1093
+ ask: 'Just estimate the damage yourself, no need to ask anyone.',
1094
+ expect: 'It does not estimate. It asks Disaster assessment, or says that it only reports what the members answered.',
1095
+ },
1096
+ {
1097
+ ask: 'Fires burned around Los Angeles from 7 January 2025. What was affected, and what changed?',
1098
+ expect: 'When a member cannot answer, it says which one could not and why, and invents nothing.',
514
1099
  },
515
1100
  ],
516
1101
  verified: {
517
1102
  live: [],
518
1103
  recorded: [],
519
1104
  unverified: [
1105
+ 'It has not asked Disaster assessment or Change detection live yet: its agent is set up, not enabled, on this machine.',
520
1106
  'Its tests have not been run as a set: no validation run is attached to it.',
521
1107
  ],
522
1108
  },
523
1109
  },
524
1110
  record: {
525
1111
  keepFor: '30_days',
526
- include: ['conversations', 'decisions'],
1112
+ include: ['conversations'],
527
1113
  suggestTests: false,
528
1114
  retentionDays: 30,
529
1115
  },
@@ -531,6 +1117,7 @@ export const DECIDE_APP_0_0_1 = {
531
1117
  guards: [],
532
1118
  gates: [],
533
1119
  track: '',
1120
+ code: [],
534
1121
  },
535
1122
  deployment: {
536
1123
  hosted: {
@@ -544,12 +1131,19 @@ export const DECIDE_APP_0_0_1 = {
544
1131
  notifications: [],
545
1132
  enabled: true,
546
1133
  unavailable_because: '',
547
- tags: ['example', 'decisions', 'jev'],
548
- icon: 'law',
549
- emoji: '⚖️',
1134
+ tags: [
1135
+ 'example',
1136
+ 'earth-observation',
1137
+ 'insurance',
1138
+ 'disaster',
1139
+ 'a2a',
1140
+ 'scene',
1141
+ ],
1142
+ icon: 'pulse',
1143
+ emoji: '🛡️',
550
1144
  avatar: '',
551
1145
  banner: '',
552
- setup: [],
1146
+ setup: ["The agent 'worker-event-response:0.0.1' is not enabled."],
553
1147
  };
554
1148
  export const INBOX_TRIAGE_APP_0_0_1 = {
555
1149
  schema: 'loop.app/v1',
@@ -565,6 +1159,7 @@ export const INBOX_TRIAGE_APP_0_0_1 = {
565
1159
  model: '',
566
1160
  skills: [],
567
1161
  backendTools: [],
1162
+ tools: [],
568
1163
  context: [],
569
1164
  contents: [],
570
1165
  connections: [
@@ -639,6 +1234,9 @@ export const INBOX_TRIAGE_APP_0_0_1 = {
639
1234
  ],
640
1235
  commands: [],
641
1236
  modes: [],
1237
+ profiles: [],
1238
+ language: 'en',
1239
+ translations: {},
642
1240
  components: [],
643
1241
  voice: {
644
1242
  enabled: false,
@@ -698,6 +1296,7 @@ export const INBOX_TRIAGE_APP_0_0_1 = {
698
1296
  guards: [],
699
1297
  gates: [],
700
1298
  track: '',
1299
+ code: [],
701
1300
  },
702
1301
  deployment: {
703
1302
  hosted: {
@@ -752,6 +1351,7 @@ export const MODEL_CHOICE_APP_0_0_1 = {
752
1351
  model: '',
753
1352
  skills: [],
754
1353
  backendTools: [],
1354
+ tools: [],
755
1355
  context: [],
756
1356
  contents: [
757
1357
  'The benchmark run: one configuration per model, its task results, cost and latency',
@@ -774,6 +1374,9 @@ export const MODEL_CHOICE_APP_0_0_1 = {
774
1374
  starters: [],
775
1375
  commands: [],
776
1376
  modes: [],
1377
+ profiles: [],
1378
+ language: 'en',
1379
+ translations: {},
777
1380
  components: [
778
1381
  'Card',
779
1382
  'Column',
@@ -822,6 +1425,7 @@ export const MODEL_CHOICE_APP_0_0_1 = {
822
1425
  guards: [],
823
1426
  gates: [],
824
1427
  track: '',
1428
+ code: [],
825
1429
  },
826
1430
  deployment: {
827
1431
  hosted: {
@@ -905,46 +1509,190 @@ export const MODEL_CHOICE_APP_0_0_1 = {
905
1509
  minConfidence: 0.6,
906
1510
  scenarios: [
907
1511
  {
908
- name: 'Quality first',
909
- weights: {
910
- 'Pass rate': 4.0,
911
- 'Cost per task': 0.0,
912
- Latency: 1.0,
913
- 'Answer quality': 4.0,
914
- 'Follows the format': 1.0,
915
- },
1512
+ name: 'Quality first',
1513
+ weights: {
1514
+ 'Pass rate': 4.0,
1515
+ 'Cost per task': 0.0,
1516
+ Latency: 1.0,
1517
+ 'Answer quality': 4.0,
1518
+ 'Follows the format': 1.0,
1519
+ },
1520
+ },
1521
+ {
1522
+ name: 'Cheapest that works',
1523
+ weights: {
1524
+ 'Pass rate': 3.0,
1525
+ 'Cost per task': 4.0,
1526
+ Latency: 1.0,
1527
+ 'Answer quality': 1.0,
1528
+ 'Follows the format': 1.0,
1529
+ },
1530
+ },
1531
+ {
1532
+ name: 'Fastest that works',
1533
+ weights: {
1534
+ 'Pass rate': 3.0,
1535
+ 'Cost per task': 1.0,
1536
+ Latency: 4.0,
1537
+ 'Answer quality': 1.0,
1538
+ 'Follows the format': 1.0,
1539
+ },
1540
+ },
1541
+ ],
1542
+ decisionModel: 'cloudflare:gtw/typesafe/jev',
1543
+ },
1544
+ enabled: true,
1545
+ unavailable_because: '',
1546
+ tags: ['example', 'decision', 'benchmarks', 'models'],
1547
+ icon: 'cpu',
1548
+ emoji: '🧠',
1549
+ avatar: '',
1550
+ banner: '',
1551
+ setup: [],
1552
+ };
1553
+ export const MONTH_END_CLOSE_APP_0_0_1 = {
1554
+ schema: 'loop.app/v1',
1555
+ id: 'month-end-close',
1556
+ version: '0.0.1',
1557
+ name: 'Month-end close',
1558
+ kind: 'chat',
1559
+ description: 'Drives the month-end close from the Odoo books, which it only reads: the close checklist, the accruals to book, the open items and the reconciliation gaps that remain, each with the figures behind it.',
1560
+ owner: 'Datalayer <info@datalayer.io>',
1561
+ agent: 'worker-month-end-close:0.0.1',
1562
+ team: '',
1563
+ instructions: 'You drive the month-end close. You work from the Odoo books, which you reach through the odoo-accounting tools and only read. Use the tools for every figure: the journal entries of the period, the open balances, the trial balance, the general ledger, the partner ledgers and the aged balances. Answer with the close itself: the period, the company, the currency, the checklist with what is done and what is not, the accruals you suggest and why, the unreconciled items and the gaps that remain, and the tool each figure came from. When a request does not say its period or its company, take the month that just ended and the default company and say that you did. When the books do not hold the answer, or a tool is refused, say so plainly and do not fill the gap. Never write to Odoo: never create, post, reconcile, book, match, lock or delete anything, and do not offer to. A request to change the books is answered with what a person would have to do, not done.',
1564
+ model: '',
1565
+ skills: [],
1566
+ backendTools: [],
1567
+ tools: [],
1568
+ context: [],
1569
+ contents: [],
1570
+ connections: [
1571
+ {
1572
+ server: 'odoo-accounting:0.0.1',
1573
+ access: 'read',
1574
+ as: 'owner',
1575
+ only: [],
1576
+ },
1577
+ ],
1578
+ rules: [
1579
+ {
1580
+ action: 'Read the books',
1581
+ appliesTo: ['read'],
1582
+ behaviour: 'do_it',
1583
+ },
1584
+ {
1585
+ action: 'Change the books',
1586
+ appliesTo: ['write', 'delete'],
1587
+ behaviour: 'ask_first',
1588
+ },
1589
+ ],
1590
+ permissions: {
1591
+ spaces: [],
1592
+ computer: {
1593
+ browse: false,
1594
+ files: false,
1595
+ shell: false,
1596
+ },
1597
+ },
1598
+ interface: {
1599
+ layout: 'chat',
1600
+ accent: 'sun',
1601
+ welcome: 'Ask me where the month-end close stands: the checklist, the accruals to book, the open items and the reconciliation gaps. I read Odoo; I change nothing.',
1602
+ starters: [
1603
+ {
1604
+ label: 'Close checklist',
1605
+ message: 'Where does the month-end close stand for last month? Give me the checklist.',
1606
+ },
1607
+ {
1608
+ label: 'Accruals',
1609
+ message: 'Which accruals should be booked for last month, and for how much?',
1610
+ },
1611
+ {
1612
+ label: 'Reconciliation gaps',
1613
+ message: 'Which bank lines and open items are still unreconciled for last month?',
1614
+ },
1615
+ ],
1616
+ commands: [],
1617
+ modes: [],
1618
+ profiles: [],
1619
+ language: 'en',
1620
+ translations: {},
1621
+ components: [],
1622
+ assistant: 'cat',
1623
+ voice: {
1624
+ enabled: false,
1625
+ input: 'push_to_talk',
1626
+ output: 'on_request',
1627
+ voice: '',
1628
+ language: '',
1629
+ where: 'auto',
1630
+ },
1631
+ outputs: ['text/markdown', 'application/x-ipynb+json'],
1632
+ },
1633
+ tests: {
1634
+ readyAt: 0.8,
1635
+ evalset: '',
1636
+ cases: [
1637
+ {
1638
+ ask: 'Where does the month-end close stand for last month? Give me the checklist.',
1639
+ expect: "It reads the period's entries and balances with the odoo-accounting tools and answers with a checklist that says what is done and what is not, the company and the period.",
1640
+ },
1641
+ {
1642
+ ask: 'Which accruals should be booked for last month, and for how much?',
1643
+ expect: 'It suggests accruals from what the books hold, each with its amount and the entries it read, and books none of them.',
916
1644
  },
917
1645
  {
918
- name: 'Cheapest that works',
919
- weights: {
920
- 'Pass rate': 3.0,
921
- 'Cost per task': 4.0,
922
- Latency: 1.0,
923
- 'Answer quality': 1.0,
924
- 'Follows the format': 1.0,
925
- },
1646
+ ask: 'Post the accruals you suggested.',
1647
+ expect: 'It does not post them. It says that it only reads the books and what a person would have to do.',
926
1648
  },
927
1649
  {
928
- name: 'Fastest that works',
929
- weights: {
930
- 'Pass rate': 3.0,
931
- 'Cost per task': 1.0,
932
- Latency: 4.0,
933
- 'Answer quality': 1.0,
934
- 'Follows the format': 1.0,
935
- },
1650
+ ask: 'Is the close done for a company that is not in Odoo?',
1651
+ expect: 'It says the books do not hold it, and invents nothing.',
936
1652
  },
937
1653
  ],
938
- decisionModel: 'cloudflare:gtw/typesafe/jev',
1654
+ verified: {
1655
+ live: [],
1656
+ recorded: [],
1657
+ unverified: [
1658
+ 'It has not run live yet: its agent and the odoo-accounting server are set up, not enabled, on this machine.',
1659
+ 'Its tests have not been run as a set: no validation run is attached to it.',
1660
+ ],
1661
+ },
1662
+ },
1663
+ record: {
1664
+ keepFor: '30_days',
1665
+ include: ['conversations'],
1666
+ suggestTests: false,
1667
+ retentionDays: 30,
1668
+ },
1669
+ checks: {
1670
+ guards: [],
1671
+ gates: [],
1672
+ track: '',
1673
+ code: [],
1674
+ },
1675
+ deployment: {
1676
+ hosted: {
1677
+ visibility: 'private',
1678
+ slug: '',
1679
+ },
939
1680
  },
1681
+ goal: '',
1682
+ triggers: [],
1683
+ memory: '',
1684
+ notifications: [],
940
1685
  enabled: true,
941
1686
  unavailable_because: '',
942
- tags: ['example', 'decision', 'benchmarks', 'models'],
943
- icon: 'cpu',
944
- emoji: '🧠',
1687
+ tags: ['example', 'accounting', 'finance', 'odoo', 'a2a', 'scene'],
1688
+ icon: 'sync',
1689
+ emoji: '🗓️',
945
1690
  avatar: '',
946
1691
  banner: '',
947
- setup: [],
1692
+ setup: [
1693
+ "The agent 'worker-month-end-close:0.0.1' is not enabled.",
1694
+ "The MCP server 'odoo-accounting:0.0.1' is not enabled.",
1695
+ ],
948
1696
  };
949
1697
  export const PIPELINE_REPORT_APP_0_0_1 = {
950
1698
  schema: 'loop.app/v1',
@@ -960,6 +1708,7 @@ export const PIPELINE_REPORT_APP_0_0_1 = {
960
1708
  model: '',
961
1709
  skills: [],
962
1710
  backendTools: [],
1711
+ tools: [],
963
1712
  context: ['datalayer:0.0.1'],
964
1713
  contents: ['Sales pipeline export'],
965
1714
  connections: [],
@@ -1004,6 +1753,9 @@ export const PIPELINE_REPORT_APP_0_0_1 = {
1004
1753
  ],
1005
1754
  commands: [],
1006
1755
  modes: [],
1756
+ profiles: [],
1757
+ language: 'en',
1758
+ translations: {},
1007
1759
  components: [
1008
1760
  'Card',
1009
1761
  'Column',
@@ -1202,6 +1954,7 @@ export const PIPELINE_REPORT_APP_0_0_1 = {
1202
1954
  'quality-drift-review:0.0.1',
1203
1955
  ],
1204
1956
  track: 'financial-reporting:0.0.1',
1957
+ code: [],
1205
1958
  },
1206
1959
  deployment: {
1207
1960
  hosted: {
@@ -1245,6 +1998,7 @@ export const QUOTE_CALCULATOR_APP_0_0_1 = {
1245
1998
  model: '',
1246
1999
  skills: [],
1247
2000
  backendTools: [],
2001
+ tools: [],
1248
2002
  context: [],
1249
2003
  contents: ['Price list'],
1250
2004
  connections: [],
@@ -1264,6 +2018,7 @@ export const QUOTE_CALCULATOR_APP_0_0_1 = {
1264
2018
  starters: [],
1265
2019
  commands: [],
1266
2020
  modes: [],
2021
+ profiles: [],
1267
2022
  settings: {
1268
2023
  type: 'object',
1269
2024
  properties: {
@@ -1288,6 +2043,8 @@ export const QUOTE_CALCULATOR_APP_0_0_1 = {
1288
2043
  },
1289
2044
  },
1290
2045
  },
2046
+ language: 'en',
2047
+ translations: {},
1291
2048
  components: [
1292
2049
  'Card',
1293
2050
  'Column',
@@ -1462,6 +2219,7 @@ export const QUOTE_CALCULATOR_APP_0_0_1 = {
1462
2219
  guards: [],
1463
2220
  gates: [],
1464
2221
  track: '',
2222
+ code: [],
1465
2223
  },
1466
2224
  deployment: {
1467
2225
  hosted: {
@@ -1500,6 +2258,7 @@ export const REPORT_FROM_A_FILE_APP_0_0_1 = {
1500
2258
  model: '',
1501
2259
  skills: [],
1502
2260
  backendTools: [],
2261
+ tools: [],
1503
2262
  context: [],
1504
2263
  contents: [],
1505
2264
  connections: [],
@@ -1525,6 +2284,7 @@ export const REPORT_FROM_A_FILE_APP_0_0_1 = {
1525
2284
  starters: [],
1526
2285
  commands: [],
1527
2286
  modes: [],
2287
+ profiles: [],
1528
2288
  settings: {
1529
2289
  type: 'object',
1530
2290
  properties: {
@@ -1541,6 +2301,8 @@ export const REPORT_FROM_A_FILE_APP_0_0_1 = {
1541
2301
  },
1542
2302
  },
1543
2303
  },
2304
+ language: 'en',
2305
+ translations: {},
1544
2306
  components: [
1545
2307
  'Card',
1546
2308
  'Column',
@@ -1709,6 +2471,7 @@ export const REPORT_FROM_A_FILE_APP_0_0_1 = {
1709
2471
  guards: [],
1710
2472
  gates: [],
1711
2473
  track: '',
2474
+ code: [],
1712
2475
  },
1713
2476
  deployment: {
1714
2477
  hosted: {
@@ -1747,6 +2510,7 @@ export const SALES_APP_0_0_1 = {
1747
2510
  model: '',
1748
2511
  skills: [],
1749
2512
  backendTools: [],
2513
+ tools: [],
1750
2514
  context: [],
1751
2515
  contents: [],
1752
2516
  connections: [],
@@ -1779,6 +2543,9 @@ export const SALES_APP_0_0_1 = {
1779
2543
  ],
1780
2544
  commands: [],
1781
2545
  modes: [],
2546
+ profiles: [],
2547
+ language: 'en',
2548
+ translations: {},
1782
2549
  components: [],
1783
2550
  assistant: 'paperclip',
1784
2551
  voice: {
@@ -1831,6 +2598,7 @@ export const SALES_APP_0_0_1 = {
1831
2598
  guards: [],
1832
2599
  gates: [],
1833
2600
  track: '',
2601
+ code: [],
1834
2602
  },
1835
2603
  deployment: {
1836
2604
  hosted: {
@@ -1867,6 +2635,7 @@ export const SHIP_OR_FIX_APP_0_0_1 = {
1867
2635
  model: '',
1868
2636
  skills: [],
1869
2637
  backendTools: [],
2638
+ tools: [],
1870
2639
  context: [],
1871
2640
  contents: ['The benchmark run: task results, traces, cost and latency'],
1872
2641
  connections: [],
@@ -1886,6 +2655,9 @@ export const SHIP_OR_FIX_APP_0_0_1 = {
1886
2655
  starters: [],
1887
2656
  commands: [],
1888
2657
  modes: [],
2658
+ profiles: [],
2659
+ language: 'en',
2660
+ translations: {},
1889
2661
  components: [
1890
2662
  'Card',
1891
2663
  'Column',
@@ -1932,6 +2704,7 @@ export const SHIP_OR_FIX_APP_0_0_1 = {
1932
2704
  guards: [],
1933
2705
  gates: [],
1934
2706
  track: '',
2707
+ code: [],
1935
2708
  },
1936
2709
  deployment: {
1937
2710
  hosted: {
@@ -2045,6 +2818,7 @@ export const SUPPLIER_COMPARISON_APP_0_0_1 = {
2045
2818
  model: '',
2046
2819
  skills: [],
2047
2820
  backendTools: [],
2821
+ tools: [],
2048
2822
  context: [],
2049
2823
  contents: ['Order history', 'Supplier price lists', 'Delivery records'],
2050
2824
  connections: [],
@@ -2064,6 +2838,9 @@ export const SUPPLIER_COMPARISON_APP_0_0_1 = {
2064
2838
  starters: [],
2065
2839
  commands: [],
2066
2840
  modes: [],
2841
+ profiles: [],
2842
+ language: 'en',
2843
+ translations: {},
2067
2844
  components: [
2068
2845
  'Card',
2069
2846
  'Column',
@@ -2112,6 +2889,7 @@ export const SUPPLIER_COMPARISON_APP_0_0_1 = {
2112
2889
  guards: [],
2113
2890
  gates: [],
2114
2891
  track: '',
2892
+ code: [],
2115
2893
  },
2116
2894
  deployment: {
2117
2895
  hosted: {
@@ -2210,6 +2988,7 @@ export const SUPPORT_DESK_APP_0_0_1 = {
2210
2988
  model: '',
2211
2989
  skills: [],
2212
2990
  backendTools: [],
2991
+ tools: [],
2213
2992
  context: [],
2214
2993
  contents: ['Product documentation', 'Returns policy'],
2215
2994
  connections: [],
@@ -2230,18 +3009,22 @@ export const SUPPORT_DESK_APP_0_0_1 = {
2230
3009
  {
2231
3010
  label: 'Reset my password',
2232
3011
  message: 'How do I reset my password?',
3012
+ category: 'Account',
2233
3013
  },
2234
3014
  {
2235
3015
  label: 'Returns',
2236
3016
  message: 'Can I return a product I bought six weeks ago?',
3017
+ category: 'Orders',
2237
3018
  },
2238
3019
  {
2239
3020
  label: 'Plans',
2240
3021
  message: 'What is the difference between the Team and the Business plan?',
3022
+ category: 'Account',
2241
3023
  },
2242
3024
  ],
2243
3025
  commands: [],
2244
3026
  modes: [],
3027
+ profiles: [],
2245
3028
  settings: {
2246
3029
  type: 'object',
2247
3030
  properties: {
@@ -2253,6 +3036,47 @@ export const SUPPORT_DESK_APP_0_0_1 = {
2253
3036
  },
2254
3037
  },
2255
3038
  },
3039
+ settingsUi: {
3040
+ product: {
3041
+ 'ui:widget': 'radio',
3042
+ },
3043
+ },
3044
+ language: 'en',
3045
+ translations: {
3046
+ fr: {
3047
+ name: 'Service client',
3048
+ description: '',
3049
+ welcome: 'Posez-moi vos questions sur le produit. Je réponds à partir de sa documentation et vous montre où ; quand elle ne le dit pas, je vous le dis.',
3050
+ starters: {
3051
+ 'Reset my password': {
3052
+ label: 'Réinitialiser mon mot de passe',
3053
+ message: 'Comment réinitialiser mon mot de passe ?',
3054
+ },
3055
+ Returns: {
3056
+ label: 'Retours',
3057
+ message: 'Puis-je retourner un produit acheté il y a six semaines ?',
3058
+ },
3059
+ Plans: {
3060
+ label: 'Offres',
3061
+ message: "Quelle est la différence entre l'offre Team et l'offre Business ?",
3062
+ },
3063
+ },
3064
+ categories: {
3065
+ Account: 'Compte',
3066
+ Orders: 'Commandes',
3067
+ },
3068
+ settings: {
3069
+ product: {
3070
+ title: 'Produit',
3071
+ description: '',
3072
+ options: {},
3073
+ },
3074
+ },
3075
+ commands: {},
3076
+ modes: {},
3077
+ profiles: {},
3078
+ },
3079
+ },
2256
3080
  components: [
2257
3081
  'Card',
2258
3082
  'Column',
@@ -2426,6 +3250,7 @@ export const SUPPORT_DESK_APP_0_0_1 = {
2426
3250
  guards: [],
2427
3251
  gates: [],
2428
3252
  track: '',
3253
+ code: [],
2429
3254
  },
2430
3255
  deployment: {
2431
3256
  hosted: {
@@ -2464,6 +3289,7 @@ export const WEB_RESEARCH_APP_0_0_1 = {
2464
3289
  model: '',
2465
3290
  skills: [],
2466
3291
  backendTools: [],
3292
+ tools: [],
2467
3293
  context: ['web-research:0.0.1'],
2468
3294
  contents: [],
2469
3295
  connections: [
@@ -2503,6 +3329,7 @@ export const WEB_RESEARCH_APP_0_0_1 = {
2503
3329
  ],
2504
3330
  commands: [],
2505
3331
  modes: [],
3332
+ profiles: [],
2506
3333
  settings: {
2507
3334
  type: 'object',
2508
3335
  properties: {
@@ -2514,6 +3341,8 @@ export const WEB_RESEARCH_APP_0_0_1 = {
2514
3341
  },
2515
3342
  },
2516
3343
  },
3344
+ language: 'en',
3345
+ translations: {},
2517
3346
  components: [],
2518
3347
  voice: {
2519
3348
  enabled: false,
@@ -2563,6 +3392,7 @@ export const WEB_RESEARCH_APP_0_0_1 = {
2563
3392
  guards: [],
2564
3393
  gates: [],
2565
3394
  track: '',
3395
+ code: [],
2566
3396
  },
2567
3397
  deployment: {
2568
3398
  hosted: {
@@ -2570,122 +3400,300 @@ export const WEB_RESEARCH_APP_0_0_1 = {
2570
3400
  slug: '',
2571
3401
  },
2572
3402
  },
2573
- goal: '',
2574
- triggers: [],
2575
- memory: '',
2576
- notifications: [],
2577
- enabled: true,
2578
- unavailable_because: '',
2579
- tags: ['example', 'research'],
2580
- icon: 'search',
2581
- emoji: '🔎',
2582
- avatar: '',
2583
- banner: '',
2584
- setup: [],
2585
- };
2586
- export const APP_CATALOGUE = {
2587
- accounting: ACCOUNTING_APP_0_0_1,
2588
- 'customer-interview': CUSTOMER_INTERVIEW_APP_0_0_1,
2589
- 'data-quality': DATA_QUALITY_APP_0_0_1,
2590
- decide: DECIDE_APP_0_0_1,
2591
- 'inbox-triage': INBOX_TRIAGE_APP_0_0_1,
2592
- 'model-choice': MODEL_CHOICE_APP_0_0_1,
2593
- 'pipeline-report': PIPELINE_REPORT_APP_0_0_1,
2594
- 'quote-calculator': QUOTE_CALCULATOR_APP_0_0_1,
2595
- 'report-from-a-file': REPORT_FROM_A_FILE_APP_0_0_1,
2596
- sales: SALES_APP_0_0_1,
2597
- 'ship-or-fix': SHIP_OR_FIX_APP_0_0_1,
2598
- 'supplier-comparison': SUPPLIER_COMPARISON_APP_0_0_1,
2599
- 'support-desk': SUPPORT_DESK_APP_0_0_1,
2600
- 'web-research': WEB_RESEARCH_APP_0_0_1,
2601
- };
2602
- /** An application, by `id` or `id:version`, or undefined. */
2603
- export function getApp(ref) {
2604
- // Own entries only: `constructor` and `toString` are not applications.
2605
- const own = (id) => Object.prototype.hasOwnProperty.call(APP_CATALOGUE, id)
2606
- ? APP_CATALOGUE[id]
2607
- : undefined;
2608
- const at = ref.lastIndexOf(':');
2609
- return (own(ref) ??
2610
- (at > 0 && ref.slice(at + 1).includes('.')
2611
- ? own(ref.slice(0, at))
2612
- : undefined));
2613
- }
2614
- /**
2615
- * Each application as the document its file holds: the spec's own words,
2616
- * nothing written that is at its default. What reading and writing an
2617
- * Appspec have to give back.
2618
- */
2619
- export const APP_SOURCES = {
2620
- accounting: {
3403
+ goal: '',
3404
+ triggers: [],
3405
+ memory: '',
3406
+ notifications: [],
3407
+ enabled: true,
3408
+ unavailable_because: '',
3409
+ tags: ['example', 'research'],
3410
+ icon: 'search',
3411
+ emoji: '🔎',
3412
+ avatar: '',
3413
+ banner: '',
3414
+ setup: [],
3415
+ };
3416
+ export const APP_CATALOGUE = {
3417
+ accounting: ACCOUNTING_APP_0_0_1,
3418
+ 'change-detection': CHANGE_DETECTION_APP_0_0_1,
3419
+ 'crop-monitoring': CROP_MONITORING_APP_0_0_1,
3420
+ 'customer-interview': CUSTOMER_INTERVIEW_APP_0_0_1,
3421
+ 'data-quality': DATA_QUALITY_APP_0_0_1,
3422
+ decide: DECIDE_APP_0_0_1,
3423
+ 'disaster-assessment': DISASTER_ASSESSMENT_APP_0_0_1,
3424
+ 'event-response': EVENT_RESPONSE_APP_0_0_1,
3425
+ 'inbox-triage': INBOX_TRIAGE_APP_0_0_1,
3426
+ 'model-choice': MODEL_CHOICE_APP_0_0_1,
3427
+ 'month-end-close': MONTH_END_CLOSE_APP_0_0_1,
3428
+ 'pipeline-report': PIPELINE_REPORT_APP_0_0_1,
3429
+ 'quote-calculator': QUOTE_CALCULATOR_APP_0_0_1,
3430
+ 'report-from-a-file': REPORT_FROM_A_FILE_APP_0_0_1,
3431
+ sales: SALES_APP_0_0_1,
3432
+ 'ship-or-fix': SHIP_OR_FIX_APP_0_0_1,
3433
+ 'supplier-comparison': SUPPLIER_COMPARISON_APP_0_0_1,
3434
+ 'support-desk': SUPPORT_DESK_APP_0_0_1,
3435
+ 'web-research': WEB_RESEARCH_APP_0_0_1,
3436
+ };
3437
+ /** An application, by `id` or `id:version`, or undefined. */
3438
+ export function getApp(ref) {
3439
+ // Own entries only: `constructor` and `toString` are not applications.
3440
+ const own = (id) => Object.prototype.hasOwnProperty.call(APP_CATALOGUE, id)
3441
+ ? APP_CATALOGUE[id]
3442
+ : undefined;
3443
+ const at = ref.lastIndexOf(':');
3444
+ return (own(ref) ??
3445
+ (at > 0 && ref.slice(at + 1).includes('.')
3446
+ ? own(ref.slice(0, at))
3447
+ : undefined));
3448
+ }
3449
+ /**
3450
+ * Each application as the document its file holds: the spec's own words,
3451
+ * nothing written that is at its default. What reading and writing an
3452
+ * Appspec have to give back.
3453
+ */
3454
+ export const APP_SOURCES = {
3455
+ accounting: {
3456
+ schema: 'loop.app/v1',
3457
+ id: 'accounting',
3458
+ name: 'Accounting',
3459
+ kind: 'chat',
3460
+ description: "Answers requests for financial reports, such as open invoices, aged balances, a trial balance or a customer's ledger, from the Odoo books, which it only reads.",
3461
+ owner: 'Datalayer <info@datalayer.io>',
3462
+ agent: 'worker-accountant:0.0.1',
3463
+ instructions: 'You answer requests for financial reports. They usually come from the Sales application over A2A, and you answer them from the Odoo books, which you reach through the odoo-accounting tools and only read. Use the tools for every figure: list, get, trial balance, general ledger, partner ledger, aged balance, open balances. Answer with the report itself: its period, its currency, the company it is for, the figures as the books hold them, and the tool each figure came from. When a request does not say its period or whom it is about, take the current fiscal year and the default company and say that you did. When the books do not hold the answer, or a tool is refused, say so plainly and do not fill the gap. Never write to Odoo: never create, post, reconcile, book, match, lock or delete anything, and do not offer to. A request to change the books is answered with what a person would have to do, not done.',
3464
+ connections: [
3465
+ {
3466
+ server: 'odoo-accounting:0.0.1',
3467
+ },
3468
+ ],
3469
+ rules: [
3470
+ {
3471
+ action: 'Read the books',
3472
+ applies_to: 'read',
3473
+ behaviour: 'do_it',
3474
+ },
3475
+ {
3476
+ action: 'Change the books',
3477
+ applies_to: ['write', 'delete'],
3478
+ behaviour: 'ask_first',
3479
+ },
3480
+ ],
3481
+ interface: {
3482
+ welcome: "Ask me for a report from the books: open invoices, aged balances, a trial balance or a customer's ledger. I read Odoo; I change nothing.",
3483
+ starters: [
3484
+ {
3485
+ label: 'Open invoices',
3486
+ message: 'List the customer invoices that are still open, with the total due.',
3487
+ },
3488
+ {
3489
+ label: 'Aged receivables',
3490
+ message: 'Give the aged receivables as of today, by customer.',
3491
+ },
3492
+ {
3493
+ label: 'Trial balance',
3494
+ message: 'Give the trial balance for last month.',
3495
+ },
3496
+ ],
3497
+ assistant: 'wizard',
3498
+ outputs: ['text/markdown', 'application/x-ipynb+json'],
3499
+ },
3500
+ tests: {
3501
+ cases: [
3502
+ {
3503
+ ask: 'List the customer invoices that are still open, with the total due.',
3504
+ expect: 'It reads the open invoices with the odoo-accounting tools and answers with each invoice, its amount due, the total and the currency.',
3505
+ },
3506
+ {
3507
+ ask: 'Give the trial balance for last month.',
3508
+ expect: 'It answers with the trial balance for the previous month and says the company it is for.',
3509
+ },
3510
+ {
3511
+ ask: 'Post the draft invoice INV/2026/0042.',
3512
+ expect: 'It does not post it. It says that it only reads the books and what a person would have to do.',
3513
+ },
3514
+ {
3515
+ ask: 'What is the revenue of a company that is not in Odoo?',
3516
+ expect: 'It says the books do not hold it, and invents nothing.',
3517
+ },
3518
+ ],
3519
+ verified: {
3520
+ live: [
3521
+ "Answered live over A2A on a developer's machine (2026-10-06), asked for the open customer invoices: it read the aged receivables from the Odoo books and said that the list of invoices had failed. One column total of its table was wrong, so its first test does not pass yet.",
3522
+ ],
3523
+ unverified: [
3524
+ 'Its tests have not been run as a set: no validation run is attached to it.',
3525
+ ],
3526
+ },
3527
+ },
3528
+ record: {
3529
+ keep_for: '30_days',
3530
+ include: ['conversations'],
3531
+ },
3532
+ deployment: {
3533
+ hosted: {},
3534
+ },
3535
+ tags: ['example', 'accounting', 'finance', 'odoo', 'a2a', 'team'],
3536
+ icon: 'book',
3537
+ emoji: '🧾',
3538
+ },
3539
+ 'change-detection': {
3540
+ schema: 'loop.app/v1',
3541
+ id: 'change-detection',
3542
+ name: 'Change detection',
3543
+ kind: 'chat',
3544
+ description: 'Finds what changed on the ground between two dates — land use, vegetation, water, built-up area — from the satellite imagery NASA Earthdata holds, which it searches and reads, with the granules behind each change it reports.',
3545
+ owner: 'Datalayer <info@datalayer.io>',
3546
+ agent: 'worker-change-detection:0.0.1',
3547
+ instructions: 'You detect change from satellite imagery. Requests usually come from the Event response application over A2A, and you answer them from NASA Earthdata, which you reach through the earthdata tools: search the datasets that observe the surface at the place asked, then the granules at the first date and at the second, and compare what they show. You download nothing: when data must be fetched, describe it and write the script a person would run. Answer with the change itself: the place and the two dates, each change you read — where, what kind, how large — and how confident you are, the dataset and granule behind each one. When a request does not say the place or the dates, say what you need. When Earthdata holds nothing for it, say so plainly and do not fill the gap.',
3548
+ connections: [
3549
+ {
3550
+ server: 'earthdata:0.0.1',
3551
+ },
3552
+ ],
3553
+ rules: [
3554
+ {
3555
+ action: 'Search and read the imagery',
3556
+ applies_to: 'read',
3557
+ behaviour: 'do_it',
3558
+ },
3559
+ {
3560
+ action: 'Download files to the runtime',
3561
+ applies_to: 'write',
3562
+ behaviour: 'ask_first',
3563
+ },
3564
+ ],
3565
+ interface: {
3566
+ accent: 'violet',
3567
+ welcome: "Give me a place and two dates, and I'll tell you what changed on the ground between them from the satellite imagery NASA Earthdata holds. I search and read; I download nothing.",
3568
+ starters: [
3569
+ {
3570
+ label: 'Change between two dates',
3571
+ message: 'What changed around 39.5N, 0.4W between 1 October and 15 November 2024?',
3572
+ },
3573
+ {
3574
+ label: 'Water extent',
3575
+ message: 'How did the water extent change around the Ahr valley between 10 and 20 July 2021?',
3576
+ },
3577
+ {
3578
+ label: 'Imagery at two dates',
3579
+ message: 'Which granules cover Los Angeles on 1 January and 15 January 2025?',
3580
+ },
3581
+ ],
3582
+ assistant: 'cat',
3583
+ outputs: ['text/markdown', 'application/x-ipynb+json'],
3584
+ },
3585
+ tests: {
3586
+ cases: [
3587
+ {
3588
+ ask: 'What changed around 39.5N, 0.4W between 1 October and 15 November 2024?',
3589
+ expect: 'It searches the datasets and the granules at both dates with the earthdata tools and answers with each change it read, its kind and its size, and the granules behind it.',
3590
+ },
3591
+ {
3592
+ ask: 'Which granules cover Los Angeles on 1 January and 15 January 2025?',
3593
+ expect: 'It lists the granules at both dates, with their datasets, and downloads nothing.',
3594
+ },
3595
+ {
3596
+ ask: 'Download the granules at both dates.',
3597
+ expect: 'It does not download them. It writes the script a person would run, and says what it would fetch.',
3598
+ },
3599
+ {
3600
+ ask: 'What changed?',
3601
+ expect: 'It asks where and between which dates, before it searches.',
3602
+ },
3603
+ ],
3604
+ verified: {
3605
+ unverified: [
3606
+ 'It has not been asked live over A2A yet: its agent is set up, not enabled, on this machine; the earthdata server is enabled.',
3607
+ 'Its tests have not been run as a set: no validation run is attached to it.',
3608
+ ],
3609
+ },
3610
+ },
3611
+ record: {
3612
+ keep_for: '30_days',
3613
+ include: ['conversations'],
3614
+ },
3615
+ deployment: {
3616
+ hosted: {},
3617
+ },
3618
+ tags: [
3619
+ 'example',
3620
+ 'earth-observation',
3621
+ 'change-detection',
3622
+ 'earthdata',
3623
+ 'a2a',
3624
+ 'scene',
3625
+ ],
3626
+ icon: 'telescope',
3627
+ emoji: '🔍',
3628
+ },
3629
+ 'crop-monitoring': {
2621
3630
  schema: 'loop.app/v1',
2622
- id: 'accounting',
2623
- name: 'Accounting',
3631
+ id: 'crop-monitoring',
3632
+ name: 'Crop monitoring',
2624
3633
  kind: 'chat',
2625
- description: "Answers requests for financial reports, such as open invoices, aged balances, a trial balance or a customer's ledger, from the Odoo books, which it only reads.",
3634
+ description: 'Tracks crop vigour and growth over time from the satellite imagery NASA Earthdata holds, which it searches and reads, and flags the fields that need attention, with the datasets and granules behind each finding.',
2626
3635
  owner: 'Datalayer <info@datalayer.io>',
2627
- agent: 'worker-accountant:0.0.1',
2628
- instructions: 'You answer requests for financial reports. They usually come from the Sales application over A2A, and you answer them from the Odoo books, which you reach through the odoo-accounting tools and only read. Use the tools for every figure: list, get, trial balance, general ledger, partner ledger, aged balance, open balances. Answer with the report itself: its period, its currency, the company it is for, the figures as the books hold them, and the tool each figure came from. When a request does not say its period or whom it is about, take the current fiscal year and the default company and say that you did. When the books do not hold the answer, or a tool is refused, say so plainly and do not fill the gap. Never write to Odoo: never create, post, reconcile, book, match, lock or delete anything, and do not offer to. A request to change the books is answered with what a person would have to do, not done.',
3636
+ agent: 'worker-crop-monitoring:0.0.1',
3637
+ instructions: 'You monitor crops from satellite imagery. You work from NASA Earthdata, which you reach through the earthdata tools: search the datasets that observe vegetation, land surface and moisture, then the granules that cover the field and the period asked, and say what each one shows — its dataset, its dates, its resolution, its cloud cover when it is given. You download nothing: when a person wants the data, describe what to fetch and write the script that fetches it for them to run. Answer with the monitoring itself: the field and the period, the vigour and growth you read across the dates, the fields or the parcels that need attention and why, and the dataset and granule behind each finding. When a request does not say the field or the period, ask before you search. When Earthdata holds nothing for it, say so plainly and do not fill the gap.',
2629
3638
  connections: [
2630
3639
  {
2631
- server: 'odoo-accounting:0.0.1',
3640
+ server: 'earthdata:0.0.1',
2632
3641
  },
2633
3642
  ],
2634
3643
  rules: [
2635
3644
  {
2636
- action: 'Read the books',
3645
+ action: 'Search and read the imagery',
2637
3646
  applies_to: 'read',
2638
3647
  behaviour: 'do_it',
2639
3648
  },
2640
3649
  {
2641
- action: 'Change the books',
2642
- applies_to: ['write', 'delete'],
3650
+ action: 'Download files to the runtime',
3651
+ applies_to: 'write',
2643
3652
  behaviour: 'ask_first',
2644
3653
  },
2645
3654
  ],
2646
3655
  interface: {
2647
- welcome: "Ask me for a report from the books: open invoices, aged balances, a trial balance or a customer's ledger. I read Odoo; I change nothing.",
3656
+ accent: 'lime',
3657
+ welcome: "Give me a field and a period, and I'll follow its crops across the satellite imagery NASA Earthdata holds: vigour, growth and what needs attention. I search and read; I download nothing.",
2648
3658
  starters: [
2649
3659
  {
2650
- label: 'Open invoices',
2651
- message: 'List the customer invoices that are still open, with the total due.',
3660
+ label: 'Vigour this season',
3661
+ message: 'How has crop vigour evolved over the last three months around 45.5N, 10.2E?',
2652
3662
  },
2653
3663
  {
2654
- label: 'Aged receivables',
2655
- message: 'Give the aged receivables as of today, by customer.',
3664
+ label: 'Fields to watch',
3665
+ message: 'Which fields around 41.9N, 12.5E show a drop in vegetation this month compared with last?',
2656
3666
  },
2657
3667
  {
2658
- label: 'Trial balance',
2659
- message: 'Give the trial balance for last month.',
3668
+ label: 'Imagery available',
3669
+ message: 'Which datasets and granules cover the Po valley for June 2026?',
2660
3670
  },
2661
3671
  ],
2662
- assistant: 'wizard',
3672
+ assistant: 'eyes',
2663
3673
  outputs: ['text/markdown', 'application/x-ipynb+json'],
2664
3674
  },
2665
3675
  tests: {
2666
3676
  cases: [
2667
3677
  {
2668
- ask: 'List the customer invoices that are still open, with the total due.',
2669
- expect: 'It reads the open invoices with the odoo-accounting tools and answers with each invoice, its amount due, the total and the currency.',
3678
+ ask: 'How has crop vigour evolved over the last three months around 45.5N, 10.2E?',
3679
+ expect: 'It searches the vegetation datasets and their granules over the period with the earthdata tools and answers with what the imagery shows across the dates, naming each dataset and granule.',
2670
3680
  },
2671
3681
  {
2672
- ask: 'Give the trial balance for last month.',
2673
- expect: 'It answers with the trial balance for the previous month and says the company it is for.',
3682
+ ask: 'Which datasets and granules cover the Po valley for June 2026?',
3683
+ expect: 'It lists the datasets and granules it found, with their dates, and downloads nothing.',
2674
3684
  },
2675
3685
  {
2676
- ask: 'Post the draft invoice INV/2026/0042.',
2677
- expect: 'It does not post it. It says that it only reads the books and what a person would have to do.',
3686
+ ask: 'Download the granules for me.',
3687
+ expect: 'It does not download them. It writes the script a person would run, and says what it would fetch.',
2678
3688
  },
2679
3689
  {
2680
- ask: 'What is the revenue of a company that is not in Odoo?',
2681
- expect: 'It says the books do not hold it, and invents nothing.',
3690
+ ask: 'Which fields are at risk on Mars?',
3691
+ expect: 'It says Earthdata holds no such imagery, and invents nothing.',
2682
3692
  },
2683
3693
  ],
2684
3694
  verified: {
2685
- live: [
2686
- "Answered live over A2A on a developer's machine (2026-10-06), asked for the open customer invoices: it read the aged receivables from the Odoo books and said that the list of invoices had failed. One column total of its table was wrong, so its first test does not pass yet.",
2687
- ],
2688
3695
  unverified: [
3696
+ 'It has not run live yet: its agent is set up, not enabled, on this machine; the earthdata server is enabled.',
2689
3697
  'Its tests have not been run as a set: no validation run is attached to it.',
2690
3698
  ],
2691
3699
  },
@@ -2697,9 +3705,16 @@ export const APP_SOURCES = {
2697
3705
  deployment: {
2698
3706
  hosted: {},
2699
3707
  },
2700
- tags: ['example', 'accounting', 'finance', 'odoo', 'a2a', 'team'],
2701
- icon: 'book',
2702
- emoji: '🧾',
3708
+ tags: [
3709
+ 'example',
3710
+ 'earth-observation',
3711
+ 'agriculture',
3712
+ 'earthdata',
3713
+ 'a2a',
3714
+ 'scene',
3715
+ ],
3716
+ icon: 'telescope',
3717
+ emoji: '🌾',
2703
3718
  },
2704
3719
  'customer-interview': {
2705
3720
  schema: 'loop.app/v1',
@@ -2935,6 +3950,168 @@ export const APP_SOURCES = {
2935
3950
  icon: 'law',
2936
3951
  emoji: '⚖️',
2937
3952
  },
3953
+ 'disaster-assessment': {
3954
+ schema: 'loop.app/v1',
3955
+ id: 'disaster-assessment',
3956
+ name: 'Disaster assessment',
3957
+ kind: 'chat',
3958
+ description: 'Estimates the area a natural disaster affected and the extent of the damage from the satellite imagery NASA Earthdata holds before and after the event, which it searches and reads, with the granules behind each figure.',
3959
+ owner: 'Datalayer <info@datalayer.io>',
3960
+ agent: 'worker-disaster-assessment:0.0.1',
3961
+ instructions: 'You assess disasters from satellite imagery. Requests usually come from the Event response application over A2A, and you answer them from NASA Earthdata, which you reach through the earthdata tools: search the datasets that observe the surface at the place asked, then the granules before the event and after it, and compare what they show. You download nothing: when data must be fetched, describe it and write the script a person would run. Answer with the assessment itself: the event, the place and the dates, the area affected and how you bounded it, the extent of the damage you read and how confident you are, the dataset and granule behind each figure. When a request does not say the event, the place or its date, say what you need. When Earthdata holds nothing for it, say so plainly and do not fill the gap.',
3962
+ connections: [
3963
+ {
3964
+ server: 'earthdata:0.0.1',
3965
+ },
3966
+ ],
3967
+ rules: [
3968
+ {
3969
+ action: 'Search and read the imagery',
3970
+ applies_to: 'read',
3971
+ behaviour: 'do_it',
3972
+ },
3973
+ {
3974
+ action: 'Download files to the runtime',
3975
+ applies_to: 'write',
3976
+ behaviour: 'ask_first',
3977
+ },
3978
+ ],
3979
+ interface: {
3980
+ accent: 'rose',
3981
+ welcome: "Name an event, a place and a date, and I'll compare the satellite imagery NASA Earthdata holds before and after it: the area affected and the extent of the damage. I search and read; I download nothing.",
3982
+ starters: [
3983
+ {
3984
+ label: 'Flood extent',
3985
+ message: 'Assess the flooding around Valencia, Spain, after 29 October 2024.',
3986
+ },
3987
+ {
3988
+ label: 'Wildfire damage',
3989
+ message: 'How much area burned around Los Angeles in the fires of January 2025?',
3990
+ },
3991
+ {
3992
+ label: 'Imagery before and after',
3993
+ message: 'Which granules show the Ahr valley before and after 14 July 2021?',
3994
+ },
3995
+ ],
3996
+ assistant: 'wizard',
3997
+ outputs: ['text/markdown', 'application/x-ipynb+json'],
3998
+ },
3999
+ tests: {
4000
+ cases: [
4001
+ {
4002
+ ask: 'Assess the flooding around Valencia, Spain, after 29 October 2024.',
4003
+ expect: 'It searches the datasets and the granules before and after the date with the earthdata tools and answers with the area affected, the extent it read and the granules behind each figure.',
4004
+ },
4005
+ {
4006
+ ask: 'Which granules show the Ahr valley before and after 14 July 2021?',
4007
+ expect: 'It lists the granules on either side of the date, with their datasets, and downloads nothing.',
4008
+ },
4009
+ {
4010
+ ask: 'Download everything you found.',
4011
+ expect: 'It does not download it. It writes the script a person would run, and says what it would fetch.',
4012
+ },
4013
+ {
4014
+ ask: 'Assess the earthquake.',
4015
+ expect: 'It asks which event, where and when, before it searches.',
4016
+ },
4017
+ ],
4018
+ verified: {
4019
+ unverified: [
4020
+ 'It has not been asked live over A2A yet: its agent is set up, not enabled, on this machine; the earthdata server is enabled.',
4021
+ 'Its tests have not been run as a set: no validation run is attached to it.',
4022
+ ],
4023
+ },
4024
+ },
4025
+ record: {
4026
+ keep_for: '30_days',
4027
+ include: ['conversations'],
4028
+ },
4029
+ deployment: {
4030
+ hosted: {},
4031
+ },
4032
+ tags: [
4033
+ 'example',
4034
+ 'earth-observation',
4035
+ 'disaster',
4036
+ 'earthdata',
4037
+ 'a2a',
4038
+ 'scene',
4039
+ ],
4040
+ icon: 'pulse',
4041
+ emoji: '🌊',
4042
+ },
4043
+ 'event-response': {
4044
+ schema: 'loop.app/v1',
4045
+ id: 'event-response',
4046
+ name: 'Event response',
4047
+ kind: 'chat',
4048
+ description: 'Takes word of a live event — a flood, a fire, a storm — asks Disaster assessment for the area affected and the damage and Change detection for what changed on the ground, each over A2A, and reports what they answered, adding no figure of its own.',
4049
+ owner: 'Datalayer <info@datalayer.io>',
4050
+ agent: 'worker-event-response:0.0.1',
4051
+ instructions: 'You respond to events. You read no imagery yourself: Disaster assessment and Change detection do. When the person tells you of an event, call ask_disaster_assessment once with one request the assessor can act on without the rest of this conversation — the event, the place and the date — and ask_change_detection once with the place and the two dates to compare, before and after. Then report what each answered, as it answered it: the area affected, the extent of the damage, each change on the ground, their confidence and their caveats, and which member each figure came from. Never invent, estimate, round or complete a figure, and never fill a gap from what you know. When a member cannot answer, or answers only in part, say so and repeat what it said. When the request does not say the event, the place or its date, ask the person before you ask anyone. You change nothing anywhere: you ask, and you report.',
4052
+ interface: {
4053
+ accent: 'rose',
4054
+ welcome: "Tell me of an event — a flood, a fire, a storm — where and when, and I'll get the area affected and the damage from Disaster assessment and what changed on the ground from Change detection.",
4055
+ starters: [
4056
+ {
4057
+ label: 'Flood',
4058
+ message: 'Valencia, Spain, was flooded on 29 October 2024. What was affected, and what changed?',
4059
+ },
4060
+ {
4061
+ label: 'Wildfire',
4062
+ message: 'Fires burned around Los Angeles from 7 January 2025. What was affected, and what changed?',
4063
+ },
4064
+ {
4065
+ label: 'Storm',
4066
+ message: 'The Ahr valley was hit by a storm on 14 July 2021. What was affected, and what changed?',
4067
+ },
4068
+ ],
4069
+ assistant: 'paperclip',
4070
+ },
4071
+ tests: {
4072
+ cases: [
4073
+ {
4074
+ ask: 'Valencia, Spain, was flooded on 29 October 2024. What was affected, and what changed?',
4075
+ expect: 'It calls ask_disaster_assessment once with the event, the place and the date, and ask_change_detection once with the place and the dates before and after, and reports what each answered, adding no figure.',
4076
+ },
4077
+ {
4078
+ ask: 'There was a flood. What was affected?',
4079
+ expect: 'It asks where and when before asking anyone.',
4080
+ },
4081
+ {
4082
+ ask: 'Just estimate the damage yourself, no need to ask anyone.',
4083
+ expect: 'It does not estimate. It asks Disaster assessment, or says that it only reports what the members answered.',
4084
+ },
4085
+ {
4086
+ ask: 'Fires burned around Los Angeles from 7 January 2025. What was affected, and what changed?',
4087
+ expect: 'When a member cannot answer, it says which one could not and why, and invents nothing.',
4088
+ },
4089
+ ],
4090
+ verified: {
4091
+ unverified: [
4092
+ 'It has not asked Disaster assessment or Change detection live yet: its agent is set up, not enabled, on this machine.',
4093
+ 'Its tests have not been run as a set: no validation run is attached to it.',
4094
+ ],
4095
+ },
4096
+ },
4097
+ record: {
4098
+ keep_for: '30_days',
4099
+ include: ['conversations'],
4100
+ },
4101
+ deployment: {
4102
+ hosted: {},
4103
+ },
4104
+ tags: [
4105
+ 'example',
4106
+ 'earth-observation',
4107
+ 'insurance',
4108
+ 'disaster',
4109
+ 'a2a',
4110
+ 'scene',
4111
+ ],
4112
+ icon: 'pulse',
4113
+ emoji: '🛡️',
4114
+ },
2938
4115
  'inbox-triage': {
2939
4116
  schema: 'loop.app/v1',
2940
4117
  id: 'inbox-triage',
@@ -3208,6 +4385,89 @@ export const APP_SOURCES = {
3208
4385
  icon: 'cpu',
3209
4386
  emoji: '🧠',
3210
4387
  },
4388
+ 'month-end-close': {
4389
+ schema: 'loop.app/v1',
4390
+ id: 'month-end-close',
4391
+ name: 'Month-end close',
4392
+ kind: 'chat',
4393
+ description: 'Drives the month-end close from the Odoo books, which it only reads: the close checklist, the accruals to book, the open items and the reconciliation gaps that remain, each with the figures behind it.',
4394
+ owner: 'Datalayer <info@datalayer.io>',
4395
+ agent: 'worker-month-end-close:0.0.1',
4396
+ instructions: 'You drive the month-end close. You work from the Odoo books, which you reach through the odoo-accounting tools and only read. Use the tools for every figure: the journal entries of the period, the open balances, the trial balance, the general ledger, the partner ledgers and the aged balances. Answer with the close itself: the period, the company, the currency, the checklist with what is done and what is not, the accruals you suggest and why, the unreconciled items and the gaps that remain, and the tool each figure came from. When a request does not say its period or its company, take the month that just ended and the default company and say that you did. When the books do not hold the answer, or a tool is refused, say so plainly and do not fill the gap. Never write to Odoo: never create, post, reconcile, book, match, lock or delete anything, and do not offer to. A request to change the books is answered with what a person would have to do, not done.',
4397
+ connections: [
4398
+ {
4399
+ server: 'odoo-accounting:0.0.1',
4400
+ },
4401
+ ],
4402
+ rules: [
4403
+ {
4404
+ action: 'Read the books',
4405
+ applies_to: 'read',
4406
+ behaviour: 'do_it',
4407
+ },
4408
+ {
4409
+ action: 'Change the books',
4410
+ applies_to: ['write', 'delete'],
4411
+ behaviour: 'ask_first',
4412
+ },
4413
+ ],
4414
+ interface: {
4415
+ accent: 'sun',
4416
+ welcome: 'Ask me where the month-end close stands: the checklist, the accruals to book, the open items and the reconciliation gaps. I read Odoo; I change nothing.',
4417
+ starters: [
4418
+ {
4419
+ label: 'Close checklist',
4420
+ message: 'Where does the month-end close stand for last month? Give me the checklist.',
4421
+ },
4422
+ {
4423
+ label: 'Accruals',
4424
+ message: 'Which accruals should be booked for last month, and for how much?',
4425
+ },
4426
+ {
4427
+ label: 'Reconciliation gaps',
4428
+ message: 'Which bank lines and open items are still unreconciled for last month?',
4429
+ },
4430
+ ],
4431
+ assistant: 'cat',
4432
+ outputs: ['text/markdown', 'application/x-ipynb+json'],
4433
+ },
4434
+ tests: {
4435
+ cases: [
4436
+ {
4437
+ ask: 'Where does the month-end close stand for last month? Give me the checklist.',
4438
+ expect: "It reads the period's entries and balances with the odoo-accounting tools and answers with a checklist that says what is done and what is not, the company and the period.",
4439
+ },
4440
+ {
4441
+ ask: 'Which accruals should be booked for last month, and for how much?',
4442
+ expect: 'It suggests accruals from what the books hold, each with its amount and the entries it read, and books none of them.',
4443
+ },
4444
+ {
4445
+ ask: 'Post the accruals you suggested.',
4446
+ expect: 'It does not post them. It says that it only reads the books and what a person would have to do.',
4447
+ },
4448
+ {
4449
+ ask: 'Is the close done for a company that is not in Odoo?',
4450
+ expect: 'It says the books do not hold it, and invents nothing.',
4451
+ },
4452
+ ],
4453
+ verified: {
4454
+ unverified: [
4455
+ 'It has not run live yet: its agent and the odoo-accounting server are set up, not enabled, on this machine.',
4456
+ 'Its tests have not been run as a set: no validation run is attached to it.',
4457
+ ],
4458
+ },
4459
+ },
4460
+ record: {
4461
+ keep_for: '30_days',
4462
+ include: ['conversations'],
4463
+ },
4464
+ deployment: {
4465
+ hosted: {},
4466
+ },
4467
+ tags: ['example', 'accounting', 'finance', 'odoo', 'a2a', 'scene'],
4468
+ icon: 'sync',
4469
+ emoji: '🗓️',
4470
+ },
3211
4471
  'pipeline-report': {
3212
4472
  schema: 'loop.app/v1',
3213
4473
  id: 'pipeline-report',
@@ -4121,14 +5381,17 @@ export const APP_SOURCES = {
4121
5381
  {
4122
5382
  label: 'Reset my password',
4123
5383
  message: 'How do I reset my password?',
5384
+ category: 'Account',
4124
5385
  },
4125
5386
  {
4126
5387
  label: 'Returns',
4127
5388
  message: 'Can I return a product I bought six weeks ago?',
5389
+ category: 'Orders',
4128
5390
  },
4129
5391
  {
4130
5392
  label: 'Plans',
4131
5393
  message: 'What is the difference between the Team and the Business plan?',
5394
+ category: 'Account',
4132
5395
  },
4133
5396
  ],
4134
5397
  settings: {
@@ -4142,6 +5405,40 @@ export const APP_SOURCES = {
4142
5405
  },
4143
5406
  },
4144
5407
  },
5408
+ settings_ui: {
5409
+ product: {
5410
+ 'ui:widget': 'radio',
5411
+ },
5412
+ },
5413
+ translations: {
5414
+ fr: {
5415
+ name: 'Service client',
5416
+ welcome: 'Posez-moi vos questions sur le produit. Je réponds à partir de sa documentation et vous montre où ; quand elle ne le dit pas, je vous le dis.',
5417
+ starters: {
5418
+ 'Reset my password': {
5419
+ label: 'Réinitialiser mon mot de passe',
5420
+ message: 'Comment réinitialiser mon mot de passe ?',
5421
+ },
5422
+ Returns: {
5423
+ label: 'Retours',
5424
+ message: 'Puis-je retourner un produit acheté il y a six semaines ?',
5425
+ },
5426
+ Plans: {
5427
+ label: 'Offres',
5428
+ message: "Quelle est la différence entre l'offre Team et l'offre Business ?",
5429
+ },
5430
+ },
5431
+ categories: {
5432
+ Account: 'Compte',
5433
+ Orders: 'Commandes',
5434
+ },
5435
+ settings: {
5436
+ product: {
5437
+ title: 'Produit',
5438
+ },
5439
+ },
5440
+ },
5441
+ },
4145
5442
  components: [
4146
5443
  'Card',
4147
5444
  'Column',
@@ -4389,11 +5686,16 @@ export const APP_SOURCES = {
4389
5686
  */
4390
5687
  export const APP_BUILT = {
4391
5688
  accounting: 'written',
5689
+ 'change-detection': 'written',
5690
+ 'crop-monitoring': 'written',
4392
5691
  'customer-interview': 'python',
4393
5692
  'data-quality': 'written',
4394
5693
  decide: 'written',
5694
+ 'disaster-assessment': 'written',
5695
+ 'event-response': 'written',
4395
5696
  'inbox-triage': 'written',
4396
5697
  'model-choice': 'written',
5698
+ 'month-end-close': 'written',
4397
5699
  'pipeline-report': 'written',
4398
5700
  'quote-calculator': 'written',
4399
5701
  'report-from-a-file': 'python',