@aws-amplify/ui-react-ai 0.3.2 → 1.0.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.
Files changed (71) hide show
  1. package/dist/esm/components/AIConversation/AIConversation.mjs +21 -33
  2. package/dist/esm/components/AIConversation/AIConversationProvider.mjs +22 -16
  3. package/dist/esm/components/AIConversation/context/AIContextContext.mjs +8 -0
  4. package/dist/esm/components/AIConversation/context/FallbackComponentContext.mjs +8 -0
  5. package/dist/esm/components/AIConversation/context/MessageRenderContext.mjs +9 -0
  6. package/dist/esm/components/AIConversation/context/ResponseComponentsContext.mjs +6 -2
  7. package/dist/esm/components/AIConversation/context/WelcomeMessageContext.mjs +8 -0
  8. package/dist/esm/components/AIConversation/createAIConversation.mjs +18 -22
  9. package/dist/esm/components/AIConversation/views/Controls/ActionsBarControl.mjs +6 -2
  10. package/dist/esm/components/AIConversation/views/Controls/AttachFileControl.mjs +5 -0
  11. package/dist/esm/components/AIConversation/views/Controls/AttachmentListControl.mjs +5 -0
  12. package/dist/esm/components/AIConversation/views/Controls/AvatarControl.mjs +5 -0
  13. package/dist/esm/components/AIConversation/views/Controls/DefaultMessageControl.mjs +31 -0
  14. package/dist/esm/components/AIConversation/views/Controls/{FieldControl.mjs → FormControl.mjs} +22 -13
  15. package/dist/esm/components/AIConversation/views/Controls/MessagesControl.mjs +42 -42
  16. package/dist/esm/components/AIConversation/views/Controls/PromptControl.mjs +9 -36
  17. package/dist/esm/components/AIConversation/views/default/Form.mjs +4 -5
  18. package/dist/esm/components/AIConversation/views/default/MessageList.mjs +34 -16
  19. package/dist/esm/components/AIConversation/views/default/PromptList.mjs +1 -1
  20. package/dist/esm/hooks/contentFromEvents.mjs +22 -0
  21. package/dist/esm/hooks/createAIHooks.mjs +0 -3
  22. package/dist/esm/hooks/exhaustivelyListMessages.mjs +19 -0
  23. package/dist/esm/hooks/shared.mjs +14 -0
  24. package/dist/esm/hooks/useAIConversation.mjs +246 -106
  25. package/dist/esm/hooks/useAIGeneration.mjs +1 -8
  26. package/dist/esm/index.mjs +0 -1
  27. package/dist/esm/version.mjs +3 -0
  28. package/dist/index.js +569 -444
  29. package/dist/types/components/AIConversation/AIConversation.d.ts +2 -19
  30. package/dist/types/components/AIConversation/AIConversationProvider.d.ts +2 -3
  31. package/dist/types/components/AIConversation/context/AIContextContext.d.ts +6 -0
  32. package/dist/types/components/AIConversation/context/ControlsContext.d.ts +1 -0
  33. package/dist/types/components/AIConversation/context/FallbackComponentContext.d.ts +7 -0
  34. package/dist/types/components/AIConversation/context/MessageRenderContext.d.ts +5 -0
  35. package/dist/types/components/AIConversation/context/ResponseComponentsContext.d.ts +2 -2
  36. package/dist/types/components/AIConversation/context/WelcomeMessageContext.d.ts +8 -0
  37. package/dist/types/components/AIConversation/context/elements/definitions.d.ts +1 -1
  38. package/dist/types/components/AIConversation/context/index.d.ts +5 -0
  39. package/dist/types/components/AIConversation/createAIConversation.d.ts +0 -3
  40. package/dist/types/components/AIConversation/index.d.ts +2 -1
  41. package/dist/types/components/AIConversation/types.d.ts +24 -36
  42. package/dist/types/components/AIConversation/utils.d.ts +2 -2
  43. package/dist/types/components/AIConversation/views/Controls/DefaultMessageControl.d.ts +2 -0
  44. package/dist/types/components/AIConversation/views/Controls/{FieldControl.d.ts → FormControl.d.ts} +2 -2
  45. package/dist/types/components/AIConversation/views/Controls/MessagesControl.d.ts +3 -9
  46. package/dist/types/components/AIConversation/views/Controls/PromptControl.d.ts +0 -3
  47. package/dist/types/components/AIConversation/views/Controls/index.d.ts +3 -4
  48. package/dist/types/components/AIConversation/views/default/Form.d.ts +1 -1
  49. package/dist/types/components/AIConversation/views/default/MessageList.d.ts +1 -1
  50. package/dist/types/components/AIConversation/views/default/PromptList.d.ts +1 -1
  51. package/dist/types/components/AIConversation/views/index.d.ts +2 -3
  52. package/dist/types/hooks/contentFromEvents.d.ts +2 -0
  53. package/dist/types/hooks/createAIHooks.d.ts +0 -3
  54. package/dist/types/hooks/exhaustivelyListMessages.d.ts +8 -0
  55. package/dist/types/hooks/index.d.ts +1 -2
  56. package/dist/types/hooks/shared.d.ts +23 -0
  57. package/dist/types/hooks/useAIConversation.d.ts +6 -4
  58. package/dist/types/hooks/useAIGeneration.d.ts +3 -13
  59. package/dist/types/index.d.ts +1 -1
  60. package/dist/types/types.d.ts +38 -7
  61. package/dist/types/version.d.ts +1 -0
  62. package/package.json +20 -6
  63. package/dist/ai-conversation-styles.css +0 -195
  64. package/dist/ai-conversation-styles.js +0 -2
  65. package/dist/esm/components/AIConversation/views/Controls/HeaderControl.mjs +0 -34
  66. package/dist/esm/components/AIConversation/views/ConversationView.mjs +0 -20
  67. package/dist/esm/hooks/AIContextProvider.mjs +0 -20
  68. package/dist/types/ai-conversation-styles.d.ts +0 -1
  69. package/dist/types/components/AIConversation/views/Controls/HeaderControl.d.ts +0 -9
  70. package/dist/types/components/AIConversation/views/ConversationView.d.ts +0 -2
  71. package/dist/types/hooks/AIContextProvider.d.ts +0 -17
