Repository navigation
fix(relay): p-tag a one-to-one DM's agent partner on new messages - #2475
rileycrane wants to merge 3 commits into
Conversation
A hosted agent is woken only by a `p` tag naming it, but the desktop app tagged only explicit @mentions, so a plain DM to a hosted agent woke nothing. Add a `p` tag for the other member of a 1:1 DM when its profile is an agent, on new messages and thread replies. Human partners are never tagged (a `p` tag would bypass their mute); edits, reactions and group DMs are unchanged. Co-authored-by: Opus 5.5 Max <d9fc2aa400ad81a2f289921a1720811e5d922c43e079f37241d4be458d8d92aa@buzz.block.builderlab.xyz> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Riley Crane <rileycrane@squareup.com>
New Message reads people outside the shared profile cache, and opening a DM confirmed membership only. A first plain message to a hosted agent therefore had no `p` tag and did not wake it. `directMessages.open` now ensures the partner's profile for a one-to-one DM before it returns, so `send` can classify the partner. A failed read still opens the DM. Adds a session-level open → first-send regression for agent and human partners, and makes the test relay filter discovery by kind. Co-authored-by: Opus 5.5 Max <d9fc2aa400ad81a2f289921a1720811e5d922c43e079f37241d4be458d8d92aa@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Riley Crane <rileycrane@squareup.com>
e79f5ab to
aba44f5
Compare
kazemek21
left a comment
There was a problem hiding this comment.
I reviewed the PR and went through the Nexus review-tracker notes. Approving with the non-blocking reconnect comment below.
Posted by Codex (gpt-6.1-sol) on behalf of kylez
| tags: [ | ||
| ["h", channelId], | ||
| ...mentionTags(channelId, mentions), | ||
| ...mentionTags(channelId, withDmAgents(channelId, mentions)), |
There was a problem hiding this comment.
[P2] Preserve plain DM queueing while the live stream reconnects
When an established two-member DM has a cached agent profile and its live stream is reconnecting, this implicit recipient reaches validateMentions, which throws because liveSnapshot.status is not connected. A plain send/reply previously passed an empty mention list and entered the durable outbox; now it fails before enqueueing with a mention-specific error even though the user added no mention. Could we preserve durable enqueueing for this implicit recipient while retaining fresh membership validation before publication? A session-level reconnect regression case would cover the distinction.
Posted by Codex (gpt-6.1-sol) on behalf of kylez
There was a problem hiding this comment.
🤖 Good catch, thanks. Fixed in 474f80d. A one-to-one DM's partner is now exempt from only the "connected live stream" precondition in validateMentions, so a plain message to an agent goes into the outbox while the stream reconnects. The cached roster must still list the partner, and publication still runs the strong roster read in preflightMentions, so a partner who has left is refused before dispatch. Mentions of anyone else still need a connected stream. New session-level cases in mentions.test.ts cover the reconnect queueing (which fails without the fix), the refusal of a partner who has left, and the unchanged check for other recipients.
…onnects A one-to-one DM's agent partner is now p-tagged on every new message, so the "connected live stream" check for mentions also blocked a plain message from entering the outbox while the stream reconnected. Exempt only the DM partner from that precondition: the cached roster must still list them, and publication still reads the roster fresh and refuses a partner who has left. Co-authored-by: Opus 5.5 Max <d9fc2aa400ad81a2f289921a1720811e5d922c43e079f37241d4be458d8d92aa@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Riley Crane <rileycrane@squareup.com>
Summary
A hosted agent (one that a provider runs, not this device) wakes only for a message whose
ptag names it. The desktop app addedptags only for explicit @mentions, so a plain desktop DM to a hosted agent never woke it. The mobile app already tags a DM's partner.This PR adds
["p", <agent>]to new messages and thread replies in a one-to-one DM whose other member is an agent.unmentionedRecipients(channelId).isAgentsignal: an owner attestation (authtag) or a declared agent flag.mentionTags. Deduplication with explicit mentions, the 32-recipient cap andvalidateMentionsall still apply.ptag counts as a mention, so a person would be notified when they don't expect it.directMessages.opennow loads a one-to-one partner's profile before it returns. Without this, the first message sent from New Message had no tag: the New Message picker reads people outside the shared profile cache, and opening the DM confirmed membership only. If the profile read fails, the DM still opens and that message is sent without the tag, as before this PR.Related: #2478 adds the Bestie tab for hosted agents.
Notes for review
Testing
messages-dm-agent.test.ts(new): an agent partner is tagged on send and on reply. A human partner is not tagged. An explicit mention is not tagged twice. Group DMs and channels are unchanged. The cap still applies.mentions.test.ts: on a real session with the live stream reconnecting, a plain DM message to an agent is queued and published with the tag, a message to a partner who has left is refused before publishing, and a mention of anyone else still requires a connected stream. The first case fails without the fix.direct-messages.test.ts: starts with an empty profile cache, then runsopen→ firstsendon a real session. An agent partner gets the tag and a human partner doesn't.vitest run: all pass exceptbrowser-host/media-preparation.integration.test.mjs(tiled HEIC dimensions, local ffmpeg). It fails without this change too.typecheckandlintare clean.🤖 Generated with Claude Code