Previously the same `text` field was used for both header.title and body.text,
causing duplicate content to appear. Now `title` controls the header (defaults
to a space like Pastorini) and `text` controls the body independently.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove messageContextInfo (deviceListMetadata) from viewOnceMessage wrapper
in generateButtonMessage and remove empty subtitle from header. This fixes
CTA mixed buttons (url, copy, call) not being delivered to iOS devices -
same pattern that fixed carousel messages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Flatten image validation nesting to max 4 levels (eslint max-depth)
- Collapse multi-line ternary to single line (prettier)
- Add missing blank line before statement
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Lint fixes:
- Replace `any` types with proper proto interfaces (IInteractiveMessage)
- Fix missing blank lines before statements (eslint padding-line-between-statements)
- Fix unused variable and indentation in protocol dump
- Remove pre-existing `any` casts in createParticipantNodes
Review feedback (Copilot/Codex):
- Gate protobuf roundtrip test and protocol dump behind debug level
(avoids CPU overhead and sensitive data exposure in production)
- Add empty array validation for nativeButtons (fixes [].every() edge case)
- Support headerTitle in quick_reply buttonsMessage (HeaderType.TEXT)
- Fix stale comment that said "wrap viewOnceMessage" when code sends direct
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Carousel (interactiveMessage):
- Remove messageContextInfo from carousel (breaks iOS delivery)
- Remove empty subtitle field from card headers
- Add jpegThumbnail/dimensions validation for card images
- Return direct interactiveMessage at root (no viewOnceMessage wrapper)
- Skip DSM (deviceSentMessage) for own devices (causes error 479)
- Skip bot node injection for carousel messages
Quick Reply Buttons (buttonsMessage):
- Separate quick_reply buttons from CTA buttons in generateWAMessageContent
- quick_reply (reply only) uses legacy buttonsMessage format (works on Android + iOS + Web)
- CTA buttons (url, copy, call) use nativeFlowMessage with viewOnceMessage wrapper
Stanza construction (messages-send.ts):
- Defer biz/bot nodes to be appended LAST (after device-identity, tctoken)
- Fix button name extraction for carousel (flatMap from cards)
- Add protobuf roundtrip test and protocol dump for debugging
Tested: Carousel renders on Android + iOS. Quick reply buttons render on Android + iOS + Web.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Updated protobufjs from ^7.2.4 to ^8.0.0
- Updated protobufjs-cli from ^1.1.3 to ^2.0.0
- This resolves peer dependency conflicts
- Use --legacy-peer-deps flag when installing
https://claude.ai/code/session_015R3U3kiprQiNTTNNt31Sg6
Production server (vmi2736502) uses Node v20.20.0, not v22.
@types/node must match the lowest Node version we support.
Changed:
- @types/node: ^22.12.5 → ^20.19.33
Local dev may use Node 22, but types must be compatible with
production Node 20 to avoid runtime errors from missing APIs.
https://claude.ai/code/session_015R3U3kiprQiNTTNNt31Sg6
- Cache .yarn/cache instead of node_modules to avoid inconsistencies
- Include both yarn.lock and package.json in cache key hash
- Update restore-keys to be more specific with package.json hash
- This prevents CI from using stale caches after dependency updates
https://claude.ai/code/session_015R3U3kiprQiNTTNNt31Sg6
Changes:
- Replace gh pr merge with peter-evans/enable-pull-request-automerge action
- Add pr_number output to create_pr step
- Support auto-merge for both new and existing PRs
- Simplify workflow by removing manual merge logic
- Better error handling and reliability
Benefits:
- More robust auto-merge using GraphQL API
- Works even if repository allows auto-merge is disabled
- Clearer separation of concerns
- Better support for existing PRs
https://claude.ai/code/session_015R3U3kiprQiNTTNNt31Sg6
Changes:
- Use GH_PAT (if available) for better permissions
- Extract PR number for more reliable merge command
- Add detailed error logging with exit codes
- Attempt auto-merge on existing PRs
- Provide clear troubleshooting guidance
This should help diagnose why auto-merge is failing and potentially
fix permission issues if a GH_PAT secret is configured.
https://claude.ai/code/session_015R3U3kiprQiNTTNNt31Sg6
Removed the "Debug Git Config" step from all workflows as it could
potentially expose the GITHUB_TOKEN in logs (shown in git URL rewrites).
Now that the workflows are passing with the HTTPS libsignal fix,
this debug output is no longer needed.
Addresses security concern raised by Copilot AI in PR #170.
https://claude.ai/code/session_015R3U3kiprQiNTTNNt31Sg6
Changed libsignal dependency from "github:whiskeysockets/libsignal-node"
to "https://github.com/whiskeysockets/libsignal-node.git" to fix
GitHub Actions workflow failures.
The Yarn package manager was not respecting Git's global URL rewrite
configuration and was trying to use SSH (which failed with "Permission
denied (publickey)"). Using explicit HTTPS syntax ensures the dependency
is always fetched over HTTPS in CI environments.
https://claude.ai/code/session_015R3U3kiprQiNTTNNt31Sg6
Added debug output to see:
- Git URL rewrites configuration
- Environment variables
- Verbose yarn install output
This will help identify why yarn install is failing after the GITHUB_TOKEN fix.
https://claude.ai/code/session_015R3U3kiprQiNTTNNt31Sg6
Fixed 4 failing workflow checks:
1. **Build/Lint/Test workflows**: Fixed yarn install authentication
- Changed Git URL rewrite to include GITHUB_TOKEN in all rewrites
- Added GITHUB_TOKEN and GIT_TERMINAL_PROMPT env vars to yarn install step
- Now correctly handles github: dependencies (like libsignal)
2. **PR Comment workflow**: Fixed missing token error
- Changed from secrets.PERSONAL_TOKEN to secrets.GITHUB_TOKEN
- Workflow now has proper authentication
Root cause: Yarn 4.x was trying to clone github: dependencies via SSH,
but CI had no SSH keys. Git config now rewrites ALL GitHub URLs to
HTTPS with token authentication.
https://claude.ai/code/session_015R3U3kiprQiNTTNNt31Sg6
Fixed timing issue in "should handle exactly 24h for LID orphan (boundary)" test
that was causing intermittent failures.
Problem:
- Test captured Date.now() at start, then cleanup.runCleanup() called Date.now() again
- Milliseconds of execution time between the two calls caused inactiveDuration to be
slightly > 24h, triggering deletion when it shouldn't
- Expected: 0 deletions, Received: 1 deletion
Solution:
- Mock Date.now() to return fixed timestamp (1700000000000)
- Ensures inactiveDuration is exactly 24h throughout test execution
- Properly restore original Date.now() in finally block
Result:
✅ All 583 tests now passing (100%)
✅ Boundary test no longer flaky
https://claude.ai/code/session_015R3U3kiprQiNTTNNt31Sg6
This commit implements a permanent fix for the proto extraction process to handle
WhatsApp's recent changes where they mark certain fields as "required" in their
JavaScript metadata.
Changes:
1. proto-extract/index.js:
- Added automatic conversion of 'required' to 'optional' after proto generation
- Proto3 spec doesn't support 'required' keyword (only proto2 does)
- All fields in proto3 are implicitly optional by default
2. WAProto/WAProto.proto:
- Updated to WhatsApp version 2.3000.1033472679 (latest)
- All 27 'required' fields converted to 'optional'
- Now compiles successfully with protoc
3. WAProto/index.d.ts & index.js:
- Regenerated with correct proto3 syntax
- index.d.ts now has 14,572 lines (was 2 lines when broken)
- Full TypeScript definitions restored
Impact:
- ✅ Build now succeeds (was failing with proto3 required error)
- ✅ Tests: 582/583 passing (99.8%)
- ✅ Lint: 0 errors, 239 warnings
- ✅ Future proto updates will auto-fix 'required' fields
Technical details:
WhatsApp Web still uses proto3 but now marks certain fields as "required" in their
JS metadata. The extractor was copying these flags directly, causing invalid proto3
syntax. This fix ensures all 'required' keywords are converted to 'optional' after
extraction, maintaining proto3 compliance.
https://claude.ai/code/session_015R3U3kiprQiNTTNNt31Sg6
Fixed compatibility issue with lru-cache v11 which requires maxSize instead of max when using sizeCalculation.
Progress: Reduced test failures from 33 to 7 tests (79% improvement)
- Fixed all cache-utils tests
- Fixed 1 baileys-event-stream test
- Remaining 7 failures are pre-existing issues
https://claude.ai/code/session_015R3U3kiprQiNTTNNt31Sg6