Add Control UI notification controls and web push test fixes#73894
Add Control UI notification controls and web push test fixes#73894hryousafzai15 wants to merge 9 commits into
Conversation
Greptile SummaryThis PR adds a response-completion sound cue with configurable volume, a Notifications section in the Control UI combining response cues and web-push controls, and fixes repeated push notifications being coalesced by assigning unique default tags. The implementation is clean and well-tested. Two P2 concerns worth addressing before shipping:
Confidence Score: 4/5Safe to merge; both findings are P2 and affect edge-case behaviour, not correctness of the main path. Two P2 issues found (renotify coalescing edge case, AudioContext suspension). No P0/P1 defects. P2s alone cap at 4/5. ui/public/sw.js (renotify unconditional), ui/src/ui/response-completion-cue.ts (AudioContext resume) Prompt To Fix All With AIThis is a comment left during a code review.
Path: ui/public/sw.js
Line: 94
Comment:
**`renotify: true` defeats intentional tag-based coalescing**
`renotify: true` is applied unconditionally, even when the server provides an explicit `data.tag`. If a future server-side notification uses a stable tag to intentionally coalesce repeated updates (e.g., a long-running job status), `renotify: true` will re-alert the user on every replace — the opposite of coalescing behaviour. The flag is only relevant when a notification replaces another with the same tag, so scoping it to the default-tag path avoids the conflict:
```suggestion
tag: data.tag || `openclaw-notification-${Date.now()}`,
renotify: data.renotify ?? !data.tag,
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: ui/src/ui/response-completion-cue.ts
Line: 82-115
Comment:
**AudioContext may be suspended — sound silently skipped**
`new AudioContextCtor()` can start in the `"suspended"` state when there is no recent user gesture. This scenario is exactly when the cue is most useful — the user has the tab hidden or unfocused. A suspended context still lets you call `currentTime` and schedule events, but they only play once the context is running; without `resume()` the scheduled oscillators are silently dropped.
Adding a `resume()` call before reading `currentTime` fixes this:
```ts
const context = new AudioContextCtor();
// Resume in case the context was created while the page had no recent gesture.
void context.resume().catch(() => undefined);
const now = context.currentTime;
```
Because `resume()` is async, schedule notes relative to `0` (or keep the `now` reference after the promise resolves) if tight timing is needed; for a short ding at 350 ms the 1–2 ms resume latency is imperceptible.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "feat(ui): add notification controls" | Re-trigger Greptile |
|
Thanks for the context here. I swept through the related work, and this is now duplicate or superseded. Keep this PR open: it still contains useful Control UI notification work that is not on current main, but it is not merge-ready because the head is dirty against main, browser-facing proof is still insufficient, and the new persisted UI settings/default notification behavior need maintainer review before landing. Canonical path: Close this stale PR. The latest review rated it F, the branch still lacks merge-ready proof, and there has been no human follow-up after the durable review. So I’m closing this here because the remaining work is already tracked in the canonical issue. Review detailsBest possible solution: Close this stale PR. The latest review rated it F, the branch still lacks merge-ready proof, and there has been no human follow-up after the durable review. Do we have a high-confidence way to reproduce the issue? Yes for the web-push coalescing part at source level: current main uses a fixed default service-worker tag for pushes without data.tag. I did not run a live browser/audio reproduction, and the completion sound is a new capability rather than a current-main bug. Is this the best way to solve the issue? Unclear: the implementation direction is reasonable, but the dirty branch, insufficient browser proof, and open default-setting question mean it is not yet the best mergeable form. A rebased branch with real browser proof is the safer path. Security review: Security review cleared: No concrete security or supply-chain regression was found; the diff changes UI state, Web Audio cue logic, and existing service-worker notification options without adding dependencies, secrets, install hooks, or broader permissions. AGENTS.md: found and applied where relevant. What I checked:
Likely related people:
Codex review notes: model gpt-5.5, reasoning high; reviewed against e1a98171417c. |
|
Addressed the two Greptile P2 findings in
Greptile’s visible summary still appears to reference the previous commit ( Re-review progress:
|
b374cec to
99e317d
Compare
|
Friendly bump 🙏 — would be great to see this land. While waiting, I packaged the same idea as a zero-build local patch so users on
It's intentionally narrower than this PR (no settings UI, no service-worker fixes — those still need to come from #73894 proper). My Real-world feedback from running it locally for a few hours:
Happy to help if there's review bandwidth — even a "needs changes" pointer would help unblock the lane. Cc @steipete who has been moving things along on adjacent Control UI lanes. |
Local zero-build OpenClaw Control UI patch that plays a short two-tone Web Audio chime when an assistant reply finishes streaming. Stop-gap mirror of openclaw/openclaw#73894 / issue #69186. - ClawHub: https://clawhub.ai/symbolstar/echo-cue - Source: https://github.com/SymbolStar/echo-cue
|
Thanks, this is really helpful, and appreciate you packaging a temporary workaround. Good to know the final-state hook held up in real use. I will double-check the streaming and tool-heavy path for duplicate cue firing, and also think through whether the default should be always-on rather than hidden-only. Glad the patch auto-skips once this lands. This PR is intended to be the proper upstream version with settings UI and push notification fixes included. |
|
Pushed a follow-up in Changes:
Verified locally:
|
…-completion-cue # Conflicts: # ui/src/ui/app-gateway.ts # ui/src/ui/storage.ts # ui/src/ui/views/config.ts
|
This pull request has been automatically marked as stale due to inactivity. |
|
ClawSweeper applied the proposed close for this PR.
|
Summary
renotifyNotes
Notifications is a virtual Communication section because push subscription state and response cue preferences are browser/runtime UI state, not gateway config schema.
Real behavior proof
NO_REPLYfinal paths, and should not ring multiple times for the same completed run.control-ui-response-completion-cue, Node 25.8.2, focused Control UI runtime modules underui/src/ui.npm --prefix ui test -- response-completion-cue.node.test.ts app-gateway.node.test.tsNO_REPLYfinals do not cue, and repeated completion signals for the same run id dedupe to one cue. Existing app-gateway terminal event coverage still passes.AudioContextresume path plus focused cue logic tests.Test plan
corepack pnpm exec oxfmt --check ui/public/sw.js ui/src/styles/config.css ui/src/ui/app-render.ts ui/src/ui/app-view-state.ts ui/src/ui/response-completion-cue.node.test.ts ui/src/ui/response-completion-cue.ts ui/src/ui/storage.ts ui/src/ui/views/config.tscorepack pnpm exec oxlint ui/src/ui/app-render.ts ui/src/ui/app-view-state.ts ui/src/ui/response-completion-cue.node.test.ts ui/src/ui/response-completion-cue.ts ui/src/ui/storage.ts ui/src/ui/views/config.tsPATH=/tmp/corepack-shims:$PATH pnpm check:test-typescorepack pnpm exec vitest run ui/src/ui/response-completion-cue.node.test.ts ui/src/ui/app-gateway.node.test.tsPATH=/tmp/corepack-shims:$PATH pnpm ui:buildManual: