@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.
@@ -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
- borderRadius: 2,
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: 2,
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
- borderRadius: 2,
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, datalayerCreatePayload: datalayerCreatePayload, ...embed, plugins: allPlugins }));
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
  /**
@@ -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,
@@ -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 header says why, beside the title, for the same reason 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
  *
@@ -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
  *
@@ -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 —
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datalayer/agent-runtimes",
3
- "version": "1.3.20",
3
+ "version": "1.3.22",
4
4
  "type": "module",
5
5
  "workspaces": [
6
6
  ".",