* fix(telegram): honor zero DM history while preserving replies
* fix(telegram): apply effective DM history limit end to end
* fix(telegram): keep DM history default private
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* fix(qqbot): add heartbeat-ACK liveness watchdog
The gateway sent heartbeats but never verified that op:11 ACKs arrived,
so a half-open connection (silent packet loss) stayed OPEN indefinitely
and inbound messages were lost with no status change.
Adds a counter-based watchdog: each heartbeat sent increments an
outstanding count, each op:11 resets it. When the count reaches the
missed-ACK threshold (2 unanswered sends), the socket is terminated so
handleClose -> scheduleReconnect re-establishes delivery.
ACKs are recognized synchronously in ws.on('message') before
socketMessageTail, so a slow ingress.receive() cannot mask an arrived
ACK. The raw frame is decoded/parsed once and carried as {rawData,
payload}; non-object frames are guarded to stay within the error path.
Closes#114885
* style(qqbot): oxfmt heartbeat liveness tests
* fix(qqbot): use this.ctx.log in heartbeat watchdog terminate path
handleHello has no local log binding; the overdue-ACK error log must
read this.ctx.log to match the existing GatewayConnection logging
convention and pass check-prod-types.
* chore: retrigger CI to clear stale checks
* origin/main:
fix: stop lost cancellations, false success, and stuck Codex compaction (#117902)
fix(cli): reject incomplete hosted video downloads (#117893)
refactor(board): remove duplicate in-memory store (#117353)
refactor: consolidate Teams and error helpers (#117907)
fix(msteams): cancel unread Graph error response bodies (#117664)
fix(imessage): rewind the recovery cursor when chat.db is replaced at the same path (#117788)
feat(browser): relay CDP compat for Puppeteer clients (chrome-devtools-mcp) (#117915)
* fix(imessage): rewind the recovery cursor when chat.db is replaced at the same path
A restored, rebuilt, or symlink-retargeted chat.db keeps the configured
pathname, so it keeps the same recovery-cursor identity while its rowid
sequence restarts far below the persisted high-water. Startup then seeded
since_rowid with the stale value and imsg, which emits only rows above it,
suppressed every inbound message in the replacement database, including
messages arriving after the restart.
loadIMessageRecoveryCursor now takes the startup watermark and reconciles
the stored cursor against it. A cursor above the database's current
MAX(ROWID) cannot belong to the file now at that path, so the persisted
high-water rewinds to the new watermark and the monitor tails the
replacement database instead of skipping it.
* fix(imessage): rewind the recovery cursor for an empty rebuilt chat.db
A successful MAX(ROWID) on an empty message table yields null, the same value the watermark read returns for an unreadable database, so an empty rebuilt chat.db kept the stale high-water and suppressed its first rows. Return 0 for a readable empty table and keep null for an unavailable one.
* fix(imessage): preserve first row during empty database startup
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* feat(browser): relay CDP compat for Puppeteer clients
Answer Target.getBrowserContexts with the always-empty context list so
puppeteer.connect() (chrome-devtools-mcp) can drive the paired Chrome
through the extension relay without the remote-debugging prompt. Serve
DevTools-style /json/list descriptors (id + type), which also makes the
HTTP tab-list fallback see extension-profile tabs, and add
`openclaw browser extension cdp` to print the relay endpoint and auth
header for external CDP clients.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(browser): avoid map-spread in relay target descriptors
oxc(no-map-spread): build the /json/list descriptor object explicitly
instead of spreading RelayTabInfo inside map().
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Peter Steinberger <steipete@mac-studio-sf2.local>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>