Skip to content

Add support for interacting with buttons and lists#258

Merged
steipete merged 14 commits into
openclaw:mainfrom
morgs:feature/interactive-select
May 22, 2026
Merged

Add support for interacting with buttons and lists#258
steipete merged 14 commits into
openclaw:mainfrom
morgs:feature/interactive-select

Conversation

@morgs
Copy link
Copy Markdown
Contributor

@morgs morgs commented May 21, 2026

Summary

Adds wacli send select for selecting stored inbound WhatsApp quick-reply buttons and list rows from scripts.

This builds on the existing button/list parsing and storage support by adding the send-side command, delegation support, metadata needed to choose safely, and docs/tests.

Details

  • Adds wacli send select --to ... --id ... (--label | --button-id | --index)
  • Stores optional response_type and index metadata for parsed buttons/list rows
  • Supports send delegation while sync --follow owns the store
  • Sends list rows and plain quick replies as quoted text replies to the original message
  • Keeps native-flow quick replies explicitly unsupported until the wire format is verified
  • Warns if local outbound persistence fails after WhatsApp accepts a send

Testing

  • pnpm format:check
  • pnpm lint
  • pnpm test
  • pnpm build
  • git diff --check

@morgs morgs marked this pull request as ready for review May 21, 2026 14:38
@steipete
Copy link
Copy Markdown
Collaborator

Pushed maintainer updates in 2f877e9.

What changed:

  • merged current main after fix: import completed call logs #261 landed
  • resolved the changelog conflict
  • changed send select to emit structured list_response / buttons_response payloads carrying the selected row/button ID instead of plain quoted text
  • updated tests and docs for the structured wire shape

Local proof:

  • go test ./cmd/wacli ./internal/app ./internal/store ./internal/wa
  • pnpm format:check && pnpm lint && pnpm test && pnpm build && git diff --check
  • autoreview local patch clean: no accepted/actionable findings

Live proof status: blocked locally. The only local store at ~/.wacli currently reports authenticated:false, so I cannot honestly verify send select against WhatsApp from this machine yet.

@clawsweeper re-review

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 22, 2026

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 22, 2026

Codex review: needs maintainer review before merge.

Latest ClawSweeper review: 2026-05-22 15:01 UTC / May 22, 2026, 11:01 AM ET.

Workflow note: Future ClawSweeper reviews update this same comment in place.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

Summary
The PR adds wacli send select, selection metadata for stored WhatsApp buttons/list rows, send-delegation support, docs, changelog, and focused tests.

Reproducibility: not applicable. as a bug reproduction; this is a feature PR. For merge proof, the latest comment gives current-head live CLI output showing accepted WhatsApp sends for one quick reply and one list row.

PR rating
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🐚 platinum hermit
Summary: Focused feature patch with live transport proof and tests, with a remaining maintainer decision around the exact interaction semantics.

Rank-up moves:

  • Add flow-advancement proof only if maintainers want send select to mean more than sending the selected display text as a quoted reply.
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Real behavior proof
Sufficient (live_output): Current-head redacted live output shows send select returning successful WhatsApp message IDs for a quick reply and a list row, which is sufficient for the documented quoted-reply transport behavior.

Risk before merge

  • The latest proof shows WhatsApp accepted quoted text sends with message IDs, but it does not prove that the target bot/business flow advanced after those replies.
  • Template quick-reply selections still use a structured protocol response path that is source-reviewed and unit-tested here, but not demonstrated in the latest live proof.

Maintainer options:

  1. Accept quoted-reply semantics
    Maintainers can merge if the intended contract is WhatsApp accepting a quoted text reply, with no guarantee that a bot treats it like a phone tap.
  2. Require flow-advancement proof
    Before merge, ask for redacted live output showing a real inbound control advancing the target business/bot flow, or explicitly scope docs to transport-only selection.
  3. Narrow unproven protocol paths
    If template quick replies are not ready to own, make them quoted-text or unsupported until live protocol proof exists.

Next step before merge
The remaining action is maintainer judgment on the quoted-reply contract and message-delivery proof scope, not a narrow automated repair.

Security
Cleared: No dependency, workflow, secret, permission, or downloaded-code changes were found; the new delegate fields stay within the existing local socket flow.

Review details

Best possible solution:

Land the feature if maintainers accept quoted replies as the supported send select contract, and keep synthetic phone-tap/native-flow behavior explicitly unsupported until real fixtures prove it.

