Skip to content

Ping/mention collaborators inside a session (non-agent messages)#1788

Open
rusackas wants to merge 7 commits into
mainfrom
session-ping-collaborators
Open

Ping/mention collaborators inside a session (non-agent messages)#1788
rusackas wants to merge 7 commits into
mainfrom
session-ping-collaborators

Conversation

@rusackas

@rusackas rusackas commented Jul 2, 2026

Copy link
Copy Markdown
Member

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

  • New mention MessageType (packages/core/src/types/message.ts), stored via the existing messages pipeline. Mentioned user ids + author live in message.metadata (mirrors BoardComment.mentions). No DB migration needed — the enum option on a text column is TS-level only (per context/guides/creating-database-migrations.md).
  • POST /sessions/:id/ping (apps/agor-daemon/src/register-routes.ts) — a sibling to /sessions/:id/prompt that 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.
  • Excluded from agor_messages_list (the agent-facing MCP tool), closing the one remaining path an agent could otherwise read a ping back through.
  • Composer UI: a "Ping" button in SessionFooter, wired through AppActionsContextclient.sessions.ping(). Tracks @mentioned users via a new onMentionSelect callback on AutocompleteTextarea (also fixes a latent bug where multi-word mention names weren't quoted).
  • Distinct rendering: pings render as a comment-styled note (author + mentioned collaborators + text), not as agent output.
  • Tests: MCP tool exclusion is unconditional, mention quoting/callback behavior in AutocompleteTextarea.

Explicitly out of scope (follow-ups)

  • Slack DM on mention via the gateway (mention → look up email → openDmByEmail/sendSlackMessage). Feasible, left for a fast-follow.
  • Cross-session notification center / unread badges. For this PR, the ping simply appears live in the session view (same Socket.io/Feathers event path as any other message) — no new notification infrastructure.
  • Editing/deleting pings.

Test plan

  • pnpm typecheck across @agor/core, @agor/daemon, agor-ui, @agor-live/client
  • biome check clean on all changed files
  • Existing daemon/UI test suites for touched files pass (register-hooks, widgets/submissions, messages MCP tool, SessionPanel send, SessionFooter, AutocompleteTextarea)
  • New tests: agor_messages_list unconditionally excludes mention messages; AutocompleteTextarea quotes multi-word mentions and fires onMentionSelect
  • Manual smoke test in a running dev environment (not run in this session)

🤖 Generated with Claude Code

rusackas added 7 commits July 2, 2026 21:56
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.
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.

1 participant