Class AiMessageList
java.lang.Object
com.vaadin.flow.component.Component
io.jmix.aichat.component.messagelist.AiMessageList
- All Implemented Interfaces:
com.vaadin.flow.component.AttachNotifier,com.vaadin.flow.component.DetachNotifier,com.vaadin.flow.component.HasElement,com.vaadin.flow.component.HasSize,com.vaadin.flow.component.HasStyle,com.vaadin.flow.i18n.LocaleChangeObserver,HasSubParts,Serializable,org.springframework.beans.factory.Aware,org.springframework.beans.factory.InitializingBean,org.springframework.context.ApplicationContextAware
@Tag("jmix-ai-message-list")
@JsModule("./src/ai-chat/messagelist/jmix-ai-message-list-connector.js") @JsModule("./src/ai-chat/messagelist/jmix-ai-message-list.js")
@NpmPackage(value="marked",version="16.4.2") @NpmPackage(value="dompurify",version="3.4.5")
public class AiMessageList
extends com.vaadin.flow.component.Component
implements com.vaadin.flow.component.HasStyle, com.vaadin.flow.component.HasSize, com.vaadin.flow.i18n.LocaleChangeObserver, org.springframework.context.ApplicationContextAware, org.springframework.beans.factory.InitializingBean, HasSubParts
Message List allows you to show a list of messages, for example, a chat log.
You can configure the text content, information about the sender and the time
of sending for each message. The component displays a list of messages that
can be configured with
setItems(Collection).- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classInternal event: a message action button was clicked on the client.static classFired when the user clicks an attachment of a message.static classFired when the user clicks the retry action of the error banner. -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected org.springframework.context.ApplicationContextprotected List<AiMessageAction<?>> protected intprotected @Nullable com.vaadin.flow.component.UIThe attached UI, cached becausegetUI()must not be called from a background thread — and thinking statuses are normally published from one.protected static final Stringprotected static final longprotected static final longprotected static final longprotected AiMessageListI18nprotected List<AiMessageListItem> protected @Nullable Integerprotected booleanprotected booleanprotected GenerationStateprotected static final Stringprotected List<ThinkingStage> protected ThinkingStatusPublisherprotected List<AiMessageAction<?>> protected int -
Constructor Summary
ConstructorsConstructorDescriptionCreates a new message list component.AiMessageList(AiMessageListItem... items) Creates a new message list component, with the provided items rendered as messages.AiMessageList(Collection<AiMessageListItem> items) Creates a new message list component, with the provided items rendered as messages. -
Method Summary
Modifier and TypeMethodDescriptionvoidaddAssistantAction(AiMessageAction<?> action) Appends an action to the actions shown under assistant messages, keeping the ones already there — including any declared in a view descriptor, whichsetAssistantActions(List)would replace.com.vaadin.flow.shared.RegistrationaddAttachmentClickListener(com.vaadin.flow.component.ComponentEventListener<AiMessageList.AttachmentClickEvent> listener) Adds a listener notified when the user clicks an attachment of a message.voidaddItem(AiMessageListItem item) Adds a single item to be rendered as a message at the end of this message list.com.vaadin.flow.shared.RegistrationaddRetryListener(com.vaadin.flow.component.ComponentEventListener<AiMessageList.RetryEvent> listener) Adds a listener for the retry action of the error banner.voidaddUserAction(AiMessageAction<?> action) Appends an action to the actions shown under user messages, keeping the ones already there — including any declared in a view descriptor, whichsetUserActions(List)would replace.voidprotected static List<ThinkingStage> protected @Nullable AiMessageListItemprotected @Nullable AiMessageListItemprotected Optional<AiMessageAction<?>> Finds a message action by its id, searching the user actions and then the assistant actions.protected Optional<com.vaadin.flow.component.Component> findSlotSubPart(com.vaadin.flow.component.Component slotComponent, String name) Resolves an id against the slot component: the component itself when its own id matches, otherwise a descendant of it.@Nullable AiMessageListItemThe active (generating) message: the lastMessageRole.ASSISTANTitem while the list isGenerationState.GENERATING, otherwisenull.List<AiMessageAction<?>> getI18n()getItems()Gets the items that are rendered as message components in this message list.getState()@Nullable ObjectgetSubPart(String name) Exposes the message actions and the custom thinking-indicator slot to the framework's id-based component walk.@Nullable com.vaadin.flow.component.ComponentThe thinking-status feed: the ordered account of what the assistant is doing, rendered above the thinking indicator while generating.List<AiMessageAction<?>> protected voidRoutes a client action click to the matching action, ignoring stale or invalid keys and out-of-range item indexes.protected voidhandleAddItemsUpdate(com.vaadin.flow.component.UI ui) Handles an incremental update that appends the newly added items to the client.protected voidhandleFullUpdate(com.vaadin.flow.component.UI ui) Handles a full update of the message list items.protected voidHandles incremental updates of the message list items' text content.protected voidSlots the default thinking indicator and registers the internal listeners.protected voidinitI18n()Resolves the localization and the default thinking stages from the message bundle.booleanReturns whether new messages are announced to assistive technologies.voidlocaleChange(com.vaadin.flow.i18n.LocaleChangeEvent event) protected voidonAttach(com.vaadin.flow.component.AttachEvent attachEvent) protected voidonDetach(com.vaadin.flow.component.DetachEvent detachEvent) protected voidSerializes and pushes the assistant actions to the client under the current generation.protected voidPushes the whole status feed to the client through the cached UI.protected voidSerializes and pushes the user actions to the client under the current generation.protected @Nullable AiMessageAction<?> resolveAction(@Nullable String key) Resolves a serialized action key back to its action.protected voidSchedules an incremental update to append newly added items to the client.protected voidSchedules an incremental update of the message list items' text content.protected voidSchedules a full update of the message list items.protected voidSchedules a client sync of the message list items to be run before the next client response.protected tools.jackson.databind.node.ArrayNodeserializeActions(List<AiMessageAction<?>> actions, String keyPrefix, int generation) Serializes the actions to their client wire format.voidsetAnnounceMessages(boolean announceMessages) When set totrue, new messages are announced to assistive technologies using ARIA live regions.voidsetApplicationContext(org.springframework.context.ApplicationContext applicationContext) voidsetAssistantActions(List<? extends AiMessageAction<?>> actions) Sets the actions shown under assistant messages.voidsetI18n(AiMessageListI18n i18n) Sets the i18n strings (error message, retry label, scroll-to-bottom label, copied label, and the nested code-block labels).voidsetItems(AiMessageListItem... items) Sets the items that will be rendered as messages in this message list.voidsetItems(Collection<AiMessageListItem> items) Sets the items that will be rendered as messages in this message list.voidsetState(GenerationState state) Sets the list-level generation state.voidsetThinkingIndicator(@Nullable com.vaadin.flow.component.Component indicator) Sets a custom thinking indicator, replacing the built-in animated dots.voidsetThinkingStages(List<ThinkingStage> thinkingStages) Sets the escalating "thinking" stages: ordered (delay, label) pairs shown next to the thinking indicator while the active message is generating and still empty.voidsetUserActions(List<? extends AiMessageAction<?>> actions) Sets the actions shown under user messages.protected voidupdateClient(com.vaadin.flow.component.UI ui) Updates the client with the current state of the message list items.Methods inherited from class com.vaadin.flow.component.Component
addListener, bindVisible, findAncestor, fireEvent, from, get, getChildren, getElement, getEventBus, getId, getListeners, getLocale, getParent, getTestId, getTranslation, getTranslation, getTranslation, getTranslation, getTranslation, getTranslation, getUI, hasListener, isAttached, isTemplateMapped, isVisible, onEnabledStateChanged, removeFromParent, scrollIntoView, scrollIntoView, set, setElement, setId, setTestId, setVisible, whenAttachedMethods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface com.vaadin.flow.component.AttachNotifier
addAttachListenerMethods inherited from interface com.vaadin.flow.component.DetachNotifier
addDetachListenerMethods inherited from interface com.vaadin.flow.component.HasElement
getElementMethods inherited from interface com.vaadin.flow.component.HasSize
bindHeight, bindWidth, getHeight, getHeightUnit, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getWidth, getWidthUnit, setHeight, setHeight, setHeightFull, setMaxHeight, setMaxHeight, setMaxWidth, setMaxWidth, setMinHeight, setMinHeight, setMinWidth, setMinWidth, setSizeFull, setSizeUndefined, setWidth, setWidth, setWidthFullMethods inherited from interface com.vaadin.flow.component.HasStyle
addClassName, addClassNames, bindClassName, bindClassNames, getClassName, getClassNames, getStyle, hasClassName, removeClassName, removeClassNames, setClassName, setClassName
-
Field Details
-
CONNECTOR_OBJECT
- See Also:
-
THINKING_INDICATOR_SLOT
- See Also:
-
DEFAULT_THINKING_DELAY_MS
protected static final long DEFAULT_THINKING_DELAY_MS- See Also:
-
DEFAULT_STILL_THINKING_DELAY_MS
protected static final long DEFAULT_STILL_THINKING_DELAY_MS- See Also:
-
DEFAULT_ALMOST_DONE_DELAY_MS
protected static final long DEFAULT_ALMOST_DONE_DELAY_MS- See Also:
-
applicationContext
protected org.springframework.context.ApplicationContext applicationContext -
i18n
-
items
-
pendingUpdate
protected boolean pendingUpdate -
pendingTextUpdate
protected boolean pendingTextUpdate -
pendingAddItemsIndex
-
state
-
thinkingStages
-
thinkingStatusPublisher
-
attachedUi
protected transient volatile @Nullable com.vaadin.flow.component.UI attachedUiThe attached UI, cached becausegetUI()must not be called from a background thread — and thinking statuses are normally published from one. Deliberatelytransient, unlikeThinkingStatusItem.owner: a cachedUIis worth nothing once a session is restored, since the push path needs a live one. The point is moot anyway, sinceapplicationContextis already non-transient and non-serializable, so this component tree cannot be passivated regardless. -
userActions
-
assistantActions
-
userActionsGeneration
protected int userActionsGeneration -
assistantActionsGeneration
protected int assistantActionsGeneration
-
-
Constructor Details
-
AiMessageList
public AiMessageList()Creates a new message list component. To populate the content of the list, usesetItems(Collection). -
AiMessageList
Creates a new message list component, with the provided items rendered as messages.- Parameters:
items- the items to render as messages- See Also:
-
AiMessageList
Creates a new message list component, with the provided items rendered as messages.- Parameters:
items- the items to render as messages- See Also:
-
-
Method Details
-
defaultThinkingStages
-
initComponent
protected void initComponent()Slots the default thinking indicator and registers the internal listeners. Called from the constructor. -
setItems
Sets the items that will be rendered as messages in this message list. An item instance may appear in the list only once: its incremental updates are routed to the list it was added to last, so sharing an instance between lists leaves the other list stale.- Parameters:
items- the items to set, notnull, not containing anynullitems and not containing the same item instance twice- Throws:
IllegalArgumentException- if the collection containsnullor duplicate items
-
setItems
Sets the items that will be rendered as messages in this message list.- Parameters:
items- the items to set, none of which can benull
-
addItem
Adds a single item to be rendered as a message at the end of this message list.- Parameters:
item- the item to add, notnulland not already present in this list- Throws:
IllegalArgumentException- if the item is already present in this list
-
getItems
Gets the items that are rendered as message components in this message list.- Returns:
- an unmodifiable view of the list of items
-
scheduleItemsTextUpdate
protected void scheduleItemsTextUpdate()Schedules an incremental update of the message list items' text content. -
scheduleAddItemsUpdate
protected void scheduleAddItemsUpdate()Schedules an incremental update to append newly added items to the client. -
scheduleItemsUpdate
protected void scheduleItemsUpdate()Schedules a full update of the message list items. -
scheduleUpdate
protected void scheduleUpdate()Schedules a client sync of the message list items to be run before the next client response. -
updateClient
protected void updateClient(com.vaadin.flow.component.UI ui) Updates the client with the current state of the message list items.- Parameters:
ui- the UI the component is attached to
-
handleFullUpdate
protected void handleFullUpdate(com.vaadin.flow.component.UI ui) Handles a full update of the message list items.- Parameters:
ui- the UI the component is attached to
-
handleTextUpdates
protected void handleTextUpdates()Handles incremental updates of the message list items' text content. This may involve appending text to existing text or replacing it entirely. -
handleAddItemsUpdate
protected void handleAddItemsUpdate(com.vaadin.flow.component.UI ui) Handles an incremental update that appends the newly added items to the client.- Parameters:
ui- the UI the component is attached to
-
onAttach
protected void onAttach(com.vaadin.flow.component.AttachEvent attachEvent) - Overrides:
onAttachin classcom.vaadin.flow.component.Component
-
onDetach
protected void onDetach(com.vaadin.flow.component.DetachEvent detachEvent) - Overrides:
onDetachin classcom.vaadin.flow.component.Component
-
localeChange
public void localeChange(com.vaadin.flow.i18n.LocaleChangeEvent event) - Specified by:
localeChangein interfacecom.vaadin.flow.i18n.LocaleChangeObserver
-
setApplicationContext
public void setApplicationContext(org.springframework.context.ApplicationContext applicationContext) throws org.springframework.beans.BeansException - Specified by:
setApplicationContextin interfaceorg.springframework.context.ApplicationContextAware- Throws:
org.springframework.beans.BeansException
-
afterPropertiesSet
public void afterPropertiesSet()- Specified by:
afterPropertiesSetin interfaceorg.springframework.beans.factory.InitializingBean
-
initI18n
protected void initI18n()Resolves the localization and the default thinking stages from the message bundle. Runs fromafterPropertiesSet(), after the application context is injected. -
setI18n
Sets the i18n strings (error message, retry label, scroll-to-bottom label, copied label, and the nested code-block labels). Updating the object after this call has no effect; call again to apply.The escalating thinking-stage labels are not part of this object: each is paired with a delay on a
ThinkingStagepassed tosetThinkingStages(List).- Parameters:
i18n- the i18n object, notnull
-
getI18n
- Returns:
- the current i18n object
-
setThinkingStages
Sets the escalating "thinking" stages: ordered (delay, label) pairs shown next to the thinking indicator while the active message is generating and still empty. The first stage's delay is the fast-response threshold (below it, only the indicator shows, with no label). A stage without text is skipped: it neither shows a label nor clears the one already showing. Replaces the defaults.- Parameters:
thinkingStages- the ordered thinking stages, notnull
-
getThinkingStages
- Returns:
- an unmodifiable view of the current thinking stages
-
getThinkingStatusPublisher
The thinking-status feed: the ordered account of what the assistant is doing, rendered above the thinking indicator while generating. Statuses are ephemeral — anAiChatclears the feed at the start and the end of every generation.- Returns:
- the feed, never
null
-
pushThinkingStatuses
protected void pushThinkingStatuses()Pushes the whole status feed to the client through the cached UI. With no UI attached the push is skipped — the model has already been updated, andonAttach(com.vaadin.flow.component.AttachEvent)re-pushes the accumulated feed when the component returns. A UI that detaches concurrently with this call, after the null check above, is treated the same way as none at all. -
setUserActions
Sets the actions shown under user messages. Actions are reusable: the sameAiMessageActioninstance may be passed here and tosetAssistantActions(List). Replaces any previous user actions.- Parameters:
actions- the user-message actions, notnull
-
addUserAction
Appends an action to the actions shown under user messages, keeping the ones already there — including any declared in a view descriptor, whichsetUserActions(List)would replace. Appending reuses the current key generation: already-rendered actions keep their keys, so a click in flight while the append happens still routes.- Parameters:
action- the action to append, notnull
-
getUserActions
- Returns:
- an unmodifiable view of the user-message actions
-
setAssistantActions
Sets the actions shown under assistant messages. Actions are reusable: the sameAiMessageActioninstance may be passed here and tosetUserActions(List). Replaces any previous assistant actions.- Parameters:
actions- the assistant-message actions, notnull
-
addAssistantAction
Appends an action to the actions shown under assistant messages, keeping the ones already there — including any declared in a view descriptor, whichsetAssistantActions(List)would replace. Appending reuses the current key generation: already-rendered actions keep their keys, so a click in flight while the append happens still routes.- Parameters:
action- the action to append, notnull
-
getAssistantActions
- Returns:
- an unmodifiable view of the assistant-message actions
-
pushUserActions
protected void pushUserActions()Serializes and pushes the user actions to the client under the current generation. Callers replacing the whole set bump the generation first; appends and re-pushes must not. -
pushAssistantActions
protected void pushAssistantActions()Serializes and pushes the assistant actions to the client under the current generation. Callers replacing the whole set bump the generation first; appends and re-pushes must not. -
serializeActions
protected tools.jackson.databind.node.ArrayNode serializeActions(List<AiMessageAction<?>> actions, String keyPrefix, int generation) Serializes the actions to their client wire format. Keys are qualified with the actions' generation ("<keyPrefix><generation>-<index>") soresolveAction(String)can reject keys minted for a replaced action set. Anulldescription is omitted (the client falls back to the key for the accessible name). The built-in copy action's description is taken from the list's i18n object, not the action, so it follows the message bundle's locale.- Parameters:
actions- the actions to serializekeyPrefix- the role prefix ("u"or"a")generation- the generation of this actions assignment- Returns:
- the serialized actions array
-
resolveAction
Resolves a serialized action key back to its action. Returnsnullfor malformed keys and for stale keys — ones minted for an action set that has been replaced while the click was in flight.- Parameters:
key- the client-sent action key, ornull- Returns:
- the resolved action, or
null
-
handleActionClick
Routes a client action click to the matching action, ignoring stale or invalid keys and out-of-range item indexes.- Parameters:
event- the client click event
-
setState
Sets the list-level generation state. This drives the thinking indicator, the error banner, and which message is treated as active.- Parameters:
state- the generation state, notnull
-
getState
- Returns:
- the current list-level generation state (never
null)
-
getActiveItem
The active (generating) message: the lastMessageRole.ASSISTANTitem while the list isGenerationState.GENERATING, otherwisenull.- Returns:
- the active item, or
null
-
findLastAssistantItem
- Returns:
- the last item with role
MessageRole.ASSISTANT, ornullif there is none. Ignores the list state.
-
findLastUserItem
- Returns:
- the last item with role
MessageRole.USER, ornullif there is none
-
addRetryListener
public com.vaadin.flow.shared.Registration addRetryListener(com.vaadin.flow.component.ComponentEventListener<AiMessageList.RetryEvent> listener) Adds a listener for the retry action of the error banner.- Parameters:
listener- the listener, notnull- Returns:
- a registration for removing the listener
-
addAttachmentClickListener
public com.vaadin.flow.shared.Registration addAttachmentClickListener(com.vaadin.flow.component.ComponentEventListener<AiMessageList.AttachmentClickEvent> listener) Adds a listener notified when the user clicks an attachment of a message.- Parameters:
listener- the listener to add- Returns:
- a handle that can be used to remove the listener
-
setThinkingIndicator
public void setThinkingIndicator(@Nullable com.vaadin.flow.component.Component indicator) Sets a custom thinking indicator, replacing the built-in animated dots. The component occupies the list'sthinking-indicatorslot (managed withSlotUtils, likeHasPrefix). The list shows or hides the whole thinking region (indicator + escalating label) based on its state, so a custom indicator keeps the label.- Parameters:
indicator- the indicator component, ornullto clear the slot (no indicator at all, removing the default too)
-
getThinkingIndicator
public @Nullable com.vaadin.flow.component.Component getThinkingIndicator()- Returns:
- the custom thinking indicator, or
nullwhen the built-in default element is in use (it has no Java wrapper) or the slot was cleared
-
getSubPart
Exposes the message actions and the custom thinking-indicator slot to the framework's id-based component walk. The list is not a container and the indicator lives in a managed slot, so without this an id declared on a customthinkingIndicatorcould not be injected with@ViewComponent. A message action id is answered first, which is what lets a controller subscribe to a declared action's performed event; the id is then resolved against the indicator and its descendants.- Specified by:
getSubPartin interfaceHasSubParts- Parameters:
name- the component id to find- Returns:
- the matching action, indicator component or descendant, or
nullif none matches
-
findMessageAction
Finds a message action by its id, searching the user actions and then the assistant actions. Declared ids are unique across both containers, so the order only matters for actions added programmatically.- Parameters:
id- the action id- Returns:
- the matching action, or an empty
Optional
-
findSlotSubPart
protected Optional<com.vaadin.flow.component.Component> findSlotSubPart(com.vaadin.flow.component.Component slotComponent, String name) Resolves an id against the slot component: the component itself when its own id matches, otherwise a descendant of it.- Parameters:
slotComponent- the slot component to searchname- the component id to find- Returns:
- the matching component, or an empty
Optional
-
setAnnounceMessages
public void setAnnounceMessages(boolean announceMessages) When set totrue, new messages are announced to assistive technologies using ARIA live regions. By default, this is set tofalse.- Parameters:
announceMessages-trueif new messages should be announced to assistive technologies.
-
isAnnounceMessages
public boolean isAnnounceMessages()Returns whether new messages are announced to assistive technologies.- Returns:
trueif new messages are announced to assistive technologies.
-