Do we have a high-confidence way to reproduce the issue?

Not applicable as a bug reproduction; this is a feature PR. For merge proof, the latest comment gives current-head live CLI output showing accepted WhatsApp sends for one quick reply and one list row.

Is this the best way to solve the issue?

Unclear until maintainers decide the product contract: the implementation is narrow and documented as quoted-text selection, but it intentionally does not synthesize a real button/list tap.

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. Current-head redacted live output shows send select returning successful WhatsApp message IDs for a quick reply and a list row, which is sufficient for the documented quoted-reply transport behavior.
  • add rating: 🐚 platinum hermit: Current PR rating is 🐚 platinum hermit because proof is 🐚 platinum hermit, patch quality is 🐚 platinum hermit, and Focused feature patch with live transport proof and tests, with a remaining maintainer decision around the exact interaction semantics.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): Current-head redacted live output shows send select returning successful WhatsApp message IDs for a quick reply and a list row, which is sufficient for the documented quoted-reply transport behavior.
  • remove rating: 🧂 unranked krab: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.
  • remove status: 📣 needs proof: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P2: This is a normal user-facing send feature with limited blast radius and focused tests/docs.
  • merge-risk: 🚨 message-delivery: The PR adds a new WhatsApp send path where accepted transport does not fully prove bot-flow advancement or every response subtype.
  • rating: 🐚 platinum hermit: Current PR rating is 🐚 platinum hermit because proof is 🐚 platinum hermit, patch quality is 🐚 platinum hermit, and Focused feature patch with live transport proof and tests, with a remaining maintainer decision around the exact interaction semantics.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): Current-head redacted live output shows send select returning successful WhatsApp message IDs for a quick reply and a list row, which is sufficient for the documented quoted-reply transport behavior.
  • proof: sufficient: Contributor real behavior proof is sufficient. Current-head redacted live output shows send select returning successful WhatsApp message IDs for a quick reply and a list row, which is sufficient for the documented quoted-reply transport behavior.

What I checked:

  • Current main does not already implement the command: A current-main grep for newSendSelectCmd or send select across cmd/docs/internal returned no matches, so this PR is not obsolete on main. (bb68ecc79dec)
  • Selection send path: The PR builds list-row and classic button selections as quoted ExtendedTextMessage sends, keeps template quick replies on TemplateButtonReplyMessage, and explicitly errors for native-flow quick replies. (cmd/wacli/send_select_cmd.go:366, 288e36aa7cf6)
  • Documented user contract: The docs say send select sends selected display text as a quoted reply and intentionally does not synthesize a phone-tap event. (docs/send.md:60, 288e36aa7cf6)
  • Parser/storage metadata: The PR stores response_type and index metadata for hydrated buttons, classic buttons, list rows, and native-flow buttons so selection can choose the intended response path. (internal/wa/messages_business.go:26, 288e36aa7cf6)
  • Whitespace check: The patch diff passes git diff --check against current main. (288e36aa7cf6)
  • Live proof from discussion: The latest contributor comment on May 22, 2026 reports redacted current-head live output for one quick reply and one list row returning success:true with WhatsApp message IDs on head 288e36a. (288e36aa7cf6)

Likely related people:

  • steipete: Authored the current send-delegation flow, quoted reply support, native-flow parser support, and recent quoted-message metadata touched by this PR. (role: recent area contributor; confidence: high; commits: eaa7a1b97925, 782c29078c3a, cac5f20e45b2; files: cmd/wacli/send.go, cmd/wacli/send_ipc.go, internal/wa/messages_business.go)
  • ignaciovarela: Introduced the stored interactive button/list parser and store pipeline that send select builds on. (role: feature introducer; confidence: high; commits: 7b6896ccb07f; files: internal/wa/messages_business.go, internal/store/types.go, internal/app/sync.go)
  • Ortes: Added WhatsApp poll send/vote flows and helper patterns for stored-message lookup, sender resolution, and delegated send behavior that this PR mirrors. (role: adjacent owner; confidence: medium; commits: de9a3dd43480; files: cmd/wacli/poll_cmd.go, cmd/wacli/send_poll_cmd.go, cmd/wacli/send_ipc.go)

Codex review notes: model gpt-5.5, reasoning high; reviewed against bb68ecc79dec.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 message-delivery 🚨 Merging this PR could drop, duplicate, misroute, suppress, or wrongly target messages. labels May 22, 2026
@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 22, 2026

ClawSweeper PR egg

