Skip to content

Conversation

@Abigayle-Mercer
Copy link

@Abigayle-Mercer Abigayle-Mercer commented Oct 30, 2025

This patch extends the mention detection functionality from add_message (added in PR #235) to update_message, enabling automatic @mention detection when messages are updated. This is particularly useful for
streaming scenarios where message content is built incrementally, allowing personas to mention each other while streaming.

Changes:

  • Extracted mention detection logic into reusable find_mentions() function in utils.py
  • Updated add_message to accept trigger_actions parameter (defaults to [find_mentions_callback]) to maintain expected behavior
  • Added trigger_actions parameter to update_message for flexible callback execution
  • Added three test cases covering mention updates, append with mentions, and deduplication
  • Updated docstrings to document the trigger_actions parameter

Streaming Support:

The new trigger_actions parameter provides flexible control over when mention extraction and notifications occur:

  • During streaming: update_message(chunk, append=True, trigger_actions=None) - defers mention extraction
  • When complete: update_message(message, trigger_actions=[find_mentions_callback]) - triggers mention extraction and persona notifications

This callback-based approach ensures personas are only notified once when the complete message is ready, rather than on every incremental update. The find_mentions implementation ensures no duplicate
mentions are added when messages are updated multiple times, making it safe for streaming use cases.

Extensibility:

The trigger_actions parameter accepts a list of callbacks, allowing consumers to register custom actions beyond mention detection. Each callback receives (message, chat) arguments and can inspect or modify
message state before the update is committed.

Integration:

This PR enables a forthcoming jupyter-ai-contrib/jupyter-ai-persona-manager#11 to stream_message() in BasePersona (jupyter-ai-persona-manager) that will leverage the trigger_actions
parameter to properly handle @mentions in streaming responses. The companion PR will add a final update_message(..., trigger_actions=[find_mentions_callback]) call after streaming completes, ensuring
mentioned personas are notified only when the full message is available.

@github-actions
Copy link
Contributor

Binder 👈 Launch a Binder on branch Abigayle-Mercer/jupyter-chat/add-mention-detection-update-message

@Abigayle-Mercer Abigayle-Mercer marked this pull request as ready for review October 31, 2025 16:59
@Zsailer Zsailer added the enhancement New feature or request label Oct 31, 2025
@Zsailer Zsailer requested review from brichet and dlqqq and removed request for dlqqq October 31, 2025 17:58
@Zsailer
Copy link
Member

Zsailer commented Nov 1, 2025

Looks great @Abigayle-Mercer! Just left a minor comment about the argument name.

  This patch extends the mention detection functionality from add_message
  (added in PR jupyterlab#235) to update_message. This enables automatic @mention
  detection when messages are updated, which is particularly useful for
  streaming scenarios where message content is built incrementally.

  Changes:
  - Refactored mention detection logic into reusable _extract_mentions() helper method
  - Updated add_message to use the new helper method
  - Added mention detection to update_message that scans the complete message body
  - Added three test cases covering mention updates, append with mentions, and deduplication
  - Fixed regex pattern to use raw string to avoid SyntaxWarning

  The implementation ensures no duplicate mentions are added when the same
  message is updated multiple times, making it safe for streaming use cases.
Copy link
Collaborator

@brichet brichet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Abigayle-Mercer for working on this.
I have some comments below.

updated_msg = chat.get_message(msg_id)
assert updated_msg
# Should only have one mention despite appearing twice
assert set(updated_msg.mentions) == set([USER2.username])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK the set function returns unique elements, which would no prove that USER2 is not mentioned several times.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thank you!

return uid

def update_message(self, message: Message, append: bool = False):
def update_message(self, message: Message, append: bool = False, find_mentions: bool = False):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC the expectation is to find the mentions for the last update of a streaming message.
Maybe in future we'd like to trigger other actions on the last update. I wonder if we should rename this parameter last_update or something similar to be more generic.
I also wonder if the default value should be True, to trigger the find_mentions by default when this is not a streaming message.

Suggested change
def update_message(self, message: Message, append: bool = False, find_mentions: bool = False):
def update_message(self, message: Message, append: bool = False, last_update: bool = True):

What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized that it has been discussed and updated in another comment, with the opposite argument 😄

I still think that the default could be True, though, but don't have a strong opinion on it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😆 I think you make a great point though, @brichet.

Maybe this should be more generic... like trigger_actions—where actions are a set of callbacks that get triggered when the message is updated. Right now, we can just hardcode a single action, finding mentions. This would allows us to expand that API to include other actions without changing this method signature.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think that the default could be True

I wrestled with this a bit too. I think it should be False. The simple argument, is that keeps backwards compatibility. Right now, streaming doesn't ever parse the mentions, so this won't introduce unexpected behavior.

But the deeper reason is that if the developer is not explicit when using this API, it has the potential to trigger a bunch of actions repeatedly, unintendedly. While it's a bit more verbose in the downstream code, I think it's best to force folks to be explicit when triggering actions.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Zsailer Are you suggesting something like this for now?

def update_message(self, message: Message, append: bool = False, trigger_actions: set[str] | None = None):
      # Then inside:
      if trigger_actions and 'mentions' in trigger_actions:
          message.mentions = self._find_mentions(message.body)

And then down the road make trigger_actions be flexible callbacks?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Abigayle-Mercer your suggestion sounds good to me, for full flexibility in the long run.
Perhaps trigger_actions could be a list rather than a set, converting it to a set at the beginning of the function in order to remove duplicate entries.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the approach you took in the latest updates!

I don't think the set action is needed. I can imagine cases where people might actually pass a trigger that they want to happen twice... Let's leave it as a list like @brichet suggested.

@Abigayle-Mercer Abigayle-Mercer force-pushed the add-mention-detection-update-message branch from edc43a8 to f6440ea Compare November 11, 2025 20:53
@Zsailer
Copy link
Member

Zsailer commented Dec 3, 2025

This looks great @Abigayle-Mercer!

I like how you split out the find_mentions into a separate modules. This can be a place where we start dropping a other message utilities that act on the message.

Minor nitpick about the function name. Otherwise this LGTM! I can merge once you update.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants