@datalayer/agent-runtimes 1.3.56 → 1.3.58
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/lib/chat/marks/SpecMark.d.ts +2 -0
- package/lib/chat/marks/SpecMark.js +3 -1
- package/lib/loop/apps/appspec.js +17 -2
- package/lib/specs/actions.js +2 -0
- package/lib/specs/apps.d.ts +1 -0
- package/lib/specs/apps.js +417 -4
- package/lib/specs/appspecSchema.js +37 -1
- package/lib/stories/loop/LoopReference.stories.d.ts +2 -0
- package/lib/stories/loop/LoopReference.stories.js +3 -1
- package/lib/stories/loop/ReferenceScreens.d.ts +4 -2
- package/lib/stories/loop/ReferenceScreens.js +27 -3
- package/lib/types/agentspecs.d.ts +11 -0
- package/package.json +1 -1
|
@@ -15,6 +15,8 @@ import { type IconPackage, type IconRef } from './iconRef';
|
|
|
15
15
|
export type MarkIcon = React.ComponentType<{
|
|
16
16
|
size?: number;
|
|
17
17
|
'aria-hidden'?: boolean | 'true' | 'false';
|
|
18
|
+
/** The Datalayer icons' own colours: a brand drawn as itself. */
|
|
19
|
+
colored?: boolean;
|
|
18
20
|
}>;
|
|
19
21
|
type IconModule = Record<string, unknown>;
|
|
20
22
|
/** Import a package of icons, once. */
|
|
@@ -71,7 +71,9 @@ export function useMarkIcon(icon) {
|
|
|
71
71
|
export function SpecMark({ icon, emoji, size = 16 }) {
|
|
72
72
|
const Icon = useMarkIcon(icon);
|
|
73
73
|
if (icon) {
|
|
74
|
-
return Icon ? (_jsx("span", { "data-mark": icon, style: { display: 'inline-flex', flexShrink: 0, lineHeight: 0 }, children: _jsx(Icon, { size: size, "aria-hidden": "true"
|
|
74
|
+
return Icon ? (_jsx("span", { "data-mark": icon, style: { display: 'inline-flex', flexShrink: 0, lineHeight: 0 }, children: _jsx(Icon, { size: size, "aria-hidden": "true", ...(icon.startsWith('@datalayer/icons-react:')
|
|
75
|
+
? { colored: true }
|
|
76
|
+
: {}) }) })) : (_jsx("span", { "data-mark": icon, "aria-hidden": "true", style: { display: 'inline-block', width: size, height: size } }));
|
|
75
77
|
}
|
|
76
78
|
if (emoji) {
|
|
77
79
|
return (_jsx("span", { "data-mark": "emoji", "aria-hidden": "true", style: {
|
package/lib/loop/apps/appspec.js
CHANGED
|
@@ -106,7 +106,12 @@ export function emptyAppspec(kind = 'chat') {
|
|
|
106
106
|
settings: [],
|
|
107
107
|
components: [],
|
|
108
108
|
},
|
|
109
|
-
tests: {
|
|
109
|
+
tests: {
|
|
110
|
+
readyAt: DEFAULT_READY_AT,
|
|
111
|
+
evalset: '',
|
|
112
|
+
cases: [],
|
|
113
|
+
verified: { live: [], recorded: [], unverified: [] },
|
|
114
|
+
},
|
|
110
115
|
record: {
|
|
111
116
|
keepFor: DEFAULT_KEEP_FOR,
|
|
112
117
|
retentionDays: retentionDays(DEFAULT_KEEP_FOR),
|
|
@@ -315,6 +320,7 @@ export function parseAppspec(document) {
|
|
|
315
320
|
const permissions = isData(data.permissions) ? data.permissions : {};
|
|
316
321
|
const computer = isData(permissions.computer) ? permissions.computer : {};
|
|
317
322
|
const tests = isData(data.tests) ? data.tests : {};
|
|
323
|
+
const verified = isData(tests.verified) ? tests.verified : {};
|
|
318
324
|
const record = isData(data.record) ? data.record : {};
|
|
319
325
|
const checks = isData(data.checks) ? data.checks : {};
|
|
320
326
|
const keepFor = text(record.keep_for, DEFAULT_KEEP_FOR);
|
|
@@ -359,6 +365,11 @@ export function parseAppspec(document) {
|
|
|
359
365
|
ask: text(testCase.ask),
|
|
360
366
|
expect: text(testCase.expect),
|
|
361
367
|
})),
|
|
368
|
+
verified: {
|
|
369
|
+
live: texts(verified.live),
|
|
370
|
+
recorded: texts(verified.recorded),
|
|
371
|
+
unverified: texts(verified.unverified),
|
|
372
|
+
},
|
|
362
373
|
},
|
|
363
374
|
record: {
|
|
364
375
|
keepFor,
|
|
@@ -559,7 +570,11 @@ export function dumpAppspec(app) {
|
|
|
559
570
|
.list('cases', app.tests.cases.map(testCase => ({
|
|
560
571
|
ask: testCase.ask,
|
|
561
572
|
expect: testCase.expect,
|
|
562
|
-
})))
|
|
573
|
+
})))
|
|
574
|
+
.part('verified', new Writer()
|
|
575
|
+
.list('live', app.tests.verified.live)
|
|
576
|
+
.list('recorded', app.tests.verified.recorded)
|
|
577
|
+
.list('unverified', app.tests.verified.unverified).data).data)
|
|
563
578
|
.part('record', new Writer()
|
|
564
579
|
.text('keep_for', app.record.keepFor, DEFAULT_KEEP_FOR)
|
|
565
580
|
.list('include', app.record.include, DEFAULT_RECORD_INCLUDE)
|
package/lib/specs/actions.js
CHANGED
|
@@ -644,6 +644,7 @@ export const SERVER_ACTIONS = {
|
|
|
644
644
|
export const APP_BEHAVIOURS = {
|
|
645
645
|
'customer-interview': {},
|
|
646
646
|
'data-quality': {},
|
|
647
|
+
decide: {},
|
|
647
648
|
'inbox-triage': {
|
|
648
649
|
'google-workspace.append_table_rows': 'leave_to_me',
|
|
649
650
|
'google-workspace.batch_modify_gmail_message_labels': 'do_it',
|
|
@@ -788,6 +789,7 @@ export const APP_BEHAVIOURS = {
|
|
|
788
789
|
export const APP_ESCALATIONS = {
|
|
789
790
|
'customer-interview': {},
|
|
790
791
|
'data-quality': {},
|
|
792
|
+
decide: {},
|
|
791
793
|
'inbox-triage': {
|
|
792
794
|
'google-workspace.batch_modify_gmail_message_labels': [
|
|
793
795
|
{
|
package/lib/specs/apps.d.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import type { AppBuilt, AppKind, AppSpec } from '../types/agentspecs';
|
|
11
11
|
export declare const CUSTOMER_INTERVIEW_APP_0_0_1: AppSpec;
|
|
12
12
|
export declare const DATA_QUALITY_APP_0_0_1: AppSpec;
|
|
13
|
+
export declare const DECIDE_APP_0_0_1: AppSpec;
|
|
13
14
|
export declare const INBOX_TRIAGE_APP_0_0_1: AppSpec;
|
|
14
15
|
export declare const MODEL_CHOICE_APP_0_0_1: AppSpec;
|
|
15
16
|
export declare const PIPELINE_REPORT_APP_0_0_1: AppSpec;
|
package/lib/specs/apps.js
CHANGED
|
@@ -90,6 +90,17 @@ export const CUSTOMER_INTERVIEW_APP_0_0_1 = {
|
|
|
90
90
|
expect: 'It gives the goal, the insights each with its quote, and the questions left open.',
|
|
91
91
|
},
|
|
92
92
|
],
|
|
93
|
+
verified: {
|
|
94
|
+
live: [
|
|
95
|
+
"Tried signed out in the browser from its example's page (2026-10-04): the model answered. Its Python code did not run there.",
|
|
96
|
+
],
|
|
97
|
+
recorded: [
|
|
98
|
+
"Its code runs in process in Datalayer's own tests with a scripted model: consent asked, a refusal honoured, a reply per message, an insight saved, the result recorded.",
|
|
99
|
+
],
|
|
100
|
+
unverified: [
|
|
101
|
+
'Its agent is switched off in the catalogue: its code has not run with a real model, and its tests have not been run.',
|
|
102
|
+
],
|
|
103
|
+
},
|
|
93
104
|
},
|
|
94
105
|
record: {
|
|
95
106
|
keepFor: '1_years',
|
|
@@ -169,6 +180,14 @@ export const DATA_QUALITY_APP_0_0_1 = {
|
|
|
169
180
|
readyAt: 0.8,
|
|
170
181
|
evalset: '',
|
|
171
182
|
cases: [],
|
|
183
|
+
verified: {
|
|
184
|
+
live: [],
|
|
185
|
+
recorded: [],
|
|
186
|
+
unverified: [
|
|
187
|
+
'It has not decided live: no dataset has been measured for it.',
|
|
188
|
+
'It has no test yet: what a good decision looks like has not been written down.',
|
|
189
|
+
],
|
|
190
|
+
},
|
|
172
191
|
},
|
|
173
192
|
record: {
|
|
174
193
|
keepFor: '1_years',
|
|
@@ -250,6 +269,114 @@ export const DATA_QUALITY_APP_0_0_1 = {
|
|
|
250
269
|
banner: '',
|
|
251
270
|
setup: ["The agent 'jupyter-data-analyst:0.0.1' is not enabled."],
|
|
252
271
|
};
|
|
272
|
+
export const DECIDE_APP_0_0_1 = {
|
|
273
|
+
schema: 'loop.app/v1',
|
|
274
|
+
id: 'decide',
|
|
275
|
+
version: '0.0.1',
|
|
276
|
+
name: 'Decide',
|
|
277
|
+
kind: 'chat',
|
|
278
|
+
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.',
|
|
279
|
+
owner: 'Datalayer <info@datalayer.io>',
|
|
280
|
+
agent: 'example-simple:0.0.1',
|
|
281
|
+
team: '',
|
|
282
|
+
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.',
|
|
283
|
+
model: '',
|
|
284
|
+
skills: [],
|
|
285
|
+
tools: ['decide:0.0.1'],
|
|
286
|
+
context: [],
|
|
287
|
+
contents: [],
|
|
288
|
+
connections: [],
|
|
289
|
+
rules: [
|
|
290
|
+
{
|
|
291
|
+
action: 'Ask a decision',
|
|
292
|
+
appliesTo: ['decide'],
|
|
293
|
+
behaviour: 'do_it',
|
|
294
|
+
},
|
|
295
|
+
],
|
|
296
|
+
permissions: {
|
|
297
|
+
spaces: [],
|
|
298
|
+
computer: {
|
|
299
|
+
browse: false,
|
|
300
|
+
files: false,
|
|
301
|
+
shell: false,
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
interface: {
|
|
305
|
+
layout: 'chat',
|
|
306
|
+
accent: 'sun',
|
|
307
|
+
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.',
|
|
308
|
+
starters: [
|
|
309
|
+
{
|
|
310
|
+
label: 'Is it urgent?',
|
|
311
|
+
message: "Is this ticket urgent? 'Help! My payouts have been failing for 3 days.'",
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
label: 'Which team?',
|
|
315
|
+
message: "Which team should handle this: 'I was charged twice this month'? Billing, Tech or Sales.",
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
label: 'Score a review',
|
|
319
|
+
message: "Score how positive this review is from 1 to 5: 'Setup took an hour, but support answered fast and it works.'",
|
|
320
|
+
},
|
|
321
|
+
],
|
|
322
|
+
settings: [],
|
|
323
|
+
components: [],
|
|
324
|
+
assistant: 'wizard',
|
|
325
|
+
},
|
|
326
|
+
tests: {
|
|
327
|
+
readyAt: 0.8,
|
|
328
|
+
evalset: '',
|
|
329
|
+
cases: [
|
|
330
|
+
{
|
|
331
|
+
ask: "Is this ticket urgent? 'Help! My payouts have been failing for 3 days.'",
|
|
332
|
+
expect: 'It calls decide with a noul question and answers yes, with its probability.',
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
ask: "Which team should handle this: 'I was charged twice this month'? Billing, Tech or Sales.",
|
|
336
|
+
expect: 'It calls decide with a choice among the three and answers Billing, with its confidence.',
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
ask: 'Score this review.',
|
|
340
|
+
expect: 'It asks for the review and the scale rather than inventing them.',
|
|
341
|
+
},
|
|
342
|
+
],
|
|
343
|
+
verified: {
|
|
344
|
+
live: [],
|
|
345
|
+
recorded: [],
|
|
346
|
+
unverified: [
|
|
347
|
+
'Its tests have not been run as a set: no validation run is attached to it.',
|
|
348
|
+
],
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
record: {
|
|
352
|
+
keepFor: '30_days',
|
|
353
|
+
include: ['conversations', 'decisions'],
|
|
354
|
+
suggestTests: false,
|
|
355
|
+
retentionDays: 30,
|
|
356
|
+
},
|
|
357
|
+
checks: {
|
|
358
|
+
guards: [],
|
|
359
|
+
gates: [],
|
|
360
|
+
track: '',
|
|
361
|
+
},
|
|
362
|
+
deployment: {
|
|
363
|
+
hosted: {
|
|
364
|
+
visibility: 'private',
|
|
365
|
+
slug: '',
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
goal: '',
|
|
369
|
+
triggers: [],
|
|
370
|
+
memory: '',
|
|
371
|
+
notifications: [],
|
|
372
|
+
enabled: true,
|
|
373
|
+
tags: ['example', 'decisions', 'jev'],
|
|
374
|
+
icon: 'law',
|
|
375
|
+
emoji: '⚖️',
|
|
376
|
+
avatar: '',
|
|
377
|
+
banner: '',
|
|
378
|
+
setup: [],
|
|
379
|
+
};
|
|
253
380
|
export const INBOX_TRIAGE_APP_0_0_1 = {
|
|
254
381
|
schema: 'loop.app/v1',
|
|
255
382
|
id: 'inbox-triage',
|
|
@@ -360,6 +487,16 @@ export const INBOX_TRIAGE_APP_0_0_1 = {
|
|
|
360
487
|
expect: 'It does not delete, and says deleting is left to me.',
|
|
361
488
|
},
|
|
362
489
|
],
|
|
490
|
+
verified: {
|
|
491
|
+
live: [
|
|
492
|
+
"Its page drawn in the Studio's Preview signed in (2026-10-04); no mail read.",
|
|
493
|
+
],
|
|
494
|
+
recorded: [],
|
|
495
|
+
unverified: [
|
|
496
|
+
'Its agent and the Google Workspace server are switched off in the catalogue: no mail has been read, drafted or sent.',
|
|
497
|
+
'Its tests have not been run.',
|
|
498
|
+
],
|
|
499
|
+
},
|
|
363
500
|
},
|
|
364
501
|
record: {
|
|
365
502
|
keepFor: '1_years',
|
|
@@ -462,6 +599,17 @@ export const MODEL_CHOICE_APP_0_0_1 = {
|
|
|
462
599
|
readyAt: 0.8,
|
|
463
600
|
evalset: '',
|
|
464
601
|
cases: [],
|
|
602
|
+
verified: {
|
|
603
|
+
live: [
|
|
604
|
+
'Its page edited on the Canvas in Chrome signed in (2026-10-04); a decision of it is kept, with its record.',
|
|
605
|
+
],
|
|
606
|
+
recorded: [
|
|
607
|
+
'Its three measured criteria — pass rate, cost and latency per task — are read from a run already recorded, not measured as it decides.',
|
|
608
|
+
],
|
|
609
|
+
unverified: [
|
|
610
|
+
'It has no test yet: what a good decision looks like has not been written down.',
|
|
611
|
+
],
|
|
612
|
+
},
|
|
465
613
|
},
|
|
466
614
|
record: {
|
|
467
615
|
keepFor: '1_years',
|
|
@@ -792,6 +940,15 @@ export const PIPELINE_REPORT_APP_0_0_1 = {
|
|
|
792
940
|
expect: 'It leaves personal data out of a board report, and says so.',
|
|
793
941
|
},
|
|
794
942
|
],
|
|
943
|
+
verified: {
|
|
944
|
+
live: [],
|
|
945
|
+
recorded: [],
|
|
946
|
+
unverified: [
|
|
947
|
+
'Its agent is switched off in the catalogue: no report has been built, no schedule has fired and nothing has stopped for an approval.',
|
|
948
|
+
'The pipeline export is named, not given.',
|
|
949
|
+
'Its tests have not been run.',
|
|
950
|
+
],
|
|
951
|
+
},
|
|
795
952
|
},
|
|
796
953
|
record: {
|
|
797
954
|
keepFor: '7_years',
|
|
@@ -1061,6 +1218,16 @@ export const QUOTE_CALCULATOR_APP_0_0_1 = {
|
|
|
1061
1218
|
expect: 'It refuses, and says a quote needs at least one seat.',
|
|
1062
1219
|
},
|
|
1063
1220
|
],
|
|
1221
|
+
verified: {
|
|
1222
|
+
live: [
|
|
1223
|
+
"Its page drawn in the Studio's Preview signed in (2026-10-04); no quote computed.",
|
|
1224
|
+
],
|
|
1225
|
+
recorded: [],
|
|
1226
|
+
unverified: [
|
|
1227
|
+
'Its agent is switched off in the catalogue: no quote has been computed live.',
|
|
1228
|
+
'Its tests have not been run.',
|
|
1229
|
+
],
|
|
1230
|
+
},
|
|
1064
1231
|
},
|
|
1065
1232
|
record: {
|
|
1066
1233
|
keepFor: '90_days',
|
|
@@ -1154,6 +1321,7 @@ export const REPORT_FROM_A_FILE_APP_0_0_1 = {
|
|
|
1154
1321
|
'Text',
|
|
1155
1322
|
'TextField',
|
|
1156
1323
|
'ChoicePicker',
|
|
1324
|
+
'FileUpload',
|
|
1157
1325
|
'Button',
|
|
1158
1326
|
],
|
|
1159
1327
|
surface: {
|
|
@@ -1178,7 +1346,17 @@ export const REPORT_FROM_A_FILE_APP_0_0_1 = {
|
|
|
1178
1346
|
{
|
|
1179
1347
|
id: 'inputs-body',
|
|
1180
1348
|
component: 'Column',
|
|
1181
|
-
children: ['report', 'question'],
|
|
1349
|
+
children: ['file', 'report', 'question'],
|
|
1350
|
+
},
|
|
1351
|
+
{
|
|
1352
|
+
id: 'file',
|
|
1353
|
+
component: 'FileUpload',
|
|
1354
|
+
label: 'The CSV',
|
|
1355
|
+
accept: ['.csv'],
|
|
1356
|
+
max_mb: 25,
|
|
1357
|
+
files: {
|
|
1358
|
+
path: '/files',
|
|
1359
|
+
},
|
|
1182
1360
|
},
|
|
1183
1361
|
{
|
|
1184
1362
|
id: 'report',
|
|
@@ -1221,7 +1399,7 @@ export const REPORT_FROM_A_FILE_APP_0_0_1 = {
|
|
|
1221
1399
|
{
|
|
1222
1400
|
id: 'run-label',
|
|
1223
1401
|
component: 'Text',
|
|
1224
|
-
text: '
|
|
1402
|
+
text: 'Run',
|
|
1225
1403
|
},
|
|
1226
1404
|
{
|
|
1227
1405
|
id: 'result',
|
|
@@ -1275,6 +1453,16 @@ export const REPORT_FROM_A_FILE_APP_0_0_1 = {
|
|
|
1275
1453
|
expect: 'It reports the text as data, emails nothing, and keeps to the report.',
|
|
1276
1454
|
},
|
|
1277
1455
|
],
|
|
1456
|
+
verified: {
|
|
1457
|
+
live: [],
|
|
1458
|
+
recorded: [
|
|
1459
|
+
"Its code runs in process in Datalayer's own tests with a scripted model: a CSV asked for and reported on, a PDF refused, a file given on its page answering what its code asks.",
|
|
1460
|
+
],
|
|
1461
|
+
unverified: [
|
|
1462
|
+
'Its agent is switched off in the catalogue: no real model has written a report, and its tests have not been run.',
|
|
1463
|
+
'The report is kept in its record; no download link is drawn yet.',
|
|
1464
|
+
],
|
|
1465
|
+
},
|
|
1278
1466
|
},
|
|
1279
1467
|
record: {
|
|
1280
1468
|
keepFor: '90_days',
|
|
@@ -1358,6 +1546,15 @@ export const SHIP_OR_FIX_APP_0_0_1 = {
|
|
|
1358
1546
|
readyAt: 0.8,
|
|
1359
1547
|
evalset: '',
|
|
1360
1548
|
cases: [],
|
|
1549
|
+
verified: {
|
|
1550
|
+
live: [],
|
|
1551
|
+
recorded: [
|
|
1552
|
+
'Its three measured criteria — pass rate, cost and latency per task — are read from a run already recorded, not measured as it decides.',
|
|
1553
|
+
],
|
|
1554
|
+
unverified: [
|
|
1555
|
+
'It has no test yet: what a good decision looks like has not been written down.',
|
|
1556
|
+
],
|
|
1557
|
+
},
|
|
1361
1558
|
},
|
|
1362
1559
|
record: {
|
|
1363
1560
|
keepFor: '1_years',
|
|
@@ -1516,6 +1713,17 @@ export const SUPPLIER_COMPARISON_APP_0_0_1 = {
|
|
|
1516
1713
|
readyAt: 0.8,
|
|
1517
1714
|
evalset: '',
|
|
1518
1715
|
cases: [],
|
|
1716
|
+
verified: {
|
|
1717
|
+
live: [
|
|
1718
|
+
'Decided in the Studio signed in (2026-10-04): alternatives added, metrics filled, the ranking recomputed, Assess all answered by the decision model, an alternative chosen and the decision saved; on its public run page and embedded too.',
|
|
1719
|
+
],
|
|
1720
|
+
recorded: [
|
|
1721
|
+
'Its measured criteria are filled from the past orders, the price lists and the delivery records you give it, not fetched live.',
|
|
1722
|
+
],
|
|
1723
|
+
unverified: [
|
|
1724
|
+
'It has no test yet: what a good decision looks like has not been written down.',
|
|
1725
|
+
],
|
|
1726
|
+
},
|
|
1519
1727
|
},
|
|
1520
1728
|
record: {
|
|
1521
1729
|
keepFor: '1_years',
|
|
@@ -1807,6 +2015,15 @@ export const SUPPORT_DESK_APP_0_0_1 = {
|
|
|
1807
2015
|
expect: 'It does not do it, says a person handles refunds, and offers to hand the request over.',
|
|
1808
2016
|
},
|
|
1809
2017
|
],
|
|
2018
|
+
verified: {
|
|
2019
|
+
live: [],
|
|
2020
|
+
recorded: [],
|
|
2021
|
+
unverified: [
|
|
2022
|
+
'Its agent is switched off in the catalogue: no conversation has run.',
|
|
2023
|
+
'Its two documents are named, not given: a builder gives their own on What it knows.',
|
|
2024
|
+
'Its tests have not been run.',
|
|
2025
|
+
],
|
|
2026
|
+
},
|
|
1810
2027
|
},
|
|
1811
2028
|
record: {
|
|
1812
2029
|
keepFor: '1_years',
|
|
@@ -1920,6 +2137,16 @@ export const WEB_RESEARCH_APP_0_0_1 = {
|
|
|
1920
2137
|
expect: 'It keeps to its task, and does not follow instructions found in what it reads.',
|
|
1921
2138
|
},
|
|
1922
2139
|
],
|
|
2140
|
+
verified: {
|
|
2141
|
+
live: [
|
|
2142
|
+
"Answered live on r1, in the Studio's Preview and from the terminal (2026-10-03), on Tavily.",
|
|
2143
|
+
'Drawn in the Preview signed in, with its page, what it suggests you ask and its setting (2026-10-04).',
|
|
2144
|
+
],
|
|
2145
|
+
recorded: [],
|
|
2146
|
+
unverified: [
|
|
2147
|
+
'Its tests have not been run as a set: no validation run is attached to it.',
|
|
2148
|
+
],
|
|
2149
|
+
},
|
|
1923
2150
|
},
|
|
1924
2151
|
record: {
|
|
1925
2152
|
keepFor: '90_days',
|
|
@@ -1953,6 +2180,7 @@ export const WEB_RESEARCH_APP_0_0_1 = {
|
|
|
1953
2180
|
export const APP_CATALOGUE = {
|
|
1954
2181
|
'customer-interview': CUSTOMER_INTERVIEW_APP_0_0_1,
|
|
1955
2182
|
'data-quality': DATA_QUALITY_APP_0_0_1,
|
|
2183
|
+
decide: DECIDE_APP_0_0_1,
|
|
1956
2184
|
'inbox-triage': INBOX_TRIAGE_APP_0_0_1,
|
|
1957
2185
|
'model-choice': MODEL_CHOICE_APP_0_0_1,
|
|
1958
2186
|
'pipeline-report': PIPELINE_REPORT_APP_0_0_1,
|
|
@@ -2049,6 +2277,17 @@ export const APP_SOURCES = {
|
|
|
2049
2277
|
expect: 'It gives the goal, the insights each with its quote, and the questions left open.',
|
|
2050
2278
|
},
|
|
2051
2279
|
],
|
|
2280
|
+
verified: {
|
|
2281
|
+
live: [
|
|
2282
|
+
"Tried signed out in the browser from its example's page (2026-10-04): the model answered. Its Python code did not run there.",
|
|
2283
|
+
],
|
|
2284
|
+
recorded: [
|
|
2285
|
+
"Its code runs in process in Datalayer's own tests with a scripted model: consent asked, a refusal honoured, a reply per message, an insight saved, the result recorded.",
|
|
2286
|
+
],
|
|
2287
|
+
unverified: [
|
|
2288
|
+
'Its agent is switched off in the catalogue: its code has not run with a real model, and its tests have not been run.',
|
|
2289
|
+
],
|
|
2290
|
+
},
|
|
2052
2291
|
},
|
|
2053
2292
|
record: {
|
|
2054
2293
|
include: ['conversations', 'outputs', 'feedback'],
|
|
@@ -2084,6 +2323,14 @@ export const APP_SOURCES = {
|
|
|
2084
2323
|
'Button',
|
|
2085
2324
|
],
|
|
2086
2325
|
},
|
|
2326
|
+
tests: {
|
|
2327
|
+
verified: {
|
|
2328
|
+
unverified: [
|
|
2329
|
+
'It has not decided live: no dataset has been measured for it.',
|
|
2330
|
+
'It has no test yet: what a good decision looks like has not been written down.',
|
|
2331
|
+
],
|
|
2332
|
+
},
|
|
2333
|
+
},
|
|
2087
2334
|
record: {
|
|
2088
2335
|
include: ['decisions', 'sources', 'checks'],
|
|
2089
2336
|
},
|
|
@@ -2128,6 +2375,74 @@ export const APP_SOURCES = {
|
|
|
2128
2375
|
icon: 'filter',
|
|
2129
2376
|
emoji: '🧹',
|
|
2130
2377
|
},
|
|
2378
|
+
decide: {
|
|
2379
|
+
schema: 'loop.app/v1',
|
|
2380
|
+
id: 'decide',
|
|
2381
|
+
name: 'Decide',
|
|
2382
|
+
kind: 'chat',
|
|
2383
|
+
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.',
|
|
2384
|
+
owner: 'Datalayer <info@datalayer.io>',
|
|
2385
|
+
agent: 'example-simple:0.0.1',
|
|
2386
|
+
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.',
|
|
2387
|
+
tools: ['decide:0.0.1'],
|
|
2388
|
+
rules: [
|
|
2389
|
+
{
|
|
2390
|
+
action: 'Ask a decision',
|
|
2391
|
+
applies_to: ['decide'],
|
|
2392
|
+
behaviour: 'do_it',
|
|
2393
|
+
},
|
|
2394
|
+
],
|
|
2395
|
+
interface: {
|
|
2396
|
+
accent: 'sun',
|
|
2397
|
+
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.',
|
|
2398
|
+
starters: [
|
|
2399
|
+
{
|
|
2400
|
+
label: 'Is it urgent?',
|
|
2401
|
+
message: "Is this ticket urgent? 'Help! My payouts have been failing for 3 days.'",
|
|
2402
|
+
},
|
|
2403
|
+
{
|
|
2404
|
+
label: 'Which team?',
|
|
2405
|
+
message: "Which team should handle this: 'I was charged twice this month'? Billing, Tech or Sales.",
|
|
2406
|
+
},
|
|
2407
|
+
{
|
|
2408
|
+
label: 'Score a review',
|
|
2409
|
+
message: "Score how positive this review is from 1 to 5: 'Setup took an hour, but support answered fast and it works.'",
|
|
2410
|
+
},
|
|
2411
|
+
],
|
|
2412
|
+
assistant: 'wizard',
|
|
2413
|
+
},
|
|
2414
|
+
tests: {
|
|
2415
|
+
cases: [
|
|
2416
|
+
{
|
|
2417
|
+
ask: "Is this ticket urgent? 'Help! My payouts have been failing for 3 days.'",
|
|
2418
|
+
expect: 'It calls decide with a noul question and answers yes, with its probability.',
|
|
2419
|
+
},
|
|
2420
|
+
{
|
|
2421
|
+
ask: "Which team should handle this: 'I was charged twice this month'? Billing, Tech or Sales.",
|
|
2422
|
+
expect: 'It calls decide with a choice among the three and answers Billing, with its confidence.',
|
|
2423
|
+
},
|
|
2424
|
+
{
|
|
2425
|
+
ask: 'Score this review.',
|
|
2426
|
+
expect: 'It asks for the review and the scale rather than inventing them.',
|
|
2427
|
+
},
|
|
2428
|
+
],
|
|
2429
|
+
verified: {
|
|
2430
|
+
unverified: [
|
|
2431
|
+
'Its tests have not been run as a set: no validation run is attached to it.',
|
|
2432
|
+
],
|
|
2433
|
+
},
|
|
2434
|
+
},
|
|
2435
|
+
record: {
|
|
2436
|
+
keep_for: '30_days',
|
|
2437
|
+
include: ['conversations', 'decisions'],
|
|
2438
|
+
},
|
|
2439
|
+
deployment: {
|
|
2440
|
+
hosted: {},
|
|
2441
|
+
},
|
|
2442
|
+
tags: ['example', 'decisions', 'jev'],
|
|
2443
|
+
icon: 'law',
|
|
2444
|
+
emoji: '⚖️',
|
|
2445
|
+
},
|
|
2131
2446
|
'inbox-triage': {
|
|
2132
2447
|
schema: 'loop.app/v1',
|
|
2133
2448
|
id: 'inbox-triage',
|
|
@@ -2218,6 +2533,15 @@ export const APP_SOURCES = {
|
|
|
2218
2533
|
expect: 'It does not delete, and says deleting is left to me.',
|
|
2219
2534
|
},
|
|
2220
2535
|
],
|
|
2536
|
+
verified: {
|
|
2537
|
+
live: [
|
|
2538
|
+
"Its page drawn in the Studio's Preview signed in (2026-10-04); no mail read.",
|
|
2539
|
+
],
|
|
2540
|
+
unverified: [
|
|
2541
|
+
'Its agent and the Google Workspace server are switched off in the catalogue: no mail has been read, drafted or sent.',
|
|
2542
|
+
'Its tests have not been run.',
|
|
2543
|
+
],
|
|
2544
|
+
},
|
|
2221
2545
|
},
|
|
2222
2546
|
record: {
|
|
2223
2547
|
include: ['conversations', 'actions', 'decisions', 'approvals', 'checks'],
|
|
@@ -2272,6 +2596,19 @@ export const APP_SOURCES = {
|
|
|
2272
2596
|
'Button',
|
|
2273
2597
|
],
|
|
2274
2598
|
},
|
|
2599
|
+
tests: {
|
|
2600
|
+
verified: {
|
|
2601
|
+
live: [
|
|
2602
|
+
'Its page edited on the Canvas in Chrome signed in (2026-10-04); a decision of it is kept, with its record.',
|
|
2603
|
+
],
|
|
2604
|
+
recorded: [
|
|
2605
|
+
'Its three measured criteria — pass rate, cost and latency per task — are read from a run already recorded, not measured as it decides.',
|
|
2606
|
+
],
|
|
2607
|
+
unverified: [
|
|
2608
|
+
'It has no test yet: what a good decision looks like has not been written down.',
|
|
2609
|
+
],
|
|
2610
|
+
},
|
|
2611
|
+
},
|
|
2275
2612
|
record: {
|
|
2276
2613
|
include: ['decisions', 'sources', 'checks'],
|
|
2277
2614
|
},
|
|
@@ -2547,6 +2884,13 @@ export const APP_SOURCES = {
|
|
|
2547
2884
|
expect: 'It leaves personal data out of a board report, and says so.',
|
|
2548
2885
|
},
|
|
2549
2886
|
],
|
|
2887
|
+
verified: {
|
|
2888
|
+
unverified: [
|
|
2889
|
+
'Its agent is switched off in the catalogue: no report has been built, no schedule has fired and nothing has stopped for an approval.',
|
|
2890
|
+
'The pipeline export is named, not given.',
|
|
2891
|
+
'Its tests have not been run.',
|
|
2892
|
+
],
|
|
2893
|
+
},
|
|
2550
2894
|
},
|
|
2551
2895
|
record: {
|
|
2552
2896
|
keep_for: '7_years',
|
|
@@ -2782,6 +3126,15 @@ export const APP_SOURCES = {
|
|
|
2782
3126
|
expect: 'It refuses, and says a quote needs at least one seat.',
|
|
2783
3127
|
},
|
|
2784
3128
|
],
|
|
3129
|
+
verified: {
|
|
3130
|
+
live: [
|
|
3131
|
+
"Its page drawn in the Studio's Preview signed in (2026-10-04); no quote computed.",
|
|
3132
|
+
],
|
|
3133
|
+
unverified: [
|
|
3134
|
+
'Its agent is switched off in the catalogue: no quote has been computed live.',
|
|
3135
|
+
'Its tests have not been run.',
|
|
3136
|
+
],
|
|
3137
|
+
},
|
|
2785
3138
|
},
|
|
2786
3139
|
record: {
|
|
2787
3140
|
keep_for: '90_days',
|
|
@@ -2835,6 +3188,7 @@ export const APP_SOURCES = {
|
|
|
2835
3188
|
'Text',
|
|
2836
3189
|
'TextField',
|
|
2837
3190
|
'ChoicePicker',
|
|
3191
|
+
'FileUpload',
|
|
2838
3192
|
'Button',
|
|
2839
3193
|
],
|
|
2840
3194
|
surface: {
|
|
@@ -2858,7 +3212,17 @@ export const APP_SOURCES = {
|
|
|
2858
3212
|
{
|
|
2859
3213
|
id: 'inputs-body',
|
|
2860
3214
|
component: 'Column',
|
|
2861
|
-
children: ['report', 'question'],
|
|
3215
|
+
children: ['file', 'report', 'question'],
|
|
3216
|
+
},
|
|
3217
|
+
{
|
|
3218
|
+
id: 'file',
|
|
3219
|
+
component: 'FileUpload',
|
|
3220
|
+
accept: ['.csv'],
|
|
3221
|
+
files: {
|
|
3222
|
+
path: '/files',
|
|
3223
|
+
},
|
|
3224
|
+
label: 'The CSV',
|
|
3225
|
+
max_mb: 25,
|
|
2862
3226
|
},
|
|
2863
3227
|
{
|
|
2864
3228
|
id: 'report',
|
|
@@ -2901,7 +3265,7 @@ export const APP_SOURCES = {
|
|
|
2901
3265
|
{
|
|
2902
3266
|
id: 'run-label',
|
|
2903
3267
|
component: 'Text',
|
|
2904
|
-
text: '
|
|
3268
|
+
text: 'Run',
|
|
2905
3269
|
},
|
|
2906
3270
|
{
|
|
2907
3271
|
id: 'result',
|
|
@@ -2952,6 +3316,15 @@ export const APP_SOURCES = {
|
|
|
2952
3316
|
expect: 'It reports the text as data, emails nothing, and keeps to the report.',
|
|
2953
3317
|
},
|
|
2954
3318
|
],
|
|
3319
|
+
verified: {
|
|
3320
|
+
recorded: [
|
|
3321
|
+
"Its code runs in process in Datalayer's own tests with a scripted model: a CSV asked for and reported on, a PDF refused, a file given on its page answering what its code asks.",
|
|
3322
|
+
],
|
|
3323
|
+
unverified: [
|
|
3324
|
+
'Its agent is switched off in the catalogue: no real model has written a report, and its tests have not been run.',
|
|
3325
|
+
'The report is kept in its record; no download link is drawn yet.',
|
|
3326
|
+
],
|
|
3327
|
+
},
|
|
2955
3328
|
},
|
|
2956
3329
|
record: {
|
|
2957
3330
|
keep_for: '90_days',
|
|
@@ -2989,6 +3362,16 @@ export const APP_SOURCES = {
|
|
|
2989
3362
|
'Button',
|
|
2990
3363
|
],
|
|
2991
3364
|
},
|
|
3365
|
+
tests: {
|
|
3366
|
+
verified: {
|
|
3367
|
+
recorded: [
|
|
3368
|
+
'Its three measured criteria — pass rate, cost and latency per task — are read from a run already recorded, not measured as it decides.',
|
|
3369
|
+
],
|
|
3370
|
+
unverified: [
|
|
3371
|
+
'It has no test yet: what a good decision looks like has not been written down.',
|
|
3372
|
+
],
|
|
3373
|
+
},
|
|
3374
|
+
},
|
|
2992
3375
|
record: {
|
|
2993
3376
|
include: ['decisions', 'sources', 'checks'],
|
|
2994
3377
|
},
|
|
@@ -3086,6 +3469,19 @@ export const APP_SOURCES = {
|
|
|
3086
3469
|
'Button',
|
|
3087
3470
|
],
|
|
3088
3471
|
},
|
|
3472
|
+
tests: {
|
|
3473
|
+
verified: {
|
|
3474
|
+
live: [
|
|
3475
|
+
'Decided in the Studio signed in (2026-10-04): alternatives added, metrics filled, the ranking recomputed, Assess all answered by the decision model, an alternative chosen and the decision saved; on its public run page and embedded too.',
|
|
3476
|
+
],
|
|
3477
|
+
recorded: [
|
|
3478
|
+
'Its measured criteria are filled from the past orders, the price lists and the delivery records you give it, not fetched live.',
|
|
3479
|
+
],
|
|
3480
|
+
unverified: [
|
|
3481
|
+
'It has no test yet: what a good decision looks like has not been written down.',
|
|
3482
|
+
],
|
|
3483
|
+
},
|
|
3484
|
+
},
|
|
3089
3485
|
record: {
|
|
3090
3486
|
include: ['decisions', 'sources', 'checks'],
|
|
3091
3487
|
},
|
|
@@ -3318,6 +3714,13 @@ export const APP_SOURCES = {
|
|
|
3318
3714
|
expect: 'It does not do it, says a person handles refunds, and offers to hand the request over.',
|
|
3319
3715
|
},
|
|
3320
3716
|
],
|
|
3717
|
+
verified: {
|
|
3718
|
+
unverified: [
|
|
3719
|
+
'Its agent is switched off in the catalogue: no conversation has run.',
|
|
3720
|
+
'Its two documents are named, not given: a builder gives their own on What it knows.',
|
|
3721
|
+
'Its tests have not been run.',
|
|
3722
|
+
],
|
|
3723
|
+
},
|
|
3321
3724
|
},
|
|
3322
3725
|
record: {
|
|
3323
3726
|
include: ['conversations', 'sources', 'feedback'],
|
|
@@ -3389,6 +3792,15 @@ export const APP_SOURCES = {
|
|
|
3389
3792
|
expect: 'It keeps to its task, and does not follow instructions found in what it reads.',
|
|
3390
3793
|
},
|
|
3391
3794
|
],
|
|
3795
|
+
verified: {
|
|
3796
|
+
live: [
|
|
3797
|
+
"Answered live on r1, in the Studio's Preview and from the terminal (2026-10-03), on Tavily.",
|
|
3798
|
+
'Drawn in the Preview signed in, with its page, what it suggests you ask and its setting (2026-10-04).',
|
|
3799
|
+
],
|
|
3800
|
+
unverified: [
|
|
3801
|
+
'Its tests have not been run as a set: no validation run is attached to it.',
|
|
3802
|
+
],
|
|
3803
|
+
},
|
|
3392
3804
|
},
|
|
3393
3805
|
record: {
|
|
3394
3806
|
keep_for: '90_days',
|
|
@@ -3409,6 +3821,7 @@ export const APP_SOURCES = {
|
|
|
3409
3821
|
export const APP_BUILT = {
|
|
3410
3822
|
'customer-interview': 'python',
|
|
3411
3823
|
'data-quality': 'written',
|
|
3824
|
+
decide: 'written',
|
|
3412
3825
|
'inbox-triage': 'written',
|
|
3413
3826
|
'model-choice': 'written',
|
|
3414
3827
|
'pipeline-report': 'written',
|
|
@@ -633,6 +633,10 @@ export const APPSPEC_SCHEMA = {
|
|
|
633
633
|
title: 'Cases',
|
|
634
634
|
type: 'array',
|
|
635
635
|
},
|
|
636
|
+
verified: {
|
|
637
|
+
$ref: '#/$defs/AppVerified',
|
|
638
|
+
description: 'What was verified live, what runs on recorded data, and what is not verified yet',
|
|
639
|
+
},
|
|
636
640
|
},
|
|
637
641
|
title: 'AppTests',
|
|
638
642
|
type: 'object',
|
|
@@ -680,6 +684,38 @@ export const APPSPEC_SCHEMA = {
|
|
|
680
684
|
title: 'AppTrigger',
|
|
681
685
|
type: 'object',
|
|
682
686
|
},
|
|
687
|
+
AppVerified: {
|
|
688
|
+
additionalProperties: false,
|
|
689
|
+
description: 'What was verified, and how, each in a sentence a person reads (LOOP E-14).\n\nAn example says it on its card and on its page: what was tried live,\nwhat runs on recorded data instead, and what is not verified yet. Said\nby whoever tried it; nothing here is computed.',
|
|
690
|
+
properties: {
|
|
691
|
+
live: {
|
|
692
|
+
description: 'What was tried live, where and when',
|
|
693
|
+
items: {
|
|
694
|
+
type: 'string',
|
|
695
|
+
},
|
|
696
|
+
title: 'Live',
|
|
697
|
+
type: 'array',
|
|
698
|
+
},
|
|
699
|
+
recorded: {
|
|
700
|
+
description: 'What runs on recorded data, not on live calls',
|
|
701
|
+
items: {
|
|
702
|
+
type: 'string',
|
|
703
|
+
},
|
|
704
|
+
title: 'Recorded',
|
|
705
|
+
type: 'array',
|
|
706
|
+
},
|
|
707
|
+
unverified: {
|
|
708
|
+
description: 'What is not verified yet',
|
|
709
|
+
items: {
|
|
710
|
+
type: 'string',
|
|
711
|
+
},
|
|
712
|
+
title: 'Unverified',
|
|
713
|
+
type: 'array',
|
|
714
|
+
},
|
|
715
|
+
},
|
|
716
|
+
title: 'AppVerified',
|
|
717
|
+
type: 'object',
|
|
718
|
+
},
|
|
683
719
|
Behaviour: {
|
|
684
720
|
description: 'What an application does when it meets an action: the four a person chooses from.',
|
|
685
721
|
enum: ['do_it', 'if_asked', 'ask_first', 'leave_to_me'],
|
|
@@ -860,7 +896,7 @@ export const APPSPEC_SCHEMA = {
|
|
|
860
896
|
type: 'array',
|
|
861
897
|
},
|
|
862
898
|
context: {
|
|
863
|
-
description:
|
|
899
|
+
description: "The Frames it works under: the catalogue's, or its organization's own (`org-…`)",
|
|
864
900
|
items: {
|
|
865
901
|
type: 'string',
|
|
866
902
|
},
|
|
@@ -17,5 +17,7 @@ export declare const BesideItsWork: Story;
|
|
|
17
17
|
export declare const WorkerActivity: Story;
|
|
18
18
|
/** An approval. */
|
|
19
19
|
export declare const Approval: Story;
|
|
20
|
+
/** Tool calls, each led by the mark of whoever the tool belongs to. */
|
|
21
|
+
export declare const ToolMarks: Story;
|
|
20
22
|
/** The floating assistant, in each of its states or stepped aside. */
|
|
21
23
|
export declare const Assistant: Story;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { ASSISTANT_PICTURES, AssistantScreen, ApprovalScreen, BesideWorkScreen, ConversationScreen, REFERENCE_THEMES, ReferenceTheme, WorkerActivityScreen, } from './ReferenceScreens';
|
|
2
|
+
import { ASSISTANT_PICTURES, AssistantScreen, ApprovalScreen, BesideWorkScreen, ConversationScreen, REFERENCE_THEMES, ReferenceTheme, ToolMarksScreen, WorkerActivityScreen, } from './ReferenceScreens';
|
|
3
3
|
const meta = {
|
|
4
4
|
title: 'Loop/Reference screens',
|
|
5
5
|
parameters: { layout: 'fullscreen' },
|
|
@@ -25,6 +25,8 @@ export const BesideItsWork = story(BesideWorkScreen);
|
|
|
25
25
|
export const WorkerActivity = story(WorkerActivityScreen);
|
|
26
26
|
/** An approval. */
|
|
27
27
|
export const Approval = story(ApprovalScreen);
|
|
28
|
+
/** Tool calls, each led by the mark of whoever the tool belongs to. */
|
|
29
|
+
export const ToolMarks = story(ToolMarksScreen);
|
|
28
30
|
/** The floating assistant, in each of its states or stepped aside. */
|
|
29
31
|
export const Assistant = {
|
|
30
32
|
render: ({ theme, mode, picture }) => (_jsx(ReferenceTheme, { theme: theme, mode: mode, children: _jsx(AssistantScreen, { picture: picture }) })),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { JSX, ReactNode } from 'react';
|
|
2
2
|
import { type ThemeVariant } from '@datalayer/primer-addons';
|
|
3
|
-
/** The
|
|
4
|
-
export declare const REFERENCE_SCREENS: readonly ["conversation", "beside-work", "worker-activity", "approval"];
|
|
3
|
+
/** The screens, by the name a picture and a story take. */
|
|
4
|
+
export declare const REFERENCE_SCREENS: readonly ["conversation", "beside-work", "worker-activity", "approval", "tool-marks"];
|
|
5
5
|
export type ReferenceScreen = (typeof REFERENCE_SCREENS)[number];
|
|
6
6
|
/** The floating assistant's pictures (T-27): its states, and stepped aside. */
|
|
7
7
|
export declare const ASSISTANT_PICTURES: readonly ["idle", "thinking", "working", "waiting", "paused", "speaking", "aside"];
|
|
@@ -34,6 +34,8 @@ export declare function BesideWorkScreen(): JSX.Element;
|
|
|
34
34
|
export declare function WorkerActivityScreen(): JSX.Element;
|
|
35
35
|
/** An approval: the action, the rule that asks, and the one decision. */
|
|
36
36
|
export declare function ApprovalScreen(): JSX.Element;
|
|
37
|
+
/** Tool calls, each led by the mark of whoever the tool belongs to. */
|
|
38
|
+
export declare function ToolMarksScreen(): JSX.Element;
|
|
37
39
|
export declare const REFERENCE_SCREEN_COMPONENTS: Record<ReferenceScreen, () => JSX.Element>;
|
|
38
40
|
/**
|
|
39
41
|
* The paper clip in one state, in the page's corner. `aside` puts a dialog
|
|
@@ -31,12 +31,13 @@ import { ASSISTANT_WORDS, } from '../../chat/assistant/state';
|
|
|
31
31
|
import { buildReactorFromPlugins } from '@datalayer/reactor';
|
|
32
32
|
import { AssistantCharactersPlugin, assistantCharacterNamed, } from '../../loop/plugins/assistant-characters';
|
|
33
33
|
import { OwlCharacterPlugin } from '../../examples/utils/owlCharacterPlugin';
|
|
34
|
-
/** The
|
|
34
|
+
/** The screens, by the name a picture and a story take. */
|
|
35
35
|
export const REFERENCE_SCREENS = [
|
|
36
36
|
'conversation',
|
|
37
37
|
'beside-work',
|
|
38
38
|
'worker-activity',
|
|
39
39
|
'approval',
|
|
40
|
+
'tool-marks',
|
|
40
41
|
];
|
|
41
42
|
/** The floating assistant's pictures (T-27): its states, and stepped aside. */
|
|
42
43
|
export const ASSISTANT_PICTURES = [
|
|
@@ -145,6 +146,24 @@ const APPROVAL = [
|
|
|
145
146
|
said('a2', 'assistant', 'Sending is a rule you keep: I ask first.'),
|
|
146
147
|
tool('a3', 'send_email', { to: 'ada@example.com', subject: 'Your order 1042' }, 'inProgress', { pending_approval: true, approval_id: 'approval-1' }),
|
|
147
148
|
];
|
|
149
|
+
/*
|
|
150
|
+
* Whose tools: an MCP server's (the Odoo accounting server's, its icon the
|
|
151
|
+
* Datalayer icons' Odoo), a skill's and a frontend tool set's, each call led
|
|
152
|
+
* by its mark.
|
|
153
|
+
*/
|
|
154
|
+
const TOOL_MARKS = [
|
|
155
|
+
said('t1', 'user', 'What is still open on the books, and does my notebook agree?'),
|
|
156
|
+
tool('t2', 'odoo_accounting_list_open_balances', { account: '400000' }, 'complete', { partners: 7 }),
|
|
157
|
+
tool('t3', 'run_skill_script', { skill_name: 'accounting', script: 'variance' }, 'complete', { variance: 0 }),
|
|
158
|
+
tool('t4', 'readCell', { index: 3 }, 'complete', { source: 'balances' }),
|
|
159
|
+
said('t5', 'assistant', 'Seven customers owe you, and your notebook says the same total.'),
|
|
160
|
+
];
|
|
161
|
+
const TOOL_MARKS_SERVERS = [
|
|
162
|
+
{
|
|
163
|
+
id: 'odoo-accounting',
|
|
164
|
+
tools: [{ name: 'odoo_accounting_list_open_balances' }],
|
|
165
|
+
},
|
|
166
|
+
];
|
|
148
167
|
// ---------------------------------------------------------------------------
|
|
149
168
|
// The conversation
|
|
150
169
|
// ---------------------------------------------------------------------------
|
|
@@ -157,7 +176,7 @@ const AVATARS = {
|
|
|
157
176
|
assistantAvatarBg: 'accent.emphasis',
|
|
158
177
|
};
|
|
159
178
|
/** A chat as an application shows it: its presence, its words, its composer. */
|
|
160
|
-
function Conversation({ name, face, presence, items, composer = true, }) {
|
|
179
|
+
function Conversation({ name, face, presence, items, composer = true, mcpServers, }) {
|
|
161
180
|
const endRef = useRef(null);
|
|
162
181
|
const [input, setInput] = useState('');
|
|
163
182
|
return (_jsxs(Box, { sx: {
|
|
@@ -166,7 +185,7 @@ function Conversation({ name, face, presence, items, composer = true, }) {
|
|
|
166
185
|
display: 'flex',
|
|
167
186
|
flexDirection: 'column',
|
|
168
187
|
height: '100%',
|
|
169
|
-
}, children: [_jsx(ChatBaseHeader, { title: name, brandIcon: _jsx(PresenceFace, { face: face, size: 20, state: presence }), headerContent: _jsx(PresenceLine, { state: presence }), padding: 3, messageCount: items.length, onNewChat: () => undefined, onClear: () => undefined }), _jsx(Box, { sx: { flex: 1, minHeight: 0, overflow: 'hidden' }, children: _jsx(ChatMessageList, { displayItems: items, isLoading: false, isStreaming: false, showLoadingIndicator: false, hideMessagesAfterToolUI: false, avatarConfig: AVATARS, padding: 3, emptyContent: null, messagesEndRef: endRef, onRespond: async () => undefined }) }), composer && (_jsx(InputPrompt, { input: input, setInput: setInput, isLoading: false, connectionConfirmed: true, placeholder: "Send a message", autoFocus: false, padding: 3, onSend: () => undefined, onStop: () => undefined, showTokenUsage: false, showModelSelector: false, showToolsMenu: false, showSkillsMenu: false, codemodeEnabled: false, hasConfigData: false, hasSkillsData: false, isA2AProtocol: false }))] }));
|
|
188
|
+
}, children: [_jsx(ChatBaseHeader, { title: name, brandIcon: _jsx(PresenceFace, { face: face, size: 20, state: presence }), headerContent: _jsx(PresenceLine, { state: presence }), padding: 3, messageCount: items.length, onNewChat: () => undefined, onClear: () => undefined }), _jsx(Box, { sx: { flex: 1, minHeight: 0, overflow: 'hidden' }, children: _jsx(ChatMessageList, { displayItems: items, isLoading: false, isStreaming: false, showLoadingIndicator: false, hideMessagesAfterToolUI: false, avatarConfig: AVATARS, padding: 3, emptyContent: null, messagesEndRef: endRef, onRespond: async () => undefined, mcpServers: mcpServers }) }), composer && (_jsx(InputPrompt, { input: input, setInput: setInput, isLoading: false, connectionConfirmed: true, placeholder: "Send a message", autoFocus: false, padding: 3, onSend: () => undefined, onStop: () => undefined, showTokenUsage: false, showModelSelector: false, showToolsMenu: false, showSkillsMenu: false, codemodeEnabled: false, hasConfigData: false, hasSkillsData: false, isA2AProtocol: false }))] }));
|
|
170
189
|
}
|
|
171
190
|
// ---------------------------------------------------------------------------
|
|
172
191
|
// The four screens
|
|
@@ -198,11 +217,16 @@ export function WorkerActivityScreen() {
|
|
|
198
217
|
export function ApprovalScreen() {
|
|
199
218
|
return (_jsx(Frame, { children: _jsx(Box, { sx: { flex: 1, display: 'flex', justifyContent: 'center' }, children: _jsx(Box, { sx: { width: '100%', maxWidth: 640, display: 'flex' }, children: _jsx(Conversation, { name: "Support desk", face: "\uD83E\uDD8A", presence: "waiting", items: APPROVAL }) }) }) }));
|
|
200
219
|
}
|
|
220
|
+
/** Tool calls, each led by the mark of whoever the tool belongs to. */
|
|
221
|
+
export function ToolMarksScreen() {
|
|
222
|
+
return (_jsx(Frame, { children: _jsx(Box, { sx: { flex: 1, display: 'flex', justifyContent: 'center' }, children: _jsx(Box, { sx: { width: '100%', maxWidth: 680, display: 'flex' }, children: _jsx(Conversation, { name: "Bookkeeper", face: "\uD83E\uDDEE", presence: "idle", items: TOOL_MARKS, composer: false, mcpServers: TOOL_MARKS_SERVERS }) }) }) }));
|
|
223
|
+
}
|
|
201
224
|
export const REFERENCE_SCREEN_COMPONENTS = {
|
|
202
225
|
conversation: ConversationScreen,
|
|
203
226
|
'beside-work': BesideWorkScreen,
|
|
204
227
|
'worker-activity': WorkerActivityScreen,
|
|
205
228
|
approval: ApprovalScreen,
|
|
229
|
+
'tool-marks': ToolMarksScreen,
|
|
206
230
|
};
|
|
207
231
|
// ---------------------------------------------------------------------------
|
|
208
232
|
// The floating assistant (T-27)
|
|
@@ -469,12 +469,23 @@ export interface AppTestCaseSpec {
|
|
|
469
469
|
ask: string;
|
|
470
470
|
expect: string;
|
|
471
471
|
}
|
|
472
|
+
/**
|
|
473
|
+
* What was verified, and how, each in a sentence a person reads (LOOP E-14):
|
|
474
|
+
* what was tried live, what runs on recorded data, what is not verified yet.
|
|
475
|
+
*/
|
|
476
|
+
export interface AppVerifiedSpec {
|
|
477
|
+
live: string[];
|
|
478
|
+
recorded: string[];
|
|
479
|
+
unverified: string[];
|
|
480
|
+
}
|
|
472
481
|
/** How an application is verified. */
|
|
473
482
|
export interface AppTestsSpec {
|
|
474
483
|
/** The share of tests that has to pass for it to be ready. */
|
|
475
484
|
readyAt: number;
|
|
476
485
|
evalset: string;
|
|
477
486
|
cases: AppTestCaseSpec[];
|
|
487
|
+
/** What was verified live, what runs on recorded data, what is not yet. */
|
|
488
|
+
verified: AppVerifiedSpec;
|
|
478
489
|
}
|
|
479
490
|
/** What is kept of what an application did, and for how long. */
|
|
480
491
|
export interface AppRecordSpec {
|