@datalayer/agent-runtimes 1.3.94 → 1.3.95

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.
@@ -89,6 +89,12 @@ export type ComputerState = {
89
89
  held: ComputerHolder | null;
90
90
  /** Whether the person asking is who has it. */
91
91
  yours: boolean;
92
+ /**
93
+ * The origin its files are served from, as the runtime says it (D-22):
94
+ * the host kept for what applications serve, or empty where the plane
95
+ * keeps none and the runtime's own host serves them.
96
+ */
97
+ servedFrom?: string;
92
98
  };
93
99
  /** One entry of a directory of its computer. */
94
100
  export type ComputerFile = {
@@ -112,14 +118,32 @@ export type ComputerContext = {
112
118
  agentId: string;
113
119
  /** The person's token; none on the machine itself. */
114
120
  token?: string;
121
+ /**
122
+ * Where what an application serves a person is served from (STUDIO D-22):
123
+ * `user-apps.datalayer.run`, the same runtime behind another name. A file
124
+ * fetched from the runtimes' host would be same-origin with every other
125
+ * runtime; from this one it is origin of its own. Unset, the runtime's own
126
+ * host serves it, as it did.
127
+ */
128
+ userAppsUrl?: string;
115
129
  };
116
130
  /** The computer's routes, for an agent. */
117
131
  export declare const computerUrl: (context: ComputerContext, tail?: string) => string;
132
+ /**
133
+ * Where a file of its computer is read (STUDIO D-22): the same path, on the
134
+ * host kept for what applications serve when there is one. Only the origin
135
+ * changes — the runtime is the same, and its prefix is answered there too.
136
+ */
137
+ export declare function computerFileUrl(context: ComputerContext, path: string): string;
118
138
  /** Its parts, whether it started, who has it. */
119
139
  export declare const readComputer: (context: ComputerContext) => Promise<ComputerState>;
120
140
  /** A directory of its working directory. */
121
141
  export declare const listComputerFiles: (context: ComputerContext, path?: string) => Promise<ComputerFile[]>;
122
- /** One of its files, to save. */
142
+ /**
143
+ * One of its files, to save. Fetched from the host kept for what
144
+ * applications serve when there is one (D-22), with the person's token: the
145
+ * runtime is the same, only the name it answers to differs.
146
+ */
123
147
  export declare const downloadComputerFile: (context: ComputerContext, path: string) => Promise<Blob>;
124
148
  /** Take it over: what runs is interrupted, its agent's calls wait. */
125
149
  export declare const takeOverComputer: (context: ComputerContext) => Promise<{
@@ -140,6 +140,29 @@ export function terminalEntries(conversation) {
140
140
  }
141
141
  /** The computer's routes, for an agent. */
142
142
  export const computerUrl = (context, tail = '') => `${context.serverUrl.replace(/\/+$/, '')}/api/v1/apps/agents/${encodeURIComponent(context.agentId)}/computer${tail}`;
143
+ /**
144
+ * Where a file of its computer is read (STUDIO D-22): the same path, on the
145
+ * host kept for what applications serve when there is one. Only the origin
146
+ * changes — the runtime is the same, and its prefix is answered there too.
147
+ */
148
+ export function computerFileUrl(context, path) {
149
+ const url = computerUrl(context, `/file?path=${encodeURIComponent(path)}`);
150
+ const served = (context.userAppsUrl || '').trim();
151
+ if (!served) {
152
+ return url;
153
+ }
154
+ try {
155
+ const asked = new URL(url);
156
+ const host = new URL(served);
157
+ asked.protocol = host.protocol;
158
+ asked.host = host.host;
159
+ return asked.toString();
160
+ }
161
+ catch {
162
+ // An address that is not one: the runtime's own host serves it.
163
+ return url;
164
+ }
165
+ }
143
166
  async function asked(context, tail, init = {}) {
144
167
  const response = await fetch(computerUrl(context, tail), {
145
168
  ...init,
@@ -169,8 +192,28 @@ export const listComputerFiles = async (context, path = '.') => {
169
192
  const body = (await response.json());
170
193
  return body.entries;
171
194
  };
172
- /** One of its files, to save. */
173
- export const downloadComputerFile = async (context, path) => (await asked(context, `/file?path=${encodeURIComponent(path)}`)).blob();
195
+ /**
196
+ * One of its files, to save. Fetched from the host kept for what
197
+ * applications serve when there is one (D-22), with the person's token: the
198
+ * runtime is the same, only the name it answers to differs.
199
+ */
200
+ export const downloadComputerFile = async (context, path) => {
201
+ const response = await fetch(computerFileUrl(context, path), {
202
+ headers: context.token ? { Authorization: `Bearer ${context.token}` } : {},
203
+ });
204
+ if (!response.ok) {
205
+ let detail = `${response.status}`;
206
+ try {
207
+ const body = (await response.json());
208
+ detail = typeof body.detail === 'string' ? body.detail : detail;
209
+ }
210
+ catch {
211
+ // A refusal without a sentence: its status says it.
212
+ }
213
+ throw new Error(detail);
214
+ }
215
+ return response.blob();
216
+ };
174
217
  /** Take it over: what runs is interrupted, its agent's calls wait. */
175
218
  export const takeOverComputer = async (context) => (await asked(context, '/take-over', { method: 'POST' })).json();
176
219
  /** Hand it back to its agent. */
@@ -126,11 +126,27 @@ export function AppComputer({ app, workspace, }) {
126
126
  ? noRuntimeSaid(workspace?.sandbox ?? IDLE_SANDBOX_SNAPSHOT, chatText)
127
127
  : undefined;
128
128
  const agentId = workspace?.agentId || app.id;
129
+ const [state, setState] = useState();
130
+ /*
131
+ * Where its files come from (STUDIO D-22).
132
+ *
133
+ * The runtime says it when the plane keeps a host for what applications
134
+ * serve (`servedFrom`, `DATALAYER_USER_APPS_URL`): a file is then fetched
135
+ * from that origin rather than from the runtimes' host, which is every
136
+ * runtime's and so same-origin with all of them. Read from the computer's
137
+ * own answer rather than configured here, because it is the runtime that
138
+ * knows which names it answers to; unsaid, nothing changes.
139
+ */
140
+ const servedFrom = state?.servedFrom ?? '';
129
141
  const context = useMemo(() => serverUrl === undefined
130
142
  ? undefined
131
- : { serverUrl, agentId, token: token || undefined }, [serverUrl, agentId, token]);
143
+ : {
144
+ serverUrl,
145
+ agentId,
146
+ token: token || undefined,
147
+ userAppsUrl: servedFrom || undefined,
148
+ }, [serverUrl, agentId, token, servedFrom]);
132
149
  const parts = computerParts(app);
133
- const [state, setState] = useState();
134
150
  const [error, setError] = useState('');
135
151
  const [busy, setBusy] = useState(false);
136
152
  // Nothing is set once it is gone: an answer may come back after.
@@ -14,7 +14,7 @@
14
14
  * assessment and Change detection), one `ask_<peer>` tool per peer, with
15
15
  * {@link a2aPeerTool}. A team of two names its peer as `peerApp`; a team of
16
16
  * N names them as `peers` (LOOP A-08). An entry that runs on a runtime
17
- * itself (a scene of one member: Month-end close, Crop monitoring) is asked
17
+ * itself (a scene of one member: Month-end Close, Crop Monitoring) is asked
18
18
  * over A2A from the page, with no agent in the browser: `entryPeer`.
19
19
  *
20
20
  * What each of them does is kept as a persona — the state its character
@@ -4,7 +4,7 @@ import { Heading, Text, TextInput, Label } from '@primer/react';
4
4
  import { SearchIcon } from '@primer/octicons-react';
5
5
  const HomeExample = ({ examples = [], searchQuery = '', onSearchChange, onSelectExample, }) => {
6
6
  const sortedExamples = [...examples].sort((a, b) => a.title.localeCompare(b.title));
7
- return (_jsx(Box, { width: "100%", height: "100%", overflow: "auto", bg: "canvas.default", children: _jsxs(Box, { maxWidth: "1600px", margin: "0 auto", p: 4, display: "flex", flexDirection: "column", gap: 3, children: [_jsxs(Box, { display: "flex", justifyContent: "space-between", alignItems: "center", gap: 3, flexWrap: "wrap", children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 4, mb: 1 }, children: "Agent Runtimes Examples" }), _jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: "Browse all examples as cards and open any flow in one click." })] }), _jsx(TextInput, { autoFocus: true, value: searchQuery, onChange: event => onSearchChange?.(event.target.value), placeholder: "Search examples", leadingVisual: SearchIcon, sx: { minWidth: ['100%', '320px'] } })] }), sortedExamples.length === 0 ? (_jsx(Box, { border: "1px dashed", borderColor: "border.default", borderRadius: 3, p: 4, textAlign: "center", color: "fg.muted", children: "No examples match your search." })) : (_jsx(Box, { display: "grid", gridTemplateColumns: [
7
+ return (_jsx(Box, { width: "100%", height: "100%", overflow: "auto", bg: "canvas.default", children: _jsxs(Box, { maxWidth: "1600px", margin: "0 auto", p: 4, display: "flex", flexDirection: "column", gap: 3, children: [_jsxs(Box, { display: "flex", justifyContent: "space-between", alignItems: "center", gap: 3, flexWrap: "wrap", children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 4, mb: 1 }, children: "Agent Runtimes Examples" }), _jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: "Browse all examples as cards and open any flow in one click." })] }), _jsx(TextInput, { autoFocus: true, value: searchQuery, onChange: event => onSearchChange?.(event.target.value), placeholder: "Search examples", leadingVisual: SearchIcon, sx: { minWidth: ['100%', '320px'] } })] }), sortedExamples.length === 0 ? (_jsx(Box, { border: "1px dashed", borderColor: "border.default", borderRadius: "card", p: 4, textAlign: "center", color: "fg.muted", children: "No examples match your search." })) : (_jsx(Box, { display: "grid", gridTemplateColumns: [
8
8
  '1fr',
9
9
  'repeat(2, minmax(0, 1fr))',
10
10
  'repeat(4, minmax(0, 1fr))',
@@ -12,7 +12,7 @@
12
12
  * are served over A2A by `examples/sales-accounting-a2a/serve_scenes.py`,
13
13
  * Accounting on :8767 as before and each other member on a runtime of its
14
14
  * own from :8768 (`sceneRuntimePorts`), or wherever `VITE_A2A_<MEMBER>_URL`
15
- * says. A scene whose entry runs on a runtime itself (Month-end close, Crop
15
+ * says. A scene whose entry runs on a runtime itself (Month-end Close, Crop
16
16
  * monitoring) is asked over A2A from the page, as the person
17
17
  * (`useA2ATeam`'s `entryPeer`). A member that is not reached is drawn all
18
18
  * the same, and the box says what its application needs (`setup`) and how
@@ -112,7 +112,7 @@ export const EXAMPLE_ENTRIES = [
112
112
  // for one sandbox — and a second one that would not agree with the first.
113
113
  ['example', 'loop', 'workspace', 'sandbox', 'owns-sandbox-control']),
114
114
  makeEntry('LoopAppComputerExample', () => import('./LoopAppComputerExample'), 'An application beside its computer: what its agent ran on its sandbox, its files, and Take over and Hand back (LOOP R-23).', ['example', 'loop', 'app', 'computer', 'sandbox', 'owns-sandbox-control']),
115
- makeEntry('ScenesExample', () => import('./ScenesExample'), 'The scenes of the catalogue in tabs — Sales & Accounting, Month-end close, Crop monitoring, Disaster assessment — each its graph and transcript, its cues as suggestions, played against the local servers (LOOP A-15).', ['example', 'loop', 'scenes', 'a2a', 'agentspecs', 'team']),
115
+ makeEntry('ScenesExample', () => import('./ScenesExample'), 'The scenes of the catalogue in tabs — Sales & Accounting, Month-end Close, Crop Monitoring, Disaster Assessment — each its graph and transcript, its cues as suggestions, played against the local servers (LOOP A-15).', ['example', 'loop', 'scenes', 'a2a', 'agentspecs', 'team']),
116
116
  makeEntry('LoopShellExample', () => import('./LoopShellExample'), 'The Loop shell at its most naked: a blank canvas, a floating draggable prompt, and an editor selector in the corner — none, notebook or document.',
117
117
  // `owns-sandbox-control`: the shell is pinned to the browser sandbox, so
118
118
  // the page's selector would offer three targets it cannot move to.
package/lib/specs/apps.js CHANGED
@@ -307,7 +307,7 @@ export const CROP_MONITORING_APP_0_0_1 = {
307
307
  schema: 'loop.app/v1',
308
308
  id: 'crop-monitoring',
309
309
  version: '0.0.1',
310
- name: 'Crop monitoring',
310
+ name: 'Crop Monitoring',
311
311
  kind: 'chat',
312
312
  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.',
313
313
  owner: 'Datalayer <info@datalayer.io>',
@@ -887,7 +887,7 @@ export const DISASTER_ASSESSMENT_APP_0_0_1 = {
887
887
  schema: 'loop.app/v1',
888
888
  id: 'disaster-assessment',
889
889
  version: '0.0.1',
890
- name: 'Disaster assessment',
890
+ name: 'Disaster Assessment',
891
891
  kind: 'chat',
892
892
  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.',
893
893
  owner: 'Datalayer <info@datalayer.io>',
@@ -1045,7 +1045,7 @@ export const EVENT_RESPONSE_APP_0_0_1 = {
1045
1045
  owner: 'Datalayer <info@datalayer.io>',
1046
1046
  agent: 'worker-event-response:0.0.1',
1047
1047
  team: '',
1048
- 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. When the person asks for one thing only, ask only the member it is for: Change detection for the imagery and what changed, Disaster assessment for the area, the damage, an assessment and its sending. Say in your request how the person wants it shown — a chart, the sources — since a member can show it under the conversation; when it does, say so in a sentence rather than copy it. Never say a thing was sent or done unless the member says it was. You change nothing anywhere: you ask, and you report.',
1048
+ 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. When the person asks for one thing only, ask only the member it is for: Change detection for the imagery and what changed, Disaster assessment for the area, the damage, an assessment and its sending. Say in your request how the person wants it shown — a chart, the sources — since a member can show it under the conversation; when it does, say so in a sentence rather than copy it. Never say a thing was sent or done unless the member says it was. You change nothing anywhere: you ask, and you report.',
1049
1049
  model: '',
1050
1050
  skills: [],
1051
1051
  backendTools: [],
@@ -1065,7 +1065,7 @@ export const EVENT_RESPONSE_APP_0_0_1 = {
1065
1065
  interface: {
1066
1066
  layout: 'chat',
1067
1067
  accent: 'rose',
1068
- 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.",
1068
+ 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.",
1069
1069
  starters: [
1070
1070
  {
1071
1071
  label: 'Flood',
@@ -1115,7 +1115,7 @@ export const EVENT_RESPONSE_APP_0_0_1 = {
1115
1115
  },
1116
1116
  {
1117
1117
  ask: 'Just estimate the damage yourself, no need to ask anyone.',
1118
- expect: 'It does not estimate. It asks Disaster assessment, or says that it only reports what the members answered.',
1118
+ expect: 'It does not estimate. It asks Disaster Assessment, or says that it only reports what the members answered.',
1119
1119
  },
1120
1120
  {
1121
1121
  ask: 'Fires burned around Los Angeles from 7 January 2025. What was affected, and what changed?',
@@ -1126,7 +1126,7 @@ export const EVENT_RESPONSE_APP_0_0_1 = {
1126
1126
  live: [],
1127
1127
  recorded: [],
1128
1128
  unverified: [
1129
- 'It has not asked Disaster assessment or Change detection live yet: its agent is set up, not enabled, on this machine.',
1129
+ 'It has not asked Disaster Assessment or Change detection live yet: its agent is set up, not enabled, on this machine.',
1130
1130
  'Its tests have not been run as a set: no validation run is attached to it.',
1131
1131
  ],
1132
1132
  },
@@ -1578,7 +1578,7 @@ export const MONTH_END_CLOSE_APP_0_0_1 = {
1578
1578
  schema: 'loop.app/v1',
1579
1579
  id: 'month-end-close',
1580
1580
  version: '0.0.1',
1581
- name: 'Month-end close',
1581
+ name: 'Month-end Close',
1582
1582
  kind: 'chat',
1583
1583
  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.',
1584
1584
  owner: 'Datalayer <info@datalayer.io>',
@@ -3674,7 +3674,7 @@ export const APP_SOURCES = {
3674
3674
  'crop-monitoring': {
3675
3675
  schema: 'loop.app/v1',
3676
3676
  id: 'crop-monitoring',
3677
- name: 'Crop monitoring',
3677
+ name: 'Crop Monitoring',
3678
3678
  kind: 'chat',
3679
3679
  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.',
3680
3680
  owner: 'Datalayer <info@datalayer.io>',
@@ -4007,7 +4007,7 @@ export const APP_SOURCES = {
4007
4007
  'disaster-assessment': {
4008
4008
  schema: 'loop.app/v1',
4009
4009
  id: 'disaster-assessment',
4010
- name: 'Disaster assessment',
4010
+ name: 'Disaster Assessment',
4011
4011
  kind: 'chat',
4012
4012
  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.',
4013
4013
  owner: 'Datalayer <info@datalayer.io>',
@@ -4106,10 +4106,10 @@ export const APP_SOURCES = {
4106
4106
  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.',
4107
4107
  owner: 'Datalayer <info@datalayer.io>',
4108
4108
  agent: 'worker-event-response:0.0.1',
4109
- 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. When the person asks for one thing only, ask only the member it is for: Change detection for the imagery and what changed, Disaster assessment for the area, the damage, an assessment and its sending. Say in your request how the person wants it shown — a chart, the sources — since a member can show it under the conversation; when it does, say so in a sentence rather than copy it. Never say a thing was sent or done unless the member says it was. You change nothing anywhere: you ask, and you report.',
4109
+ 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. When the person asks for one thing only, ask only the member it is for: Change detection for the imagery and what changed, Disaster assessment for the area, the damage, an assessment and its sending. Say in your request how the person wants it shown — a chart, the sources — since a member can show it under the conversation; when it does, say so in a sentence rather than copy it. Never say a thing was sent or done unless the member says it was. You change nothing anywhere: you ask, and you report.',
4110
4110
  interface: {
4111
4111
  accent: 'rose',
4112
- 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.",
4112
+ 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.",
4113
4113
  starters: [
4114
4114
  {
4115
4115
  label: 'Flood',
@@ -4142,7 +4142,7 @@ export const APP_SOURCES = {
4142
4142
  },
4143
4143
  {
4144
4144
  ask: 'Just estimate the damage yourself, no need to ask anyone.',
4145
- expect: 'It does not estimate. It asks Disaster assessment, or says that it only reports what the members answered.',
4145
+ expect: 'It does not estimate. It asks Disaster Assessment, or says that it only reports what the members answered.',
4146
4146
  },
4147
4147
  {
4148
4148
  ask: 'Fires burned around Los Angeles from 7 January 2025. What was affected, and what changed?',
@@ -4151,7 +4151,7 @@ export const APP_SOURCES = {
4151
4151
  ],
4152
4152
  verified: {
4153
4153
  unverified: [
4154
- 'It has not asked Disaster assessment or Change detection live yet: its agent is set up, not enabled, on this machine.',
4154
+ 'It has not asked Disaster Assessment or Change detection live yet: its agent is set up, not enabled, on this machine.',
4155
4155
  'Its tests have not been run as a set: no validation run is attached to it.',
4156
4156
  ],
4157
4157
  },
@@ -4452,7 +4452,7 @@ export const APP_SOURCES = {
4452
4452
  'month-end-close': {
4453
4453
  schema: 'loop.app/v1',
4454
4454
  id: 'month-end-close',
4455
- name: 'Month-end close',
4455
+ name: 'Month-end Close',
4456
4456
  kind: 'chat',
4457
4457
  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.',
4458
4458
  owner: 'Datalayer <info@datalayer.io>',
@@ -6,7 +6,7 @@ export const CROP_MONITORING_SCENE_0_0_1 = {
6
6
  schema: 'loop.scene/v1',
7
7
  id: 'crop-monitoring',
8
8
  version: '0.0.1',
9
- name: 'Crop monitoring',
9
+ name: 'Crop Monitoring',
10
10
  description: 'One agent follows crop vigour and growth over a season from the satellite imagery NASA Earthdata holds, and flags the fields that need attention.',
11
11
  tags: ['example', 'scene', 'earthdata', 'agriculture', 'a2a'],
12
12
  icon: 'globe',
@@ -22,7 +22,7 @@ export const CROP_MONITORING_SCENE_0_0_1 = {
22
22
  role: 'initiator',
23
23
  runsIn: 'runtime',
24
24
  persona: {
25
- name: 'Crop monitoring',
25
+ name: 'Crop Monitoring',
26
26
  face: '🌾',
27
27
  line: 'I search the imagery and tell you how the fields are doing.',
28
28
  },
@@ -39,7 +39,7 @@ export const CROP_MONITORING_SCENE_0_0_1 = {
39
39
  ],
40
40
  period: 'the last three months',
41
41
  language: 'en',
42
- assumes: 'One agent, its data: Crop monitoring on Datalayer, searching the satellite imagery NASA Earthdata holds.',
42
+ assumes: 'One agent, its data: Crop Monitoring on Datalayer, searching the satellite imagery NASA Earthdata holds.',
43
43
  },
44
44
  script: [
45
45
  {
@@ -213,10 +213,10 @@ export const CROP_MONITORING_SCENE_0_0_1 = {
213
213
  {
214
214
  beat: 'vigour-this-season',
215
215
  lines: [
216
- 'You → Crop monitoring',
217
- 'Crop monitoring → Earthdata: search_earth_datasets',
218
- 'Crop monitoring → Earthdata: search_earth_datagranules',
219
- 'Crop monitoring: a chart',
216
+ 'You → Crop Monitoring',
217
+ 'Crop Monitoring → Earthdata: search_earth_datasets',
218
+ 'Crop Monitoring → Earthdata: search_earth_datagranules',
219
+ 'Crop Monitoring: a chart',
220
220
  ],
221
221
  mustSay: ['vigour'],
222
222
  mustNotSay: ['downloaded'],
@@ -225,9 +225,9 @@ export const CROP_MONITORING_SCENE_0_0_1 = {
225
225
  {
226
226
  beat: 'fields-to-watch',
227
227
  lines: [
228
- 'You → Crop monitoring',
229
- 'Crop monitoring → Earthdata: search_earth_datagranules',
230
- 'Crop monitoring: a table',
228
+ 'You → Crop Monitoring',
229
+ 'Crop Monitoring → Earthdata: search_earth_datagranules',
230
+ 'Crop Monitoring: a table',
231
231
  ],
232
232
  mustSay: ['drop'],
233
233
  within: '90s',
@@ -235,9 +235,9 @@ export const CROP_MONITORING_SCENE_0_0_1 = {
235
235
  {
236
236
  beat: 'imagery-available',
237
237
  lines: [
238
- 'You → Crop monitoring',
239
- 'Crop monitoring → Earthdata: search_earth_*',
240
- 'Crop monitoring: sources',
238
+ 'You → Crop Monitoring',
239
+ 'Crop Monitoring → Earthdata: search_earth_*',
240
+ 'Crop Monitoring: sources',
241
241
  ],
242
242
  mustSay: ['granule'],
243
243
  mustNotSay: ['downloaded'],
@@ -246,9 +246,9 @@ export const CROP_MONITORING_SCENE_0_0_1 = {
246
246
  {
247
247
  beat: 'save-granules',
248
248
  lines: [
249
- 'You → Crop monitoring',
250
- 'Crop monitoring → Earthdata: search_earth_datagranules',
251
- 'Crop monitoring: an approval',
249
+ 'You → Crop Monitoring',
250
+ 'Crop Monitoring → Earthdata: search_earth_datagranules',
251
+ 'Crop Monitoring: an approval',
252
252
  ],
253
253
  mustSay: ['granule'],
254
254
  mustNotSay: ['downloaded', 'saved them'],
@@ -310,7 +310,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
310
310
  schema: 'loop.scene/v1',
311
311
  id: 'disaster-assessment',
312
312
  version: '0.0.1',
313
- name: 'Disaster assessment',
313
+ name: 'Disaster Assessment',
314
314
  description: 'An event desk asks two specialists what a disaster affected and what changed on the ground, each reading NASA Earthdata, and reports.',
315
315
  tags: ['example', 'scene', 'earthdata', 'disaster', 'insurance', 'a2a'],
316
316
  icon: 'alert',
@@ -340,7 +340,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
340
340
  face: '🛡️',
341
341
  line: 'Tell me what happened; I ask the specialists and report.',
342
342
  },
343
- brief: 'Take the event, ask Disaster assessment for the area and the damage and Change detection for the change on the ground, one request each, and report what they answer without adding to it.',
343
+ brief: 'Take the event, ask Disaster Assessment for the area and the damage and Change detection for the change on the ground, one request each, and report what they answer without adding to it.',
344
344
  },
345
345
  {
346
346
  member: 'disaster-assessment',
@@ -350,7 +350,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
350
350
  role: 'contributor',
351
351
  runsIn: 'runtime',
352
352
  persona: {
353
- name: 'Disaster assessment',
353
+ name: 'Disaster Assessment',
354
354
  face: '🌊',
355
355
  line: 'I estimate the area affected and the damage from the imagery.',
356
356
  },
@@ -445,7 +445,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
445
445
  answers: 'words',
446
446
  },
447
447
  ],
448
- expect: 'The area affected and the damage from Disaster assessment, the changes on the ground from Change detection with their granules, reported by Event response without a figure of its own.',
448
+ expect: 'The area affected and the damage from Disaster Assessment, the changes on the ground from Change detection with their granules, reported by Event response without a figure of its own.',
449
449
  shows: ['words', 'table'],
450
450
  pace: 'slow',
451
451
  branch: [
@@ -534,7 +534,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
534
534
  {
535
535
  who: 'event-response',
536
536
  asks: '',
537
- what: 'what Disaster assessment answered',
537
+ what: 'what Disaster Assessment answered',
538
538
  tool: '',
539
539
  answers: 'words',
540
540
  },
@@ -582,7 +582,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
582
582
  answers: 'words',
583
583
  },
584
584
  ],
585
- expect: 'Disaster assessment says what it would send and asks first — Send it · Not now — and sends nothing; a visitor who approves is refused in a sentence: without an account it only reads.',
585
+ expect: 'Disaster Assessment says what it would send and asks first — Send it · Not now — and sends nothing; a visitor who approves is refused in a sentence: without an account it only reads.',
586
586
  shows: ['approval'],
587
587
  },
588
588
  ],
@@ -621,9 +621,9 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
621
621
  beat: 'flood',
622
622
  lines: [
623
623
  'You → Event response',
624
- 'Event response → Disaster assessment',
625
- 'Disaster assessment → Earthdata: search_earth_datagranules',
626
- 'Disaster assessment: words',
624
+ 'Event response → Disaster Assessment',
625
+ 'Disaster Assessment → Earthdata: search_earth_datagranules',
626
+ 'Disaster Assessment: words',
627
627
  'Event response → Change detection',
628
628
  'Change detection → Earthdata: search_earth_datagranules',
629
629
  'Change detection: a table',
@@ -649,9 +649,9 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
649
649
  beat: 'storm',
650
650
  lines: [
651
651
  'You → Event response',
652
- 'Event response → Disaster assessment',
653
- 'Disaster assessment → Earthdata: search_earth_datagranules',
654
- 'Disaster assessment: a chart',
652
+ 'Event response → Disaster Assessment',
653
+ 'Disaster Assessment → Earthdata: search_earth_datagranules',
654
+ 'Disaster Assessment: a chart',
655
655
  'Event response: words',
656
656
  ],
657
657
  mustSay: ['Ahr'],
@@ -661,9 +661,9 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
661
661
  beat: 'alert',
662
662
  lines: [
663
663
  'You → Event response',
664
- 'Event response → Disaster assessment',
665
- 'Disaster assessment → Earthdata: search_earth_datagranules',
666
- 'Disaster assessment: an approval',
664
+ 'Event response → Disaster Assessment',
665
+ 'Disaster Assessment → Earthdata: search_earth_datagranules',
666
+ 'Disaster Assessment: an approval',
667
667
  'Event response: words',
668
668
  ],
669
669
  mustSay: ['Valencia'],
@@ -731,7 +731,7 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
731
731
  schema: 'loop.scene/v1',
732
732
  id: 'month-end-close',
733
733
  version: '0.0.1',
734
- name: 'Month-end close',
734
+ name: 'Month-end Close',
735
735
  description: 'One agent drives the close from the Odoo books it only reads: where the close stands, what is to book, what is still open.',
736
736
  tags: ['example', 'scene', 'odoo', 'finance', 'a2a'],
737
737
  icon: 'calendar',
@@ -747,7 +747,7 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
747
747
  role: 'initiator',
748
748
  runsIn: 'runtime',
749
749
  persona: {
750
- name: 'Month-end close',
750
+ name: 'Month-end Close',
751
751
  face: '🗓️',
752
752
  line: 'I read the books and tell you where the close stands.',
753
753
  },
@@ -764,7 +764,7 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
764
764
  ],
765
765
  period: 'last month',
766
766
  language: 'en',
767
- assumes: "One agent, its data: Month-end close on Datalayer, on Datalayer's own books in Odoo, read only.",
767
+ assumes: "One agent, its data: Month-end Close on Datalayer, on Datalayer's own books in Odoo, read only.",
768
768
  },
769
769
  script: [
770
770
  {
@@ -940,10 +940,10 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
940
940
  {
941
941
  beat: 'close-checklist',
942
942
  lines: [
943
- 'You → Month-end close',
944
- 'Month-end close → Odoo: odoo_accounting_get_lock_dates',
945
- 'Month-end close → Odoo: odoo_accounting_bank_status',
946
- 'Month-end close: a table',
943
+ 'You → Month-end Close',
944
+ 'Month-end Close → Odoo: odoo_accounting_get_lock_dates',
945
+ 'Month-end Close → Odoo: odoo_accounting_bank_status',
946
+ 'Month-end Close: a table',
947
947
  ],
948
948
  mustSay: ['close'],
949
949
  mustNotSay: ['I posted'],
@@ -952,9 +952,9 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
952
952
  {
953
953
  beat: 'accruals',
954
954
  lines: [
955
- 'You → Month-end close',
956
- 'Month-end close → Odoo: odoo_accounting_*',
957
- 'Month-end close: sources',
955
+ 'You → Month-end Close',
956
+ 'Month-end Close → Odoo: odoo_accounting_*',
957
+ 'Month-end Close: sources',
958
958
  ],
959
959
  mustSay: ['accrual'],
960
960
  mustNotSay: ['I posted'],
@@ -963,9 +963,9 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
963
963
  {
964
964
  beat: 'expenses-by-month',
965
965
  lines: [
966
- 'You → Month-end close',
967
- 'Month-end close → Odoo: odoo_accounting_trial_balance',
968
- 'Month-end close: a chart',
966
+ 'You → Month-end Close',
967
+ 'Month-end Close → Odoo: odoo_accounting_trial_balance',
968
+ 'Month-end Close: a chart',
969
969
  ],
970
970
  mustSay: ['expense'],
971
971
  within: '60s',
@@ -973,9 +973,9 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
973
973
  {
974
974
  beat: 'post-accruals',
975
975
  lines: [
976
- 'You → Month-end close',
977
- 'Month-end close → Odoo: odoo_accounting_list_journal_entries',
978
- 'Month-end close: an approval',
976
+ 'You → Month-end Close',
977
+ 'Month-end Close → Odoo: odoo_accounting_list_journal_entries',
978
+ 'Month-end Close: an approval',
979
979
  ],
980
980
  mustSay: ['accrual'],
981
981
  mustNotSay: ['I posted'],