Skip to content

feat(editor): add @everyone mention support#572

Open
data-bot-coasys wants to merge 1 commit intodevfrom
feat/everyone-mention
Open

feat(editor): add @everyone mention support#572
data-bot-coasys wants to merge 1 commit intodevfrom
feat/everyone-mention

Conversation

@data-bot-coasys
Copy link
Copy Markdown
Contributor

@data-bot-coasys data-bot-coasys commented Mar 22, 2026

Summary

Adds @everyone as a protocol-level group mention in the chat editor.

Changes

packages/flux-editor/src/flux-editor.ts

  • Added ad4m://everyone to mention autocomplete suggestions
  • Shows at the top of the suggestion list when typing @e...

packages/flux-editor/src/mention.ts

  • Updated renderLabel to recognize ad4m:// URIs as mentions (prefix with @ not #)

How It Works

  1. User types @e in chat → "everyone" appears in autocomplete
  2. Selecting it inserts: <a data-type="mention" href="ad4m://everyone" data-label="everyone">@everyone</a>
  3. The AD4M waker matches on ad4m://everyone in message bodies and wakes all subscribed agents

Related

Closes #571

Summary by CodeRabbit

  • New Features

    • Group mention suggestions now appear alongside member mentions in the editor, with results limited to the top 10 suggestions.
  • Bug Fixes

    • Improved mention rendering to correctly display different mention types with appropriate formatting for better clarity.

depends on d9011e34-8219-4ba1-bdd1-7d104a25cd1f/91215135-9143-46eb-8f5d-b38504a40392#770

Adds ad4m://everyone as a protocol-level group mention:
- Autocomplete shows 'everyone' option when typing @e...
- Uses ad4m://everyone URI (protocol-level, not app-specific)
- renderLabel correctly prefixes @ for ad4m:// URIs

Companion to coasys/ad4m#769
Closes #571
@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 22, 2026

Deploy Preview for fluxsocial-dev ready!

Name Link
🔨 Latest commit b1152cc
🔍 Latest deploy log https://app.netlify.com/projects/fluxsocial-dev/deploys/69c04f187046f90008d0fca4
😎 Deploy Preview https://deploy-preview-572--fluxsocial-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 22, 2026

📝 Walkthrough

Walkthrough

The changes add support for @everyone group mentions in the chat editor. The mention suggestions system now includes a special ad4m://everyone protocol mention that appears when users type "@everyone", and the rendering logic treats ad4m:// identifiers like DID identifiers, displaying them with the @ prefix.

Changes

