Ping/mention collaborators inside a session (non-agent messages)#1788
Open
rusackas wants to merge 7 commits into
Open
Ping/mention collaborators inside a session (non-agent messages)#1788rusackas wants to merge 7 commits into
rusackas wants to merge 7 commits into
Conversation
New message type for human-to-human notes in the conversation stream (the ping/mention feature). Stores mentioned user IDs in metadata.mentions, mirroring BoardComment.mentions. No DB migration needed — the drizzle `enum` option on a text column is TS-level only.
New sibling route to /sessions/:id/prompt that writes a `mention`-type message via the existing messages service (same RBAC hooks as prompting) but never creates/queues a Task and never spawns the executor, so the ping structurally cannot reach the agent. Attaches to the session's host task (mirrors the widget_request pattern) so the transcript renderer picks it up. Also excludes 'mention' messages from the agent-facing agor_messages_list MCP tool, closing the one remaining path an agent could otherwise read pings back through.
Thin wrapper mirroring sessions.prompt(), calling POST /sessions/:id/ping.
Adds a secondary "Ping" button next to Send in the composer's action bar. Pings post a human-to-human note (never sent to the agent) and carry any @mentioned collaborators, tracked via a new onMentionSelect callback on AutocompleteTextarea (reusing the existing @-user autocomplete rather than inferring intent from a leading @, which would collide with the file/user/KB autocomplete trigger already overloaded on @). Wires client.sessions.ping() through onSendPing end-to-end: App.tsx -> components/App/App.tsx -> AppActionsContext -> SessionPanel -> SessionFooter. Also fixes a latent bug where user-mention insertText wasn't quoted for multi-word names (quoteIfNeeded was only applied to file paths), which would have broken mention tracking for names with spaces.
Adds a PingNote renderer for type === 'mention' messages: author avatar, "X pinged Y" header, and the note text — styled as a human-to-human comment rather than agent output. Author attribution needed a new metadata.author_user_id field since Message has no general created_by column (ordinary messages are attributed to the session's current viewer instead, which doesn't work for pings since any collaborator with access can post one).
- agor_messages_list: assert the 'mention' exclusion is applied even with includeToolCalls:true, proving it's unconditional (not just folded into the existing tool-call filter). - AutocompleteTextarea: assert multi-word user names are quoted on insert and onMentionSelect fires with the resolved userId.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a Slack-like "ping" — bring a collaborator's attention to something inside a session without prompting the agent. A ping is a human-to-human note: it shows up in the conversation stream and is visible to session viewers, but it never enters the agent's context and never triggers a run.
Design decision (why not the
@-prefix heuristic): the composer's@is already an overloaded autocomplete trigger for files/users/KB references whose results do go to the agent (e.g.@file.ts explain this). Inferring "this is a ping, not a prompt" from a leading@would collide with that and be fragile. Instead, intent is explicit via a distinct Ping button next to Send in the composer's action bar. It reuses the existing@-user autocomplete to pick who to mention.What's in scope
mentionMessageType(packages/core/src/types/message.ts), stored via the existing messages pipeline. Mentioned user ids + author live inmessage.metadata(mirrorsBoardComment.mentions). No DB migration needed — theenumoption on a text column is TS-level only (percontext/guides/creating-database-migrations.md).POST /sessions/:id/ping(apps/agor-daemon/src/register-routes.ts) — a sibling to/sessions/:id/promptthat writes the message via the same messages-service RBAC hooks, but never creates/queues a Task and never spawns the executor. Since none of the agent executors (Claude/Codex/Gemini/Copilot) read conversation context from Agor's message table — they resume from their own native session files — never creating a Task is sufficient to structurally guarantee a ping can't reach the agent.agor_messages_list(the agent-facing MCP tool), closing the one remaining path an agent could otherwise read a ping back through.SessionFooter, wired throughAppActionsContext→client.sessions.ping(). Tracks@mentionedusers via a newonMentionSelectcallback onAutocompleteTextarea(also fixes a latent bug where multi-word mention names weren't quoted).AutocompleteTextarea.Explicitly out of scope (follow-ups)
openDmByEmail/sendSlackMessage). Feasible, left for a fast-follow.Test plan
pnpm typecheckacross@agor/core,@agor/daemon,agor-ui,@agor-live/clientbiome checkclean on all changed filesagor_messages_listunconditionally excludesmentionmessages;AutocompleteTextareaquotes multi-word mentions and firesonMentionSelect🤖 Generated with Claude Code