@datalayer/agent-runtimes 1.3.25 → 1.3.28

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.
Files changed (43) hide show
  1. package/lib/chat/messages/ChatMessages.d.ts +4 -4
  2. package/lib/chat/messages/ChatMessages.js +17 -17
  3. package/lib/config/AgentConfiguration.js +1 -1
  4. package/lib/examples/example-selector.js +1 -1
  5. package/lib/loop/apps/AppRenderer.d.ts +8 -1
  6. package/lib/loop/apps/AppRenderer.js +10 -2
  7. package/lib/loop/apps/checks.d.ts +6 -1
  8. package/lib/loop/apps/checks.js +17 -0
  9. package/lib/loop/embed/LoopEmbed.js +14 -1
  10. package/lib/loop/plugins/chat/ChatView.js +40 -6
  11. package/lib/loop/plugins/chat/Presence.d.ts +9 -0
  12. package/lib/loop/plugins/chat/Presence.js +57 -0
  13. package/lib/loop/plugins/chat/index.d.ts +27 -0
  14. package/lib/loop/plugins/chat/presenceStatus.d.ts +26 -0
  15. package/lib/loop/plugins/chat/presenceStatus.js +28 -0
  16. package/lib/loop/presets.d.ts +5 -1
  17. package/lib/loop/presets.js +4 -2
  18. package/lib/protocols/A2AAdapter.d.ts +1 -1
  19. package/lib/specs/uiPlugins.d.ts +6 -1
  20. package/lib/specs/uiPlugins.js +471 -0
  21. package/lib/stores/chatStore.d.ts +11 -11
  22. package/lib/stores/chatStore.js +34 -34
  23. package/lib/stores/index.d.ts +1 -1
  24. package/lib/stores/index.js +1 -1
  25. package/lib/types/agentspecs.d.ts +33 -0
  26. package/lib/types/index.d.ts +1 -1
  27. package/lib/types/index.js +1 -1
  28. package/lib/types/{extensions.d.ts → uiPlugins.d.ts} +49 -49
  29. package/lib/types/{extensions.js → uiPlugins.js} +8 -8
  30. package/lib/{extensions/A2UIExtension.d.ts → ui-plugins/A2UIPlugin.d.ts} +7 -7
  31. package/lib/{extensions/A2UIExtension.js → ui-plugins/A2UIPlugin.js} +4 -4
  32. package/lib/{extensions/MCPUIExtension.d.ts → ui-plugins/MCPUIPlugin.d.ts} +9 -9
  33. package/lib/{extensions/MCPUIExtension.js → ui-plugins/MCPUIPlugin.js} +6 -6
  34. package/lib/ui-plugins/UIPluginRegistry.d.ts +65 -0
  35. package/lib/{extensions/ExtensionRegistry.js → ui-plugins/UIPluginRegistry.js} +32 -32
  36. package/lib/ui-plugins/index.d.ts +9 -0
  37. package/lib/ui-plugins/index.js +12 -0
  38. package/package.json +1 -1
  39. package/scripts/codegen/generate_agents.py +6 -6
  40. package/scripts/codegen/generate_ui_plugins.py +64 -4
  41. package/lib/extensions/ExtensionRegistry.d.ts +0 -65
  42. package/lib/extensions/index.d.ts +0 -9
  43. package/lib/extensions/index.js +0 -12