✨ Hatched: 🌱 uncommon Sunspot Diff Drake

Hatch command

Comment @clawsweeper hatch when this PR is hatchable.

Hatchability rules:

  • Merged PRs are hatchable.
  • Open PRs are hatchable when they are status: 👀 ready for maintainer look, status: 🚀 automerge armed, or labeled clawsweeper:automerge.
  • Closed unmerged PRs are hatchable only when one of those hatchable labels is still present in the durable record.

Rarity: 🌱 uncommon.
Trait: hums during re-review.
Image traits: location CI tidepool; accessory lint brush; palette amber, ink, and glacier blue; mood calm; pose nestled inside a glowing shell; shell woven fiber shell; lighting bright celebratory glints; background subtle branch markers.
Share on X: post this hatch
Copy: My PR egg hatched a 🌱 uncommon Sunspot Diff Drake in ClawSweeper.

What is this egg doing here?
  • Eggs appear after the PR passes real-behavior proof. It is here for vibes, not verdicts: it does not change labels, ratings, merge decisions, or automation.
  • The shell reacts to review momentum: open follow-up work warms it up, re-review makes it wobble, and a clean final review lets it hatch.
  • Hatchability usually comes from sufficient real-behavior proof, no blocking P0/P1/P2 findings, no security attention needed, and clean correctness. A merged PR is already final, so merge makes the egg hatchable independently.
  • The hatch is seeded from this repository and PR number, so the same PR keeps the same creature; the reviewed head SHA can only change safe visual details.
  • Rarity is just collectible sparkle: 🥚 common, 🌱 uncommon, 💎 rare, ✨ glimmer, and 🌈 legendary.

@morgs
Copy link
Copy Markdown
Contributor Author

morgs commented May 22, 2026

Live follow-up pushed in 4063db3.

What changed after testing Peter's structured-send update:

  • 8540b60 fixes the group-selection review finding: stored group selections now require a known sender or --sender before building reply context.
  • 4063db3 changes ordinary list_response / buttons_response selections back to quoted display-text replies. Template button replies remain structured; native-flow replies still fail explicitly.

Redacted live WhatsApp proof from an authenticated test account against a live chatbot:

# Structured quick reply from 2f877e9:
wacli send select --to [redacted-bot-jid] --id 8121520C30244B2CEB --label [redacted-label] --type quick_reply --json
=> {"success":false,"error":"server returned error 479"}

# Structured list row from 2f877e9:
wacli send select --to [redacted-bot-jid] --id 7EB4C463B52413FC75 --label [redacted-label] --type list_row --json
=> {"success":false,"error":"server returned error 479"}

# Quoted-text quick reply after 4063db3:
wacli send select --to [redacted-bot-jid] --id 8121520C30244B2CEB --label [redacted-label] --type quick_reply --json
=> {"success":true,"data":{"sent":true,"to":"[redacted-bot-jid]","id":"3EB0353605F5850DD4D001","target":"8121520C30244B2CEB","selected":{"type":"quick_reply","display_text":"[redacted-label]","id":"8J+PoCBJbWVueXUgZW5rdWx1"}},"error":null}

# Quoted-text list row after 4063db3:
wacli send select --to [redacted-bot-jid] --id 7EB4C463B52413FC75 --label [redacted-label] --type list_row --json
=> {"success":true,"data":{"sent":true,"to":"[redacted-bot-jid]","id":"3EB06A17027D3672E24112","target":"7EB4C463B52413FC75","selected":{"type":"list_row","display_text":"[redacted-label]","id":"UGhha2F0aGkga3VrYQ"}},"error":null}

Follow-up sync after the accepted quoted-text sends idled out with messages_stored:0, so I am not claiming bot-flow advancement from those stale stored controls. The transport-level result is the important part here: WhatsApp rejected the structured response payloads with 479, while the revised send select command produced accepted WhatsApp message IDs for both surfaces.

Local gate on the pushed head:

pnpm format:check
pnpm lint
pnpm test
pnpm build
git diff --check

All passed locally.

@clawsweeper re-review

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 22, 2026

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 22, 2026
@steipete
Copy link
Copy Markdown
Collaborator