@@ -1,71 +1,59 @@
1
1
  import * as React from 'react';
2
- import { Text, Flex, ScrollView } from '@aws-amplify/ui-react';
2
+ import { Flex, ScrollView } from '@aws-amplify/ui-react';
3
3
  import { useIcons, IconAssistant, IconUser } from '@aws-amplify/ui-react/internal';
4
4
  import { MessagesControl } from './views/Controls/MessagesControl.mjs';
5
- import './context/elements/definitions.mjs';
6
- import './views/Controls/ActionsBarControl.mjs';
7
- import './views/Controls/AvatarControl.mjs';
8
- import './views/Controls/HeaderControl.mjs';
9
- import { FieldControl } from './views/Controls/FieldControl.mjs';
10
- import { AutoHidablePromptControl } from './views/Controls/PromptControl.mjs';
5
+ import { FormControl } from './views/Controls/FormControl.mjs';
11
6
  import { MessageList } from './views/default/MessageList.mjs';
12
7
  import { Form } from './views/default/Form.mjs';
13
8
  import { PromptList } from './views/default/PromptList.mjs';
14
9
  import { ComponentClassName } from '@aws-amplify/ui';
15
10
  import { AIConversationProvider } from './AIConversationProvider.mjs';
11
+ import { useSetUserAgent } from '@aws-amplify/ui-react-core';
12
+ import { VERSION } from '../../version.mjs';
13
+ import { DefaultMessageControl } from './views/Controls/DefaultMessageControl.mjs';
16
14
 
17
- function AIConversationBase({ actions, avatars, controls, handleSendMessage, messages, responseComponents, suggestedPrompts, variant, isLoading, displayText, allowAttachments, }) {
15
+ function AIConversationBase({ avatars, controls, ...rest }) {
16
+ useSetUserAgent({
17
+ componentName: 'AIConversation',
18
+ packageName: 'react-ai',
19
+ version: VERSION,
20
+ });
18
21
  const icons = useIcons('aiConversation');
19
22
  const defaultAvatars = {
20
23
  ai: {
21
24
  username: 'Assistant',
22
- avatar: icons?.assistant ?? React.createElement(IconAssistant, null),
25
+ avatar: icons?.assistant ?? React.createElement(IconAssistant, { testId: "icon-assistant" }),
23
26
  },
24
27
  user: {
25
28
  username: 'User',
26
- avatar: icons?.user ?? React.createElement(IconUser, null),
29
+ avatar: icons?.user ?? React.createElement(IconUser, { testId: "icon-user" }),
27
30
  },
28
31
  };
29
32
  const providerProps = {
30
- messages,
31
- handleSendMessage,
33
+ ...rest,
32
34
  avatars: {
33
35
  ...defaultAvatars,
34
36
  ...avatars,
35
37
  },
36
- isLoading,
37
- elements: {
38
- Text: React.forwardRef(function _Text(props, ref) {
39
- return React.createElement(Text, { ...props, ref: ref });
40
- }),
41
- },
42
- actions,
43
- suggestedPrompts,
44
- responseComponents,
45
- variant,
46
38
  controls: {
47
39
  MessageList,
48
40
  PromptList,
49
41
  Form,
50
42
  ...controls,
51
43
  },
52
- displayText,
53
- allowAttachments,
54
44
  };
55
45
  return (React.createElement(AIConversationProvider, { ...providerProps },
56
- React.createElement(Flex, { className: ComponentClassName.AIConversation },
46
+ React.createElement(Flex, { className: ComponentClassName.AIConversation, testId: "ai-conversation" },
57
47
  React.createElement(ScrollView, { autoScroll: "smooth", flex: "1" },
58
- React.createElement(AutoHidablePromptControl, null),
48
+ React.createElement(DefaultMessageControl, null),
59
49
  React.createElement(MessagesControl, null)),
60
- React.createElement(FieldControl, null))));
50
+ React.createElement(FormControl, null))));
61
51
  }
62
- /**
63
- * @experimental
64
- */
65
52
  const AIConversation = Object.assign(AIConversationBase, {
66
- MessageList,
67
- PromptList,
68
- Form,
53
+ Provider: AIConversationProvider,
54
+ DefaultMessage: DefaultMessageControl,
55
+ Messages: MessagesControl,
56
+ Form: FormControl,
69
57
  });
70
58
 
71
59
  export { AIConversation };
@@ -1,6 +1,6 @@
1
1
  import React__default from 'react';
2
- import { ElementsProvider } from '@aws-amplify/ui-react-core/elements';
3
2
  import { defaultAIConversationDisplayTextEn } from './displayText.mjs';
