Skip to content

Commit e109361

Browse files
Birfycursoragent
andauthored
Send a JSON body when Enter chat starts a face room (#1098)
<!-- CURSOR_AGENT_PR_BODY_BEGIN --> Written-by: Dev Owner: Dev Reviewer: Reviewer Fixes #1085 ## What changed Enter chat calls `POST /v1/face-rooms/:id/start` with no body. On https://social.botawaken.com that request is HTTP 500 `{ code: "internal_error", message: "internal error" }` before auth, and the waiting dialog shows that string. The same POST with `{}` reaches the handler. Face-room POST, PUT, and PATCH calls that omit a body now send `{}`. Docs-not-needed: the face-room request body is not an architecture change. ## Verification at the tip Tip SHA: 5eee4ac Fail-without-change: on the unbroken tip, `node --import ./test/resolve.mjs --test --test-name-pattern '#1085' test/face-rooms.test.js` in plugins/social failed with message "internal error" (code internal_error). After the callHttp change the same test passes. Ran: `TZ=UTC npm run verify` (exit 0). core lint and arch-docs OK; plugins lint OK; client.js check OK; 10 patches apply; core equals ds-bot + patches. core tests 1439 pass / 0 fail; social 476 pass / 0 fail (includes #1085); tree 125 pass / 0 fail; timeline 125 pass / 0 fail; .github/scripts 417 pass / 0 fail; interop 37 pass / 0 fail; live-e2e 16 pass / 0 fail. After the commit, `node core/scripts/check-arch-docs.mjs` reported OK (3 changed files) and `node .github/scripts/changelog.mjs check` reported the fragments well formed. Not run: smoke (no core/index.js or src/host change). Desktop. A live face room on Social (the production probe was unauthenticated: a bodyless POST /start returned 500 internal error, and the same POST with `{}` returned 401 and reached the handler). ## Self-review note Implementer only. No Verdict. PASS and enqueue stay with the coordinator. Not enqueued. <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-aeb772ba-58a9-5608-80d1-a141c5b7f233?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-aeb772ba-58a9-5608-80d1-a141c5b7f233&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div> Co-authored-by: Cursor Agent <cursoragent@cursor.com>
1 parent 24d306b commit e109361

3 files changed

Lines changed: 33 additions & 2 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Enter chat in a face-to-face room no longer shows "internal error" after the other person has joined. The start request sends an empty JSON body, which Bot Social accepts ([#1085](https://github.com/ThinkFlowLab/FlyBot/issues/1085)).

‎plugins/social/src/face-rooms.js‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -706,15 +706,21 @@ export function createFaceRoomApi({ server, token, fetch: fetchImpl = socialFetc
706706
let response
707707
let data
708708
const sentAt = Date.now()
709+
// A POST or PUT with no body never reaches the handler on the deployed Bot Social
710+
// (social.botawaken.com, 2026-10-25): it answers 500 "internal error" before auth.
711+
// The same call with `{}` is an empty JSON body and the handler runs. Enter chat
712+
// is POST /face-rooms/:id/start, which otherwise sends nothing (#1085).
713+
const verb = String(method || 'GET').toUpperCase()
714+
const payload = body === undefined && (verb === 'POST' || verb === 'PUT' || verb === 'PATCH') ? {} : body
709715
try {
710716
response = await fetchImpl(url, {
711717
method,
712718
headers: {
713719
authorization: `Bearer ${token}`,
714720
accept: 'application/json',
715-
...(body !== undefined ? { 'content-type': 'application/json' } : {}),
721+
...(payload !== undefined ? { 'content-type': 'application/json' } : {}),
716722
},
717-
body: body !== undefined ? JSON.stringify(body) : undefined,
723+
body: payload !== undefined ? JSON.stringify(payload) : undefined,
718724
signal,
719725
})
720726
const offset = serverClockOffset(response.headers?.get?.('date'), sentAt, Date.now())

‎plugins/social/test/face-rooms.test.js‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,30 @@ test('REST join, poll, start, leave, and pending_approval send', async () => {
439439
assert.equal(left.status, 'closed')
440440
})
441441

442+
test('#1085: Enter chat sends a JSON body, so a bodyless POST is not an internal error', async () => {
443+
// social.botawaken.com (2026-10-25): POST /v1/face-rooms/:id/start with no body
444+
// answers 500 { code: "internal_error", message: "internal error" } before auth.
445+
// The same POST with `{}` reaches the handler. Enter chat is that POST.
446+
const fetch = async (url, init) => {
447+
assert.equal(String(url), 'https://s/v1/face-rooms/frm_1/start')
448+
assert.equal(init.method, 'POST')
449+
const raw = init.body
450+
if (raw === undefined || raw === '') {
451+
return new Response(JSON.stringify({ error: { code: 'internal_error', message: 'internal error' } }), { status: 500 })
452+
}
453+
assert.equal(init.headers['content-type'], 'application/json')
454+
assert.equal(raw, '{}')
455+
return new Response(JSON.stringify({
456+
room_id: 'frm_1', status: 'open', members: [], events: [], event_cursor: 1,
457+
started_at: '2026-10-25T00:00:00.000Z',
458+
}), { status: 200 })
459+
}
460+
const api = createFaceRoomApi({ server: 'https://s', token: 'otk_test', fetch })
461+
const started = await api.start('frm_1')
462+
assert.equal(started.status, 'open')
463+
assert.equal(started.roomId, 'frm_1')
464+
})
465+
442466
test('failed join never includes members or events', () => {
443467
const err = mapFaceError({ error: { code: 'room_full', members: [{ handle: '@x' }], events: [1], room_id: 'frm_leak' } }, 409)
444468
assert.equal(err.message.includes('frm_leak'), false)

0 commit comments

Comments
 (0)