fix: /pair qr fails to show QR code in chat surfaces#97933
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 29, 2026, 7:09 PM ET / 23:09 UTC. Summary PR surface: Source +141, Tests +131. Total +272 across 11 files. Reproducibility: yes. Current main's device-pair webchat branch returns a sensitive Review metrics: 2 noteworthy metrics.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the current internal live-only QR rendering shape after maintainer review confirms the sensitive QR block remains broadcast-only and current head checks are green. Do we have a high-confidence way to reproduce the issue? Yes. Current main's device-pair webchat branch returns a sensitive Is this the best way to solve the issue? Yes, with maintainer review. The latest head is the narrowest maintainable shape I found because it keeps the QR metadata internal, renders live-only QR blocks for chat surfaces, and recomputes persisted history without QR content. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against b7b2e1f77eb4. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +141, Tests +131. Total +272 across 11 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
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. How this review workflow works
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
* fix(pair): render qr per chat surface * test(plugin-sdk): update reply helper surface budget * fix(pair): keep qr metadata internal
* fix(pair): render qr per chat surface * test(plugin-sdk): update reply helper surface budget * fix(pair): keep qr metadata internal
* fix(pair): render qr per chat surface * test(plugin-sdk): update reply helper surface budget * fix(pair): keep qr metadata internal
* fix(pair): render qr per chat surface * test(plugin-sdk): update reply helper surface budget * fix(pair): keep qr metadata internal
Related: user report from Telegram/TUI/ControlUI pairing flow.
What Problem This Solves
Fixes an issue where users running
/pair qrcould fail to get a useful QR code in chat surfaces when the command was routed through the gateway-backed reply path. The same pairing command could showMedia failed, no visible QR image, or no TUI-readable QR even though the setup code itself was generated.Why This Change Was Made
The fix keeps native media-capable channel sends on the existing temporary PNG path, but moves the gateway fallback off sensitive
data:image/pngmedia URLs and onto typed pairing QR channel data. The gateway now builds a live-onlyopenclaw_pairing_qrcontent block with both an image URL and terminal QR text, while persisted history is recomputed without the sensitive QR block; TUI and ControlUI render that block directly.User Impact
Users can now run
/pair qrand get a useful QR code in Telegram, the TUI, and the ControlUI dashboard. The pairing QR remains single-use and live-only rather than being stored in durable chat history.Evidence
AI-assisted: yes, Codex.
./node_modules/.bin/oxfmt --check --threads=1 extensions/device-pair/index.ts extensions/device-pair/index.test.ts src/auto-reply/reply-payload.ts src/plugin-sdk/reply-payload.ts src/plugin-sdk/reply-payload.test.ts src/gateway/server-methods/chat.ts src/gateway/server-methods/chat.directive-tags.test.ts src/tui/tui-formatters.ts src/tui/tui-stream-assembler.test.ts ui/src/ui/chat/grouped-render.ts ui/src/ui/chat/grouped-render.test.tsnode scripts/run-vitest.mjs src/plugin-sdk/reply-payload.test.ts extensions/device-pair/index.test.ts src/gateway/server-methods/chat.directive-tags.test.ts src/gateway/server-methods/chat-reply-media.test.ts src/gateway/server-methods/chat-webchat-media.test.ts src/tui/tui-stream-assembler.test.ts src/tui/tui-event-handlers.test.ts ui/src/ui/chat/grouped-render.test.ts src/media/qr-terminal.test.ts src/media/qr-terminal.render.test.ts src/cli/qr-cli.test.ts src/cli/qr-dashboard.integration.test.ts src/pairing/setup-code.test.tsgit diff --checknode --max-old-space-size=8192 --import tsx scripts/generate-plugin-sdk-api-baseline.ts --check.agents/skills/autoreview/scripts/autoreview --mode localreturned clean after refreshing the plugin SDK API baseline.telegramcredential lease used thetelegramkind, nottelegram-user; real TelegramsendPhotowas observed, the caption included scan instructions, and noMedia failedtext was emitted.mediaUrl; TUI output included terminal QR block glyphs and instructions; ControlUI rendered one data-PNG image with alt textOpenClaw pairing QR code.15de9d881a8reproduced the legacy broken shape withdata:image/pnginmediaUrland no pairing QR channel data.