@aws-amplify/ui-react-ai 0.0.0-storage-browser-alpha-5147028-20240909221818 → 0.0.0-storage-browser-alpha-4edafc6-20241001200620
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/esm/components/AIConversation/AIConversation.mjs +3 -1
- package/dist/esm/components/AIConversation/context/AttachmentContext.mjs +8 -0
- package/dist/esm/components/AIConversation/context/DisplayTextContext.mjs +9 -0
- package/dist/esm/components/AIConversation/context/ResponseComponentsContext.mjs +10 -2
- package/dist/esm/components/AIConversation/createAIConversation.mjs +3 -1
- package/dist/esm/components/AIConversation/createProvider.mjs +21 -11
- package/dist/esm/components/AIConversation/displayText.mjs +7 -0
- package/dist/esm/components/AIConversation/views/Controls/ActionsBarControl.mjs +5 -0
- package/dist/esm/components/AIConversation/views/Controls/AttachFileControl.mjs +18 -1
- package/dist/esm/components/AIConversation/views/Controls/AttachmentListControl.mjs +5 -0
- package/dist/esm/components/AIConversation/views/Controls/AvatarControl.mjs +5 -0
- package/dist/esm/components/AIConversation/views/Controls/FieldControl.mjs +10 -7
- package/dist/esm/components/AIConversation/views/Controls/MessagesControl.mjs +15 -6
- package/dist/esm/components/AIConversation/views/Controls/PromptControl.mjs +5 -1
- package/dist/esm/components/AIConversation/views/default/Form.mjs +26 -11
- package/dist/esm/components/AIConversation/views/default/MessageList.mjs +25 -3
- package/dist/index.js +366 -286
- package/dist/types/components/AIConversation/AIConversation.d.ts +5 -4
- package/dist/types/components/AIConversation/context/AttachmentContext.d.ts +6 -0
- package/dist/types/components/AIConversation/context/ControlsContext.d.ts +1 -0
- package/dist/types/components/AIConversation/context/DisplayTextContext.d.ts +5 -0
- package/dist/types/components/AIConversation/context/ResponseComponentsContext.d.ts +1 -0
- package/dist/types/components/AIConversation/context/index.d.ts +11 -7
- package/dist/types/components/AIConversation/createProvider.d.ts +2 -2
- package/dist/types/components/AIConversation/displayText.d.ts +2 -2
- package/dist/types/components/AIConversation/index.d.ts +2 -1
- package/dist/types/components/AIConversation/types.d.ts +1 -0
- package/dist/types/components/AIConversation/views/default/Form.d.ts +1 -1
- package/dist/types/index.d.ts +3 -3
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -4,12 +4,10 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var React = require('react');
|
|
6
6
|
var elements = require('@aws-amplify/ui-react-core/elements');
|
|
7
|
+
var uiReactCore = require('@aws-amplify/ui-react-core');
|
|
7
8
|
var ui = require('@aws-amplify/ui');
|
|
8
9
|
var uiReact = require('@aws-amplify/ui-react');
|
|
9
10
|
var internal = require('@aws-amplify/ui-react/internal');
|
|
10
|
-
var uiReactCore = require('@aws-amplify/ui-react-core');
|
|
11
|
-
|
|
12
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
13
11
|
|
|
14
12
|
function _interopNamespace(e) {
|
|
15
13
|
if (e && e.__esModule) return e;
|
|
@@ -29,7 +27,6 @@ function _interopNamespace(e) {
|
|
|
29
27
|
return Object.freeze(n);
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
33
30
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
34
31
|
|
|
35
32
|
const DEFAULT_ICON_PATHS = {
|
|
@@ -54,7 +51,7 @@ const BaseIconElement = elements.defineBaseElementWithRef({
|
|
|
54
51
|
});
|
|
55
52
|
const getIconProps = ({ variant, ...props }) => {
|
|
56
53
|
const pathData = variant ? DEFAULT_ICON_PATHS[variant] : undefined;
|
|
57
|
-
const children = pathData ? (
|
|
54
|
+
const children = pathData ? (React__namespace["default"].createElement("path", { d: pathData, fill: "currentColor" })) : undefined;
|
|
58
55
|
return {
|
|
59
56
|
...DEFAULT_ICON_ATTRIBUTES,
|
|
60
57
|
...props,
|
|
@@ -120,38 +117,140 @@ const AIConversationElements = {
|
|
|
120
117
|
View: ViewElement,
|
|
121
118
|
};
|
|
122
119
|
|
|
123
|
-
const ActionsContext =
|
|
120
|
+
const ActionsContext = React__namespace["default"].createContext(undefined);
|
|
124
121
|
const ActionsProvider = ({ children, actions, }) => {
|
|
125
|
-
return (
|
|
122
|
+
return (React__namespace["default"].createElement(ActionsContext.Provider, { value: actions }, children));
|
|
126
123
|
};
|
|
127
124
|
|
|
128
|
-
const AvatarsContext =
|
|
125
|
+
const AvatarsContext = React__namespace["default"].createContext(undefined);
|
|
129
126
|
const AvatarsProvider = ({ children, avatars, }) => {
|
|
130
|
-
return (
|
|
127
|
+
return (React__namespace["default"].createElement(AvatarsContext.Provider, { value: avatars }, children));
|
|
131
128
|
};
|
|
132
129
|
|
|
133
|
-
const ConversationInputContext =
|
|
130
|
+
const ConversationInputContext = React__namespace["default"].createContext({});
|
|
134
131
|
const ConversationInputContextProvider = ({ children, }) => {
|
|
135
|
-
const [input, setInput] =
|
|
136
|
-
const providerValue =
|
|
137
|
-
return (
|
|
132
|
+
const [input, setInput] = React__namespace["default"].useState();
|
|
133
|
+
const providerValue = React__namespace["default"].useMemo(() => ({ input, setInput }), [input, setInput]);
|
|
134
|
+
return (React__namespace["default"].createElement(ConversationInputContext.Provider, { value: providerValue }, children));
|
|
138
135
|
};
|
|
139
136
|
|
|
140
|
-
const MessagesContext =
|
|
137
|
+
const MessagesContext = React__namespace["default"].createContext(undefined);
|
|
141
138
|
// role of the user sending the message, assistant or user
|
|
142
|
-
const RoleContext =
|
|
139
|
+
const RoleContext = React__namespace["default"].createContext(undefined);
|
|
143
140
|
const MessagesProvider = ({ children, messages, }) => {
|
|
144
|
-
return (
|
|
141
|
+
return (React__namespace["default"].createElement(MessagesContext.Provider, { value: messages }, children));
|
|
145
142
|
};
|
|
146
143
|
|
|
147
|
-
const SuggestedPromptsContext =
|
|
144
|
+
const SuggestedPromptsContext = React__namespace["default"].createContext(undefined);
|
|
148
145
|
const SuggestedPromptProvider = ({ children, suggestedPrompts, }) => {
|
|
149
|
-
return (
|
|
146
|
+
return (React__namespace["default"].createElement(SuggestedPromptsContext.Provider, { value: suggestedPrompts }, children));
|
|
150
147
|
};
|
|
151
148
|
|
|
152
|
-
const MessageVariantContext =
|
|
149
|
+
const MessageVariantContext = React__namespace["default"].createContext(undefined);
|
|
153
150
|
const MessageVariantProvider = ({ children, variant, }) => {
|
|
154
|
-
return (
|
|
151
|
+
return (React__namespace["default"].createElement(MessageVariantContext.Provider, { value: variant }, children));
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
function formatDate(date) {
|
|
155
|
+
const dateString = date.toLocaleDateString('en-US', {
|
|
156
|
+
weekday: 'short',
|
|
157
|
+
month: 'short',
|
|
158
|
+
day: 'numeric',
|
|
159
|
+
});
|
|
160
|
+
const timeString = date.toLocaleTimeString('en-US', {
|
|
161
|
+
hour: 'numeric',
|
|
162
|
+
minute: 'numeric',
|
|
163
|
+
hour12: true,
|
|
164
|
+
});
|
|
165
|
+
return `${dateString} at ${timeString}`;
|
|
166
|
+
}
|
|
167
|
+
function arrayBufferToBase64(buffer) {
|
|
168
|
+
let binary = '';
|
|
169
|
+
const bytes = new Uint8Array(buffer);
|
|
170
|
+
const len = bytes.byteLength;
|
|
171
|
+
for (let i = 0; i < len; i++) {
|
|
172
|
+
binary += String.fromCharCode(bytes[i]);
|
|
173
|
+
}
|
|
174
|
+
return window.btoa(binary);
|
|
175
|
+
}
|
|
176
|
+
function convertBufferToBase64(buffer, format) {
|
|
177
|
+
let base64string = '';
|
|
178
|
+
// Use node-based buffer if available
|
|
179
|
+
// fall back on browser if not
|
|
180
|
+
if (typeof Buffer !== 'undefined') {
|
|
181
|
+
base64string = Buffer.from(new Uint8Array(buffer)).toString('base64');
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
base64string = arrayBufferToBase64(buffer);
|
|
185
|
+
}
|
|
186
|
+
return `data:image/${format};base64,${base64string}`;
|
|
187
|
+
}
|
|
188
|
+
function getImageTypeFromMimeType(mimeType) {
|
|
189
|
+
return mimeType.split('/')[1];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const defaultAIConversationDisplayTextEn = {
|
|
193
|
+
getMessageTimestampText: (date) => formatDate(date),
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const { ConversationDisplayTextContext, ConversationDisplayTextProvider, useConversationDisplayText, } = uiReactCore.createContextUtilities({
|
|
197
|
+
contextName: 'ConversationDisplayText',
|
|
198
|
+
defaultValue: defaultAIConversationDisplayTextEn,
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
const ControlsContext = React__namespace["default"].createContext(undefined);
|
|
202
|
+
const ControlsProvider = ({ children, controls, }) => {
|
|
203
|
+
return (React__namespace["default"].createElement(ControlsContext.Provider, { value: controls }, children));
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const LoadingContext = React__namespace["default"].createContext(undefined);
|
|
207
|
+
const LoadingContextProvider = ({ children, isLoading, }) => {
|
|
208
|
+
return (React__namespace["default"].createElement(LoadingContext.Provider, { value: isLoading }, children));
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const RESPONSE_COMPONENT_PREFIX = 'AMPLIFY_UI_';
|
|
212
|
+
const ResponseComponentsContext = React__namespace["default"].createContext(undefined);
|
|
213
|
+
const prependResponseComponents = (responseComponents) => {
|
|
214
|
+
if (!responseComponents)
|
|
215
|
+
return responseComponents;
|
|
216
|
+
return Object.keys(responseComponents).reduce((prev, key) => ((prev[`${RESPONSE_COMPONENT_PREFIX}${key}`] = responseComponents[key]),
|
|
217
|
+
prev), {});
|
|
218
|
+
};
|
|
219
|
+
const ResponseComponentsProvider = ({ children, responseComponents, }) => {
|
|
220
|
+
const _responseComponents = React__namespace["default"].useMemo(() => prependResponseComponents(responseComponents), [responseComponents]);
|
|
221
|
+
return (React__namespace["default"].createElement(ResponseComponentsContext.Provider, { value: _responseComponents }, children));
|
|
222
|
+
};
|
|
223
|
+
const convertResponseComponentsToToolConfiguration = (responseComponents) => {
|
|
224
|
+
if (!responseComponents) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const tools = {};
|
|
228
|
+
Object.keys(responseComponents).forEach((toolName) => {
|
|
229
|
+
const { props } = responseComponents[toolName];
|
|
230
|
+
const requiredProps = [];
|
|
231
|
+
Object.keys(props).forEach((propName) => {
|
|
232
|
+
if (props[propName].required)
|
|
233
|
+
requiredProps.push(propName);
|
|
234
|
+
});
|
|
235
|
+
tools[toolName] = {
|
|
236
|
+
description: responseComponents[toolName].description,
|
|
237
|
+
inputSchema: {
|
|
238
|
+
json: {
|
|
239
|
+
type: 'object',
|
|
240
|
+
required: requiredProps,
|
|
241
|
+
properties: {
|
|
242
|
+
...props,
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
});
|
|
248
|
+
return { tools };
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
const SendMessageContext = React__namespace["default"].createContext(undefined);
|
|
252
|
+
const SendMessageContextProvider = ({ children, handleSendMessage, }) => {
|
|
253
|
+
return (React__namespace["default"].createElement(SendMessageContext.Provider, { value: handleSendMessage }, children));
|
|
155
254
|
};
|
|
156
255
|
|
|
157
256
|
const { Button: Button$5, Span: Span$3, View: View$7 } = AIConversationElements;
|
|
@@ -163,16 +262,16 @@ const ActionIcon = elements.withBaseElementProps(Span$3, {
|
|
|
163
262
|
const ActionButtonBase = elements.withBaseElementProps(Button$5, {
|
|
164
263
|
className: `${ACTIONS_BAR_BLOCK}__button`,
|
|
165
264
|
});
|
|
166
|
-
const ActionButton =
|
|
167
|
-
return
|
|
265
|
+
const ActionButton = React__namespace["default"].forwardRef(function ActionButton(props, ref) {
|
|
266
|
+
return React__namespace["default"].createElement(ActionButtonBase, { ...props, ref: ref });
|
|
168
267
|
});
|
|
169
268
|
const Container$4 = elements.withBaseElementProps(View$7, {
|
|
170
269
|
className: `${ACTIONS_BAR_BLOCK}__container`,
|
|
171
270
|
});
|
|
172
271
|
const ActionsBarControl = ({ message, focusable, }) => {
|
|
173
|
-
const actions =
|
|
174
|
-
return (
|
|
175
|
-
|
|
272
|
+
const actions = React__namespace["default"].useContext(ActionsContext);
|
|
273
|
+
return (React__namespace["default"].createElement(Container$4, null, actions?.map((action, index) => (React__namespace["default"].createElement(ActionButton, { "aria-label": action.displayName, key: index, onClick: () => action.handler(message), tabIndex: focusable ? 0 : -1 },
|
|
274
|
+
React__namespace["default"].createElement(ActionIcon, { "data-testid": `action-icon-${action.displayName}` }, action.icon))))));
|
|
176
275
|
};
|
|
177
276
|
ActionsBarControl.Button = ActionButton;
|
|
178
277
|
ActionsBarControl.Container = Container$4;
|
|
@@ -183,9 +282,9 @@ const AVATAR_BLOCK = 'ai-avatar';
|
|
|
183
282
|
const DEFAULT_USER_ICON = elements.withBaseElementProps(Icon$5, {
|
|
184
283
|
variant: 'user-avatar',
|
|
185
284
|
});
|
|
186
|
-
const DEFAULT_AI_ICON = () => (
|
|
187
|
-
|
|
188
|
-
|
|
285
|
+
const DEFAULT_AI_ICON = () => (React__namespace["default"].createElement("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
|
|
286
|
+
React__namespace["default"].createElement("g", { id: "raven-logo" },
|
|
287
|
+
React__namespace["default"].createElement("path", { id: "Subtract", fillRule: "evenodd", clipRule: "evenodd", d: "M16 1.29833C14.7624 0.583803 13.2376 0.583804 12 1.29833L4.00006 5.91711C2.76246 6.63165 2.00006 7.95216 2.00006 9.38122V18.6188C2.00006 20.0478 2.76246 21.3684 4.00006 22.0829L12 26.7017C13.2376 27.4162 14.7624 27.4162 16 26.7017L24 22.0829C25.2376 21.3684 26 20.0478 26 18.6188V9.38122C26 7.95215 25.2376 6.63164 24 5.91711L16 1.29833ZM14.9379 6.37317C14.6157 5.50255 13.3843 5.50255 13.0622 6.37317L11.4151 10.8243C11.3138 11.098 11.098 11.3138 10.8243 11.4151L6.37317 13.0621C5.50256 13.3843 5.50256 14.6157 6.37317 14.9378L10.8243 16.5849C11.098 16.6862 11.3138 16.902 11.4151 17.1757L13.0622 21.6268C13.3843 22.4974 14.6157 22.4974 14.9379 21.6268L16.5849 17.1757C16.6862 16.902 16.902 16.6862 17.1757 16.5849L21.6268 14.9378C22.4974 14.6157 22.4974 13.3843 21.6268 13.0621L17.1757 11.4151C16.902 11.3138 16.6862 11.098 16.5849 10.8243L14.9379 6.37317Z", fill: "#0D1A26" }))));
|
|
189
288
|
const AvatarDisplayName = elements.withBaseElementProps(Text$4, {
|
|
190
289
|
className: `${AVATAR_BLOCK}__display-name`,
|
|
191
290
|
});
|
|
@@ -197,14 +296,14 @@ const Container$3 = elements.withBaseElementProps(View$6, {
|
|
|
197
296
|
className: `${AVATAR_BLOCK}__container`,
|
|
198
297
|
});
|
|
199
298
|
const AvatarControl = () => {
|
|
200
|
-
const avatars =
|
|
201
|
-
const role =
|
|
299
|
+
const avatars = React__namespace["default"].useContext(AvatarsContext);
|
|
300
|
+
const role = React__namespace["default"].useContext(RoleContext);
|
|
202
301
|
const avatar = role === 'assistant' ? avatars?.ai : avatars?.user;
|
|
203
|
-
const defaultIcon = role === 'assistant' ?
|
|
302
|
+
const defaultIcon = role === 'assistant' ? React__namespace["default"].createElement(DEFAULT_AI_ICON, null) : React__namespace["default"].createElement(DEFAULT_USER_ICON, null);
|
|
204
303
|
const defaultDisplayName = role === 'user' ? 'User' : 'Assistant';
|
|
205
|
-
return (
|
|
206
|
-
|
|
207
|
-
|
|
304
|
+
return (React__namespace["default"].createElement(Container$3, { "data-testid": 'avatar' },
|
|
305
|
+
React__namespace["default"].createElement(AvatarIcon, { "data-testid": `avatar-icon-${role}` }, avatar?.avatar ?? defaultIcon),
|
|
306
|
+
React__namespace["default"].createElement(AvatarDisplayName, null, avatar?.username ?? defaultDisplayName)));
|
|
208
307
|
};
|
|
209
308
|
AvatarControl.Container = Container$3;
|
|
210
309
|
AvatarControl.DisplayName = AvatarDisplayName;
|
|
@@ -215,8 +314,8 @@ const HEADER_BLOCK = 'ai-header';
|
|
|
215
314
|
const HeaderTextBase = elements.withBaseElementProps(Text$3, {
|
|
216
315
|
className: `${HEADER_BLOCK}__text`,
|
|
217
316
|
});
|
|
218
|
-
const HeaderText$1 =
|
|
219
|
-
return
|
|
317
|
+
const HeaderText$1 = React__namespace["default"].forwardRef(function HeaderText(props, ref) {
|
|
318
|
+
return React__namespace["default"].createElement(HeaderTextBase, { ...props, ref: ref });
|
|
220
319
|
});
|
|
221
320
|
const CloseIcon = elements.withBaseElementProps(Icon$4, {
|
|
222
321
|
className: `${HEADER_BLOCK}__icon`,
|
|
@@ -225,16 +324,16 @@ const CloseIcon = elements.withBaseElementProps(Icon$4, {
|
|
|
225
324
|
const CloseButtonBase = elements.withBaseElementProps(Button$4, {
|
|
226
325
|
className: `${HEADER_BLOCK}__button`,
|
|
227
326
|
});
|
|
228
|
-
const CloseButton =
|
|
229
|
-
return
|
|
327
|
+
const CloseButton = React__namespace["default"].forwardRef(function CloseButton(props, ref) {
|
|
328
|
+
return React__namespace["default"].createElement(CloseButtonBase, { ...props, ref: ref });
|
|
230
329
|
});
|
|
231
330
|
const Container$2 = elements.withBaseElementProps(View$5, {
|
|
232
331
|
className: `${HEADER_BLOCK}__container`,
|
|
233
332
|
});
|
|
234
|
-
const HeaderControl = () => (
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
333
|
+
const HeaderControl = () => (React__namespace["default"].createElement(Container$2, null,
|
|
334
|
+
React__namespace["default"].createElement(HeaderText$1, null, "Raven Chat"),
|
|
335
|
+
React__namespace["default"].createElement(CloseButton, null,
|
|
336
|
+
React__namespace["default"].createElement(CloseIcon, null))));
|
|
238
337
|
HeaderControl.Container = Container$2;
|
|
239
338
|
HeaderControl.Text = HeaderText$1;
|
|
240
339
|
HeaderControl.Button = CloseButton;
|
|
@@ -259,8 +358,19 @@ const AttachFileButton = elements.withBaseElementProps(Button$3, {
|
|
|
259
358
|
variant: 'attach',
|
|
260
359
|
});
|
|
261
360
|
const AttachFileControl = () => {
|
|
262
|
-
const hiddenInput =
|
|
263
|
-
const { setInput } =
|
|
361
|
+
const hiddenInput = React__namespace["default"].useRef(null);
|
|
362
|
+
const { setInput } = React__namespace["default"].useContext(ConversationInputContext);
|
|
363
|
+
const { dragState, ...dropHandlers } = uiReactCore.useDropZone({
|
|
364
|
+
acceptedFileTypes: ['.jpeg'],
|
|
365
|
+
onDropComplete: ({ acceptedFiles }) => {
|
|
366
|
+
if (acceptedFiles && acceptedFiles?.length > 0 && setInput) {
|
|
367
|
+
setInput((prevInput) => ({
|
|
368
|
+
...prevInput,
|
|
369
|
+
files: [...(prevInput?.files ?? []), ...acceptedFiles],
|
|
370
|
+
}));
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
});
|
|
264
374
|
function handleButtonClick() {
|
|
265
375
|
if (hiddenInput.current) {
|
|
266
376
|
hiddenInput.current.click();
|
|
@@ -278,11 +388,11 @@ const AttachFileControl = () => {
|
|
|
278
388
|
});
|
|
279
389
|
}
|
|
280
390
|
}
|
|
281
|
-
return (
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
391
|
+
return (React__namespace["default"].createElement(AttachFileContainer, { ...dropHandlers },
|
|
392
|
+
React__namespace["default"].createElement(AttachFileButton, { onClick: handleButtonClick },
|
|
393
|
+
React__namespace["default"].createElement(AttachFileIcon, null)),
|
|
394
|
+
React__namespace["default"].createElement(VisuallyHidden$1, null,
|
|
395
|
+
React__namespace["default"].createElement("input", { accept: ".jpeg,.png,.webp,.gif", "data-testid": "hidden-file-input", onChange: handleFileChange, ref: hiddenInput, type: "file", multiple: true }))));
|
|
286
396
|
};
|
|
287
397
|
AttachFileControl.Icon = AttachFileIcon;
|
|
288
398
|
AttachFileControl.Button = AttachFileButton;
|
|
@@ -304,8 +414,8 @@ const RemoveButton = elements.withBaseElementProps(Button$2, {
|
|
|
304
414
|
type: 'button',
|
|
305
415
|
});
|
|
306
416
|
const RemoveButtonControl = ({ onRemove }) => {
|
|
307
|
-
return (
|
|
308
|
-
|
|
417
|
+
return (React__namespace["default"].createElement(RemoveButton, { onClick: onRemove },
|
|
418
|
+
React__namespace["default"].createElement(RemoveIcon, null)));
|
|
309
419
|
};
|
|
310
420
|
RemoveButtonControl.Icon = RemoveIcon;
|
|
311
421
|
RemoveButtonControl.Button = RemoveButton;
|
|
@@ -328,10 +438,10 @@ const TextContainer = elements.withBaseElementProps(View$3, {
|
|
|
328
438
|
className: `${IMAGE_TEXT_BLOCK}__container`,
|
|
329
439
|
});
|
|
330
440
|
const TextControl = ({ fileName, fileSize }) => {
|
|
331
|
-
return (
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
441
|
+
return (React__namespace["default"].createElement(TextContainer, null,
|
|
442
|
+
React__namespace["default"].createElement(FileNameText, null, fileName),
|
|
443
|
+
React__namespace["default"].createElement(Separator$1, null),
|
|
444
|
+
React__namespace["default"].createElement(FileSizeText, null, fileSize)));
|
|
335
445
|
};
|
|
336
446
|
TextControl.Container = TextContainer;
|
|
337
447
|
TextControl.FileName = FileNameText;
|
|
@@ -341,10 +451,10 @@ const Container$1 = elements.withBaseElementProps(ListItem, {
|
|
|
341
451
|
className: `${IMAGE_ITEM_BLOCK}__list-item`,
|
|
342
452
|
});
|
|
343
453
|
const AttachmentControl = ({ image, onRemove }) => {
|
|
344
|
-
return (
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
454
|
+
return (React__namespace["default"].createElement(Container$1, null,
|
|
455
|
+
React__namespace["default"].createElement(ImageIcon, null),
|
|
456
|
+
React__namespace["default"].createElement(TextControl, { fileName: image.name, fileSize: image.size }),
|
|
457
|
+
React__namespace["default"].createElement(RemoveButtonControl, { onRemove: onRemove })));
|
|
348
458
|
};
|
|
349
459
|
AttachmentControl.Container = Container$1;
|
|
350
460
|
AttachmentControl.ImageIcon = ImageIcon;
|
|
@@ -354,8 +464,8 @@ const UnorderedList = elements.withBaseElementProps(ListElement, {
|
|
|
354
464
|
className: `${IMAGE_LIST_BLOCK}__unordered-list`,
|
|
355
465
|
});
|
|
356
466
|
const AttachmentListControl = () => {
|
|
357
|
-
const { input, setInput } =
|
|
358
|
-
return (
|
|
467
|
+
const { input, setInput } = React__namespace["default"].useContext(ConversationInputContext);
|
|
468
|
+
return (React__namespace["default"].createElement(UnorderedList, null, input?.files?.map((file, index) => {
|
|
359
469
|
const onRemove = () => {
|
|
360
470
|
if (setInput) {
|
|
361
471
|
setInput((prevInput) => ({
|
|
@@ -364,95 +474,15 @@ const AttachmentListControl = () => {
|
|
|
364
474
|
}));
|
|
365
475
|
}
|
|
366
476
|
};
|
|
367
|
-
return (
|
|
477
|
+
return (React__namespace["default"].createElement(AttachmentControl, { key: index, image: file, onRemove: onRemove }));
|
|
368
478
|
})));
|
|
369
479
|
};
|
|
370
480
|
AttachmentListControl.List = UnorderedList;
|
|
371
481
|
AttachmentListControl.Item = AttachmentControl;
|
|
372
482
|
|
|
373
|
-
const
|
|
374
|
-
const
|
|
375
|
-
return (
|
|
376
|
-
};
|
|
377
|
-
|
|
378
|
-
const ResponseComponentsContext = React__default["default"].createContext(undefined);
|
|
379
|
-
const ResponseComponentsProvider = ({ children, responseComponents, }) => {
|
|
380
|
-
return (React__default["default"].createElement(ResponseComponentsContext.Provider, { value: responseComponents }, children));
|
|
381
|
-
};
|
|
382
|
-
const convertResponseComponentsToToolConfiguration = (responseComponents) => {
|
|
383
|
-
if (!responseComponents) {
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
|
-
const tools = {};
|
|
387
|
-
Object.keys(responseComponents).forEach((toolName) => {
|
|
388
|
-
const { props } = responseComponents[toolName];
|
|
389
|
-
const requiredProps = [];
|
|
390
|
-
Object.keys(props).forEach((propName) => {
|
|
391
|
-
if (props[propName].required)
|
|
392
|
-
requiredProps.push(propName);
|
|
393
|
-
});
|
|
394
|
-
tools[toolName] = {
|
|
395
|
-
description: responseComponents[toolName].description,
|
|
396
|
-
inputSchema: {
|
|
397
|
-
json: {
|
|
398
|
-
type: 'object',
|
|
399
|
-
required: requiredProps,
|
|
400
|
-
properties: {
|
|
401
|
-
...props,
|
|
402
|
-
},
|
|
403
|
-
},
|
|
404
|
-
},
|
|
405
|
-
};
|
|
406
|
-
});
|
|
407
|
-
return { tools };
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
const ControlsContext = React__default["default"].createContext(undefined);
|
|
411
|
-
const ControlsProvider = ({ children, controls, }) => {
|
|
412
|
-
return (React__default["default"].createElement(ControlsContext.Provider, { value: controls }, children));
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
function formatDate(date) {
|
|
416
|
-
const dateString = date.toLocaleDateString('en-US', {
|
|
417
|
-
weekday: 'short',
|
|
418
|
-
month: 'short',
|
|
419
|
-
day: 'numeric',
|
|
420
|
-
});
|
|
421
|
-
const timeString = date.toLocaleTimeString('en-US', {
|
|
422
|
-
hour: 'numeric',
|
|
423
|
-
minute: 'numeric',
|
|
424
|
-
hour12: true,
|
|
425
|
-
});
|
|
426
|
-
return `${dateString} at ${timeString}`;
|
|
427
|
-
}
|
|
428
|
-
function arrayBufferToBase64(buffer) {
|
|
429
|
-
let binary = '';
|
|
430
|
-
const bytes = new Uint8Array(buffer);
|
|
431
|
-
const len = bytes.byteLength;
|
|
432
|
-
for (let i = 0; i < len; i++) {
|
|
433
|
-
binary += String.fromCharCode(bytes[i]);
|
|
434
|
-
}
|
|
435
|
-
return window.btoa(binary);
|
|
436
|
-
}
|
|
437
|
-
function convertBufferToBase64(buffer, format) {
|
|
438
|
-
let base64string = '';
|
|
439
|
-
// Use node-based buffer if available
|
|
440
|
-
// fall back on browser if not
|
|
441
|
-
if (typeof Buffer !== 'undefined') {
|
|
442
|
-
base64string = Buffer.from(new Uint8Array(buffer)).toString('base64');
|
|
443
|
-
}
|
|
444
|
-
else {
|
|
445
|
-
base64string = arrayBufferToBase64(buffer);
|
|
446
|
-
}
|
|
447
|
-
return `data:image/${format};base64,${base64string}`;
|
|
448
|
-
}
|
|
449
|
-
function getImageTypeFromMimeType(mimeType) {
|
|
450
|
-
return mimeType.split('/')[1];
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
const LoadingContext = React__default["default"].createContext(undefined);
|
|
454
|
-
const LoadingContextProvider = ({ children, isLoading, }) => {
|
|
455
|
-
return (React__default["default"].createElement(LoadingContext.Provider, { value: isLoading }, children));
|
|
483
|
+
const AttachmentContext = React__namespace.createContext(false);
|
|
484
|
+
const AttachmentProvider = ({ children, allowAttachments, }) => {
|
|
485
|
+
return (React__namespace.createElement(AttachmentContext.Provider, { value: allowAttachments ?? false }, children));
|
|
456
486
|
};
|
|
457
487
|
|
|
458
488
|
const { Button: Button$1, Icon: Icon$1, Label: LabelElement, TextArea, View: View$2, } = AIConversationElements;
|
|
@@ -465,11 +495,11 @@ const SendButtonBase = elements.withBaseElementProps(Button$1, {
|
|
|
465
495
|
'aria-label': 'Send message',
|
|
466
496
|
className: `${FIELD_BLOCK}__button ${FIELD_BLOCK}__button--send`,
|
|
467
497
|
});
|
|
468
|
-
const SendButton =
|
|
469
|
-
const { input } =
|
|
470
|
-
const isLoading =
|
|
498
|
+
const SendButton = React__namespace["default"].forwardRef(function SendButton(props, ref) {
|
|
499
|
+
const { input } = React__namespace["default"].useContext(ConversationInputContext);
|
|
500
|
+
const isLoading = React__namespace["default"].useContext(LoadingContext);
|
|
471
501
|
const hasInput = !!input?.text || !!input?.files?.length;
|
|
472
|
-
return (
|
|
502
|
+
return (React__namespace["default"].createElement(SendButtonBase, { ...props,
|
|
473
503
|
// we intentionally || in the case where isLoading is false we should use the value of hasInput
|
|
474
504
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
475
505
|
disabled: isLoading || !hasInput, type: "submit", ref: ref, "data-testid": "send-button" }));
|
|
@@ -488,7 +518,7 @@ const Label = elements.withBaseElementProps(LabelElement, {
|
|
|
488
518
|
htmlFor: 'text-input',
|
|
489
519
|
});
|
|
490
520
|
const useHandleResize = (textAreaRef) => {
|
|
491
|
-
|
|
521
|
+
React__namespace["default"].useEffect(() => {
|
|
492
522
|
const { current } = textAreaRef;
|
|
493
523
|
const handleResize = () => {
|
|
494
524
|
if (current) {
|
|
@@ -507,18 +537,18 @@ const useHandleResize = (textAreaRef) => {
|
|
|
507
537
|
};
|
|
508
538
|
}, [textAreaRef]);
|
|
509
539
|
};
|
|
510
|
-
const TextInput =
|
|
511
|
-
const { setInput } =
|
|
512
|
-
const messages =
|
|
513
|
-
const textAreaRef =
|
|
540
|
+
const TextInput = React__namespace["default"].forwardRef(function TextInput(props, ref) {
|
|
541
|
+
const { setInput } = React__namespace["default"].useContext(ConversationInputContext);
|
|
542
|
+
const messages = React__namespace["default"].useContext(MessagesContext);
|
|
543
|
+
const textAreaRef = React__namespace["default"].useRef(null);
|
|
514
544
|
useHandleResize(textAreaRef);
|
|
515
545
|
const isFirstMessage = !messages || messages.length === 0;
|
|
516
|
-
|
|
546
|
+
React__namespace["default"].useEffect(() => {
|
|
517
547
|
if (textAreaRef && textAreaRef.current) {
|
|
518
548
|
textAreaRef.current.focus();
|
|
519
549
|
}
|
|
520
550
|
}, [textAreaRef]);
|
|
521
|
-
return (
|
|
551
|
+
return (React__namespace["default"].createElement(TextAreaBase, { ...props, "data-testid": "text-input", id: "text-input", onChange: (e) => props.onChange ??
|
|
522
552
|
(setInput &&
|
|
523
553
|
setInput((prevInput) => ({ ...prevInput, text: e.target.value }))), placeholder: props.placeholder ?? isFirstMessage
|
|
524
554
|
? 'Ask anything...'
|
|
@@ -536,11 +566,12 @@ const InputContainer = elements.withBaseElementProps(View$2, {
|
|
|
536
566
|
className: `${FIELD_BLOCK}__input-container`,
|
|
537
567
|
});
|
|
538
568
|
const FieldControl = () => {
|
|
539
|
-
const { input, setInput } =
|
|
540
|
-
const handleSendMessage =
|
|
541
|
-
const
|
|
542
|
-
const
|
|
543
|
-
const
|
|
569
|
+
const { input, setInput } = React__namespace["default"].useContext(ConversationInputContext);
|
|
570
|
+
const handleSendMessage = React__namespace["default"].useContext(SendMessageContext);
|
|
571
|
+
const allowAttachments = React__namespace["default"].useContext(AttachmentContext);
|
|
572
|
+
const ref = React__namespace["default"].useRef(null);
|
|
573
|
+
const responseComponents = React__namespace["default"].useContext(ResponseComponentsContext);
|
|
574
|
+
const controls = React__namespace["default"].useContext(ControlsContext);
|
|
544
575
|
const submitMessage = async () => {
|
|
545
576
|
ref.current?.reset();
|
|
546
577
|
const submittedContent = [];
|
|
@@ -556,7 +587,7 @@ const FieldControl = () => {
|
|
|
556
587
|
const fileContent = {
|
|
557
588
|
image: {
|
|
558
589
|
format: getImageTypeFromMimeType(file.type),
|
|
559
|
-
source: { bytes: Uint8Array
|
|
590
|
+
source: { bytes: new Uint8Array(buffer) },
|
|
560
591
|
},
|
|
561
592
|
};
|
|
562
593
|
submittedContent.push(fileContent);
|
|
@@ -586,17 +617,17 @@ const FieldControl = () => {
|
|
|
586
617
|
}
|
|
587
618
|
};
|
|
588
619
|
if (controls?.Form) {
|
|
589
|
-
return (
|
|
620
|
+
return (React__namespace["default"].createElement(controls.Form, { handleSubmit: handleSubmit, input: input, setInput: setInput, allowAttachments: allowAttachments }));
|
|
590
621
|
}
|
|
591
|
-
return (
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
622
|
+
return (React__namespace["default"].createElement("form", { className: `${FIELD_BLOCK}__form`, onSubmit: handleSubmit, method: "post", ref: ref },
|
|
623
|
+
allowAttachments ? React__namespace["default"].createElement(AttachFileControl, null) : null,
|
|
624
|
+
React__namespace["default"].createElement(InputContainer, null,
|
|
625
|
+
React__namespace["default"].createElement(VisuallyHidden, null,
|
|
626
|
+
React__namespace["default"].createElement(Label, null)),
|
|
627
|
+
React__namespace["default"].createElement(TextInput, { onKeyDown: handleOnKeyDown }),
|
|
628
|
+
React__namespace["default"].createElement(AttachmentListControl, null)),
|
|
629
|
+
React__namespace["default"].createElement(SendButton, null,
|
|
630
|
+
React__namespace["default"].createElement(SendIcon, null))));
|
|
600
631
|
};
|
|
601
632
|
FieldControl.AttachFile = AttachFileControl;
|
|
602
633
|
FieldControl.InputContainer = InputContainer;
|
|
@@ -611,37 +642,39 @@ const MESSAGE_BLOCK = 'ai-message';
|
|
|
611
642
|
const MediaContentBase = elements.withBaseElementProps(Image, {
|
|
612
643
|
alt: 'Image attachment',
|
|
613
644
|
});
|
|
614
|
-
const MediaContent =
|
|
615
|
-
const variant =
|
|
616
|
-
const role =
|
|
617
|
-
return (
|
|
645
|
+
const MediaContent = React__namespace["default"].forwardRef(function MediaContent(props, ref) {
|
|
646
|
+
const variant = React__namespace["default"].useContext(MessageVariantContext);
|
|
647
|
+
const role = React__namespace["default"].useContext(RoleContext);
|
|
648
|
+
return (React__namespace["default"].createElement(MediaContentBase, { ref: ref, className: `${MESSAGE_BLOCK}__image ${MESSAGE_BLOCK}__image--${variant} ${MESSAGE_BLOCK}__image--${role}`, ...props }));
|
|
618
649
|
});
|
|
619
|
-
const TextContent =
|
|
620
|
-
return
|
|
650
|
+
const TextContent = React__namespace["default"].forwardRef(function TextContent(props, ref) {
|
|
651
|
+
return React__namespace["default"].createElement(Text$1, { ref: ref, className: `${MESSAGE_BLOCK}__text`, ...props });
|
|
621
652
|
});
|
|
622
|
-
const ContentContainer =
|
|
623
|
-
const variant =
|
|
624
|
-
return (
|
|
653
|
+
const ContentContainer = React__namespace["default"].forwardRef(function ContentContainer(props, ref) {
|
|
654
|
+
const variant = React__namespace["default"].useContext(MessageVariantContext);
|
|
655
|
+
return (React__namespace["default"].createElement(View$1, { "data-testid": 'content', className: `${MESSAGE_BLOCK}__content ${MESSAGE_BLOCK}__content--${variant}`, ref: ref, ...props }));
|
|
625
656
|
});
|
|
626
657
|
const MessageControl = ({ message }) => {
|
|
627
|
-
const responseComponents =
|
|
628
|
-
return (
|
|
658
|
+
const responseComponents = React__namespace["default"].useContext(ResponseComponentsContext);
|
|
659
|
+
return (React__namespace["default"].createElement(ContentContainer, null, message.content.map((content, index) => {
|
|
629
660
|
if (content.text) {
|
|
630
|
-
return (
|
|
661
|
+
return (React__namespace["default"].createElement(TextContent, { "data-testid": 'text-content', key: index }, content.text));
|
|
631
662
|
}
|
|
632
663
|
else if (content.image) {
|
|
633
|
-
return (
|
|
664
|
+
return (React__namespace["default"].createElement(MediaContent, { "data-testid": 'image-content', key: index, src: convertBufferToBase64(content.image?.source.bytes, content.image?.format) }));
|
|
634
665
|
}
|
|
635
666
|
else if (content.toolUse) {
|
|
636
667
|
// For now tool use is limited to custom response components
|
|
637
668
|
const { name, input } = content.toolUse;
|
|
638
|
-
if (!responseComponents ||
|
|
669
|
+
if (!responseComponents ||
|
|
670
|
+
!name ||
|
|
671
|
+
!name.startsWith(RESPONSE_COMPONENT_PREFIX)) {
|
|
639
672
|
return;
|
|
640
673
|
}
|
|
641
674
|
else {
|
|
642
675
|
const response = responseComponents[name];
|
|
643
676
|
const CustomComponent = response.component;
|
|
644
|
-
return
|
|
677
|
+
return React__namespace["default"].createElement(CustomComponent, { ...input, key: index });
|
|
645
678
|
}
|
|
646
679
|
}
|
|
647
680
|
})));
|
|
@@ -657,26 +690,27 @@ const Separator = elements.withBaseElementProps(Span, {
|
|
|
657
690
|
const Timestamp = elements.withBaseElementProps(Text$1, {
|
|
658
691
|
className: `${MESSAGE_BLOCK}__timestamp`,
|
|
659
692
|
});
|
|
660
|
-
const HeaderContainer =
|
|
661
|
-
const variant =
|
|
662
|
-
return (
|
|
693
|
+
const HeaderContainer = React__namespace["default"].forwardRef(function HeaderContainer(props, ref) {
|
|
694
|
+
const variant = React__namespace["default"].useContext(MessageVariantContext);
|
|
695
|
+
return (React__namespace["default"].createElement(View$1, { ref: ref, className: `${MESSAGE_BLOCK}__header__container ${MESSAGE_BLOCK}__header__container--${variant}`, ...props }));
|
|
663
696
|
});
|
|
664
|
-
const MessageContainer =
|
|
665
|
-
const variant =
|
|
666
|
-
const role =
|
|
667
|
-
return (
|
|
697
|
+
const MessageContainer = React__namespace["default"].forwardRef(function MessageContainer(props, ref) {
|
|
698
|
+
const variant = React__namespace["default"].useContext(MessageVariantContext);
|
|
699
|
+
const role = React__namespace["default"].useContext(RoleContext);
|
|
700
|
+
return (React__namespace["default"].createElement(View$1, { ref: ref, className: `${MESSAGE_BLOCK} ${MESSAGE_BLOCK}--${variant} ${MESSAGE_BLOCK}--${role}`, ...props }));
|
|
668
701
|
});
|
|
669
|
-
const Layout =
|
|
670
|
-
const variant =
|
|
671
|
-
return (
|
|
702
|
+
const Layout = React__namespace["default"].forwardRef(function Layout(props, ref) {
|
|
703
|
+
const variant = React__namespace["default"].useContext(MessageVariantContext);
|
|
704
|
+
return (React__namespace["default"].createElement(View$1, { ref: ref, className: `${MESSAGES_BLOCK}__container ${MESSAGES_BLOCK}__container--${variant}`, "aria-live": 'assertive', ...props }));
|
|
672
705
|
});
|
|
673
706
|
const MessagesControl = ({ renderMessage }) => {
|
|
674
|
-
const messages =
|
|
675
|
-
const controls =
|
|
676
|
-
const
|
|
677
|
-
const
|
|
707
|
+
const messages = React__namespace["default"].useContext(MessagesContext);
|
|
708
|
+
const controls = React__namespace["default"].useContext(ControlsContext);
|
|
709
|
+
const { getMessageTimestampText } = useConversationDisplayText();
|
|
710
|
+
const messagesRef = React__namespace["default"].useRef([]);
|
|
711
|
+
const [focusedItemIndex, setFocusedItemIndex] = React__namespace["default"].useState(messages ? messages.length - 1 : 0);
|
|
678
712
|
const handleFocus = (index) => setFocusedItemIndex(index);
|
|
679
|
-
const onKeyDown =
|
|
713
|
+
const onKeyDown = React__namespace["default"].useCallback((index, { key }) => {
|
|
680
714
|
let newIndex;
|
|
681
715
|
switch (key) {
|
|
682
716
|
case 'ArrowUp':
|
|
@@ -703,17 +737,20 @@ const MessagesControl = ({ renderMessage }) => {
|
|
|
703
737
|
return;
|
|
704
738
|
}, [messages]);
|
|
705
739
|
if (controls?.MessageList) {
|
|
706
|
-
return
|
|
740
|
+
return React__namespace["default"].createElement(controls.MessageList, { messages: messages });
|
|
707
741
|
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
742
|
+
const messagesWithRenderableContent = messages?.filter((message) => message.content.some((content) => content.image ??
|
|
743
|
+
content.text ??
|
|
744
|
+
content.toolUse?.name.startsWith(RESPONSE_COMPONENT_PREFIX))) ?? [];
|
|
745
|
+
return (React__namespace["default"].createElement(Layout, null, messagesWithRenderableContent?.map((message, index) => {
|
|
746
|
+
return renderMessage ? (renderMessage(message)) : (React__namespace["default"].createElement(RoleContext.Provider, { value: message.role, key: `message-${index}` },
|
|
747
|
+
React__namespace["default"].createElement(MessageContainer, { "data-testid": `message`, key: `message-${index}`, tabIndex: focusedItemIndex === index ? 0 : -1, onFocus: () => handleFocus(index), onKeyDown: (event) => onKeyDown(index, event), ref: (el) => (messagesRef.current[index] = el) },
|
|
748
|
+
React__namespace["default"].createElement(HeaderContainer, null,
|
|
749
|
+
React__namespace["default"].createElement(AvatarControl, null),
|
|
750
|
+
React__namespace["default"].createElement(Separator, null),
|
|
751
|
+
React__namespace["default"].createElement(Timestamp, null, getMessageTimestampText(new Date(message.createdAt)))),
|
|
752
|
+
React__namespace["default"].createElement(MessageControl, { message: message }),
|
|
753
|
+
message.role === 'assistant' ? (React__namespace["default"].createElement(ActionsBarControl, { message: message, focusable: focusedItemIndex === index })) : null)));
|
|
717
754
|
})));
|
|
718
755
|
};
|
|
719
756
|
MessagesControl.ActionsBar = ActionsBarControl;
|
|
@@ -733,13 +770,13 @@ const PromptCard = elements.withBaseElementProps(Button, {
|
|
|
733
770
|
type: 'button',
|
|
734
771
|
});
|
|
735
772
|
const AIIconProps = () => ({
|
|
736
|
-
children: (
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
773
|
+
children: (React__namespace["default"].createElement(React__namespace["default"].Fragment, null,
|
|
774
|
+
React__namespace["default"].createElement("path", { d: "M17.5 1.64858C19.047 0.755412 20.953 0.755412 22.5 1.64858L34.6428 8.65923C36.1898 9.55239 37.1428 11.203 37.1428 12.9894V27.0107C37.1428 28.797 36.1898 30.4476 34.6428 31.3408L22.5 38.3514C20.953 39.2446 19.047 39.2446 17.5 38.3514L5.35718 31.3408C3.81017 30.4476 2.85718 28.797 2.85718 27.0107V12.9894C2.85718 11.203 3.81017 9.55239 5.35718 8.65923L17.5 1.64858Z", fill: "white" }),
|
|
775
|
+
React__namespace["default"].createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M22.5 1.64851C20.953 0.755347 19.047 0.755347 17.5 1.64851L5.35718 8.65916C3.81017 9.55233 2.85718 11.203 2.85718 12.9893V27.0106C2.85718 28.7969 3.81017 30.4476 5.35718 31.3407L17.5 38.3514C19.047 39.2445 20.953 39.2445 22.5 38.3514L34.6428 31.3407C36.1898 30.4476 37.1428 28.7969 37.1428 27.0106V12.9893C37.1428 11.203 36.1898 9.55233 34.6428 8.65916L22.5 1.64851ZM20.9378 8.01826C20.6156 7.14764 19.3843 7.14764 19.0621 8.01825L16.2388 15.648C16.1375 15.9217 15.9217 16.1375 15.648 16.2388L8.01826 19.0621C7.14765 19.3842 7.14765 20.6156 8.01826 20.9378L15.648 23.7611C15.9217 23.8623 16.1375 24.0782 16.2388 24.3519L19.0621 31.9816C19.3843 32.8522 20.6156 32.8522 20.9378 31.9816L23.7611 24.3519C23.8624 24.0782 24.0782 23.8623 24.3519 23.7611L31.9816 20.9378C32.8523 20.6156 32.8523 19.3842 31.9816 19.0621L24.3519 16.2388C24.0782 16.1375 23.8624 15.9217 23.7611 15.648L20.9378 8.01826Z", fill: "url(#paint0_linear_395_1815)" }),
|
|
776
|
+
React__namespace["default"].createElement("defs", null,
|
|
777
|
+
React__namespace["default"].createElement("linearGradient", { id: "paint0_linear_395_1815", x1: "20", y1: "0.978638", x2: "20", y2: "39.0213", gradientUnits: "userSpaceOnUse" },
|
|
778
|
+
React__namespace["default"].createElement("stop", { stopColor: "#7DD6E8" }),
|
|
779
|
+
React__namespace["default"].createElement("stop", { offset: "1", stopColor: "#BF40BF" }))))),
|
|
743
780
|
className: `${PROMPT_CONTROL}__icon`,
|
|
744
781
|
width: '40',
|
|
745
782
|
height: '40',
|
|
@@ -754,41 +791,41 @@ const HeaderText = elements.withBaseElementProps(Heading, {
|
|
|
754
791
|
const PromptGroupBase = elements.withBaseElementProps(View, {
|
|
755
792
|
className: `${PROMPT_CONTROL}__buttongroup`,
|
|
756
793
|
});
|
|
757
|
-
const PromptGroup =
|
|
758
|
-
const suggestedPromptsArray =
|
|
759
|
-
const { setInput } =
|
|
794
|
+
const PromptGroup = React__namespace["default"].forwardRef(function ButtonGroup(props, ref) {
|
|
795
|
+
const suggestedPromptsArray = React__namespace["default"].useContext(SuggestedPromptsContext);
|
|
796
|
+
const { setInput } = React__namespace["default"].useContext(ConversationInputContext);
|
|
760
797
|
if (!suggestedPromptsArray) {
|
|
761
798
|
return;
|
|
762
799
|
}
|
|
763
|
-
return (
|
|
764
|
-
return (
|
|
800
|
+
return (React__namespace["default"].createElement(PromptGroupBase, { ...props, ref: ref }, suggestedPromptsArray.map((prompt, index) => {
|
|
801
|
+
return (React__namespace["default"].createElement(PromptCard, { key: index, "aria-label": prompt.inputText, onClick: () => setInput &&
|
|
765
802
|
setInput((prevInput) => ({
|
|
766
803
|
...prevInput,
|
|
767
804
|
text: prompt.inputText,
|
|
768
805
|
})) },
|
|
769
|
-
|
|
770
|
-
|
|
806
|
+
React__namespace["default"].createElement(Text, { className: ui.classNames(`${PROMPT_CARD}__header`, `${PROMPT_CARD}__text`) }, prompt.header),
|
|
807
|
+
React__namespace["default"].createElement(Text, { className: `${PROMPT_CARD}__text` }, prompt.inputText)));
|
|
771
808
|
})));
|
|
772
809
|
});
|
|
773
810
|
const Container = elements.withBaseElementProps(View, {
|
|
774
811
|
className: `${PROMPT_BLOCK}__container`,
|
|
775
812
|
});
|
|
776
813
|
const PromptControl = () => {
|
|
777
|
-
const suggestedPromptsArray =
|
|
778
|
-
const controls =
|
|
779
|
-
const { setInput } =
|
|
814
|
+
const suggestedPromptsArray = React__namespace["default"].useContext(SuggestedPromptsContext);
|
|
815
|
+
const controls = React__namespace["default"].useContext(ControlsContext);
|
|
816
|
+
const { setInput } = React__namespace["default"].useContext(ConversationInputContext);
|
|
780
817
|
if (controls?.PromptList) {
|
|
781
|
-
return (
|
|
818
|
+
return (React__namespace["default"].createElement(controls.PromptList, { setInput: setInput, suggestedPrompts: suggestedPromptsArray }));
|
|
782
819
|
}
|
|
783
|
-
return (
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
820
|
+
return (React__namespace["default"].createElement(Container, null,
|
|
821
|
+
React__namespace["default"].createElement(AIIcon, null),
|
|
822
|
+
React__namespace["default"].createElement(HeaderText, null, "How can I help you today?"),
|
|
823
|
+
React__namespace["default"].createElement(PromptGroup, null)));
|
|
787
824
|
};
|
|
788
825
|
const AutoHidablePromptControl = () => {
|
|
789
|
-
const messages =
|
|
826
|
+
const messages = React__namespace["default"].useContext(MessagesContext);
|
|
790
827
|
if (!messages || messages.length === 0) {
|
|
791
|
-
return
|
|
828
|
+
return React__namespace["default"].createElement(PromptControl, null);
|
|
792
829
|
}
|
|
793
830
|
};
|
|
794
831
|
PromptControl.Container = Container;
|
|
@@ -798,28 +835,34 @@ PromptControl.PromptGroup = PromptGroup;
|
|
|
798
835
|
PromptControl.PromptCard = PromptCard;
|
|
799
836
|
|
|
800
837
|
function Conversation() {
|
|
801
|
-
return (
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
838
|
+
return (React__namespace["default"].createElement(ViewElement, null,
|
|
839
|
+
React__namespace["default"].createElement(HeaderControl, null),
|
|
840
|
+
React__namespace["default"].createElement(ViewElement, null,
|
|
841
|
+
React__namespace["default"].createElement(AutoHidablePromptControl, null),
|
|
842
|
+
React__namespace["default"].createElement(MessagesControl, null)),
|
|
843
|
+
React__namespace["default"].createElement(ViewElement, null,
|
|
844
|
+
React__namespace["default"].createElement(FieldControl, null))));
|
|
808
845
|
}
|
|
809
846
|
|
|
810
|
-
function createProvider({ elements: elements$1, actions, suggestedPrompts, responseComponents, variant, controls, }) {
|
|
847
|
+
function createProvider({ elements: elements$1, actions, suggestedPrompts, responseComponents, variant, controls, displayText, allowAttachments, }) {
|
|
811
848
|
return function Provider({ children, messages, avatars, handleSendMessage, isLoading, }) {
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
849
|
+
const _displayText = {
|
|
850
|
+
...defaultAIConversationDisplayTextEn,
|
|
851
|
+
...displayText,
|
|
852
|
+
};
|
|
853
|
+
return (React__namespace["default"].createElement(elements.ElementsProvider, { elements: elements$1 },
|
|
854
|
+
React__namespace["default"].createElement(ControlsProvider, { controls: controls },
|
|
855
|
+
React__namespace["default"].createElement(SuggestedPromptProvider, { suggestedPrompts: suggestedPrompts },
|
|
856
|
+
React__namespace["default"].createElement(ResponseComponentsProvider, { responseComponents: responseComponents },
|
|
857
|
+
React__namespace["default"].createElement(AttachmentProvider, { allowAttachments: allowAttachments },
|
|
858
|
+
React__namespace["default"].createElement(ConversationDisplayTextProvider, { ..._displayText },
|
|
859
|
+
React__namespace["default"].createElement(ConversationInputContextProvider, null,
|
|
860
|
+
React__namespace["default"].createElement(SendMessageContextProvider, { handleSendMessage: handleSendMessage },
|
|
861
|
+
React__namespace["default"].createElement(AvatarsProvider, { avatars: avatars },
|
|
862
|
+
React__namespace["default"].createElement(ActionsProvider, { actions: actions },
|
|
863
|
+
React__namespace["default"].createElement(MessageVariantProvider, { variant: variant },
|
|
864
|
+
React__namespace["default"].createElement(MessagesProvider, { messages: messages },
|
|
865
|
+
React__namespace["default"].createElement(LoadingContextProvider, { isLoading: isLoading }, children))))))))))))));
|
|
823
866
|
};
|
|
824
867
|
}
|
|
825
868
|
|
|
@@ -827,7 +870,7 @@ function createProvider({ elements: elements$1, actions, suggestedPrompts, respo
|
|
|
827
870
|
* @experimental
|
|
828
871
|
*/
|
|
829
872
|
function createAIConversation(input = {}) {
|
|
830
|
-
const { elements, suggestedPrompts, actions, responseComponents, variant, controls, } = input;
|
|
873
|
+
const { elements, suggestedPrompts, actions, responseComponents, variant, controls, displayText, allowAttachments, } = input;
|
|
831
874
|
const Provider = createProvider({
|
|
832
875
|
elements,
|
|
833
876
|
actions,
|
|
@@ -835,11 +878,13 @@ function createAIConversation(input = {}) {
|
|
|
835
878
|
responseComponents,
|
|
836
879
|
variant,
|
|
837
880
|
controls,
|
|
881
|
+
displayText,
|
|
882
|
+
allowAttachments,
|
|
838
883
|
});
|
|
839
884
|
function AIConversation(props) {
|
|
840
885
|
const { messages, avatars, handleSendMessage, isLoading } = props;
|
|
841
|
-
return (
|
|
842
|
-
|
|
886
|
+
return (React__namespace["default"].createElement(Provider, { messages: messages, avatars: avatars, handleSendMessage: handleSendMessage, isLoading: isLoading },
|
|
887
|
+
React__namespace["default"].createElement(Conversation, null)));
|
|
843
888
|
}
|
|
844
889
|
const Controls = {
|
|
845
890
|
ActionsBar: ActionsBarControl,
|
|
@@ -859,11 +904,23 @@ const MessageMeta = ({ message }) => {
|
|
|
859
904
|
// need to pass this in as props in order for it to be overridable
|
|
860
905
|
const avatars = React__namespace.useContext(AvatarsContext);
|
|
861
906
|
const role = React__namespace.useContext(RoleContext);
|
|
907
|
+
const { getMessageTimestampText } = useConversationDisplayText();
|
|
862
908
|
// maybe rename 'avatar' to something else
|
|
863
909
|
const avatar = role === 'assistant' ? avatars?.ai : avatars?.user;
|
|
864
910
|
return (React__namespace.createElement(uiReact.View, { className: ui.ComponentClassName.AIConversationMessageSender },
|
|
865
911
|
React__namespace.createElement(uiReact.Text, { className: ui.ComponentClassName.AIConversationMessageSenderUsername }, avatar?.username),
|
|
866
|
-
React__namespace.createElement(uiReact.Text, { className: ui.ComponentClassName.AIConversationMessageSenderTimestamp },
|
|
912
|
+
React__namespace.createElement(uiReact.Text, { className: ui.ComponentClassName.AIConversationMessageSenderTimestamp }, getMessageTimestampText(new Date(message.createdAt)))));
|
|
913
|
+
};
|
|
914
|
+
const LoadingMessage = () => {
|
|
915
|
+
const avatars = React__namespace.useContext(AvatarsContext);
|
|
916
|
+
const variant = React__namespace.useContext(MessageVariantContext);
|
|
917
|
+
const avatar = avatars?.ai;
|
|
918
|
+
return (React__namespace.createElement(uiReact.View, { className: ui.classNames(ui.ComponentClassName.AIConversationMessage, ui.classNameModifier(ui.ComponentClassName.AIConversationMessage, variant), ui.classNameModifier(ui.ComponentClassName.AIConversationMessage, 'assistant')) },
|
|
919
|
+
React__namespace.createElement(uiReact.View, { className: ui.ComponentClassName.AIConversationMessageAvatar },
|
|
920
|
+
React__namespace.createElement(uiReact.Avatar, { isLoading: true }, avatar?.avatar)),
|
|
921
|
+
React__namespace.createElement(uiReact.View, { className: ui.ComponentClassName.AIConversationMessageBody },
|
|
922
|
+
React__namespace.createElement(uiReact.View, { className: ui.ComponentClassName.AIConversationMessageSender },
|
|
923
|
+
React__namespace.createElement(uiReact.Text, { className: ui.ComponentClassName.AIConversationMessageSenderUsername }, avatar?.username)))));
|
|
867
924
|
};
|
|
868
925
|
const Message = ({ message }) => {
|
|
869
926
|
const avatars = React__namespace.useContext(AvatarsContext);
|
|
@@ -879,7 +936,13 @@ const Message = ({ message }) => {
|
|
|
879
936
|
React__namespace.createElement(MessageControl, { message: message }))))));
|
|
880
937
|
};
|
|
881
938
|
const MessageList = ({ messages, }) => {
|
|
882
|
-
|
|
939
|
+
const isLoading = React__namespace.useContext(LoadingContext);
|
|
940
|
+
const messagesWithRenderableContent = messages?.filter((message) => message.content.some((content) => content.image ??
|
|
941
|
+
content.text ??
|
|
942
|
+
content.toolUse?.name.startsWith(RESPONSE_COMPONENT_PREFIX))) ?? [];
|
|
943
|
+
return (React__namespace.createElement(uiReact.View, { className: ui.ComponentClassName.AIConversationMessageList },
|
|
944
|
+
messagesWithRenderableContent.map((message, i) => (React__namespace.createElement(Message, { key: `message-${i}`, message: message }))),
|
|
945
|
+
isLoading ? React__namespace.createElement(LoadingMessage, null) : null));
|
|
883
946
|
};
|
|
884
947
|
|
|
885
948
|
const Attachment = ({ file, handleRemove, }) => {
|
|
@@ -908,22 +971,37 @@ const Attachments = ({ files, setInput, }) => {
|
|
|
908
971
|
function isHTMLFormElement(target) {
|
|
909
972
|
return 'form' in target;
|
|
910
973
|
}
|
|
911
|
-
|
|
974
|
+
/**
|
|
975
|
+
* Will conditionally render the DropZone if allowAttachments
|
|
976
|
+
* is true
|
|
977
|
+
*/
|
|
978
|
+
const FormWrapper = ({ children, allowAttachments, setInput, }) => {
|
|
979
|
+
if (allowAttachments) {
|
|
980
|
+
return (React__namespace.createElement(uiReact.DropZone, { className: ui.ComponentClassName.AIConversationFormDropzone, onDropComplete: ({ acceptedFiles }) => {
|
|
981
|
+
setInput?.((prevInput) => ({
|
|
982
|
+
...prevInput,
|
|
983
|
+
files: [...(prevInput?.files ?? []), ...acceptedFiles],
|
|
984
|
+
}));
|
|
985
|
+
} }, children));
|
|
986
|
+
}
|
|
987
|
+
else {
|
|
988
|
+
return children;
|
|
989
|
+
}
|
|
990
|
+
};
|
|
991
|
+
const Form = ({ setInput, input, handleSubmit, allowAttachments, }) => {
|
|
912
992
|
const icons = internal.useIcons('aiConversation');
|
|
913
993
|
const sendIcon = icons?.send ?? React__namespace.createElement(internal.IconSend, null);
|
|
914
994
|
const attachIcon = icons?.attach ?? React__namespace.createElement(internal.IconAttach, null);
|
|
915
995
|
const hiddenInput = React__namespace.useRef(null);
|
|
916
996
|
const isLoading = React__namespace.useContext(LoadingContext);
|
|
917
997
|
const isInputEmpty = !input?.text?.length && !input?.files?.length;
|
|
918
|
-
return (React__namespace.createElement(
|
|
919
|
-
setInput((prevInput) => ({
|
|
920
|
-
...prevInput,
|
|
921
|
-
files: [...(prevInput?.files ?? []), ...acceptedFiles],
|
|
922
|
-
}));
|
|
923
|
-
} },
|
|
998
|
+
return (React__namespace.createElement(FormWrapper, { allowAttachments: allowAttachments, setInput: setInput },
|
|
924
999
|
React__namespace.createElement(uiReact.View, { as: "form", className: ui.ComponentClassName.AIConversationForm, onSubmit: handleSubmit },
|
|
925
|
-
React__namespace.createElement(uiReact.Button, { className: ui.ComponentClassName.AIConversationFormAttach, onClick: () => {
|
|
1000
|
+
allowAttachments ? (React__namespace.createElement(uiReact.Button, { className: ui.ComponentClassName.AIConversationFormAttach, onClick: () => {
|
|
926
1001
|
hiddenInput?.current?.click();
|
|
1002
|
+
if (hiddenInput?.current) {
|
|
1003
|
+
hiddenInput.current.value = '';
|
|
1004
|
+
}
|
|
927
1005
|
} },
|
|
928
1006
|
React__namespace.createElement("span", null, attachIcon),
|
|
929
1007
|
React__namespace.createElement(uiReact.VisuallyHidden, null,
|
|
@@ -936,8 +1014,8 @@ const Form = ({ setInput, input, handleSubmit, }) => {
|
|
|
936
1014
|
...prevValue,
|
|
937
1015
|
files: [...(prevValue?.files ?? []), ...Array.from(files)],
|
|
938
1016
|
}));
|
|
939
|
-
}, multiple: true, accept: "*" }))),
|
|
940
|
-
React__namespace.createElement(uiReact.TextAreaField, { className: ui.ComponentClassName.AIConversationFormField, label: "input", labelHidden: true, autoResize: true, flex: "1", rows: 1, value: input?.text ?? '', onKeyDown: (e) => {
|
|
1017
|
+
}, multiple: true, accept: "*", "data-testid": "hidden-file-input" })))) : null,
|
|
1018
|
+
React__namespace.createElement(uiReact.TextAreaField, { className: ui.ComponentClassName.AIConversationFormField, label: "input", labelHidden: true, autoResize: true, flex: "1", rows: 1, value: input?.text ?? '', testId: "text-input", onKeyDown: (e) => {
|
|
941
1019
|
// Submit on enter key if shift is not pressed also
|
|
942
1020
|
const shouldSubmit = !e.shiftKey && e.key === 'Enter';
|
|
943
1021
|
if (shouldSubmit && isHTMLFormElement(e.target)) {
|
|
@@ -969,7 +1047,7 @@ const PromptList = ({ setInput, suggestedPrompts = [], }) => {
|
|
|
969
1047
|
})));
|
|
970
1048
|
};
|
|
971
1049
|
|
|
972
|
-
function AIConversationBase({ actions, avatars, controls, handleSendMessage, messages, responseComponents, suggestedPrompts, variant, isLoading, }) {
|
|
1050
|
+
function AIConversationBase({ actions, avatars, controls, handleSendMessage, messages, responseComponents, suggestedPrompts, variant, isLoading, displayText, allowAttachments, }) {
|
|
973
1051
|
const icons = internal.useIcons('aiConversation');
|
|
974
1052
|
const defaultAvatars = {
|
|
975
1053
|
ai: {
|
|
@@ -997,6 +1075,7 @@ function AIConversationBase({ actions, avatars, controls, handleSendMessage, mes
|
|
|
997
1075
|
Form,
|
|
998
1076
|
...controls,
|
|
999
1077
|
},
|
|
1078
|
+
displayText,
|
|
1000
1079
|
});
|
|
1001
1080
|
const providerProps = {
|
|
1002
1081
|
messages,
|
|
@@ -1006,6 +1085,7 @@ function AIConversationBase({ actions, avatars, controls, handleSendMessage, mes
|
|
|
1006
1085
|
...avatars,
|
|
1007
1086
|
},
|
|
1008
1087
|
isLoading,
|
|
1088
|
+
allowAttachments,
|
|
1009
1089
|
};
|
|
1010
1090
|
return (React__namespace.createElement(Provider, { ...providerProps },
|
|
1011
1091
|
React__namespace.createElement(uiReact.Flex, { className: ui.ComponentClassName.AIConversation },
|
|
@@ -1023,10 +1103,10 @@ const AIConversation = Object.assign(AIConversationBase, {
|
|
|
1023
1103
|
Form,
|
|
1024
1104
|
});
|
|
1025
1105
|
|
|
1026
|
-
const AIContext =
|
|
1106
|
+
const AIContext = React__namespace["default"].createContext(undefined);
|
|
1027
1107
|
const useAIContext = () => {
|
|
1028
|
-
const context =
|
|
1029
|
-
const [routeToConversationsMap, setRouteToConversationsMap] =
|
|
1108
|
+
const context = React__namespace["default"].useContext(AIContext);
|
|
1109
|
+
const [routeToConversationsMap, setRouteToConversationsMap] = React__namespace["default"].useState({});
|
|
1030
1110
|
if (context) {
|
|
1031
1111
|
return context;
|
|
1032
1112
|
}
|
|
@@ -1037,7 +1117,7 @@ const useAIContext = () => {
|
|
|
1037
1117
|
*/
|
|
1038
1118
|
const AIContextProvider = ({ children, }) => {
|
|
1039
1119
|
const context = useAIContext();
|
|
1040
|
-
return
|
|
1120
|
+
return React__namespace["default"].createElement(AIContext.Provider, { value: context }, children);
|
|
1041
1121
|
};
|
|
1042
1122
|
|
|
1043
1123
|
function createUseAIGeneration(client) {
|
|
@@ -1076,13 +1156,13 @@ function createUseAIConversation(client) {
|
|
|
1076
1156
|
const messagesFromAIContext = input.id
|
|
1077
1157
|
? routeToConversationsMap[routeName]?.[input.id]
|
|
1078
1158
|
: undefined;
|
|
1079
|
-
const [localMessages, setLocalMessages] =
|
|
1080
|
-
const [conversation, setConversation] =
|
|
1081
|
-
const [waitingForAIResponse, setWaitingForAIResponse] =
|
|
1082
|
-
const [errorMessage, setErrorMessage] =
|
|
1083
|
-
const [hasError, setHasError] =
|
|
1159
|
+
const [localMessages, setLocalMessages] = React__namespace["default"].useState(messagesFromAIContext ?? []);
|
|
1160
|
+
const [conversation, setConversation] = React__namespace["default"].useState(undefined);
|
|
1161
|
+
const [waitingForAIResponse, setWaitingForAIResponse] = React__namespace["default"].useState(false);
|
|
1162
|
+
const [errorMessage, setErrorMessage] = React__namespace["default"].useState();
|
|
1163
|
+
const [hasError, setHasError] = React__namespace["default"].useState(false);
|
|
1084
1164
|
// On hook initialization get conversation and load all messages
|
|
1085
|
-
|
|
1165
|
+
React__namespace["default"].useEffect(() => {
|
|
1086
1166
|
async function initialize() {
|
|
1087
1167
|
const { data: conversation } = input.id
|
|
1088
1168
|
? await clientRoute.get({ id: input.id })
|
|
@@ -1108,11 +1188,11 @@ function createUseAIConversation(client) {
|
|
|
1108
1188
|
initialize();
|
|
1109
1189
|
}, [clientRoute, input.id, routeName, setRouteToConversationsMap]);
|
|
1110
1190
|
// Update messages to match what is in AIContext if they aren't equal
|
|
1111
|
-
|
|
1191
|
+
React__namespace["default"].useEffect(() => {
|
|
1112
1192
|
if (!!messagesFromAIContext && messagesFromAIContext !== localMessages)
|
|
1113
1193
|
setLocalMessages(messagesFromAIContext);
|
|
1114
1194
|
}, [messagesFromAIContext, localMessages]);
|
|
1115
|
-
const sendMessage =
|
|
1195
|
+
const sendMessage = React__namespace["default"].useCallback((input) => {
|
|
1116
1196
|
const { content, aiContext, toolConfiguration } = input;
|
|
1117
1197
|
conversation
|
|
1118
1198
|
?.sendMessage({ content, aiContext, toolConfiguration })
|
|
@@ -1142,7 +1222,7 @@ function createUseAIConversation(client) {
|
|
|
1142
1222
|
setErrorMessage(`error sending message ${reason}`);
|
|
1143
1223
|
});
|
|
1144
1224
|
}, [conversation, routeName, setRouteToConversationsMap]);
|
|
1145
|
-
const subscribe =
|
|
1225
|
+
const subscribe = React__namespace["default"].useCallback((handleStoreChange) => {
|
|
1146
1226
|
const subscription = conversation &&
|
|
1147
1227
|
conversation.onMessage((message) => {
|
|
1148
1228
|
if (input.onResponse)
|
|
@@ -1169,10 +1249,10 @@ function createUseAIConversation(client) {
|
|
|
1169
1249
|
subscription?.unsubscribe();
|
|
1170
1250
|
};
|
|
1171
1251
|
}, [conversation, routeName, setRouteToConversationsMap, input]);
|
|
1172
|
-
const getSnapshot =
|
|
1252
|
+
const getSnapshot = React__namespace["default"].useCallback(() => localMessages, [localMessages]);
|
|
1173
1253
|
// Using useSyncExternalStore to subscribe to external data updates
|
|
1174
1254
|
// Have to provide third optional argument in next - https://github.com/vercel/next.js/issues/54685
|
|
1175
|
-
const messagesFromStore =
|
|
1255
|
+
const messagesFromStore = React__namespace["default"].useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
1176
1256
|
return [
|
|
1177
1257
|
{
|
|
1178
1258
|
data: { messages: messagesFromStore },
|