Cohort / File(s) Summary
@everyone Mention Support
packages/flux-editor/src/flux-editor.ts, packages/flux-editor/src/mention.ts
Added ad4m://everyone as a group mention suggestion in autocomplete, and updated mention rendering to display ad4m:// identifiers with @ prefix (instead of #) alongside existing DID-based mentions.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A whisper on the breeze, ad4m://everyone to please,
With @ signs in sight, we mention all at once,
The rabbit hops with glee—group shouts, now unified! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(editor): add @everyone mention support' accurately and concisely summarizes the main change—adding @everyone mention functionality to the editor.
Linked Issues check ✅ Passed The PR implements all primary coding objectives from #571: adds @everyone autocomplete suggestion, renders it with @ prefix, uses ad4m://everyone URI, and integrates with notification system.
Out of Scope Changes check ✅ Passed All changes are directly scoped to @everyone mention support: getMentionSuggestions enhancement and renderLabel ad4m:// URI handling are both necessary for the feature.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/everyone-mention

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/flux-editor/src/flux-editor.ts`:
- Around line 303-307: The unconditional inclusion of the ad4m://everyone
suggestion in the groupMentions array must be gated by a permission/capability
check: modify the logic that builds groupMentions in flux-editor.ts (the
groupMentions variable) to only include { id: 'ad4m://everyone', label:
'everyone' } when the current user passes an explicit check (e.g.,
hasCapability('mention:everyone') or canMentionEveryone()) and fall back to an
empty set otherwise; additionally ensure the backend mention-processing path
(where the mention plugin validates ad4m:// prefixes) enforces the same
capability check when handling outgoing/received messages so unsupported
mentions are rejected server-side.

In `@packages/flux-editor/src/mention.ts`:
- Around line 21-22: Guard the access to node.attrs.id before calling startsWith
in the mention rendering logic: in the expression using isMention and the return
that builds the label (the snippet around node.attrs.id.startsWith(...) and
`${isMention ? '@' : '#'}${node.attrs.label ?? node.attrs.id}` in
packages/flux-editor/src/mention.ts), check that node.attrs.id is a non-empty
string (e.g. typeof node.attrs.id === 'string' && node.attrs.id.startsWith(...))
and fall back to treating it as not-a-mention when it is
null/undefined/non-string so rendering uses node.attrs.label or a safe fallback
instead of calling startsWith on null.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 01489baa-7f7e-4685-ba8f-791e79da28eb

📥 Commits

Reviewing files that changed from the base of the PR and between 0b44ab8 and b1152cc.

📒 Files selected for processing (2)
  • packages/flux-editor/src/flux-editor.ts
  • packages/flux-editor/src/mention.ts

Comment on lines +303 to +307
// Protocol-level group mentions
const groupMentions: Suggestion[] = [
{ id: 'ad4m://everyone', label: 'everyone' },
].filter((m) => m.label.toLowerCase().startsWith(query.toLowerCase()));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, verify the file exists and read the context around the mentioned lines
find . -type f -name "flux-editor.ts" | head -20

Repository: coasys/flux

Length of output: 96


🏁 Script executed:

# Read the relevant section of the file
cat -n packages/flux-editor/src/flux-editor.ts | sed -n '295,320p'

Repository: coasys/flux

Length of output: 1106


🏁 Script executed:

# Search for getMentionSuggestions method to understand the full context
rg -n "getMentionSuggestions" packages/flux-editor/src/flux-editor.ts -A 20 -B 5

Repository: coasys/flux

Length of output: 2920


🏁 Script executed:

# Search for any permission checks related to mentions or ad4m://everyone
rg -n "permission|capability|role|authorize" packages/flux-editor/src/flux-editor.ts -i

Repository: coasys/flux

Length of output: 37


🏁 Script executed:

# Check if there are backend implementations that enforce permissions for ad4m://everyone
find . -type f \( -name "*.ts" -o -name "*.js" \) | xargs rg "ad4m://everyone" -l

Repository: coasys/flux

Length of output: 98


🏁 Script executed:

# Search for mention processing or validation in the codebase
rg -n "mention" packages/flux-editor/src/ -i --type ts -A 3 | head -50

Repository: coasys/flux

Length of output: 3396


🏁 Script executed:

# Check the full flux-editor.ts class definition to see what properties exist
cat -n packages/flux-editor/src/flux-editor.ts | head -150 | tail -100

Repository: coasys/flux

Length of output: 2573


🏁 Script executed:

# Search for message sending or dispatch logic
rg -n "send|dispatch|message" packages/flux-editor/src/flux-editor.ts -i -A 2

Repository: coasys/flux

Length of output: 665


🏁 Script executed:

# Look for where mentions are actually processed when sending
find . -type f \( -name "*.ts" -o -name "*.js" \) -path "*/packages/*" | xargs rg "ad4m://everyone" -B 5 -A 5

Repository: coasys/flux

Length of output: 984


🏁 Script executed:

# Check if there's any reference to permissions or roles in the codebase
find . -type f \( -name "*.ts" -o -name "*.js" \) -path "*/packages/*" | xargs rg "everyone|permission|role" -i -l | head -20

Repository: coasys/flux

Length of output: 464


🏁 Script executed:

# Look at the full mention.ts to understand the complete flow
cat -n packages/flux-editor/src/mention.ts

Repository: coasys/flux

Length of output: 5138


🏁 Script executed:

# Find Message class and create method
find . -type f \( -name "*.ts" -o -name "*.js" \) -path "*/packages/*" | xargs rg "class Message|export.*Message" -A 5 | head -50

Repository: coasys/flux

Length of output: 3684


🏁 Script executed:

# Search for Message.create specifically
find . -type f \( -name "*.ts" -o -name "*.js" \) -path "*/packages/*" | xargs rg "create\(" -B 3 -A 10 | grep -A 10 "Message.create"

Repository: coasys/flux

Length of output: 912


🏁 Script executed:

# Check the api package for Message handling
find packages/api -type f -name "*.ts" | head -20

Repository: coasys/flux

Length of output: 783


🏁 Script executed:

# Look for any validation of mention content
rg -n "ad4m://" packages/ -r -A 5 -B 5

Repository: coasys/flux

Length of output: 18215


🏁 Script executed:

# Check if there's any role/permission based logic for messages
find . -type f \( -name "*.ts" -o -name "*.js" \) -path "*/packages/api*" | xargs rg -l "permission|role|authorize" 2>/dev/null

Repository: coasys/flux

Length of output: 105


🏁 Script executed:

# Get the exact content around line 305 to confirm
cat -n packages/flux-editor/src/flux-editor.ts | sed -n '303,307p'

Repository: coasys/flux

Length of output: 297


🏁 Script executed:

# Also check the mention.ts file to see what IDs it recognizes
cat -n packages/flux-editor/src/mention.ts | sed -n '20,23p'

Repository: coasys/flux

Length of output: 299


🏁 Script executed:

# Check the Message class implementation for any validation
cat -n packages/api/src/message/index.ts | head -80

Repository: coasys/flux

Length of output: 1443


🏁 Script executed:

# Search for where mentions are parsed or processed from body
rg -n "body|mention" packages/api/src/ -i -B 2 -A 2 | grep -A 3 -B 3 "everyone\|ad4m://"

Repository: coasys/flux

Length of output: 37


🏁 Script executed:

# Check if there's any mention processing or notification logic
find packages/api -type f -name "*.ts" | xargs rg -l "notification\|broadcast\|mention" -i

Repository: coasys/flux

Length of output: 39


🏁 Script executed:

# Look for any permission enforcement on message creation or sending
rg -n "permission\|capability\|authorize\|admin\|role" packages/api/src/message -i

Repository: coasys/flux

Length of output: 37


🏁 Script executed:

# Check what properties the flux-editor component has
cat -n packages/flux-editor/src/flux-editor.ts | sed -n '110,150p'

Repository: coasys/flux

Length of output: 986


🏁 Script executed:

# Check how messages flow from the editor to the perspective
rg -n "perspective.add\|Message.create" packages/flux-editor/src/flux-editor.ts -B 3 -A 3

Repository: coasys/flux

Length of output: 37


Gate @everyone suggestion behind an explicit permission/capability check in the editor.

Lines 303–307 expose ad4m://everyone to all users unconditionally in the suggestion list. The mention plugin accepts any mention with the ad4m:// prefix without validation. Ensure this capability is restricted based on user permissions—at minimum in the backend when processing messages, and preferably also in the UI suggestion layer to prevent users from attempting unsupported mentions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/flux-editor/src/flux-editor.ts` around lines 303 - 307, The
unconditional inclusion of the ad4m://everyone suggestion in the groupMentions
array must be gated by a permission/capability check: modify the logic that
builds groupMentions in flux-editor.ts (the groupMentions variable) to only
include { id: 'ad4m://everyone', label: 'everyone' } when the current user
passes an explicit check (e.g., hasCapability('mention:everyone') or
canMentionEveryone()) and fall back to an empty set otherwise; additionally
ensure the backend mention-processing path (where the mention plugin validates
ad4m:// prefixes) enforces the same capability check when handling
outgoing/received messages so unsupported mentions are rejected server-side.

Comment on lines +21 to 22
const isMention = node.attrs.id.startsWith('did:') || node.attrs.id.startsWith('ad4m://');
return `${isMention ? '@' : '#'}${node.attrs.label ?? node.attrs.id}`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Guard node.attrs.id before calling startsWith to avoid render-time crashes.

Line 21 assumes node.attrs.id is always a string, but id defaults to null (Line 72). A malformed/pasted mention node can throw here and break rendering.

Proposed fix
       renderLabel({ node }) {
-        const isMention = node.attrs.id.startsWith('did:') || node.attrs.id.startsWith('ad4m://');
-        return `${isMention ? '@' : '#'}${node.attrs.label ?? node.attrs.id}`;
+        const id = typeof node.attrs.id === 'string' ? node.attrs.id : '';
+        const isMention = id.startsWith('did:') || id.startsWith('ad4m://');
+        return `${isMention ? '@' : '#'}${node.attrs.label ?? id}`;
       },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const isMention = node.attrs.id.startsWith('did:') || node.attrs.id.startsWith('ad4m://');
return `${isMention ? '@' : '#'}${node.attrs.label ?? node.attrs.id}`;
const id = typeof node.attrs.id === 'string' ? node.attrs.id : '';
const isMention = id.startsWith('did:') || id.startsWith('ad4m://');
return `${isMention ? '@' : '#'}${node.attrs.label ?? id}`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/flux-editor/src/mention.ts` around lines 21 - 22, Guard the access
to node.attrs.id before calling startsWith in the mention rendering logic: in
the expression using isMention and the return that builds the label (the snippet
around node.attrs.id.startsWith(...) and `${isMention ? '@' :
'#'}${node.attrs.label ?? node.attrs.id}` in
packages/flux-editor/src/mention.ts), check that node.attrs.id is a non-empty
string (e.g. typeof node.attrs.id === 'string' && node.attrs.id.startsWith(...))
and fall back to treating it as not-a-mention when it is
null/undefined/non-string so rendering uses node.attrs.label or a safe fallback
instead of calling startsWith on null.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Add @everyone mention support in chat

1 participant