Mark each incoming WhatsApp message as read via sock.readMessages()
right after the startup-timestamp filter. Wrapped in try/catch so a
failed receipt never blocks message processing.
The Anthropic Messages API rejects tool IDs that don't match
`^[a-zA-Z0-9_-]+$` with a 400 error. Tool IDs originating from other
providers or restored multi-turn sessions can contain invalid
characters (pipes, dots). Add a deterministic _sanitize_tool_id() and
apply it to both the tool_use id and the matching tool_result
tool_use_id so the pair stays consistent.
The .gitignore already excludes desktop/ and webui/ node_modules but
not the bridge's. Add bridge/node_modules/ so the compiled bridge deps
are never accidentally committed.
Add AssemblyAI as a third transcription provider option alongside
OpenAI and Groq. AssemblyAI offers better accuracy for certain
audio types (distant voices, noisy environments) and serves as a
reliable fallback when other providers struggle.
Changes:
- Add AssemblyAITranscriptionProvider class in providers/transcription.py
- Add 'assemblyai' option in base channel's transcribe_audio()
- Per-channel configuration via transcriptionProvider in config
Usage:
Set transcriptionProvider: 'assemblyai' and provide an AssemblyAI
API key via transcriptionApiKey in the channel config.
Three improvements to the WhatsApp Baileys bridge:
1. Forwarded message detection: Extracts contextInfo.isForwarded from
all message types (text, image, video, audio, document) and passes
it as isForwarded in the InboundMessage. Allows the agent to
distinguish forwarded content from direct messages — useful for
different handling (e.g., transcribe-only vs execute as instruction).
2. Startup timestamp guard: Records the timestamp when the bridge
starts and drops any messages with messageTimestamp older than
startup time. Prevents replaying message history on reconnect,
which caused duplicate processing and stale command execution.
3. Contact message handling: Adds support for contactMessage and
contactsArrayMessage types, extracting displayName and vcard
data instead of silently dropping shared contacts.
Changes:
- Add isForwarded field to InboundMessage interface
- Add startupTimestamp guard in message processing loop
- Add contactMessage/contactsArrayMessage extraction
- Extract contextInfo.isForwarded from all media message types
- Wrap both token estimation calls in try/except to prevent silent failures
from crashing the consolidation cycle
- Add _MAX_CHUNK_MESSAGES = 60 to cap messages per consolidation round,
avoiding oversized chunks being sent to the consolidation LLM
- Improve idle log to include unconsolidated message count for easier debugging
These are purely defensive improvements with no behaviour change for
normal sessions.
The bridge's pn/sender fields don't consistently map to phone/LID
across different versions. Classify by JID suffix instead:
@s.whatsapp.net → phone number
@lid.whatsapp.net → LID (internal WhatsApp identifier)
This ensures allowFrom works reliably with phone numbers regardless
of which field the bridge populates.