feat: add custom_msg websocket type with QR download links#574
feat: add custom_msg websocket type with QR download links#574WcaleNieWolny merged 2 commits intomainfrom
Conversation
Add a generic `custom_msg` websocket message type that the CLI can handle in a custom way. First use case: `qr_download_link` renders a scannable QR code + URL text for APK/IPA download links. - Add `customMsg` callback to BuildLogger interface - Add `custom_msg` case to websocket message handler - Create qr.ts helper with QR rendering (qrcode package) - Unknown message kinds show warning + raw data dump - Wire up both default logger and Ink onboarding UI
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds QR code generation and custom WebSocket message handling to the build log pipeline: a new Changes
Sequence DiagramsequenceDiagram
participant WS as WebSocket Stream
participant REQ as streamBuildLogs (request.ts)
participant LOG as BuildLogger (app.tsx)
participant QR as handleCustomMsg (qr.ts)
participant OUT as Console / Output
WS->>REQ: Emit message (batch or single) containing entry with type='custom_msg', kind, data
REQ->>REQ: Parse message, detect entry.type === 'custom_msg'
REQ->>LOG: await logger.customMsg(kind, data) or fallback to QR handler
LOG->>QR: handleCustomMsg(kind, data, logFn, warnFn)
alt kind == "qr_download_link"
QR->>QR: validate data.url is string
QR->>QR: QRCode.toString(url, {type:'utf8', errorCorrectionLevel:'L'})
QR->>OUT: log empty line, each QR line, URL, empty line
else unknown kind
QR->>OUT: warn about unknown kind
QR->>OUT: log pretty-printed data JSON
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
Companion server-side PR: Cap-go/capgo_builder#67 |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
src/build/request.ts (1)
62-63: Consider documenting or fixing the sync/async interface mismatch.The
customMsgcallback is typed as synchronousvoid, but all implementations call asynchandleCustomMsgwithout awaiting. While this works for the current single-message use case, the interface doesn't communicate that implementations may be async.💡 Option: Update interface to support async
/** Called with custom messages from the builder (QR codes, etc.) */ - customMsg: (kind: string, data: Record<string, unknown>) => void + customMsg: (kind: string, data: Record<string, unknown>) => void | Promise<void>This makes the async nature explicit and allows callers to await if needed in the future.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/build/request.ts` around lines 62 - 63, The customMsg callback is currently declared as synchronous (customMsg: (kind: string, data: Record<string, unknown>) => void) but implementations call async functions like handleCustomMsg without awaiting; change the callback signature to return a Promise<void> so the async contract is explicit (customMsg: (kind: string, data: Record<string, unknown>) => Promise<void>), update all implementations (e.g., functions calling handleCustomMsg) to be async and return/await the promise, and update any callers of customMsg to await its result where appropriate to preserve correct async flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/build/onboarding/ui/app.tsx`:
- Around line 546-553: The call to async handleCustomMsg is not awaited, causing
possible out-of-order buildOutput updates; update the BuildLogger.customMsg
signature (in the BuildLogger interface) to return Promise<void> (or
void|Promise<void>), change the customMsg implementation in app.tsx to be async
and await handleCustomMsg(...) (i.e., make the customMsg callback async and
await the handleCustomMsg call), and update any other call sites/types that rely
on BuildLogger.customMsg to accept the Promise-returning signature so the async
behavior is properly propagated.
In `@src/build/qr.ts`:
- Line 16: The warn messages in src/build/qr.ts are double-prefixed because the
warn callback already prepends "⚠ "; update the two warn(...) calls (the ones
currently passing strings that start with "⚠ ") to remove the manual "⚠ " prefix
so they only pass the descriptive text (e.g., change warn('⚠ qr_download_link
message missing url field') to warn('qr_download_link message missing url
field') and likewise for the other warn at line 39), leaving the warn function
and its callback unchanged.
In `@src/build/request.ts`:
- Around line 114-124: customMsg currently calls handleCustomMsg without
awaiting and passes a logger that causes duplicate warning prefixes; update
customMsg to await handleCustomMsg (so it isn't fire-and-forget) and pass a
plain warning printer that does not add an extra "⚠" (replace clackLog.warn with
a simple wrapper or use clackLog.info/print depending on clack API) and keep the
console.log printer for standard lines; also ensure you apply the same
single-prefix change you made in qr.ts so the warning symbol isn't duplicated
when clackLog functions already add styling.
---
Nitpick comments:
In `@src/build/request.ts`:
- Around line 62-63: The customMsg callback is currently declared as synchronous
(customMsg: (kind: string, data: Record<string, unknown>) => void) but
implementations call async functions like handleCustomMsg without awaiting;
change the callback signature to return a Promise<void> so the async contract is
explicit (customMsg: (kind: string, data: Record<string, unknown>) =>
Promise<void>), update all implementations (e.g., functions calling
handleCustomMsg) to be async and return/await the promise, and update any
callers of customMsg to await its result where appropriate to preserve correct
async flow.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d67aca46-604c-48d0-babd-760311137f76
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (4)
package.jsonsrc/build/onboarding/ui/app.tsxsrc/build/qr.tssrc/build/request.ts
- Make customMsg callback async and await handleCustomMsg at all call sites (default logger, websocket handler, onboarding UI) - Update BuildLogger.customMsg signature to void | Promise<void> - Remove manual ⚠ prefix from warn() calls in qr.ts since the warn callbacks already add their own warning styling
|



Summary
custom_msgwebsocket message type withkindanddatafields — extensible for future use casesqr_download_linkrenders a scannable QR code + URL text in the terminal for APK/IPA downloadskindvalues show a warning + raw data dump (forward-compatible with newer server versions)BuildLogger(console path) and the Ink onboarding UICompanion PR: Cap-go/capgo_builder — pushes the
custom_msgfrom the server on build successTest plan
--output-uploadand verify QR code renders after successkindvalues show warning + raw JSONtsc --noEmitpassesSummary by CodeRabbit