@datalayer/agent-runtimes 1.5.10 → 1.5.12
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 +9 -9
- package/lib/apps/plugins/pap-sign-in/PapSignInCard.js +30 -4
- package/lib/apps/plugins/pap-sign-in/signIn.d.ts +23 -1
- package/lib/apps/plugins/pap-sign-in/signIn.js +32 -1
- package/lib/examples/AgentA2ATeamExample.js +2 -2
- package/lib/specs/actions.js +1 -0
- package/lib/specs/apps.d.ts +11 -11
- package/lib/specs/apps.js +143 -118
- package/lib/specs/scenes.js +2 -2
- package/lib/specs/teams/teams.js +4 -4
- package/package.json +1 -1
|
@@ -1,14 +1,38 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
3
|
import { Button, Flash, Heading, Text } from '@primer/react';
|
|
4
4
|
import { CopyIcon, LinkExternalIcon } from '@primer/octicons-react';
|
|
5
5
|
import { Box } from '@datalayer/primer-addons';
|
|
6
6
|
import QRCode from 'react-qr-code';
|
|
7
|
-
import { PAP_SIGN_IN_WORDS, readPapSignIn } from './signIn';
|
|
7
|
+
import { PAP_SIGN_IN_CHANNEL, PAP_SIGN_IN_WORDS, readPapSignIn, signInReturnOf, } from './signIn';
|
|
8
8
|
export function PapSignInCard({ context, send, }) {
|
|
9
9
|
const [copied, setCopied] = useState(false);
|
|
10
10
|
const [sent, setSent] = useState(false);
|
|
11
|
+
const [returned, setReturned] = useState(null);
|
|
11
12
|
const read = context.status === 'complete' ? readPapSignIn(context.result) : null;
|
|
13
|
+
// A Direct Sign-In: Datalayer's `/pap/signed-in`, in the tab the company sent the person
|
|
14
|
+
// back to, says how it came back (PAP_DATALAYER P-04); the conversation goes on here.
|
|
15
|
+
const company = read && !('refused' in read) && read.mode === 'direct'
|
|
16
|
+
? (read.company ?? '')
|
|
17
|
+
: '';
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (!company || typeof BroadcastChannel === 'undefined') {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const channel = new BroadcastChannel(PAP_SIGN_IN_CHANNEL);
|
|
23
|
+
channel.onmessage = (event) => {
|
|
24
|
+
const outcome = signInReturnOf(event.data, company);
|
|
25
|
+
if (outcome) {
|
|
26
|
+
setReturned(outcome);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
return () => channel.close();
|
|
30
|
+
}, [company]);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (returned === 'signed_in' && send && !sent) {
|
|
33
|
+
setSent(send(PAP_SIGN_IN_WORDS.checkMessage(company)));
|
|
34
|
+
}
|
|
35
|
+
}, [returned, send, sent, company]);
|
|
12
36
|
if (!read) {
|
|
13
37
|
// Running, or another answer: the chat's own row says it.
|
|
14
38
|
return _jsx(_Fragment, { children: context.defaultUI });
|
|
@@ -25,9 +49,11 @@ export function PapSignInCard({ context, send, }) {
|
|
|
25
49
|
setCopied(false);
|
|
26
50
|
}
|
|
27
51
|
};
|
|
52
|
+
// Who the person signs in at: the company itself for a Direct Sign-In (P-04), the page's host otherwise.
|
|
53
|
+
const named = read.company ?? read.host;
|
|
28
54
|
const title = read.mode === 'mediated'
|
|
29
55
|
? PAP_SIGN_IN_WORDS.mediatedTitle(read.host)
|
|
30
|
-
: PAP_SIGN_IN_WORDS.title(
|
|
56
|
+
: PAP_SIGN_IN_WORDS.title(named);
|
|
31
57
|
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'
|
|
32
58
|
? PAP_SIGN_IN_WORDS.device
|
|
33
59
|
: read.mode === 'mediated'
|
|
@@ -37,6 +63,6 @@ export function PapSignInCard({ context, send, }) {
|
|
|
37
63
|
fontSize: 5,
|
|
38
64
|
fontWeight: 'bold',
|
|
39
65
|
letterSpacing: '0.15em',
|
|
40
|
-
}, children: read.code }), _jsx(Button, { size: "small", leadingVisual: CopyIcon, onClick: () => void copy(), children: copied ? PAP_SIGN_IN_WORDS.copied : PAP_SIGN_IN_WORDS.copy })] }), _jsx(Box, { bg: "#ffffff", p: 2, borderRadius: 2, lineHeight: 0, children: _jsx(QRCode, { value: read.open, size: 112, title: PAP_SIGN_IN_WORDS.qr(read.host) }) })] })) : null, _jsxs(Box, { display: "flex", gap: 2, flexWrap: "wrap", alignItems: "center", children: [_jsx(Button, { as: "a", href: read.open, target: "_blank", rel: "noopener noreferrer", variant: "primary", trailingVisual: LinkExternalIcon, children: PAP_SIGN_IN_WORDS.open(
|
|
66
|
+
}, children: read.code }), _jsx(Button, { size: "small", leadingVisual: CopyIcon, onClick: () => void copy(), children: copied ? PAP_SIGN_IN_WORDS.copied : PAP_SIGN_IN_WORDS.copy })] }), _jsx(Box, { bg: "#ffffff", p: 2, borderRadius: 2, lineHeight: 0, children: _jsx(QRCode, { value: read.open, size: 112, title: PAP_SIGN_IN_WORDS.qr(read.host) }) })] })) : null, _jsxs(Box, { display: "flex", gap: 2, flexWrap: "wrap", alignItems: "center", children: [_jsx(Button, { as: "a", href: read.open, target: "_blank", rel: "noopener noreferrer", variant: "primary", trailingVisual: LinkExternalIcon, children: PAP_SIGN_IN_WORDS.open(named) }), send ? (_jsx(Button, { disabled: sent, onClick: () => setSent(send(PAP_SIGN_IN_WORDS.checkMessage(named))), children: PAP_SIGN_IN_WORDS.checkAgain })) : null] }), returned ? (_jsx(Text, { as: "p", role: "status", sx: { mt: 2, mb: 0, fontSize: 1 }, children: PAP_SIGN_IN_WORDS.returned[returned](named) })) : null, read.expiresAt ? (_jsx(Text, { as: "p", sx: { mt: 2, mb: 0, fontSize: 0, color: 'fg.muted' }, children: PAP_SIGN_IN_WORDS.until(read.expiresAt) })) : null, send ? null : (_jsx(Text, { as: "p", sx: { mt: 1, mb: 0, fontSize: 1 }, children: PAP_SIGN_IN_WORDS.tellMe }))] }));
|
|
41
67
|
}
|
|
42
68
|
export default PapSignInCard;
|
|
@@ -19,6 +19,12 @@ export type PapSignInWaiting = {
|
|
|
19
19
|
open: string;
|
|
20
20
|
/** The page's domain, read from its address: what the person can trust. */
|
|
21
21
|
host: string;
|
|
22
|
+
/**
|
|
23
|
+
* The company's domain, when the gateway names it: for a bound `direct`
|
|
24
|
+
* sign-in the page opened is Datalayer's start link (PAP_DATALAYER P-04),
|
|
25
|
+
* which sends the person on to the company and takes them back only from it.
|
|
26
|
+
*/
|
|
27
|
+
company?: string;
|
|
22
28
|
/** The code to enter, for `device`. */
|
|
23
29
|
code?: string;
|
|
24
30
|
/** Where the company sent a code, for `mediated`, when it did. */
|
|
@@ -29,7 +35,7 @@ export type PapSignInWaiting = {
|
|
|
29
35
|
/** What the card says. */
|
|
30
36
|
export declare const PAP_SIGN_IN_WORDS: {
|
|
31
37
|
readonly title: (host: string) => string;
|
|
32
|
-
readonly direct: "Open the company’s page, sign in there, and
|
|
38
|
+
readonly direct: "Open the company’s page through Datalayer, sign in there, and this conversation goes on once you are back.";
|
|
33
39
|
readonly device: "Open the company’s page and enter this code there.";
|
|
34
40
|
/** `mediated`: the page is Datalayer's, which names the company and asks what it asks. */
|
|
35
41
|
readonly mediatedTitle: (host: string) => string;
|
|
@@ -45,7 +51,23 @@ export declare const PAP_SIGN_IN_WORDS: {
|
|
|
45
51
|
readonly checkMessage: (host: string) => string;
|
|
46
52
|
readonly refused: "This sign-in link cannot be opened safely, so it is not shown.";
|
|
47
53
|
readonly qr: (host: string) => string;
|
|
54
|
+
/** Once the person's browser came back from the company (P-04), said under the card. */
|
|
55
|
+
readonly returned: {
|
|
56
|
+
readonly signed_in: (company: string) => string;
|
|
57
|
+
readonly denied: (company: string) => string;
|
|
58
|
+
readonly refused: (company: string) => string;
|
|
59
|
+
};
|
|
48
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* Where Datalayer's `/pap/signed-in` page says a Direct Sign-In came back
|
|
63
|
+
* (PAP_DATALAYER P-04): the card waiting for that company hears it in the
|
|
64
|
+
* person's tab, so the conversation goes on there.
|
|
65
|
+
*/
|
|
66
|
+
export declare const PAP_SIGN_IN_CHANNEL = "datalayer-pap-sign-in";
|
|
67
|
+
/** How a Direct Sign-In came back. */
|
|
68
|
+
export type PapSignInReturn = keyof typeof PAP_SIGN_IN_WORDS.returned;
|
|
69
|
+
/** What a message on the channel says of this company's sign-in, or `null`: another company's, or not one. */
|
|
70
|
+
export declare function signInReturnOf(message: unknown, company: string): PapSignInReturn | null;
|
|
49
71
|
/**
|
|
50
72
|
* `pap_sign_in` — or a business's `pact_sign_in` (PI-56) — as the gateway
|
|
51
73
|
* names it with or without a prefix.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
/** What the card says. */
|
|
6
6
|
export const PAP_SIGN_IN_WORDS = {
|
|
7
7
|
title: (host) => `Sign in at ${host}`,
|
|
8
|
-
direct: 'Open the company’s page, sign in there, and
|
|
8
|
+
direct: 'Open the company’s page through Datalayer, sign in there, and this conversation goes on once you are back.',
|
|
9
9
|
device: 'Open the company’s page and enter this code there.',
|
|
10
10
|
/** `mediated`: the page is Datalayer's, which names the company and asks what it asks. */
|
|
11
11
|
mediatedTitle: (host) => `Sign in through ${host}`,
|
|
@@ -21,7 +21,32 @@ export const PAP_SIGN_IN_WORDS = {
|
|
|
21
21
|
checkMessage: (host) => `I have signed in at ${host}. Please check again.`,
|
|
22
22
|
refused: 'This sign-in link cannot be opened safely, so it is not shown.',
|
|
23
23
|
qr: (host) => `A code to scan to open ${host} on your phone`,
|
|
24
|
+
/** Once the person's browser came back from the company (P-04), said under the card. */
|
|
25
|
+
returned: {
|
|
26
|
+
signed_in: (company) => `Signed in at ${company}: checking again.`,
|
|
27
|
+
denied: (company) => `You did not sign in at ${company}: ask again when you want to.`,
|
|
28
|
+
refused: (company) => `That sign-in at ${company} was refused, and nothing was kept: start it again here.`,
|
|
29
|
+
},
|
|
24
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* Where Datalayer's `/pap/signed-in` page says a Direct Sign-In came back
|
|
33
|
+
* (PAP_DATALAYER P-04): the card waiting for that company hears it in the
|
|
34
|
+
* person's tab, so the conversation goes on there.
|
|
35
|
+
*/
|
|
36
|
+
export const PAP_SIGN_IN_CHANNEL = 'datalayer-pap-sign-in';
|
|
37
|
+
const DOMAIN = /^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/;
|
|
38
|
+
/** What a message on the channel says of this company's sign-in, or `null`: another company's, or not one. */
|
|
39
|
+
export function signInReturnOf(message, company) {
|
|
40
|
+
if (!message || typeof message !== 'object' || Array.isArray(message)) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const said = message;
|
|
44
|
+
const outcome = said.outcome;
|
|
45
|
+
return said.company === company &&
|
|
46
|
+
(outcome === 'signed_in' || outcome === 'denied' || outcome === 'refused')
|
|
47
|
+
? outcome
|
|
48
|
+
: null;
|
|
49
|
+
}
|
|
25
50
|
/**
|
|
26
51
|
* `pap_sign_in` — or a business's `pact_sign_in` (PI-56) — as the gateway
|
|
27
52
|
* names it with or without a prefix.
|
|
@@ -92,10 +117,16 @@ export function readPapSignIn(result) {
|
|
|
92
117
|
if (data.mode === 'device' && (typeof data.code !== 'string' || !data.code)) {
|
|
93
118
|
return null;
|
|
94
119
|
}
|
|
120
|
+
// A bound Direct Sign-In opens Datalayer's start link: the card names the company the gateway
|
|
121
|
+
// names (`PapSignIn.company`); without one, the page's own domain is the company's.
|
|
122
|
+
const company = typeof data.company === 'string' && DOMAIN.test(data.company)
|
|
123
|
+
? data.company
|
|
124
|
+
: '';
|
|
95
125
|
return {
|
|
96
126
|
mode: data.mode,
|
|
97
127
|
open: url.toString(),
|
|
98
128
|
host: url.hostname,
|
|
129
|
+
...(company ? { company } : {}),
|
|
99
130
|
...(typeof data.code === 'string' && data.code ? { code: data.code } : {}),
|
|
100
131
|
...(data.mode === 'mediated' &&
|
|
101
132
|
typeof data.sent_to === 'string' &&
|
|
@@ -11,11 +11,11 @@ import { useBrowserInference } from '../hooks/useBrowserInference';
|
|
|
11
11
|
import { readJwtClaims, tokenLifetimeMs, useAnonymousSessionStore, } from '../runtimes/browser/anonymousToken';
|
|
12
12
|
import { connectA2APeer } from '../runtimes/browser/a2aPeer';
|
|
13
13
|
import { A2ATeamGraph, SceneView, NOTEBOOK_AND_WORDS, teamConnectionsOf, teamToolClassifier, useA2ATeam, usePeerSandbox, } from '../components/teams';
|
|
14
|
-
import { ACCOUNTING_APP_0_0_1,
|
|
14
|
+
import { ACCOUNTING_APP_0_0_1, SALES_APP_0_0_2 } from '../specs/apps';
|
|
15
15
|
import { AgentInspector, classifyToolCall, traceA2AFetch, useAgentInspector, } from '../components/inspector';
|
|
16
16
|
import { SALES_AND_ACCOUNTING_TEAM_SPEC_0_0_1 } from '../specs/teams/teams';
|
|
17
17
|
const TEAM = SALES_AND_ACCOUNTING_TEAM_SPEC_0_0_1;
|
|
18
|
-
const SALES =
|
|
18
|
+
const SALES = SALES_APP_0_0_2;
|
|
19
19
|
const ACCOUNTING = ACCOUNTING_APP_0_0_1;
|
|
20
20
|
/** What Accounting reaches, from its Appspec: Odoo, through the odoo-accounting MCP server. */
|
|
21
21
|
const ACCOUNTING_CONNECTIONS = teamConnectionsOf(ACCOUNTING);
|
package/lib/specs/actions.js
CHANGED
package/lib/specs/apps.d.ts
CHANGED
|
@@ -12,32 +12,32 @@ export declare const ACCOUNTING_APP_0_0_1: AppSpec;
|
|
|
12
12
|
export declare const BOOKKEEPING_DESK_APP_0_0_1: AppSpec;
|
|
13
13
|
export declare const CHANGE_DETECTION_APP_0_0_1: AppSpec;
|
|
14
14
|
export declare const CROP_MONITORING_APP_0_0_1: AppSpec;
|
|
15
|
-
export declare const
|
|
16
|
-
export declare const
|
|
15
|
+
export declare const CUSTOMER_INTERVIEW_APP_0_0_2: AppSpec;
|
|
16
|
+
export declare const DATA_QUALITY_APP_0_0_2: AppSpec;
|
|
17
17
|
export declare const DECIDE_APP_0_0_1: AppSpec;
|
|
18
18
|
export declare const DISASTER_ASSESSMENT_APP_0_0_1: AppSpec;
|
|
19
19
|
export declare const ERRAND_RUNNER_APP_0_0_1: AppSpec;
|
|
20
|
-
export declare const
|
|
21
|
-
export declare const
|
|
20
|
+
export declare const EVENT_RESPONSE_APP_0_0_2: AppSpec;
|
|
21
|
+
export declare const EXCHANGE_DESK_APP_0_0_2: AppSpec;
|
|
22
22
|
export declare const GUEST_DESK_APP_0_0_1: AppSpec;
|
|
23
23
|
export declare const INBOX_TRIAGE_APP_0_0_1: AppSpec;
|
|
24
24
|
export declare const LIVE_SHOP_CHAT_APP_0_0_1: AppSpec;
|
|
25
|
-
export declare const
|
|
25
|
+
export declare const MODEL_CHOICE_APP_0_0_2: AppSpec;
|
|
26
26
|
export declare const MONTH_END_CLOSE_APP_0_0_1: AppSpec;
|
|
27
27
|
export declare const ORDER_DESK_APP_0_0_1: AppSpec;
|
|
28
28
|
export declare const ORDER_TRACKER_APP_0_0_1: AppSpec;
|
|
29
29
|
export declare const PIPELINE_REPORT_APP_0_0_1: AppSpec;
|
|
30
|
-
export declare const
|
|
31
|
-
export declare const
|
|
30
|
+
export declare const QUOTE_CALCULATOR_APP_0_0_5: AppSpec;
|
|
31
|
+
export declare const REPORT_FROM_A_FILE_APP_0_0_4: AppSpec;
|
|
32
32
|
export declare const RETURNS_DESK_APP_0_0_1: AppSpec;
|
|
33
|
-
export declare const
|
|
34
|
-
export declare const
|
|
33
|
+
export declare const SALES_APP_0_0_2: AppSpec;
|
|
34
|
+
export declare const SHIP_OR_FIX_APP_0_0_2: AppSpec;
|
|
35
35
|
export declare const SHOP_CONCIERGE_APP_0_0_1: AppSpec;
|
|
36
36
|
export declare const SHOPPING_DESK_APP_0_0_1: AppSpec;
|
|
37
37
|
export declare const SIGN_IN_DESK_APP_0_0_1: AppSpec;
|
|
38
38
|
export declare const SIGNED_READER_APP_0_0_1: AppSpec;
|
|
39
|
-
export declare const
|
|
40
|
-
export declare const
|
|
39
|
+
export declare const SUPPLIER_COMPARISON_APP_0_0_2: AppSpec;
|
|
40
|
+
export declare const SUPPORT_DESK_APP_0_0_4: AppSpec;
|
|
41
41
|
export declare const TRAVEL_DESK_APP_0_0_1: AppSpec;
|
|
42
42
|
export declare const WEB_RESEARCH_APP_0_0_1: AppSpec;
|
|
43
43
|
export declare const APP_CATALOGUE: Record<string, AppSpec>;
|