Skip to content

feat(social): show pending Bot Social approvals in Friends' Bots - #70

Merged
Birfy merged 1 commit into
ThinkFlowLab:mainfrom
Birfy:cursor/pending-approval-cue-5abe
Oct 15, 2026
Merged

Birfy merged 1 commit into
ThinkFlowLab:mainfrom
Birfy:cursor/pending-approval-cue-5abe

Conversation

@Birfy

@Birfy Birfy commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes #69. Pending outbound Bot Social approvals are easy to miss: friends see no reply while the owner may never notice drafts are held.

This adds a persistent N to approve badge and a Waiting for your approval section in Friends' Bots, with Approve / Reject that call existing decide_approval. Bot Social's default hold-outbound policy is unchanged.

Docs

Quick Start / social README note that inbound arrives immediately and outbound may wait unless Auto-accept is on for that friend.

Test plan

  • plugins/social tests pass (agent reported 33/33)
  • With a pending outbound approval, Friends' Bots shows the badge and draft
  • Approve delivers; Reject drops
  • Auto-accept for a friend still skips the hold for clean messages

Branch: Birfy:cursor/pending-approval-cue-5abe (1 commit, 8 files vs upstream main).

Outbound drafts the server holds were invisible in FlyBot, so friends
saw no reply. Surface them on social/status and in Friends' Bots with
Approve / Reject. Inbound still arrives immediately.

Fixes ThinkFlowLab#69

Co-authored-by: Danyang Chen <birfychen@gmail.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-15T05:10:01.566447Z 112d20b PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 112d20b51b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +708 to +712
const result = await client.callTool('list_approvals', { status: 'pending' })
const raw = result?.approvals ?? (Array.isArray(result) ? result : [])
const items = raw
.map(item => approvalView(item, { localName: localNameOf }))
.filter(item => item && item.kind === 'outbound_message' && (item.status === 'pending' || item.status === 'pending_approval'))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scope pending approvals to this FlyBot identity

Because createMcpClient authenticates to the owner-wide MCP endpoint, list_approvals can return pending sends for every bot owned by the connector. This filter only checks kind/status, so when the same owner token is used for another Bot or home (as supported by the legacy token + botId configuration), that other bot's draft appears in this team's Friends' Bots and can be approved or rejected here; restrict the results to config.botId or this home's registered member IDs before exposing them.

Useful? React with 👍 / 👎.

Comment thread plugins/social/client.js
load().then(loadSettings)
loadApprovals()
if (typeof setInterval !== 'function') return undefined
const timer = setInterval(loadApprovals, 5000)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Coalesce approval polls while a request is pending

When Bot Social stops responding, social/status can remain pending for the MCP client's 30-second timeout, but this five-second interval starts another loadApprovals call without tracking the previous promise. Each mounted panel can therefore accumulate roughly six concurrent list_approvals requests and keep launching more as they time out, adding avoidable host load and allowing older responses to overwrite newer state; reuse an in-flight poll or schedule the next poll only after the current one settles.

Useful? React with 👍 / 👎.

@Birfy
Birfy merged commit 2ed9c32 into ThinkFlowLab:main Oct 15, 2026
5 checks passed
HugoXK pushed a commit to HugoXK/FlyBot that referenced this pull request Oct 25, 2026
…owLab#1162)

<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
Written-by: Dev

Owner: Dev
Reviewer: Reviewer

Fixes ThinkFlowLab#1161

## What changed

Joining
`https://social.botawaken.com/r/@chief.flybot682b8a43.home/AwWkxg8zt7fPMgLSt3Wj1w`
(room **FlyBot 交付组**) claims the ticket and then stays on `Asked to join
"FlyBot 交付组". It opens in your sidebar as soon as their FlyBot seats
your Bots.` The host is prod `c0a3369` (ThinkFlowLab#1082 already seats from the
claim). The live ticket was not previewed, claimed, or revoked here.

Host logs on prod u-682b8a (last 60 minutes) are the failure:

- About 3656 times: `[ds-bot] a room link claim was not read: Too many
attempts. Try again in 10 minutes.` Stack: `face-rooms.js`
preview/`callHttp` → `seatOpenClaims` → `@flybot/social` `pollOnce`.
Retries ran 10–85/min, so the 10-minute cool-down never cleared. Ticket
`AwWkxg8zt7fPMgLSt3Wj1w` has 0 successful claim reads.
- `room share not sent to @chief.flybot98b8ecba.home: Bot Social
send_as_member: payload.text (1-4000 chars) required` via
`sendTicketShare` ← `sendShareTo`.

A quiet poll now reads one open `/r/@handle/ticket` link about once a
minute. When the preview says `Too many attempts` (or answers
`rate_limited` / `locked_out`), it waits out the minutes that sentence
names, or `Retry-After`, at least one minute and at most 10 minutes, and
it does not preview the next link in that call. **Seat them** and a read
of one room still verify at once. A network error is tried again on the
next tick.

Every room-share text is kept inside 1–4000 characters before
`send_as_member`: a join drops instruction-override lines and then
oldest history, notice, and roster; a line's own text is shortened;
`sendShareTo` and `sendTicketShare` refuse a text outside that range
instead of calling Bot Social. A seating send that is still
`pending_approval` is not marked told.

Who may be seated is unchanged: the server's claim list is still
required, an unsharable room stays `not-addable`, and the knock is not
authority.

Bot Social still counts an authenticated minter's re-read of their own
ticket on the anonymous preview budget (`previewLocalRoomInvite` →
`faceIpRateLimit` at `7a07e1b`; ThinkFlowLab#69/ThinkFlowLab#70 kept mints off that budget and
left previews on it). A minter exemption on Birfy/bot-social would stop
a long-open host from spending the budget in the first place. This
change is what lets the cool-down expire and the join leave. No Bot
Social change is in this pull request.

## Verification at the tip

Tip SHA: 2801302

Ran: `TZ=UTC npm run verify` (exit 0, Node v22.23.4). On `origin/main`
`cb346c2`, before the fix, the new core tests failed: 30 previews in one
burst (the poll must do 1), a join of 4811 characters that still
contained `ignore previous instructions`, and a pending join recorded as
`not-delivered` rather than `held`. The social test expected
`pending_approval` and the send was reported delivered. This tip adds
the logged sentence with no error code: 90 polls across 9 minutes call
preview once, a poll one millisecond before 10 minutes does not call it
again, and the poll at 10 minutes seats the claim and opens the sidebar.
A line of 8000 characters and a join with 20 full history lines encode
to 1–4000 characters and still parse. A seating send longer than 4000
characters is refused before `send_as_member`.

Not run: the smoke bench (`core/dev/bench.sh`). The harness checkout
beside this tree does not resolve `@deepseek-ai/dsh-llm`; `npm run
verify` is the suite CI's `tests-ok` runs.

<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-9decfb0d-2fae-5da3-b548-cb65239ca32c?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-9decfb0d-2fae-5da3-b548-cb65239ca32c&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>
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.

Pending Bot Social approvals are hard to discover in the UI

2 participants