Engine pluggability and plugin extensibility. OpenWA can now run on a second, browser-free WhatsApp engine
(Baileys) as a peer to whatsapp-web.js, and bot-shaped features can ship as first-party extension plugins
on a scoped capability layer instead of living in core (#265).
⚠️ Breaking (plugin API):
PluginContext.getServiceis removed. It was a stub returningundefined
with no real consumers; out-of-tree plugins must migrate to the newctx.messages/ctx.engine
capabilities.
Added
- Baileys engine (
ENGINE_TYPE=baileys) — a second, browser-free WhatsApp engine built on
@whiskeysockets/baileys(WebSocket/Noise protocol, no Chromium), selectable as a peer to the default
whatsapp-web.js engine. It supports linking (QR + pairing code); sending text, media
(image/video/audio/document/sticker), location, and contacts; reply / forward / react /
delete-for-everyone; full group management (create, participants, subject/description, invite codes),
profile pictures, and block/unblock; contacts, chats, and read receipts; and receiving messages with
their media, captions, location, quoted context, reactions, and remote deletes. URL media is fetched
through the same SSRF-guarded path as the default engine. Reply/forward/react/delete are backed by a
per-session persisted message store (baileys_stored_messages, bounded byBAILEYS_MESSAGE_STORE_LIMIT,
default 5000; cleared on logout; CASCADE-deleted with its session).getChatHistoryand
labels/channels/status/catalog remain unsupported (HTTP 501) — Baileys has no on-demand history API, and
the rest are parity with the whatsapp-web.js engine. Config:BAILEYS_AUTH_DIR(default./data/baileys);
proxy is not yet supported on this engine. The engine loads lazily (dynamicimport()only when
selected), so default-engine operators are unaffected and there is no global Node version floor.
(#299, #307, #308, #309, #310, #312) - Plugin capability layer (Tier-2 extension plugins): scoped
ctx.messages(sendText/reply,
routed throughMessageServiceso persistence and the send pipeline are preserved) and read-only
ctx.engine(getGroupInfo/getContacts/getContactById/checkNumberExists/getChats) on
PluginContext, replacing the stubbedgetService. A manifest-declaredsessionsscope is enforced at
the facade before any engine access (default['*']), and a capability call to a dead/unstarted session
fails withPluginCapabilityErrorinstead of a raw error. (#294) HookManagerre-entrancy guard (AsyncLocalStorage): a plugin that sends from inside a hook handler
can no longer recurse into the same event (synchronous re-entry; the asyncmessage:sentecho loop is
documented as out of scope for now). (#294)auto-replyreference extension plugin, first-party and registered disabled by default — enable
it viaPOST /plugins/auto-reply/enableto exercise the capability layer end-to-end. (#294)- Group auto-translation extension plugin — a first-party, disabled-by-default plugin that
auto-translates incoming group messages via LibreTranslate, built entirely on the new capability layer
(supersedes the earlier in-core approach). (#300) - Schema-driven plugin config form (dashboard): the Plugins page now renders an editable config form
for any plugin that exposes aconfigSchema(text / secret / number / boolean / enum), saved via the
existing plugin-config endpoint — previously only the engine plugin had editable fields. (#303) - Spanish (
es) dashboard locale at full parity with English. (#292)
Changed
- Engine config is now opaque per-engine:
EngineFactorypasses only engine-neutral fields
(sessionId/proxyUrl/proxyType) to an engine plugin and supplies engine-specific config (Puppeteer
for whatsapp-web.js) as a blob via the plugin context, so a non-browser engine can be added without the
factory knowing browser fields. No env-var or behavior change for existing deployments. (#296)