github rmyndharis/OpenWA v0.10.0

latest releases: v0.23.4, v0.23.3, v0.23.2...
one month ago

Added

  • Reconnect-loop observability: every scheduled reconnect attempt is counted in the new
    openwa_session_reconnect_attempts_total Prometheus counter, and every fifth consecutive attempt
    of an episode emits a session.reconnect_loop webhook event ({ sessionId, attempts, nextDelayMs }),
    a structured warning log, and an openwa_session_reconnect_loop_alerts_total counter tick — a
    session stuck in a reconnect loop is now visible to operators instead of retrying silently forever.
    The episode streak re-arms after a stable connection, so recovered sessions do not keep alerting.
  • The whatsapp-web.js engine now sweeps orphaned Chromium processes before each (re)launch: browsers
    are started with an --openwa-session=<id> marker arg, and any leftover browser process carrying
    this session's marker from a previous process lifetime (e.g. after the gateway itself was killed)
    is terminated before the new launch, alongside the existing stale Singleton-file cleanup.
  • Messages composed on a linked phone are now persisted to local history (previously only API
    sends and inbound messages were stored). Deduplication against the REST send path is atomic on the
    existing unique message index, and delivery/read state advances via acks on these rows as well.
  • The whatsapp-web.js own-send echo now downloads media through the same capped inbound path as
    inbound messages (declared-size pre-gate, timeout, concurrency limiter), so phone-composed images
    persist and render with their real payload.
  • The dashboard gains a shared accessible modal dialog — Escape and overlay dismissal, a focus
    trap with initial focus, background scroll lock, and role="dialog" semantics. The Sessions page
    modals are the first to use it, gaining those behaviors plus a pinned header/footer with a
    scrolling body on long content.
  • The dashboard Message Tester now covers every outbound message type: in addition to
    text/image/video/audio/document it can send location, contact-card, sticker, and native poll
    messages, forward an existing message to another chat, and submit a bulk text batch (recipients
    one per line, optional inter-message delay) with live batch progress polling and a cancel control
    in the response panel.

Changed

  • Dashboard theming is simplified to a single light/dark toggle button; the accent-palette picker
    was removed for maintainability. The global h2 is a real heading
    again instead of a forced small uppercase eyebrow (section/card titles were smaller than body
    text); the eyebrow look survives as an opt-in .eyebrow class.
    The stored theme is applied before first paint, so standalone
    routes no longer flash the OS default, and the message-analytics chart now defaults to 24h.
  • The dev compose defaults AUTO_START_SESSIONS=true, so previously authenticated sessions come
    back by themselves after a container restart (the application-level default stays off).
  • Dashboard action buttons are consolidated into shared global .btn-primary/.btn-secondary/
    .btn-danger classes (28 page-scoped copies removed), so padding, radius, hover, and disabled
    states are consistent across pages; the Plugins hover now uses the --primary-hover token and
    danger buttons use the single --error red.
  • The Infrastructure page's inline-styled elements (including the restart/migration progress modal) are
    moved to scoped CSS classes, so all surfaces stay on the design-token system.
  • Decorative hover/selection effects are flattened for a more professional look: the install/config
    tab active state no longer lifts or glows, the restart progress bar is a flat primary fill instead
    of a gradient, and the emoji-picker button no longer scales on hover.

Removed

  • Verified dead dashboard code: unused CSS across multiple pages, dead client methods and utilities,
    unused image assets, and 39 unused i18n keys across all locales.
  • Verified-unused dashboard i18n keys (19 per locale across all 11 locales): dead common.*
    vocabulary and page-specific keys with zero references in the app.

Fixed

  • Boot no longer warns about (and the plugin list no longer shows) ghost entries for the legacy
    bundled extensions removed in v0.7 (auto-reply, translation): when their code directory has no
    manifest, the stale registry entry is pruned at startup. The guard is scoped to those known ids so
    a temporarily unreadable plugin directory never loses its persisted config.

  • Long-lived sessions no longer die permanently after hours of uptime. A dead whatsapp-web.js
    Chromium (browser process exit, renderer crash, or closed page) is now detected through the
    puppeteer lifecycle handles and driven through the standard disconnect → reconnect pipeline, and
    a session watchdog probes READY engines every 60 seconds, treating two consecutive liveness-probe
    failures as a disconnect. The reconnect budget is now unlimited by default (exponential backoff
    capped at 1 hour, counter reset after 5 stable minutes) instead of a terminal failure after 5
    attempts; explicit maxReconnectAttempts (0 = disabled, clamped to 1–20) is unchanged. On the
    Baileys engine, connectionReplaced (440) is now terminal instead of fighting the other instance,
    duplicate close events no longer burn retry attempts, and a failed reconnect attempt no longer
    fails the session.

  • Harden session stability further: the Baileys engine now treats forbidden (403, banned/blocked
    account) as terminal instead of retrying forever; stale Chromium SingletonLock/SingletonSocket/
    SingletonCookie files are removed before each whatsapp-web.js (re)launch so a previously
    force-killed browser can never block startup; and page transport errors (Protocol error,
    Target closed, detached frame, …) observed during send/query operations are now treated as an
    immediate death signal, cutting dead-session detection from minutes to the first failed call.

  • Sent images no longer vanish from the chat thread: the realtime own-send echo carries no media
    payload by design, and the live cache merge replaced metadata wholesale, wiping the optimistic
    bubble's base64. Metadata now merges per field (a real payload always beats a payload-less echo
    marker), and the post-send reconciliation folds the optimistic copy into the echo row.

  • Chat thread scrolling now behaves on every path: opens at the latest message, restores the exact
    per-chat position when returning (position is saved continuously, not read after the content
    swap), and stays pinned while media decodes instead of clamping the restore to the pre-decode
    height — releasing cleanly on user scroll.

  • The messages-by-type chart no longer shows a misleading Unknown slice: rows with no body and no
    metadata (content-less system/event rows) are excluded from the aggregation.

  • Full-text search self-heals its schema at boot when migrations are skipped (DATABASE_SYNCHRONIZE=true),
    and SQLite FTS5 queries are sanitized per token, so phone numbers, chat identifiers, quotes, and
    parentheses no longer fail as malformed queries.

  • Audit log rows now carry the resolved API key and client IP for every call site: the values are
    stamped into the per-request async context by the auth guard and auto-filled on write (explicit
    context still wins).

  • Dashboard CSS no longer references undefined custom properties or fallbacks from a foreign
    design system: every danger/danger-color usage now resolves to the single --error token, wrong
    --primary/--text-secondary/--border/--warning fallbacks are dropped, and the plugin
    instances "off" badge shows its background again (it referenced an undefined --bg-secondary).

  • Dashboard readability and behavior: the send button stays readable when disabled, API Keys badges
    render on desktop (rules were stranded in a mobile-only media query), the Templates page gets real
    primary/secondary button styles, fourteen dark-mode selectors are corrected so dark mode applies,
    Sessions modals regain the 90vh cap with a scrolling body, QR provisioning uses the realtime push
    with fetching gated to qr_ready (no more expected-but-noisy 400 console errors), and enabling a
    plugin with unset required config opens its config dialog with a warning instead of failing with a
    raw sandbox error.

  • Plugins whose config schema declares field defaults no longer fail to enable with those values
    missing: defaults are now seeded into the stored config at load time (fresh installs and every
    boot), without ever overwriting explicit values. Required fields without a declared default still
    need real operator input.

Don't miss a new OpenWA release

NewReleases is sending notifications on new releases.