@unieai/uad-client-ui-settings-notifications
v0.1.21
Published
Notifications settings section: per-device task-completion desktop notifications and the completion sound picker
Readme
@unieai/uad-client-ui-settings-notifications
English | 中文
通知设置页,以及它所描述的行为:当一次回合在无人注视时结束,本设备会播放提示音;在浏览器已授予权限后,还会弹出一条桌面通知,点击即可打开对应会话。此页面是 UnieAI Copilot 网页产品通知设置在本地主机上的复刻,其中一块的承诺被刻意收窄——见下文这里的“推送”指什么。
该分区以 order 5 注册进设置外壳的 settings.section 插槽,位于「通用」与「模型」之间。页面展示的一切都是当前设备的事实;此处不与 Host 通信。
什么算一次任务完成
本部署没有服务端任务队列。回合运行在本地 Host 中,而客户端本就知道它何时结束:会话列表为每个会话携带 running 位,侧栏的活动圆点读取的正是它。因此一次完成就是某一行的 running→idle 边沿,由浏览器从运行时已经发布的快照中推导而来。本包不另开订阅,也不增加任何链路流量。
两条规则保证这个边沿是可信的:
- 短于
MIN_RUN_MS(2 秒)的运行不算任务。 打开会话会先把它标为运行中,直到 Host 的首个状态帧把它复位;重连也会重放同样的抖动。真实回合远比这长。 - 首个快照不触发任何东西。 页面加载时已处于空闲的会话,其结束发生在无人可被告知之时;而已经在运行的会话没有可观测的起点。
当窗口可见且该会话正是屏幕上那一个时,这次完成被视为已被注视——结束本身已经宣告过了,页面便保持安静。其余情况都会宣告。从列表中消失的会话不是完成,会被遗忘而非上报。
这里的“推送”指什么
网页产品对应的那一块标题是「推播通知」,并承诺在「背景或关闭应用时」也能送达。那是 Web Push:一个 Service Worker、一个 VAPID 签名的发送端,以及一份保存各设备订阅的服务端存储。本仓库三者皆无,而且它们也帮不上忙——本该通知你的那个东西,正是你关掉的那个进程。
桌面版真正拥有的是浏览器自带的 Notification API。Host 通过 127.0.0.1 提供页面,属于安全上下文,因此该 API 可用,窗口位于背景时弹出的通知也能进入操作系统的通知中心。这正是「启用通知」按钮所请求的东西,也正是该块文案所写的内容——去掉了「或关闭应用」一句。desktop.title 与 desktop.desc 是仅有的两条偏离网页产品词条的字符串,而偏离的方向是这个构建真正能做到的事。
权限提示只能由「启用通知」按钮的点击触达。没有用户手势的提示会被拒绝,而 Chrome 会把这次拒绝永久记在该源头上。浏览器一旦作答,该块就渲染成一句话而非控件:此页面无法撤销已授予或已封锁的权限,而一个开关不了任何东西的开关,比一句事实陈述更糟。在浏览器站点设置中撤销的权限不会通知页面,因此每当窗口重新回到前台时都会重新读取该状态。
提示音及其音频文件
十一个提示音与 unieai:notify-sound 存储键都取自网页产品,让在那边选过音效的用户在这里认得同样的名字。这项选择刻意保持按设备存储——哪种音效合适取决于机器的扬声器与摆放位置——因此它落在 localStorage,而不是同步设置里。点击一个音效即同时选中并试听;选择器没有单独的试听控件。
音频由 Web 外壳从 apps/web/public/sounds/notify/<id>.wav 提供,并由 dsh-host-frontend-static 标注为 audio/wav。本包只负责命名:它不持有任何字节,缺少音频文件的构建仍可工作,只是没有声音。
十一个名字取自网页产品,音频则不是。每个音频都是为本仓库从零合成的——叠加的正弦分音、频率滑音,rattle 还用了经过滤波的伪随机噪声,每一个都由几毫秒的起音与指数衰减包络塑形,因此既不爆音也不惊人。没有任何录音或采样,所以这套音效是本仓库的原创作品,随仓库以 MIT 发布,无需写入 THIRD_PARTY_NOTICES.md。它们是单声道 16 位 44.1 kHz WAV,时长 0.34 秒到 1.00 秒,峰值不高于 -6 dBFS。
只要完成未被注视,无论通知是否获授权,提示音都会播放——这是本页中无需向浏览器索取任何东西的那一半。播放尽力而为:自动播放策略会在页面尚未被交互前拒绝,被拒绝或缺失的音频会被吞掉而非上报。
Model Experience
无:本包渲染设置界面并响应客户端列表边沿,此处不触达任何模型请求。
KV Cache effect
无;本包既不组装也不发送供应商请求。
Known Limitations and Deferred Work
- 没有 Web Push,也没有从这里通往它的路径——通知只在页面开着时送达,无论是否位于背景。要恢复网页产品「或关闭应用」的承诺,需要 Service Worker、一对 VAPID 密钥、Host 侧的订阅存储以及发送端;本仓库均无,而且发送端必须活得比用户关掉的那个进程更久。
- 提示音是合成音,而非设计过的音频——这十一个音频是生成的波形,而不是声音设计师的作品,听起来比商业音效朴素。它们经由测量验证:时长、峰值电平、响度、无削波,以及两两之间的频谱区分度;而不是在各类扬声器上试听验证,因此它们在一台笔记本上能否传遍一个房间尚未测试。它们还以未压缩形式发布,整套约 660 kB,因为本仓库的工具链没有音频编码器;要改用压缩音频得先引入一个。
- TUI 中没有任何完成宣告——这是一个浏览器包。在终端上通过
rabi结束的回合既无通知也无提示音。 - 提示音无法关闭——选择器沿用网页产品的设计:十一个音效,没有「静音」。想要完成只有视觉提示而无声音的用户,只能将标签页静音。
- 宣告没有限流——一批会话同时结束会各弹一条通知。按会话的
tag只合并同一个会话的重复通知。 - 页面错过的完成永远不会被宣告——运行位读自实时列表,因此在应用关闭期间开始并结束的回合,只会表现为加载时就已空闲的会话,而这按设计不会触发任何东西。
