@datalayer/agent-runtimes 1.5.16 → 1.5.17
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-Dr-1g_cg.js +32 -0
- package/dist-embed/datalayer-app-main.js +59 -59
- package/lib/apps/apps/appspec.d.ts +5 -3
- package/lib/apps/apps/appspec.js +52 -10
- package/lib/apps/apps/threads.d.ts +20 -0
- package/lib/apps/apps/threads.js +31 -0
- package/lib/apps/plugins/canvas-blocks/index.d.ts +7 -9
- package/lib/apps/plugins/canvas-blocks/index.js +8 -10
- package/lib/apps/plugins/canvas-parts/index.d.ts +4 -1
- package/lib/apps/plugins/canvas-parts/index.js +7 -3
- package/lib/apps/plugins/chat/ChatView.js +11 -5
- package/lib/config/AgentConfiguration.d.ts +5 -1
- package/lib/specs/agents/agents.js +169 -169
- package/lib/specs/apps.js +4 -4
- package/lib/specs/appspecSchema.js +30 -2
- package/lib/specs/cogs.js +3 -3
- package/lib/specs/index.d.ts +1 -0
- package/lib/specs/index.js +1 -0
- package/lib/specs/sceneSchema.js +2 -0
- package/lib/specs/ui.d.ts +32 -6
- package/lib/specs/ui.js +760 -26
- package/lib/specs/uiRenderers.d.ts +17 -0
- package/lib/specs/uiRenderers.js +40 -0
- package/lib/types/agentspecs.d.ts +58 -12
- package/package.json +2 -2
- package/scripts/codegen/generate_agents.py +26 -9
- package/scripts/codegen/generate_ui.py +68 -22
- package/scripts/codegen/generate_ui_renderers.py +176 -0
- package/dist-embed/chunks/ChatView-nnI1-MOR.js +0 -32
|
@@ -97,9 +97,11 @@ export interface ParsedAppspec {
|
|
|
97
97
|
*/
|
|
98
98
|
export declare function parseAppspec(document: unknown): ParsedAppspec;
|
|
99
99
|
/**
|
|
100
|
-
* What is wrong with the UI an application
|
|
101
|
-
*
|
|
102
|
-
*
|
|
100
|
+
* What is wrong with the UI plugins an application names (AGENTIC_UI R8), in
|
|
101
|
+
* the sentences agentspecs says (`ui_choices_problems`): a plugin the
|
|
102
|
+
* catalogue does not have or said twice — a renderer named as a plugin is
|
|
103
|
+
* refused —, a renderer the catalogue does not have or the plugin may not be
|
|
104
|
+
* exposed through, and one not enabled while the application is offered.
|
|
103
105
|
*/
|
|
104
106
|
export declare function uiProblems(app: Pick<AppSpec, 'ui' | 'enabled'>): string[];
|
|
105
107
|
/**
|
package/lib/apps/apps/appspec.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { BEHAVIOURS } from './rules';
|
|
6
6
|
import { PROTOCOL_CATALOGUE } from '../../specs/protocols';
|
|
7
7
|
import { UI_CATALOGUE } from '../../specs/ui';
|
|
8
|
+
import { UI_RENDERER_CATALOGUE } from '../../specs/uiRenderers';
|
|
8
9
|
import { DEFAULT_MAX_FILES, DEFAULT_UPLOAD_MB } from './uploads';
|
|
9
10
|
/** The version of the spec itself. */
|
|
10
11
|
export const APP_SCHEMA = 'loop.app/v1';
|
|
@@ -90,6 +91,25 @@ const texts = (value) => Array.isArray(value)
|
|
|
90
91
|
? value.filter((item) => typeof item === 'string')
|
|
91
92
|
: [];
|
|
92
93
|
const records = (value) => Array.isArray(value) ? value.filter(isData) : [];
|
|
94
|
+
/**
|
|
95
|
+
* An application's UI plugins as its document says them (AGENTIC_UI R8):
|
|
96
|
+
* `{plugin, renderer}` each. A bare id — the old shape, a renderer named as a
|
|
97
|
+
* UI — is read as the plugin it names, which `uiProblems` refuses.
|
|
98
|
+
*/
|
|
99
|
+
const uiChoices = (value) => Array.isArray(value)
|
|
100
|
+
? value.flatMap((item) => typeof item === 'string'
|
|
101
|
+
? [{ plugin: item }]
|
|
102
|
+
: isData(item)
|
|
103
|
+
? [
|
|
104
|
+
{
|
|
105
|
+
plugin: text(item.plugin),
|
|
106
|
+
...(text(item.renderer)
|
|
107
|
+
? { renderer: text(item.renderer) }
|
|
108
|
+
: {}),
|
|
109
|
+
},
|
|
110
|
+
]
|
|
111
|
+
: [])
|
|
112
|
+
: [];
|
|
93
113
|
/**
|
|
94
114
|
* One turn of a test's conversation as its document says it (STUDIO E-01):
|
|
95
115
|
* what it says, chooses or presses, with a press's payload; nothing it does
|
|
@@ -984,7 +1004,7 @@ export function parseAppspec(document) {
|
|
|
984
1004
|
contents: texts(data.contents),
|
|
985
1005
|
connections: records(data.connections).map(parseConnection),
|
|
986
1006
|
protocols: texts(data.protocols),
|
|
987
|
-
ui:
|
|
1007
|
+
ui: uiChoices(data.ui),
|
|
988
1008
|
rules: records(data.rules).map(parseRule),
|
|
989
1009
|
permissions: {
|
|
990
1010
|
spaces: records(permissions.spaces).map(grant => ({
|
|
@@ -1097,25 +1117,45 @@ export function parseAppspec(document) {
|
|
|
1097
1117
|
return { app, problems };
|
|
1098
1118
|
}
|
|
1099
1119
|
/**
|
|
1100
|
-
* What is wrong with the UI an application
|
|
1101
|
-
*
|
|
1102
|
-
*
|
|
1120
|
+
* What is wrong with the UI plugins an application names (AGENTIC_UI R8), in
|
|
1121
|
+
* the sentences agentspecs says (`ui_choices_problems`): a plugin the
|
|
1122
|
+
* catalogue does not have or said twice — a renderer named as a plugin is
|
|
1123
|
+
* refused —, a renderer the catalogue does not have or the plugin may not be
|
|
1124
|
+
* exposed through, and one not enabled while the application is offered.
|
|
1103
1125
|
*/
|
|
1104
1126
|
export function uiProblems(app) {
|
|
1105
1127
|
const problems = [];
|
|
1106
1128
|
const seen = [];
|
|
1107
|
-
for (const
|
|
1129
|
+
for (const choice of app.ui) {
|
|
1130
|
+
const id = choice.plugin;
|
|
1108
1131
|
if (seen.includes(id)) {
|
|
1109
|
-
problems.push(`It lists the UI '${id}' twice.`);
|
|
1132
|
+
problems.push(`It lists the UI plugin '${id}' twice.`);
|
|
1110
1133
|
continue;
|
|
1111
1134
|
}
|
|
1112
1135
|
seen.push(id);
|
|
1113
1136
|
const spec = UI_CATALOGUE[id];
|
|
1114
1137
|
if (!spec) {
|
|
1115
|
-
problems.push(`There is no UI named '${id}': one of ${Object.keys(UI_CATALOGUE).sort().join(', ')}.`
|
|
1138
|
+
problems.push(`There is no UI plugin named '${id}': one of ${Object.keys(UI_CATALOGUE).sort().join(', ')}.` +
|
|
1139
|
+
(UI_RENDERER_CATALOGUE[id]
|
|
1140
|
+
? ` '${id}' is a UI renderer: say it as a plugin's \`renderer\`.`
|
|
1141
|
+
: ''));
|
|
1142
|
+
continue;
|
|
1143
|
+
}
|
|
1144
|
+
if (choice.renderer === undefined) {
|
|
1145
|
+
continue;
|
|
1146
|
+
}
|
|
1147
|
+
const renderer = UI_RENDERER_CATALOGUE[choice.renderer];
|
|
1148
|
+
if (!renderer) {
|
|
1149
|
+
problems.push(`There is no UI renderer named '${choice.renderer}': one of ${Object.keys(UI_RENDERER_CATALOGUE).sort().join(', ')}.`);
|
|
1150
|
+
}
|
|
1151
|
+
else if (!spec.renderers.includes(renderer.id)) {
|
|
1152
|
+
problems.push(`The UI plugin ${spec.name} ('${id}') is not exposed through ${renderer.name}: ` +
|
|
1153
|
+
(spec.renderers.length > 0
|
|
1154
|
+
? `through ${spec.renderers.join(', ')} only.`
|
|
1155
|
+
: 'through no renderer.'));
|
|
1116
1156
|
}
|
|
1117
|
-
else if (app.enabled && !
|
|
1118
|
-
problems.push(`The UI ${
|
|
1157
|
+
else if (app.enabled && !renderer.enabled) {
|
|
1158
|
+
problems.push(`The UI renderer ${renderer.name} ('${renderer.id}') is not enabled: an application cannot be exposed through it yet.`);
|
|
1119
1159
|
}
|
|
1120
1160
|
}
|
|
1121
1161
|
return problems;
|
|
@@ -1426,7 +1466,9 @@ export function dumpAppspec(app) {
|
|
|
1426
1466
|
.value('as', connection.as, 'owner')
|
|
1427
1467
|
.list('only', connection.only).data))
|
|
1428
1468
|
.list('protocols', app.protocols)
|
|
1429
|
-
.list('ui', app.ui
|
|
1469
|
+
.list('ui', app.ui.map(choice => choice.renderer
|
|
1470
|
+
? { plugin: choice.plugin, renderer: choice.renderer }
|
|
1471
|
+
: { plugin: choice.plugin }))
|
|
1430
1472
|
.part('pap', dumpPap(app.pap))
|
|
1431
1473
|
.part('pact', dumpPact(app.pact))
|
|
1432
1474
|
.part('commerce', dumpCommerce(app.commerce))
|
|
@@ -13,12 +13,32 @@
|
|
|
13
13
|
*
|
|
14
14
|
* @module apps/apps/threads
|
|
15
15
|
*/
|
|
16
|
+
import type { ResumedThread } from '../../types/chat';
|
|
16
17
|
import type { ChatMessage } from '../../types/messages';
|
|
17
18
|
/** What opening a thread says, in a person's words. */
|
|
18
19
|
export declare const THREAD_WORDS: {
|
|
19
20
|
readonly opening: "Opening your conversation…";
|
|
20
21
|
readonly notOpened: (detail: string) => string;
|
|
21
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* The deployment an application's agent is created for, as its create
|
|
25
|
+
* payload names it (`app_instance.deployment_uid`, `appDatalayerCreatePayload`),
|
|
26
|
+
* or `''` for a Preview, a test or no application.
|
|
27
|
+
*/
|
|
28
|
+
export declare function deploymentOfPayload(createPayload: Record<string, unknown> | undefined): string;
|
|
29
|
+
/**
|
|
30
|
+
* The thread a deployment's chat opens on when its host gave none: a new one,
|
|
31
|
+
* `id` (PAP_DATALAYER's release gates, found on r1, 14 October 2026).
|
|
32
|
+
*
|
|
33
|
+
* A deployment's agent serves every visitor, and what its runtime holds in
|
|
34
|
+
* memory is the last run's, whoever ran it: drawn as the page's
|
|
35
|
+
* conversation, a second account opening the same link saw the first
|
|
36
|
+
* person's turns. A given thread is drawn as given and never replaced by the
|
|
37
|
+
* runtime's snapshot, so each visitor sees only their own conversation —
|
|
38
|
+
* this one, or one opened from their history. A Preview, or a chat that runs
|
|
39
|
+
* no deployment, keeps what it was given.
|
|
40
|
+
*/
|
|
41
|
+
export declare function threadOfVisit(given: ResumedThread | undefined, deploymentUid: string, id: string): ResumedThread | undefined;
|
|
22
42
|
/** The AG-UI messages a session-API stream's `MESSAGES_SNAPSHOT` carries, if one does. */
|
|
23
43
|
export declare function snapshotOfStream(text: string): unknown[] | undefined;
|
|
24
44
|
/**
|
package/lib/apps/apps/threads.js
CHANGED
|
@@ -8,6 +8,37 @@ export const THREAD_WORDS = {
|
|
|
8
8
|
opening: 'Opening your conversation…',
|
|
9
9
|
notOpened: (detail) => `Your conversation could not be opened, so this is a new one: ${detail}`,
|
|
10
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
* The deployment an application's agent is created for, as its create
|
|
13
|
+
* payload names it (`app_instance.deployment_uid`, `appDatalayerCreatePayload`),
|
|
14
|
+
* or `''` for a Preview, a test or no application.
|
|
15
|
+
*/
|
|
16
|
+
export function deploymentOfPayload(createPayload) {
|
|
17
|
+
const instance = createPayload?.app_instance;
|
|
18
|
+
if (!instance || typeof instance !== 'object') {
|
|
19
|
+
return '';
|
|
20
|
+
}
|
|
21
|
+
const uid = instance.deployment_uid;
|
|
22
|
+
return typeof uid === 'string' ? uid.trim() : '';
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The thread a deployment's chat opens on when its host gave none: a new one,
|
|
26
|
+
* `id` (PAP_DATALAYER's release gates, found on r1, 14 October 2026).
|
|
27
|
+
*
|
|
28
|
+
* A deployment's agent serves every visitor, and what its runtime holds in
|
|
29
|
+
* memory is the last run's, whoever ran it: drawn as the page's
|
|
30
|
+
* conversation, a second account opening the same link saw the first
|
|
31
|
+
* person's turns. A given thread is drawn as given and never replaced by the
|
|
32
|
+
* runtime's snapshot, so each visitor sees only their own conversation —
|
|
33
|
+
* this one, or one opened from their history. A Preview, or a chat that runs
|
|
34
|
+
* no deployment, keeps what it was given.
|
|
35
|
+
*/
|
|
36
|
+
export function threadOfVisit(given, deploymentUid, id) {
|
|
37
|
+
if (given || !deploymentUid) {
|
|
38
|
+
return given;
|
|
39
|
+
}
|
|
40
|
+
return { id, messages: [] };
|
|
41
|
+
}
|
|
11
42
|
/** The AG-UI messages a session-API stream's `MESSAGES_SNAPSHOT` carries, if one does. */
|
|
12
43
|
export function snapshotOfStream(text) {
|
|
13
44
|
let found;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The Canvas's palette as a
|
|
3
|
-
* the catalogue that renders components (`agentspecs/ui`, C-13
|
|
4
|
-
*
|
|
2
|
+
* The Canvas's palette as a Contribution Point (LOOP C-12): each UI plugin
|
|
3
|
+
* of the catalogue that renders components (`agentspecs/ui`, C-13 — the
|
|
4
|
+
* A2UI surfaces, `a2ui-surface`) has its components contributed to
|
|
5
|
+
* `loop.canvas.block` by a Reactor plugin of its own, one per UI spec. The
|
|
5
6
|
* palette lists what the enabled plugins contribute, and nothing else; a
|
|
6
7
|
* plugin disabled takes its blocks off it, and an application that uses one
|
|
7
8
|
* of them says so in its setup notes (`blockSetupNotes`).
|
|
@@ -24,10 +25,7 @@ type BlocksReader = {
|
|
|
24
25
|
export declare const canvasBlocksPluginName: (ui: string) => string;
|
|
25
26
|
/** A UI of the catalogue as the Reactor plugin contributing its components as blocks. */
|
|
26
27
|
export declare function uiPluginBlocks(ui: UISpec): ReactorPlugin<Record<string, never>, unknown, unknown>;
|
|
27
|
-
/**
|
|
28
|
-
* The plugins of the catalogue's UI specs that render components and may
|
|
29
|
-
* be named today (`enabled` in the catalogue).
|
|
30
|
-
*/
|
|
28
|
+
/** The block plugins of the catalogue's UI plugins that render components. */
|
|
31
29
|
export declare const CANVAS_BLOCK_PLUGINS: ReactorPlugin<Record<string, never>, unknown, unknown>[];
|
|
32
30
|
/**
|
|
33
31
|
* A reactor holding the block plugins given, started, with those named in
|
|
@@ -35,8 +33,8 @@ export declare const CANVAS_BLOCK_PLUGINS: ReactorPlugin<Record<string, never>,
|
|
|
35
33
|
*/
|
|
36
34
|
export declare function canvasBlocksReactor(disabled?: readonly string[], plugins?: ReactorPlugin<any, any, any>[]): ReactorPlatform;
|
|
37
35
|
/**
|
|
38
|
-
* The palette of an organization: the block plugins of the UI
|
|
39
|
-
* turned off (`plugins_off` in IAM,
|
|
36
|
+
* The palette of an organization: the block plugins of the UI plugins it has
|
|
37
|
+
* turned off (`plugins_off` in IAM, ids of `agentspecs/ui` such as 'a2ui-surface') switched
|
|
40
38
|
* off. A UI of the catalogue that contributes no block takes nothing
|
|
41
39
|
* off; an id the catalogue does not have is said by `unknownPluginsOff`.
|
|
42
40
|
*/
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
|
-
* The Canvas's palette as a
|
|
7
|
-
* the catalogue that renders components (`agentspecs/ui`, C-13
|
|
8
|
-
*
|
|
6
|
+
* The Canvas's palette as a Contribution Point (LOOP C-12): each UI plugin
|
|
7
|
+
* of the catalogue that renders components (`agentspecs/ui`, C-13 — the
|
|
8
|
+
* A2UI surfaces, `a2ui-surface`) has its components contributed to
|
|
9
|
+
* `loop.canvas.block` by a Reactor plugin of its own, one per UI spec. The
|
|
9
10
|
* palette lists what the enabled plugins contribute, and nothing else; a
|
|
10
11
|
* plugin disabled takes its blocks off it, and an application that uses one
|
|
11
12
|
* of them says so in its setup notes (`blockSetupNotes`).
|
|
@@ -30,12 +31,9 @@ export function uiPluginBlocks(ui) {
|
|
|
30
31
|
contributes: ui.components.map(component => contribution(LoopCanvasBlock, { id: component.id, ui: ui.id, component }, { id: component.id })),
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
|
-
/**
|
|
34
|
-
* The plugins of the catalogue's UI specs that render components and may
|
|
35
|
-
* be named today (`enabled` in the catalogue).
|
|
36
|
-
*/
|
|
34
|
+
/** The block plugins of the catalogue's UI plugins that render components. */
|
|
37
35
|
export const CANVAS_BLOCK_PLUGINS = listUI()
|
|
38
|
-
.filter(ui => ui.
|
|
36
|
+
.filter(ui => ui.components.length > 0)
|
|
39
37
|
.map(uiPluginBlocks);
|
|
40
38
|
/**
|
|
41
39
|
* A reactor holding the block plugins given, started, with those named in
|
|
@@ -53,8 +51,8 @@ export function canvasBlocksReactor(disabled = [], plugins = CANVAS_BLOCK_PLUGIN
|
|
|
53
51
|
return reactor;
|
|
54
52
|
}
|
|
55
53
|
/**
|
|
56
|
-
* The palette of an organization: the block plugins of the UI
|
|
57
|
-
* turned off (`plugins_off` in IAM,
|
|
54
|
+
* The palette of an organization: the block plugins of the UI plugins it has
|
|
55
|
+
* turned off (`plugins_off` in IAM, ids of `agentspecs/ui` such as 'a2ui-surface') switched
|
|
58
56
|
* off. A UI of the catalogue that contributes no block takes nothing
|
|
59
57
|
* off; an id the catalogue does not have is said by `unknownPluginsOff`.
|
|
60
58
|
*/
|
|
@@ -32,7 +32,10 @@ export declare const TEST_PARTS: CanvasPartContribution[];
|
|
|
32
32
|
export declare const EVENT_PARTS: CanvasPartContribution[];
|
|
33
33
|
/** Each protocol of the catalogue (AGENT_PROTOCOLS PS-04): a planned one offered, not enabled. */
|
|
34
34
|
export declare const PROTOCOL_PARTS: CanvasPartContribution[];
|
|
35
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Each UI plugin of the catalogue (AGENTIC_UI R8): a part of the agent's
|
|
37
|
+
* interface, dropped on it, then exposed through a renderer it may be.
|
|
38
|
+
*/
|
|
36
39
|
export declare const UI_PARTS: CanvasPartContribution[];
|
|
37
40
|
/** Datalayer's characters for its floating assistant, dropped on the agent (AGENT_PROTOCOLS PS-05). */
|
|
38
41
|
export declare const CHARACTER_PARTS: CanvasPartContribution[];
|
|
@@ -187,14 +187,18 @@ export const PROTOCOL_PARTS = listProtocolSpecs().map(protocol => ({
|
|
|
187
187
|
example: protocol.id,
|
|
188
188
|
enabled: protocol.status === 'shipped',
|
|
189
189
|
}));
|
|
190
|
-
/**
|
|
190
|
+
/**
|
|
191
|
+
* Each UI plugin of the catalogue (AGENTIC_UI R8): a part of the agent's
|
|
192
|
+
* interface, dropped on it, then exposed through a renderer it may be.
|
|
193
|
+
*/
|
|
191
194
|
export const UI_PARTS = listUI().map(ui => ({
|
|
192
195
|
id: `ui:${ui.id}`,
|
|
193
196
|
kind: 'ui',
|
|
194
197
|
label: ui.name,
|
|
195
198
|
says: ui.description,
|
|
196
|
-
|
|
197
|
-
|
|
199
|
+
// The Appspec's `ui` entry it adds: the plugin, its renderer chosen after.
|
|
200
|
+
example: { plugin: ui.id },
|
|
201
|
+
enabled: true,
|
|
198
202
|
}));
|
|
199
203
|
/** Datalayer's characters for its floating assistant, dropped on the agent (AGENT_PROTOCOLS PS-05). */
|
|
200
204
|
export const CHARACTER_PARTS = ASSISTANT_CHARACTERS.map(character => ({
|
|
@@ -48,7 +48,7 @@ import { isInactiveSurfaceContribution, orderToolContributions, toolsForChatView
|
|
|
48
48
|
import { agentBundleToolDefinitions, useAgentCommandTools, } from '../../../tools/adapters/commands';
|
|
49
49
|
import { NONE_EDITOR, seedEditorChoice, setEditorOptions, } from '../shell/editorChoice';
|
|
50
50
|
import { generateMessageId } from '../../../types/messages';
|
|
51
|
-
import { openThread, THREAD_WORDS } from '../../apps/threads';
|
|
51
|
+
import { deploymentOfPayload, openThread, THREAD_WORDS, threadOfVisit, } from '../../apps/threads';
|
|
52
52
|
import { FaceDrawing, PresenceFace, PresenceLine, } from '../../../chat/presence/Presence';
|
|
53
53
|
import { presenceState, presenceToolOf, } from '../../../chat/presence/presenceStatus';
|
|
54
54
|
import { latestSaying, newestIsAnswer, } from '../../../chat/assistant/state';
|
|
@@ -1280,9 +1280,10 @@ export default function ChatView({ workspace }) {
|
|
|
1280
1280
|
* not published (STUDIO D-15). It speaks to the application's session API,
|
|
1281
1281
|
* whose refusal says why.
|
|
1282
1282
|
*/
|
|
1283
|
-
const
|
|
1284
|
-
|
|
1285
|
-
|
|
1283
|
+
const hostCreatePayload = reactor.getConfig(AGENTS_PLUGIN_NAME)?.datalayerCreatePayload;
|
|
1284
|
+
const runsApp = Boolean(blueprintTurn?.createPayload?.app_spec || hostCreatePayload?.app_spec);
|
|
1285
|
+
// The deployment its host runs, if it runs one: its agent is every visitor's.
|
|
1286
|
+
const deploymentUid = deploymentOfPayload(hostCreatePayload);
|
|
1286
1287
|
const memberToken = useIAMStore(state => state.token);
|
|
1287
1288
|
/*
|
|
1288
1289
|
* Without an account (LOOP R-30) the application runs on the visitors'
|
|
@@ -1300,7 +1301,12 @@ export default function ChatView({ workspace }) {
|
|
|
1300
1301
|
* its record — then drawn and gone on with on the same thread. One that
|
|
1301
1302
|
* cannot be opened is said, and a new one starts.
|
|
1302
1303
|
*/
|
|
1303
|
-
|
|
1304
|
+
/*
|
|
1305
|
+
* A deployment's visit with no thread given opens a new one: its runtime's
|
|
1306
|
+
* agent holds every visitor's turns, never drawn as this person's.
|
|
1307
|
+
*/
|
|
1308
|
+
const [visitThreadId] = useState(generateMessageId);
|
|
1309
|
+
const givenThread = useMemo(() => threadOfVisit(config?.thread, deploymentUid, visitThreadId), [config?.thread, deploymentUid, visitThreadId]);
|
|
1304
1310
|
const [openedThread, setOpenedThread] = useState(null);
|
|
1305
1311
|
const opening = Boolean(givenThread?.fromRuntime && openedThread?.given !== givenThread.id);
|
|
1306
1312
|
useEffect(() => {
|
|
@@ -29,7 +29,11 @@ export interface LibraryAgentspec {
|
|
|
29
29
|
welcomeDocument?: string | null;
|
|
30
30
|
sandboxVariant?: string | null;
|
|
31
31
|
protocol?: string | null;
|
|
32
|
-
|
|
32
|
+
/** Its UI plugins, each with the renderer it is exposed through (AGENTIC_UI R8). */
|
|
33
|
+
ui?: Array<{
|
|
34
|
+
plugin: string;
|
|
35
|
+
renderer?: string;
|
|
36
|
+
}> | null;
|
|
33
37
|
trigger?: Record<string, unknown> | null;
|
|
34
38
|
modelConfig?: Record<string, unknown> | null;
|
|
35
39
|
mcpServerTools?: Array<Record<string, unknown>> | null;
|