@@ -9,6 +9,462 @@ export const A2UI_UI_PLUGIN_0_0_1 = {
9
9
  description: 'An agent describes an interface — a form, a table, a card — as a tree of components from a catalogue the host allows, and the host renders it; what the user does in it comes back to the agent as an action.',
10
10
  docsUrl: 'https://a2ui.org/',
11
11
  enabled: true,
12
+ catalog: 'a2ui/v0.9',
13
+ components: [
14
+ {
15
+ id: 'Text',
16
+ name: 'Text',
17
+ category: 'text',
18
+ emoji: '🔤',
19
+ description: 'Words on the page: a heading, a paragraph, the answer — plain or Markdown.',
20
+ standard: true,
21
+ events: [],
22
+ },
23
+ {
24
+ id: 'Image',
25
+ name: 'Image',
26
+ category: 'media',
27
+ emoji: '🖼️',
28
+ description: 'A picture: a chart rendered elsewhere, a logo, a photo.',
29
+ standard: true,
30
+ events: [],
31
+ },
32
+ {
33
+ id: 'Icon',
34
+ name: 'Icon',
35
+ category: 'media',
36
+ emoji: '🔣',
37
+ description: 'A small drawing that says what something is: a check, a warning, a link.',
38
+ standard: true,
39
+ events: [],
40
+ },
41
+ {
42
+ id: 'Video',
43
+ name: 'Video',
44
+ category: 'media',
45
+ emoji: '🎬',
46
+ description: 'A film played in place.',
47
+ standard: true,
48
+ events: [],
49
+ },
50
+ {
51
+ id: 'AudioPlayer',
52
+ name: 'Audio',
53
+ category: 'media',
54
+ emoji: '🔊',
55
+ description: 'A sound played in place: a recording, a summary read aloud.',
56
+ standard: true,
57
+ events: [],
58
+ },
59
+ {
60
+ id: 'Row',
61
+ name: 'Row',
62
+ category: 'layout',
63
+ emoji: '➡️',
64
+ description: 'Children side by side, left to right.',
65
+ standard: true,
66
+ events: [],
67
+ },
68
+ {
69
+ id: 'Column',
70
+ name: 'Column',
71
+ category: 'layout',
72
+ emoji: '⬇️',
73
+ description: 'Children one under the other.',
74
+ standard: true,
75
+ events: [],
76
+ },
77
+ {
78
+ id: 'List',
79
+ name: 'List',
80
+ category: 'layout',
81
+ emoji: '📃',
82
+ description: 'Items one after the other, each drawn by the same children: results, alternatives, steps.',
83
+ standard: true,
84
+ events: [],
85
+ },
86
+ {
87
+ id: 'Card',
88
+ name: 'Card',
89
+ category: 'layout',
90
+ emoji: '🗂️',
91
+ description: 'A framed group: what belongs together, set apart.',
92
+ standard: true,
93
+ events: [],
94
+ },
95
+ {
96
+ id: 'Tabs',
97
+ name: 'Tabs',
98
+ category: 'layout',
99
+ emoji: '📑',
100
+ description: 'Several views of one place, one shown at a time.',
101
+ standard: true,
102
+ events: [],
103
+ },
104
+ {
105
+ id: 'Divider',
106
+ name: 'Divider',
107
+ category: 'layout',
108
+ emoji: '➖',
109
+ description: 'A line between what comes before and after.',
110
+ standard: true,
111
+ events: [],
112
+ },
113
+ {
114
+ id: 'Modal',
115
+ name: 'Modal',
116
+ category: 'layout',
117
+ emoji: '🪟',
118
+ description: 'A window over the page, opened by a trigger: details, a confirmation.',
119
+ standard: true,
120
+ events: [],
121
+ },
122
+ {
123
+ id: 'Button',
124
+ name: 'Button',
125
+ category: 'action',
126
+ emoji: '🔘',
127
+ description: 'An action the person takes: send, run, approve. One filled button per screen.',
128
+ standard: true,
129
+ events: [],
130
+ },
131
+ {
132
+ id: 'TextField',
133
+ name: 'Input',
134
+ category: 'input',
135
+ emoji: '⌨️',
136
+ description: 'A field the person types in: a word, a sentence, a number, a date.',
137
+ standard: true,
138
+ events: [],
139
+ },
140
+ {
141
+ id: 'CheckBox',
142
+ name: 'Checkbox',
143
+ category: 'input',
144
+ emoji: '☑️',
145
+ description: 'Yes or no: an option on or off, a consent given.',
146
+ standard: true,
147
+ events: [],
148
+ },
149
+ {
150
+ id: 'ChoicePicker',
151
+ name: 'Select',
152
+ category: 'input',
153
+ emoji: '🔽',
154
+ description: 'One choice, or several, among options the builder lists or the data gives.',
155
+ standard: true,
156
+ events: [],
157
+ },
158
+ {
159
+ id: 'Slider',
160
+ name: 'Slider',
161
+ category: 'input',
162
+ emoji: '🎚️',
163
+ description: 'A number chosen along a range: a weight, a budget, a threshold.',
164
+ standard: true,
165
+ events: [],
166
+ },
167
+ {
168
+ id: 'DateTimeInput',
169
+ name: 'Date and time',
170
+ category: 'input',
171
+ emoji: '📅',
172
+ description: 'A date, a time, or both, chosen from a calendar.',
173
+ standard: true,
174
+ events: [],
175
+ },
176
+ {
177
+ id: 'Table',
178
+ name: 'Table',
179
+ category: 'data',
180
+ emoji: '📋',
181
+ description: 'Rows the application found or keeps, with the columns the builder chooses.',
182
+ standard: false,
183
+ properties: {
184
+ type: 'object',
185
+ required: ['columns'],
186
+ properties: {
187
+ title: {
188
+ type: 'string',
189
+ title: 'Title',
190
+ description: 'What the table is, above it.',
191
+ },
192
+ columns: {
193
+ type: 'array',
194
+ title: 'Columns',
195
+ description: 'The columns, in order.',
196
+ minItems: 1,
197
+ items: {
198
+ type: 'string',
199
+ },
200
+ },
201
+ page_size: {
202
+ type: 'integer',
203
+ title: 'Rows per page',
204
+ description: 'How many rows show at once.',
205
+ minimum: 1,
206
+ maximum: 500,
207
+ default: 20,
208
+ },
209
+ selectable: {
210
+ type: 'boolean',
211
+ title: 'Selectable',
212
+ description: 'A row may be chosen, and its choice sent.',
213
+ default: false,
214
+ },
215
+ },
216
+ },
217
+ bindings: {
218
+ shows: ['rows'],
219
+ sends: ['selected'],
220
+ },
221
+ events: ['select'],
222
+ example: {
223
+ title: 'Runs',
224
+ columns: ['model', 'pass rate', 'cost'],
225
+ },
226
+ },
227
+ {
228
+ id: 'Chart',
229
+ name: 'Chart',
230
+ category: 'data',
231
+ emoji: '📊',
232
+ description: 'Numbers drawn: a bar, a line, a scatter of what the application measured.',
233
+ standard: false,
234
+ properties: {
235
+ type: 'object',
236
+ required: ['kind', 'x', 'y'],
237
+ properties: {
238
+ title: {
239
+ type: 'string',
240
+ title: 'Title',
241
+ description: 'What the chart shows, above it.',
242
+ },
243
+ kind: {
244
+ type: 'string',
245
+ title: 'Kind',
246
+ description: 'How the numbers are drawn.',
247
+ enum: ['bar', 'line', 'scatter', 'area'],
248
+ default: 'bar',
249
+ },
250
+ x: {
251
+ type: 'string',
252
+ title: 'Across',
253
+ description: 'The field along the bottom.',
254
+ },
255
+ y: {
256
+ type: 'string',
257
+ title: 'Up',
258
+ description: 'The field measured.',
259
+ },
260
+ series: {
261
+ type: 'string',
262
+ title: 'Series',
263
+ description: 'A field whose values are drawn apart.',
264
+ },
265
+ },
266
+ },
267
+ bindings: {
268
+ shows: ['points'],
269
+ sends: [],
270
+ },
271
+ events: [],
272
+ example: {
273
+ kind: 'bar',
274
+ x: 'model',
275
+ y: 'pass rate',
276
+ },
277
+ },
278
+ {
279
+ id: 'FileUpload',
280
+ name: 'File upload',
281
+ category: 'input',
282
+ emoji: '📎',
283
+ description: 'A file the person gives the application: a document to read, a sheet to check.',
284
+ standard: false,
285
+ properties: {
286
+ type: 'object',
287
+ required: ['label'],
288
+ properties: {
289
+ label: {
290
+ type: 'string',
291
+ title: 'Label',
292
+ description: 'What the person reads beside it.',
293
+ },
294
+ accept: {
295
+ type: 'array',
296
+ title: 'Accepts',
297
+ description: 'The kinds of file it takes, by extension.',
298
+ items: {
299
+ type: 'string',
300
+ pattern: '^\\.[a-z0-9]+$',
301
+ },
302
+ },
303
+ multiple: {
304
+ type: 'boolean',
305
+ title: 'Several',
306
+ description: 'More than one file at once.',
307
+ default: false,
308
+ },
309
+ max_mb: {
310
+ type: 'integer',
311
+ title: 'Largest (MB)',
312
+ description: 'The largest file it takes.',
313
+ minimum: 1,
314
+ maximum: 500,
315
+ default: 25,
316
+ },
317
+ },
318
+ },
319
+ bindings: {
320
+ shows: [],
321
+ sends: ['files'],
322
+ },
323
+ events: ['upload'],
324
+ example: {
325
+ label: 'The contract',
326
+ accept: ['.pdf', '.docx'],
327
+ },
328
+ },
329
+ {
330
+ id: 'Chat',
331
+ name: 'Chat',
332
+ category: 'conversation',
333
+ emoji: '💬',
334
+ description: 'The conversation with the application: its welcome, its starters, the composer.',
335
+ standard: false,
336
+ properties: {
337
+ type: 'object',
338
+ properties: {
339
+ welcome: {
340
+ type: 'string',
341
+ title: 'Welcome',
342
+ description: 'What it says before anyone writes.',
343
+ },
344
+ placeholder: {
345
+ type: 'string',
346
+ title: 'Composer hint',
347
+ description: 'Shown in the composer while it is empty.',
348
+ default: 'Ask anything',
349
+ },
350
+ starters: {
351
+ type: 'array',
352
+ title: 'Starters',
353
+ description: 'Questions offered before the first message.',
354
+ maxItems: 6,
355
+ items: {
356
+ type: 'string',
357
+ },
358
+ },
359
+ show_tools: {
360
+ type: 'boolean',
361
+ title: 'Shows its tools',
362
+ description: 'The tool calls are shown as they happen.',
363
+ default: true,
364
+ },
365
+ },
366
+ },
367
+ bindings: {
368
+ shows: ['messages'],
369
+ sends: ['message'],
370
+ },
371
+ events: ['send'],
372
+ example: {
373
+ welcome: 'Ask me to research anything.',
374
+ starters: ['What changed in Python 3.13?'],
375
+ },
376
+ },
377
+ {
378
+ id: 'Evidence',
379
+ name: 'Evidence',
380
+ category: 'data',
381
+ emoji: '🔎',
382
+ description: 'What an answer rests on: the sources opened, the passages cited, each with its link.',
383
+ standard: false,
384
+ properties: {
385
+ type: 'object',
386
+ properties: {
387
+ title: {
388
+ type: 'string',
389
+ title: 'Title',
390
+ description: 'Above the sources.',
391
+ default: 'Sources',
392
+ },
393
+ show_passages: {
394
+ type: 'boolean',
395
+ title: 'Shows passages',
396
+ description: 'Each source with the passage cited from it.',
397
+ default: true,
398
+ },
399
+ max_items: {
400
+ type: 'integer',
401
+ title: 'Most shown',
402
+ description: 'How many sources show before *more*.',
403
+ minimum: 1,
404
+ maximum: 50,
405
+ default: 5,
406
+ },
407
+ },
408
+ },
409
+ bindings: {
410
+ shows: ['sources'],
411
+ sends: [],
412
+ },
413
+ events: ['open'],
414
+ example: {
415
+ title: 'What this rests on',
416
+ },
417
+ },
418
+ {
419
+ id: 'Form',
420
+ name: 'Form',
421
+ category: 'input',
422
+ emoji: '🧾',
423
+ description: 'Several fields asked at once, from a JSON Schema, checked as they are filled and again when they arrive (drawn with @datalayer/primer-rjsf).',
424
+ standard: false,
425
+ properties: {
426
+ type: 'object',
427
+ required: ['schema'],
428
+ properties: {
429
+ title: {
430
+ type: 'string',
431
+ title: 'Title',
432
+ description: 'What the form is for, above it.',
433
+ },
434
+ schema: {
435
+ type: 'object',
436
+ title: 'Fields',
437
+ description: 'The JSON Schema of what is asked: its fields, their types, what is required.',
438
+ },
439
+ submit_label: {
440
+ type: 'string',
441
+ title: 'Send button',
442
+ description: 'The words on its button.',
443
+ default: 'Send',
444
+ },
445
+ },
446
+ },
447
+ bindings: {
448
+ shows: ['values'],
449
+ sends: ['values'],
450
+ },
451
+ events: ['submit'],
452
+ example: {
453
+ title: 'The quote',
454
+ schema: {
455
+ type: 'object',
456
+ required: ['seats'],
457
+ properties: {
458
+ seats: {
459
+ type: 'integer',
460
+ minimum: 1,
461
+ title: 'Seats',
462
+ },
463
+ },
464
+ },
465
+ },
466
+ },
467
+ ],
12
468
  };
