@datalayer/agent-runtimes 1.3.113 → 1.4.0
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/chunks/{ChatView-D41Nx5rC.js → ChatView-BpKZPdcp.js} +4 -4
- package/dist-embed/datalayer-app-main.js +150 -150
- package/lib/apps/apps/appspec.d.ts +13 -0
- package/lib/apps/apps/appspec.js +125 -0
- package/lib/apps/apps/checks.d.ts +1 -1
- package/lib/apps/apps/checks.js +2 -2
- package/lib/apps/apps/customComponents.js +1 -1
- package/lib/apps/core/canvasBlocks.d.ts +3 -3
- package/lib/apps/core/canvasParts.d.ts +6 -4
- package/lib/apps/embed/AppEmbed.js +3 -7
- package/lib/apps/embed/embedSession.d.ts +8 -4
- package/lib/apps/embed/embedSession.js +16 -9
- package/lib/apps/plugins/a2ui-surface/AnswerShows.d.ts +21 -0
- package/lib/apps/plugins/a2ui-surface/AnswerShows.js +29 -0
- package/lib/apps/plugins/a2ui-surface/SurfaceToolResult.js +4 -7
- package/lib/apps/plugins/a2ui-surface/index.d.ts +2 -1
- package/lib/apps/plugins/a2ui-surface/index.js +10 -1
- package/lib/apps/plugins/a2ui-surface/toolResult.d.ts +20 -11
- package/lib/apps/plugins/a2ui-surface/toolResult.js +27 -11
- package/lib/apps/plugins/app-components/index.d.ts +1 -1
- package/lib/apps/plugins/app-components/index.js +2 -2
- package/lib/apps/plugins/app-elements/AppElements.d.ts +3 -3
- package/lib/apps/plugins/app-elements/AppElements.js +5 -20
- package/lib/apps/plugins/app-elements/QuestionView.d.ts +28 -0
- package/lib/apps/plugins/app-elements/QuestionView.js +57 -0
- package/lib/apps/plugins/app-elements/index.d.ts +7 -4
- package/lib/apps/plugins/app-elements/index.js +14 -5
- package/lib/apps/plugins/canvas-blocks/index.d.ts +13 -13
- package/lib/apps/plugins/canvas-blocks/index.js +24 -24
- package/lib/apps/plugins/canvas-parts/index.d.ts +7 -1
- package/lib/apps/plugins/canvas-parts/index.js +36 -0
- package/lib/apps/plugins/chat/ChatView.js +7 -0
- package/lib/chat/base/ChatBase.js +234 -43
- package/lib/chat/base/loopElement.d.ts +16 -17
- package/lib/chat/base/loopElement.js +11 -27
- package/lib/chat/base/loopStep.d.ts +15 -15
- package/lib/chat/base/loopStep.js +10 -13
- package/lib/chat/base/loopWindow.d.ts +15 -20
- package/lib/chat/base/loopWindow.js +26 -27
- package/lib/chat/base/uiOps.d.ts +96 -0
- package/lib/chat/base/uiOps.js +251 -0
- package/lib/chat/messages/ChatMessageList.d.ts +8 -1
- package/lib/chat/messages/ChatMessageList.js +4 -4
- package/lib/components/a2ui/datalayer/Chart.d.ts +1 -1
- package/lib/components/a2ui/datalayer/schema.js +1 -1
- package/lib/components/teams/AnswerSurfaces.d.ts +3 -2
- package/lib/components/teams/AnswerSurfaces.js +7 -7
- package/lib/components/teams/useA2ATeam.d.ts +1 -1
- package/lib/config/AgentConfiguration.d.ts +1 -1
- package/lib/protocols/AGUIAdapter.d.ts +7 -0
- package/lib/protocols/AGUIAdapter.js +43 -3
- package/lib/protocols/agentic-commerce/index.d.ts +5 -9
- package/lib/protocols/agentic-commerce/index.js +6 -10
- package/lib/protocols/commerce.d.ts +8 -9
- package/lib/protocols/commerce.js +29 -0
- package/lib/protocols/ucp/index.d.ts +5 -10
- package/lib/protocols/ucp/index.js +6 -11
- package/lib/specs/actions.d.ts +8 -0
- package/lib/specs/actions.js +56 -0
- package/lib/specs/agents/agents.js +338 -169
- package/lib/specs/apps.d.ts +1 -0
- package/lib/specs/apps.js +272 -0
- package/lib/specs/appspecSchema.js +125 -0
- package/lib/specs/cogs.js +6 -3
- package/lib/specs/index.d.ts +2 -1
- package/lib/specs/index.js +2 -1
- package/lib/specs/protocols.d.ts +24 -0
- package/lib/specs/protocols.js +197 -0
- package/lib/specs/ui.d.ts +21 -0
- package/lib/specs/{uiPlugins.js → ui.js} +14 -14
- package/lib/types/agentspecs.d.ts +72 -5
- package/lib/types/messages.d.ts +7 -0
- package/lib/types/protocol.d.ts +8 -0
- package/package.json +2 -2
- package/scripts/codegen/generate_agents.py +43 -8
- package/scripts/codegen/generate_apps.py +38 -1
- package/scripts/codegen/generate_protocols.py +207 -0
- package/scripts/codegen/generate_sandbox_agents.py +1 -1
- package/scripts/codegen/{generate_ui_plugins.py → generate_ui.py} +40 -40
- package/scripts/gen_workers.py +2 -2
- package/lib/chat/base/loopMessage.d.ts +0 -37
- package/lib/chat/base/loopMessage.js +0 -37
- package/lib/specs/uiPlugins.d.ts +0 -21
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
export const A2A_PROTOCOL_0_0_1 = {
|
|
6
|
+
id: 'a2a',
|
|
7
|
+
version: '0.0.1',
|
|
8
|
+
name: 'Agent2Agent',
|
|
9
|
+
description: "How agents talk to agents: teams and scenes talk over it, an application's route serves it, and its Agent Card advertises its extensions.",
|
|
10
|
+
publisher: 'Google, now the Linux Foundation',
|
|
11
|
+
layer: 'transport',
|
|
12
|
+
specUrl: 'https://a2a-protocol.org',
|
|
13
|
+
specVersion: '1.0',
|
|
14
|
+
status: 'shipped',
|
|
15
|
+
connects: 'Other agents, each at its address with its Agent Card',
|
|
16
|
+
packages: {
|
|
17
|
+
python: ['fasta2a', 'a2a-sdk'],
|
|
18
|
+
typescript: ['@a2a-js/sdk'],
|
|
19
|
+
},
|
|
20
|
+
protocolTools: [],
|
|
21
|
+
appspecBlock: 'a2a',
|
|
22
|
+
};
|
|
23
|
+
export const A2UI_PROTOCOL_0_0_1 = {
|
|
24
|
+
id: 'a2ui',
|
|
25
|
+
version: '0.0.1',
|
|
26
|
+
name: 'A2UI',
|
|
27
|
+
description: "How an agent's answer becomes an interface: components the host renders from a declarative surface.",
|
|
28
|
+
publisher: 'Google',
|
|
29
|
+
layer: 'ui',
|
|
30
|
+
specUrl: 'https://a2ui.org',
|
|
31
|
+
specVersion: '0.9',
|
|
32
|
+
status: 'shipped',
|
|
33
|
+
connects: 'The person, through components an answer draws',
|
|
34
|
+
packages: {
|
|
35
|
+
python: ['agent-runtimes'],
|
|
36
|
+
typescript: ['@a2ui/react', '@a2ui/web_core'],
|
|
37
|
+
},
|
|
38
|
+
protocolTools: [],
|
|
39
|
+
};
|
|
40
|
+
export const ACP_PROTOCOL_0_0_1 = {
|
|
41
|
+
id: 'acp',
|
|
42
|
+
version: '0.0.1',
|
|
43
|
+
name: 'Agentic Commerce Protocol',
|
|
44
|
+
description: 'Checkout sessions at a seller, completed with a delegated payment token the model never sees. Planned in applications: the client exists, purchases wait on a source of payment tokens.',
|
|
45
|
+
publisher: 'OpenAI, Stripe',
|
|
46
|
+
layer: 'commerce',
|
|
47
|
+
specUrl: 'https://github.com/agentic-commerce-protocol/agentic-commerce-protocol',
|
|
48
|
+
specVersion: '2026-04-17',
|
|
49
|
+
status: 'planned',
|
|
50
|
+
connects: 'Sellers, to check out with a delegated payment',
|
|
51
|
+
packages: {
|
|
52
|
+
python: ['agent-runtimes'],
|
|
53
|
+
typescript: ['@datalayer/agent-runtimes'],
|
|
54
|
+
},
|
|
55
|
+
protocolTools: ['agentic-commerce'],
|
|
56
|
+
};
|
|
57
|
+
export const AG_UI_PROTOCOL_0_0_1 = {
|
|
58
|
+
id: 'ag-ui',
|
|
59
|
+
version: '0.0.1',
|
|
60
|
+
name: 'AG-UI',
|
|
61
|
+
description: 'How an agent streams its run to a page: messages, tool calls and state as events.',
|
|
62
|
+
publisher: 'CopilotKit',
|
|
63
|
+
layer: 'ui',
|
|
64
|
+
specUrl: 'https://docs.ag-ui.com',
|
|
65
|
+
specVersion: '0.0.57 (@ag-ui/core)',
|
|
66
|
+
status: 'shipped',
|
|
67
|
+
connects: 'The page a person talks to the agent on',
|
|
68
|
+
packages: {
|
|
69
|
+
python: ['ag-ui-protocol'],
|
|
70
|
+
typescript: ['@ag-ui/client', '@ag-ui/core'],
|
|
71
|
+
},
|
|
72
|
+
protocolTools: [],
|
|
73
|
+
};
|
|
74
|
+
export const MCP_PROTOCOL_0_0_1 = {
|
|
75
|
+
id: 'mcp',
|
|
76
|
+
version: '0.0.1',
|
|
77
|
+
name: 'Model Context Protocol',
|
|
78
|
+
description: 'How an agent calls tools and reads resources: clients and servers in both languages, and the MCP gateway every connection goes through.',
|
|
79
|
+
publisher: 'Anthropic',
|
|
80
|
+
layer: 'transport',
|
|
81
|
+
specUrl: 'https://modelcontextprotocol.io/specification',
|
|
82
|
+
specVersion: '2026-07-28 (Python), 2025-11-25 (TypeScript)',
|
|
83
|
+
status: 'shipped',
|
|
84
|
+
connects: 'Tools, resources and prompts served by MCP servers',
|
|
85
|
+
packages: {
|
|
86
|
+
python: ['mcp'],
|
|
87
|
+
typescript: ['@modelcontextprotocol/sdk', '@mcp-ui/client'],
|
|
88
|
+
},
|
|
89
|
+
protocolTools: [],
|
|
90
|
+
};
|
|
91
|
+
export const PACT_PROTOCOL_0_0_1 = {
|
|
92
|
+
id: 'pact',
|
|
93
|
+
version: '0.0.1',
|
|
94
|
+
name: 'Personal Agent Consent & Trust',
|
|
95
|
+
description: "A personal agent asking a business's agent over A2A, first as itself, then for a person who delegated some of their permissions.",
|
|
96
|
+
publisher: 'Decagon, Instinct',
|
|
97
|
+
layer: 'consent',
|
|
98
|
+
specUrl: 'https://openpactprotocol.org',
|
|
99
|
+
specVersion: '1.0',
|
|
100
|
+
status: 'shipped',
|
|
101
|
+
connects: "Businesses' agents, asked for a person with their delegation",
|
|
102
|
+
packages: {
|
|
103
|
+
python: ['agent-runtimes'],
|
|
104
|
+
typescript: ['@datalayer/agent-runtimes'],
|
|
105
|
+
},
|
|
106
|
+
protocolTools: ['pact'],
|
|
107
|
+
appspecBlock: 'pact',
|
|
108
|
+
};
|
|
109
|
+
export const PAP_PROTOCOL_0_0_1 = {
|
|
110
|
+
id: 'pap',
|
|
111
|
+
version: '0.0.1',
|
|
112
|
+
name: 'Personal Agent Protocol',
|
|
113
|
+
description: "A person's agent working with a company for them — signed out, then signed in at the company, its changes confirmed by the person — and an application being a company personal agents reach.",
|
|
114
|
+
publisher: 'Sierra, Meta',
|
|
115
|
+
layer: 'consent',
|
|
116
|
+
specUrl: 'https://poppy.md',
|
|
117
|
+
specVersion: 'draft 0.1',
|
|
118
|
+
status: 'shipped',
|
|
119
|
+
connects: "Companies, as a person's agent there, or being one",
|
|
120
|
+
packages: {
|
|
121
|
+
python: ['personal-agent-protocol'],
|
|
122
|
+
typescript: ['@datalayer/personal-agent-protocol'],
|
|
123
|
+
},
|
|
124
|
+
protocolTools: ['pap'],
|
|
125
|
+
appspecBlock: 'pap',
|
|
126
|
+
};
|
|
127
|
+
export const TAP_PROTOCOL_0_0_1 = {
|
|
128
|
+
id: 'tap',
|
|
129
|
+
version: '0.0.1',
|
|
130
|
+
name: 'Trusted Agent Protocol',
|
|
131
|
+
description: 'An agent-recognition profile over Web Bot Auth for merchants. Planned: nothing is built until its profile is confirmed.',
|
|
132
|
+
publisher: 'Visa',
|
|
133
|
+
layer: 'identity',
|
|
134
|
+
specUrl: 'https://developer.visa.com',
|
|
135
|
+
specVersion: 'none yet',
|
|
136
|
+
status: 'planned',
|
|
137
|
+
connects: 'Merchants that recognise an agent by its signature',
|
|
138
|
+
packages: {
|
|
139
|
+
python: [],
|
|
140
|
+
typescript: [],
|
|
141
|
+
},
|
|
142
|
+
protocolTools: [],
|
|
143
|
+
};
|
|
144
|
+
export const UCP_PROTOCOL_0_0_1 = {
|
|
145
|
+
id: 'ucp',
|
|
146
|
+
version: '0.0.1',
|
|
147
|
+
name: 'Universal Commerce Protocol',
|
|
148
|
+
description: 'Shopping at a merchant: catalogue, checkout and orders, every purchase an exact proposal the person approves. Planned in applications: the client exists, purchases wait on a source of payment tokens.',
|
|
149
|
+
publisher: 'Google, with Shopify and retailers',
|
|
150
|
+
layer: 'commerce',
|
|
151
|
+
specUrl: 'https://github.com/Universal-Commerce-Protocol/ucp',
|
|
152
|
+
specVersion: '2026-08-25',
|
|
153
|
+
status: 'planned',
|
|
154
|
+
connects: 'Merchants, to search, check out and follow orders',
|
|
155
|
+
packages: {
|
|
156
|
+
python: ['ucp-sdk', 'agent-runtimes'],
|
|
157
|
+
typescript: ['@ucp-js/sdk', '@datalayer/agent-runtimes'],
|
|
158
|
+
},
|
|
159
|
+
protocolTools: ['ucp'],
|
|
160
|
+
};
|
|
161
|
+
export const WEB_BOT_AUTH_PROTOCOL_0_0_1 = {
|
|
162
|
+
id: 'web-bot-auth',
|
|
163
|
+
version: '0.0.1',
|
|
164
|
+
name: 'Web Bot Auth',
|
|
165
|
+
description: 'Signed outbound requests (RFC 9421) and the key directory a website checks them against.',
|
|
166
|
+
publisher: 'Cloudflare (IETF draft)',
|
|
167
|
+
layer: 'identity',
|
|
168
|
+
specUrl: 'https://datatracker.ietf.org/doc/draft-ietf-webbotauth-httpsig-protocol/',
|
|
169
|
+
specVersion: 'draft-ietf-webbotauth-httpsig-protocol-00',
|
|
170
|
+
status: 'shipped',
|
|
171
|
+
connects: "Websites, which can tell the application's requests from someone pretending",
|
|
172
|
+
packages: {
|
|
173
|
+
python: ['agent-runtimes'],
|
|
174
|
+
typescript: ['@datalayer/agent-runtimes', 'web-bot-auth'],
|
|
175
|
+
},
|
|
176
|
+
protocolTools: [],
|
|
177
|
+
};
|
|
178
|
+
export const PROTOCOL_CATALOGUE = {
|
|
179
|
+
a2a: A2A_PROTOCOL_0_0_1,
|
|
180
|
+
a2ui: A2UI_PROTOCOL_0_0_1,
|
|
181
|
+
acp: ACP_PROTOCOL_0_0_1,
|
|
182
|
+
'ag-ui': AG_UI_PROTOCOL_0_0_1,
|
|
183
|
+
mcp: MCP_PROTOCOL_0_0_1,
|
|
184
|
+
pact: PACT_PROTOCOL_0_0_1,
|
|
185
|
+
pap: PAP_PROTOCOL_0_0_1,
|
|
186
|
+
tap: TAP_PROTOCOL_0_0_1,
|
|
187
|
+
ucp: UCP_PROTOCOL_0_0_1,
|
|
188
|
+
'web-bot-auth': WEB_BOT_AUTH_PROTOCOL_0_0_1,
|
|
189
|
+
};
|
|
190
|
+
/** A protocol by id. */
|
|
191
|
+
export function getProtocol(protocolId) {
|
|
192
|
+
return PROTOCOL_CATALOGUE[protocolId];
|
|
193
|
+
}
|
|
194
|
+
/** Every protocol of the catalogue. */
|
|
195
|
+
export function listProtocolSpecs() {
|
|
196
|
+
return Object.values(PROTOCOL_CATALOGUE);
|
|
197
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UI Catalog.
|
|
3
|
+
*
|
|
4
|
+
* How an agent's answer becomes an interface: the protocols a host renders.
|
|
5
|
+
*
|
|
6
|
+
* This file is AUTO-GENERATED from YAML specifications.
|
|
7
|
+
* DO NOT EDIT MANUALLY - run 'make specs' to regenerate.
|
|
8
|
+
*/
|
|
9
|
+
import type { ComponentSpec, UISpec } from '../types/agentspecs';
|
|
10
|
+
export declare const A2UI_UI_0_0_1: UISpec;
|
|
11
|
+
export declare const MCP_APPS_UI_0_0_1: UISpec;
|
|
12
|
+
export declare const MCP_UI_UI_0_0_1: UISpec;
|
|
13
|
+
export declare const UI_CATALOGUE: Record<string, UISpec>;
|
|
14
|
+
/** The UI an agent spec's `ui` names, or undefined. */
|
|
15
|
+
export declare function getUI(pluginId: string): UISpec | undefined;
|
|
16
|
+
export declare function listUI(): UISpec[];
|
|
17
|
+
/** The visual components the enabled UI specs render, by the name a surface gives them (LOOP C-13). */
|
|
18
|
+
export declare const COMPONENT_CATALOGUE: Record<string, ComponentSpec>;
|
|
19
|
+
/** The component a layout names, or undefined. */
|
|
20
|
+
export declare function getComponent(name: string): ComponentSpec | undefined;
|
|
21
|
+
export declare function listComponents(): ComponentSpec[];
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
-
export const
|
|
5
|
+
export const A2UI_UI_0_0_1 = {
|
|
6
6
|
id: 'a2ui',
|
|
7
7
|
version: '0.0.1',
|
|
8
8
|
name: 'A2UI',
|
|
@@ -1055,7 +1055,7 @@ export const A2UI_UI_PLUGIN_0_0_1 = {
|
|
|
1055
1055
|
},
|
|
1056
1056
|
],
|
|
1057
1057
|
};
|
|
1058
|
-
export const
|
|
1058
|
+
export const MCP_APPS_UI_0_0_1 = {
|
|
1059
1059
|
id: 'mcp-apps',
|
|
1060
1060
|
version: '0.0.1',
|
|
1061
1061
|
name: 'MCP Apps',
|
|
@@ -1065,7 +1065,7 @@ export const MCP_APPS_UI_PLUGIN_0_0_1 = {
|
|
|
1065
1065
|
catalog: '',
|
|
1066
1066
|
components: [],
|
|
1067
1067
|
};
|
|
1068
|
-
export const
|
|
1068
|
+
export const MCP_UI_UI_0_0_1 = {
|
|
1069
1069
|
id: 'mcp-ui',
|
|
1070
1070
|
version: '0.0.1',
|
|
1071
1071
|
name: 'MCP UI',
|
|
@@ -1075,20 +1075,20 @@ export const MCP_UI_UI_PLUGIN_0_0_1 = {
|
|
|
1075
1075
|
catalog: '',
|
|
1076
1076
|
components: [],
|
|
1077
1077
|
};
|
|
1078
|
-
export const
|
|
1079
|
-
a2ui:
|
|
1080
|
-
'mcp-apps':
|
|
1081
|
-
'mcp-ui':
|
|
1078
|
+
export const UI_CATALOGUE = {
|
|
1079
|
+
a2ui: A2UI_UI_0_0_1,
|
|
1080
|
+
'mcp-apps': MCP_APPS_UI_0_0_1,
|
|
1081
|
+
'mcp-ui': MCP_UI_UI_0_0_1,
|
|
1082
1082
|
};
|
|
1083
|
-
/** The
|
|
1084
|
-
export function
|
|
1085
|
-
return
|
|
1083
|
+
/** The UI an agent spec's `ui` names, or undefined. */
|
|
1084
|
+
export function getUI(pluginId) {
|
|
1085
|
+
return UI_CATALOGUE[pluginId];
|
|
1086
1086
|
}
|
|
1087
|
-
export function
|
|
1088
|
-
return Object.values(
|
|
1087
|
+
export function listUI() {
|
|
1088
|
+
return Object.values(UI_CATALOGUE);
|
|
1089
1089
|
}
|
|
1090
|
-
/** The visual components the enabled UI
|
|
1091
|
-
export const COMPONENT_CATALOGUE = Object.fromEntries(Object.values(
|
|
1090
|
+
/** The visual components the enabled UI specs render, by the name a surface gives them (LOOP C-13). */
|
|
1091
|
+
export const COMPONENT_CATALOGUE = Object.fromEntries(Object.values(UI_CATALOGUE)
|
|
1092
1092
|
.filter(plugin => plugin.enabled)
|
|
1093
1093
|
.flatMap(plugin => plugin.components.map(component => [component.id, component])));
|
|
1094
1094
|
/** The component a layout names, or undefined. */
|
|
@@ -107,10 +107,10 @@ export interface ComponentSpec {
|
|
|
107
107
|
}
|
|
108
108
|
/**
|
|
109
109
|
* How an agent's answer becomes an interface: a protocol the host renders
|
|
110
|
-
* (`agentspecs/ui
|
|
110
|
+
* (`agentspecs/ui`). An agent spec's `ui` names one.
|
|
111
111
|
*/
|
|
112
|
-
export interface
|
|
113
|
-
/** What an agent spec's `
|
|
112
|
+
export interface UISpec {
|
|
113
|
+
/** What an agent spec's `ui` names (e.g. 'a2ui'). */
|
|
114
114
|
id: string;
|
|
115
115
|
version: string;
|
|
116
116
|
name: string;
|
|
@@ -125,6 +125,39 @@ export interface UIPluginSpec {
|
|
|
125
125
|
/** The visual components it renders (LOOP C-13). */
|
|
126
126
|
components: ComponentSpec[];
|
|
127
127
|
}
|
|
128
|
+
/** The layer of an agent's visit a protocol answers (AGENT_PROTOCOLS §1). */
|
|
129
|
+
export type ProtocolLayer = 'transport' | 'consent' | 'identity' | 'commerce' | 'ui';
|
|
130
|
+
/**
|
|
131
|
+
* An agent protocol Datalayer targets (`agentspecs/protocols`, AGENT_PROTOCOLS
|
|
132
|
+
* PS-01). An agent spec's or an application's `protocols` names the ones it speaks.
|
|
133
|
+
*/
|
|
134
|
+
export interface ProtocolSpec {
|
|
135
|
+
/** What `protocols` lists (e.g. 'pap'). */
|
|
136
|
+
id: string;
|
|
137
|
+
version: string;
|
|
138
|
+
name: string;
|
|
139
|
+
description: string;
|
|
140
|
+
/** Who publishes the specification. */
|
|
141
|
+
publisher: string;
|
|
142
|
+
layer: ProtocolLayer;
|
|
143
|
+
/** The specification. */
|
|
144
|
+
specUrl: string;
|
|
145
|
+
/** The version implemented. */
|
|
146
|
+
specVersion: string;
|
|
147
|
+
/** Implemented by agent-runtimes today, or only planned: an application cannot ship a planned one. */
|
|
148
|
+
status: 'shipped' | 'planned';
|
|
149
|
+
/** What it connects an agent to. */
|
|
150
|
+
connects: string;
|
|
151
|
+
/** The packages implementing it, by language. */
|
|
152
|
+
packages: {
|
|
153
|
+
python: string[];
|
|
154
|
+
typescript: string[];
|
|
155
|
+
};
|
|
156
|
+
/** Its tools' action-class tables (`agentspecs/protocol-tools`). */
|
|
157
|
+
protocolTools: string[];
|
|
158
|
+
/** The Appspec block it configures, if any: refused unless `protocols` lists it. */
|
|
159
|
+
appspecBlock?: 'pap' | 'pact' | 'a2a';
|
|
160
|
+
}
|
|
128
161
|
/** A check a Frame requires of the output of work done under it. */
|
|
129
162
|
export interface FrameGuardSpec {
|
|
130
163
|
id: string;
|
|
@@ -507,6 +540,25 @@ export interface AppPactConnectionSpec {
|
|
|
507
540
|
export interface AppPactSpec {
|
|
508
541
|
connections: AppPactConnectionSpec[];
|
|
509
542
|
}
|
|
543
|
+
/**
|
|
544
|
+
* An A2A extension the application's Agent Card advertises, beside the
|
|
545
|
+
* runtime's own (AGENT_PROTOCOLS PR-02). Its params are public: never a
|
|
546
|
+
* credential.
|
|
547
|
+
*/
|
|
548
|
+
export interface AppA2AExtensionSpec {
|
|
549
|
+
/** The extension's URI: an `https://` URL or a `urn:`. */
|
|
550
|
+
uri: string;
|
|
551
|
+
/** What it adds, for whoever reads the card. */
|
|
552
|
+
description: string;
|
|
553
|
+
/** Whether a client must support it to talk to the application at all. */
|
|
554
|
+
required: boolean;
|
|
555
|
+
/** Its parameters on the card, as the extension defines them. */
|
|
556
|
+
params: Record<string, unknown>;
|
|
557
|
+
}
|
|
558
|
+
/** A2A: the extensions its Agent Card advertises. */
|
|
559
|
+
export interface AppA2ASpec {
|
|
560
|
+
extensions: AppA2AExtensionSpec[];
|
|
561
|
+
}
|
|
510
562
|
/** When an application acts alone, and when it asks. */
|
|
511
563
|
export interface AppRuleSpec {
|
|
512
564
|
/** The action, in the words a person reads. */
|
|
@@ -1063,10 +1115,20 @@ export interface AppSpec {
|
|
|
1063
1115
|
/** The documents and datasets it answers from. */
|
|
1064
1116
|
contents: string[];
|
|
1065
1117
|
connections: AppConnectionSpec[];
|
|
1118
|
+
/**
|
|
1119
|
+
* The agent protocols it speaks, ids of `agentspecs/protocols` (AGENT_PROTOCOLS
|
|
1120
|
+
* PS-02): its `pap`, `pact` and `a2a` blocks are refused unless their protocol
|
|
1121
|
+
* is listed, and a planned one only while it is not offered.
|
|
1122
|
+
*/
|
|
1123
|
+
protocols: string[];
|
|
1124
|
+
/** The UI its answers render in, ids of `agentspecs/ui` (AGENT_PROTOCOLS PS-04). */
|
|
1125
|
+
ui: string[];
|
|
1066
1126
|
/** Personal Agent Protocol; absent, the application has none. */
|
|
1067
1127
|
pap?: AppPapSpec;
|
|
1068
1128
|
/** PACT: the businesses it asks for each person (AGENT_PROTOCOLS PI-01). */
|
|
1069
1129
|
pact?: AppPactSpec;
|
|
1130
|
+
/** A2A: the extensions its Agent Card advertises (AGENT_PROTOCOLS PR-02). */
|
|
1131
|
+
a2a?: AppA2ASpec;
|
|
1070
1132
|
rules: AppRuleSpec[];
|
|
1071
1133
|
permissions: AppPermissionsSpec;
|
|
1072
1134
|
interface: AppInterfaceSpec;
|
|
@@ -1187,8 +1249,13 @@ export interface Agentspec {
|
|
|
1187
1249
|
delegable?: AgentCapability[];
|
|
1188
1250
|
/** Communication protocol (e.g., 'ag-ui', 'acp', 'a2a', 'vercel-ai') */
|
|
1189
1251
|
protocol?: string;
|
|
1190
|
-
/**
|
|
1191
|
-
|
|
1252
|
+
/**
|
|
1253
|
+
* The agent protocols it speaks, ids of `agentspecs/protocols` (AGENT_PROTOCOLS
|
|
1254
|
+
* PS-02). `protocol` says how a page reaches it; this, what it speaks to the world.
|
|
1255
|
+
*/
|
|
1256
|
+
protocols?: string[];
|
|
1257
|
+
/** The UI its answers render in (e.g., 'a2ui', 'mcp-apps'), one of the `UI_CATALOGUE`. */
|
|
1258
|
+
ui?: string;
|
|
1192
1259
|
/** Trigger configuration (type, cron, event source, prompt) */
|
|
1193
1260
|
trigger?: AgentTriggerConfig;
|
|
1194
1261
|
/** Model configuration (temperature, max_tokens) */
|
package/lib/types/messages.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* @module types/messages
|
|
6
6
|
*/
|
|
7
|
+
import type { Display } from '@datalayer/reactor/ui';
|
|
7
8
|
/**
|
|
8
9
|
* Message role enumeration
|
|
9
10
|
*/
|
|
@@ -121,6 +122,12 @@ export interface ChatMessage {
|
|
|
121
122
|
note?: 'waiting' | 'failed' | 'stopped';
|
|
122
123
|
/** Optional metadata */
|
|
123
124
|
metadata?: Record<string, unknown>;
|
|
125
|
+
/**
|
|
126
|
+
* What the message shows besides its words: the displays sent under it
|
|
127
|
+
* (`reactor.ui`, REACTOR_UI RU-2), in the order they came; each drawn by
|
|
128
|
+
* the renderer a plugin contributed for its type.
|
|
129
|
+
*/
|
|
130
|
+
displays?: Display[];
|
|
124
131
|
/** Tool calls for assistant messages */
|
|
125
132
|
toolCalls?: ToolCallContentPart[];
|
|
126
133
|
/** For activity messages (A2A, A2UI, etc.) */
|
package/lib/types/protocol.d.ts
CHANGED
|
@@ -44,6 +44,14 @@ export interface ProtocolConfig {
|
|
|
44
44
|
enableConfigQuery?: boolean;
|
|
45
45
|
/** Config endpoint URL for non-Jupyter protocols (if not set, uses Jupyter requestAPI) */
|
|
46
46
|
configEndpoint?: string;
|
|
47
|
+
/**
|
|
48
|
+
* The ui channel's WebSocket (`ws://` or `wss://`, REACTOR_UI RU-W): an
|
|
49
|
+
* application's session says on it what its messages show, its steps, its
|
|
50
|
+
* elements, its authors and its window messages, and takes the presses of
|
|
51
|
+
* what they offered. Set for an application's agent; one connection per
|
|
52
|
+
* conversation, its thread the scope.
|
|
53
|
+
*/
|
|
54
|
+
uiSocket?: string;
|
|
47
55
|
/** Additional protocol options */
|
|
48
56
|
options?: Record<string, unknown>;
|
|
49
57
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datalayer/agent-runtimes",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"workspaces": [
|
|
6
6
|
".",
|
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
"@datalayer/primer-addons": "^1.0.39",
|
|
162
162
|
"@datalayer/primer-rjsf": "^1.0.3",
|
|
163
163
|
"@datalayer/personal-agent-protocol": "^0.6.0",
|
|
164
|
-
"@datalayer/reactor": "^1.0
|
|
164
|
+
"@datalayer/reactor": "^1.2.0",
|
|
165
165
|
"@datalayer/reactor-commands": "^1.0.4",
|
|
166
166
|
"@datalayer/reactor-manager": "^1.0.4",
|
|
167
167
|
"@datalayer/reactor-shell": "^1.0.4",
|
|
@@ -235,7 +235,10 @@ def load_fragments(specs_dir: Path) -> List[Dict[str, Any]]:
|
|
|
235
235
|
|
|
236
236
|
|
|
237
237
|
def refuse_tools_field(spec: Dict[str, Any], path: Path) -> None:
|
|
238
|
-
"""Refuse an agent spec that still says `tools
|
|
238
|
+
"""Refuse an agent spec that still says `tools` (it is `backend_tools` now) or
|
|
239
|
+
`ui_plugin` (it is `ui` now, AGENT_PROTOCOLS PS-03)."""
|
|
240
|
+
if "ui_plugin" in spec:
|
|
241
|
+
raise SystemExit(f"Error: {path} says `ui_plugin`: the field is `ui`, one of agentspecs/ui")
|
|
239
242
|
if "tools" in spec:
|
|
240
243
|
raise SystemExit(
|
|
241
244
|
f"Error: {path} says `tools`: the field is `backend_tools` — the tools "
|
|
@@ -288,9 +291,37 @@ def load_yaml_specs(specs_dir: Path) -> List[tuple[str, Dict[str, Any]]]:
|
|
|
288
291
|
resolved.append((subfolder, spec))
|
|
289
292
|
|
|
290
293
|
check_model_additionals(resolved, load_model_ids(specs_dir))
|
|
294
|
+
check_protocols(resolved, load_protocol_ids(specs_dir))
|
|
291
295
|
return resolved
|
|
292
296
|
|
|
293
297
|
|
|
298
|
+
def load_protocol_ids(specs_dir: Path) -> set[str]:
|
|
299
|
+
"""Every id of the protocols catalogue (`agentspecs/protocols`, AGENT_PROTOCOLS PS-01)."""
|
|
300
|
+
ids: set[str] = set()
|
|
301
|
+
for yaml_file in sorted((specs_dir.parent / "protocols").glob("*.yaml")):
|
|
302
|
+
protocol = yaml.safe_load(yaml_file.read_text()) or {}
|
|
303
|
+
if protocol.get("id"):
|
|
304
|
+
ids.add(str(protocol["id"]))
|
|
305
|
+
return ids
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def check_protocols(specs: List[tuple[str, Dict[str, Any]]], protocol_ids: set[str]) -> None:
|
|
309
|
+
"""Refuse an agent whose `protocols` is not a list of the catalogue's ids, each once (PS-02)."""
|
|
310
|
+
problems = []
|
|
311
|
+
for _, spec in specs:
|
|
312
|
+
said = spec.get("protocols")
|
|
313
|
+
if said is None:
|
|
314
|
+
continue
|
|
315
|
+
if not isinstance(said, list) or len(set(map(str, said))) != len(said):
|
|
316
|
+
problems.append(f"{spec.get('id')}: protocols is a list of protocol ids, each once")
|
|
317
|
+
continue
|
|
318
|
+
unknown = [str(p) for p in said if str(p) not in protocol_ids]
|
|
319
|
+
if unknown:
|
|
320
|
+
problems.append(f"{spec.get('id')}: protocols names what the catalogue does not know: {', '.join(unknown)}")
|
|
321
|
+
if problems:
|
|
322
|
+
raise SystemExit("\n".join(problems))
|
|
323
|
+
|
|
324
|
+
|
|
294
325
|
def load_model_ids(specs_dir: Path) -> set[str]:
|
|
295
326
|
"""Every id the models catalogue answers to: its ids and their aliases."""
|
|
296
327
|
ids: set[str] = set()
|
|
@@ -508,8 +539,8 @@ from agent_runtimes.types import (
|
|
|
508
539
|
protocol_val = spec.get("protocol")
|
|
509
540
|
protocol_str = f'"{protocol_val}"' if protocol_val else "None"
|
|
510
541
|
delegable_str = _fmt_py_delegable(spec.get("delegable", []))
|
|
511
|
-
|
|
512
|
-
|
|
542
|
+
ui_id = spec.get("ui")
|
|
543
|
+
ui_str = f'"{ui_id}"' if ui_id else "None"
|
|
513
544
|
trigger_val = spec.get("trigger")
|
|
514
545
|
model_cfg = spec.get("model_config")
|
|
515
546
|
mcp_srv_tools = spec.get("mcp_server_tools")
|
|
@@ -620,7 +651,8 @@ from agent_runtimes.types import (
|
|
|
620
651
|
goal={goal_str},
|
|
621
652
|
delegable={delegable_str},
|
|
622
653
|
protocol={protocol_str},
|
|
623
|
-
|
|
654
|
+
ui={ui_str},
|
|
655
|
+
protocols={_fmt_list([str(p) for p in spec.get("protocols") or []])},
|
|
624
656
|
trigger={_fmt_py_literal(trigger_val)},
|
|
625
657
|
model_configuration={_fmt_py_literal(model_cfg)},
|
|
626
658
|
mcp_server_tools={_fmt_py_literal(mcp_srv_tools)},
|
|
@@ -1135,8 +1167,8 @@ const FRONTEND_TOOL_MAP: Record<string, any> = {
|
|
|
1135
1167
|
protocol_val = spec.get("protocol")
|
|
1136
1168
|
protocol_ts = f"'{protocol_val}'" if protocol_val else "undefined"
|
|
1137
1169
|
delegable_ts = _fmt_ts_delegable(spec.get("delegable", []))
|
|
1138
|
-
|
|
1139
|
-
|
|
1170
|
+
ui_id = spec.get("ui")
|
|
1171
|
+
ui_ts = f"'{ui_id}'" if ui_id else "undefined"
|
|
1140
1172
|
trigger_val = spec.get("trigger")
|
|
1141
1173
|
model_cfg = spec.get("model_config")
|
|
1142
1174
|
mcp_srv_tools = spec.get("mcp_server_tools")
|
|
@@ -1195,7 +1227,8 @@ const FRONTEND_TOOL_MAP: Record<string, any> = {
|
|
|
1195
1227
|
goal: {goal_ts},
|
|
1196
1228
|
delegable: {delegable_ts},
|
|
1197
1229
|
protocol: {protocol_ts},
|
|
1198
|
-
|
|
1230
|
+
ui: {ui_ts},
|
|
1231
|
+
protocols: {_fmt_ts_literal([str(p) for p in spec.get("protocols") or []])},
|
|
1199
1232
|
trigger: {_fmt_ts_literal(trigger_val)},
|
|
1200
1233
|
modelConfig: {_fmt_ts_literal(model_cfg)},
|
|
1201
1234
|
mcpServerTools: {_fmt_ts_literal(mcp_srv_tools)},
|
|
@@ -1635,11 +1668,13 @@ export * from './memory';
|
|
|
1635
1668
|
export * from './models';
|
|
1636
1669
|
export * from './modelProviders';
|
|
1637
1670
|
export * from './notifications';
|
|
1671
|
+
export * from './voices';
|
|
1638
1672
|
export * from './outputs';
|
|
1639
1673
|
export * from './skills';
|
|
1640
1674
|
export * from './backendTools';
|
|
1641
1675
|
export * from './triggers';
|
|
1642
|
-
export * from './
|
|
1676
|
+
export * from './ui';
|
|
1677
|
+
export * from './protocols';
|
|
1643
1678
|
export * from './frames';
|
|
1644
1679
|
export * from './cogs';
|
|
1645
1680
|
export * from './guards';
|
|
@@ -152,8 +152,16 @@ def load_specs(specs_dir: Path) -> tuple[list[dict[str, Any]], dict[str, Any]]:
|
|
|
152
152
|
# Personal Agent Protocol only when the application says something of it:
|
|
153
153
|
# an Appspec that does not mention `pap` reads back with none (the TypeScript
|
|
154
154
|
# reader's rule), so the catalogue leaves the defaults out too.
|
|
155
|
-
if "pap" in spec and spec["pap"] == type(app.pap)().model_dump(
|
|
155
|
+
if "pap" in spec and spec["pap"] == type(app.pap)().model_dump(
|
|
156
|
+
mode="json", by_alias=True
|
|
157
|
+
):
|
|
156
158
|
spec.pop("pap")
|
|
159
|
+
# PACT and A2A's extensions the same way (AGENT_PROTOCOLS PI-01, PR-02).
|
|
160
|
+
for block in ("pact", "a2a"):
|
|
161
|
+
if block in spec and spec[block] == type(getattr(app, block))().model_dump(
|
|
162
|
+
mode="json", by_alias=True
|
|
163
|
+
):
|
|
164
|
+
spec.pop(block)
|
|
157
165
|
for key in ("description", "instructions", "goal"):
|
|
158
166
|
spec[key] = _flat(spec.get(key))
|
|
159
167
|
spec["interface"]["welcome"] = _flat(spec["interface"].get("welcome"))
|
|
@@ -198,8 +206,24 @@ def load_specs(specs_dir: Path) -> tuple[list[dict[str, Any]], dict[str, Any]]:
|
|
|
198
206
|
if (signs := actions_module.server_tool_signs(server, name))
|
|
199
207
|
},
|
|
200
208
|
}
|
|
209
|
+
# The agent protocols' tools (AGENT_PROTOCOLS PR-54): by protocol, the
|
|
210
|
+
# connection prefix its connections take and what each tool can do.
|
|
211
|
+
protocols = {
|
|
212
|
+
identity: {
|
|
213
|
+
"connection": spec["connection"],
|
|
214
|
+
"tools": {
|
|
215
|
+
name: [
|
|
216
|
+
item.value
|
|
217
|
+
for item in actions_module.protocol_tool_classes(identity, name)
|
|
218
|
+
]
|
|
219
|
+
for name in actions_module.protocol_tool_names(identity)
|
|
220
|
+
},
|
|
221
|
+
}
|
|
222
|
+
for identity, spec in sorted(actions_module.protocol_tool_specs().items())
|
|
223
|
+
}
|
|
201
224
|
actions = {
|
|
202
225
|
"classes": [item.value for item in actions_module.ActionClass],
|
|
226
|
+
"protocols": protocols,
|
|
203
227
|
"tools": tools,
|
|
204
228
|
"servers": servers,
|
|
205
229
|
"behaviours": behaviours,
|
|
@@ -419,6 +443,10 @@ def generate_actions_python_code(actions: dict[str, Any]) -> str:
|
|
|
419
443
|
[
|
|
420
444
|
"}",
|
|
421
445
|
"",
|
|
446
|
+
"#: What each agent protocol's tools do, by protocol id: the prefix its",
|
|
447
|
+
"#: connections take (`pap:<domain>`) and each tool's classes (PR-54).",
|
|
448
|
+
f"PROTOCOL_TOOL_CLASSES: Dict[str, Dict[str, Any]] = {actions['protocols']!r}",
|
|
449
|
+
"",
|
|
422
450
|
"#: What each application of the catalogue does about each classed tool of the",
|
|
423
451
|
"#: servers it connects to, as agentspecs decides it: `do_it`, `if_asked`,",
|
|
424
452
|
"#: `ask_first` or `leave_to_me`. What the rules engine has to reproduce.",
|
|
@@ -471,6 +499,15 @@ def generate_actions_typescript_code(actions: dict[str, Any]) -> str:
|
|
|
471
499
|
+ ";",
|
|
472
500
|
"",
|
|
473
501
|
"/**",
|
|
502
|
+
" * What each agent protocol's tools do, by protocol id: the prefix its",
|
|
503
|
+
" * connections take (`pap:<domain>`) and each tool's classes (PR-54).",
|
|
504
|
+
" */",
|
|
505
|
+
"export const PROTOCOL_TOOL_CLASSES: Record<",
|
|
506
|
+
" string,",
|
|
507
|
+
" { connection: string; tools: Record<string, ActionClass[]> }",
|
|
508
|
+
"> = " + json.dumps(actions["protocols"], indent=2) + ";",
|
|
509
|
+
"",
|
|
510
|
+
"/**",
|
|
474
511
|
" * What each application of the catalogue does about each classed tool of the",
|
|
475
512
|
" * servers it connects to, as agentspecs decides it. What the rules engine has",
|
|
476
513
|
" * to reproduce.",
|