@datalayer/agent-runtimes 1.5.89 → 1.5.91
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/README.md +29 -297
- package/dist-embed/datalayer-app-main.js +40 -36
- package/lib/apps/embed/element.js +20 -5
- package/lib/apps/embed/visitorApp.d.ts +23 -45
- package/lib/apps/embed/visitorApp.js +65 -13
- package/lib/components/teams/A2ATeamGraph.d.ts +58 -152
- package/lib/components/teams/A2ATeamGraph.js +169 -410
- package/lib/components/teams/SceneTranscript.d.ts +5 -1
- package/lib/components/teams/SceneTranscript.js +2 -2
- package/lib/components/teams/SceneView.d.ts +17 -5
- package/lib/components/teams/SceneView.js +7 -3
- package/lib/components/teams/a2aTeamFlow.d.ts +16 -7
- package/lib/components/teams/a2aTeamFlow.js +17 -14
- package/lib/components/teams/backdrops/catalogue.d.ts +35 -0
- package/lib/components/teams/backdrops/catalogue.js +34 -0
- package/lib/components/teams/backdrops/edges.d.ts +20 -0
- package/lib/components/teams/backdrops/edges.js +29 -0
- package/lib/components/teams/backdrops/faces.d.ts +24 -0
- package/lib/components/teams/backdrops/faces.js +39 -0
- package/lib/components/teams/backdrops/halo.d.ts +14 -0
- package/lib/components/teams/backdrops/halo.js +5 -0
- package/lib/components/teams/backdrops/hero.d.ts +14 -0
- package/lib/components/teams/backdrops/hero.js +178 -0
- package/lib/components/teams/backdrops/index.d.ts +22 -0
- package/lib/components/teams/backdrops/index.js +38 -0
- package/lib/components/teams/backdrops/nodes.d.ts +123 -0
- package/lib/components/teams/backdrops/nodes.js +265 -0
- package/lib/components/teams/backdrops/plain.d.ts +14 -0
- package/lib/components/teams/backdrops/plain.js +116 -0
- package/lib/components/teams/backdrops/studio.d.ts +17 -0
- package/lib/components/teams/backdrops/studio.js +122 -0
- package/lib/components/teams/backdrops/theme.d.ts +14 -0
- package/lib/components/teams/backdrops/theme.js +19 -0
- package/lib/components/teams/backdrops/types.d.ts +214 -0
- package/lib/components/teams/backdrops/types.js +5 -0
- package/lib/components/teams/index.d.ts +2 -0
- package/lib/components/teams/index.js +2 -0
- package/lib/components/teams/sceneTranscriptRules.d.ts +32 -1
- package/lib/components/teams/sceneTranscriptRules.js +104 -2
- package/lib/components/teams/transcript/RecordingLabel.d.ts +17 -0
- package/lib/components/teams/transcript/RecordingLabel.js +7 -0
- package/lib/components/teams/transcript/SequenceDiagram.d.ts +39 -0
- package/lib/components/teams/transcript/SequenceDiagram.js +190 -0
- package/lib/components/teams/transcript/TranscriptDetail.d.ts +27 -0
- package/lib/components/teams/transcript/TranscriptDetail.js +48 -0
- package/lib/components/teams/transcript/TranscriptTable.d.ts +23 -0
- package/lib/components/teams/transcript/TranscriptTable.js +112 -0
- package/lib/components/teams/transcript/TranscriptViews.d.ts +66 -0
- package/lib/components/teams/transcript/TranscriptViews.js +135 -0
- package/lib/components/teams/transcript/TranscriptViewsTypes.d.ts +13 -0
- package/lib/components/teams/transcript/TranscriptViewsTypes.js +5 -0
- package/lib/components/teams/transcript/index.d.ts +23 -0
- package/lib/components/teams/transcript/index.js +27 -0
- package/lib/components/teams/transcript/recordingPlayback.d.ts +52 -0
- package/lib/components/teams/transcript/recordingPlayback.js +146 -0
- package/lib/components/teams/transcript/selection.d.ts +59 -0
- package/lib/components/teams/transcript/selection.js +79 -0
- package/lib/components/teams/transcript/sequenceDiagramRules.d.ts +35 -0
- package/lib/components/teams/transcript/sequenceDiagramRules.js +158 -0
- package/lib/components/teams/transcript/transcriptDetailRules.d.ts +80 -0
- package/lib/components/teams/transcript/transcriptDetailRules.js +208 -0
- package/lib/components/teams/transcript/transcriptExport.d.ts +31 -0
- package/lib/components/teams/transcript/transcriptExport.js +82 -0
- package/lib/components/teams/transcript/transcriptRows.d.ts +76 -0
- package/lib/components/teams/transcript/transcriptRows.js +187 -0
- package/lib/components/teams/transcript/useSceneRecording.d.ts +45 -0
- package/lib/components/teams/transcript/useSceneRecording.js +96 -0
- package/lib/examples/ScenesExample.js +16 -3
- package/lib/portable/hosts/agentClient.d.ts +8 -0
- package/lib/portable/hosts/agentClient.js +2 -0
- package/lib/portable/hosts/approvalRenderers.d.ts +10 -2
- package/lib/portable/hosts/approvalRenderers.js +81 -2
- package/lib/portable/hosts/contracts.d.ts +1 -0
- package/lib/portable/hosts/contracts.js +2 -0
- package/lib/portable/hosts/contracts.json +56 -2
- package/lib/specs/actions.js +2 -0
- package/lib/specs/apps.d.ts +1 -0
- package/lib/specs/apps.js +219 -0
- package/lib/specs/sceneRecordings.d.ts +14 -0
- package/lib/specs/sceneRecordings.js +12 -0
- package/lib/specs/sceneSchema.js +11 -0
- package/lib/specs/scenes.d.ts +1 -0
- package/lib/specs/scenes.js +159 -0
- package/lib/types/scenes.d.ts +54 -0
- package/package.json +2 -1
- package/scripts/codegen/generate_mcp_servers.py +5 -16
- package/scripts/codegen/generate_scenes.py +80 -0
|
@@ -72,7 +72,7 @@ import { AppEmbed, embedAssistantCharacter } from './AppEmbed.js';
|
|
|
72
72
|
import { WINDOW_NOT_YET } from './embedSession.js';
|
|
73
73
|
import { EMBED_HOST_VARIABLES, EMBED_OBSERVED_ATTRIBUTES, EMBED_TAG, EMBED_TOKEN_NAMES_NO_DEPLOYMENT, EmbedAttributeError, adoptPropertiesSetEarly, embedLookOf, embedTokenDeployment, inlineHeightOf, languageOf, resumeOf, runnable, } from './embedConfig.js';
|
|
74
74
|
import { embedShadowCss } from './embedTheme.js';
|
|
75
|
-
import { DEFAULT_API, readVisitorApp } from './visitorApp.js';
|
|
75
|
+
import { DEFAULT_API, DEFAULT_INFERENCE, readVisitorApp } from './visitorApp.js';
|
|
76
76
|
export { runnable };
|
|
77
77
|
/** What the framed run page and the element say to each other. */
|
|
78
78
|
export const EMBED_MESSAGES = {
|
|
@@ -383,7 +383,11 @@ export function defineDatalayerAppElement(options = {}) {
|
|
|
383
383
|
// A public application, as a visitor without an account (D-07):
|
|
384
384
|
// an example kept warm or an address open to visitors, run on the
|
|
385
385
|
// visitors' runtime; a decision framed; a refusal said.
|
|
386
|
-
const visitor = await readVisitorApp({
|
|
386
|
+
const visitor = await readVisitorApp({
|
|
387
|
+
api: this.agents(),
|
|
388
|
+
inference: this.inference(),
|
|
389
|
+
app,
|
|
390
|
+
});
|
|
387
391
|
if (visitor.kind === 'decision') {
|
|
388
392
|
return { kind: 'frame', src: frameSrcOf(this.origin(), visitor.app) };
|
|
389
393
|
}
|
|
@@ -410,15 +414,26 @@ export function defineDatalayerAppElement(options = {}) {
|
|
|
410
414
|
}
|
|
411
415
|
/**
|
|
412
416
|
* ai-agents, where a visitor's address is read and beside which the
|
|
413
|
-
* visitors' runtime
|
|
414
|
-
* the
|
|
415
|
-
* on another plane.
|
|
417
|
+
* visitors' runtime answers: the `api` attribute, else the platform's,
|
|
418
|
+
* else the AI plane's (`DEFAULT_API`). Not Spacer's address (`api()`),
|
|
419
|
+
* which lives on another plane.
|
|
416
420
|
*/
|
|
417
421
|
agents() {
|
|
418
422
|
return (this.getAttribute('api') ||
|
|
419
423
|
coreStore.getState().configuration?.aiAgentsUrl ||
|
|
420
424
|
DEFAULT_API).replace(/\/+$/, '');
|
|
421
425
|
}
|
|
426
|
+
/**
|
|
427
|
+
* ai-inference, which mints a visitor's token: the `api` attribute, else
|
|
428
|
+
* the platform's, else the AI plane's (`DEFAULT_INFERENCE`) — never the
|
|
429
|
+
* control plane, where no ai-inference answers (28 October 2026: a bare
|
|
430
|
+
* `<datalayer-app app="…">` asked prod1 and got "Failed to fetch").
|
|
431
|
+
*/
|
|
432
|
+
inference() {
|
|
433
|
+
return (this.getAttribute('api') ||
|
|
434
|
+
coreStore.getState().configuration?.aiInferenceUrl ||
|
|
435
|
+
DEFAULT_INFERENCE).replace(/\/+$/, '');
|
|
436
|
+
}
|
|
422
437
|
/** Spacer, where an application is read with its embed token: the `api` attribute, else the platform's, else prod1's. */
|
|
423
438
|
api() {
|
|
424
439
|
return (this.getAttribute('api') ||
|
|
@@ -1,39 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A public application in the element, for a visitor without an account
|
|
3
|
-
* (D-07, R-30).
|
|
4
|
-
*
|
|
5
|
-
* `<datalayer-app app="…">` with no token names a public application. The
|
|
6
|
-
* element reads what it is without anybody's credentials, as the landing's
|
|
7
|
-
* hosted page does for whoever is signed out:
|
|
8
|
-
*
|
|
9
|
-
* - **an example Datalayer keeps warm for visitors** (`web-research`,
|
|
10
|
-
* `customer-interview`): its Appspec from the catalogue this bundle
|
|
11
|
-
* carries; the visitors' runtime answers its id;
|
|
12
|
-
* - **an application at its address** (`demo-accounting`): ai-agents'
|
|
13
|
-
* `GET /apps/deployments/at/<slug>` without a token says what its page is
|
|
14
|
-
* drawn from — the Appspec of the version it runs — and whether somebody
|
|
15
|
-
* signed out may talk to it (`session.opens`); the visitors' runtime
|
|
16
|
-
* answers `at:<slug>`, making the address's agent when first talked to —
|
|
17
|
-
* or, for a version with code of its own (`runs_code`), the runtime its
|
|
18
|
-
* deployment is kept on (`kept.url`), which runs that code;
|
|
19
|
-
* - **a decision**, named by its id (`01M…`): framed from Datalayer's run
|
|
20
|
-
* page, as before.
|
|
21
|
-
*
|
|
22
|
-
* The conversation then runs as the landing's signed-out one does: the chat
|
|
23
|
-
* mints the visitor's token itself from ai-inference (`useVisitorToken`,
|
|
24
|
-
* `POST /anonymous/token {app}`), minted again before it runs out, and talks
|
|
25
|
-
* to the visitors' runtime with it — in every mode, inline or floating.
|
|
26
|
-
*
|
|
27
|
-
* What a visitor may not have is said in one sentence, before anything is
|
|
28
|
-
* drawn (fail fast): a private address (ai-agents answers *No application is
|
|
29
|
-
* at this address*), one that acts through its owner's connections or
|
|
30
|
-
* documents (ai-agents' own reason), an example the visitors' runtime does
|
|
31
|
-
* not keep. Each says the embed token is what an embed of it takes.
|
|
32
|
-
*
|
|
33
|
-
* Pure but for the one request, given or `fetch`.
|
|
34
|
-
*
|
|
35
|
-
* @module apps/embed/visitorApp
|
|
36
|
-
*/
|
|
37
1
|
import type { AppSpec } from '../../types/agentspecs';
|
|
38
2
|
import type { DatalayerVisitors } from '../apps/visitorToken';
|
|
39
3
|
/** Where the visitors' runtime is published, on ai-agents' host (its chart). */
|
|
@@ -45,12 +9,21 @@ export declare const AT_PREFIX = "at:";
|
|
|
45
9
|
/**
|
|
46
10
|
* Datalayer's services for a visitor, where the element names none (`api`)
|
|
47
11
|
* and the platform's configuration says none: ai-agents, where an address is
|
|
48
|
-
* read, and beside it the visitors' runtime
|
|
49
|
-
*
|
|
50
|
-
* embed token: the two live on different
|
|
51
|
-
* prod1), found 15 October 2026 on
|
|
12
|
+
* read, and beside it the visitors' runtime — the AI plane, as core's plane
|
|
13
|
+
* table says it, never a literal of this bundle's own. Not Spacer's address,
|
|
14
|
+
* which reads an application with its embed token: the two live on different
|
|
15
|
+
* planes (ai-agents on r1, Spacer on prod1), found 15 October 2026 on
|
|
16
|
+
* datalayer.ai's embed; a bundle whose literal still said prod1 failed to
|
|
17
|
+
* mint a visitor's token there on 28 October 2026 ("Failed to fetch"),
|
|
18
|
+
* ai-inference being on r1 with the agents that call it.
|
|
19
|
+
*/
|
|
20
|
+
export declare const DEFAULT_API: string;
|
|
21
|
+
/**
|
|
22
|
+
* ai-inference, which mints a visitor's token, where the element names none
|
|
23
|
+
* (`api`) and the platform's configuration says none: the AI plane, as core's
|
|
24
|
+
* plane table says it.
|
|
52
25
|
*/
|
|
53
|
-
export declare const
|
|
26
|
+
export declare const DEFAULT_INFERENCE: string;
|
|
54
27
|
/** An application's id on Datalayer: a ULID. */
|
|
55
28
|
export declare const isAppUid: (value: string) => boolean;
|
|
56
29
|
/** What `app` with no token resolves to. */
|
|
@@ -74,9 +47,10 @@ export type VisitorApp =
|
|
|
74
47
|
/**
|
|
75
48
|
* Where a visitor's conversation with `app` runs: the visitors' runtime beside
|
|
76
49
|
* ai-agents — or `runtime`, the one a deployment with code of its own is
|
|
77
|
-
* kept on (R-30) — its token from ai-inference
|
|
50
|
+
* kept on (R-30) — its token from ai-inference, at `inference` when it is
|
|
51
|
+
* named, else beside ai-agents.
|
|
78
52
|
*/
|
|
79
|
-
export declare function visitorsAt(api: string, app: string, runtime?: string): DatalayerVisitors;
|
|
53
|
+
export declare function visitorsAt(api: string, app: string, runtime?: string, inference?: string): DatalayerVisitors;
|
|
80
54
|
/** What an embed without a token is told it takes. */
|
|
81
55
|
export declare const TOKEN_HINT = "Embedded for a visitor it refuses, it takes its embed token (the \"token\" attribute).";
|
|
82
56
|
/** The sentence for an example the visitors' runtime does not keep. */
|
|
@@ -87,13 +61,17 @@ export declare const refusedSentence: (reason: string) => string;
|
|
|
87
61
|
* Read what `app` is for a visitor without an account: a decision to frame,
|
|
88
62
|
* an example or an address to run on the visitors' runtime, or a sentence.
|
|
89
63
|
*
|
|
90
|
-
* @param api - Datalayer's services (ai-agents, ai-inference
|
|
64
|
+
* @param api - Datalayer's services (ai-agents, and ai-inference unless
|
|
65
|
+
* `inference` names it): the `api` attribute; the AI plane unless given.
|
|
66
|
+
* @param inference - ai-inference, which mints the visitor's token: `api`
|
|
67
|
+
* when that is given, else the AI plane.
|
|
91
68
|
* @param app - The `app` attribute: a decision's id, an example's id or an address.
|
|
92
69
|
* @param fetcher - What asks ai-agents; `fetch` unless given.
|
|
93
70
|
* @param catalogue - The examples; the bundle's catalogue unless given.
|
|
94
71
|
*/
|
|
95
|
-
export declare function readVisitorApp({ api, app, fetcher, catalogue, }: {
|
|
72
|
+
export declare function readVisitorApp({ api, inference, app, fetcher, catalogue, }: {
|
|
96
73
|
api?: string;
|
|
74
|
+
inference?: string;
|
|
97
75
|
app: string;
|
|
98
76
|
fetcher?: typeof fetch;
|
|
99
77
|
catalogue?: (ref: string) => AppSpec | undefined;
|
|
@@ -2,6 +2,43 @@
|
|
|
2
2
|
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* A public application in the element, for a visitor without an account
|
|
7
|
+
* (D-07, R-30).
|
|
8
|
+
*
|
|
9
|
+
* `<datalayer-app app="…">` with no token names a public application. The
|
|
10
|
+
* element reads what it is without anybody's credentials, as the landing's
|
|
11
|
+
* hosted page does for whoever is signed out:
|
|
12
|
+
*
|
|
13
|
+
* - **an example Datalayer keeps warm for visitors** (`web-research`,
|
|
14
|
+
* `customer-interview`): its Appspec from the catalogue this bundle
|
|
15
|
+
* carries; the visitors' runtime answers its id;
|
|
16
|
+
* - **an application at its address** (`demo-accounting`): ai-agents'
|
|
17
|
+
* `GET /apps/deployments/at/<slug>` without a token says what its page is
|
|
18
|
+
* drawn from — the Appspec of the version it runs — and whether somebody
|
|
19
|
+
* signed out may talk to it (`session.opens`); the visitors' runtime
|
|
20
|
+
* answers `at:<slug>`, making the address's agent when first talked to —
|
|
21
|
+
* or, for a version with code of its own (`runs_code`), the runtime its
|
|
22
|
+
* deployment is kept on (`kept.url`), which runs that code;
|
|
23
|
+
* - **a decision**, named by its id (`01M…`): framed from Datalayer's run
|
|
24
|
+
* page, as before.
|
|
25
|
+
*
|
|
26
|
+
* The conversation then runs as the landing's signed-out one does: the chat
|
|
27
|
+
* mints the visitor's token itself from ai-inference (`useVisitorToken`,
|
|
28
|
+
* `POST /anonymous/token {app}`), minted again before it runs out, and talks
|
|
29
|
+
* to the visitors' runtime with it — in every mode, inline or floating.
|
|
30
|
+
*
|
|
31
|
+
* What a visitor may not have is said in one sentence, before anything is
|
|
32
|
+
* drawn (fail fast): a private address (ai-agents answers *No application is
|
|
33
|
+
* at this address*), one that acts through its owner's connections or
|
|
34
|
+
* documents (ai-agents' own reason), an example the visitors' runtime does
|
|
35
|
+
* not keep. Each says the embed token is what an embed of it takes.
|
|
36
|
+
*
|
|
37
|
+
* Pure but for the one request, given or `fetch`.
|
|
38
|
+
*
|
|
39
|
+
* @module apps/embed/visitorApp
|
|
40
|
+
*/
|
|
41
|
+
import { DEFAULT_PLANE_URLS } from '@datalayer/core/lib/config/planes.js';
|
|
5
42
|
import { getApp } from '../../specs/apps.js';
|
|
6
43
|
import { parseAppspec } from '../apps/appspec.js';
|
|
7
44
|
import { runnable } from './embedConfig.js';
|
|
@@ -17,12 +54,21 @@ export const AT_PREFIX = 'at:';
|
|
|
17
54
|
/**
|
|
18
55
|
* Datalayer's services for a visitor, where the element names none (`api`)
|
|
19
56
|
* and the platform's configuration says none: ai-agents, where an address is
|
|
20
|
-
* read, and beside it the visitors' runtime
|
|
21
|
-
*
|
|
22
|
-
* embed token: the two live on different
|
|
23
|
-
* prod1), found 15 October 2026 on
|
|
57
|
+
* read, and beside it the visitors' runtime — the AI plane, as core's plane
|
|
58
|
+
* table says it, never a literal of this bundle's own. Not Spacer's address,
|
|
59
|
+
* which reads an application with its embed token: the two live on different
|
|
60
|
+
* planes (ai-agents on r1, Spacer on prod1), found 15 October 2026 on
|
|
61
|
+
* datalayer.ai's embed; a bundle whose literal still said prod1 failed to
|
|
62
|
+
* mint a visitor's token there on 28 October 2026 ("Failed to fetch"),
|
|
63
|
+
* ai-inference being on r1 with the agents that call it.
|
|
64
|
+
*/
|
|
65
|
+
export const DEFAULT_API = DEFAULT_PLANE_URLS.aiAgentsUrl;
|
|
66
|
+
/**
|
|
67
|
+
* ai-inference, which mints a visitor's token, where the element names none
|
|
68
|
+
* (`api`) and the platform's configuration says none: the AI plane, as core's
|
|
69
|
+
* plane table says it.
|
|
24
70
|
*/
|
|
25
|
-
export const
|
|
71
|
+
export const DEFAULT_INFERENCE = DEFAULT_PLANE_URLS.aiInferenceUrl;
|
|
26
72
|
/** An application's id on Datalayer: a ULID. */
|
|
27
73
|
export const isAppUid = (value) => /^[0-9A-HJKMNP-TV-Z]{26}$/.test(value);
|
|
28
74
|
/** An address, as ai-agents spells one. */
|
|
@@ -30,14 +76,15 @@ const SLUG = /^[a-z0-9][a-z0-9-]{0,62}$/;
|
|
|
30
76
|
/**
|
|
31
77
|
* Where a visitor's conversation with `app` runs: the visitors' runtime beside
|
|
32
78
|
* ai-agents — or `runtime`, the one a deployment with code of its own is
|
|
33
|
-
* kept on (R-30) — its token from ai-inference
|
|
79
|
+
* kept on (R-30) — its token from ai-inference, at `inference` when it is
|
|
80
|
+
* named, else beside ai-agents.
|
|
34
81
|
*/
|
|
35
|
-
export function visitorsAt(api, app, runtime) {
|
|
82
|
+
export function visitorsAt(api, app, runtime, inference) {
|
|
36
83
|
const base = api.replace(/\/+$/, '');
|
|
37
84
|
return {
|
|
38
85
|
url: runtime ? runtime.replace(/\/+$/, '') : `${base}${VISITORS_PATH}`,
|
|
39
86
|
app,
|
|
40
|
-
inferenceUrl: base,
|
|
87
|
+
inferenceUrl: (inference || base).replace(/\/+$/, ''),
|
|
41
88
|
};
|
|
42
89
|
}
|
|
43
90
|
/** What an embed without a token is told it takes. */
|
|
@@ -50,12 +97,17 @@ export const refusedSentence = (reason) => `datalayer-app: ${reason.trim().repla
|
|
|
50
97
|
* Read what `app` is for a visitor without an account: a decision to frame,
|
|
51
98
|
* an example or an address to run on the visitors' runtime, or a sentence.
|
|
52
99
|
*
|
|
53
|
-
* @param api - Datalayer's services (ai-agents, ai-inference
|
|
100
|
+
* @param api - Datalayer's services (ai-agents, and ai-inference unless
|
|
101
|
+
* `inference` names it): the `api` attribute; the AI plane unless given.
|
|
102
|
+
* @param inference - ai-inference, which mints the visitor's token: `api`
|
|
103
|
+
* when that is given, else the AI plane.
|
|
54
104
|
* @param app - The `app` attribute: a decision's id, an example's id or an address.
|
|
55
105
|
* @param fetcher - What asks ai-agents; `fetch` unless given.
|
|
56
106
|
* @param catalogue - The examples; the bundle's catalogue unless given.
|
|
57
107
|
*/
|
|
58
|
-
export async function readVisitorApp({ api
|
|
108
|
+
export async function readVisitorApp({ api, inference, app, fetcher = fetch, catalogue = getApp, }) {
|
|
109
|
+
const agents = api || DEFAULT_API;
|
|
110
|
+
const mints = inference || api || DEFAULT_INFERENCE;
|
|
59
111
|
const named = app.trim();
|
|
60
112
|
if (isAppUid(named)) {
|
|
61
113
|
return { kind: 'decision', app: named };
|
|
@@ -71,7 +123,7 @@ export async function readVisitorApp({ api = DEFAULT_API, app, fetcher = fetch,
|
|
|
71
123
|
return {
|
|
72
124
|
kind: 'visitors',
|
|
73
125
|
app: runnable({ app: example, problems: [] }),
|
|
74
|
-
visitors: visitorsAt(
|
|
126
|
+
visitors: visitorsAt(agents, example.id, undefined, mints),
|
|
75
127
|
};
|
|
76
128
|
}
|
|
77
129
|
if (!SLUG.test(named)) {
|
|
@@ -82,7 +134,7 @@ export async function readVisitorApp({ api = DEFAULT_API, app, fetcher = fetch,
|
|
|
82
134
|
}
|
|
83
135
|
let response;
|
|
84
136
|
try {
|
|
85
|
-
response = await fetcher(`${
|
|
137
|
+
response = await fetcher(`${agents.replace(/\/+$/, '')}/api/ai-agents/v1/apps/deployments/at/${encodeURIComponent(named)}`);
|
|
86
138
|
}
|
|
87
139
|
catch (error) {
|
|
88
140
|
return {
|
|
@@ -117,7 +169,7 @@ export async function readVisitorApp({ api = DEFAULT_API, app, fetcher = fetch,
|
|
|
117
169
|
return {
|
|
118
170
|
kind: 'visitors',
|
|
119
171
|
app: runnable({ app: { ...parsed.app, name }, problems: parsed.problems }),
|
|
120
|
-
visitors: visitorsAt(
|
|
172
|
+
visitors: visitorsAt(agents, `${AT_PREFIX}${named}`, runtime.url, mints),
|
|
121
173
|
};
|
|
122
174
|
}
|
|
123
175
|
/**
|
|
@@ -21,114 +21,38 @@
|
|
|
21
21
|
*
|
|
22
22
|
* A member's connections — the MCP servers it reaches, Odoo for Accounting —
|
|
23
23
|
* stand to its right, each a node half a member's size with the server's mark
|
|
24
|
-
* (`SpecMark`), linked to it by an edge of its own
|
|
25
|
-
* the member calls one of the connection's tools
|
|
26
|
-
* connection for as long as the call runs
|
|
27
|
-
*
|
|
24
|
+
* (`SpecMark`), linked to it by an edge of its own, `MCP`, drawn as the A2A
|
|
25
|
+
* link is: still until the member calls one of the connection's tools, then
|
|
26
|
+
* flowing toward the connection for as long as the call runs
|
|
27
|
+
* ({@link A2ATeamCall}), `MCP · list invoices`, and back with its result for
|
|
28
|
+
* a moment, `MCP · Odoo answers` (a screen reader hears who calls whom);
|
|
29
|
+
* under reduced motion, the arrow and the words alone.
|
|
28
30
|
*
|
|
29
31
|
* The graph is a picture, not an editor: nothing is dragged, panned or
|
|
30
32
|
* zoomed, and the wheel scrolls the page. Its viewport is worked out from its
|
|
31
33
|
* box, so it fits a phone as it fits a desk.
|
|
32
34
|
*
|
|
35
|
+
* How it is drawn is its *backdrop* (`backdrop`, the scene's
|
|
36
|
+
* `stage.backdrop`; {@link SceneBackdrop}): `studio`, the drawing above —
|
|
37
|
+
* characters, balloons, flowing edges — `hero`, faces on a deep tint with
|
|
38
|
+
* a dot that flies with each message, or `plain`, boxes and arrows that do
|
|
39
|
+
* not move. The graph works out the same things for every backdrop — who
|
|
40
|
+
* stands where, which way each link carries a message, which connection
|
|
41
|
+
* answers a call, the words a screen reader hears — and reads the node
|
|
42
|
+
* types, the edge types, the colours and the layout from the backdrop.
|
|
43
|
+
*
|
|
33
44
|
* @module components/teams/A2ATeamGraph
|
|
34
45
|
*/
|
|
35
|
-
import type { AssistantModel3D } from '../../chat/assistant/avatar3dModel';
|
|
36
46
|
import type { JSX } from 'react';
|
|
37
|
-
import { type
|
|
47
|
+
import { type Viewport } from '@xyflow/react';
|
|
38
48
|
import '@xyflow/react/dist/base.css';
|
|
39
|
-
import { type AssistantAbout } from '../../chat/assistant/AssistantStage';
|
|
40
|
-
import type { BalloonSuggestion } from '../../chat/assistant/SpeechBalloon';
|
|
41
|
-
import type { DisplayItem } from '../../types/chat';
|
|
42
|
-
import type { AssistantMenuItem } from '../../chat/assistant/AssistantContextMenu';
|
|
43
|
-
import type { AssistantSandbox } from '../../chat/assistant/assistantDetails';
|
|
44
|
-
import type { OtelLiveTracer } from '@datalayer/core/lib/otel/live';
|
|
45
49
|
import { type A2ATeamCall, type A2ATeamConnection, type A2ATeamFlow } from './a2aTeamFlow';
|
|
46
|
-
import type {
|
|
47
|
-
import type {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
export
|
|
51
|
-
|
|
52
|
-
name: string;
|
|
53
|
-
emoji?: string;
|
|
54
|
-
/** Its avatar, as its Appspec's `interface.avatar` names it: an id, or a 3D model. */
|
|
55
|
-
character: string | AssistantModel3D;
|
|
56
|
-
/** Where it runs, in a few words: "in your browser", "on a runtime". */
|
|
57
|
-
where: string;
|
|
58
|
-
persona: A2ATeamPersona;
|
|
59
|
-
/** A click on the character. */
|
|
60
|
-
onToggle?: () => void;
|
|
61
|
-
/** It was sent away, or called back. */
|
|
62
|
-
onAway?: (away: boolean) => void;
|
|
63
|
-
/** The MCP servers it reaches, drawn to its right (`teamConnectionsOf`). */
|
|
64
|
-
connections?: A2ATeamConnection[];
|
|
65
|
-
/**
|
|
66
|
-
* How its balloon shows what it says (T-23): only what it says or
|
|
67
|
-
* does now (`current`, a team's default) — the words, the tool it calls,
|
|
68
|
-
* a notebook it was given — or a peek (`history`).
|
|
69
|
-
*/
|
|
70
|
-
balloonDisplay?: BalloonDisplay;
|
|
71
|
-
/**
|
|
72
|
-
* The notebook in its balloon was clicked: by default, it is expanded —
|
|
73
|
-
* into `expandTarget`, scrolled to and focused, or in a dialog.
|
|
74
|
-
*/
|
|
75
|
-
onNotebookOpen?: () => void;
|
|
76
|
-
/**
|
|
77
|
-
* Where the notebook it was given runs (`TeamNotebook`, editable, on the
|
|
78
|
-
* browser sandbox): an element of the page — the area under the graph —
|
|
79
|
-
* where it is drawn as it arrives and when it is expanded; without one,
|
|
80
|
-
* *Expand* opens it in a dialog over the page.
|
|
81
|
-
*/
|
|
82
|
-
expandTarget?: BalloonExpandTarget;
|
|
83
|
-
/** What its notebook is called: `Accounting's notebook`. */
|
|
84
|
-
notebookTitle?: string;
|
|
85
|
-
/**
|
|
86
|
-
* What the person may ask it: chips in its balloon while it waits for a
|
|
87
|
-
* question, and a group of its menu; one chosen is sent (`onSuggestion`).
|
|
88
|
-
*/
|
|
89
|
-
suggestions?: readonly BalloonSuggestion[];
|
|
90
|
-
onSuggestion?: (suggestion: BalloonSuggestion) => void;
|
|
91
|
-
/**
|
|
92
|
-
* The team's Agent Inspector's tracer: its menu offers *Inspect the
|
|
93
|
-
* agent…*, its own spans (what it did, and the A2A requests sent to it).
|
|
94
|
-
*/
|
|
95
|
-
inspector?: OtelLiveTracer | null;
|
|
96
|
-
/** Stops its turn, from its menu, while it works. */
|
|
97
|
-
onStop?: () => void;
|
|
98
|
-
/** What its menu's *About* and *Agent Details…* say. */
|
|
99
|
-
about?: AssistantAbout;
|
|
100
|
-
/**
|
|
101
|
-
* Its code sandbox, for *Code Sandbox Details…*. The entry — the agent in
|
|
102
|
-
* the page — has the kernel of the notebook open under the graph, while
|
|
103
|
-
* one is.
|
|
104
|
-
*/
|
|
105
|
-
sandbox?: AssistantSandbox;
|
|
106
|
-
/** The host's own entries of its menu. */
|
|
107
|
-
contextMenu?: readonly AssistantMenuItem[];
|
|
108
|
-
/**
|
|
109
|
-
* What its menu calls a click on it (`onToggle`): `Ask Sales` where it
|
|
110
|
-
* takes the person to the composer. Without `onToggle`, its menu has no
|
|
111
|
-
* such entry.
|
|
112
|
-
*/
|
|
113
|
-
conversationLabel?: string;
|
|
114
|
-
/**
|
|
115
|
-
* What it said and did, as its `history` balloon lists it (`useA2ATeam`'s
|
|
116
|
-
* `entryHistory`, `peerHistory`): shown when its menu chooses *History*.
|
|
117
|
-
*/
|
|
118
|
-
history?: readonly DisplayItem[];
|
|
119
|
-
/** Its balloon's display was chosen in its menu: the page may keep it. */
|
|
120
|
-
onBalloonDisplayChange?: (display: BalloonDisplay) => void;
|
|
121
|
-
};
|
|
122
|
-
/** Who talks to whom over A2A: an edge of the graph. */
|
|
123
|
-
export type A2ATeamGraphLink = {
|
|
124
|
-
from: string;
|
|
125
|
-
to: string;
|
|
126
|
-
};
|
|
127
|
-
/** Where a member stands: fractions of the box, as a scene's stage says. */
|
|
128
|
-
export type A2ATeamGraphPosition = {
|
|
129
|
-
x: number;
|
|
130
|
-
y: number;
|
|
131
|
-
};
|
|
50
|
+
import type { A2ATeamGraphLink, A2ATeamGraphMember, A2ATeamGraphPosition, SceneBackdropId } from './backdrops/types';
|
|
51
|
+
import type { SelectedEdge } from './transcript/selection';
|
|
52
|
+
export type { A2ATeamGraphLink, A2ATeamGraphMember, A2ATeamGraphPosition, } from './backdrops/types';
|
|
53
|
+
export { MEMBER_HANDLES, clampOffset, connectionDetails, connectionLabel, memberLabel, type MemberBounds, type MemberOffset, } from './backdrops/nodes';
|
|
54
|
+
export { arrowPath } from './backdrops/edges';
|
|
55
|
+
export { CallEdge, LinkEdge, MemberNode, ConnectionNode, } from './backdrops/studio';
|
|
132
56
|
export type A2ATeamGraphProps = {
|
|
133
57
|
/** The member that asks: drawn on the left. */
|
|
134
58
|
entry: A2ATeamGraphMember;
|
|
@@ -164,25 +88,32 @@ export type A2ATeamGraphProps = {
|
|
|
164
88
|
* The least room above the members for their balloons, in pixels at full
|
|
165
89
|
* scale: the graph keeps what its balloons take now (`useBalloonRoom`) —
|
|
166
90
|
* suggestions, *more* unfolded — and never less than this. A notebook in
|
|
167
|
-
* a balloon gets at least its own.
|
|
91
|
+
* a balloon gets at least its own. Unsaid, the backdrop's.
|
|
168
92
|
*/
|
|
169
93
|
balloonRoom?: number;
|
|
94
|
+
/**
|
|
95
|
+
* How the stage is drawn (`SceneStageSpec.backdrop`): `studio`, the
|
|
96
|
+
* drawing every scene had first, `hero` or `plain`. `studio` when unsaid,
|
|
97
|
+
* and for an id the graph does not know.
|
|
98
|
+
*/
|
|
99
|
+
backdrop?: SceneBackdropId;
|
|
100
|
+
/**
|
|
101
|
+
* The exchange selected in the transcript, as the edge it is on
|
|
102
|
+
* (`selectedEdgeOf`, SCENES S3-02): drawn with a halo on every backdrop —
|
|
103
|
+
* the edge by its id, or by its ends either way, since an answer travels
|
|
104
|
+
* the asker's edge back.
|
|
105
|
+
*/
|
|
106
|
+
selected?: SelectedEdge | null;
|
|
107
|
+
/**
|
|
108
|
+
* An edge was clicked: the page selects its latest exchange
|
|
109
|
+
* (`latestLineOnEdge`). With it, the edges take the pointer.
|
|
110
|
+
*/
|
|
111
|
+
onSelectEdge?: (edge: A2ATeamGraphEdge) => void;
|
|
170
112
|
};
|
|
171
|
-
/**
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
export declare const MEMBER_HANDLES: {
|
|
176
|
-
readonly inLeft: "in-left";
|
|
177
|
-
readonly outRight: "out-right";
|
|
178
|
-
readonly inTop: "in-top";
|
|
179
|
-
readonly outBottom: "out-bottom";
|
|
180
|
-
readonly inRight: "in-right";
|
|
181
|
-
readonly outLeft: "out-left";
|
|
182
|
-
readonly inBottom: "in-bottom";
|
|
183
|
-
readonly outTop: "out-top";
|
|
184
|
-
readonly connections: "connections";
|
|
185
|
-
};
|
|
113
|
+
/** An edge of the graph, as a click names it: `selectedEdgeOf`'s shape without the selection's key. */
|
|
114
|
+
export type A2ATeamGraphEdge = Omit<SelectedEdge, 'key'>;
|
|
115
|
+
/** Whether a selection is on the edge between two ends: by its id, or by its ends either way. */
|
|
116
|
+
export declare function edgeSelected(selected: SelectedEdge | null | undefined, from: string, to: string): boolean;
|
|
186
117
|
/**
|
|
187
118
|
* The handles for an edge from one place to another: rightward across,
|
|
188
119
|
* leftward across, or down or up when the other member is mostly below or
|
|
@@ -198,47 +129,22 @@ export declare function handlesBetween(from: {
|
|
|
198
129
|
sourceHandle: string;
|
|
199
130
|
targetHandle: string;
|
|
200
131
|
};
|
|
201
|
-
/** How far a member was moved from its place, in the graph's coordinates. */
|
|
202
|
-
export type MemberOffset = {
|
|
203
|
-
dx: number;
|
|
204
|
-
dy: number;
|
|
205
|
-
};
|
|
206
|
-
/** How far a member may move: its node stays inside the graph's box. */
|
|
207
|
-
export type MemberBounds = {
|
|
208
|
-
minDx: number;
|
|
209
|
-
maxDx: number;
|
|
210
|
-
minDy: number;
|
|
211
|
-
maxDy: number;
|
|
212
|
-
};
|
|
213
|
-
/** An offset kept inside its bounds. */
|
|
214
|
-
export declare function clampOffset(offset: MemberOffset, bounds: MemberBounds): MemberOffset;
|
|
215
|
-
/** A member's accessible name: its name, and where it runs. */
|
|
216
|
-
export declare function memberLabel(member: Pick<A2ATeamGraphMember, 'name' | 'where'>): string;
|
|
217
|
-
/** A connection's accessible name: `Odoo, Accounting's MCP connection`. */
|
|
218
|
-
export declare function connectionLabel(connection: Pick<A2ATeamConnection, 'label'>, member: string | undefined): string;
|
|
219
|
-
/** What a connection's details say: the server, who reaches it, and the call running now. */
|
|
220
|
-
export declare function connectionDetails(connection: Pick<A2ATeamConnection, 'name' | 'tools'>, member: string | undefined, calling?: string): string;
|
|
221
132
|
/** The words on the edge for a flow. */
|
|
222
133
|
export declare function flowWords(flow: A2ATeamFlow, entry: string, peer: string): string;
|
|
134
|
+
/** What a link to a connection says at rest, as `A2A` says the members' link. */
|
|
135
|
+
export declare const MCP_LABEL = "MCP";
|
|
223
136
|
/**
|
|
224
|
-
*
|
|
225
|
-
* the
|
|
137
|
+
* What a link to a connection says while it carries a call, short enough
|
|
138
|
+
* for the room beside the member: the tool going out, `MCP · list invoices`,
|
|
139
|
+
* then `MCP · Odoo answers` as its result comes back.
|
|
226
140
|
*/
|
|
227
|
-
export declare function
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
type CallData = {
|
|
235
|
-
/** The tool being called, in words (`list invoices`); empty while none is. */
|
|
236
|
-
calling: string;
|
|
237
|
-
};
|
|
238
|
-
/** A member's link to a connection: still, or flowing toward it while a call runs. */
|
|
239
|
-
export declare const CallEdge: import("react").NamedExoticComponent<EdgeProps<Edge<CallData>>>;
|
|
240
|
-
/** What a member's call says, on its edge and to a screen reader. */
|
|
241
|
-
export declare function callWords(member: string, connection: A2ATeamConnection, tool: string): string;
|
|
141
|
+
export declare function callEdgeWords(connection: A2ATeamConnection, tool: string, flow: A2ATeamFlow): string;
|
|
142
|
+
/**
|
|
143
|
+
* What a member's call says, on its edge and to a screen reader: the call
|
|
144
|
+
* going out, `Accounting calls Odoo · list invoices`, then its result
|
|
145
|
+
* coming back, `Odoo answers Accounting · list invoices`.
|
|
146
|
+
*/
|
|
147
|
+
export declare function callWords(member: string, connection: A2ATeamConnection, tool: string, flow?: A2ATeamFlow): string;
|
|
242
148
|
/** The viewport that shows a graph `drawn` wide whole in a box `width` wide, never larger than drawn. */
|
|
243
149
|
export declare function teamViewport(width: number, drawn?: number): Viewport;
|
|
244
150
|
/** Where a member is laid out: its column and row, from the positions or the default. */
|
|
@@ -260,5 +166,5 @@ export declare function placeMembers(entryId: string, peerIds: readonly string[]
|
|
|
260
166
|
/** The one flow the graph reports for all its edges: asking before answering before still. */
|
|
261
167
|
export declare function flowOfAll(flows: readonly A2ATeamFlow[]): A2ATeamFlow;
|
|
262
168
|
/** Draw a team over A2A, each link moving with what travels on it. */
|
|
263
|
-
export declare function A2ATeamGraph({ entry, peer, peers: more, flow, flows, connected, label, labels, links, positions, size, calls, balloonRoom, }: A2ATeamGraphProps): JSX.Element;
|
|
169
|
+
export declare function A2ATeamGraph({ entry, peer, peers: more, flow, flows, connected, label, labels, links, positions, size, calls, balloonRoom, backdrop, selected, onSelectEdge, }: A2ATeamGraphProps): JSX.Element;
|
|
264
170
|
export default A2ATeamGraph;
|