13
469
  export const MCP_APPS_UI_PLUGIN_0_0_1 = {
14
470
  id: 'mcp-apps',
@@ -17,6 +473,8 @@ export const MCP_APPS_UI_PLUGIN_0_0_1 = {
17
473
  description: "An MCP server ships an interactive app with a tool: the host renders it in a sandboxed frame beside the conversation, and the app calls the server's tools through the host.",
18
474
  docsUrl: 'https://modelcontextprotocol.io/docs/extensions/apps',
19
475
  enabled: false,
476
+ catalog: '',
477
+ components: [],
20
478
  };
21
479
  export const MCP_UI_UI_PLUGIN_0_0_1 = {
22
480
  id: 'mcp-ui',
@@ -25,6 +483,8 @@ export const MCP_UI_UI_PLUGIN_0_0_1 = {
25
483
  description: 'An MCP tool answers with a UI resource — HTML, a remote page or a component — that the host renders in place of plain text.',
26
484
  docsUrl: 'https://mcpui.dev/',
27
485
  enabled: false,
486
+ catalog: '',
487
+ components: [],
28
488
  };
29
489
  export const UI_PLUGIN_CATALOGUE = {
30
490
  a2ui: A2UI_UI_PLUGIN_0_0_1,
@@ -38,3 +498,14 @@ export function getUIPlugin(pluginId) {
38
498
  export function listUIPlugins() {
39
499
  return Object.values(UI_PLUGIN_CATALOGUE);
40
500
  }
501
+ /** The visual components the enabled UI plugins render, by the name a surface gives them (LOOP C-13). */
502
+ export const COMPONENT_CATALOGUE = Object.fromEntries(Object.values(UI_PLUGIN_CATALOGUE)
503
+ .filter(plugin => plugin.enabled)
504
+ .flatMap(plugin => plugin.components.map(component => [component.id, component])));
505
+ /** The component a layout names, or undefined. */
506
+ export function getComponent(name) {
507
+ return COMPONENT_CATALOGUE[name];
508
+ }
509
+ export function listComponents() {
510
+ return Object.values(COMPONENT_CATALOGUE);
511
+ }
@@ -1,10 +1,10 @@
1
- import type { ChatMessage, ChatThread, ToolRegistryEntry, ToolDefinition, ChatExtension, ExtensionRegistryEntry, ChatMiddleware } from '../types';
1
+ import type { ChatMessage, ChatThread, ToolRegistryEntry, ToolDefinition, ChatUIPlugin, UIPluginRegistryEntry, ChatMiddleware } from '../types';
2
2
  import type { ToolCallStatus } from '../types/messages';
3
3
  import type { InferenceProvider } from '../types/inference';
4
4
  import type { ProtocolAdapter } from '../types/protocol';
5
5
  import type { ToolExecutor } from '../tools/ToolExecutor';
6
6
  import type { MiddlewarePipeline } from '../middleware/MiddlewarePipeline';
7
- import type { ExtensionRegistry } from '../extensions/ExtensionRegistry';
7
+ import type { UIPluginRegistry } from '../ui-plugins/UIPluginRegistry';
8
8
  /**
9
9
  * Chat configuration options
10
10
  */
@@ -59,7 +59,7 @@ export interface ChatState {
59
59
  protocolAdapter: ProtocolAdapter | null;
60
60
  toolExecutor: ToolExecutor | null;
61
61
  middlewarePipeline: MiddlewarePipeline | null;
62
- extensionRegistry: ExtensionRegistry | null;
62
+ uiPluginRegistry: UIPluginRegistry | null;
63
63
  messages: ChatMessage[];
64
64
  isLoading: boolean;
65
65
  isStreaming: boolean;
@@ -68,7 +68,7 @@ export interface ChatState {
68
68
  threads: Map<string, ChatThread>;
69
69
  tools: Map<string, ToolRegistryEntry>;
70
70
  pendingToolCalls: Map<string, ToolCallState>;
71
- extensions: Map<string, ExtensionRegistryEntry>;
71
+ uiPlugins: Map<string, UIPluginRegistryEntry>;
72
72
  middlewares: ChatMiddleware[];
73
73
  isOpen: boolean;
74
74
  error: Error | null;
@@ -84,7 +84,7 @@ export interface ChatActions {
84
84
  setProtocolAdapter: (adapter: ProtocolAdapter | null) => void;
85
85
  setToolExecutor: (executor: ToolExecutor | null) => void;
86
86
  setMiddlewarePipeline: (pipeline: MiddlewarePipeline | null) => void;
87
- setExtensionRegistry: (registry: ExtensionRegistry | null) => void;
87
+ setUIPluginRegistry: (registry: UIPluginRegistry | null) => void;
88
88
  addMessage: (message: ChatMessage) => void;
89
89
  updateMessage: (messageId: string, updates: Partial<ChatMessage>) => void;
90
90
  deleteMessage: (messageId: string) => void;
@@ -105,13 +105,13 @@ export interface ChatActions {
105
105
  startToolCall: (toolCallId: string, toolName: string, args: Record<string, unknown>) => void;
106
106
  updateToolCallStatus: (toolCallId: string, status: ToolCallStatus, result?: unknown, error?: string) => void;
107
107
  getPendingToolCalls: () => ToolCallState[];
108
- registerExtension: (extension: ChatExtension, options?: {
108
+ registerUIPlugin: (plugin: ChatUIPlugin, options?: {
109
109
  enabled?: boolean;
110
110
  }) => void;
111
- unregisterExtension: (name: string) => void;
112
- enableExtension: (name: string) => void;
113
- disableExtension: (name: string) => void;
114
- getExtensions: <T extends ChatExtension>(type?: T['type']) => T[];
111
+ unregisterUIPlugin: (name: string) => void;
112
+ enableUIPlugin: (name: string) => void;
113
+ disableUIPlugin: (name: string) => void;
114
+ getUIPlugins: <T extends ChatUIPlugin>(type?: T['type']) => T[];
115
115
  addMiddleware: (middleware: ChatMiddleware) => void;
116
116
  removeMiddleware: (name: string) => void;
117
117
  getMiddlewares: () => ChatMiddleware[];
@@ -155,4 +155,4 @@ export declare const useChatOpen: () => boolean;
155
155
  export declare const useChatConfig: () => ChatConfig;
156
156
  export declare const useChatReady: () => boolean;
157
157
  export declare const useChatInferenceProvider: () => InferenceProvider | null;
158
- export declare const useChatExtensionRegistry: () => ExtensionRegistry | null;
158
+ export declare const useChatUIPluginRegistry: () => UIPluginRegistry | null;
@@ -32,7 +32,7 @@ const initialState = {
32
32
  protocolAdapter: null,
33
33
  toolExecutor: null,
34
34
  middlewarePipeline: null,
35
- extensionRegistry: null,
35
+ uiPluginRegistry: null,
36
36
  messages: [],
37
37
  isLoading: false,
38
38
  isStreaming: false,
@@ -41,7 +41,7 @@ const initialState = {
41
41
  threads: new Map(),
42
42
  tools: new Map(),
43
43
  pendingToolCalls: new Map(),
44
- extensions: new Map(),
44
+ uiPlugins: new Map(),
45
45
  middlewares: [],
46
46
  isOpen: false,
47
47
  error: null,
@@ -77,8 +77,8 @@ export const useChatStore = create()(devtools(subscribeWithSelector(
77
77
  setMiddlewarePipeline: pipeline => {
78
78
  set({ middlewarePipeline: pipeline }, false, 'setMiddlewarePipeline');
79
79
  },
80
- setExtensionRegistry: registry => {
81
- set({ extensionRegistry: registry }, false, 'setExtensionRegistry');
80
+ setUIPluginRegistry: registry => {
81
+ set({ uiPluginRegistry: registry }, false, 'setUIPluginRegistry');
82
82
  },
83
83
  // === Message actions ===
84
84
  addMessage: message => {
@@ -218,53 +218,53 @@ export const useChatStore = create()(devtools(subscribeWithSelector(
218
218
  getPendingToolCalls: () => {
219
219
  return Array.from(get().pendingToolCalls.values()).filter(tc => tc.status === 'pending' || tc.status === 'executing');
220
220
  },
221
- // === Extension registry actions ===
222
- registerExtension: (extension, options) => {
221
+ // === UI plugin registry actions ===
222
+ registerUIPlugin: (plugin, options) => {
223
223
  set(state => {
224
- const newExtensions = new Map(state.extensions);
225
- newExtensions.set(extension.name, {
226
- extension,
224
+ const newUIPlugins = new Map(state.uiPlugins);
225
+ newUIPlugins.set(plugin.name, {
226
+ plugin,
227
227
  enabled: options?.enabled ?? true,
228
228
  registeredAt: new Date(),
229
229
  });
230
- return { extensions: newExtensions };
231
- }, false, 'registerExtension');
230
+ return { uiPlugins: newUIPlugins };
231
+ }, false, 'registerUIPlugin');
232
232
  },
233
- unregisterExtension: name => {
233
+ unregisterUIPlugin: name => {
234
234
  set(state => {
235
- const newExtensions = new Map(state.extensions);
236
- newExtensions.delete(name);
237
- return { extensions: newExtensions };
238
- }, false, 'unregisterExtension');
235
+ const newUIPlugins = new Map(state.uiPlugins);
236
+ newUIPlugins.delete(name);
237
+ return { uiPlugins: newUIPlugins };
238
+ }, false, 'unregisterUIPlugin');
239
239
  },
240
- enableExtension: name => {
240
+ enableUIPlugin: name => {
241
241
  set(state => {
242
- const newExtensions = new Map(state.extensions);
243
- const entry = newExtensions.get(name);
242
+ const newUIPlugins = new Map(state.uiPlugins);
243
+ const entry = newUIPlugins.get(name);
244
244
  if (entry) {
245
- newExtensions.set(name, { ...entry, enabled: true });
245
+ newUIPlugins.set(name, { ...entry, enabled: true });
246
246
  }
247
- return { extensions: newExtensions };
248
- }, false, 'enableExtension');
247
+ return { uiPlugins: newUIPlugins };
248
+ }, false, 'enableUIPlugin');
249
249
  },
250
- disableExtension: name => {
250
+ disableUIPlugin: name => {
251
251
  set(state => {
252
- const newExtensions = new Map(state.extensions);
253
- const entry = newExtensions.get(name);
252
+ const newUIPlugins = new Map(state.uiPlugins);
253
+ const entry = newUIPlugins.get(name);
254
254
  if (entry) {
255
- newExtensions.set(name, { ...entry, enabled: false });
255
+ newUIPlugins.set(name, { ...entry, enabled: false });
256
256
  }
257
- return { extensions: newExtensions };
258
- }, false, 'disableExtension');
257
+ return { uiPlugins: newUIPlugins };
258
+ }, false, 'disableUIPlugin');
259
259
  },
260
- getExtensions: (type) => {
261
- const extensions = Array.from(get().extensions.values())
260
+ getUIPlugins: (type) => {
261
+ const uiPlugins = Array.from(get().uiPlugins.values())
262
262
  .filter(entry => entry.enabled)
263
- .map(entry => entry.extension);
263
+ .map(entry => entry.plugin);
264
264
  if (type) {
265
- return extensions.filter(ext => ext.type === type);
265
+ return uiPlugins.filter(ext => ext.type === type);
266
266
  }
267
- return extensions;
267
+ return uiPlugins;
268
268
  },
269
269
  // === Middleware actions ===
270
270
  addMiddleware: middleware => {
@@ -310,4 +310,4 @@ export const useChatOpen = () => useChatStore(state => state.isOpen);
310
310
  export const useChatConfig = () => useChatStore(state => state.config);
311
311
  export const useChatReady = () => useChatStore(state => state.ready);
312
312
  export const useChatInferenceProvider = () => useChatStore(state => state.inferenceProvider);
313
- export const useChatExtensionRegistry = () => useChatStore(state => state.extensionRegistry);
313
+ export const useChatUIPluginRegistry = () => useChatStore(state => state.uiPluginRegistry);
@@ -4,5 +4,5 @@
4
4
  * @module store
5
5
  */
6
6
  export { agentRuntimeStore, useAgentRuntimeStore, useAgentRuntimeConnection, useAgentRuntimeStatus, useAgentRuntimeError, useAgentRuntimeIsLaunching, useAgentRuntimeApprovals, useAgentRuntimePendingCount, useAgentRuntimeMcpStatus, useAgentRuntimeFullContext, useAgentRuntimeContextSnapshot, useAgentRuntimeCostUsage, useAgentRuntimeCodemodeStatus, useAgentRuntimeWsState, useAgentRuntimeLoadedSkills, useAgentRuntimeActiveSubagentToolCallId, useAgentRuntimeRunningSubagentNames, runningSubagentNames, isSubagentRunOver, useAgentRuntimeSubagentActivity, useAgentRuntimeSubagentActivityByToolCall, useAgentRuntimeCompaction, useAgentRuntimeHistoryVersion, getAgentRuntimeState, subscribeToAgentRuntime, type AgentRegistryEntry, type AgentRuntimeWsState, type AgentRuntimeStoreState, type AgentRuntimeStoreActions, type AgentRuntimeStore, } from './agentRuntimeStore';
7
- export { useChatStore, useChatMessages, useChatLoading, useChatStreaming, useChatError, useChatTools, useChatOpen, useChatConfig, useChatReady, useChatInferenceProvider, useChatExtensionRegistry, defaultChatConfig, type ChatStore, type ChatState, type ChatActions, type ChatConfig, type ToolCallState, } from './chatStore';
7
+ export { useChatStore, useChatMessages, useChatLoading, useChatStreaming, useChatError, useChatTools, useChatOpen, useChatConfig, useChatReady, useChatInferenceProvider, useChatUIPluginRegistry, defaultChatConfig, type ChatStore, type ChatState, type ChatActions, type ChatConfig, type ToolCallState, } from './chatStore';
8
8
  export { useConversationStore, useConversationMessages, useNeedsFetch, useIsFetching, type ConversationStore, type ConversationData, } from './conversationStore';