Repository navigation
Face room: a peer's multi-paragraph line arrives empty (3+ lines lose first/last line) — room.message viewed twice #302
Copy link
Copy link
Closed
Description
Summary
In a Face-to-face room, a peer line with two paragraphs arrives on the other home as an empty bubble. A line with three or more lines loses its first and last line. Single-line text and plain two-line text arrive intact. The text is complete on Bot Social, so this is a FlyBot client bug. The cause is proven below; it is not the new mentions field.
Environment
- FlyBot main
a003044(after fix(ui,host): stable tool mask, one Main Bot term, own Bots only as Main Bot, short typed-line header, display name in People with access #292, Face rooms: sender-side explicit mention list (handles) on typed lines, receiver resolves by handle first (follow-up to #287) #293/feat(face-rooms): explicit mention list: typed lines carry target handles, receiver resolves by handle first (#293) #294, Face rooms: a plain line should let every Bot in the room answer (one round, capped), not only the first (follow-up to #287) #295/feat(face-rooms): a plain line lets every Bot in the room answer, one pass, capped (#295) #296), core + plugins/social + plugins/tree on@deepseek-ai/dsh@0.2.0-rc.2, Node 24. - Two fresh installs on one Linux box: A
:3090(SelfA1622,@selfa1622.home) and B:3091(SelfB1622,@selfb1622.home). Both Chiefs runark/deepseek-v4-flash. A's Chief is shared with B by a per-Bot invite. - Bot Social prod
https://47-80-69-220.sslip.io(deploy1870786, featurestyped_by_owner,mentions). - Scheduled product self-test, focus: Face-to-face room, 2026-10-18 16:27–16:33 Asia/Shanghai.
Repro
- A: + → Face-to-face group → Chief → number
482913. B joins the same number with Chief. Enter chat. - A types
hi from A(a plain line, so both Chiefs answer, Face rooms: a plain line should let every Bot in the room answer (one round, capped), not only the first (follow-up to #287) #295). Approve A's Chief's reply on A. - A's Chief's reply has two paragraphs:
Hi from A's side 👋 I'm Chief, A's assistant here. … nice face-to-face setup.+ blank line +Anything you'd like us to work on together while we're here? @SelfB1622's Chief, want to say hello from B's side? - Look at that line on B.
Actual
- On A the reply shows in full.
- On B it is an empty grey bubble under
SelfA1622's Chief @chief.selfa1622.home. It stays empty after a reload and in Past rooms → Open (read-only). B's sidebar preview readsSelfA1622's Chief:with nothing after it. Screenshot: B's room with the empty bubble between B's own Chief line and the user's next line. - The short reply later (
2 + 2 = 4 😄) arrives fine. - B's stored transcript has the line with
"text": ""(room log seq 6, noeventId). B's room Session got[Group post from Chief · SelfA1622]\nwith nothing after it, so B's Chief also saw an empty post.
Evidence (read-only)
- Bot Social has the full text.
GET /v1/face-rooms/frm_01M571ZK5FZCKPS54G5J27B4ZS?after=0(as A; B had left, so it got 404) returns event 199 withuntrusted_content: { text: "Hi from A's side …\n\nAnything … from B's side?" }(240 chars). That event has nomentionsfield. Mentions only appear on B's typed line 201, and that line arrived fine. - Root cause: the event is "viewed" twice.
faceApi.get()→viewFaceRoom()→viewFaceEvent()turnsuntrusted_contentinto a plain stringuntrustedText.applyFaceSnapshot()(plugins/social/src/social.jsL2211) then callsrenderFaceEvent(event), which callsviewFaceEvent()again. On that second passuntrusted_contentis absent, sofaceUntrustedText(untrustedText)takes the string branch. That branch (face-rooms.jsL64–69,UNTRUSTED = /^[\s\S]*?\n([\s\S]*)\n[^\n]*$/) assumes a wrapped<marker>\n…\n<marker>string. It drops the first and last line of any plain text with ≥ 2 newlines. - Reproduced with the real server payload (
node, ona003044):viewFaceRoom(serverBody) → renderFaceEvent(ev, { attested: true }).text 198 "hi from A" → "hi from A" 199 (240 chars, 2 paras) → "" 202 "2 + 2 = 4 😄" → "2 + 2 = 4 😄" "line1\nline2\nline3" → "line2" - The same path handles every received
room.message: Bot lines, people's typed lines, and Past rooms replay. Any multi-paragraph message from another home is blanked or cut.
Expected
- Every home shows a peer's line exactly as Bot Social delivered it, including paragraphs and line breaks (
docs/subsystems/social.md: peer text is fenced, not rewritten). - The receiving Bot sees the same fenced text.
- A regression test feeds a multi-paragraph
room.messagethroughviewFaceRoom→applyFaceSnapshot/renderFaceEvent.
Fix direction (not done here)
Make viewFaceEvent idempotent: keep an already-viewed untrustedText string as-is, or have renderFaceEvent accept a viewed event without viewing it again. Apply the marker regex only to strings that really carry the begin/end markers.
Metadata
Metadata
Assignees
Labels
No labels
Activity