@datalayer/agent-runtimes 1.3.81 โ 1.3.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/chat/assistant/SpeechBalloon.js +16 -1
- package/lib/chat/base/ChatBase.js +40 -4
- package/lib/chat/indicators/McpStatusIndicator.d.ts +1 -1
- package/lib/chat/indicators/McpStatusIndicator.js +13 -6
- package/lib/chat/indicators/SkillsStatusIndicator.d.ts +1 -1
- package/lib/chat/indicators/SkillsStatusIndicator.js +7 -3
- package/lib/chat/prompt/InputPrompt.d.ts +4 -1
- package/lib/chat/prompt/InputPrompt.js +2 -2
- package/lib/chat/prompt/InputPromptBase.d.ts +4 -1
- package/lib/chat/prompt/InputPromptBase.js +2 -2
- package/lib/chat/prompt/InputPromptLexical.d.ts +7 -1
- package/lib/chat/prompt/InputPromptLexical.js +5 -3
- package/lib/components/a2ui/datalayer/Form.js +19 -2
- package/lib/components/teams/index.d.ts +1 -0
- package/lib/components/teams/index.js +1 -0
- package/lib/components/teams/usePeerSandbox.d.ts +13 -0
- package/lib/components/teams/usePeerSandbox.js +59 -0
- package/lib/examples/AgentA2ATeamExample.js +7 -2
- package/lib/loop/apps/AppComposer.d.ts +31 -0
- package/lib/loop/apps/AppComposer.js +67 -0
- package/lib/loop/apps/AppRenderer.d.ts +16 -5
- package/lib/loop/apps/AppRenderer.js +49 -16
- package/lib/loop/apps/appspec.d.ts +8 -1
- package/lib/loop/apps/appspec.js +88 -23
- package/lib/loop/apps/checks.js +125 -8
- package/lib/loop/apps/composer.d.ts +37 -0
- package/lib/loop/apps/composer.js +61 -0
- package/lib/loop/apps/index.d.ts +2 -0
- package/lib/loop/apps/index.js +2 -0
- package/lib/loop/core/index.d.ts +31 -0
- package/lib/loop/core/index.js +22 -0
- package/lib/loop/embed/AppEmbed.d.ts +46 -7
- package/lib/loop/embed/AppEmbed.js +108 -26
- package/lib/loop/embed/LoopEmbed.js +2 -0
- package/lib/loop/embed/element.js +19 -5
- package/lib/loop/embed/embedConfig.d.ts +10 -1
- package/lib/loop/embed/embedConfig.js +12 -1
- package/lib/loop/embed/embedSession.d.ts +79 -0
- package/lib/loop/embed/embedSession.js +136 -0
- package/lib/loop/embed/embedTheme.d.ts +12 -9
- package/lib/loop/embed/embedTheme.js +32 -22
- package/lib/loop/index.d.ts +4 -3
- package/lib/loop/index.js +4 -3
- package/lib/loop/plugins/agent-capacity/index.d.ts +3 -1
- package/lib/loop/plugins/agent-capacity/index.js +2 -1
- package/lib/loop/plugins/app-page/appPageModel.d.ts +14 -5
- package/lib/loop/plugins/app-page/appPageModel.js +80 -88
- package/lib/loop/plugins/chat/ChatView.js +31 -4
- package/lib/loop/plugins/chat/index.d.ts +6 -1
- package/lib/loop/presets.d.ts +3 -1
- package/lib/loop/presets.js +2 -1
- package/lib/loop/shell/LoopWorkspace.js +3 -0
- package/lib/protocols/BrowserAgentAdapter.d.ts +18 -0
- package/lib/protocols/BrowserAgentAdapter.js +35 -2
- package/lib/runtimes/__tests__/fixtures/accounting-agent-card.json +8 -0
- package/lib/runtimes/browser/a2aPeer.d.ts +11 -0
- package/lib/runtimes/browser/a2aPeer.js +15 -1
- package/lib/runtimes/browser/protocol.d.ts +3 -0
- package/lib/runtimes/browser/protocol.js +2 -1
- package/lib/specs/agents/agents.js +6 -3
- package/lib/specs/apps.js +216 -176
- package/lib/specs/appspecSchema.js +205 -84
- package/lib/specs/cogs.js +3 -2
- package/lib/types/agentspecs.d.ts +92 -7
- package/lib/types/chat.d.ts +29 -1
- package/package.json +1 -1
- package/scripts/codegen/generate_agents.py +4 -2
- package/scripts/codegen/generate_apps.py +0 -1
- package/scripts/codegen/generate_backend_tools.py +4 -12
- package/scripts/codegen/generate_cogs.py +3 -1
- package/scripts/codegen/generate_ui_plugins.py +22 -9
- package/scripts/voice/transcribe.mjs +29 -21
|
@@ -26,6 +26,7 @@ import { type LanguageModel } from 'ai';
|
|
|
26
26
|
import type { ProtocolAdapterConfig } from '../types/protocol';
|
|
27
27
|
import type { ChatMessage } from '../types/messages';
|
|
28
28
|
import type { FrontendToolDefinition } from '../types/tools';
|
|
29
|
+
import type { AppModeEffect } from '../types/agentspecs';
|
|
29
30
|
import type { AgentStreamSubagentPayload } from '../types/stream';
|
|
30
31
|
import { BaseProtocolAdapter } from './BaseProtocolAdapter';
|
|
31
32
|
import type { TeamContextSharing } from '../types/teams';
|
|
@@ -63,6 +64,13 @@ export interface BrowserAgentAdapterConfig extends ProtocolAdapterConfig, Fronte
|
|
|
63
64
|
sharing?: TeamContextSharing;
|
|
64
65
|
/** Told what a delegated run does, as it does it โ see `subagentTools`. */
|
|
65
66
|
onSubagentEvent?: (event: AgentStreamSubagentPayload) => void;
|
|
67
|
+
/**
|
|
68
|
+
* What the modes a run is sent in (`forwardedProps.loop.modes`, LOOP P-19)
|
|
69
|
+
* tell it, and the model it runs on: an application's, by agentspecs'
|
|
70
|
+
* rules. Unsaid for an agent with no modes, which refuses a run sent in
|
|
71
|
+
* some.
|
|
72
|
+
*/
|
|
73
|
+
modeEffect?: (chosen: Record<string, string>) => AppModeEffect;
|
|
66
74
|
}
|
|
67
75
|
/**
|
|
68
76
|
* An agent loop running in the page, speaking the protocol adapter interface.
|
|
@@ -111,6 +119,15 @@ export declare class BrowserAgentAdapter extends BaseProtocolAdapter {
|
|
|
111
119
|
* `languageModel` is the host's own choice and is not swapped out.
|
|
112
120
|
*/
|
|
113
121
|
private resolveModel;
|
|
122
|
+
/**
|
|
123
|
+
* What the modes a run is sent in tell it, and the model it runs on (LOOP
|
|
124
|
+
* P-19) โ the runtime's session API applies the same, for that run only.
|
|
125
|
+
*
|
|
126
|
+
* Refused, in a sentence, rather than run without them: modes sent to an
|
|
127
|
+
* agent that has none, modes that are not the application's, and a mode
|
|
128
|
+
* naming a model for an agent whose model is the host's own.
|
|
129
|
+
*/
|
|
130
|
+
private runModes;
|
|
114
131
|
/**
|
|
115
132
|
* Run one turn of the loop and report it as it happens.
|
|
116
133
|
*
|
|
@@ -121,5 +138,6 @@ export declare class BrowserAgentAdapter extends BaseProtocolAdapter {
|
|
|
121
138
|
sendMessage(message: ChatMessage, options?: {
|
|
122
139
|
messages?: ChatMessage[];
|
|
123
140
|
model?: string;
|
|
141
|
+
forwardedProps?: Record<string, unknown>;
|
|
124
142
|
}): Promise<void>;
|
|
125
143
|
}
|
|
@@ -140,6 +140,30 @@ export class BrowserAgentAdapter extends BaseProtocolAdapter {
|
|
|
140
140
|
}
|
|
141
141
|
return createBrowserModel({ ...inference, model: requested || model });
|
|
142
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* What the modes a run is sent in tell it, and the model it runs on (LOOP
|
|
145
|
+
* P-19) โ the runtime's session API applies the same, for that run only.
|
|
146
|
+
*
|
|
147
|
+
* Refused, in a sentence, rather than run without them: modes sent to an
|
|
148
|
+
* agent that has none, modes that are not the application's, and a mode
|
|
149
|
+
* naming a model for an agent whose model is the host's own.
|
|
150
|
+
*/
|
|
151
|
+
runModes(forwardedProps) {
|
|
152
|
+
const loop = forwardedProps?.loop;
|
|
153
|
+
const chosen = loop?.modes;
|
|
154
|
+
if (!chosen || Object.keys(chosen).length === 0) {
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
const { modeEffect, languageModel } = this.browserConfig;
|
|
158
|
+
if (!modeEffect) {
|
|
159
|
+
throw new Error('This agent has no modes: the options chosen in the composer cannot be applied to it.');
|
|
160
|
+
}
|
|
161
|
+
const effect = modeEffect(chosen);
|
|
162
|
+
if (effect.model && languageModel) {
|
|
163
|
+
throw new Error(`The mode chosen runs on ${effect.model}, and this agent's model is its host's own: it cannot run on another.`);
|
|
164
|
+
}
|
|
165
|
+
return effect;
|
|
166
|
+
}
|
|
143
167
|
/**
|
|
144
168
|
* Run one turn of the loop and report it as it happens.
|
|
145
169
|
*
|
|
@@ -194,9 +218,18 @@ export class BrowserAgentAdapter extends BaseProtocolAdapter {
|
|
|
194
218
|
this.emit({ type: 'message', message: assistant, timestamp: new Date() });
|
|
195
219
|
};
|
|
196
220
|
try {
|
|
221
|
+
// The modes the person is in, for this run only: their instructions
|
|
222
|
+
// after the agent's, and the model one names over the chat's.
|
|
223
|
+
const modes = this.runModes(options?.forwardedProps);
|
|
224
|
+
const { instructions } = this.browserConfig;
|
|
225
|
+
const system = modes?.instructions
|
|
226
|
+
? [instructions?.trim(), modes.instructions]
|
|
227
|
+
.filter(Boolean)
|
|
228
|
+
.join('\n\n')
|
|
229
|
+
: instructions;
|
|
197
230
|
const result = streamText({
|
|
198
|
-
model: this.resolveModel(options?.model),
|
|
199
|
-
system
|
|
231
|
+
model: this.resolveModel(modes?.model || options?.model),
|
|
232
|
+
system,
|
|
200
233
|
messages: history,
|
|
201
234
|
tools: this.tools,
|
|
202
235
|
stopWhen: stepCountIs(this.browserConfig.maxSteps ?? DEFAULT_BROWSER_MAX_STEPS),
|
|
@@ -38,6 +38,14 @@
|
|
|
38
38
|
"pause": "/api/v1/a2a/pause",
|
|
39
39
|
"steer": "/api/v1/a2a/steer"
|
|
40
40
|
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"uri": "https://datalayer.ai/extensions/face/v1",
|
|
44
|
+
"description": "Its face: an emoji, and an avatar when it has one.",
|
|
45
|
+
"required": false,
|
|
46
|
+
"params": {
|
|
47
|
+
"emoji": "๐งพ"
|
|
48
|
+
}
|
|
41
49
|
}
|
|
42
50
|
]
|
|
43
51
|
},
|
|
@@ -37,7 +37,18 @@ export type A2APeer = {
|
|
|
37
37
|
client: Client;
|
|
38
38
|
card: AgentCard;
|
|
39
39
|
skill: AgentSkill;
|
|
40
|
+
/** Its face, when its card carries one (`A2A_FACE_EXTENSION_URI`). */
|
|
41
|
+
face?: A2APeerFace;
|
|
40
42
|
};
|
|
43
|
+
/** The extension an agent card carries its face in: its name stays plain. */
|
|
44
|
+
export declare const A2A_FACE_EXTENSION_URI = "https://datalayer.ai/extensions/face/v1";
|
|
45
|
+
/** A peer's face: its emoji and, when it has one, its avatar's name. */
|
|
46
|
+
export type A2APeerFace = {
|
|
47
|
+
emoji: string;
|
|
48
|
+
avatar?: string;
|
|
49
|
+
};
|
|
50
|
+
/** The face an agent card carries, if it carries one. */
|
|
51
|
+
export declare function faceOfCard(card: AgentCard): A2APeerFace | undefined;
|
|
41
52
|
export type ConnectA2APeerOptions = {
|
|
42
53
|
/** Where the peer is served: `โฆ/api/v1/a2a/agents/<application id>`. */
|
|
43
54
|
url: string;
|
|
@@ -36,6 +36,19 @@ import { ClientFactory, ClientFactoryOptions, DefaultAgentCardResolver, JsonRpcT
|
|
|
36
36
|
import { jsonSchema, tool } from 'ai';
|
|
37
37
|
/** Where an A2A agent's card is, under the address it is served at. */
|
|
38
38
|
export const AGENT_CARD_PATH = '.well-known/agent-card.json';
|
|
39
|
+
/** The extension an agent card carries its face in: its name stays plain. */
|
|
40
|
+
export const A2A_FACE_EXTENSION_URI = 'https://datalayer.ai/extensions/face/v1';
|
|
41
|
+
/** The face an agent card carries, if it carries one. */
|
|
42
|
+
export function faceOfCard(card) {
|
|
43
|
+
const extension = card.capabilities?.extensions?.find(candidate => candidate.uri === A2A_FACE_EXTENSION_URI);
|
|
44
|
+
const params = (extension?.params ?? {});
|
|
45
|
+
if (typeof params.emoji !== 'string' || !params.emoji) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
return typeof params.avatar === 'string' && params.avatar
|
|
49
|
+
? { emoji: params.emoji, avatar: params.avatar }
|
|
50
|
+
: { emoji: params.emoji };
|
|
51
|
+
}
|
|
39
52
|
/** A fetch that sends the key as a bearer token, beside the caller's headers. */
|
|
40
53
|
function withKey(base, key) {
|
|
41
54
|
if (!key) {
|
|
@@ -69,7 +82,8 @@ export async function connectA2APeer(options) {
|
|
|
69
82
|
if (!skill) {
|
|
70
83
|
throw new Error(`${card.name || root} offers no skill on its agent card: there is nothing to ask it.`);
|
|
71
84
|
}
|
|
72
|
-
|
|
85
|
+
const face = faceOfCard(card);
|
|
86
|
+
return face ? { client, card, skill, face } : { client, card, skill };
|
|
73
87
|
}
|
|
74
88
|
/** The media types an answer in words comes in: the answer itself, never an artifact of its own. */
|
|
75
89
|
export const TEXT_MEDIA_TYPES = [
|
|
@@ -12,6 +12,7 @@ import type { ProtocolConfig } from '../../types/protocol';
|
|
|
12
12
|
import type { AgentStreamSubagentPayload } from '../../types/stream';
|
|
13
13
|
import type { FrontendToolDefinition } from '../../types/tools';
|
|
14
14
|
import type { TeamContextSharing } from '../../types/teams';
|
|
15
|
+
import type { AppModeEffect } from '../../types/agentspecs';
|
|
15
16
|
import type { BrowserModelOptions } from './model';
|
|
16
17
|
import type { BrowserSubagent } from './subagents';
|
|
17
18
|
export type BrowserProtocolOptions = {
|
|
@@ -37,6 +38,8 @@ export type BrowserProtocolOptions = {
|
|
|
37
38
|
sharing?: TeamContextSharing;
|
|
38
39
|
/** Told what a delegated run does, as it does it โ see `subagentTools`. */
|
|
39
40
|
onSubagentEvent?: (event: AgentStreamSubagentPayload) => void;
|
|
41
|
+
/** What the modes a run is sent in tell it (LOOP P-19); none when unsaid. */
|
|
42
|
+
modeEffect?: (chosen: Record<string, string>) => AppModeEffect;
|
|
40
43
|
};
|
|
41
44
|
/**
|
|
42
45
|
* The protocol config for an agent whose loop runs in this page.
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* keystroke, so an omitted flag reads as a chat that silently ignores typing.
|
|
17
17
|
*/
|
|
18
18
|
export function browserProtocolConfig(options) {
|
|
19
|
-
const { agentId, instructions, model, frontendTools, inference, subagents, sharing, onSubagentEvent, } = options;
|
|
19
|
+
const { agentId, instructions, model, frontendTools, inference, subagents, sharing, onSubagentEvent, modeEffect, } = options;
|
|
20
20
|
return {
|
|
21
21
|
type: 'browser-vercel-ai',
|
|
22
22
|
endpoint: '',
|
|
@@ -30,6 +30,7 @@ export function browserProtocolConfig(options) {
|
|
|
30
30
|
subagents,
|
|
31
31
|
sharing,
|
|
32
32
|
onSubagentEvent,
|
|
33
|
+
modeEffect,
|
|
33
34
|
},
|
|
34
35
|
};
|
|
35
36
|
}
|
|
@@ -4900,8 +4900,9 @@ export const JUPYTER_DATA_ANALYST_AGENTSPEC_0_0_1 = {
|
|
|
4900
4900
|
'collaboration',
|
|
4901
4901
|
],
|
|
4902
4902
|
domain: undefined,
|
|
4903
|
-
enabled:
|
|
4903
|
+
enabled: true,
|
|
4904
4904
|
model: 'bedrock:us.anthropic.claude-sonnet-4-6',
|
|
4905
|
+
modelAdditionals: ['alibaba:qwen-max'],
|
|
4905
4906
|
mcpServers: [],
|
|
4906
4907
|
skills: [].filter(Boolean),
|
|
4907
4908
|
backendTools: [TOOL_MAP['runtime-echo:0.0.1']],
|
|
@@ -7966,8 +7967,9 @@ export const WORKER_CUSTOMER_INTERVIEWER_AGENTSPEC_0_0_1 = {
|
|
|
7966
7967
|
description: `Conducts adaptive, AI-led interviews that respond intelligently to each answer. It asks relevant follow-up questions, uncovers motivations and decision-making patterns, and transforms conversations into structured, actionable insights.`,
|
|
7967
7968
|
tags: ['research', 'customer-support', 'analysis'],
|
|
7968
7969
|
domain: 'market-analyst',
|
|
7969
|
-
enabled:
|
|
7970
|
+
enabled: true,
|
|
7970
7971
|
model: 'bedrock:us.anthropic.claude-sonnet-4-6',
|
|
7972
|
+
modelAdditionals: ['alibaba:qwen-max'],
|
|
7971
7973
|
mcpServers: [],
|
|
7972
7974
|
skills: [
|
|
7973
7975
|
SKILL_MAP['text-summarizer:0.0.1']
|
|
@@ -8249,8 +8251,9 @@ export const WORKER_DOCUMENT_QA_AGENTSPEC_0_0_1 = {
|
|
|
8249
8251
|
'qa',
|
|
8250
8252
|
],
|
|
8251
8253
|
domain: 'personal-assistant',
|
|
8252
|
-
enabled:
|
|
8254
|
+
enabled: true,
|
|
8253
8255
|
model: 'bedrock:us.anthropic.claude-sonnet-4-6',
|
|
8256
|
+
modelAdditionals: ['alibaba:qwen-max'],
|
|
8254
8257
|
mcpServers: [],
|
|
8255
8258
|
skills: [
|
|
8256
8259
|
SKILL_MAP['events:0.0.1']
|