3
+ import { AIContextProvider } from './context/AIContextContext.mjs';
4
4
  import { ActionsProvider } from './context/ActionsContext.mjs';
5
5
  import { AvatarsProvider } from './context/AvatarsContext.mjs';
6
6
  import { ConversationInputContextProvider } from './context/ConversationInputContext.mjs';
@@ -12,27 +12,33 @@ import { ControlsProvider } from './context/ControlsContext.mjs';
12
12
  import { LoadingContextProvider } from './context/LoadingContext.mjs';
13
13
  import { ResponseComponentsProvider } from './context/ResponseComponentsContext.mjs';
14
14
  import { SendMessageContextProvider } from './context/SendMessageContext.mjs';
15
- import './context/elements/definitions.mjs';
15
+ import { MessageRendererProvider } from './context/MessageRenderContext.mjs';
16
16
  import { AttachmentProvider } from './context/AttachmentContext.mjs';
17
+ import { WelcomeMessageProvider } from './context/WelcomeMessageContext.mjs';
18
+ import { FallbackComponentProvider } from './context/FallbackComponentContext.mjs';
19
+ import './context/elements/definitions.mjs';
17
20
 
18
- const AIConversationProvider = ({ elements, actions, suggestedPrompts, responseComponents, variant, controls, displayText, allowAttachments, messages, handleSendMessage, avatars, isLoading, children, }) => {
21
+ const AIConversationProvider = ({ aiContext, actions, allowAttachments, avatars, children, controls, displayText, handleSendMessage, isLoading, messages, messageRenderer, responseComponents, suggestedPrompts, variant, welcomeMessage, FallbackResponseComponent, }) => {
19
22
  const _displayText = {
20
23
  ...defaultAIConversationDisplayTextEn,
21
24
  ...displayText,
22
25
  };
23
- return (React__default.createElement(ElementsProvider, { elements: elements },
24
- React__default.createElement(ControlsProvider, { controls: controls },
25
- React__default.createElement(SuggestedPromptProvider, { suggestedPrompts: suggestedPrompts },
26
- React__default.createElement(ResponseComponentsProvider, { responseComponents: responseComponents },
27
- React__default.createElement(AttachmentProvider, { allowAttachments: allowAttachments },
28
- React__default.createElement(ConversationDisplayTextProvider, { ..._displayText },
29
- React__default.createElement(ConversationInputContextProvider, null,
30
- React__default.createElement(SendMessageContextProvider, { handleSendMessage: handleSendMessage },
31
- React__default.createElement(AvatarsProvider, { avatars: avatars },
32
- React__default.createElement(ActionsProvider, { actions: actions },
33
- React__default.createElement(MessageVariantProvider, { variant: variant },
34
- React__default.createElement(MessagesProvider, { messages: messages },
35
- React__default.createElement(LoadingContextProvider, { isLoading: isLoading }, children))))))))))))));
26
+ return (React__default.createElement(ControlsProvider, { controls: controls },
27
+ React__default.createElement(SuggestedPromptProvider, { suggestedPrompts: suggestedPrompts },
28
+ React__default.createElement(WelcomeMessageProvider, { welcomeMessage: welcomeMessage },
29
+ React__default.createElement(FallbackComponentProvider, { FallbackComponent: FallbackResponseComponent },
30
+ React__default.createElement(MessageRendererProvider, { ...messageRenderer },
31
+ React__default.createElement(ResponseComponentsProvider, { responseComponents: responseComponents },
32
+ React__default.createElement(AttachmentProvider, { allowAttachments: allowAttachments },
33
+ React__default.createElement(ConversationDisplayTextProvider, { ..._displayText },
34
+ React__default.createElement(ConversationInputContextProvider, null,
35
+ React__default.createElement(SendMessageContextProvider, { handleSendMessage: handleSendMessage },
36
+ React__default.createElement(AvatarsProvider, { avatars: avatars },
37
+ React__default.createElement(ActionsProvider, { actions: actions },
38
+ React__default.createElement(MessageVariantProvider, { variant: variant },
39
+ React__default.createElement(MessagesProvider, { messages: messages },
40
+ React__default.createElement(AIContextProvider, { aiContext: aiContext },
41
+ React__default.createElement(LoadingContextProvider, { isLoading: isLoading }, children)))))))))))))))));
36
42
  };
37
43
 
38
44
  export { AIConversationProvider };
@@ -0,0 +1,8 @@
1
+ import React__default from 'react';
2
+
3
+ const AIContextContext = React__default.createContext(undefined);
4
+ const AIContextProvider = ({ children, aiContext, }) => {
5
+ return (React__default.createElement(AIContextContext.Provider, { value: aiContext }, children));
6
+ };
7
+
8
+ export { AIContextContext, AIContextProvider };
@@ -0,0 +1,8 @@
1
+ import React__default from 'react';
2
+
3
+ const FallbackComponentContext = React__default.createContext(undefined);
4
+ const FallbackComponentProvider = ({ children, FallbackComponent, }) => {
5
+ return (React__default.createElement(FallbackComponentContext.Provider, { value: FallbackComponent }, children));
6
+ };
7
+
8
+ export { FallbackComponentContext, FallbackComponentProvider };
@@ -0,0 +1,9 @@
1
+ import { createContextUtilities } from '@aws-amplify/ui-react-core';
2
+
3
+ const { MessageRendererContext, MessageRendererProvider, useMessageRenderer, } = createContextUtilities({
4
+ contextName: 'MessageRenderer',
5
+ defaultValue: undefined,
6
+ errorMessage: '`useMessageRenderer` must be used with an AIConversation component',
7
+ });
8
+
9
+ export { MessageRendererContext, MessageRendererProvider, useMessageRenderer };
@@ -21,8 +21,12 @@ const convertResponseComponentsToToolConfiguration = (responseComponents) => {
21
21
  const { props } = responseComponents[toolName];
22
22
  const requiredProps = [];
23
23
  Object.keys(props).forEach((propName) => {
24
- if (props[propName].required)
24
+ if (props[propName].required) {
25
25
  requiredProps.push(propName);
26
+ // The inputSchema for a tool needs to not
27
+ // have `required` in the properties
28
+ props[propName].required = undefined;
29
+ }
26
30
  });
27
31
  tools[toolName] = {
28
32
  description: responseComponents[toolName].description,
@@ -40,4 +44,4 @@ const convertResponseComponentsToToolConfiguration = (responseComponents) => {
40
44
  return { tools };
41
45
  };
42
46
 
43
- export { RESPONSE_COMPONENT_PREFIX, ResponseComponentsContext, ResponseComponentsProvider, convertResponseComponentsToToolConfiguration };
47
+ export { RESPONSE_COMPONENT_PREFIX, ResponseComponentsContext, ResponseComponentsProvider, convertResponseComponentsToToolConfiguration, prependResponseComponents };
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+
3
+ const WelcomeMessageContext = React.createContext(undefined);
4
+ const WelcomeMessageProvider = ({ children, welcomeMessage, }) => {
5
+ return (React.createElement(WelcomeMessageContext.Provider, { value: welcomeMessage }, children));
6
+ };
7
+
8
+ export { WelcomeMessageContext, WelcomeMessageProvider };
@@ -1,22 +1,18 @@
1
1
  import React__default from 'react';
2
- import Conversation from './views/ConversationView.mjs';
3
- import { ActionsBarControl } from './views/Controls/ActionsBarControl.mjs';
4
- import { AvatarControl } from './views/Controls/AvatarControl.mjs';
5
- import { HeaderControl } from './views/Controls/HeaderControl.mjs';
6
- import { FieldControl } from './views/Controls/FieldControl.mjs';
2
+ import './views/Controls/ActionsBarControl.mjs';
3
+ import './views/Controls/AvatarControl.mjs';
4
+ import { FormControl } from './views/Controls/FormControl.mjs';
7
5
  import { MessagesControl } from './views/Controls/MessagesControl.mjs';
8
- import { PromptControl } from './views/Controls/PromptControl.mjs';
6
+ import './views/Controls/PromptControl.mjs';
7
+ import { ViewElement } from './context/elements/definitions.mjs';
9
8
  import { AIConversationProvider } from './AIConversationProvider.mjs';
9
+ import { DefaultMessageControl } from './views/Controls/DefaultMessageControl.mjs';
10
10
 
11
- /**
12
- * @experimental
13
- */
14
11
  function createAIConversation(input = {}) {
15
- const { elements, suggestedPrompts, actions, responseComponents, variant, controls, displayText, allowAttachments, } = input;
12
+ const { suggestedPrompts, actions, responseComponents, variant, controls, displayText, allowAttachments, messageRenderer, FallbackResponseComponent, } = input;
16
13
  function AIConversation(props) {
17
14
  const { messages, avatars, handleSendMessage, isLoading } = props;
18
15
  const providerProps = {
19
- elements,
20
16
  actions,
21
17
  suggestedPrompts,
22
18
  responseComponents,
@@ -28,21 +24,21 @@ function createAIConversation(input = {}) {
28
24
  avatars,
29
25
  handleSendMessage,
30
26
  isLoading,
27
+ messageRenderer,
28
+ FallbackResponseComponent,
31
29
  };
32
30
  return (React__default.createElement(AIConversationProvider, { ...providerProps },
33
- React__default.createElement(Conversation, null)));
31
+ React__default.createElement(ViewElement, null,
32
+ React__default.createElement(ViewElement, null,
33
+ React__default.createElement(DefaultMessageControl, null),
34
+ React__default.createElement(MessagesControl, null)),
35
+ React__default.createElement(ViewElement, null,
36
+ React__default.createElement(FormControl, null)))));
34
37
  }
35
- const Controls = {
36
- ActionsBar: ActionsBarControl,
37
- Avatars: AvatarControl,
38
- Field: FieldControl,
39
- Header: HeaderControl,
40
- Messages: MessagesControl,
41
- SuggestedPrompts: PromptControl,
42
- };
43
38
  AIConversation.Provider = AIConversationProvider;
44
- AIConversation.Conversation = Conversation;
45
- AIConversation.Controls = Controls;
39
+ AIConversation.DefaultMessage = DefaultMessageControl;
40
+ AIConversation.Messages = MessagesControl;
41
+ AIConversation.Form = FormControl;
46
42
  return { AIConversation };
47
43
  }
48
44
 
@@ -1,5 +1,6 @@
1
1
  import React__default from 'react';
2
2
  import { withBaseElementProps } from '@aws-amplify/ui-react-core/elements';
3
+ import '../../context/AIContextContext.mjs';
3
4
  import { ActionsContext } from '../../context/ActionsContext.mjs';
4
5
  import '../../context/AvatarsContext.mjs';
5
6
  import '../../context/ConversationInputContext.mjs';
@@ -11,6 +12,10 @@ import '../../context/ControlsContext.mjs';
11
12
  import '../../context/LoadingContext.mjs';
12
13
  import '../../context/ResponseComponentsContext.mjs';
13
14
  import '../../context/SendMessageContext.mjs';
15
+ import '../../context/MessageRenderContext.mjs';
16
+ import '../../context/AttachmentContext.mjs';
17
+ import '../../context/WelcomeMessageContext.mjs';
18
+ import '../../context/FallbackComponentContext.mjs';
14
19
  import { AIConversationElements } from '../../context/elements/definitions.mjs';
15
20
 
16
21
  const { Button, Span, View } = AIConversationElements;
@@ -30,8 +35,7 @@ const Container = withBaseElementProps(View, {
30
35
  });
31
36
  const ActionsBarControl = ({ message, focusable, }) => {
32
37
  const actions = React__default.useContext(ActionsContext);
33
- return (React__default.createElement(Container, null, actions?.map((action, index) => (React__default.createElement(ActionButton, { "aria-label": action.displayName, key: index, onClick: () => action.handler(message), tabIndex: focusable ? 0 : -1 },
34
- React__default.createElement(ActionIcon, { "data-testid": `action-icon-${action.displayName}` }, action.icon))))));
38
+ return (React__default.createElement(Container, null, actions?.map((action, index) => (React__default.createElement(ActionButton, { key: index, onClick: () => action.handler(message), tabIndex: focusable ? 0 : -1 }, action.component)))));
35
39
  };
36
40
  ActionsBarControl.Button = ActionButton;
37
41
  ActionsBarControl.Container = Container;
@@ -1,5 +1,6 @@
1
1
  import React__default from 'react';
2
2
  import { withBaseElementProps } from '@aws-amplify/ui-react-core/elements';
3
+ import '../../context/AIContextContext.mjs';
3
4
  import '../../context/ActionsContext.mjs';
4
5
  import '../../context/AvatarsContext.mjs';
5
6
  import { ConversationInputContext } from '../../context/ConversationInputContext.mjs';
@@ -11,6 +12,10 @@ import '../../context/ControlsContext.mjs';
11
12
  import '../../context/LoadingContext.mjs';
12
13
  import '../../context/ResponseComponentsContext.mjs';
13
14
  import '../../context/SendMessageContext.mjs';
15
+ import '../../context/MessageRenderContext.mjs';
16
+ import '../../context/AttachmentContext.mjs';
17
+ import '../../context/WelcomeMessageContext.mjs';
18
+ import '../../context/FallbackComponentContext.mjs';
14
19
  import { AIConversationElements } from '../../context/elements/definitions.mjs';
15
20
  import { useDropZone } from '@aws-amplify/ui-react-core';
16
21
 
@@ -1,5 +1,6 @@
1
1
  import React__default from 'react';
2
2
  import { withBaseElementProps } from '@aws-amplify/ui-react-core/elements';
3
+ import '../../context/AIContextContext.mjs';
3
4
  import '../../context/ActionsContext.mjs';
4
5
  import '../../context/AvatarsContext.mjs';
5
6
  import { ConversationInputContext } from '../../context/ConversationInputContext.mjs';
@@ -11,6 +12,10 @@ import '../../context/ControlsContext.mjs';
11
12
  import '../../context/LoadingContext.mjs';
12
13
  import '../../context/ResponseComponentsContext.mjs';
13
14
  import '../../context/SendMessageContext.mjs';
15
+ import '../../context/MessageRenderContext.mjs';
16
+ import '../../context/AttachmentContext.mjs';
17
+ import '../../context/WelcomeMessageContext.mjs';
18
+ import '../../context/FallbackComponentContext.mjs';
14
19
  import { AIConversationElements } from '../../context/elements/definitions.mjs';
15
20
 
16
21
  const { Button, Icon, ListItem, UnorderedList: ListElement, Span, Text, View, } = AIConversationElements;
@@ -1,5 +1,6 @@
1
1
  import React__default from 'react';
2
2
  import { withBaseElementProps } from '@aws-amplify/ui-react-core/elements';
3
+ import '../../context/AIContextContext.mjs';
3
4
  import '../../context/ActionsContext.mjs';
4
5
  import { AvatarsContext } from '../../context/AvatarsContext.mjs';
5
6
  import '../../context/ConversationInputContext.mjs';
@@ -11,6 +12,10 @@ import '../../context/ControlsContext.mjs';
11
12
  import '../../context/LoadingContext.mjs';
12
13
  import '../../context/ResponseComponentsContext.mjs';
13
14
  import '../../context/SendMessageContext.mjs';
15
+ import '../../context/MessageRenderContext.mjs';
16
+ import '../../context/AttachmentContext.mjs';
17
+ import '../../context/WelcomeMessageContext.mjs';
18
+ import '../../context/FallbackComponentContext.mjs';
14
19
  import { AIConversationElements } from '../../context/elements/definitions.mjs';
15
20
 
16
21
  const { Icon, Span, Text, View } = AIConversationElements;
@@ -0,0 +1,31 @@
1
+ import * as React from 'react';
2
+ import '../../context/AIContextContext.mjs';
3
+ import '../../context/ActionsContext.mjs';
4
+ import '../../context/AvatarsContext.mjs';
5
+ import '../../context/ConversationInputContext.mjs';
6
+ import { MessagesContext } from '../../context/MessagesContext.mjs';
7
+ import '../../context/SuggestedPromptsContext.mjs';
8
+ import '../../context/MessageVariantContext.mjs';
9
+ import '../../context/DisplayTextContext.mjs';
10
+ import '../../context/ControlsContext.mjs';
11
+ import '../../context/LoadingContext.mjs';
12
+ import '../../context/ResponseComponentsContext.mjs';
13
+ import '../../context/SendMessageContext.mjs';
14
+ import '../../context/MessageRenderContext.mjs';
15
+ import '../../context/AttachmentContext.mjs';
16
+ import { WelcomeMessageContext } from '../../context/WelcomeMessageContext.mjs';
17
+ import '../../context/FallbackComponentContext.mjs';
18
+ import '../../context/elements/definitions.mjs';
19
+ import { PromptControl } from './PromptControl.mjs';
20
+
21
+ const DefaultMessageControl = () => {
22
+ const messages = React.useContext(MessagesContext);
23
+ const welcomeMessage = React.useContext(WelcomeMessageContext);
24
+ if (!messages || messages.length === 0) {
25
+ return (React.createElement(React.Fragment, null,
26
+ welcomeMessage,
27
+ React.createElement(PromptControl, null)));
28
+ }
29
+ };
30
+
31
+ export { DefaultMessageControl };
@@ -1,5 +1,6 @@
1
1
  import React__default from 'react';
2
2
  import { withBaseElementProps } from '@aws-amplify/ui-react-core/elements';
3
+ import { AIContextContext } from '../../context/AIContextContext.mjs';
3
4
  import '../../context/ActionsContext.mjs';
4
5
  import '../../context/AvatarsContext.mjs';
5
6
  import { ConversationInputContext } from '../../context/ConversationInputContext.mjs';
@@ -11,11 +12,15 @@ import { ControlsContext } from '../../context/ControlsContext.mjs';
11
12
  import { LoadingContext } from '../../context/LoadingContext.mjs';
12
13
  import { ResponseComponentsContext, convertResponseComponentsToToolConfiguration } from '../../context/ResponseComponentsContext.mjs';
13
14
  import { SendMessageContext } from '../../context/SendMessageContext.mjs';
15
+ import '../../context/MessageRenderContext.mjs';
16
+ import { AttachmentContext } from '../../context/AttachmentContext.mjs';
17
+ import '../../context/WelcomeMessageContext.mjs';
18
+ import '../../context/FallbackComponentContext.mjs';
14
19
  import { AIConversationElements } from '../../context/elements/definitions.mjs';
15
20
  import { AttachFileControl } from './AttachFileControl.mjs';
16
21
  import { AttachmentListControl } from './AttachmentListControl.mjs';
17
22
  import { getImageTypeFromMimeType } from '../../utils.mjs';
18
- import { AttachmentContext } from '../../context/AttachmentContext.mjs';
23
+ import { isFunction } from '@aws-amplify/ui';
19
24
 
20
25
  const { Button, Icon, Label: LabelElement, TextArea, View, } = AIConversationElements;
21
26
  const FIELD_BLOCK = 'ai-field';
@@ -97,13 +102,16 @@ const TextInput = React__default.forwardRef(function TextInput(props, ref) {
97
102
  const InputContainer = withBaseElementProps(View, {
98
103
  className: `${FIELD_BLOCK}__input-container`,
99
104
  });
100
- const FieldControl = () => {
105
+ const FormControl = () => {
101
106
  const { input, setInput } = React__default.useContext(ConversationInputContext);
102
107
  const handleSendMessage = React__default.useContext(SendMessageContext);
103
108
  const allowAttachments = React__default.useContext(AttachmentContext);
104
- const ref = React__default.useRef(null);
105
109
  const responseComponents = React__default.useContext(ResponseComponentsContext);
110
+ const isLoading = React__default.useContext(LoadingContext);
111
+ const aiContext = React__default.useContext(AIContextContext);
112
+ const ref = React__default.useRef(null);
106
113
  const controls = React__default.useContext(ControlsContext);
114
+ const [composing, setComposing] = React__default.useState(false);
107
115
  const submitMessage = async () => {
108
116
  ref.current?.reset();
109
117
  const submittedContent = [];
@@ -128,6 +136,7 @@ const FieldControl = () => {
128
136
  if (handleSendMessage) {
129
137
  handleSendMessage({
130
138
  content: submittedContent,
139
+ aiContext: isFunction(aiContext) ? aiContext() : undefined,
131
140
  toolConfiguration: convertResponseComponentsToToolConfiguration(responseComponents),
132
141
  });
133
142
  }
@@ -140,7 +149,7 @@ const FieldControl = () => {
140
149
  };
141
150
  const handleOnKeyDown = (event) => {
142
151
  const { key, shiftKey } = event;
143
- if (key === 'Enter' && !shiftKey) {
152
+ if (key === 'Enter' && !shiftKey && !composing) {
144
153
  event.preventDefault();
145
154
  const hasInput = !!input?.text || (input?.files?.length && input?.files?.length > 0);
146
155
  if (hasInput) {
@@ -149,23 +158,23 @@ const FieldControl = () => {
149
158
  }
150
159
  };
151
160
  if (controls?.Form) {
152
- return (React__default.createElement(controls.Form, { handleSubmit: handleSubmit, input: input, setInput: setInput, allowAttachments: allowAttachments }));
161
+ return (React__default.createElement(controls.Form, { handleSubmit: handleSubmit, input: input, setInput: setInput, allowAttachments: allowAttachments, isLoading: isLoading }));
153
162
  }
154
163
  return (React__default.createElement("form", { className: `${FIELD_BLOCK}__form`, onSubmit: handleSubmit, method: "post", ref: ref },
155
164
  allowAttachments ? React__default.createElement(AttachFileControl, null) : null,
156
165
  React__default.createElement(InputContainer, null,
157
166
  React__default.createElement(VisuallyHidden, null,
158
167
  React__default.createElement(Label, null)),
159
- React__default.createElement(TextInput, { onKeyDown: handleOnKeyDown }),
168
+ React__default.createElement(TextInput, { onKeyDown: handleOnKeyDown, onCompositionStart: () => setComposing(true), onCompositionEnd: () => setComposing(false) }),
160
169
  React__default.createElement(AttachmentListControl, null)),
161
170
  React__default.createElement(SendButton, null,
162
171
  React__default.createElement(SendIcon, null))));
163
172
  };
164
- FieldControl.AttachFile = AttachFileControl;
165
- FieldControl.InputContainer = InputContainer;
166
- FieldControl.Label = Label;
167
- FieldControl.TextInput = TextInput;
168
- FieldControl.SendButton = SendButton;
169
- FieldControl.SendIcon = SendIcon;
173
+ FormControl.AttachFile = AttachFileControl;
174
+ FormControl.InputContainer = InputContainer;
175
+ FormControl.Label = Label;
176
+ FormControl.TextInput = TextInput;
177
+ FormControl.SendButton = SendButton;
178
+ FormControl.SendIcon = SendIcon;
170
179
 
171
- export { FieldControl };
180
+ export { FormControl };
@@ -1,5 +1,7 @@
1
1
  import React__default from 'react';
2
+ import { Image } from '@aws-amplify/ui-react';
2
3
  import { withBaseElementProps } from '@aws-amplify/ui-react-core/elements';
4
+ import '../../context/AIContextContext.mjs';
3
5
  import '../../context/ActionsContext.mjs';
4
6
  import '../../context/AvatarsContext.mjs';
5
7
  import '../../context/ConversationInputContext.mjs';
@@ -9,64 +11,64 @@ import { MessageVariantContext } from '../../context/MessageVariantContext.mjs';
9
11
  import { useConversationDisplayText } from '../../context/DisplayTextContext.mjs';
10
12
  import { ControlsContext } from '../../context/ControlsContext.mjs';
11
13
  import '../../context/LoadingContext.mjs';
12
- import { ResponseComponentsContext, RESPONSE_COMPONENT_PREFIX } from '../../context/ResponseComponentsContext.mjs';
14
+ import { RESPONSE_COMPONENT_PREFIX, ResponseComponentsContext } from '../../context/ResponseComponentsContext.mjs';
13
15
  import '../../context/SendMessageContext.mjs';
16
+ import { MessageRendererContext } from '../../context/MessageRenderContext.mjs';
17
+ import '../../context/AttachmentContext.mjs';
18
+ import '../../context/WelcomeMessageContext.mjs';
19
+ import { FallbackComponentContext } from '../../context/FallbackComponentContext.mjs';
14
20
  import { AIConversationElements } from '../../context/elements/definitions.mjs';
15
21
  import { convertBufferToBase64 } from '../../utils.mjs';
16
22
  import { ActionsBarControl } from './ActionsBarControl.mjs';
17
23
  import { AvatarControl } from './AvatarControl.mjs';
24
+ import { classNames } from '@aws-amplify/ui';
18
25
 
19
- const { Image, Span, Text, View } = AIConversationElements;
20
- const MESSAGES_BLOCK = 'ai-messages';
21
- const MESSAGE_BLOCK = 'ai-message';
22
- const MediaContentBase = withBaseElementProps(Image, {
23
- alt: 'Image attachment',
24
- });
25
- const MediaContent = React__default.forwardRef(function MediaContent(props, ref) {
26
+ const { Text, View } = AIConversationElements;
27
+ const MESSAGES_BLOCK = 'amplify-ai-conversation__message__list';
28
+ const MESSAGE_BLOCK = 'amplify-ai-conversation__message';
29
+ const MediaContent = (props) => {
26
30
  const variant = React__default.useContext(MessageVariantContext);
27
31
  const role = React__default.useContext(RoleContext);
28
- return (React__default.createElement(MediaContentBase, { ref: ref, className: `${MESSAGE_BLOCK}__image ${MESSAGE_BLOCK}__image--${variant} ${MESSAGE_BLOCK}__image--${role}`, ...props }));
29
- });
32
+ return (React__default.createElement(Image, { className: classNames(`${MESSAGE_BLOCK}__image`, variant && `${MESSAGE_BLOCK}__image--${variant}`, `${MESSAGE_BLOCK}__image--${role}`), ...props }));
33
+ };
30
34
  const TextContent = React__default.forwardRef(function TextContent(props, ref) {
31
35
  return React__default.createElement(Text, { ref: ref, className: `${MESSAGE_BLOCK}__text`, ...props });
32
36
  });
33
- const ContentContainer = React__default.forwardRef(function ContentContainer(props, ref) {
34
- const variant = React__default.useContext(MessageVariantContext);
35
- return (React__default.createElement(View, { "data-testid": 'content', className: `${MESSAGE_BLOCK}__content ${MESSAGE_BLOCK}__content--${variant}`, ref: ref, ...props }));
36
- });
37
+ const ToolContent = ({ toolUse, }) => {
38
+ const responseComponents = React__default.useContext(ResponseComponentsContext) ?? {};
39
+ const FallbackComponent = React__default.useContext(FallbackComponentContext);
40
+ // For now tool use is limited to custom response components
41
+ const { name, input } = toolUse;
42
+ if (!name || !name.startsWith(RESPONSE_COMPONENT_PREFIX)) {
43
+ return;
44
+ }
45
+ else {
46
+ const response = responseComponents[name];
47
+ if (response) {
48
+ const CustomComponent = response.component;
49
+ return React__default.createElement(CustomComponent, { ...input });
50
+ }
51
+ // fallback if there is a UI component message but we don't have
52
+ // a React component that matches
53
+ if (FallbackComponent) {
54
+ return React__default.createElement(FallbackComponent, { ...input });
55
+ }
56
+ }
57
+ };
37
58
  const MessageControl = ({ message }) => {
38
- const responseComponents = React__default.useContext(ResponseComponentsContext);
39
- return (React__default.createElement(ContentContainer, null, message.content.map((content, index) => {
59
+ const messageRenderer = React__default.useContext(MessageRendererContext);
60
+ return (React__default.createElement(React__default.Fragment, null, message.content.map((content, index) => {
40
61
  if (content.text) {
41
- return (React__default.createElement(TextContent, { "data-testid": 'text-content', key: index }, content.text));
62
+ return messageRenderer?.text ? (React__default.createElement(React__default.Fragment, { key: index }, messageRenderer.text({ text: content.text }))) : (React__default.createElement(TextContent, { "data-testid": 'text-content', key: index }, content.text));
42
63
  }
43
64
  else if (content.image) {
44
- return (React__default.createElement(MediaContent, { "data-testid": 'image-content', key: index, src: convertBufferToBase64(content.image?.source.bytes, content.image?.format) }));
65
+ return messageRenderer?.image ? (React__default.createElement(React__default.Fragment, { key: index }, messageRenderer?.image({ image: content.image }))) : (React__default.createElement(MediaContent, { "data-testid": 'image-content', key: index, alt: "", src: convertBufferToBase64(content.image?.source.bytes, content.image?.format) }));
45
66
  }
46
67
  else if (content.toolUse) {
47
- // For now tool use is limited to custom response components
48
- const { name, input } = content.toolUse;
49
- if (!responseComponents ||
50
- !name ||
51
- !name.startsWith(RESPONSE_COMPONENT_PREFIX)) {
52
- return;
53
- }
54
- else {
55
- const response = responseComponents[name];
56
- const CustomComponent = response.component;
57
- return React__default.createElement(CustomComponent, { ...input, key: index });
58
- }
68
+ return React__default.createElement(ToolContent, { toolUse: content.toolUse, key: index });
59
69
  }
60
70
  })));
61
71
  };
62
- MessageControl.Container = ContentContainer;
63
- MessageControl.MediaContent = MediaContent;
64
- MessageControl.TextContent = TextContent;
65
- const Separator = withBaseElementProps(Span, {
66
- 'aria-hidden': true,
67
- children: '|',
68
- className: `${MESSAGE_BLOCK}__separator`,
69
- });
70
72
  const Timestamp = withBaseElementProps(Text, {
71
73
  className: `${MESSAGE_BLOCK}__timestamp`,
72
74
  });
@@ -83,7 +85,7 @@ const Layout = React__default.forwardRef(function Layout(props, ref) {
83
85
  const variant = React__default.useContext(MessageVariantContext);
84
86
  return (React__default.createElement(View, { ref: ref, className: `${MESSAGES_BLOCK}__container ${MESSAGES_BLOCK}__container--${variant}`, "aria-live": 'assertive', ...props }));
85
87
  });
86
- const MessagesControl = ({ renderMessage }) => {
88
+ const MessagesControl = () => {
87
89
  const messages = React__default.useContext(MessagesContext);
88
90
  const controls = React__default.useContext(ControlsContext);
89
91
  const { getMessageTimestampText } = useConversationDisplayText();
@@ -123,11 +125,10 @@ const MessagesControl = ({ renderMessage }) => {
123
125
  content.text ??
124
126
  content.toolUse?.name.startsWith(RESPONSE_COMPONENT_PREFIX))) ?? [];
125
127
  return (React__default.createElement(Layout, null, messagesWithRenderableContent?.map((message, index) => {
126
- return renderMessage ? (renderMessage(message)) : (React__default.createElement(RoleContext.Provider, { value: message.role, key: `message-${index}` },
128
+ return (React__default.createElement(RoleContext.Provider, { value: message.role, key: `message-${index}` },
127
129
  React__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) },
128
130
  React__default.createElement(HeaderContainer, null,
129
131
  React__default.createElement(AvatarControl, null),
130
- React__default.createElement(Separator, null),
131
132
  React__default.createElement(Timestamp, null, getMessageTimestampText(new Date(message.createdAt)))),
132
133
  React__default.createElement(MessageControl, { message: message }),
133
134
  message.role === 'assistant' ? (React__default.createElement(ActionsBarControl, { message: message, focusable: focusedItemIndex === index })) : null)));
@@ -139,6 +140,5 @@ MessagesControl.Container = MessageContainer;
139
140
  MessagesControl.HeaderContainer = HeaderContainer;
140
141
  MessagesControl.Layout = Layout;
141
142
  MessagesControl.Message = MessageControl;
142
- MessagesControl.Separator = Separator;
143
143
 
144
144
  export { MessageControl, MessagesControl };