@datalayer/agent-runtimes 1.3.20 → 1.3.22
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/messages/ChatMessageList.js +13 -2
- package/lib/chat/prompt/InputPromptBase.js +2 -1
- package/lib/loop/apps/AppRenderer.d.ts +12 -1
- package/lib/loop/apps/AppRenderer.js +15 -3
- package/lib/loop/apps/checks.d.ts +2 -0
- package/lib/loop/apps/checks.js +18 -0
- package/lib/loop/embed/LoopEmbed.js +1 -0
- package/lib/loop/index.d.ts +1 -1
- package/lib/loop/plugins/chat/ChatView.js +3 -3
- package/lib/loop/plugins/chat/index.d.ts +6 -0
- package/lib/loop/presets.d.ts +2 -0
- package/lib/loop/presets.js +2 -1
- package/package.json +1 -1
|
@@ -679,7 +679,18 @@ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoad
|
|
|
679
679
|
}, children: message.directedTo.name })] })) : speaker.role ? (_jsx(Label, { size: "small", children: speaker.role })) : null, message.createdAt ? (_jsx(RelativeTime, { datetime: message.createdAt.toISOString(), sx: { fontSize: 0, color: 'fg.muted' } })) : null] })) : null, _jsxs(Box, { sx: {
|
|
680
680
|
p: 2,
|
|
681
681
|
overflowX: 'auto',
|
|
682
|
-
|
|
682
|
+
// The theme's bubble (LOOP T-03, T-06): today's 6px elsewhere.
|
|
683
|
+
borderRadius: 'var(--theme-radius-bubble, 6px)',
|
|
684
|
+
// A message arriving, at the theme's pace (LOOP T-10): no
|
|
685
|
+
// motion in a theme that sets none, nor when motion is reduced.
|
|
686
|
+
animation: 'chatMessageArrive var(--theme-motion-message, 0ms) var(--theme-motion-easing, ease) both',
|
|
687
|
+
'@keyframes chatMessageArrive': {
|
|
688
|
+
from: { opacity: 0, transform: 'translateY(4px)' },
|
|
689
|
+
to: { opacity: 1, transform: 'none' },
|
|
690
|
+
},
|
|
691
|
+
'@media (prefers-reduced-motion: reduce)': {
|
|
692
|
+
animation: 'none',
|
|
693
|
+
},
|
|
683
694
|
backgroundColor: isUser
|
|
684
695
|
? 'accent.emphasis'
|
|
685
696
|
: speaker
|
|
@@ -748,7 +759,7 @@ export function ChatMessageList({ displayItems, isLoading, isStreaming, showLoad
|
|
|
748
759
|
display: 'flex',
|
|
749
760
|
alignItems: 'center',
|
|
750
761
|
p: 2,
|
|
751
|
-
borderRadius:
|
|
762
|
+
borderRadius: 'var(--theme-radius-bubble, 6px)',
|
|
752
763
|
bg: 'canvas.subtle',
|
|
753
764
|
minHeight: '32px',
|
|
754
765
|
}, children: _jsx(TypingDots, {}) })] }) })), _jsx("div", { ref: messagesEndRef })] }));
|
|
@@ -212,7 +212,8 @@ export function InputPromptBase({ variant = 'lexical', placeholder = 'Ask anythi
|
|
|
212
212
|
}, sx: {
|
|
213
213
|
border: '1px solid',
|
|
214
214
|
borderColor: 'border.default',
|
|
215
|
-
|
|
215
|
+
// The theme's card (LOOP T-03, T-06): today's 6px elsewhere.
|
|
216
|
+
borderRadius: 'var(--theme-radius-card, 6px)',
|
|
216
217
|
bg: 'canvas.default',
|
|
217
218
|
overflow: 'hidden',
|
|
218
219
|
transition: 'border-color 0.2s ease',
|
|
@@ -16,9 +16,20 @@ export declare const agentIdOf: (app: Pick<AppSpec, "agent" | "team">) => string
|
|
|
16
16
|
* is not an agent spec, and is refused here rather than launched as one.
|
|
17
17
|
*/
|
|
18
18
|
export declare function defineAppPlugin(app: AppSpec): ReactorPlugin<Record<string, never>, unknown, unknown>;
|
|
19
|
+
/** Which instance of an application runs, as the platform knows it (LOOP R-07). */
|
|
20
|
+
export type AppInstance = {
|
|
21
|
+
/** Its `app` item. */
|
|
22
|
+
appUid?: string;
|
|
23
|
+
/** The deployment it runs as, when it is one. */
|
|
24
|
+
deploymentUid?: string;
|
|
25
|
+
/** The version that runs. */
|
|
26
|
+
version?: number;
|
|
27
|
+
};
|
|
19
28
|
export type AppRendererProps = Omit<LoopEmbedProps, 'agentId'> & {
|
|
20
29
|
/** The application to render. */
|
|
21
30
|
app: AppSpec;
|
|
31
|
+
/** What its record is kept under, on Datalayer: the application, its deployment. */
|
|
32
|
+
instance?: AppInstance;
|
|
22
33
|
};
|
|
23
34
|
/**
|
|
24
35
|
* An application in a LOOP workspace: its agent, its starters, its layout.
|
|
@@ -29,5 +40,5 @@ export type AppRendererProps = Omit<LoopEmbedProps, 'agentId'> & {
|
|
|
29
40
|
/** No host plugins: one array, so that it never reads as a change. */
|
|
30
41
|
/** The agentspec a runtime is allocated with before an application's agent is created on it. */
|
|
31
42
|
export declare const DATALAYER_BOOTSTRAP_AGENTSPEC = "example-simple";
|
|
32
|
-
export declare function AppRenderer({ app, plugins, ...embed }: AppRendererProps): React.JSX.Element;
|
|
43
|
+
export declare function AppRenderer({ app, plugins, instance, ...embed }: AppRendererProps): React.JSX.Element;
|
|
33
44
|
export default AppRenderer;
|
|
@@ -76,7 +76,7 @@ export function defineAppPlugin(app) {
|
|
|
76
76
|
/** The agentspec a runtime is allocated with before an application's agent is created on it. */
|
|
77
77
|
export const DATALAYER_BOOTSTRAP_AGENTSPEC = 'example-simple';
|
|
78
78
|
const NO_PLUGINS = [];
|
|
79
|
-
export function AppRenderer({ app, plugins = NO_PLUGINS, ...embed }) {
|
|
79
|
+
export function AppRenderer({ app, plugins = NO_PLUGINS, instance, ...embed }) {
|
|
80
80
|
const chatOnly = app.interface.layout === 'chat';
|
|
81
81
|
/*
|
|
82
82
|
* The application plugin, made once per application. `LoopEmbed` rebuilds
|
|
@@ -107,10 +107,19 @@ export function AppRenderer({ app, plugins = NO_PLUGINS, ...embed }) {
|
|
|
107
107
|
// application without a shell is refused: its tools are called
|
|
108
108
|
// one by one instead, each decided by its rules.
|
|
109
109
|
enable_codemode: Boolean(app.permissions?.computer?.shell),
|
|
110
|
+
...(instance
|
|
111
|
+
? {
|
|
112
|
+
app_instance: {
|
|
113
|
+
app_uid: instance.appUid ?? '',
|
|
114
|
+
deployment_uid: instance.deploymentUid ?? '',
|
|
115
|
+
version: instance.version ?? 0,
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
: {}),
|
|
110
119
|
}
|
|
111
120
|
: undefined,
|
|
112
121
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
113
|
-
[source]);
|
|
122
|
+
[source, instance?.appUid, instance?.deploymentUid, instance?.version]);
|
|
114
123
|
if (!appPlugin) {
|
|
115
124
|
return (_jsxs("div", { role: "status", style: { padding: 16 }, children: ["\u201C", app.name, "\u201D is run by a team, which the workspace does not run as an application yet."] }));
|
|
116
125
|
}
|
|
@@ -123,6 +132,9 @@ export function AppRenderer({ app, plugins = NO_PLUGINS, ...embed }) {
|
|
|
123
132
|
agentId: app.id, editors: !chatOnly, showViewSelector: !chatOnly, teamPicker: false, showAgentVariants: false, graph: false, pluginsPanel: false, datalayerAgentSpecId: DATALAYER_BOOTSTRAP_AGENTSPEC,
|
|
124
133
|
// Where an application runs is decided by its host — the Studio's
|
|
125
134
|
// Preview, the hosted page — not offered to its user.
|
|
126
|
-
targetFixed: true,
|
|
135
|
+
targetFixed: true,
|
|
136
|
+
// Applications first (LOOP T-12): an application's conversation wears
|
|
137
|
+
// the `loop` theme; a host may say otherwise.
|
|
138
|
+
themeVariant: "loop", datalayerCreatePayload: datalayerCreatePayload, ...embed, plugins: allPlugins }));
|
|
127
139
|
}
|
|
128
140
|
export default AppRenderer;
|
|
@@ -9,6 +9,8 @@ export interface AppCheck {
|
|
|
9
9
|
attention: string[];
|
|
10
10
|
setup: string[];
|
|
11
11
|
}
|
|
12
|
+
/** The Guards the runtime executes (agent-runtimes `loop/apps/guards.py`). */
|
|
13
|
+
export declare const EXECUTED_GUARDS: readonly string[];
|
|
12
14
|
/** The instant checks of an application as an editor holds it. */
|
|
13
15
|
export declare function checkApp(app: AppSpec, read?: string[]): AppCheck;
|
|
14
16
|
/**
|
package/lib/loop/apps/checks.js
CHANGED
|
@@ -256,8 +256,26 @@ function attentionNotes(app) {
|
|
|
256
256
|
if (app.record.include.length === 0) {
|
|
257
257
|
notes.push('It keeps no record of what it did.');
|
|
258
258
|
}
|
|
259
|
+
// A Guard the runtime does not run checks nothing (LOOP R-06): said here,
|
|
260
|
+
// where the builder decides, rather than found out in production.
|
|
261
|
+
for (const ref of app.checks.guards) {
|
|
262
|
+
const guard = own(GUARD_CATALOGUE, idOf(ref));
|
|
263
|
+
if (guard && !EXECUTED_GUARDS.includes(guard.id)) {
|
|
264
|
+
const judge = guard.method === 'cog'
|
|
265
|
+
? 'a Cog'
|
|
266
|
+
: guard.method === 'human'
|
|
267
|
+
? 'a person'
|
|
268
|
+
: 'a method';
|
|
269
|
+
notes.push(`The ${guard.name} is judged by ${judge} the runtime does not run yet: nothing is checked by it.`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
259
272
|
return notes;
|
|
260
273
|
}
|
|
274
|
+
/** The Guards the runtime executes (agent-runtimes `loop/apps/guards.py`). */
|
|
275
|
+
export const EXECUTED_GUARDS = [
|
|
276
|
+
'sensitive-data-guard',
|
|
277
|
+
'tool-use-policy-guard',
|
|
278
|
+
];
|
|
261
279
|
/** Whether a spec of the catalogue says it is not offered today. */
|
|
262
280
|
const isOff = (spec) => {
|
|
263
281
|
const fields = (spec ?? {});
|
|
@@ -65,6 +65,7 @@ export function LoopEmbed({ agentId = '', showHeader = false, chatHeaderActions,
|
|
|
65
65
|
preset.target,
|
|
66
66
|
preset.datalayerAgentSpecId,
|
|
67
67
|
preset.targetFixed,
|
|
68
|
+
preset.themeVariant,
|
|
68
69
|
// By its content: an application's spec written inline is a new object each render.
|
|
69
70
|
JSON.stringify(preset.datalayerCreatePayload ?? null),
|
|
70
71
|
preset.defaultEditor,
|
package/lib/loop/index.d.ts
CHANGED
|
@@ -66,4 +66,4 @@ export { LoopEmbed, type LoopEmbedProps } from './embed/LoopEmbed';
|
|
|
66
66
|
export { SubagentActivityPlugin, SubagentPulse, SUBAGENT_ACTIVITY_PLUGIN_NAME, } from './plugins/subagent-activity';
|
|
67
67
|
export { loopPlugins, type LoopPresetOptions } from './presets';
|
|
68
68
|
export { DocumentExtension, NotebookExtension } from './extensions';
|
|
69
|
-
export { BEHAVIOURS as APP_BEHAVIOUR_ORDER, DEFAULT_BEHAVIOURS as APP_DEFAULT_BEHAVIOURS, behaviourFor, classesOf, isReadOnly, toolBehaviours, toolEscalations, type BehaviourOptions, type ToolArguments, APP_SCHEMA, APPSPEC_KEY_ORDER, DEFAULT_LAYOUTS as APP_DEFAULT_LAYOUTS, dumpAppspec, emptyAppspec, parseAppspec, AppRenderer, checkApp, checkAppspec, type AppCheck, defineAppPlugin, type AppRendererProps, readAppspecYaml, writeAppspecYaml, type ParsedAppspec, } from './apps';
|
|
69
|
+
export { BEHAVIOURS as APP_BEHAVIOUR_ORDER, DEFAULT_BEHAVIOURS as APP_DEFAULT_BEHAVIOURS, behaviourFor, classesOf, isReadOnly, toolBehaviours, toolEscalations, type BehaviourOptions, type ToolArguments, APP_SCHEMA, APPSPEC_KEY_ORDER, DEFAULT_LAYOUTS as APP_DEFAULT_LAYOUTS, dumpAppspec, emptyAppspec, parseAppspec, AppRenderer, checkApp, checkAppspec, type AppCheck, defineAppPlugin, type AppRendererProps, type AppInstance, readAppspecYaml, writeAppspecYaml, type ParsedAppspec, } from './apps';
|
|
@@ -1397,10 +1397,10 @@ export default function ChatView({ workspace }) {
|
|
|
1397
1397
|
? 'attention.muted'
|
|
1398
1398
|
: 'danger.muted',
|
|
1399
1399
|
}, children: chatExtras.errorBanner.message })) : null, _jsx(Box, { sx: { flex: '1 1 auto', minHeight: 0, display: 'flex' }, children: _jsx(ChatBase
|
|
1400
|
-
// The
|
|
1401
|
-
// placeholder does: a dead control with no explanation is worse
|
|
1402
|
-
// than an absent one.
|
|
1400
|
+
// The theme it wears, when the host names one (an application's).
|
|
1403
1401
|
, {
|
|
1402
|
+
// The theme it wears, when the host names one (an application's).
|
|
1403
|
+
themeVariant: config?.themeVariant,
|
|
1404
1404
|
// The header says why, beside the title, for the same reason the
|
|
1405
1405
|
// placeholder does: a dead control with no explanation is worse
|
|
1406
1406
|
// than an absent one.
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
/** What a host may set on the chat. */
|
|
2
2
|
export type ChatPluginConfig = {
|
|
3
|
+
/**
|
|
4
|
+
* The theme the conversation wears, by name: the person's unless said. An
|
|
5
|
+
* application says `loop` (LOOP T-06, T-12) — the conversation then takes
|
|
6
|
+
* the theme's bubbles, pills and colours whatever the page around it wears.
|
|
7
|
+
*/
|
|
8
|
+
themeVariant?: string;
|
|
3
9
|
/**
|
|
4
10
|
* What the empty prompt says.
|
|
5
11
|
*
|
package/lib/loop/presets.d.ts
CHANGED
|
@@ -126,6 +126,8 @@ export type LoopPresetOptions = {
|
|
|
126
126
|
datalayerCreatePayload?: Record<string, unknown>;
|
|
127
127
|
/** The target is the host's to fix, even with the agent control hidden. */
|
|
128
128
|
targetFixed?: boolean;
|
|
129
|
+
/** The theme the conversation wears, by name; the person's unless said. */
|
|
130
|
+
themeVariant?: string;
|
|
129
131
|
/**
|
|
130
132
|
* The agentspec the local agent is created from, by id.
|
|
131
133
|
*
|
package/lib/loop/presets.js
CHANGED
|
@@ -52,7 +52,7 @@ import { LoopPageLayoutPlugin } from './plugins/page-layout';
|
|
|
52
52
|
* be installed or signed into, and the switches a demonstration wants are off.
|
|
53
53
|
*/
|
|
54
54
|
export function loopPlugins(options = {}) {
|
|
55
|
-
const { serverUrl, target = 'browser', defaultEditor = 'notebook', showViewSelector = true, hideChatHeader = false, chatHeaderButtons = false, promptPlacement, autoFocusPrompt = true, suggestionLabels = true, fullScreenTopOffset = 0, showAgentVariants = false, agentSummary = true, teamId, teamPicker = true, pageLayout = false, pageLayoutTurnPanel = 'below', pageLayoutPrompt = 'docked', pageLayoutPromptAnchor = 'top', pageLayoutSize, pageLayoutTurnPanelFooter = 'full', localAgent, localAgentSpec, datalayerAgentSpecId, datalayerCreatePayload, targetFixed, floatingPrompt = false, editorSelector = false, editors = true, graph = false, commandPalette = false, pluginsPanel = false, windowFrame = false, firstPromptHook, } = options;
|
|
55
|
+
const { serverUrl, target = 'browser', defaultEditor = 'notebook', showViewSelector = true, hideChatHeader = false, chatHeaderButtons = false, promptPlacement, autoFocusPrompt = true, suggestionLabels = true, fullScreenTopOffset = 0, showAgentVariants = false, agentSummary = true, teamId, teamPicker = true, pageLayout = false, pageLayoutTurnPanel = 'below', pageLayoutPrompt = 'docked', pageLayoutPromptAnchor = 'top', pageLayoutSize, pageLayoutTurnPanelFooter = 'full', localAgent, localAgentSpec, datalayerAgentSpecId, datalayerCreatePayload, targetFixed, themeVariant, floatingPrompt = false, editorSelector = false, editors = true, graph = false, commandPalette = false, pluginsPanel = false, windowFrame = false, firstPromptHook, } = options;
|
|
56
56
|
return [
|
|
57
57
|
// The chat owns the editor beside it, so which one opens is its
|
|
58
58
|
// configuration rather than the workspace's.
|
|
@@ -68,6 +68,7 @@ export function loopPlugins(options = {}) {
|
|
|
68
68
|
autoFocusPrompt,
|
|
69
69
|
suggestionLabels,
|
|
70
70
|
fullScreenTopOffset,
|
|
71
|
+
themeVariant,
|
|
71
72
|
}),
|
|
72
73
|
// The composer and the title bar are plugins of their own: the chat
|
|
73
74
|
// assembles their props, these render them. In the preset by default —
|