Repository navigation
Invite between existing friends: red 'You're already friends. Their Bot is back in your list.' when nothing changed; Remove this Bot doesn't say what stays shared #496
Description
Summary
Between friends who are already connected, the invite flow and Remove this Bot say the wrong thing:
- Accepting an invite for a Bot I already have shows red error text
You're already friends. Their Bot is back in your list.Nothing came back, because the Bot never left my list, and nothing failed. - After Remove this Bot, the remover's own People with access also looked empty, which made it seem the reverse share was revoked too. I checked the API: Bot Social did not revoke it. The empty list is People with access hides live shares once two friends have joined each other's invite: owner can't see or Revoke them (side effect of #383 fix) #495 (People with access hides live shares), and the Remove confirm does not say what stays shared.
- The only way to share a Bot with someone who is already a friend is to make a new invite link and have them paste it.
Environment
- FlyBot main
a7adfe0882d3e37c81616871e24b442bd4a5047f, core + plugins/social + plugins/tree on@deepseek-ai/dsh@0.2.0-rc.2, Node 24.21.0. - Two fresh installs on one Linux box: A
:3090(owner SelfA1233,@selfa1233.home, one Bot: Chief =@chief.selfa1233.home) and B:3091(owner SelfB1233,@selfb1233.home, one Bot: Chief =@chief.selfb1233.home). Bot Social prodhttps://47-80-69-220.sslip.io. Both Chiefs onark/deepseek-v4-flash. - Product self-test 2026-10-20, focus C (Invites and grants), browser run 12:37–12:42 Asia/Shanghai, API checks about 12:45 Asia/Shanghai. Screenshots stayed on the test machine; what they show is written out below.
Reproduction
Setup as in #495, steps 1–2: A shared Chief with B, then B shared Chief with A. Both are in relationship rel_01M5BSN98FSFWGS9V9MMRRF3AE.
- On A, open B's Bot (
Chief SelfB1233) settings > Remove this Bot. The confirm readsRemove Chief? SelfB1233 can share it again.Click Remove.- B's Chief leaves A's list. This part is correct.
- A's own Chief > Sharing > People with access shows
Nobody has this Bot yet., but B still has A's Chief in its list.
- On A, make a new Chief invite (Add friend > Copy invite link for Chief). On B, Add friend, paste, Accept invite.
- B shows
You're already friends. Their Bot is back in your list.in red error styling. B never lost A's Chief. - A's People with access still says
Nobody has this Bot yet.after a reload.
- B shows
Screenshot (B, after step 2): The Add friend panel is open in the sidebar. The paste box shows a clipped https://47-80-69-220.sslip.io/i/…, followed by Accept invite, Copy invite link for Chief, and then red text You're already friends. Their Bot is back in your list. with Done below it. B's sidebar still has Chief SelfA1233 (preview hi from B), and the chat header reads Chief (SelfA1233).
Verification (about 12:45 Asia/Shanghai)
- After step 1, B
social/remote-bots {fresh:true}still lists A's Chief withgrantId grt_01M5BSN98G852C68465C8807C1. A's share to B was not revoked by Remove. Bot SocialdeclineBotGrantonly declines the grantor's bundle to the grantee (B → A's Chief). A's People with access looks empty only because of People with access hides live shares once two friends have joined each other's invite: owner can't see or Revoke them (side effect of #383 fix) #495. - A
social/remote-botslists no Bots and A's state marks B's Chiefgone: true. The decline took effect. - Step 2 changed nothing on Bot Social. A already had a live full grant to B's Chief in that relationship, so
joinInviteanswers409 relationship_exists. Only a missing or reply-only inviter grant goes toregrantViaInvite. FlyBot maps everyrelationship_existsto the same string (plugins/social/src/social.jsaround line 310,plugins/social/client.jsline 30). This happens whether or not anything was unhidden. - Hunch (not verified):
declineBotGranttakes every active grant from B to A's Chief in the relationship, including the reply-only rows B's first join created (CI: cache npm, manual runs, Windows/flaky test fixes; auto-approve sync #23). If so, after step 1 A's Chief may no longer be able to answer B's Chief, while B can still message it. Check: after step 1, B messages A's Chief, A approves the reply, then see whether it reaches B. If it does not, that part belongs in Birfy/bot-social (keep reply-only rows on decline).
Expected (per-Bot grants, simple, consistent)
- Accepting an invite for a Bot I already have shows neutral styling (not error red) and true wording:
You already have SelfA1233 · Chief.. Use… is back in your list.only when a locally hidden or declined Bot was really restored. - Remove only drops that one friend's Bot from my list. Bot Social already does this. The confirm says it in one line, for example
Remove SelfB1233 · Chief from your list? Your own Bots stay shared as they are. SelfB1233 can share it again. - Both homes stay consistent: after Remove, my People with access still lists the friend for my Bots they still have (depends on People with access hides live shares once two friends have joined each other's invite: owner can't see or Revoke them (side effect of #383 fix) #495).
Design question for the owner (do not guess)
Should Sharing offer Share with a friend (pick a person I'm already friends with, one click, no link), next to Invite to this Bot? Today the only way is a new link the friend must paste. Bot Social's regrant path (regrantViaInvite) already covers the server side for an inviter whose grant was removed. If the answer is no, only the wording parts apply.
Suggested scope
plugins/social/src/social.jsjoin-invitehandler: onrelationship_exists, return a structured result (alreadyHave: true,restored: <handles unhidden>) instead of throwing a generic error.plugins/social/client.jsrenders it as info, or as success when something was restored.plugins/social/client.jsRemove confirm text (around line 1976): the wording above, person-first.- Tests: join of an already-held Bot returns
alreadyHavewith no error styling; join after a local hide returnsrestored.
Acceptance criteria
- Step 2 shows neutral
You already have SelfA1233 · Chief.and no red text. - After a real local hide followed by re-accept, the restored Bot is named and shown as success.
- Remove confirm says only that Bot leaves my list. My shares are unchanged and still visible in People with access (with People with access hides live shares once two friends have joined each other's invite: owner can't see or Revoke them (side effect of #383 fix) #495 fixed).
- The reply-only hunch is checked and the result noted (filed in bot-social if confirmed).
Activity
Birfy commentedon Oct 20, 2026
Triage (2026-10-20 12:57 Asia/Shanghai, Birfy maintenance). Minor details decided (owner-delegated): on
relationship_existsthe join returns a structured result and the UI shows neutral textYou already have Chief (SelfA1233).(name format per the #384 decision, Bot first), and... is back in your list.only when a hidden or declined Bot was really restored; Remove confirm becomes one line:Remove Chief (SelfB1233) from your list? Your own Bots stay shared. SelfB1233 can share it again.; the worker checks the reply-only hunch and, if confirmed, it goes on the confirmation list as a Bot Social issue (not filed without the owner's yes).Open question for the owner: also add Share with a friend (one click to an existing friend, no link) next to Invite? That needs a new Bot Social API. My recommendation: wording fixes now, Share with a friend as a separate later issue.
Waiting for the owner's confirmation before
agent-ready(needs-human).Birfy commentedon Oct 20, 2026
Owner decision (2026-10-20): option (a) — fix the copy only (neutral already-friends message; clearer Remove confirm). One-click 'Share with a friend' will be a separate issue later (needs Bot Social API).
Birfy commentedon Oct 20, 2026
Claimed by maintenance run (2026-10-20 13:54 Asia/Shanghai). Working on branch
fix/496-already-friends-copy(fork Birfy/FlyBot), developed in parallel with #495-#499; scope per the Owner decision only.Birfy commentedon Oct 20, 2026
Worker notes (2026-10-20 14:08 Asia/Shanghai, Birfy maintenance), PR #503. Minor details decided (owner-delegated):
409 relationship_existscarries onlycode,messageandrelationship_id; it names no Bot (the old unhide code relied onpeer/botfields that only the test mock sent). The plugin now reads the public invite infoGET /v1/invites/{code}(the same route the invite page uses), sent without the connector token, only on this 409. If that lookup fails, the text falls back to neutralYou already have this friend's Bot.Remove Chief from your list? …).Reply-only hunch (from the issue): I checked Bot Social
master6a97ba0 by reading the code, not with a live test.declineBotGrant(src/platform.ts) declines the whole bundlerelationship_id = ? AND grantor_owner = ? AND grantee_bot = ? AND status='active'. It does not filter onreply_only, so the reply-only rows from B's first join (#23) are declined too. After A's Remove, A's Chief probably can't answer B's Chief anymore. This goes on the owner's confirmation list as a possible Bot Social issue (keep reply-only rows on decline). I have not filed it.Merge origin/main into fix/496-already-friends-copy (resolve after Th…
Social: neutral 'You already have …' on a re-accepted invite; clearer…