@datalayer/agent-runtimes 1.3.71 → 1.3.73
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/ChatFloating.d.ts +16 -1
- package/lib/chat/ChatFloating.js +62 -17
- package/lib/chat/assistant/AssistantStage.d.ts +17 -2
- package/lib/chat/assistant/AssistantStage.js +3 -3
- package/lib/chat/assistant/BalloonParts.d.ts +55 -0
- package/lib/chat/assistant/BalloonParts.js +140 -0
- package/lib/chat/assistant/ConversationBalloon.d.ts +5 -0
- package/lib/chat/assistant/ConversationBalloon.js +5 -0
- package/lib/chat/assistant/SpeechBalloon.d.ts +23 -2
- package/lib/chat/assistant/SpeechBalloon.js +22 -8
- package/lib/chat/assistant/toolLine.d.ts +69 -0
- package/lib/chat/assistant/toolLine.js +118 -0
- package/lib/components/teams/A2ATeamGraph.d.ts +12 -0
- package/lib/components/teams/A2ATeamGraph.js +35 -8
- package/lib/components/teams/NotebookPreview.d.ts +39 -0
- package/lib/components/teams/NotebookPreview.js +68 -0
- package/lib/components/teams/NotebookPreviewView.d.ts +21 -0
- package/lib/components/teams/NotebookPreviewView.js +42 -0
- package/lib/components/teams/TeamNotebook.js +16 -1
- package/lib/components/teams/a2aTeamFlow.d.ts +5 -0
- package/lib/components/teams/a2aTeamFlow.js +11 -0
- package/lib/components/teams/index.d.ts +1 -0
- package/lib/components/teams/index.js +1 -0
- package/lib/components/teams/useA2ATeam.d.ts +8 -0
- package/lib/components/teams/useA2ATeam.js +38 -3
- package/lib/examples/AgentA2ATeamExample.d.ts +8 -4
- package/lib/examples/AgentA2ATeamExample.js +2 -2
- package/lib/examples/ChatAssistantExample.js +4 -2
- package/lib/examples/ChatAssistantGalleryExample.d.ts +5 -1
- package/lib/examples/ChatAssistantGalleryExample.js +40 -10
- package/lib/examples/utils/AssistantGalleryGrid.d.ts +14 -11
- package/lib/examples/utils/AssistantGalleryGrid.js +42 -1
- package/lib/examples/utils/assistantGallery.d.ts +49 -1
- package/lib/examples/utils/assistantGallery.js +52 -1
- package/lib/loop/apps/appspec.js +6 -0
- package/lib/loop/apps/checks.js +2 -0
- package/lib/loop/embed/AppEmbed.js +3 -1
- package/lib/loop/plugins/assistant/index.d.ts +14 -1
- package/lib/loop/plugins/assistant/index.js +39 -13
- package/lib/specs/appspecSchema.js +18 -0
- package/lib/stories/loop/ReferenceScreens.d.ts +1 -1
- package/lib/stories/loop/ReferenceScreens.js +20 -3
- package/lib/types/agentspecs.d.ts +8 -0
- package/package.json +1 -1
|
@@ -13,6 +13,12 @@
|
|
|
13
13
|
* the runtime to ask (`decisions`), its balloon offers *Ask a decision*: a
|
|
14
14
|
* typed decision asked of Jev through the runtime, answered there.
|
|
15
15
|
*
|
|
16
|
+
* Its balloon shows the conversation as `balloon` says (LOOP T-23; the
|
|
17
|
+
* Appspec's `interface.balloon`): a peek of the newest words (`history`, the
|
|
18
|
+
* default), or the one thing being said or done now (`current`). Either way
|
|
19
|
+
* what the agent is doing while a tool runs — the turn's `activity` — is said
|
|
20
|
+
* there, and heard once as it starts.
|
|
21
|
+
*
|
|
16
22
|
* The workspace's chat is the conversation: on a page layout, its side panel
|
|
17
23
|
* is opened and closed; where the conversation is always on screen, a click
|
|
18
24
|
* takes the person to its composer.
|
|
@@ -23,6 +29,7 @@ import type { JSX } from 'react';
|
|
|
23
29
|
import { type AssistantState } from '../../../chat/assistant/state';
|
|
24
30
|
import type { PresenceState } from '../../../chat/presence/presenceStatus';
|
|
25
31
|
import { type ChatTurnSnapshot } from '../../core';
|
|
32
|
+
import type { BalloonDisplay } from '../../../chat/assistant/toolLine';
|
|
26
33
|
export declare const LOOP_ASSISTANT_PLUGIN_NAME = "@datalayer/loop-plugin-assistant";
|
|
27
34
|
export type LoopAssistantConfig = {
|
|
28
35
|
/** The character the application's Appspec names; it wins. */
|
|
@@ -45,6 +52,12 @@ export type LoopAssistantConfig = {
|
|
|
45
52
|
serverUrl: string;
|
|
46
53
|
token?: string;
|
|
47
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* How the balloon shows the conversation (T-23): a peek of the newest
|
|
57
|
+
* words (`history`, the default), or only what is said or done now
|
|
58
|
+
* (`current`). The Appspec's `interface.balloon`.
|
|
59
|
+
*/
|
|
60
|
+
balloon?: BalloonDisplay;
|
|
48
61
|
};
|
|
49
62
|
/**
|
|
50
63
|
* What the character acts out (T-22), from what the application is doing as
|
|
@@ -55,6 +68,6 @@ export declare function assistantStateOfTurn(turn: ChatTurnSnapshot, presence: P
|
|
|
55
68
|
arriving?: boolean;
|
|
56
69
|
leaving?: boolean;
|
|
57
70
|
}): AssistantState;
|
|
58
|
-
export declare function LoopAssistant({ app, person, appId, decisions, }: LoopAssistantConfig): JSX.Element | null;
|
|
71
|
+
export declare function LoopAssistant({ app, person, appId, decisions, balloon: display, }: LoopAssistantConfig): JSX.Element | null;
|
|
59
72
|
export declare const LoopAssistantPlugin: import("@datalayer/reactor").ReactorPlugin<LoopAssistantConfig, unknown, unknown>;
|
|
60
73
|
export default LoopAssistantPlugin;
|
|
@@ -69,7 +69,7 @@ function focusComposer() {
|
|
|
69
69
|
const composer = document.querySelector('[data-chat-composer] textarea, [data-chat-composer] [contenteditable="true"]');
|
|
70
70
|
composer?.focus();
|
|
71
71
|
}
|
|
72
|
-
export function LoopAssistant({ app, person, appId, decisions, }) {
|
|
72
|
+
export function LoopAssistant({ app, person, appId, decisions, balloon: display = 'history', }) {
|
|
73
73
|
const contributed = useContributions(LoopAssistantCharacter).map(entry => entry.value);
|
|
74
74
|
const chosen = assistantCharacterFor(contributed, { app, person });
|
|
75
75
|
const turnEntries = useContributions(LoopChatTurn);
|
|
@@ -136,25 +136,50 @@ export function LoopAssistant({ app, person, appId, decisions, }) {
|
|
|
136
136
|
}
|
|
137
137
|
const state = assistantStateOfTurn(turn, presence, { arriving, leaving });
|
|
138
138
|
const unheard = !!saying && saying.id !== heardId;
|
|
139
|
+
// What the agent does while a tool runs, in its own words (T-23).
|
|
140
|
+
const tool = turn.activity
|
|
141
|
+
? {
|
|
142
|
+
id: `${turn.id}:${turn.activity}`,
|
|
143
|
+
tool: '',
|
|
144
|
+
name: '',
|
|
145
|
+
phase: 'running',
|
|
146
|
+
words: turn.activity,
|
|
147
|
+
}
|
|
148
|
+
: undefined;
|
|
149
|
+
const atWork = turn.status === 'streaming' || turn.status === 'thinking';
|
|
150
|
+
const current = display === 'current';
|
|
139
151
|
const balloon = state === 'paused'
|
|
140
152
|
? { text: ASSISTANT_WORDS.paused }
|
|
141
153
|
: approval
|
|
142
154
|
? { text: ASSISTANT_WORDS.approval, approval }
|
|
143
155
|
: presence === 'waiting'
|
|
144
156
|
? { text: ASSISTANT_WORDS.waiting }
|
|
145
|
-
:
|
|
146
|
-
? {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
157
|
+
: tool
|
|
158
|
+
? { text: turn.activity ?? '', tool, busy: true }
|
|
159
|
+
: current && (atWork || unheard)
|
|
160
|
+
? {
|
|
161
|
+
text: turn.status === 'thinking'
|
|
162
|
+
? 'Thinking…'
|
|
163
|
+
: (saying?.text ?? 'Thinking…'),
|
|
164
|
+
more: saying?.more,
|
|
165
|
+
speaking: turn.status === 'streaming',
|
|
166
|
+
busy: atWork,
|
|
167
|
+
}
|
|
168
|
+
: unheard && saying
|
|
169
|
+
? {
|
|
170
|
+
// A peek: the first words; the rest is in the conversation.
|
|
171
|
+
...peekLine(saying.text),
|
|
172
|
+
onDismiss: () => {
|
|
173
|
+
setHeardId(saying.id);
|
|
174
|
+
setFresh(false);
|
|
175
|
+
},
|
|
176
|
+
}
|
|
177
|
+
: { text: 'Click me to open the conversation.' };
|
|
155
178
|
const insist = state === 'greeting' ||
|
|
156
179
|
presence === 'waiting' ||
|
|
157
180
|
(!!approval && state !== 'paused') ||
|
|
181
|
+
!!tool ||
|
|
182
|
+
(current && atWork) ||
|
|
158
183
|
(unheard && (state === 'speaking' || fresh));
|
|
159
184
|
const onToggle = () => {
|
|
160
185
|
if (onPageLayout) {
|
|
@@ -174,7 +199,7 @@ export function LoopAssistant({ app, person, appId, decisions, }) {
|
|
|
174
199
|
};
|
|
175
200
|
return (_jsxs(_Fragment, { children: [appId && signedIn ? (_jsx(WaitingApprovals, { appId: appId, onWaiting: setApproval })) : null, _jsx(AssistantStage, { character: chosen.character, state: state, size: SIZE, place: drag.position
|
|
176
201
|
? { left: `${drag.position.left}px`, top: `${drag.position.top}px` }
|
|
177
|
-
: { right: '24px', bottom: '24px' }, stageRef: stageRef, onDragStart: drag.onHandlePointerDown, open: open, onToggle: onToggle, balloon: balloon, insist: insist, onDismiss: onDismiss, decide: decide })] }));
|
|
202
|
+
: { right: '24px', bottom: '24px' }, stageRef: stageRef, onDragStart: drag.onHandlePointerDown, open: open, onToggle: onToggle, balloon: balloon, balloonDisplay: display, insist: insist, onDismiss: onDismiss, decide: decide })] }));
|
|
178
203
|
}
|
|
179
204
|
export const LoopAssistantPlugin = definePlugin({
|
|
180
205
|
name: LOOP_ASSISTANT_PLUGIN_NAME,
|
|
@@ -183,12 +208,13 @@ export const LoopAssistantPlugin = definePlugin({
|
|
|
183
208
|
person: undefined,
|
|
184
209
|
appId: undefined,
|
|
185
210
|
decisions: undefined,
|
|
211
|
+
balloon: undefined,
|
|
186
212
|
},
|
|
187
213
|
displayName: 'Floating assistant',
|
|
188
214
|
description: 'The chat as a character on the page: the application’s own, or the one the person chose, from the characters the enabled plugins contribute.',
|
|
189
215
|
octicon: 'paperclip',
|
|
190
216
|
build: ({ config }) => {
|
|
191
|
-
const Configured = () => (_jsx(LoopAssistant, { app: config.app, person: config.person, appId: config.appId, decisions: config.decisions }));
|
|
217
|
+
const Configured = () => (_jsx(LoopAssistant, { app: config.app, person: config.person, appId: config.appId, decisions: config.decisions, balloon: config.balloon }));
|
|
192
218
|
return {
|
|
193
219
|
components: [
|
|
194
220
|
{ id: 'loop-assistant', slot: LoopSlots.root, Component: Configured },
|
|
@@ -326,6 +326,18 @@ export const APPSPEC_SCHEMA = {
|
|
|
326
326
|
description: "The character its floating assistant shows, by the id a plugin contributes it under (lowercase letters and digits, words joined by a hyphen): Datalayer's are `paperclip`, `wizard`, `cat` and `eyes`. The paper clip when unsaid; an id no enabled plugin contributes is refused where the plugins are known, the runtime and the page. Said here, it wins over a person's own choice in their settings",
|
|
327
327
|
title: 'Assistant',
|
|
328
328
|
},
|
|
329
|
+
balloon: {
|
|
330
|
+
anyOf: [
|
|
331
|
+
{
|
|
332
|
+
$ref: '#/$defs/BalloonDisplay',
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
type: 'null',
|
|
336
|
+
},
|
|
337
|
+
],
|
|
338
|
+
default: null,
|
|
339
|
+
description: "How its floating assistant's balloon shows the conversation: `history` (every message, scrolled, the composer last) or `current` (only what it says or does now, the answer being written or the tool it calls, in one balloon). The page's own when unsaid: `history` for the floating chat",
|
|
340
|
+
},
|
|
329
341
|
voice: {
|
|
330
342
|
$ref: '#/$defs/AppVoice',
|
|
331
343
|
description: 'Its voice: whether it listens and speaks, with which voice, in which language (off unless said)',
|
|
@@ -772,6 +784,12 @@ export const APPSPEC_SCHEMA = {
|
|
|
772
784
|
title: 'AppVoice',
|
|
773
785
|
type: 'object',
|
|
774
786
|
},
|
|
787
|
+
BalloonDisplay: {
|
|
788
|
+
description: "How a floating assistant's balloon shows the conversation (LOOP T-23).",
|
|
789
|
+
enum: ['history', 'current'],
|
|
790
|
+
title: 'BalloonDisplay',
|
|
791
|
+
type: 'string',
|
|
792
|
+
},
|
|
775
793
|
Behaviour: {
|
|
776
794
|
description: 'What an application does when it meets an action: the four a person chooses from.',
|
|
777
795
|
enum: ['do_it', 'if_asked', 'ask_first', 'leave_to_me'],
|
|
@@ -8,7 +8,7 @@ export type ReferenceScreen = (typeof REFERENCE_SCREENS)[number];
|
|
|
8
8
|
* where it has something to say — stepped aside, and open, the conversation
|
|
9
9
|
* as its balloon (T-23).
|
|
10
10
|
*/
|
|
11
|
-
export declare const ASSISTANT_PICTURES: readonly ["idle", "thinking", "working", "waiting", "paused", "speaking", "aside", "open"];
|
|
11
|
+
export declare const ASSISTANT_PICTURES: readonly ["idle", "thinking", "working", "waiting", "paused", "speaking", "aside", "open", "current"];
|
|
12
12
|
export type AssistantPicture = (typeof ASSISTANT_PICTURES)[number];
|
|
13
13
|
/**
|
|
14
14
|
* The characters pictured idle, each in light and dark (T-25, T-24):
|
|
@@ -30,6 +30,7 @@ import { AssistantStage, } from '../../chat/assistant/AssistantStage';
|
|
|
30
30
|
import { ASSISTANT_WORDS, } from '../../chat/assistant/state';
|
|
31
31
|
import { CONVERSATION_BALLOON_WIDTH, ConversationBalloonClose, balloonTailAt, conversationBalloonHeight, conversationBalloonSx, peekLine, } from '../../chat/assistant/ConversationBalloon';
|
|
32
32
|
import { DecisionAsk } from '../../chat/assistant/DecisionAsk';
|
|
33
|
+
import { ConversationBalloonHeader } from '../../chat/assistant/BalloonParts';
|
|
33
34
|
import { buildReactorFromPlugins } from '@datalayer/reactor';
|
|
34
35
|
import { AssistantCharactersPlugin, assistantCharacterNamed, } from '../../loop/plugins/assistant-characters';
|
|
35
36
|
import { OwlCharacterPlugin } from '../../examples/utils/owlCharacterPlugin';
|
|
@@ -55,6 +56,7 @@ export const ASSISTANT_PICTURES = [
|
|
|
55
56
|
'speaking',
|
|
56
57
|
'aside',
|
|
57
58
|
'open',
|
|
59
|
+
'current',
|
|
58
60
|
];
|
|
59
61
|
/**
|
|
60
62
|
* The characters pictured idle, each in light and dark (T-25, T-24):
|
|
@@ -257,6 +259,17 @@ const BALLOONS = {
|
|
|
257
259
|
},
|
|
258
260
|
},
|
|
259
261
|
paused: { text: ASSISTANT_WORDS.paused },
|
|
262
|
+
// Current (T-23): only what it does now — the tool it calls.
|
|
263
|
+
current: {
|
|
264
|
+
text: 'Using list_invoices…',
|
|
265
|
+
tool: {
|
|
266
|
+
id: 'picture-tool',
|
|
267
|
+
tool: 'list_invoices',
|
|
268
|
+
name: 'list_invoices',
|
|
269
|
+
phase: 'running',
|
|
270
|
+
},
|
|
271
|
+
busy: true,
|
|
272
|
+
},
|
|
260
273
|
};
|
|
261
274
|
/**
|
|
262
275
|
* The paper clip in one state, in the page's corner. `aside` puts a dialog
|
|
@@ -265,7 +278,11 @@ const BALLOONS = {
|
|
|
265
278
|
*/
|
|
266
279
|
export function AssistantScreen({ picture, }) {
|
|
267
280
|
const stageRef = useRef(null);
|
|
268
|
-
const state = picture === 'aside' || picture === 'open'
|
|
281
|
+
const state = picture === 'aside' || picture === 'open'
|
|
282
|
+
? 'idle'
|
|
283
|
+
: picture === 'current'
|
|
284
|
+
? 'working'
|
|
285
|
+
: picture;
|
|
269
286
|
const balloon = BALLOONS[picture];
|
|
270
287
|
return (_jsxs(Box, { sx: { flex: 1, position: 'relative' }, children: [picture === 'open' && _jsx(OpenConversation, {}), picture === 'aside' && (_jsxs(Box, { role: "dialog", "aria-label": "A dialog over the assistant", sx: {
|
|
271
288
|
position: 'fixed',
|
|
@@ -280,7 +297,7 @@ export function AssistantScreen({ picture, }) {
|
|
|
280
297
|
borderColor: 'border.default',
|
|
281
298
|
borderRadius: 'var(--theme-radius-card, 6px)',
|
|
282
299
|
boxShadow: 'var(--theme-shadow, none)',
|
|
283
|
-
}, children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "A dialog" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1 }, children: "The assistant steps aside while this is open." })] })), _jsx(AssistantStage, { character: "paperclip", state: state, place: { right: 48, bottom: 48 }, stageRef: stageRef, onDragStart: () => undefined, open: picture === 'open', onToggle: () => undefined, balloon: balloon, insist: !!balloon, onDismiss: () => undefined })] }));
|
|
300
|
+
}, children: [_jsx(Text, { sx: { fontWeight: 600 }, children: "A dialog" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1 }, children: "The assistant steps aside while this is open." })] })), _jsx(AssistantStage, { character: "paperclip", state: state, place: { right: 48, bottom: 48 }, stageRef: stageRef, onDragStart: () => undefined, open: picture === 'open', onToggle: () => undefined, balloon: balloon, balloonDisplay: picture === 'current' ? 'current' : 'history', insist: !!balloon, onDismiss: () => undefined })] }));
|
|
284
301
|
}
|
|
285
302
|
/** What the open picture's conversation holds. */
|
|
286
303
|
const OPEN_CONVERSATION = [
|
|
@@ -316,7 +333,7 @@ function OpenConversation() {
|
|
|
316
333
|
edge: 'bottom',
|
|
317
334
|
at: balloonTailAt(window.innerWidth - 48 - 44, left),
|
|
318
335
|
}, 'canvas.subtle'),
|
|
319
|
-
}, children: [_jsx(ConversationBalloonClose, { onClose: () => undefined }), _jsxs(Box, { sx: {
|
|
336
|
+
}, children: [_jsx(ConversationBalloonClose, { onClose: () => undefined }), _jsx(ConversationBalloonHeader, { count: OPEN_CONVERSATION.length - 1 }), _jsxs(Box, { sx: {
|
|
320
337
|
flex: 1,
|
|
321
338
|
minHeight: 0,
|
|
322
339
|
display: 'flex',
|
|
@@ -392,6 +392,8 @@ export type AppAccent = 'green' | 'rose' | 'sky' | 'lime' | 'sun' | 'violet';
|
|
|
392
392
|
* known only where the plugins are.
|
|
393
393
|
*/
|
|
394
394
|
export type AppAssistantCharacter = string;
|
|
395
|
+
/** How a floating assistant's balloon shows the conversation (LOOP T-23). */
|
|
396
|
+
export type AppBalloonDisplay = 'history' | 'current';
|
|
395
397
|
/** How an application sits in another product's page (LOOP D-07). */
|
|
396
398
|
export type AppEmbedMode = 'inline' | 'bubble' | 'panel' | 'assistant';
|
|
397
399
|
/** Something an application reaches. */
|
|
@@ -479,6 +481,12 @@ export interface AppInterfaceSpec {
|
|
|
479
481
|
* Said, it wins over the one the person chose in their settings.
|
|
480
482
|
*/
|
|
481
483
|
assistant?: AppAssistantCharacter;
|
|
484
|
+
/**
|
|
485
|
+
* How its floating assistant's balloon shows the conversation: `history`
|
|
486
|
+
* (every message, the composer last) or `current` (only what it says or
|
|
487
|
+
* does now). The page's own when unsaid.
|
|
488
|
+
*/
|
|
489
|
+
balloon?: AppBalloonDisplay;
|
|
482
490
|
/** Its voice: off unless said (VO-41); absent from a spec made before voice. */
|
|
483
491
|
voice?: AppVoiceSpec;
|
|
484
492
|
/**
|