@adecore/agents-react 0.27.5 → 0.28.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/chat/ui/intelligent-ui/registry.js +2 -1
- package/dist/chat/ui/intelligent-ui/renderers/content.d.ts +1 -0
- package/dist/chat/ui/intelligent-ui/renderers/content.js +27 -1
- package/dist/host.d.ts +10 -0
- package/dist/index.d.ts +1 -1
- package/dist/locales/en/agent-chat.d.ts +5 -0
- package/dist/locales/en/agent-chat.js +5 -0
- package/dist/locales/nl/agent-chat.d.ts +5 -0
- package/dist/locales/nl/agent-chat.js +5 -0
- package/package.json +8 -8
- package/src/chat/ui/intelligent-ui/registry.ts +2 -1
- package/src/chat/ui/intelligent-ui/renderers/content.tsx +51 -1
- package/src/host.ts +19 -0
- package/src/index.ts +1 -0
- package/src/locales/en/agent-chat.ts +5 -0
- package/src/locales/nl/agent-chat.ts +5 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ChartRenderer } from './renderers/chart.js';
|
|
2
2
|
import { ChoiceRenderer, ChoicesRenderer } from './renderers/choices.js';
|
|
3
|
-
import { CodeBlockRenderer, CompareRenderer, GalleryRenderer, ImageRenderer, SourceRenderer, SourcesRenderer } from './renderers/content.js';
|
|
3
|
+
import { CodeBlockRenderer, CompareRenderer, GalleryRenderer, ImageRenderer, ModelRenderer, SourceRenderer, SourcesRenderer } from './renderers/content.js';
|
|
4
4
|
import { EntityListRenderer, EntryRenderer, StatRenderer, StatsRenderer, TableRenderer } from './renderers/data.js';
|
|
5
5
|
import { ButtonRenderer, ChecklistRenderer, ItemRenderer, SegmentedRenderer, SelectRenderer, SliderRenderer, SwitchRenderer, TextFieldRenderer } from './renderers/inputs.js';
|
|
6
6
|
import { CommitRenderer, DiffRenderer, FileRenderer, NodeRenderer } from './renderers/links.js';
|
|
@@ -37,6 +37,7 @@ export const UI_RENDERERS = {
|
|
|
37
37
|
Image: ImageRenderer,
|
|
38
38
|
Gallery: GalleryRenderer,
|
|
39
39
|
Compare: CompareRenderer,
|
|
40
|
+
Model: ModelRenderer,
|
|
40
41
|
Map: MapRenderer,
|
|
41
42
|
Place: null,
|
|
42
43
|
Sources: SourcesRenderer,
|
|
@@ -4,6 +4,7 @@ export declare function CodeBlockRenderer({ node }: UiRendererProps<UiProps<'Cod
|
|
|
4
4
|
export declare function ImageRenderer({ node, children, context }: UiRendererProps<UiProps<'Image'>>): import("react").JSX.Element;
|
|
5
5
|
export declare function GalleryRenderer({ node, children }: UiRendererProps<UiProps<'Gallery'>>): import("react").JSX.Element;
|
|
6
6
|
export declare function CompareRenderer({ node, children, context }: UiRendererProps<UiProps<'Compare'>>): import("react").JSX.Element;
|
|
7
|
+
export declare function ModelRenderer({ node, children, context }: UiRendererProps<UiProps<'Model'>>): import("react").JSX.Element;
|
|
7
8
|
export declare function SourcesRenderer({ node, children }: UiRendererProps<UiProps<'Sources'>>): import("react").JSX.Element;
|
|
8
9
|
export interface UiSourceCitationProps {
|
|
9
10
|
number: number;
|
|
@@ -2,7 +2,8 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import { createContext, useContext, useId, useState } from 'react';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import {
|
|
5
|
+
import { Box } from 'lucide-react';
|
|
6
|
+
import { ErrorBoundary, Icon, Pill, PreviewCard, Tooltip, Wipe } from '@adecore/ui';
|
|
6
7
|
import { formatNumber } from '@adecore/ui/format';
|
|
7
8
|
import { useChatHost } from '../../../../host.js';
|
|
8
9
|
import { CodeBlock } from '../../CodeBlock.js';
|
|
@@ -95,6 +96,31 @@ export function CompareRenderer({ node, children, context }) {
|
|
|
95
96
|
function CompareChip({ side, label }) {
|
|
96
97
|
return (_jsx("span", { className: clsx('pointer-events-none absolute top-2 z-20 max-w-2/5 truncate rounded-md bg-surface-raised', side === 'left' ? 'left-2' : 'right-2'), children: _jsx(Pill, { shape: "tag", size: "sm", tone: "muted", children: label }) }));
|
|
97
98
|
}
|
|
99
|
+
/*
|
|
100
|
+
* The host draws the model, since the chat knows no 3D format. The frame has a fixed height in the reply column,
|
|
101
|
+
* so a view that loads late never moves the thread. Without a view of the host, or without the bytes, the model
|
|
102
|
+
* stays a quiet row that names it.
|
|
103
|
+
*/
|
|
104
|
+
export function ModelRenderer({ node, children, context }) {
|
|
105
|
+
const { t } = useTranslation('agent-chat');
|
|
106
|
+
const host = useChatHost();
|
|
107
|
+
const { attachment, alt } = node.props;
|
|
108
|
+
const source = host.attachments.useUrl(context.scopeId, context.chatId, attachment);
|
|
109
|
+
const caption = uiNodeLabel(node);
|
|
110
|
+
const label = alt ?? (caption === '' ? t('blocks.model.label') : caption);
|
|
111
|
+
const View = host.ModelView;
|
|
112
|
+
let body;
|
|
113
|
+
if (View !== undefined && source.url !== null) {
|
|
114
|
+
body = (_jsx("div", { role: "group", "aria-label": label, className: "relative h-80 w-full overflow-hidden rounded-lg border border-border bg-surface-sunken", children: _jsx(ErrorBoundary, { label: t('blocks.model.crashed'), resetKeys: [attachment, source.url], compact: true, children: _jsx(View, { scopeId: context.scopeId, chatId: context.chatId, attachmentId: attachment, url: source.url, label: label, alt: alt, caption: caption }) }) }));
|
|
115
|
+
}
|
|
116
|
+
else if (View !== undefined && source.failure === null) {
|
|
117
|
+
body = _jsx("div", { "aria-busy": "true", "aria-label": label, className: "h-80 w-full rounded-lg border border-border bg-surface-sunken" });
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
body = (_jsxs("div", { className: "flex w-full min-w-0 items-center gap-2 rounded-lg border border-border px-3 py-2 text-xs", children: [_jsx(Icon, { icon: Box, size: 14, className: "shrink-0 text-text-muted" }), _jsx("span", { className: "min-w-0 truncate text-text", children: alt ?? attachment }), _jsx("span", { className: "ml-auto shrink-0 text-text-faint", children: source.failure === null ? t('blocks.model.label') : t('blocks.model.unavailable') })] }));
|
|
121
|
+
}
|
|
122
|
+
return (_jsxs("figure", { className: "flex flex-col items-start gap-1.5 px-2", children: [body, caption !== '' && _jsx("figcaption", { className: "text-xs text-text-muted", children: children })] }));
|
|
123
|
+
}
|
|
98
124
|
export function SourcesRenderer({ node, children }) {
|
|
99
125
|
const { t } = useTranslation('agent-chat');
|
|
100
126
|
const headingId = useId();
|
package/dist/host.d.ts
CHANGED
|
@@ -162,6 +162,15 @@ export type UiMapSource = {
|
|
|
162
162
|
state: 'off';
|
|
163
163
|
reason: 'disabled' | 'signed-out' | 'unavailable';
|
|
164
164
|
};
|
|
165
|
+
export interface UiModelViewProps {
|
|
166
|
+
scopeId: string;
|
|
167
|
+
chatId: string;
|
|
168
|
+
attachmentId: string;
|
|
169
|
+
url: string;
|
|
170
|
+
label: string;
|
|
171
|
+
alt?: string;
|
|
172
|
+
caption: string;
|
|
173
|
+
}
|
|
165
174
|
export interface ChatHost {
|
|
166
175
|
intelligentUi?: {
|
|
167
176
|
subscribe?(scopeId: string, chatId: string, changed: () => void): () => void;
|
|
@@ -195,6 +204,7 @@ export interface ChatHost {
|
|
|
195
204
|
ReadImage: ComponentType<{
|
|
196
205
|
path: string;
|
|
197
206
|
}> | null;
|
|
207
|
+
ModelView?: ComponentType<UiModelViewProps>;
|
|
198
208
|
MarkdownImage?: ComponentType<{
|
|
199
209
|
path: string;
|
|
200
210
|
alt: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { type ChatActions, type FileRef, type ShellCodeBlockContext, type ChatPlace, type SubagentTask, type TimelineFindOptions, type TimelineFind, type ComposerDictationProps, type ComposerSlotProps, type SubagentSlotProps, type ThreadCard, type VisualHost, type ReplyAuthor, type ChatHost, type UiMapSource, type CommandLook, type CommandLookMatch, type CommandName, ChatHostProvider, useChatHost, type AccentChoice, type ChatToast, type TextareaProps, type ResourceUrl } from './host.js';
|
|
1
|
+
export { type ChatActions, type FileRef, type ShellCodeBlockContext, type ChatPlace, type SubagentTask, type TimelineFindOptions, type TimelineFind, type ComposerDictationProps, type ComposerSlotProps, type SubagentSlotProps, type ThreadCard, type VisualHost, type ReplyAuthor, type ChatHost, type UiMapSource, type UiModelViewProps, type CommandLook, type CommandLookMatch, type CommandName, ChatHostProvider, useChatHost, type AccentChoice, type ChatToast, type TextareaProps, type ResourceUrl } from './host.js';
|
|
2
2
|
export { type ChatScope, ChatScopeContext, useChatScope } from './scope.js';
|
|
3
3
|
export { type ChatRequestMap, type ChatEventMap, type ChatTransportStatus, type ChatTransport, ChatTransportError, errorCode, isConnectionError } from './transport.js';
|
|
4
4
|
export { portTransport, type PortTransport } from './port-transport.js';
|
|
@@ -621,6 +621,11 @@ export default {
|
|
|
621
621
|
label: 'Image',
|
|
622
622
|
unavailable: 'The image is not available'
|
|
623
623
|
},
|
|
624
|
+
model: {
|
|
625
|
+
label: '3D model',
|
|
626
|
+
unavailable: 'The model is not available',
|
|
627
|
+
crashed: 'This model failed to render'
|
|
628
|
+
},
|
|
624
629
|
sources: 'Sources',
|
|
625
630
|
citation: 'Source {{number}}: {{title}}',
|
|
626
631
|
outsideProject: 'Outside the project, shown as text',
|
|
@@ -621,6 +621,11 @@ export default {
|
|
|
621
621
|
label: 'Afbeelding',
|
|
622
622
|
unavailable: 'De afbeelding is niet beschikbaar'
|
|
623
623
|
},
|
|
624
|
+
model: {
|
|
625
|
+
label: '3D-model',
|
|
626
|
+
unavailable: 'Het model is niet beschikbaar',
|
|
627
|
+
crashed: 'Dit model kon niet worden getekend'
|
|
628
|
+
},
|
|
624
629
|
sources: 'Bronnen',
|
|
625
630
|
citation: 'Bron {{number}}: {{title}}',
|
|
626
631
|
outsideProject: 'Buiten het project, als tekst getoond',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adecore/agents-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "React agent chat threads, composers, approvals, provider accounts and usage views.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -67,11 +67,11 @@
|
|
|
67
67
|
"test:visuals": "bun --config=integration.bunfig.toml --conditions=source test ./src/chat/visual-viewport.integration.test.ts"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@adecore/agent-contracts": "0.
|
|
71
|
-
"@adecore/editor": "0.
|
|
72
|
-
"@adecore/editor-react": "0.
|
|
73
|
-
"@adecore/intelligent-ui": "0.
|
|
74
|
-
"@adecore/merge": "0.
|
|
70
|
+
"@adecore/agent-contracts": "0.28.0",
|
|
71
|
+
"@adecore/editor": "0.28.0",
|
|
72
|
+
"@adecore/editor-react": "0.28.0",
|
|
73
|
+
"@adecore/intelligent-ui": "0.28.0",
|
|
74
|
+
"@adecore/merge": "0.28.0",
|
|
75
75
|
"@codemirror/commands": "^6.11.1",
|
|
76
76
|
"@codemirror/language": "^6.12.4",
|
|
77
77
|
"@codemirror/state": "^6.7.6",
|
|
@@ -94,14 +94,14 @@
|
|
|
94
94
|
"zustand": "^5.0.15"
|
|
95
95
|
},
|
|
96
96
|
"peerDependencies": {
|
|
97
|
-
"@adecore/ui": "^0.
|
|
97
|
+
"@adecore/ui": "^0.28.0",
|
|
98
98
|
"i18next": "^26.4.2",
|
|
99
99
|
"react": "^19.3.0",
|
|
100
100
|
"react-dom": "^19.3.0",
|
|
101
101
|
"react-i18next": "^17.0.15"
|
|
102
102
|
},
|
|
103
103
|
"devDependencies": {
|
|
104
|
-
"@adecore/ui": "0.
|
|
104
|
+
"@adecore/ui": "0.28.0",
|
|
105
105
|
"@types/bun": "^1.4.2",
|
|
106
106
|
"@types/react": "^19.3.0",
|
|
107
107
|
"@types/react-dom": "^19.3.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { UiRenderers } from './render-context';
|
|
2
2
|
import { ChartRenderer } from './renderers/chart';
|
|
3
3
|
import { ChoiceRenderer, ChoicesRenderer } from './renderers/choices';
|
|
4
|
-
import { CodeBlockRenderer, CompareRenderer, GalleryRenderer, ImageRenderer, SourceRenderer, SourcesRenderer } from './renderers/content';
|
|
4
|
+
import { CodeBlockRenderer, CompareRenderer, GalleryRenderer, ImageRenderer, ModelRenderer, SourceRenderer, SourcesRenderer } from './renderers/content';
|
|
5
5
|
import { EntityListRenderer, EntryRenderer, StatRenderer, StatsRenderer, TableRenderer } from './renderers/data';
|
|
6
6
|
import {
|
|
7
7
|
ButtonRenderer,
|
|
@@ -57,6 +57,7 @@ export const UI_RENDERERS: UiRenderers = {
|
|
|
57
57
|
Image: ImageRenderer,
|
|
58
58
|
Gallery: GalleryRenderer,
|
|
59
59
|
Compare: CompareRenderer,
|
|
60
|
+
Model: ModelRenderer,
|
|
60
61
|
Map: MapRenderer,
|
|
61
62
|
Place: null,
|
|
62
63
|
Sources: SourcesRenderer,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
2
|
import { createContext, useContext, useId, useState, type ReactNode } from 'react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { Box } from 'lucide-react';
|
|
4
5
|
import type { UiProps } from '@adecore/intelligent-ui';
|
|
5
|
-
import { Pill, PreviewCard, Tooltip, Wipe } from '@adecore/ui';
|
|
6
|
+
import { ErrorBoundary, Icon, Pill, PreviewCard, Tooltip, Wipe } from '@adecore/ui';
|
|
6
7
|
import { formatNumber } from '@adecore/ui/format';
|
|
7
8
|
import { useChatHost } from '../../../../host';
|
|
8
9
|
import { CodeBlock } from '../../CodeBlock';
|
|
@@ -187,6 +188,55 @@ function CompareChip({ side, label }: { side: 'left' | 'right'; label: string })
|
|
|
187
188
|
);
|
|
188
189
|
}
|
|
189
190
|
|
|
191
|
+
/*
|
|
192
|
+
* The host draws the model, since the chat knows no 3D format. The frame has a fixed height in the reply column,
|
|
193
|
+
* so a view that loads late never moves the thread. Without a view of the host, or without the bytes, the model
|
|
194
|
+
* stays a quiet row that names it.
|
|
195
|
+
*/
|
|
196
|
+
export function ModelRenderer({ node, children, context }: UiRendererProps<UiProps<'Model'>>) {
|
|
197
|
+
const { t } = useTranslation('agent-chat');
|
|
198
|
+
const host = useChatHost();
|
|
199
|
+
const { attachment, alt } = node.props;
|
|
200
|
+
const source = host.attachments.useUrl(context.scopeId, context.chatId, attachment);
|
|
201
|
+
const caption = uiNodeLabel(node);
|
|
202
|
+
const label = alt ?? (caption === '' ? t('blocks.model.label') : caption);
|
|
203
|
+
const View = host.ModelView;
|
|
204
|
+
let body: ReactNode;
|
|
205
|
+
if (View !== undefined && source.url !== null) {
|
|
206
|
+
body = (
|
|
207
|
+
<div role="group" aria-label={label} className="relative h-80 w-full overflow-hidden rounded-lg border border-border bg-surface-sunken">
|
|
208
|
+
<ErrorBoundary label={t('blocks.model.crashed')} resetKeys={[attachment, source.url]} compact>
|
|
209
|
+
<View
|
|
210
|
+
scopeId={context.scopeId}
|
|
211
|
+
chatId={context.chatId}
|
|
212
|
+
attachmentId={attachment}
|
|
213
|
+
url={source.url}
|
|
214
|
+
label={label}
|
|
215
|
+
alt={alt}
|
|
216
|
+
caption={caption}
|
|
217
|
+
/>
|
|
218
|
+
</ErrorBoundary>
|
|
219
|
+
</div>
|
|
220
|
+
);
|
|
221
|
+
} else if (View !== undefined && source.failure === null) {
|
|
222
|
+
body = <div aria-busy="true" aria-label={label} className="h-80 w-full rounded-lg border border-border bg-surface-sunken" />;
|
|
223
|
+
} else {
|
|
224
|
+
body = (
|
|
225
|
+
<div className="flex w-full min-w-0 items-center gap-2 rounded-lg border border-border px-3 py-2 text-xs">
|
|
226
|
+
<Icon icon={Box} size={14} className="shrink-0 text-text-muted" />
|
|
227
|
+
<span className="min-w-0 truncate text-text">{alt ?? attachment}</span>
|
|
228
|
+
<span className="ml-auto shrink-0 text-text-faint">{source.failure === null ? t('blocks.model.label') : t('blocks.model.unavailable')}</span>
|
|
229
|
+
</div>
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
return (
|
|
233
|
+
<figure className="flex flex-col items-start gap-1.5 px-2">
|
|
234
|
+
{body}
|
|
235
|
+
{caption !== '' && <figcaption className="text-xs text-text-muted">{children}</figcaption>}
|
|
236
|
+
</figure>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
190
240
|
export function SourcesRenderer({ node, children }: UiRendererProps<UiProps<'Sources'>>) {
|
|
191
241
|
const { t } = useTranslation('agent-chat');
|
|
192
242
|
const headingId = useId();
|
package/src/host.ts
CHANGED
|
@@ -260,6 +260,23 @@ export type UiMapSource =
|
|
|
260
260
|
}
|
|
261
261
|
| { state: 'off'; reason: 'disabled' | 'signed-out' | 'unavailable' };
|
|
262
262
|
|
|
263
|
+
/*
|
|
264
|
+
* What the host's view of a Model block gets. It is drawn only once the attachment has a URL, inside a frame
|
|
265
|
+
* of fixed height that the block sizes and captions itself, so the view fills its parent and draws no caption.
|
|
266
|
+
*/
|
|
267
|
+
export interface UiModelViewProps {
|
|
268
|
+
scopeId: string;
|
|
269
|
+
chatId: string;
|
|
270
|
+
attachmentId: string;
|
|
271
|
+
/* The attachment's bytes, as `attachments.useUrl` resolved them. */
|
|
272
|
+
url: string;
|
|
273
|
+
/* What the model shows, for a screen reader: the block's alt, its caption, or a word for a 3D model. */
|
|
274
|
+
label: string;
|
|
275
|
+
alt?: string;
|
|
276
|
+
/* The caption as plain text, empty without one. */
|
|
277
|
+
caption: string;
|
|
278
|
+
}
|
|
279
|
+
|
|
263
280
|
/*
|
|
264
281
|
* What the app around the chat decides and the chat cannot, handed to the views by a `ChatHostProvider`.
|
|
265
282
|
* Whatever an app leaves out keeps the default here, which is the chat without that part. One host may
|
|
@@ -313,6 +330,8 @@ export interface ChatHost {
|
|
|
313
330
|
};
|
|
314
331
|
/* The image a tool read, drawn under its row; null draws none. */
|
|
315
332
|
ReadImage: ComponentType<{ path: string }> | null;
|
|
333
|
+
/* The 3D view of a Model block; left out, a model shows as a row with its name and caption. */
|
|
334
|
+
ModelView?: ComponentType<UiModelViewProps>;
|
|
316
335
|
/* An image a reply's markdown names by a path on the host's machine, absolute or under the chat's cwd; left out, the `<img>` stays as written. */
|
|
317
336
|
MarkdownImage?: ComponentType<{ path: string; alt: string }>;
|
|
318
337
|
code: {
|
package/src/index.ts
CHANGED
|
@@ -621,6 +621,11 @@ export default {
|
|
|
621
621
|
label: 'Image',
|
|
622
622
|
unavailable: 'The image is not available'
|
|
623
623
|
},
|
|
624
|
+
model: {
|
|
625
|
+
label: '3D model',
|
|
626
|
+
unavailable: 'The model is not available',
|
|
627
|
+
crashed: 'This model failed to render'
|
|
628
|
+
},
|
|
624
629
|
sources: 'Sources',
|
|
625
630
|
citation: 'Source {{number}}: {{title}}',
|
|
626
631
|
outsideProject: 'Outside the project, shown as text',
|
|
@@ -621,6 +621,11 @@ export default {
|
|
|
621
621
|
label: 'Afbeelding',
|
|
622
622
|
unavailable: 'De afbeelding is niet beschikbaar'
|
|
623
623
|
},
|
|
624
|
+
model: {
|
|
625
|
+
label: '3D-model',
|
|
626
|
+
unavailable: 'Het model is niet beschikbaar',
|
|
627
|
+
crashed: 'Dit model kon niet worden getekend'
|
|
628
|
+
},
|
|
624
629
|
sources: 'Bronnen',
|
|
625
630
|
citation: 'Bron {{number}}: {{title}}',
|
|
626
631
|
outsideProject: 'Buiten het project, als tekst getoond',
|