feat(editor): add @everyone mention support#572
Conversation
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
✅ Deploy Preview for fluxsocial-dev ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📝 WalkthroughWalkthroughThe changes add support for Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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
📒 Files selected for processing (2)
packages/flux-editor/src/flux-editor.tspackages/flux-editor/src/mention.ts
| // Protocol-level group mentions | ||
| const groupMentions: Suggestion[] = [ | ||
| { id: 'ad4m://everyone', label: 'everyone' }, | ||
| ].filter((m) => m.label.toLowerCase().startsWith(query.toLowerCase())); | ||
|
|
There was a problem hiding this comment.
🧩 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 -20Repository: 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 5Repository: 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 -iRepository: 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" -lRepository: 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 -50Repository: 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 -100Repository: 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 2Repository: 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 5Repository: 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 -20Repository: 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.tsRepository: 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 -50Repository: 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 -20Repository: coasys/flux
Length of output: 783
🏁 Script executed:
# Look for any validation of mention content
rg -n "ad4m://" packages/ -r -A 5 -B 5Repository: 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/nullRepository: 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 -80Repository: 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" -iRepository: 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 -iRepository: 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 3Repository: 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.
| const isMention = node.attrs.id.startsWith('did:') || node.attrs.id.startsWith('ad4m://'); | ||
| return `${isMention ? '@' : '#'}${node.attrs.label ?? node.attrs.id}`; |
There was a problem hiding this comment.
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.
| 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.
Summary
Adds
@everyoneas a protocol-level group mention in the chat editor.Changes
packages/flux-editor/src/flux-editor.tsad4m://everyoneto mention autocomplete suggestions@e...packages/flux-editor/src/mention.tsrenderLabelto recognizead4m://URIs as mentions (prefix with@not#)How It Works
@ein chat → "everyone" appears in autocomplete<a data-type="mention" href="ad4m://everyone" data-label="everyone">@everyone</a>ad4m://everyonein message bodies and wakes all subscribed agentsRelated
everyone-mentionchannelCloses #571
Summary by CodeRabbit
New Features
Bug Fixes
depends on d9011e34-8219-4ba1-bdd1-7d104a25cd1f/91215135-9143-46eb-8f5d-b38504a40392#770