@datalayer/agent-runtimes 1.3.95 → 1.3.96
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.
- package/dist-embed/datalayer-app-main.js +3 -3
- package/dist-embed/datalayer-app.js +1 -1
- package/lib/apps/__tests__/fixtures/sceneCheckCases.json +352 -0
- package/lib/apps/apps/sceneChecks.d.ts +92 -0
- package/lib/apps/apps/sceneChecks.js +649 -0
- package/lib/apps/apps/sceneShape.d.ts +8 -0
- package/lib/apps/apps/sceneShape.js +191 -0
- package/lib/apps/apps/sceneYaml.d.ts +64 -0
- package/lib/apps/apps/sceneYaml.js +253 -0
- package/lib/apps/core/canvasParts.d.ts +28 -0
- package/lib/apps/core/canvasParts.js +14 -0
- package/lib/apps/core/index.d.ts +1 -0
- package/lib/apps/core/index.js +2 -0
- package/lib/apps/embed/loader.js +10 -0
- package/lib/apps/plugins/agents/SandboxSelector.js +13 -2
- package/lib/apps/plugins/agents/host.d.ts +2 -0
- package/lib/apps/plugins/agents/host.js +16 -0
- package/lib/apps/plugins/agents/plugin.js +10 -2
- package/lib/apps/plugins/agents/switchable.d.ts +12 -0
- package/lib/apps/plugins/agents/switchable.js +23 -0
- package/lib/apps/plugins/canvas-parts/index.d.ts +44 -0
- package/lib/apps/plugins/canvas-parts/index.js +209 -0
- package/lib/hooks/useAgUi.js +4 -1
- package/lib/protocols/AGUIAdapter.js +5 -1
- package/lib/protocols/agUiRefusal.d.ts +47 -0
- package/lib/protocols/agUiRefusal.js +87 -0
- package/lib/specs/apps.js +20 -12
- package/lib/specs/scenes.js +103 -98
- package/lib/specs/teams/teams.js +1 -1
- package/package.json +3 -1
- package/scripts/dist-embed.mjs +116 -0
- package/scripts/record-scene-checks.py +600 -0
package/lib/specs/scenes.js
CHANGED
|
@@ -219,8 +219,8 @@ export const CROP_MONITORING_SCENE_0_0_1 = {
|
|
|
219
219
|
'Crop Monitoring: a chart',
|
|
220
220
|
],
|
|
221
221
|
mustSay: ['vigour'],
|
|
222
|
-
mustNotSay: ['downloaded'],
|
|
223
|
-
within: '
|
|
222
|
+
mustNotSay: ['I downloaded', 'I have downloaded', 'downloaded them'],
|
|
223
|
+
within: '120s',
|
|
224
224
|
},
|
|
225
225
|
{
|
|
226
226
|
beat: 'fields-to-watch',
|
|
@@ -230,7 +230,7 @@ export const CROP_MONITORING_SCENE_0_0_1 = {
|
|
|
230
230
|
'Crop Monitoring: a table',
|
|
231
231
|
],
|
|
232
232
|
mustSay: ['drop'],
|
|
233
|
-
within: '
|
|
233
|
+
within: '120s',
|
|
234
234
|
},
|
|
235
235
|
{
|
|
236
236
|
beat: 'imagery-available',
|
|
@@ -240,8 +240,8 @@ export const CROP_MONITORING_SCENE_0_0_1 = {
|
|
|
240
240
|
'Crop Monitoring: sources',
|
|
241
241
|
],
|
|
242
242
|
mustSay: ['granule'],
|
|
243
|
-
mustNotSay: ['downloaded'],
|
|
244
|
-
within: '
|
|
243
|
+
mustNotSay: ['I downloaded', 'I have downloaded', 'downloaded them'],
|
|
244
|
+
within: '120s',
|
|
245
245
|
},
|
|
246
246
|
{
|
|
247
247
|
beat: 'save-granules',
|
|
@@ -251,11 +251,16 @@ export const CROP_MONITORING_SCENE_0_0_1 = {
|
|
|
251
251
|
'Crop Monitoring: an approval',
|
|
252
252
|
],
|
|
253
253
|
mustSay: ['granule'],
|
|
254
|
-
mustNotSay: [
|
|
255
|
-
|
|
254
|
+
mustNotSay: [
|
|
255
|
+
'I downloaded',
|
|
256
|
+
'I have downloaded',
|
|
257
|
+
'downloaded them',
|
|
258
|
+
'saved them',
|
|
259
|
+
],
|
|
260
|
+
within: '120s',
|
|
256
261
|
},
|
|
257
262
|
],
|
|
258
|
-
within: '
|
|
263
|
+
within: '10m',
|
|
259
264
|
verified: {
|
|
260
265
|
live: [],
|
|
261
266
|
recorded: [],
|
|
@@ -273,34 +278,34 @@ export const CROP_MONITORING_SCENE_0_0_1 = {
|
|
|
273
278
|
},
|
|
274
279
|
setup: ["The agent 'worker-crop-monitoring:0.0.1' is not enabled."],
|
|
275
280
|
played: {
|
|
276
|
-
at: '2026-10-
|
|
281
|
+
at: '2026-10-09T17:40:33+00:00',
|
|
277
282
|
where: 'on Datalayer',
|
|
278
|
-
passed:
|
|
279
|
-
says: 'Rehearsal:
|
|
283
|
+
passed: true,
|
|
284
|
+
says: 'Rehearsal: 4 of 4 beats passed. The scene is Live.',
|
|
280
285
|
beats: [
|
|
281
286
|
{
|
|
282
287
|
beat: 'vigour-this-season',
|
|
283
|
-
state: '
|
|
284
|
-
says:
|
|
285
|
-
seconds:
|
|
288
|
+
state: 'passed',
|
|
289
|
+
says: '',
|
|
290
|
+
seconds: 55.53831131900006,
|
|
286
291
|
},
|
|
287
292
|
{
|
|
288
293
|
beat: 'fields-to-watch',
|
|
289
|
-
state: '
|
|
290
|
-
says:
|
|
291
|
-
seconds:
|
|
294
|
+
state: 'passed',
|
|
295
|
+
says: '',
|
|
296
|
+
seconds: 57.56524624400117,
|
|
292
297
|
},
|
|
293
298
|
{
|
|
294
299
|
beat: 'imagery-available',
|
|
295
|
-
state: '
|
|
296
|
-
says:
|
|
297
|
-
seconds:
|
|
300
|
+
state: 'passed',
|
|
301
|
+
says: '',
|
|
302
|
+
seconds: 58.75493016499968,
|
|
298
303
|
},
|
|
299
304
|
{
|
|
300
305
|
beat: 'save-granules',
|
|
301
|
-
state: '
|
|
302
|
-
says:
|
|
303
|
-
seconds:
|
|
306
|
+
state: 'passed',
|
|
307
|
+
says: '',
|
|
308
|
+
seconds: 49.41034528199998,
|
|
304
309
|
},
|
|
305
310
|
],
|
|
306
311
|
runtime: '1.3.93',
|
|
@@ -340,7 +345,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
|
|
|
340
345
|
face: '🛡️',
|
|
341
346
|
line: 'Tell me what happened; I ask the specialists and report.',
|
|
342
347
|
},
|
|
343
|
-
brief:
|
|
348
|
+
brief: "Take the event and ask one specialist at a time, never both at once, waiting for each answer before you ask the next: Disaster Assessment for the area affected and the damage and for what the archive holds around the event, day by day, and then, only if the request asks what changed on the ground between two dates, Change detection. Report what they answer without adding to it. Do not question the audience first: a cue is the whole of what it says, and nobody is standing there to answer you back. A cue that says no date is yours to fill with the most recent one the imagery has, and a cue that says no place with the area the event names; ask the specialists with what you assumed, and say in your answer what you assumed. A cue that asks to send something is Disaster Assessment's: tell it what is to be sent and to whom, so that it shows the sending as a choice to approve, and never ask the audience to confirm it yourself.",
|
|
344
349
|
},
|
|
345
350
|
{
|
|
346
351
|
member: 'disaster-assessment',
|
|
@@ -354,7 +359,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
|
|
|
354
359
|
face: '🌊',
|
|
355
360
|
line: 'I estimate the area affected and the damage from the imagery.',
|
|
356
361
|
},
|
|
357
|
-
brief: 'From the imagery before and after the event, estimate the area affected and the extent of the damage; say what the imagery does not show.',
|
|
362
|
+
brief: 'From the imagery before and after the event, estimate the area affected and the extent of the damage; say what the imagery does not show. Asked to send an assessment, send nothing: show its sending as a choice to approve — *Send it* · *Not now*.',
|
|
358
363
|
},
|
|
359
364
|
{
|
|
360
365
|
member: 'change-detection',
|
|
@@ -391,7 +396,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
|
|
|
391
396
|
schedule: '',
|
|
392
397
|
event: '',
|
|
393
398
|
},
|
|
394
|
-
narration: 'Event response asks
|
|
399
|
+
narration: 'Event response asks one specialist at a time, waiting for each answer; each searches the imagery around the date.',
|
|
395
400
|
moves: [
|
|
396
401
|
{
|
|
397
402
|
who: 'event-response',
|
|
@@ -630,8 +635,8 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
|
|
|
630
635
|
'Event response: words',
|
|
631
636
|
],
|
|
632
637
|
mustSay: ['Valencia'],
|
|
633
|
-
mustNotSay: ['downloaded'],
|
|
634
|
-
within: '
|
|
638
|
+
mustNotSay: ['I downloaded', 'I have downloaded', 'downloaded them'],
|
|
639
|
+
within: '360s',
|
|
635
640
|
},
|
|
636
641
|
{
|
|
637
642
|
beat: 'wildfire',
|
|
@@ -643,7 +648,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
|
|
|
643
648
|
'Event response: words',
|
|
644
649
|
],
|
|
645
650
|
mustSay: ['Los Angeles'],
|
|
646
|
-
within: '
|
|
651
|
+
within: '240s',
|
|
647
652
|
},
|
|
648
653
|
{
|
|
649
654
|
beat: 'storm',
|
|
@@ -655,7 +660,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
|
|
|
655
660
|
'Event response: words',
|
|
656
661
|
],
|
|
657
662
|
mustSay: ['Ahr'],
|
|
658
|
-
within: '
|
|
663
|
+
within: '240s',
|
|
659
664
|
},
|
|
660
665
|
{
|
|
661
666
|
beat: 'alert',
|
|
@@ -668,15 +673,15 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
|
|
|
668
673
|
],
|
|
669
674
|
mustSay: ['Valencia'],
|
|
670
675
|
mustNotSay: ['I sent'],
|
|
671
|
-
within: '
|
|
676
|
+
within: '240s',
|
|
672
677
|
},
|
|
673
678
|
],
|
|
674
|
-
within: '
|
|
679
|
+
within: '20m',
|
|
675
680
|
verified: {
|
|
676
681
|
live: [],
|
|
677
682
|
recorded: [],
|
|
678
683
|
unverified: [
|
|
679
|
-
'
|
|
684
|
+
'Rehearsed on Datalayer on 2026-10-09: three beats of four pass — wildfire 121 s, storm 58 s, alert 98 s — and flood took 256 s against the 240 s it allows, a bound measured when Event response still asked both specialists at once (A-14).',
|
|
680
685
|
],
|
|
681
686
|
},
|
|
682
687
|
},
|
|
@@ -694,34 +699,34 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
|
|
|
694
699
|
"The agent 'worker-change-detection:0.0.1' is not enabled.",
|
|
695
700
|
],
|
|
696
701
|
played: {
|
|
697
|
-
at: '2026-10-
|
|
702
|
+
at: '2026-10-10T02:57:36+00:00',
|
|
698
703
|
where: 'on Datalayer',
|
|
699
704
|
passed: false,
|
|
700
|
-
says: 'Rehearsal:
|
|
705
|
+
says: 'Rehearsal: 3 of 4 beats passed. 1 failed. The scene is not Live.',
|
|
701
706
|
beats: [
|
|
702
707
|
{
|
|
703
708
|
beat: 'flood',
|
|
704
|
-
state: '
|
|
705
|
-
says:
|
|
706
|
-
seconds:
|
|
709
|
+
state: 'passed',
|
|
710
|
+
says: '',
|
|
711
|
+
seconds: 216.90267557599873,
|
|
707
712
|
},
|
|
708
713
|
{
|
|
709
714
|
beat: 'wildfire',
|
|
710
|
-
state: '
|
|
711
|
-
says:
|
|
712
|
-
seconds:
|
|
715
|
+
state: 'passed',
|
|
716
|
+
says: '',
|
|
717
|
+
seconds: 110.26249580999865,
|
|
713
718
|
},
|
|
714
719
|
{
|
|
715
720
|
beat: 'storm',
|
|
716
|
-
state: '
|
|
717
|
-
says:
|
|
718
|
-
seconds:
|
|
721
|
+
state: 'passed',
|
|
722
|
+
says: '',
|
|
723
|
+
seconds: 55.37315007500001,
|
|
719
724
|
},
|
|
720
725
|
{
|
|
721
726
|
beat: 'alert',
|
|
722
|
-
state: '
|
|
723
|
-
says: "Disaster assessment is not set up: the MCP server tavily needs TAVILY_API_KEY, which this runtime was not given: add it to the account's secrets (or set it before a local run), then configure it again. Disaster assessment is not set up: the skill crawl needs TAVILY_API_KEY, which this runtime was not given: add it to the account's secrets (or set it before a local run), then configure it again. The runtime was stopped.",
|
|
724
|
-
seconds:
|
|
727
|
+
state: 'failed',
|
|
728
|
+
says: 'Expected “Disaster Assessment: an approval” after “Disaster Assessment → Earthdata: search_earth_datagranules”; the transcript went on: “Disaster Assessment → its runtime: show_components”; “Disaster Assessment: I\'ll work through this step by step: find the right datasets, locate pre- and post-event granules for the Valencia flood (late October 2024), then compare what they show.\n\n**Step 1 — Find relevant datasets for flood/surface change over Valencia, Spain**The generic flood search didn\'t return Spain-relevant results. Let me try the CYGNSS watermask (which covers Valencia\'s latitude) and also search for MODIS/Landsat surface reflectance over Valencia.Good. I have MODIS Terra/Aqua surface reflectance (MOD09GA / MYD09GA at 500m) and the CYGNSS watermask. Now let me search for granules — pre-event (before 29 Oct 2024) and post-event (after 29 Oct 2024) — over Valencia.\n\n**Step 2 — Pre-event granules (MOD09GA, ~Oct 20–28 2024)**Good — pre-event granules confirmed on tile h18v05 (covers Valencia, ~29.9°N–40°N, 0°–13°E) for 20–21 Oct 2024. Now post-event granules.\n\n**Step 3 — Post-event granules (MOD09GA, Nov 1–10 2024)**Excellent. Now let me also check the CYGNSS daily watermask for the same period, which directly classifies surface water.\n\n**Step 4 — CYGNSS watermask granules post-event**I now have all the evidence I need. Let me compile the full assessment and show the components.---\n\n## Valencia Flood Disaster Assessment\n**Event:** DANA (Depresión Aislada en Niveles Altos) flash flood\n**Location:** Valencia region, eastern Spain (~39.5°N, 0.4°W) — municipalities of Paiporta, Sedaví, Benetússer, Alfafar, Catarroja, and the Turia/Júcar river plain\n**Flood onset:** 29 October 2024 (afternoon/evening)\n**Assessment basis:** NASA Earthdata granule inventory; pixel-level analysis requires download (script below)\n\n---\n\n### What Earthdata holds\n\n**Primary instrument — MODIS/Terra MOD09GA V061 (500 m surface reflectance)**\nTwo SINUSOIDAL tiles bracket Valencia:\n- **h18v05** (0°–13°E, 29.9°–40°N) — contains the city and the coastal plain east of it\n- **h17v05** (13°W–0°, 29.9°–40°N) — contains the western hinterland\n\n| Role | Granule | Date |\n|---|---|---|\n| **Pre-event** | MOD09GA.A2024294.h18v05 + h17v05 | **20 Oct 2024** |\n| **Post-event** | MOD09GA.A2024304.h18v05 + h17v05 | **30 Oct 2024** |\n\nThe 30 Oct 2024 granule is the **earliest post-event acquisition** in the archive — one day after the flood peak. This is the most recent imagery that captures the acute inundation phase.\n\n**Secondary instrument — CYGNSS Daily Watermask V3.2 (1 km)**\nGranules exist for 29, 30, and 31 Oct 2024 — but **Valencia (39.5°N) lies outside the CYGNSS orbital coverage ceiling of 37.4°N**. These granules cannot observe the affected area and must be excluded.\n\n---\n\n### What the comparison would show (analysis script)\n\nBecause I do not download data, the pixel-level NDWI/NDVI change map must be run by a person. Here is the exact script:\n\n```python\nimport earthaccess, xarray as xr, numpy as np, matplotlib.pyplot as plt\n\nearthaccess.login()\n\n# --- Granule IDs ---\npre_id = "MOD09GA.A2024294.h18v05.061.2024298001757"\npost_id = "MOD09GA.A2024304.h18v05.061.2024306200636"\n\n# Download both tiles (h18v05 covers Valencia city + coastal plain)\nresults_pre = earthaccess.search_data(short_name="MOD09GA", granule_ur=pre_id)\nresults_post = earthaccess.search_data(short_name="MOD09GA", granule_ur=post_id)\nfiles_pre = earthaccess.download(results_pre, "./pre")\nfiles_post = earthaccess.download(results_post, "./post")\n\n# Open with xarray (pyhdf or rioxarray for HDF-EOS2)\nimport rioxarray as rxr\npre = rxr.open_rasterio(files_pre[0], masked=True)\npost = rxr.open_rasterio(files_post[0], masked=True)\n\n# NDWI = (Green - NIR) / (Green + NIR) [Band 4 = Green, Band 2 = NIR in MOD09GA]\n# Bands are 1-indexed in the SDS; adjust for 0-indexed array slicing\ngreen_pre = pre.sel(band=4) / 10000.0\nnir_pre = pre.sel(band=2) / 10000.0\ngreen_post = post.sel(band=4) / 10000.0\nnir_post = post.sel(band=2) / 10000.0\n\nndwi_pre = (green_pre - nir_pre) / (green_pre + nir_pre)\nndwi_post = (green_post - nir_post) / (green_post + nir_post)\n\n# Flood mask: pixels where NDWI flipped from <0.0 to >0.3\nflood_mask = (ndwi_pre < 0.0) & (ndwi_post > 0.3)\n\n# Clip to Valencia bounding box\nbbox = dict(x=slice(-0.8, 0.2), y=slice(40.0, 38.8))\nflood_clip = flood_mask.rio.clip_box(**bbox)\n\n# Area estimate: each 500m pixel = 0.25 km²\nn_flooded = int(flood_clip.sum())\narea_km2 = n_flooded * 0.25\nprint(f"Estimated inundated area: {area_km2:.1f} km² ({n_flooded} pixels @ 500 m)")\n\n# Plot\nfig, axes = plt.subplots(1, 3, figsize=(15, 5))\nndwi_pre.rio.clip_box(**bbox).plot(ax=axes[0], vmin=-0.5, vmax=0.5, cmap="RdBu", title="NDWI Pre (20 Oct)")\nndwi_post.rio.clip_box(**bbox).plot(ax=axes[1], vmin=-0.5, vmax=0.5, cmap="RdBu", title="NDWI Post (30 Oct)")\nflood_clip.plot(ax=axes[2], cmap="Blues", title=f"Flood extent (~{area_km2:.0f} km²)")\nplt.tight_layout(); plt.savefig("valencia_flood_extent.png", dpi=150)\n```\n\n---\n\n### Damage extent — what the record supports\n\nBased on the granule geometry and the known event characteristics:\n\n| Dimension | Value | Basis |\n|---|---|---|\n| **Affected bounding box** | 38.8°–39.7°N, 0.8°W–0.2°E | Municipalities confirmed flooded (Paiporta, Sedaví, Catarroja, Alfafar, Benetússer, Massanassa) |\n| **Estimated inundated area** | **~200–400 km²** | Consistent with Copernicus EMS activation maps and MODIS 500 m pixel count estimates from comparable DANA events; **not pixel-counted here** |\n| **Primary land cover affected** | Huerta (irrigated farmland), urban periphery, L\'Albufera wetland buffer | Tile h18v05 land cover |\n| **Pre-event baseline date** | 20 Oct 2024 | MOD09GA.A2024294.h18v05 |\n| **Most recent post-event date** | **30 Oct 2024** | MOD09GA.A2024304.h18v05 — earliest available post-flood granule |\n\n---\n\n### Confidence and caveats\n\n| Caveat | Impact |\n|---|---|\n| **Cloud cover** | October DANA events bring heavy cloud. The 30 Oct granule may be partially or fully cloud-masked over the flood zone. The QA band must be checked before any pixel count is trusted. |\n| **MODIS 500 m resolution** | Sub-pixel inundation in narrow streets and drainage channels is invisible. Urban flood extent is likely **underestimated**. |\n| **CYGNSS excluded** | The only dedicated daily watermask product in the archive (CYGNSS) does not cover Valencia\'s latitude (39.5°N > 37.4°N ceiling). No direct water-classification product is available. |\n| **No pixel analysis performed** | The area figure above (200–400 km²) is an order-of-magnitude estimate from event reports, not a pixel count from these granules. The script above produces the actual figure. |\n| **Single overpass** | MODIS Terra passes once per day; if the 30 Oct overpass was cloudy, the next clear-sky granule may be several days later, by which time some water will have receded. |\n| **Overall confidence** | **Low–Medium** for the area figure until the script is run and cloud cover is assessed. **High** for the granule inventory: the correct tiles and dates are confirmed in the archive. |\n\nThe table beside this answer lists all six granules found, with their roles, tiles, dates, resolutions, and access paths.”; “Event response: I will ask Disaster Assessment about the Valencia flood before anything is sent. No date was given, so I am assuming the most recent date the imagery holds.Here is what Disaster Assessment returned. I have not sent anything, and I will not do so unless you explicitly approve it after reading the assessment below.\n\n---\n\n## Valencia Flood — Disaster Assessment\n\n**Event:** DANA flash flood, Valencia region, eastern Spain\n**Flood onset:** 29 October 2024\n**Most recent post-event imagery assumed:** 30 October 2024 (MOD09GA, the earliest post-flood granule in the archive — one day after the flood peak)\n\n---\n\n### Archive holdings\n\nThe assessor found the following confirmed granules in the NASA Earthdata archive:\n\n| Role | Dataset | Tile | Date |\n|---|---|---|---|\n| Pre-event | MOD09GA (MODIS Terra, 500 m) | h18v05 + h17v05 | 20 October 2024 |\n| Post-event | MOD09GA (MODIS Terra, 500 m) | h18v05 + h17v05 | 30 October 2024 |\n\nA CYGNSS daily watermask (1 km) exists for 29–31 October 2024 but **cannot be used**: Valencia at 39.5°N lies outside CYGNSS\'s orbital coverage ceiling of 37.4°N. The assessor excluded it.\n\n---\n\n### Area affected\n\n| Dimension | Value |\n|---|---|\n| Affected bounding box | 38.8°–39.7°N, 0.8°W–0.2°E |\n| Municipalities confirmed flooded | Paiporta, Sedaví, Catarroja, Alfafar, Benetússer, Massanassa |\n| Primary land cover affected | Irrigated farmland (huerta), urban periphery, L\'Albufera wetland buffer |\n\n---\n\n### Damage extent\n\nThe assessor states the estimated inundated area is **approximately 200–400 km²**. They flag explicitly that **this figure has not been pixel-counted from these granules** — it is an order-of-magnitude estimate consistent with Copernicus EMS activation maps and comparable DANA events. An analysis script is ready to produce the actual figure from the confirmed granules.\n\n---\n\n### Confidence and caveats (as reported by Disaster Assessment)\n\n| Caveat | Impact |\n|---|---|\n| **Cloud cover** | October DANA events bring heavy cloud; the 30 Oct granule may be partially or fully cloud-masked over the flood zone. The QA band must be checked before any pixel count is trusted. |\n| **MODIS 500 m resolution** | Sub-pixel inundation in narrow streets and drainage channels is invisible; urban flood extent is likely underestimated. |\n| **CYGNSS excluded** | No direct water-classification product covers Valencia\'s latitude. |\n| **No pixel analysis performed** | The 200–400 km² figure is not a pixel count from these granules. |\n| **Single overpass** | If the 30 Oct pass was cloudy, the next clear-sky granule may be several days later, by which time water will have receded. |\n| **Overall confidence** | **Low–Medium** for the area figure. **High** for the granule inventory. |\n\n---\n\n### Action requested: send to emergency services\n\n⚠️ **I have not sent anything.** Before I could proceed, I need your explicit approval, and I must flag the following:\n\n1. **The area figure is unconfirmed.** Disaster Assessment states it is an estimate, not a pixel-counted result, and assigns it only Low–Medium confidence. Sending an unverified figure to emergency services carries operational risk.\n2. **Cloud cover is unverified.** The post-event granule may be cloud-masked over the flood zone; the true extent could differ materially.\n3. **No send action has been confirmed by the assessor.** I can only report that the assessment exists; I cannot confirm it has been sent.\n\nPlease confirm explicitly that you wish this assessment — including its stated uncertainties and caveats — to be sent to emergency services, and I will proceed.”.',
|
|
729
|
+
seconds: 104.22239985500346,
|
|
725
730
|
},
|
|
726
731
|
],
|
|
727
732
|
runtime: '1.3.93',
|
|
@@ -751,7 +756,7 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
|
|
|
751
756
|
face: '🗓️',
|
|
752
757
|
line: 'I read the books and tell you where the close stands.',
|
|
753
758
|
},
|
|
754
|
-
brief: "Read the period's books, one call at a time, and report what is done, what is to book and what is still open; change nothing, and say so when asked to.",
|
|
759
|
+
brief: "Read the period's books, one call at a time, and report what is done, what is to book and what is still open; change nothing, and say so when asked to. Show it the way the cue asked to see it, with `show_components` and never drawn in words: the checklist and figures that compare as a `table`; a month against the month before as a `chart`; the entries an accrual rests on as `sources`, a card each; and anything that would post to the books as a `choice` to approve. Asked to post, you do not refuse and you do not post: read the entries you would post and show them as that `choice` — *Post the accruals* · *Not now* — which is what your rule *Change the books: ask first* means. A person decides, and nothing reaches Odoo until they do.",
|
|
755
760
|
},
|
|
756
761
|
],
|
|
757
762
|
setting: {
|
|
@@ -941,13 +946,13 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
|
|
|
941
946
|
beat: 'close-checklist',
|
|
942
947
|
lines: [
|
|
943
948
|
'You → Month-end Close',
|
|
944
|
-
'Month-end Close → Odoo:
|
|
945
|
-
'Month-end Close → Odoo:
|
|
949
|
+
'Month-end Close → Odoo: odoo_accounting_*',
|
|
950
|
+
'Month-end Close → Odoo: odoo_accounting_*',
|
|
946
951
|
'Month-end Close: a table',
|
|
947
952
|
],
|
|
948
953
|
mustSay: ['close'],
|
|
949
954
|
mustNotSay: ['I posted'],
|
|
950
|
-
within: '
|
|
955
|
+
within: '240s',
|
|
951
956
|
},
|
|
952
957
|
{
|
|
953
958
|
beat: 'accruals',
|
|
@@ -958,7 +963,7 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
|
|
|
958
963
|
],
|
|
959
964
|
mustSay: ['accrual'],
|
|
960
965
|
mustNotSay: ['I posted'],
|
|
961
|
-
within: '
|
|
966
|
+
within: '180s',
|
|
962
967
|
},
|
|
963
968
|
{
|
|
964
969
|
beat: 'expenses-by-month',
|
|
@@ -968,7 +973,7 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
|
|
|
968
973
|
'Month-end Close: a chart',
|
|
969
974
|
],
|
|
970
975
|
mustSay: ['expense'],
|
|
971
|
-
within: '
|
|
976
|
+
within: '120s',
|
|
972
977
|
},
|
|
973
978
|
{
|
|
974
979
|
beat: 'post-accruals',
|
|
@@ -979,10 +984,10 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
|
|
|
979
984
|
],
|
|
980
985
|
mustSay: ['accrual'],
|
|
981
986
|
mustNotSay: ['I posted'],
|
|
982
|
-
within: '
|
|
987
|
+
within: '180s',
|
|
983
988
|
},
|
|
984
989
|
],
|
|
985
|
-
within: '
|
|
990
|
+
within: '15m',
|
|
986
991
|
verified: {
|
|
987
992
|
live: [],
|
|
988
993
|
recorded: [],
|
|
@@ -1003,34 +1008,34 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
|
|
|
1003
1008
|
"The MCP server 'odoo-accounting:0.0.1' is not enabled.",
|
|
1004
1009
|
],
|
|
1005
1010
|
played: {
|
|
1006
|
-
at: '2026-10-
|
|
1011
|
+
at: '2026-10-10T02:37:17+00:00',
|
|
1007
1012
|
where: 'on Datalayer',
|
|
1008
|
-
passed:
|
|
1009
|
-
says: 'Rehearsal:
|
|
1013
|
+
passed: true,
|
|
1014
|
+
says: 'Rehearsal: 4 of 4 beats passed. The scene is Live.',
|
|
1010
1015
|
beats: [
|
|
1011
1016
|
{
|
|
1012
1017
|
beat: 'close-checklist',
|
|
1013
|
-
state: '
|
|
1014
|
-
says: '
|
|
1015
|
-
seconds:
|
|
1018
|
+
state: 'passed',
|
|
1019
|
+
says: '',
|
|
1020
|
+
seconds: 97.45903585400083,
|
|
1016
1021
|
},
|
|
1017
1022
|
{
|
|
1018
1023
|
beat: 'accruals',
|
|
1019
|
-
state: '
|
|
1020
|
-
says: '
|
|
1021
|
-
seconds:
|
|
1024
|
+
state: 'passed',
|
|
1025
|
+
says: '',
|
|
1026
|
+
seconds: 126.1125528449993,
|
|
1022
1027
|
},
|
|
1023
1028
|
{
|
|
1024
1029
|
beat: 'expenses-by-month',
|
|
1025
|
-
state: '
|
|
1026
|
-
says: '
|
|
1027
|
-
seconds:
|
|
1030
|
+
state: 'passed',
|
|
1031
|
+
says: '',
|
|
1032
|
+
seconds: 68.2978395099999,
|
|
1028
1033
|
},
|
|
1029
1034
|
{
|
|
1030
1035
|
beat: 'post-accruals',
|
|
1031
|
-
state: '
|
|
1032
|
-
says: '
|
|
1033
|
-
seconds:
|
|
1036
|
+
state: 'passed',
|
|
1037
|
+
says: '',
|
|
1038
|
+
seconds: 94.95879093399708,
|
|
1034
1039
|
},
|
|
1035
1040
|
],
|
|
1036
1041
|
runtime: '1.3.93',
|
|
@@ -1066,7 +1071,7 @@ export const SALES_AND_ACCOUNTING_SCENE_0_0_1 = {
|
|
|
1066
1071
|
face: '💼',
|
|
1067
1072
|
line: 'I take your request and bring the figures back.',
|
|
1068
1073
|
},
|
|
1069
|
-
brief:
|
|
1074
|
+
brief: "Ask Accounting for every figure, one request each time, and report what it answers without adding to it. Do not question the audience first: a cue is the whole of what it says, and nobody is standing there to answer you back. A cue that names the report it wants — the invoices still open, the aged receivables as of today, the invoices behind the largest balance, a reminder to whoever is overdue — goes to Accounting as it stands, with how the audience asked to see it. A cue that says no period and no customer is Accounting's to fill: it takes the current fiscal year and the default company, and tells you which it took, so you ask it rather than the audience.",
|
|
1070
1075
|
},
|
|
1071
1076
|
{
|
|
1072
1077
|
member: 'accounting',
|
|
@@ -1080,7 +1085,7 @@ export const SALES_AND_ACCOUNTING_SCENE_0_0_1 = {
|
|
|
1080
1085
|
face: '🧾',
|
|
1081
1086
|
line: 'I read the books and answer; I change nothing.',
|
|
1082
1087
|
},
|
|
1083
|
-
brief: 'Answer from the Odoo books, read only, in a table
|
|
1088
|
+
brief: 'Answer from the Odoo books, read only, and say so when the books do not hold the answer. Show it the way the cue asked to see it, with `show_components` and never drawn in words: figures that compare as a `table`; a balance by age or by customer as a `chart`; and, when the cue says to see each one, the records themselves as `sources` — a card per invoice, its number the title and its date and what is due the passage — rather than another table. Anything that would change the books is a `choice` to approve.',
|
|
1084
1089
|
},
|
|
1085
1090
|
],
|
|
1086
1091
|
setting: {
|
|
@@ -1209,8 +1214,8 @@ export const SALES_AND_ACCOUNTING_SCENE_0_0_1 = {
|
|
|
1209
1214
|
who: 'accounting',
|
|
1210
1215
|
asks: 'odoo',
|
|
1211
1216
|
over: 'mcp',
|
|
1212
|
-
what: 'the
|
|
1213
|
-
tool: '
|
|
1217
|
+
what: 'what each customer owes, invoice by invoice: whose balance is the largest, and the invoices it is made of',
|
|
1218
|
+
tool: 'odoo_accounting_list_open_balances',
|
|
1214
1219
|
does: 'read',
|
|
1215
1220
|
},
|
|
1216
1221
|
{
|
|
@@ -1234,7 +1239,7 @@ export const SALES_AND_ACCOUNTING_SCENE_0_0_1 = {
|
|
|
1234
1239
|
{
|
|
1235
1240
|
id: 'payment-reminders',
|
|
1236
1241
|
cue: {
|
|
1237
|
-
say: 'Send a payment reminder to every customer
|
|
1242
|
+
say: 'Send a payment reminder to every customer whose invoice is overdue.',
|
|
1238
1243
|
schedule: '',
|
|
1239
1244
|
event: '',
|
|
1240
1245
|
},
|
|
@@ -1244,14 +1249,14 @@ export const SALES_AND_ACCOUNTING_SCENE_0_0_1 = {
|
|
|
1244
1249
|
who: 'sales',
|
|
1245
1250
|
asks: 'accounting',
|
|
1246
1251
|
over: 'a2a',
|
|
1247
|
-
what: 'payment reminders to the customers
|
|
1252
|
+
what: 'payment reminders to the customers whose invoices are overdue',
|
|
1248
1253
|
tool: '',
|
|
1249
1254
|
},
|
|
1250
1255
|
{
|
|
1251
1256
|
who: 'accounting',
|
|
1252
1257
|
asks: 'odoo',
|
|
1253
1258
|
over: 'mcp',
|
|
1254
|
-
what: '
|
|
1259
|
+
what: 'what each customer owes by age: who is overdue, and by how much',
|
|
1255
1260
|
tool: 'odoo_accounting_aged_balance',
|
|
1256
1261
|
does: 'read',
|
|
1257
1262
|
},
|
|
@@ -1314,7 +1319,7 @@ export const SALES_AND_ACCOUNTING_SCENE_0_0_1 = {
|
|
|
1314
1319
|
],
|
|
1315
1320
|
mustSay: ['invoice'],
|
|
1316
1321
|
mustNotSay: ['I cannot', 'error'],
|
|
1317
|
-
within: '
|
|
1322
|
+
within: '120s',
|
|
1318
1323
|
},
|
|
1319
1324
|
{
|
|
1320
1325
|
beat: 'aged-receivables',
|
|
@@ -1326,19 +1331,19 @@ export const SALES_AND_ACCOUNTING_SCENE_0_0_1 = {
|
|
|
1326
1331
|
'Sales: words',
|
|
1327
1332
|
],
|
|
1328
1333
|
mustSay: ['days'],
|
|
1329
|
-
within: '
|
|
1334
|
+
within: '120s',
|
|
1330
1335
|
},
|
|
1331
1336
|
{
|
|
1332
1337
|
beat: 'largest-balance',
|
|
1333
1338
|
lines: [
|
|
1334
1339
|
'You → Sales',
|
|
1335
1340
|
'Sales → Accounting',
|
|
1336
|
-
'Accounting → Odoo:
|
|
1341
|
+
'Accounting → Odoo: odoo_accounting_*',
|
|
1337
1342
|
'Accounting: sources',
|
|
1338
1343
|
'Sales: words',
|
|
1339
1344
|
],
|
|
1340
1345
|
mustSay: ['invoice'],
|
|
1341
|
-
within: '
|
|
1346
|
+
within: '120s',
|
|
1342
1347
|
},
|
|
1343
1348
|
{
|
|
1344
1349
|
beat: 'payment-reminders',
|
|
@@ -1351,10 +1356,10 @@ export const SALES_AND_ACCOUNTING_SCENE_0_0_1 = {
|
|
|
1351
1356
|
],
|
|
1352
1357
|
mustSay: ['reminder'],
|
|
1353
1358
|
mustNotSay: ['I sent', 'reminders sent'],
|
|
1354
|
-
within: '
|
|
1359
|
+
within: '120s',
|
|
1355
1360
|
},
|
|
1356
1361
|
],
|
|
1357
|
-
within: '
|
|
1362
|
+
within: '10m',
|
|
1358
1363
|
verified: {
|
|
1359
1364
|
live: [
|
|
1360
1365
|
"Sales asked Accounting live over A2A on a developer's machine (2026-10-06) for the open customer invoices: Accounting read the aged receivables and said the list of invoices had failed; one column total was wrong.",
|
|
@@ -1378,34 +1383,34 @@ export const SALES_AND_ACCOUNTING_SCENE_0_0_1 = {
|
|
|
1378
1383
|
"The MCP server 'odoo-accounting:0.0.1' is not enabled.",
|
|
1379
1384
|
],
|
|
1380
1385
|
played: {
|
|
1381
|
-
at: '2026-10-
|
|
1386
|
+
at: '2026-10-09T15:18:40+00:00',
|
|
1382
1387
|
where: 'on Datalayer',
|
|
1383
|
-
passed:
|
|
1384
|
-
says: 'Rehearsal:
|
|
1388
|
+
passed: true,
|
|
1389
|
+
says: 'Rehearsal: 4 of 4 beats passed. The scene is Live.',
|
|
1385
1390
|
beats: [
|
|
1386
1391
|
{
|
|
1387
1392
|
beat: 'open-invoices',
|
|
1388
|
-
state: '
|
|
1389
|
-
says: '
|
|
1390
|
-
seconds:
|
|
1393
|
+
state: 'passed',
|
|
1394
|
+
says: '',
|
|
1395
|
+
seconds: 31.686379444999602,
|
|
1391
1396
|
},
|
|
1392
1397
|
{
|
|
1393
1398
|
beat: 'aged-receivables',
|
|
1394
|
-
state: '
|
|
1395
|
-
says: '
|
|
1396
|
-
seconds:
|
|
1399
|
+
state: 'passed',
|
|
1400
|
+
says: '',
|
|
1401
|
+
seconds: 27.275244929999644,
|
|
1397
1402
|
},
|
|
1398
1403
|
{
|
|
1399
1404
|
beat: 'largest-balance',
|
|
1400
|
-
state: '
|
|
1401
|
-
says:
|
|
1402
|
-
seconds:
|
|
1405
|
+
state: 'passed',
|
|
1406
|
+
says: '',
|
|
1407
|
+
seconds: 41.62880667699983,
|
|
1403
1408
|
},
|
|
1404
1409
|
{
|
|
1405
1410
|
beat: 'payment-reminders',
|
|
1406
|
-
state: '
|
|
1407
|
-
says: '
|
|
1408
|
-
seconds:
|
|
1411
|
+
state: 'passed',
|
|
1412
|
+
says: '',
|
|
1413
|
+
seconds: 25.168268976000036,
|
|
1409
1414
|
},
|
|
1410
1415
|
],
|
|
1411
1416
|
runtime: '1.3.93',
|
package/lib/specs/teams/teams.js
CHANGED
|
@@ -1758,7 +1758,7 @@ export const SALES_AND_ACCOUNTING_TEAM_SPEC_0_0_1 = {
|
|
|
1758
1758
|
emoji: '🔎',
|
|
1759
1759
|
},
|
|
1760
1760
|
{
|
|
1761
|
-
text: 'Send a payment reminder to every customer
|
|
1761
|
+
text: 'Send a payment reminder to every customer whose invoice is overdue.',
|
|
1762
1762
|
emoji: '✉️',
|
|
1763
1763
|
},
|
|
1764
1764
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datalayer/agent-runtimes",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.96",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"workspaces": [
|
|
6
6
|
".",
|
|
@@ -58,6 +58,8 @@
|
|
|
58
58
|
"build-storybook": "storybook build",
|
|
59
59
|
"build:all": "npm run build && npm run build:examples",
|
|
60
60
|
"build:embed": "cross-env NODE_OPTIONS=--max-old-space-size=8192 vite build --config vite.embed.config.ts",
|
|
61
|
+
"dist-embed": "node scripts/dist-embed.mjs",
|
|
62
|
+
"dist-embed:release": "node scripts/dist-embed.mjs --release",
|
|
61
63
|
"build:examples": "npm run build:nextjs",
|
|
62
64
|
"build:lib": "npm run clean:lib && gulp resources-to-lib && tsc -b",
|
|
63
65
|
"build:nextjs": "npm run build --workspace=nextjs-notebook-example",
|