Maintainer pass update:

  • Merged current main after feat: add message revoke and forward commands #259 and merged the latest contributor branch commits.
  • Fixed protocol response construction so list rows send ListResponseMessage with selectedRowID, and classic quick replies send ButtonsResponseMessage with selectedButtonID.
  • Fixed template quick-reply index handling: store the hydrated protocol button index, convert back to zero-based selectedIndex when sending, and use stored indexes for --index selection.
  • Fixed selector resolution so URL/call/list container controls do not make quick-reply/list-row label matches ambiguous.
  • Kept the group --sender requirement for unsynced group selections.

Local proof on pushed head 3b4a342:

  • pnpm format:check && pnpm lint && pnpm test && pnpm build && git diff --check
  • autoreview --mode branch --base origin/main clean

Live verification status: blocked, not passed. I tested against an authenticated linked-device account on clawmac (molty, sending to +436769770569). There were no real synced inbound button/list messages in the store. Seeded local fixtures for quick-reply and list-row targets both failed with WhatsApp server error 479, and a helper attempt to originate a real list message between the two authenticated local accounts also failed with server error 479. So this still needs verification against a real incoming WhatsApp button/list message from a business/bot before I would merge it.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels May 22, 2026
@morgs
Copy link
Copy Markdown
Contributor Author

morgs commented May 22, 2026

Pushed 288e36a to make the intended behavior explicit and keep the implementation on the live-proven path.

I think the clearest framing for this feature is:

send select looks up a stored inbound button/list option, then sends that option's visible text as a quoted reply to the original message.

For ordinary quick replies and list rows, this is intentionally not a synthetic phone-tap event and not a generated WhatsApp list/button response payload. The protocol-shaped ListResponseMessage / ButtonsResponseMessage attempts have now failed live with server error 479 in both test environments; the quoted-reply path is the one we have positive transport proof for.

Current-head live proof from 288e36a, redacted:

# quick reply, current head
wacli send select --to [redacted-bot-jid] --id 8121520C30244B2CEB --label [redacted-label] --type quick_reply --json
=> {"success":true,"data":{"sent":true,"to":"[redacted-bot-jid]","id":"3EB0E4E1463595D21DC765","target":"8121520C30244B2CEB","selected":{"type":"quick_reply","display_text":"[redacted-label]","id":"8J+PoCBJbWVueXUgZW5rdWx1"}},"error":null}

# list row, current head
wacli send select --to [redacted-bot-jid] --id 7EB4C463B52413FC75 --label [redacted-label] --type list_row --json
=> {"success":true,"data":{"sent":true,"to":"[redacted-bot-jid]","id":"3EB0018F258C73E297C103","target":"7EB4C463B52413FC75","selected":{"type":"list_row","display_text":"[redacted-label]","id":"UGhha2F0aGkga3VrYQ"}},"error":null}

What 288e36a changes:

  • ordinary list_response and buttons_response selections build quoted ExtendedTextMessage replies again
  • docs now state that send select sends selected display text as a quoted reply, not a synthetic phone-tap event
  • Peter's useful selector/index/template/group-sender fixes remain in the branch

Local gate on 288e36a:

pnpm format:check && pnpm lint && pnpm test && pnpm build && git diff --check

All passed locally.

@clawsweeper re-review

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 22, 2026

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 22, 2026
@steipete
Copy link
Copy Markdown
Collaborator

Maintainer final pass on current head 288e36a:

  • Local gate passed: pnpm format:check && pnpm lint && pnpm test && pnpm build && git diff --check.
  • Live verified from the authenticated clawmac linked-device account molty (+447511247203) to +436769770569 using the exact PR binary.
    • quick-reply quoted-text selection accepted by WhatsApp: 3EB0BDD9FA2632B16D8109
    • list-row quoted-text selection accepted by WhatsApp: 3EB094359B08AF707E40BB
  • Temporary local fixture rows used for the stored inbound controls were removed after verification.
  • Receiver-side sync did not finish reliably, so I am treating sender-side WhatsApp acceptance plus returned message IDs as the live proof here, not claiming bot-flow advancement.
  • Autoreview initially flagged the non-protocol list/button response path; I reran with the explicit PR contract and live 479 context. Final contextual autoreview is clean: quoted text is the intended/live-proven behavior for ordinary list/button selections, not synthetic phone-tap behavior.

This makes sense to land under the documented contract: send select sends the selected visible text as a quoted reply for ordinary quick replies/list rows; native-flow remains unsupported, and template replies keep their protocol-specific path.

@steipete steipete merged commit 0162313 into openclaw:main May 22, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 message-delivery 🚨 Merging this PR could drop, duplicate, misroute, suppress, or wrongly target messages. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants