@datalayer/agent-runtimes 1.5.3 → 1.5.6
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 +7 -7
- package/lib/apps/apps/appspec.d.ts +1 -1
- package/lib/apps/apps/appspec.js +46 -0
- package/lib/apps/apps/sceneYaml.js +4 -0
- package/lib/apps/plugins/pap-sign-in/PapSignInCard.d.ts +3 -1
- package/lib/apps/plugins/pap-sign-in/PapSignInCard.js +7 -2
- package/lib/apps/plugins/pap-sign-in/signIn.d.ts +20 -8
- package/lib/apps/plugins/pap-sign-in/signIn.js +18 -4
- package/lib/examples/ScenesExample.js +2 -1
- package/lib/protocols/commerce.js +11 -3
- package/lib/specs/actions.js +15 -14
- package/lib/specs/apps.d.ts +1 -0
- package/lib/specs/apps.js +287 -2
- package/lib/specs/appspecSchema.js +86 -1
- package/lib/specs/protocols.js +4 -4
- package/lib/specs/sceneSchema.js +185 -1
- package/lib/specs/scenes.d.ts +4 -0
- package/lib/specs/scenes.js +696 -0
- package/lib/types/agentspecs.d.ts +29 -0
- package/lib/types/scenes.d.ts +52 -0
- package/package.json +1 -1
- package/scripts/codegen/generate_apps.py +2 -2
- package/scripts/codegen/generate_scenes.py +11 -4
|
@@ -99,7 +99,7 @@ export declare function uiProblems(app: Pick<AppSpec, 'ui' | 'enabled'>): string
|
|
|
99
99
|
* know or said twice, a planned protocol while it is offered, and a `pap`,
|
|
100
100
|
* `pact` or `a2a` block configuring a protocol it does not list.
|
|
101
101
|
*/
|
|
102
|
-
export declare function protocolsProblems(app: Pick<AppSpec, 'protocols' | 'enabled' | 'pap' | 'pact' | 'a2a'>): string[];
|
|
102
|
+
export declare function protocolsProblems(app: Pick<AppSpec, 'protocols' | 'enabled' | 'pap' | 'pact' | 'a2a' | 'commerce'>): string[];
|
|
103
103
|
/**
|
|
104
104
|
* An application as the document its file holds.
|
|
105
105
|
*
|
package/lib/apps/apps/appspec.js
CHANGED
|
@@ -204,6 +204,7 @@ const KNOWN_KEYS = [
|
|
|
204
204
|
'ui',
|
|
205
205
|
'pap',
|
|
206
206
|
'pact',
|
|
207
|
+
'commerce',
|
|
207
208
|
'a2a',
|
|
208
209
|
'rules',
|
|
209
210
|
'permissions',
|
|
@@ -333,6 +334,41 @@ function parsePact(data) {
|
|
|
333
334
|
})),
|
|
334
335
|
};
|
|
335
336
|
}
|
|
337
|
+
/** Commerce (AGENT_PROTOCOLS PI-01): the merchants it shops at for each person. */
|
|
338
|
+
function parseCommerce(data) {
|
|
339
|
+
return {
|
|
340
|
+
merchants: records(data.merchants).map(merchant => ({
|
|
341
|
+
id: text(merchant.id),
|
|
342
|
+
protocol: oneOf(merchant.protocol, ['ucp', 'acp'], 'ucp'),
|
|
343
|
+
merchant: text(merchant.merchant),
|
|
344
|
+
access: oneOf(merchant.access, ['read', 'write'], 'read'),
|
|
345
|
+
...(isData(merchant.limit)
|
|
346
|
+
? {
|
|
347
|
+
limit: {
|
|
348
|
+
amount: text(merchant.limit.amount),
|
|
349
|
+
currency: text(merchant.limit.currency),
|
|
350
|
+
},
|
|
351
|
+
}
|
|
352
|
+
: {}),
|
|
353
|
+
})),
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
/** Commerce as its document says it, nothing at its default. */
|
|
357
|
+
function dumpCommerce(commerce) {
|
|
358
|
+
if (!commerce)
|
|
359
|
+
return {};
|
|
360
|
+
return new Writer().list('merchants', commerce.merchants.map(merchant => new Writer()
|
|
361
|
+
.text('id', merchant.id, '\u0000')
|
|
362
|
+
.text('protocol', merchant.protocol, '\u0000')
|
|
363
|
+
.text('merchant', merchant.merchant, '\u0000')
|
|
364
|
+
.value('access', merchant.access, 'read')
|
|
365
|
+
.part('limit', merchant.limit
|
|
366
|
+
? {
|
|
367
|
+
amount: merchant.limit.amount,
|
|
368
|
+
currency: merchant.limit.currency,
|
|
369
|
+
}
|
|
370
|
+
: {}).data)).data;
|
|
371
|
+
}
|
|
336
372
|
/** PACT as its document says it, nothing at its default. */
|
|
337
373
|
function dumpPact(pact) {
|
|
338
374
|
if (!pact)
|
|
@@ -912,6 +948,9 @@ export function parseAppspec(document) {
|
|
|
912
948
|
if (isData(data.pact)) {
|
|
913
949
|
app.pact = parsePact(data.pact);
|
|
914
950
|
}
|
|
951
|
+
if (isData(data.commerce)) {
|
|
952
|
+
app.commerce = parseCommerce(data.commerce);
|
|
953
|
+
}
|
|
915
954
|
if (isData(data.a2a)) {
|
|
916
955
|
app.a2a = parseA2A(data.a2a);
|
|
917
956
|
}
|
|
@@ -976,6 +1015,12 @@ export function protocolsProblems(app) {
|
|
|
976
1015
|
problems.push(`Its \`${block}\` block configures ${spec.name}, which it does not list: add '${spec.id}' to \`protocols\`.`);
|
|
977
1016
|
}
|
|
978
1017
|
}
|
|
1018
|
+
// The `commerce` block configures UCP and ACP, by each merchant's protocol.
|
|
1019
|
+
for (const id of new Set((app.commerce?.merchants ?? []).map(merchant => merchant.protocol))) {
|
|
1020
|
+
if (!app.protocols.includes(id)) {
|
|
1021
|
+
problems.push(`Its \`commerce\` block shops over ${id.toUpperCase()}, which it does not list: add '${id}' to \`protocols\`.`);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
979
1024
|
return problems;
|
|
980
1025
|
}
|
|
981
1026
|
// --- writing --------------------------------------------------------------------------
|
|
@@ -1243,6 +1288,7 @@ export function dumpAppspec(app) {
|
|
|
1243
1288
|
.list('ui', app.ui)
|
|
1244
1289
|
.part('pap', dumpPap(app.pap))
|
|
1245
1290
|
.part('pact', dumpPact(app.pact))
|
|
1291
|
+
.part('commerce', dumpCommerce(app.commerce))
|
|
1246
1292
|
.part('a2a', dumpA2A(app.a2a))
|
|
1247
1293
|
.list('rules', app.rules.map(rule => ({
|
|
1248
1294
|
action: rule.action,
|
|
@@ -31,6 +31,7 @@ export const emptySceneSpec = () => ({
|
|
|
31
31
|
schema: SCENE_SCHEMA,
|
|
32
32
|
id: '',
|
|
33
33
|
version: '0.0.1',
|
|
34
|
+
kind: 'team',
|
|
34
35
|
name: '',
|
|
35
36
|
description: '',
|
|
36
37
|
tags: [],
|
|
@@ -57,6 +58,9 @@ export const emptySceneSpec = () => ({
|
|
|
57
58
|
},
|
|
58
59
|
deployment: { account: '', page: '', addresses: {} },
|
|
59
60
|
setup: [],
|
|
61
|
+
actors: [],
|
|
62
|
+
lines: [],
|
|
63
|
+
live: '',
|
|
60
64
|
});
|
|
61
65
|
const isRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
62
66
|
/**
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
* *Sign in at a company*, in the chat (AGENT_PROTOCOLS PI-56): where the
|
|
3
3
|
* gateway's `pap_sign_in` answers, the company's page as a button opening a
|
|
4
4
|
* new tab, the code large and copyable with a code to scan for Device
|
|
5
|
-
* Sign-In,
|
|
5
|
+
* Sign-In, Datalayer's own page for Mediated Sign-In (where the person types
|
|
6
|
+
* what the company asks, never in the chat) with where a code was sent,
|
|
7
|
+
* until when, and *I have signed in: check again* — sent as the
|
|
6
8
|
* person's next message — when the chat can send one, otherwise a line
|
|
7
9
|
* asking them to say so. What it reads is `signIn`'s.
|
|
8
10
|
*
|
|
@@ -25,9 +25,14 @@ export function PapSignInCard({ context, send, }) {
|
|
|
25
25
|
setCopied(false);
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
|
-
|
|
28
|
+
const title = read.mode === 'mediated'
|
|
29
|
+
? PAP_SIGN_IN_WORDS.mediatedTitle(read.host)
|
|
30
|
+
: PAP_SIGN_IN_WORDS.title(read.host);
|
|
31
|
+
return (_jsxs(Box, { as: "section", "aria-label": title, my: 2, p: 3, border: "1px solid", borderColor: "border.default", borderRadius: 2, bg: "canvas.subtle", maxWidth: 480, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 2, mb: 1 }, children: title }), _jsx(Text, { as: "p", sx: { mt: 0, mb: 2, color: 'fg.muted', fontSize: 1 }, children: read.mode === 'device'
|
|
29
32
|
? PAP_SIGN_IN_WORDS.device
|
|
30
|
-
:
|
|
33
|
+
: read.mode === 'mediated'
|
|
34
|
+
? PAP_SIGN_IN_WORDS.mediated
|
|
35
|
+
: PAP_SIGN_IN_WORDS.direct }), read.sentTo ? (_jsx(Text, { as: "p", sx: { mt: 0, mb: 2, fontSize: 1 }, children: PAP_SIGN_IN_WORDS.sentTo(read.sentTo) })) : null, read.code ? (_jsxs(Box, { display: "flex", gap: 3, alignItems: "center", flexWrap: "wrap", mb: 2, children: [_jsxs(Box, { children: [_jsx(Text, { as: "div", sx: { fontSize: 0, color: 'fg.muted' }, children: PAP_SIGN_IN_WORDS.code }), _jsx(Text, { as: "div", "aria-live": "polite", sx: {
|
|
31
36
|
fontFamily: 'mono',
|
|
32
37
|
fontSize: 5,
|
|
33
38
|
fontWeight: 'bold',
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* What the gateway's `pap_sign_in` tool answers, read and checked
|
|
3
3
|
* (AGENT_PROTOCOLS PI-56, PAP_DATALAYER P-03): the person signs in at a
|
|
4
|
-
* company themselves — on the company's page (`direct`),
|
|
5
|
-
* code there (`device`)
|
|
6
|
-
*
|
|
4
|
+
* company themselves — on the company's page (`direct`), by entering a
|
|
5
|
+
* code there (`device`), or by typing what the company asks on Datalayer's
|
|
6
|
+
* own page (`mediated`), never in the conversation. The chat shows the link,
|
|
7
|
+
* the code and until when; the agent never sees what the person types. A
|
|
8
|
+
* business over PACT answers its `pact_sign_in` the same way (a `device`
|
|
9
|
+
* sign-in at the business).
|
|
7
10
|
*
|
|
8
11
|
* Pure: no React. A test reaches it without a chat around it.
|
|
9
12
|
*
|
|
@@ -11,13 +14,15 @@
|
|
|
11
14
|
*/
|
|
12
15
|
/** A sign-in waiting for the person, as the card shows it. */
|
|
13
16
|
export type PapSignInWaiting = {
|
|
14
|
-
mode: 'direct' | 'device';
|
|
15
|
-
/** The company's page, `https` only. */
|
|
17
|
+
mode: 'direct' | 'device' | 'mediated';
|
|
18
|
+
/** The company's page — Datalayer's own, for `mediated` — `https` only. */
|
|
16
19
|
open: string;
|
|
17
|
-
/** The
|
|
20
|
+
/** The page's domain, read from its address: what the person can trust. */
|
|
18
21
|
host: string;
|
|
19
22
|
/** The code to enter, for `device`. */
|
|
20
23
|
code?: string;
|
|
24
|
+
/** Where the company sent a code, for `mediated`, when it did. */
|
|
25
|
+
sentTo?: string;
|
|
21
26
|
/** Until when, ISO 8601. */
|
|
22
27
|
expiresAt?: string;
|
|
23
28
|
};
|
|
@@ -26,6 +31,10 @@ export declare const PAP_SIGN_IN_WORDS: {
|
|
|
26
31
|
readonly title: (host: string) => string;
|
|
27
32
|
readonly direct: "Open the company’s page, sign in there, and come back here.";
|
|
28
33
|
readonly device: "Open the company’s page and enter this code there.";
|
|
34
|
+
/** `mediated`: the page is Datalayer's, which names the company and asks what it asks. */
|
|
35
|
+
readonly mediatedTitle: (host: string) => string;
|
|
36
|
+
readonly mediated: "Open this page: it names the company and asks what the company needs. Type it there, never in this conversation.";
|
|
37
|
+
readonly sentTo: (to: string) => string;
|
|
29
38
|
readonly open: (host: string) => string;
|
|
30
39
|
readonly code: "Your code";
|
|
31
40
|
readonly copy: "Copy the code";
|
|
@@ -37,9 +46,12 @@ export declare const PAP_SIGN_IN_WORDS: {
|
|
|
37
46
|
readonly refused: "This sign-in link cannot be opened safely, so it is not shown.";
|
|
38
47
|
readonly qr: (host: string) => string;
|
|
39
48
|
};
|
|
40
|
-
/**
|
|
49
|
+
/**
|
|
50
|
+
* `pap_sign_in` — or a business's `pact_sign_in` (PI-56) — as the gateway
|
|
51
|
+
* names it with or without a prefix.
|
|
52
|
+
*/
|
|
41
53
|
export declare const PAP_SIGN_IN_TOOL: RegExp;
|
|
42
|
-
/** Whether a tool is `pap_sign_in`, as the gateway names it with or without a prefix. */
|
|
54
|
+
/** Whether a tool is `pap_sign_in` or `pact_sign_in`, as the gateway names it with or without a prefix. */
|
|
43
55
|
export declare const isPapSignInTool: (name: string) => boolean;
|
|
44
56
|
/** The page's address, `https` only; `null` for anything else. */
|
|
45
57
|
export declare function safeSignInUrl(open: unknown): URL | null;
|
|
@@ -7,6 +7,10 @@ export const PAP_SIGN_IN_WORDS = {
|
|
|
7
7
|
title: (host) => `Sign in at ${host}`,
|
|
8
8
|
direct: 'Open the company’s page, sign in there, and come back here.',
|
|
9
9
|
device: 'Open the company’s page and enter this code there.',
|
|
10
|
+
/** `mediated`: the page is Datalayer's, which names the company and asks what it asks. */
|
|
11
|
+
mediatedTitle: (host) => `Sign in through ${host}`,
|
|
12
|
+
mediated: 'Open this page: it names the company and asks what the company needs. Type it there, never in this conversation.',
|
|
13
|
+
sentTo: (to) => `The company sent a code to ${to}.`,
|
|
10
14
|
open: (host) => `Open ${host}`,
|
|
11
15
|
code: 'Your code',
|
|
12
16
|
copy: 'Copy the code',
|
|
@@ -18,9 +22,12 @@ export const PAP_SIGN_IN_WORDS = {
|
|
|
18
22
|
refused: 'This sign-in link cannot be opened safely, so it is not shown.',
|
|
19
23
|
qr: (host) => `A code to scan to open ${host} on your phone`,
|
|
20
24
|
};
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
/**
|
|
26
|
+
* `pap_sign_in` — or a business's `pact_sign_in` (PI-56) — as the gateway
|
|
27
|
+
* names it with or without a prefix.
|
|
28
|
+
*/
|
|
29
|
+
export const PAP_SIGN_IN_TOOL = /(^|[_.:\-/])pa(?:p|ct)_sign_in$/;
|
|
30
|
+
/** Whether a tool is `pap_sign_in` or `pact_sign_in`, as the gateway names it with or without a prefix. */
|
|
24
31
|
export const isPapSignInTool = (name) => PAP_SIGN_IN_TOOL.test(name);
|
|
25
32
|
/** An MCP result's own object: its structured content, or the JSON of its text. */
|
|
26
33
|
function unwrapped(result) {
|
|
@@ -73,7 +80,9 @@ export function readPapSignIn(result) {
|
|
|
73
80
|
if (!data || data.status !== 'waiting_for_the_person') {
|
|
74
81
|
return null;
|
|
75
82
|
}
|
|
76
|
-
if (data.mode !== 'direct' &&
|
|
83
|
+
if (data.mode !== 'direct' &&
|
|
84
|
+
data.mode !== 'device' &&
|
|
85
|
+
data.mode !== 'mediated') {
|
|
77
86
|
return null;
|
|
78
87
|
}
|
|
79
88
|
const url = safeSignInUrl(data.open);
|
|
@@ -88,6 +97,11 @@ export function readPapSignIn(result) {
|
|
|
88
97
|
open: url.toString(),
|
|
89
98
|
host: url.hostname,
|
|
90
99
|
...(typeof data.code === 'string' && data.code ? { code: data.code } : {}),
|
|
100
|
+
...(data.mode === 'mediated' &&
|
|
101
|
+
typeof data.sent_to === 'string' &&
|
|
102
|
+
data.sent_to
|
|
103
|
+
? { sentTo: data.sent_to }
|
|
104
|
+
: {}),
|
|
91
105
|
...(typeof data.expires_at === 'string' && data.expires_at
|
|
92
106
|
? { expiresAt: data.expires_at }
|
|
93
107
|
: {}),
|
|
@@ -208,7 +208,8 @@ function Scene({ scene }) {
|
|
|
208
208
|
} }), _jsxs(Box, { display: "flex", gap: 2, mt: 2, children: [_jsx(Button, { variant: "primary", disabled: !team.ready || team.busy || !draft.trim(), onClick: () => send(draft), children: "Ask" }), team.busy && _jsx(Button, { onClick: team.stop, children: "Stop" })] }), _jsx(Box, { mt: 3, "data-team-conversation": "", children: team.turns.map((turn, index) => (_jsxs(Box, { p: 2, mb: 2, borderRadius: 2, bg: turn.role === 'user' ? 'accent.subtle' : 'canvas.subtle', children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: turn.role === 'user' ? PERSON : entry.app.name }), _jsx(Streamdown, { children: turn.text })] }, index))) })] }), _jsxs(Box, { flex: "1 1 360px", minWidth: 0, children: [!team.notebook && stage.peers.length > 0 && (_jsxs(_Fragment, { children: [_jsx(Heading, { as: "h3", sx: { fontSize: 2, mb: 2 }, children: "The report" }), _jsx(Box, { p: 3, border: "1px solid", borderColor: "border.default", borderRadius: 2, minHeight: 120, "data-team-report": "", children: team.report ? (_jsx(Streamdown, { children: team.report })) : (_jsx(Text, { sx: { color: 'fg.muted' }, children: "What the last member asked returns appears here, as it returned it, or as a notebook to run when it gives one." })) })] })), scene.setup.length > 0 && (_jsxs(Box, { mt: 3, "data-scene-setup": "", children: [_jsx(Heading, { as: "h3", sx: { fontSize: 1, mb: 1 }, children: "What this scene needs" }), scene.setup.map(line => (_jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', m: 0 }, children: line }, line)))] }))] })] })] }));
|
|
209
209
|
}
|
|
210
210
|
function Scenes() {
|
|
211
|
-
|
|
211
|
+
// A scripted scene is played as written on its page (PAP_DATALAYER X-02): here, the teams staged live.
|
|
212
|
+
const scenes = useMemo(() => listSceneSpecs().filter(scene => scene.kind === 'team'), []);
|
|
212
213
|
const [selected, setSelected] = useState(scenes[0]?.id ?? '');
|
|
213
214
|
const scene = scenes.find(one => one.id === selected) ?? scenes[0];
|
|
214
215
|
return (_jsxs(Box, { p: 4, maxWidth: 1080, mx: "auto", children: [_jsx(Heading, { as: "h2", sx: { fontSize: 4, mb: 1 }, children: "Scenes" }), _jsxs(Text, { as: "p", sx: { color: 'fg.muted', mt: 0 }, children: ["The catalogue\u2019s scenes, played against the local servers: each member on a runtime is served over A2A by ", _jsx("code", { children: "serve_scenes.py" }), "; the entry in your browser asks on your token or a visitor\u2019s trial key."] }), _jsx(UnderlineNav, { "aria-label": "Scenes", sx: { mb: 3 }, children: scenes.map(one => (_jsxs(UnderlineNav.Item, { "aria-current": one.id === scene?.id ? 'page' : undefined, onSelect: event => {
|
|
@@ -21,13 +21,21 @@ import { PROTOCOL_TOOL_CLASSES } from '../specs/actions';
|
|
|
21
21
|
* thing: one with several classes, or none, throws rather than guess.
|
|
22
22
|
*/
|
|
23
23
|
export function operationClasses(protocol) {
|
|
24
|
+
const table = PROTOCOL_TOOL_CLASSES[protocol];
|
|
25
|
+
// The table names the gateway's tools (`ucp_search`): an operation is the
|
|
26
|
+
// tool's name without its connection's prefix.
|
|
27
|
+
const prefix = `${table.connection}_`;
|
|
24
28
|
const out = {};
|
|
25
|
-
for (const [name, classes] of Object.entries(
|
|
29
|
+
for (const [name, classes] of Object.entries(table.tools)) {
|
|
26
30
|
if (classes.length !== 1) {
|
|
27
31
|
throw new Error(`${protocol} ${name} is classed ${classes}: one class each`);
|
|
28
32
|
}
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
if (!name.startsWith(prefix)) {
|
|
34
|
+
throw new Error(`${protocol} ${name} is not one of its \`${prefix}\` tools`);
|
|
35
|
+
}
|
|
36
|
+
out[name
|
|
37
|
+
.slice(prefix.length)
|
|
38
|
+
.replace(/_([a-z])/g, (_, c) => c.toUpperCase())] = classes[0];
|
|
31
39
|
}
|
|
32
40
|
return out;
|
|
33
41
|
}
|
package/lib/specs/actions.js
CHANGED
|
@@ -671,12 +671,11 @@ export const PROTOCOL_TOOL_CLASSES = {
|
|
|
671
671
|
'agentic-commerce': {
|
|
672
672
|
connection: 'acp',
|
|
673
673
|
tools: {
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
complete: ['buy'],
|
|
674
|
+
acp_get_checkout: ['read'],
|
|
675
|
+
acp_create_checkout: ['write'],
|
|
676
|
+
acp_update_checkout: ['write'],
|
|
677
|
+
acp_cancel_checkout: ['write'],
|
|
678
|
+
acp_complete: ['buy'],
|
|
680
679
|
},
|
|
681
680
|
},
|
|
682
681
|
pact: {
|
|
@@ -694,7 +693,8 @@ export const PROTOCOL_TOOL_CLASSES = {
|
|
|
694
693
|
connection: 'pap',
|
|
695
694
|
tools: {
|
|
696
695
|
pap_company: ['read'],
|
|
697
|
-
pap_ask: ['
|
|
696
|
+
pap_ask: ['send'],
|
|
697
|
+
pap_handoff: ['send'],
|
|
698
698
|
pap_sign_in: ['read'],
|
|
699
699
|
pap_sign_in_status: ['read'],
|
|
700
700
|
pap_read: ['read'],
|
|
@@ -707,13 +707,12 @@ export const PROTOCOL_TOOL_CLASSES = {
|
|
|
707
707
|
ucp: {
|
|
708
708
|
connection: 'ucp',
|
|
709
709
|
tools: {
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
complete: ['buy'],
|
|
710
|
+
ucp_search: ['read'],
|
|
711
|
+
ucp_get_checkout: ['read'],
|
|
712
|
+
ucp_create_checkout: ['write'],
|
|
713
|
+
ucp_update_checkout: ['write'],
|
|
714
|
+
ucp_cancel_checkout: ['write'],
|
|
715
|
+
ucp_complete: ['buy'],
|
|
717
716
|
},
|
|
718
717
|
},
|
|
719
718
|
};
|
|
@@ -974,6 +973,7 @@ export const APP_BEHAVIOURS = {
|
|
|
974
973
|
'report-from-a-file': {},
|
|
975
974
|
sales: {},
|
|
976
975
|
'ship-or-fix': {},
|
|
976
|
+
'shopping-desk': {},
|
|
977
977
|
'supplier-comparison': {},
|
|
978
978
|
'support-desk': {},
|
|
979
979
|
'travel-desk': {},
|
|
@@ -1041,6 +1041,7 @@ export const APP_ESCALATIONS = {
|
|
|
1041
1041
|
'report-from-a-file': {},
|
|
1042
1042
|
sales: {},
|
|
1043
1043
|
'ship-or-fix': {},
|
|
1044
|
+
'shopping-desk': {},
|
|
1044
1045
|
'supplier-comparison': {},
|
|
1045
1046
|
'support-desk': {},
|
|
1046
1047
|
'travel-desk': {},
|
package/lib/specs/apps.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export declare const QUOTE_CALCULATOR_APP_0_0_1: AppSpec;
|
|
|
26
26
|
export declare const REPORT_FROM_A_FILE_APP_0_0_1: AppSpec;
|
|
27
27
|
export declare const SALES_APP_0_0_1: AppSpec;
|
|
28
28
|
export declare const SHIP_OR_FIX_APP_0_0_1: AppSpec;
|
|
29
|
+
export declare const SHOPPING_DESK_APP_0_0_1: AppSpec;
|
|
29
30
|
export declare const SUPPLIER_COMPARISON_APP_0_0_1: AppSpec;
|
|
30
31
|
export declare const SUPPORT_DESK_APP_0_0_1: AppSpec;
|
|
31
32
|
export declare const TRAVEL_DESK_APP_0_0_1: AppSpec;
|