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:
  • Field Details

    • CONNECTOR_OBJECT

      protected static final String CONNECTOR_OBJECT
      See Also:
    • THINKING_INDICATOR_SLOT

      protected static final String 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

      protected AiMessageListI18n i18n
    • items

      protected List<AiMessageListItem> items
    • pendingUpdate

      protected boolean pendingUpdate
    • pendingTextUpdate

      protected boolean pendingTextUpdate
    • pendingAddItemsIndex

      protected @Nullable Integer pendingAddItemsIndex
    • state

      protected GenerationState state
    • thinkingStages

      protected List<ThinkingStage> thinkingStages
    • thinkingStatusPublisher

      protected ThinkingStatusPublisher thinkingStatusPublisher
    • attachedUi

      protected transient volatile @Nullable com.vaadin.flow.component.UI attachedUi
      The attached UI, cached because getUI() must not be called from a background thread — and thinking statuses are normally published from one. Deliberately transient, unlike ThinkingStatusItem.owner: a cached UI is worth nothing once a session is restored, since the push path needs a live one. The point is moot anyway, since applicationContext is already non-transient and non-serializable, so this component tree cannot be passivated regardless.
    • userActions

      protected List<AiMessageAction<?>> userActions
    • assistantActions

      protected List<AiMessageAction<?>> 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, use setItems(Collection).
    • AiMessageList

      public AiMessageList(Collection<AiMessageListItem> items)
      Creates a new message list component, with the provided items rendered as messages.
      Parameters:
      items - the items to render as messages
      See Also:
    • AiMessageList

      public AiMessageList(AiMessageListItem... items)
      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

      protected static List<ThinkingStage> defaultThinkingStages()
    • initComponent

      protected void initComponent()
      Slots the default thinking indicator and registers the internal listeners. Called from the constructor.
    • setItems

      public void setItems(Collection<AiMessageListItem> items)
      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, not null, not containing any null items and not containing the same item instance twice
      Throws:
      IllegalArgumentException - if the collection contains null or duplicate items
    • setItems

      public void setItems(AiMessageListItem... items)
      Sets the items that will be rendered as messages in this message list.
      Parameters:
      items - the items to set, none of which can be null
    • addItem

      public void addItem(AiMessageListItem item)
      Adds a single item to be rendered as a message at the end of this message list.
      Parameters:
      item - the item to add, not null and not already present in this list
      Throws:
      IllegalArgumentException - if the item is already present in this list
    • getItems

      public List<AiMessageListItem> 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:
      onAttach in class com.vaadin.flow.component.Component
    • onDetach

      protected void onDetach(com.vaadin.flow.component.DetachEvent detachEvent)
      Overrides:
      onDetach in class com.vaadin.flow.component.Component
    • localeChange

      public void localeChange(com.vaadin.flow.i18n.LocaleChangeEvent event)
      Specified by:
      localeChange in interface com.vaadin.flow.i18n.LocaleChangeObserver
    • setApplicationContext

      public void setApplicationContext(org.springframework.context.ApplicationContext applicationContext) throws org.springframework.beans.BeansException
      Specified by:
      setApplicationContext in interface org.springframework.context.ApplicationContextAware
      Throws:
      org.springframework.beans.BeansException
    • afterPropertiesSet

      public void afterPropertiesSet()
      Specified by:
      afterPropertiesSet in interface org.springframework.beans.factory.InitializingBean
    • initI18n

      protected void initI18n()
      Resolves the localization and the default thinking stages from the message bundle. Runs from afterPropertiesSet(), after the application context is injected.
    • setI18n

      public void setI18n(AiMessageListI18n i18n)
      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 ThinkingStage passed to setThinkingStages(List).

      Parameters:
      i18n - the i18n object, not null
    • getI18n

      public AiMessageListI18n getI18n()
      Returns:
      the current i18n object
    • setThinkingStages

      public void setThinkingStages(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. 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, not null
    • getThinkingStages

      public List<ThinkingStage> getThinkingStages()
      Returns:
      an unmodifiable view of the current thinking stages
    • getThinkingStatusPublisher

      public ThinkingStatusPublisher getThinkingStatusPublisher()
      The thinking-status feed: the ordered account of what the assistant is doing, rendered above the thinking indicator while generating. Statuses are ephemeral — an AiChat clears 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, and onAttach(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

      public void setUserActions(List<? extends AiMessageAction<?>> actions)
      Sets the actions shown under user messages. Actions are reusable: the same AiMessageAction instance may be passed here and to setAssistantActions(List). Replaces any previous user actions.
      Parameters:
      actions - the user-message actions, not null
    • addUserAction

      public void addUserAction(AiMessageAction<?> action)
      Appends an action to the actions shown under user messages, keeping the ones already there — including any declared in a view descriptor, which setUserActions(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, not null
    • getUserActions

      public List<AiMessageAction<?>> getUserActions()
      Returns:
      an unmodifiable view of the user-message actions
    • setAssistantActions

      public void setAssistantActions(List<? extends AiMessageAction<?>> actions)
      Sets the actions shown under assistant messages. Actions are reusable: the same AiMessageAction instance may be passed here and to setUserActions(List). Replaces any previous assistant actions.
      Parameters:
      actions - the assistant-message actions, not null
    • addAssistantAction

      public void addAssistantAction(AiMessageAction<?> action)
      Appends an action to the actions shown under assistant messages, keeping the ones already there — including any declared in a view descriptor, which setAssistantActions(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, not null
    • getAssistantActions

      public List<AiMessageAction<?>> 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>") so resolveAction(String) can reject keys minted for a replaced action set. A null description 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 serialize
      keyPrefix - the role prefix ("u" or "a")
      generation - the generation of this actions assignment
      Returns:
      the serialized actions array
    • resolveAction

      protected @Nullable AiMessageAction<?> resolveAction(@Nullable String key)
      Resolves a serialized action key back to its action. Returns null for 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, or null
      Returns:
      the resolved action, or null
    • handleActionClick

      protected void handleActionClick(AiMessageList.ActionClickEvent event)
      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

      public void setState(GenerationState state)
      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, not null
    • getState

      public GenerationState getState()
      Returns:
      the current list-level generation state (never null)
    • getActiveItem

      public @Nullable AiMessageListItem getActiveItem()
      The active (generating) message: the last MessageRole.ASSISTANT item while the list is GenerationState.GENERATING, otherwise null.
      Returns:
      the active item, or null
    • findLastAssistantItem

      protected @Nullable AiMessageListItem findLastAssistantItem()
      Returns:
      the last item with role MessageRole.ASSISTANT, or null if there is none. Ignores the list state.
    • findLastUserItem

      protected @Nullable AiMessageListItem findLastUserItem()
      Returns:
      the last item with role MessageRole.USER, or null if 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, not null
      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's thinking-indicator slot (managed with SlotUtils, like HasPrefix). 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, or null to 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 null when the built-in default element is in use (it has no Java wrapper) or the slot was cleared
    • getSubPart

      public @Nullable Object getSubPart(String name)
      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 custom thinkingIndicator could 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:
      getSubPart in interface HasSubParts
      Parameters:
      name - the component id to find
      Returns:
      the matching action, indicator component or descendant, or null if none matches
    • findMessageAction

      protected Optional<AiMessageAction<?>> findMessageAction(String id)
      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 search
      name - the component id to find
      Returns:
      the matching component, or an empty Optional
    • setAnnounceMessages

      public void setAnnounceMessages(boolean announceMessages)
      When set to true, new messages are announced to assistive technologies using ARIA live regions. By default, this is set to false.
      Parameters:
      announceMessages - true if new messages should be announced to assistive technologies.
    • isAnnounceMessages

      public boolean isAnnounceMessages()
      Returns whether new messages are announced to assistive technologies.
      Returns:
      true if new messages are announced to assistive technologies.