@datalayer/agent-runtimes 1.3.114 → 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 +71 -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/specs/agents/agents.js +338 -169
- package/lib/specs/apps.js +47 -0
- package/lib/specs/appspecSchema.js +16 -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 +51 -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_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
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useSyncExternalStore } from 'react';
|
|
3
3
|
import { IconButton, Text } from '@primer/react';
|
|
4
4
|
import { XIcon } from '@primer/octicons-react';
|
|
5
5
|
import { Box } from '@datalayer/primer-addons';
|
|
6
6
|
import { closeLoopElement, onLoopElements, openLoopElements, } from '../../../chat/base/loopElement';
|
|
7
|
-
import {
|
|
8
|
-
import { answerAction, readA2uiToolResult } from '../a2ui-surface/toolResult';
|
|
9
|
-
import { useOwnCatalog } from '../a2ui-surface/ownComponents';
|
|
7
|
+
import { AnswerShowsView } from '../a2ui-surface/AnswerShows';
|
|
10
8
|
/** How wide the side panel is, at most. */
|
|
11
9
|
export const APP_PANEL_WIDTH = 380;
|
|
12
10
|
/** What is open now: the panels in the order they opened, and the last page. */
|
|
@@ -18,22 +16,9 @@ export function elementsByPlace(open) {
|
|
|
18
16
|
};
|
|
19
17
|
}
|
|
20
18
|
function ElementBody({ element, send, }) {
|
|
21
|
-
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
-
const onAction = (action) => {
|
|
25
|
-
// A button of what its code shows: its action goes to the application,
|
|
26
|
-
// as a button of an answer does (LOOP P-04).
|
|
27
|
-
const pressed = answerAction(action);
|
|
28
|
-
if (pressed)
|
|
29
|
-
send?.(pressed.message, pressed.forwardedProps);
|
|
30
|
-
};
|
|
31
|
-
if (!parsed?.messages || parsed.messages.length === 0) {
|
|
32
|
-
return _jsx(Text, { sx: { color: 'fg.muted' }, children: "Nothing to show." });
|
|
33
|
-
}
|
|
34
|
-
return (_jsx(InlineSurface
|
|
35
|
-
// Drawn again whole when the code changes it.
|
|
36
|
-
, { messages: parsed.messages, onAction: onAction, catalog: catalog }, JSON.stringify(element.shows)));
|
|
19
|
+
// What its code shows, drawn as an answer's display is: its buttons press
|
|
20
|
+
// what the display offered (LOOP P-04, REACTOR_UI RU-2).
|
|
21
|
+
return (_jsx(AnswerShowsView, { display: element.shows, send: (message, forwardedProps) => send !== undefined && !send(message, forwardedProps) }));
|
|
37
22
|
}
|
|
38
23
|
function ElementHeader({ element }) {
|
|
39
24
|
return (_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, mb: 2, children: [_jsx(Text, { as: "h2", sx: { fontSize: 2, fontWeight: 'bold', m: 0 }, children: element.title }), _jsx(IconButton, { icon: XIcon, variant: "invisible", size: "small", "aria-label": `Close ${element.title}`, onClick: () => closeLoopElement(element.id) })] }));
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an application's code asks, drawn from its display (REACTOR_UI
|
|
3
|
+
* RU-4): `application/vnd.datalayer.loop.question+json`, shown under the
|
|
4
|
+
* message that asks it in words. A choice is its buttons — a rule's prompt
|
|
5
|
+
* is Allow and Refuse — the words a field, a form its fields; each press of
|
|
6
|
+
* it is `reactor.answer`, through the display's `act`, which the chat sends
|
|
7
|
+
* up the conversation's ui socket. A file is attached in the composer (until
|
|
8
|
+
* RU-6). Answered, it says what answered it, and offers nothing.
|
|
9
|
+
*
|
|
10
|
+
* @module apps/plugins/app-elements/QuestionView
|
|
11
|
+
*/
|
|
12
|
+
import type { JSX } from 'react';
|
|
13
|
+
import { type Display } from '@datalayer/reactor/ui';
|
|
14
|
+
import type { RendererProps } from '@datalayer/reactor/ui/react';
|
|
15
|
+
/** The display type of what an application's code asks (`QuestionShown`). */
|
|
16
|
+
export declare const QUESTION_DISPLAY_TYPE = "application/vnd.datalayer.loop.question+json";
|
|
17
|
+
/** A question as its display says it. Throws for a display that is not one. */
|
|
18
|
+
export declare function questionOf(display: Display): {
|
|
19
|
+
kind: 'text' | 'choice' | 'file' | 'form';
|
|
20
|
+
prompt: string;
|
|
21
|
+
options: string[];
|
|
22
|
+
accept: string[];
|
|
23
|
+
form: Record<string, unknown>;
|
|
24
|
+
answered: string | null;
|
|
25
|
+
answerable: boolean;
|
|
26
|
+
};
|
|
27
|
+
export declare function QuestionView({ display, act }: RendererProps): JSX.Element;
|
|
28
|
+
export default QuestionView;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { lazy, Suspense, useState } from 'react';
|
|
3
|
+
import { Box, Button, Text, TextInput } from '@primer/react';
|
|
4
|
+
import { ANSWER_ACTION } from '@datalayer/reactor/ui';
|
|
5
|
+
/** The display type of what an application's code asks (`QuestionShown`). */
|
|
6
|
+
export const QUESTION_DISPLAY_TYPE = 'application/vnd.datalayer.loop.question+json';
|
|
7
|
+
const SchemaForm = lazy(() => import('../../../components/a2ui/datalayer/SchemaForm'));
|
|
8
|
+
/** A question as its display says it. Throws for a display that is not one. */
|
|
9
|
+
export function questionOf(display) {
|
|
10
|
+
const data = display.data ?? {};
|
|
11
|
+
const kind = data.kind;
|
|
12
|
+
if (display.type !== QUESTION_DISPLAY_TYPE ||
|
|
13
|
+
(kind !== 'text' &&
|
|
14
|
+
kind !== 'choice' &&
|
|
15
|
+
kind !== 'file' &&
|
|
16
|
+
kind !== 'form') ||
|
|
17
|
+
typeof data.prompt !== 'string') {
|
|
18
|
+
throw new Error(`Display ${display.id} is not a question`);
|
|
19
|
+
}
|
|
20
|
+
const strings = (value) => Array.isArray(value)
|
|
21
|
+
? value.filter((item) => typeof item === 'string')
|
|
22
|
+
: [];
|
|
23
|
+
return {
|
|
24
|
+
kind,
|
|
25
|
+
prompt: data.prompt,
|
|
26
|
+
options: strings(data.options),
|
|
27
|
+
accept: strings(data.accept),
|
|
28
|
+
form: data.form && typeof data.form === 'object'
|
|
29
|
+
? data.form
|
|
30
|
+
: {},
|
|
31
|
+
answered: typeof data.answered === 'string' ? data.answered : null,
|
|
32
|
+
answerable: (display.actions ?? []).some(offer => offer.name === ANSWER_ACTION),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function QuestionView({ display, act }) {
|
|
36
|
+
const question = questionOf(display);
|
|
37
|
+
const [words, setWords] = useState('');
|
|
38
|
+
const [said, setSaid] = useState(null);
|
|
39
|
+
const answer = (value) => {
|
|
40
|
+
if (!act) {
|
|
41
|
+
setSaid('The chat cannot take an answer here.');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
setSaid(null);
|
|
45
|
+
void Promise.resolve(act({ action: ANSWER_ACTION, payload: { value } })).catch((failure) => setSaid(failure instanceof Error ? failure.message : String(failure)));
|
|
46
|
+
};
|
|
47
|
+
if (question.answered !== null) {
|
|
48
|
+
return (_jsxs(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: ["Answered: ", question.answered] }));
|
|
49
|
+
}
|
|
50
|
+
const live = question.answerable && !!act;
|
|
51
|
+
return (_jsxs(Box, { display: "flex", flexDirection: "column", gap: 2, "data-question-kind": question.kind, children: [question.kind === 'choice' ? (_jsx(Box, { display: "flex", gap: 2, flexWrap: "wrap", children: question.options.map(option => (_jsx(Button, { size: "small", disabled: !live, onClick: () => answer(option), children: option }, option))) })) : null, question.kind === 'text' ? (_jsxs(Box, { as: "form", display: "flex", gap: 2, onSubmit: (event) => {
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
if (words.trim())
|
|
54
|
+
answer(words.trim());
|
|
55
|
+
}, children: [_jsx(TextInput, { "aria-label": question.prompt, value: words, disabled: !live, onChange: event => setWords(event.target.value) }), _jsx(Button, { type: "submit", size: "small", disabled: !live || !words.trim(), children: "Answer" })] })) : null, question.kind === 'form' ? (_jsx(Suspense, { fallback: null, children: _jsx(SchemaForm, { schema: question.form, disabled: !live, onSubmit: ({ formData }) => answer(formData ?? {}) }) })) : null, question.kind === 'file' ? (_jsxs(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: ["Attach the file in the message box", question.accept.length ? ` (${question.accept.join(', ')})` : '', "."] })) : null, said ? (_jsx(Text, { as: "p", sx: { color: 'danger.fg', fontSize: 1, m: 0 }, children: said })) : null] }));
|
|
56
|
+
}
|
|
57
|
+
export default QuestionView;
|
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
* code (`session.close`) or by the person. Inline, an element is a message,
|
|
6
6
|
* which the chat draws (P-04); this plugin draws the other two.
|
|
7
7
|
*
|
|
8
|
-
* The chat keeps what is open (`chat/base/loopElement`), from the session
|
|
9
|
-
*
|
|
10
|
-
* root slot, positioned against the workspace, so that nothing
|
|
11
|
-
* while nothing is open.
|
|
8
|
+
* The chat keeps what is open (`chat/base/loopElement`), from the session's
|
|
9
|
+
* ui socket (REACTOR_UI RU-3, RU-W); this plugin draws it from the
|
|
10
|
+
* workspace's root slot, positioned against the workspace, so that nothing
|
|
11
|
+
* is laid out while nothing is open. It also contributes the renderer of
|
|
12
|
+
* what the code asks (`QuestionView`, RU-4), drawn under the message that
|
|
13
|
+
* asks it.
|
|
12
14
|
*
|
|
13
15
|
* @module apps/plugins/app-elements
|
|
14
16
|
*/
|
|
@@ -17,4 +19,5 @@ export declare const APP_ELEMENTS_PLUGIN_NAME = "@datalayer/loop-plugin-app-elem
|
|
|
17
19
|
/** The plugin that draws an application's side panel and pages. */
|
|
18
20
|
export declare const AppElementsPlugin: ReactorPlugin<Record<string, never>, unknown, unknown>;
|
|
19
21
|
export { AppElements, APP_PANEL_WIDTH, elementsByPlace } from './AppElements';
|
|
22
|
+
export { QUESTION_DISPLAY_TYPE, QuestionView, questionOf, } from './QuestionView';
|
|
20
23
|
export default AppElementsPlugin;
|
|
@@ -9,17 +9,22 @@
|
|
|
9
9
|
* code (`session.close`) or by the person. Inline, an element is a message,
|
|
10
10
|
* which the chat draws (P-04); this plugin draws the other two.
|
|
11
11
|
*
|
|
12
|
-
* The chat keeps what is open (`chat/base/loopElement`), from the session
|
|
13
|
-
*
|
|
14
|
-
* root slot, positioned against the workspace, so that nothing
|
|
15
|
-
* while nothing is open.
|
|
12
|
+
* The chat keeps what is open (`chat/base/loopElement`), from the session's
|
|
13
|
+
* ui socket (REACTOR_UI RU-3, RU-W); this plugin draws it from the
|
|
14
|
+
* workspace's root slot, positioned against the workspace, so that nothing
|
|
15
|
+
* is laid out while nothing is open. It also contributes the renderer of
|
|
16
|
+
* what the code asks (`QuestionView`, RU-4), drawn under the message that
|
|
17
|
+
* asks it.
|
|
16
18
|
*
|
|
17
19
|
* @module apps/plugins/app-elements
|
|
18
20
|
*/
|
|
19
|
-
import { definePlugin } from '@datalayer/reactor';
|
|
21
|
+
import { contribution, definePlugin, } from '@datalayer/reactor';
|
|
22
|
+
import { Renderers } from '@datalayer/reactor/ui';
|
|
23
|
+
import { defineRenderer } from '@datalayer/reactor/ui/react';
|
|
20
24
|
import { clearLoopElements } from '../../../chat/base/loopElement';
|
|
21
25
|
import { LoopSlots } from '../../core';
|
|
22
26
|
import { AppElements } from './AppElements';
|
|
27
|
+
import { QUESTION_DISPLAY_TYPE, QuestionView } from './QuestionView';
|
|
23
28
|
export const APP_ELEMENTS_PLUGIN_NAME = '@datalayer/loop-plugin-app-elements';
|
|
24
29
|
/** The plugin that draws an application's side panel and pages. */
|
|
25
30
|
export const AppElementsPlugin = definePlugin({
|
|
@@ -27,6 +32,9 @@ export const AppElementsPlugin = definePlugin({
|
|
|
27
32
|
displayName: 'Side panel and pages',
|
|
28
33
|
description: 'What an application opens beside the conversation: a side panel, or a page of its own.',
|
|
29
34
|
octicon: 'sidebar-expand',
|
|
35
|
+
contributes: [
|
|
36
|
+
contribution(Renderers, defineRenderer({ type: QUESTION_DISPLAY_TYPE, component: QuestionView }), { id: 'app-elements:question' }),
|
|
37
|
+
],
|
|
30
38
|
build: () => ({
|
|
31
39
|
components: [
|
|
32
40
|
{
|
|
@@ -40,4 +48,5 @@ export const AppElementsPlugin = definePlugin({
|
|
|
40
48
|
register: () => clearLoopElements,
|
|
41
49
|
});
|
|
42
50
|
export { AppElements, APP_PANEL_WIDTH, elementsByPlace } from './AppElements';
|
|
51
|
+
export { QUESTION_DISPLAY_TYPE, QuestionView, questionOf, } from './QuestionView';
|
|
43
52
|
export default AppElementsPlugin;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The Canvas's palette as a contribution point (LOOP C-12): each UI
|
|
3
|
-
* the catalogue that renders components (`agentspecs/ui
|
|
2
|
+
* The Canvas's palette as a contribution point (LOOP C-12): each UI of
|
|
3
|
+
* the catalogue that renders components (`agentspecs/ui`, C-13) is a
|
|
4
4
|
* Reactor plugin contributing its components to `loop.canvas.block`. The
|
|
5
5
|
* palette lists what the enabled plugins contribute, and nothing else; a
|
|
6
6
|
* plugin disabled takes its blocks off it, and an application that uses one
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* @module apps/plugins/canvas-blocks
|
|
13
13
|
*/
|
|
14
14
|
import { type ReactorPlatform, type ReactorPlugin } from '@datalayer/reactor';
|
|
15
|
-
import type { AppSpec, ComponentSpec,
|
|
15
|
+
import type { AppSpec, ComponentSpec, UISpec } from '../../../types/agentspecs';
|
|
16
16
|
import { LoopCanvasBlock, type CanvasBlockContribution } from '../../core/canvasBlocks';
|
|
17
17
|
/** What is read of a reactor here: its contributions to the point, and who is enabled. */
|
|
18
18
|
type BlocksReader = {
|
|
@@ -20,12 +20,12 @@ type BlocksReader = {
|
|
|
20
20
|
value: CanvasBlockContribution;
|
|
21
21
|
}>;
|
|
22
22
|
};
|
|
23
|
-
/** The name of the Reactor plugin that contributes a UI
|
|
24
|
-
export declare const canvasBlocksPluginName: (
|
|
25
|
-
/** A UI
|
|
26
|
-
export declare function uiPluginBlocks(
|
|
23
|
+
/** The name of the Reactor plugin that contributes a UI's blocks. */
|
|
24
|
+
export declare const canvasBlocksPluginName: (ui: string) => string;
|
|
25
|
+
/** A UI of the catalogue as the Reactor plugin contributing its components as blocks. */
|
|
26
|
+
export declare function uiPluginBlocks(ui: UISpec): ReactorPlugin<Record<string, never>, unknown, unknown>;
|
|
27
27
|
/**
|
|
28
|
-
* The plugins of the catalogue's UI
|
|
28
|
+
* The plugins of the catalogue's UI specs that render components and may
|
|
29
29
|
* be named today (`enabled` in the catalogue).
|
|
30
30
|
*/
|
|
31
31
|
export declare const CANVAS_BLOCK_PLUGINS: ReactorPlugin<Record<string, never>, unknown, unknown>[];
|
|
@@ -35,16 +35,16 @@ export declare const CANVAS_BLOCK_PLUGINS: ReactorPlugin<Record<string, never>,
|
|
|
35
35
|
*/
|
|
36
36
|
export declare function canvasBlocksReactor(disabled?: readonly string[], plugins?: ReactorPlugin<any, any, any>[]): ReactorPlatform;
|
|
37
37
|
/**
|
|
38
|
-
* The palette of an organization: the block plugins of the UI
|
|
38
|
+
* The palette of an organization: the block plugins of the UI specs it has
|
|
39
39
|
* turned off (`plugins_off` in IAM, catalogue ids such as 'a2ui') switched
|
|
40
|
-
* off. A UI
|
|
40
|
+
* off. A UI of the catalogue that contributes no block takes nothing
|
|
41
41
|
* off; an id the catalogue does not have is said by `unknownPluginsOff`.
|
|
42
42
|
*/
|
|
43
43
|
export declare function canvasBlocksReactorOf(pluginsOff: readonly string[]): ReactorPlatform;
|
|
44
|
-
/** The ids an organization turns off that no UI
|
|
44
|
+
/** The ids an organization turns off that no UI of the catalogue has. */
|
|
45
45
|
export declare function unknownPluginsOff(pluginsOff: readonly string[]): string[];
|
|
46
46
|
/**
|
|
47
|
-
* What an application's page uses from a UI
|
|
47
|
+
* What an application's page uses from a UI its organization has
|
|
48
48
|
* turned off, as its setup notes say it (`blockSetupNotes`, on the palette of
|
|
49
49
|
* `canvasBlocksReactorOf`).
|
|
50
50
|
*/
|
|
@@ -55,7 +55,7 @@ export declare function canvasBlocksOf(reactor: BlocksReader): ComponentSpec[];
|
|
|
55
55
|
export declare function componentsUsedBy(app: Pick<AppSpec, 'interface'>): string[];
|
|
56
56
|
/**
|
|
57
57
|
* What an application's page uses that no enabled plugin contributes, as its
|
|
58
|
-
* setup notes say it: one sentence per UI
|
|
58
|
+
* setup notes say it: one sentence per UI of the catalogue whose
|
|
59
59
|
* blocks it uses while its plugin is off. A component the catalogue does not
|
|
60
60
|
* have is not a note but a problem of the instant checks.
|
|
61
61
|
*/
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
|
-
* The Canvas's palette as a contribution point (LOOP C-12): each UI
|
|
7
|
-
* the catalogue that renders components (`agentspecs/ui
|
|
6
|
+
* The Canvas's palette as a contribution point (LOOP C-12): each UI of
|
|
7
|
+
* the catalogue that renders components (`agentspecs/ui`, C-13) is a
|
|
8
8
|
* Reactor plugin contributing its components to `loop.canvas.block`. The
|
|
9
9
|
* palette lists what the enabled plugins contribute, and nothing else; a
|
|
10
10
|
* plugin disabled takes its blocks off it, and an application that uses one
|
|
@@ -16,26 +16,26 @@
|
|
|
16
16
|
* @module apps/plugins/canvas-blocks
|
|
17
17
|
*/
|
|
18
18
|
import { buildReactorFromPlugins, contribution, definePlugin, } from '@datalayer/reactor';
|
|
19
|
-
import {
|
|
19
|
+
import { listUI } from '../../../specs/ui';
|
|
20
20
|
import { LoopCanvasBlock, } from '../../core/canvasBlocks';
|
|
21
|
-
/** The name of the Reactor plugin that contributes a UI
|
|
22
|
-
export const canvasBlocksPluginName = (
|
|
23
|
-
/** A UI
|
|
24
|
-
export function uiPluginBlocks(
|
|
21
|
+
/** The name of the Reactor plugin that contributes a UI's blocks. */
|
|
22
|
+
export const canvasBlocksPluginName = (ui) => `@datalayer/loop-plugin-ui-${ui}`;
|
|
23
|
+
/** A UI of the catalogue as the Reactor plugin contributing its components as blocks. */
|
|
24
|
+
export function uiPluginBlocks(ui) {
|
|
25
25
|
return definePlugin({
|
|
26
|
-
name: canvasBlocksPluginName(
|
|
27
|
-
displayName:
|
|
28
|
-
description: `The blocks of ${
|
|
26
|
+
name: canvasBlocksPluginName(ui.id),
|
|
27
|
+
displayName: ui.name,
|
|
28
|
+
description: `The blocks of ${ui.name} on the Canvas: ${ui.components.map(component => component.name).join(', ')}.`,
|
|
29
29
|
octicon: 'apps',
|
|
30
|
-
contributes:
|
|
30
|
+
contributes: ui.components.map(component => contribution(LoopCanvasBlock, { id: component.id, ui: ui.id, component }, { id: component.id })),
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
|
-
* The plugins of the catalogue's UI
|
|
34
|
+
* The plugins of the catalogue's UI specs that render components and may
|
|
35
35
|
* be named today (`enabled` in the catalogue).
|
|
36
36
|
*/
|
|
37
|
-
export const CANVAS_BLOCK_PLUGINS =
|
|
38
|
-
.filter(
|
|
37
|
+
export const CANVAS_BLOCK_PLUGINS = listUI()
|
|
38
|
+
.filter(ui => ui.enabled && ui.components.length > 0)
|
|
39
39
|
.map(uiPluginBlocks);
|
|
40
40
|
/**
|
|
41
41
|
* A reactor holding the block plugins given, started, with those named in
|
|
@@ -53,9 +53,9 @@ export function canvasBlocksReactor(disabled = [], plugins = CANVAS_BLOCK_PLUGIN
|
|
|
53
53
|
return reactor;
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* The palette of an organization: the block plugins of the UI
|
|
56
|
+
* The palette of an organization: the block plugins of the UI specs it has
|
|
57
57
|
* turned off (`plugins_off` in IAM, catalogue ids such as 'a2ui') switched
|
|
58
|
-
* off. A UI
|
|
58
|
+
* off. A UI of the catalogue that contributes no block takes nothing
|
|
59
59
|
* off; an id the catalogue does not have is said by `unknownPluginsOff`.
|
|
60
60
|
*/
|
|
61
61
|
export function canvasBlocksReactorOf(pluginsOff) {
|
|
@@ -64,13 +64,13 @@ export function canvasBlocksReactorOf(pluginsOff) {
|
|
|
64
64
|
.map(canvasBlocksPluginName)
|
|
65
65
|
.filter(name => blockPlugins.has(name)));
|
|
66
66
|
}
|
|
67
|
-
/** The ids an organization turns off that no UI
|
|
67
|
+
/** The ids an organization turns off that no UI of the catalogue has. */
|
|
68
68
|
export function unknownPluginsOff(pluginsOff) {
|
|
69
|
-
const known = new Set(
|
|
69
|
+
const known = new Set(listUI().map(ui => ui.id));
|
|
70
70
|
return pluginsOff.filter(id => !known.has(id));
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
73
|
-
* What an application's page uses from a UI
|
|
73
|
+
* What an application's page uses from a UI its organization has
|
|
74
74
|
* turned off, as its setup notes say it (`blockSetupNotes`, on the palette of
|
|
75
75
|
* `canvasBlocksReactorOf`).
|
|
76
76
|
*/
|
|
@@ -96,7 +96,7 @@ export function componentsUsedBy(app) {
|
|
|
96
96
|
}
|
|
97
97
|
/**
|
|
98
98
|
* What an application's page uses that no enabled plugin contributes, as its
|
|
99
|
-
* setup notes say it: one sentence per UI
|
|
99
|
+
* setup notes say it: one sentence per UI of the catalogue whose
|
|
100
100
|
* blocks it uses while its plugin is off. A component the catalogue does not
|
|
101
101
|
* have is not a note but a problem of the instant checks.
|
|
102
102
|
*/
|
|
@@ -107,12 +107,12 @@ export function blockSetupNotes(app, reactor) {
|
|
|
107
107
|
if (contributed.has(name)) {
|
|
108
108
|
continue;
|
|
109
109
|
}
|
|
110
|
-
for (const
|
|
111
|
-
const component =
|
|
110
|
+
for (const ui of listUI()) {
|
|
111
|
+
const component = ui.components.find(each => each.id === name);
|
|
112
112
|
if (component) {
|
|
113
|
-
off.set(
|
|
113
|
+
off.set(ui, [...(off.get(ui) ?? []), component.name]);
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
-
return [...off.entries()].map(([
|
|
117
|
+
return [...off.entries()].map(([ui, names]) => `The UI “${ui.name}” is not enabled, and its page uses its ${names.length === 1 ? 'block' : 'blocks'} ${names.join(', ')}: ${names.length === 1 ? 'it is' : 'they are'} off the Canvas until it is.`);
|
|
118
118
|
}
|
|
@@ -15,7 +15,7 @@ type PartsReader = {
|
|
|
15
15
|
}>;
|
|
16
16
|
};
|
|
17
17
|
/** The short ids an organization turns off, and the plugin each names. */
|
|
18
|
-
export declare const CANVAS_PART_SOURCES: readonly ["connections", "skills", "models", "rules", "tests", "events"];
|
|
18
|
+
export declare const CANVAS_PART_SOURCES: readonly ["connections", "skills", "models", "rules", "tests", "events", "protocols", "ui", "characters"];
|
|
19
19
|
export type CanvasPartSource = (typeof CANVAS_PART_SOURCES)[number];
|
|
20
20
|
export declare const canvasPartsPluginName: (source: CanvasPartSource) => string;
|
|
21
21
|
/** A connection to each server of the catalogue: read-only, as its owner, every tool. */
|
|
@@ -30,6 +30,12 @@ export declare const RULE_PARTS: CanvasPartContribution[];
|
|
|
30
30
|
export declare const TEST_PARTS: CanvasPartContribution[];
|
|
31
31
|
/** The events an application answers (C-21): on a schedule, on an event, once. */
|
|
32
32
|
export declare const EVENT_PARTS: CanvasPartContribution[];
|
|
33
|
+
/** Each protocol of the catalogue (AGENT_PROTOCOLS PS-04): a planned one offered, not enabled. */
|
|
34
|
+
export declare const PROTOCOL_PARTS: CanvasPartContribution[];
|
|
35
|
+
/** Each UI of the catalogue its answers may render in (AGENT_PROTOCOLS PS-04). */
|
|
36
|
+
export declare const UI_PARTS: CanvasPartContribution[];
|
|
37
|
+
/** Datalayer's characters for its floating assistant, dropped on the agent (AGENT_PROTOCOLS PS-05). */
|
|
38
|
+
export declare const CHARACTER_PARTS: CanvasPartContribution[];
|
|
33
39
|
export declare const CANVAS_PART_PLUGINS: ReactorPlugin<Record<string, never>, unknown, unknown>[];
|
|
34
40
|
/** The toolbox's reactor, its named plugins disabled; a name no plugin has is refused. */
|
|
35
41
|
export declare function canvasPartsReactor(disabled?: readonly string[], plugins?: ReactorPlugin<any, any, any>[]): ReactorPlatform;
|
|
@@ -15,6 +15,9 @@ import { buildReactorFromPlugins, contribution, definePlugin, } from '@datalayer
|
|
|
15
15
|
import { MCP_SERVER_LIBRARY } from '../../../specs/mcpServers';
|
|
16
16
|
import { listChatModels } from '../../../specs/models';
|
|
17
17
|
import { getSkillSpecs } from '../../../specs/skills';
|
|
18
|
+
import { listProtocolSpecs } from '../../../specs/protocols';
|
|
19
|
+
import { listUI } from '../../../specs/ui';
|
|
20
|
+
import { ASSISTANT_CHARACTERS } from '../../../chat/assistant/characters';
|
|
18
21
|
import { LoopCanvasPart, } from '../../core/canvasParts';
|
|
19
22
|
/** The short ids an organization turns off, and the plugin each names. */
|
|
20
23
|
export const CANVAS_PART_SOURCES = [
|
|
@@ -24,6 +27,9 @@ export const CANVAS_PART_SOURCES = [
|
|
|
24
27
|
'rules',
|
|
25
28
|
'tests',
|
|
26
29
|
'events',
|
|
30
|
+
'protocols',
|
|
31
|
+
'ui',
|
|
32
|
+
'characters',
|
|
27
33
|
];
|
|
28
34
|
export const canvasPartsPluginName = (source) => `@datalayer/loop-plugin-parts-${source}`;
|
|
29
35
|
const partsPlugin = (source, displayName, parts) => definePlugin({
|
|
@@ -172,6 +178,33 @@ export const EVENT_PARTS = [
|
|
|
172
178
|
enabled: true,
|
|
173
179
|
},
|
|
174
180
|
];
|
|
181
|
+
/** Each protocol of the catalogue (AGENT_PROTOCOLS PS-04): a planned one offered, not enabled. */
|
|
182
|
+
export const PROTOCOL_PARTS = listProtocolSpecs().map(protocol => ({
|
|
183
|
+
id: `protocol:${protocol.id}`,
|
|
184
|
+
kind: 'protocol',
|
|
185
|
+
label: protocol.name,
|
|
186
|
+
says: protocol.connects,
|
|
187
|
+
example: protocol.id,
|
|
188
|
+
enabled: protocol.status === 'shipped',
|
|
189
|
+
}));
|
|
190
|
+
/** Each UI of the catalogue its answers may render in (AGENT_PROTOCOLS PS-04). */
|
|
191
|
+
export const UI_PARTS = listUI().map(ui => ({
|
|
192
|
+
id: `ui:${ui.id}`,
|
|
193
|
+
kind: 'ui',
|
|
194
|
+
label: ui.name,
|
|
195
|
+
says: ui.description,
|
|
196
|
+
example: ui.id,
|
|
197
|
+
enabled: ui.enabled,
|
|
198
|
+
}));
|
|
199
|
+
/** Datalayer's characters for its floating assistant, dropped on the agent (AGENT_PROTOCOLS PS-05). */
|
|
200
|
+
export const CHARACTER_PARTS = ASSISTANT_CHARACTERS.map(character => ({
|
|
201
|
+
id: `character:${character.id}`,
|
|
202
|
+
kind: 'character',
|
|
203
|
+
label: character.name,
|
|
204
|
+
says: `Its floating assistant shows ${character.name}.`,
|
|
205
|
+
example: character.id,
|
|
206
|
+
enabled: true,
|
|
207
|
+
}));
|
|
175
208
|
export const CANVAS_PART_PLUGINS = [
|
|
176
209
|
partsPlugin('connections', 'Connections', CONNECTION_PARTS),
|
|
177
210
|
partsPlugin('skills', 'Skills', SKILL_PARTS),
|
|
@@ -179,6 +212,9 @@ export const CANVAS_PART_PLUGINS = [
|
|
|
179
212
|
partsPlugin('rules', 'Rules', RULE_PARTS),
|
|
180
213
|
partsPlugin('tests', 'Tests', TEST_PARTS),
|
|
181
214
|
partsPlugin('events', 'Events', EVENT_PARTS),
|
|
215
|
+
partsPlugin('protocols', 'Protocols', PROTOCOL_PARTS),
|
|
216
|
+
partsPlugin('ui', 'UI', UI_PARTS),
|
|
217
|
+
partsPlugin('characters', 'Characters', CHARACTER_PARTS),
|
|
182
218
|
];
|
|
183
219
|
/** The toolbox's reactor, its named plugins disabled; a name no plugin has is refused. */
|
|
184
220
|
export function canvasPartsReactor(disabled = [], plugins = CANVAS_PART_PLUGINS) {
|
|
@@ -1374,6 +1374,13 @@ export default function ChatView({ workspace }) {
|
|
|
1374
1374
|
? `${agentServerUrl}/api/v1/apps/agents/${encodeURIComponent(agentId)}/ag-ui/`
|
|
1375
1375
|
: `${agentServerUrl}/api/v1/ag-ui/${agentId}/`,
|
|
1376
1376
|
...(runsApp && iamToken ? { authToken: iamToken } : {}),
|
|
1377
|
+
// Its session's ui channel (REACTOR_UI RU-W): what its answers
|
|
1378
|
+
// show, its steps and its elements, beside the run's text.
|
|
1379
|
+
...(runsApp
|
|
1380
|
+
? {
|
|
1381
|
+
uiSocket: `${agentServerUrl.replace(/^http/, 'ws')}/api/v1/apps/ui`,
|
|
1382
|
+
}
|
|
1383
|
+
: {}),
|
|
1377
1384
|
agentId,
|
|
1378
1385
|
// `/api/v1/configure`, not `/api/v1/configure/config`: the hooks
|
|
1379
1386
|
// strip one trailing `config`/`configure` segment to find the API
|