notix-dsh
Verifiednotix-dsh · v0.3.0 · MIT · Web UI
Desktop notifications and a built-in settings UI for DeepSeek Harness, with native macOS and Windows channels.
Install
dsh plugin add notix-dsh Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Creators
Readme
Notix
为 DeepSeek Harness 提供桌面通知:agent 需要你输入、运行过久、执行出错或任务完成时,以原生 macOS / Windows 通知提醒你。一个包即可使用,无需额外 UI 包,不参与审批逻辑,不阻塞 agent。
Notix 是纯观察者:不注册审批/回答者、不向会话日志追加事件、不阻塞 agent。它只订阅共享事件面,通过可插拔的渠道注册表投递通知,内置 macOS 与 Windows 系统通知渠道。
状态:
v0.3.0—— 首个公开版本,支持 macOS 与 Windows。npm 发布状态: 包名为
notix-dsh。如果npm view notix-dsh version仍返回 404,说明该版本尚未进入 npm registry,请先按从仓库克隆安装使用。
目录
为什么选择 Notix
- 一个包,两个半。 Host 插件与 Plugins 设置界面放在同一个 npm 包里,不需要再安装第二个
notix-dsh-ui并保持版本同步。 - 纯观察者。 不代替你审批、不写入会话事件、不阻塞 agent;投递失败被隔离,不会进入 agent 执行路径。
- 两个桌面平台都是原生通知。 macOS 走通知中心(签名 Helper、
terminal-notifier、alerter或osascript),Windows 走操作中心(由随包 PowerShell 助手发送 WinRT toast)。 - 平台隔离是结构性的。 只注册与当前
process.platform匹配的渠道,因此一份 profile 配置在 macOS 与 Windows 上都可用,另一平台的工具永远不会被启动。 - 五类触发,全部可实时调整。 审批、待回答问题、长 turn 与后台任务、错误与工具失败、完成事件,都可以在设置卡片里开关,并调整阈值、重复提醒与免打扰。
- 默认克制。 去重键、按会话的错误冷却、带紧急放行的免打扰时段、按渠道重试与熔断器。
- 可扩展。 其他插件可以通过
ctx.notix发送通知、注册自己的投递渠道。
平台支持
| 平台 | 渠道 | 投递后端 | 说明 |
|---|---|---|---|
| macOS | macos-system |
已签名 Notix Helper → terminal-notifier → alerter → osascript |
通知中心;只有 Helper 使用 Notix 自己的 bundle 身份 |
| Windows 10/11 | windows-system |
由随包 PowerShell 助手发送 WinRT ToastNotification |
操作中心;使用系统自带 Windows PowerShell 5.1,无额外运行时依赖;已在 Windows 11 验证 |
| Linux 及其他平台 | —(不注册) | — | 插件可正常加载,但不注册任何渠道:通知只写入历史,投递为空操作 |
只注册 Host 所在平台的渠道,因此同一份配置文件在两端通用。两个渠道配置块都可以配置:卡片只编辑 GUI 所在平台的渠道并即时生效,另一平台的块保持不生效,也不会启动任何进程。
安装
Notix 只发布一个 npm 包 notix-dsh,其中同时包含 Node/Host 插件与浏览器/Client 界面。选择一种安装方式即可。
从 Web GUI 安装
- 打开 Web GUI,进入 插件(Plugins) 页。
- 用 添加插件(Add plugin) 安装
notix-dsh;GUI 会自动更新当前 profile 并把 bundle 加入列表。 - 重启 DSH 实例。新的 Host 插件只在进程启动时加载;GUI 重新加载后设置卡片才会出现。
从 CLI 安装
dsh plugin --profile <name> add <package> 会把剩余参数转发给 profile 目录里的 pnpm 完成安装。由于 notix-dsh 声明了 dsh.bundle,DSH 还会同步 profile 的 dsh.profile.bundles 列表并把 notix-dsh 加入其中,因此下次启动就会组装它的 patch 层。
# 桌面 App 的 profile:先退出 App(运行中的 App 会在内存里保留已加载的插件)
dsh plugin --profile desktop add notix-dsh
# Web GUI 的 profile(dsh web / 浏览器 GUI)
dsh plugin --profile web add notix-dsh
随后重启该 DSH 实例。想确认安装结果,或在使用较旧的 dsh、手动/link: 方式未能同步时自行补上,可以检查 profile manifest 是否列出了该 bundle:
// ~/.dsh/profiles/<name>/package.json
{
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"notix-dsh"
]
}
}
}
同样的命令适用于任何 profile 名(headless、自定义 profile 等):Host 半与 profile 无关,在 macOS 或 Windows 上都能从任意 profile 投递;设置卡片只出现在 GUI profile 中。
从仓库克隆安装
适用于版本尚未进入 registry,或需要本地开发插件时:
git clone https://github.com/QiangXian/notix-dsh.git
cd notix-dsh
pnpm install --frozen-lockfile
pnpm build # 生成 lib/,package.json 的入口指向该目录
# 再把当前 checkout 装进某个 profile
dsh plugin --profile web add link:/绝对路径/notix-dsh
按上文把 "notix-dsh" 加入 dsh.profile.bundles 后重启。link: 安装使用的是 checkout 里生成好的 lib/,因此拉取更新后需要重新执行 pnpm build。
包内容
发布的 npm 包只含运行时产物:由发布时 prepack 钩子生成的 lib/(lib/ 由 src/ 构建,Git 中不跟踪)、随包 assets/(通知图标与 Helper 的 .icns)、locale/、cordis.patch.yml、icon.png、中英文 README、LICENSE,以及 macOS Helper 的构建材料(scripts/build-notifier-app.sh、scripts/notifier/)。其余内容——src/、test/、docs/、dev/、构建配置和 notify-test 脚本——只存在于仓库克隆中;需要这些文件的命令在文中标注为仓库克隆。
升级
- 从 npm 升级(先退出桌面 App):
dsh plugin --profile <name> add notix-dsh@latest,然后重启实例。 - 从仓库克隆升级:
git pull && pnpm install --frozen-lockfile && pnpm build,然后重启。 - 设置会保留:配置写在 profile 的
cordis.patch.yml中id: notix条目下,启动时重新读取。 - 从双包版本迁移:如果 profile 中还有旧的独立
notix-dsh-ui包,请从 bundle 列表里移除。v0.3.0已内置 UI,已有id: notix配置保持兼容。
卸载
- 在 Web GUI 的 插件 页移除或停用 Notix;或者
- 用 CLI:
dsh plugin --profile <name> remove notix-dsh,再删除dsh.profile.bundles中的"notix-dsh",最后重启。
卸载只从 profile 中移除该包,但会留下:通知历史(Host 提供 storage domain 时位于 ~/.dsh/storages/notix)、已安装的 macOS Helper(~/Applications/Notix.app),以及 Windows 上 HKCU\Software\Classes\AppUserModelId\<appId> 下的 per-user AppUserModelId 键。如需彻底清理,请手动删除这些内容。
快速开始
- 安装并重启 DSH,然后打开 插件 → Notix(同一个卡片也在 设置 → 插件 → Notix)。
- 选择通知语言与详略程度,开关触发项,调整阈值、重复提醒与免打扰,并配置 GUI 所在平台的渠道。卡片直接修改 profile 的 patch 文件,Host 立即生效。
- 验证投递:
- 仓库克隆,macOS:
pnpm build && pnpm notify-test - 仓库克隆,Windows:
pnpm build && pnpm notify-test:win - npm 安装:这些脚本未随包发布,请改为触发真实事件(例如让 agent 发起一次审批)。
- 仓库克隆,macOS:
- macOS 上,第一条通过签名 Helper 发送的通知会请求权限:点一次 允许。

Web GUI 中的 Notix 卡片(插件 → Notix;截图来自隔离的 macOS 测试 profile,界面为中文)。
监听内容
| 通知 | 监听的表面 | 默认 | 配置项 |
|---|---|---|---|
| 审批请求 | approval/asked;未决期间按计划重复提醒,直到 approval/decided |
开 · 5 分钟后提醒,最多 2 次 | triggers.approval |
| 待回答问题 | userQuestions 投影(open 状态),continued 时可选再提醒 |
开 · 5 分钟后提醒,最多 2 次 | triggers.userQuestion |
| 长 turn | turn/start 看门狗;agent 正在等待你时延后 |
开 · 10 分钟阈值 | triggers.longTask |
| 长后台任务 | job/registered → job/settled 看门狗 |
关 · 开启后 15 分钟阈值 | triggers.longTask.jobs / jobThresholdMs |
| 运行失败 | turn/end 的错误 reason,以及 agent/error(同一去重键) |
开 · 按会话 60 秒冷却 | triggers.error |
| 工具失败 | tool/result 带 isError;TOOL_TIMEOUT 有独立开关 |
关(两个开关均关) | triggers.error.toolErrors / toolTimeout |
| turn 完成 | turn/end 且 reason 为 completed |
开 · 仅 ≥3 分钟的 turn | triggers.completion |
| 后台任务结束 | job/settled |
关 | triggers.completion.jobs |
所有通知走同一条管线:免打扰 → 去重 → 错误冷却 → 本地化渲染 → 按渠道投递。去重键按触发类型划分并保留 24 小时,因此重复事件不会反复提醒;同一会话在 triggers.error.cooldownMs 内的错误会被抑制。最近最多 200 条通知记录保存在 notix storage domain(Host 未提供 storage domain 时仅在内存中),可通过 ctx.notix.history() 读取。被免打扰、去重或冷却抑制的通知不会写入记录。
通知样式
macOS
使用 osascript 后端时,通知是标准横幅:加粗标题 + 多行正文:

macOS 会把横幅图标分配给发送进程,因此 osascript 发出的通知显示系统 脚本编辑器 图标——这是预期行为,不是 Notix 的问题:
![]()
安装 terminal-notifier,或按在 macOS 上启用鲸鱼图标构建签名 Helper,即可改为显示 Notix 鲸鱼图标。
Windows

操作中心原生 toast,归属显示为 Notix 并带鲸鱼图标:加粗标题、最多三行正文,可选声音与点击跳转。
投递机制
一个包,两个运行时入口
manifest 同时声明 dsh.bundle.patch 与 dsh.client,因此一次安装即可提供两半:
lib/index.js是 Node/Host 入口:触发规则、渠道注册表、历史、配置与ctx.notix服务。lib/client.js是浏览器入口:插件页与「设置 → 插件」中的 Notix 卡片。cordis.patch.yml只插入一个 Loader 条目id: notix。该条目加载 Host 半,同时让 Client 加载器发现本包的dsh.client声明。
两半各自保留运行时生命周期,合并的只是打包与安装方式。
渠道注册表
投递适配器注册在 ChannelRegistry 中,会收到管线产生的每一条通知。对每个适配器,注册表为单次尝试设置 10 秒超时,失败后最多重试 3 次(退避 1 秒 / 5 秒 / 15 秒),连续 3 次投递失败后打开 5 分钟的熔断器。失败只写日志,不会抛进 agent 执行路径。
平台选择是数据驱动的:BUILTIN_CHANNELS 把 darwin → macos、win32 → windows,只注册与当前 Host 平台匹配且 enabled 为开的条目。在卡片中修改渠道设置会重新注册适配器,因此声音与点击跳转的改动立即生效。新增平台 = 一个新模块 + 一个 BUILTIN_CHANNELS 条目,检查清单见开发指南。
macOS 后端
渠道只探测一次后端并缓存结果(探测失败不会缓存,下次通知会重试):
| # | 后端 | 选用条件 | 横幅图标 | 点击跳转 | 声音 |
|---|---|---|---|---|---|
| 1 | Notix Helper(~/Applications/Notix.app,或 channels.macos.notifierApp) |
Helper 可执行文件存在 | Notix 鲸鱼图标,归属显示为 Notix | 不支持 | default / silent |
| 2 | terminal-notifier |
在 PATH 中 |
通过 -appIcon 使用随包鲸鱼图标 |
clickToOpen 与 baseUrl 均有效时传 -open <baseUrl> |
-sound default |
| 3 | alerter |
在 PATH 中 |
无 | 不支持 | --sound default |
| 4 | osascript |
始终可用 | 脚本编辑器 | 不支持 | Glass,或静音 |
选中的后端失败时不会自动降级到下一个后端:请修复日志中的错误,或移除该后端,让探测选中下一个。
在 macOS 上启用鲸鱼图标
macOS 只允许有有效代码签名的 App 申请通知权限;ad-hoc 签名或未签名 App 会在弹出授权框之前就被拒绝(requestAuthorization 返回 denied)。用真实签名身份构建随包 Helper:
# 在仓库克隆中
NOTIX_SIGN_IDENTITY="Apple Development: 你的名字 (TEAMID)" \
./scripts/build-notifier-app.sh --install
# 从 npm 安装的包中
cd "$(node -p "require.resolve('notix-dsh/package.json')" | sed 's#/package.json##')"
NOTIX_SIGN_IDENTITY="Apple Development: 你的名字 (TEAMID)" \
./scripts/build-notifier-app.sh --install
- 构建需要 Xcode Command Line Tools(
swiftc)。脚本会自行解析根目录,因此在任何目录下执行sh node_modules/notix-dsh/scripts/build-notifier-app.sh --install也可以。 - 默认先把中间产物写到包内的
build/Notix.app,再由--install复制到~/Applications/Notix.app——除非channels.macos.notifierApp覆盖,否则渠道查找的就是这个路径。想直接构建到该路径、避免写入node_modules,可设置NOTIX_APP_OUTPUT="$HOME/Applications/Notix.app"并省去--install。 - 只有 Helper 的可执行文件存在时才会使用它;否则依次回退到
terminal-notifier、alerter、osascript。 - 首条通知时点 允许,之后横幅左侧即为 Notix 鲸鱼图标。
- 没有证书时脚本会退回 ad-hoc 签名并打印警告。macOS 会拒绝 ad-hoc Helper 的通知授权,因此只要该 Helper 已安装并被选中,投递就会失败:请用有效签名重新构建,或删除
~/Applications/Notix.app,让其他后端被选中。 - 安装
terminal-notifier也能在不用 Helper 的情况下显示随包鲸鱼图标;osascript无法更换图标。Helper 的构建材料随 npm 包发布,因此 npm 安装同样可以构建。
Windows toast 细节
内置 windows-system 渠道通过 Windows PowerShell 与 WinRT Toast API 发送原生 toast。Host 在 Windows 上运行时自动注册该渠道;macOS 上不注册 Windows 渠道,Windows 上也不注册 macOS 渠道,因此一份共享配置是安全的。
Toast 助手的工作方式
Host 以无 shell 方式启动 %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe,运行随包助手:
powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File <包内路径>/lib/channels/toast.ps1
通知内容通过 NOTIX_* 环境变量传递(NOTIX_TITLE、NOTIX_BODY、NOTIX_APP_ID、NOTIX_DISPLAY_NAME、NOTIX_ICON、NOTIX_URL、NOTIX_SOUND、NOTIX_TAG、NOTIX_GROUP),标题和正文不经过 shell 引号处理。脚本对所有用户文本做 XML 转义,生成 ToastGeneric toast:标题 + 最多 3 行正文(最多 4 个 <text>;正文为空时只有 1 个)。
Windows 通过 HKCU\Software\Classes\AppUserModelId\<appId> 识别未打包应用的 toast 身份。助手写入 DisplayName = "Notix",并在图标文件存在时写入随包鲸鱼图标的 IconUri,于是横幅显示 Notix 名称与图标,而不是 PowerShell 宿主。注册是幂等的:每次发送都重写相同值,不会产生重复键。可用 channels.windows.appId 与 channels.windows.icon 覆盖 id 与图标路径。
channels.windows.sound 为开时使用 ms-winsoundevent:Notification.Default,否则发送静音 toast。点击跳转通过 WinRT 协议激活实现(activationType="protocol" launch="<baseUrl>"),仅在 clickToOpen 开启且 baseUrl 非空时生效。重复通知把去重键当作 toast 的 tag/group,因此同一事件的新通知会替换旧通知。
配置
所有字段均可选,默认值开箱可用。在 profile 的 cordis.patch.yml 中、相同 entry id 下覆盖字段。设置卡片提供除 triggers.userQuestion.maxReminders、channels.macos.notifierApp 与 channels.macos.appIcon 之外的所有字段(这三项只能改 profile 文件);卡片也只编辑 GUI 所在平台的渠道。两个渠道配置块可以同时存在——只有当前平台的块会被注册和使用。
# ~/.dsh/profiles/<name>/cordis.patch.yml
- id: notix
name: notix-dsh
config:
language: zh
triggers:
longTask:
turnThresholdMs: 300000
error:
toolErrors: true
quietHours:
enabled: true
from: "23:00"
to: "08:00"
allowUrgent: true
channels:
macos:
sound: false
windows:
sound: true
clickToOpen: true
baseUrl: "http://127.0.0.1:<端口>" # 使用 `dsh web` 实际打印的地址
YAML 中的时长单位是毫秒;设置卡片里按分钟编辑。
通用
| 字段 | 默认 | 说明 |
|---|---|---|
language |
zh |
通知文案语言:zh / en。GUI 界面语言与之独立。 |
verbosity |
minimal |
minimal 正文只保留上下文;normal 还会附带截断后的错误消息。 |
触发时机
| 字段 | 默认 | 说明 |
|---|---|---|
triggers.approval.enabled |
true |
工具调用等待审批时通知 |
triggers.approval.remindAfterMs |
300000 |
审批未处理时的重复提醒间隔 |
triggers.approval.maxReminders |
2 |
单次审批的重复提醒上限(0–10) |
triggers.userQuestion.enabled |
true |
agent 向你提问时通知 |
triggers.userQuestion.remindAfterMs |
300000 |
问题未回答时的重复提醒间隔 |
triggers.userQuestion.maxReminders |
2 |
单个问题的重复提醒上限(0–10) |
triggers.userQuestion.remindOnContinued |
true |
超时问题转为 continued 时再提醒一次 |
triggers.longTask.enabled |
true |
长 turn / 后台任务看门狗 |
triggers.longTask.turnThresholdMs |
600000 |
长 turn 阈值 |
triggers.longTask.jobs |
false |
同时看门后台任务 |
triggers.longTask.jobThresholdMs |
900000 |
长后台任务阈值(jobs 开启时使用) |
triggers.error.enabled |
true |
运行失败与可选的工具失败 |
triggers.error.cooldownMs |
60000 |
按会话的错误抑制窗口 |
triggers.error.toolErrors |
false |
通知工具失败 |
triggers.error.toolTimeout |
false |
单独通知 TOOL_TIMEOUT(与 toolErrors 独立) |
triggers.completion.enabled |
true |
完成通知 |
triggers.completion.minDurationMs |
180000 |
只有不短于该时长的 turn 才播报完成 |
triggers.completion.jobs |
false |
播报已结束的后台任务 |
免打扰
| 字段 | 默认 | 说明 |
|---|---|---|
quietHours.enabled |
false |
启用免打扰时段 |
quietHours.from |
"23:00" |
时段开始(HH:MM,本地时间) |
quietHours.to |
"08:00" |
时段结束;可跨午夜,from == to 视为关闭 |
quietHours.allowUrgent |
true |
时段内放行紧急通知(审批与提问) |
渠道
| 字段 | 默认 | 说明 |
|---|---|---|
channels.macos.enabled |
true |
Host 运行在 macOS 上时注册 macOS 渠道 |
channels.macos.sound |
true |
播放通知声音 |
channels.macos.clickToOpen |
true |
在支持点击的后端上启用点击跳转 |
channels.macos.baseUrl |
"" |
点击跳转打开的 GUI 地址 |
channels.macos.notifierApp |
"" → ~/Applications/Notix.app |
签名 Helper App bundle |
channels.macos.appIcon |
"" → 随包鲸鱼图标 |
传给 terminal-notifier 的横幅图标 |
channels.windows.enabled |
true |
Host 运行在 Windows 上时注册 Windows 渠道 |
channels.windows.sound |
true |
播放默认通知声音;false 发送静音 toast |
channels.windows.clickToOpen |
true |
点击 toast 时打开 baseUrl |
channels.windows.baseUrl |
"" |
点击跳转打开的 GUI 地址;为空时 toast 不带点击动作 |
channels.windows.appId |
"" → Notix.DSH |
注册到 HKCU 并用于 toast 归属的 AppUserModelId;不匹配 [\w.-]{1,128} 时回退默认值 |
channels.windows.icon |
"" → 随包鲸鱼图标 |
用于 appLogoOverride 并注册为应用图标的 PNG |
服务接口
其他插件可以使用 ctx.notix 服务:
// 通过正常管线发送通知(免打扰、去重、渠道投递)
ctx.notix.notify({
title: '部署完成',
body: 'main 分支已绿',
urgency: 'normal', // 'urgent' | 'normal' | 'low'
sessionId: 'session-id', // 可选;默认 'manual'
dedupeKey: 'deploy:main', // 可选;默认使用唯一键
sessionTitle: 'Deploy',
})
// 注册投递渠道;同样享有重试与熔断隔离
const dispose = ctx.notix.registerChannel({
id: 'my-channel',
send: async (notification) => {
// notification:渲染后的 title/body,以及 kind、urgency、sessionId、payload
},
})
ctx.notix.history(20) // 最新在前;最多保留 200 条
ctx.notix.config // 当前生效的解析后配置
notify() 返回已记录的通知;若被管线抑制则返回 undefined。
安全与隐私
- 不参与决策。 Notix 不注册审批回答者,审批保持 fail-closed 语义;所有决策仍在 GUI 完成。
- 不碰会话日志。 只观察事件与投影,不向会话追加事件;投递失败不会阻塞或改变 agent 执行结果。
- 默认最少内容。 通知文案只包含会话标题、工具名,以及截断后的问题或原因(问题截断到 160 字;最终标题最多 120、正文最多 500)。
verbosity: normal会额外附带截断后的错误消息(最多 200 字)。命令行与文件内容永远不会进入通知。 - 纯本地。 无网络请求:投递只启动本地系统工具(
osascript、terminal-notifier、alerter、powershell.exe)。 - 失败隔离。 重试与按渠道熔断器保证一个坏后端不会影响 agent 或其他渠道。
- 本地状态。 去重键与通知历史保存在 Host 的
notixstorage domain(若提供)。Windows 渠道只写入 per-user AppUserModelId 键(DisplayName与IconUri);macOS Helper 只是~/Applications下的普通 App bundle。
常见问题
macOS
| 现象 | 排查方式 |
|---|---|
| 完全看不到横幅 | 系统设置 → 通知:为发送方 App 打开通知——Helper 是 Notix,osascript 是 脚本编辑器;并检查专注模式/免打扰 |
| 横幅显示脚本编辑器图标 | osascript 后端的预期行为;安装 terminal-notifier 或构建签名 Helper |
| 构建 Helper 后通知反而失败 | Helper 未获授权(在系统设置 → 通知中允许 Notix),或它是 ad-hoc/未签名;用有效身份重新构建,或删除 ~/Applications/Notix.app |
| 点击通知无反应 | 仅 terminal-notifier 支持点击跳转,且需要 clickToOpen: true 与非空 baseUrl |
| 没有声音 | 检查 channels.macos.sound、系统音量与免打扰;声音开启时 osascript 播放 Glass |
修改 notifierApp / appIcon 不生效 |
这两个字段只能在 profile 文件中配置(设置卡片不提供);改完 YAML 后重启 DSH |
Windows
| 现象 | 排查方式 |
|---|---|
| 完全没有 toast | Windows 设置 → 系统 → 通知:为 Notix 打开通知,并检查专注助手(Focus Assist)/免打扰 |
| 没有声音 | 即使 channels.windows.sound 为 true,Windows 也可能在全局或按应用静音通知声音 |
| 投递报 PowerShell 错误 | 需要 %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe 存在;PowerShell 缺失或安装位置异常会在 Host 日志中报错 |
| toast 能弹出但点击无反应 | 点击跳转需要 clickToOpen: true 与非空 baseUrl;协议激活也可能被系统策略或安全软件拦截 |
| 名称或图标不对 | 修正 channels.windows.appId / channels.windows.icon;下次发送会重写注册表值 |
| 重复通知替换了上一条 | 设计如此:去重键同时作为 toast 的 tag/group。需要多条并存时,通过 ctx.notix.notify() 为每条通知指定不同的 dedupeKey |
通用
- Linux 或其他平台完全没有通知:预期行为。插件会加载,但不注册渠道;Host 日志会输出
no built-in notification channel for platform "<name>"。 - 安装或升级后通知不工作:重启 DSH——Host 插件在进程启动时加载——并确认
notix-dsh同时出现在dsh.profile.bundles与 profile 的node_modules中。 - 某个渠道按配置被静音:
channels.<key>.enabled为关时,Host 日志会输出the <key> notification channel is disabled。 - 排查投递结果:storage 可用时,通知记录(含
delivered与channels)位于~/.dsh/storages/notix,也可通过ctx.notix.history()读取。delivered: false表示没有渠道接受该通知。 - 点击跳转地址:使用 GUI 实际打印的地址(
dsh web启动时会打印),不存在固定端口。
环境要求
| 要求 | 值 |
|---|---|
| DeepSeek Harness | >=0.2.1-rc.2 <0.3.0(engines.dsh) |
| Node.js | ^22.18.0 || >=24.0.0(engines.node);用于从仓库克隆构建与运行插件 |
| macOS | 通知中心;可选 terminal-notifier / alerter;显示鲸鱼图标需要签名 Helper 或 terminal-notifier |
| Windows | Windows 10/11,系统自带 Windows PowerShell 5.1(powershell.exe);已在 Windows 11 验证 |
| Linux / 其他 | 插件可加载,但不注册渠道,投递为空操作 |
开发
所有手写源码位于 src/host/(Node)与 src/client/(浏览器)。lib/ 由 node scripts/build.mjs 全量生成,已加入 .gitignore,发布时由 prepack 钩子重建。Host 模块逐字节复制;Client 由 tsdown 打成单个 classic-script factory。Windows toast 助手是 src/host/channels/toast.ps1,必须保持 ASCII-only:构建逐字节复制该文件,而 PowerShell 5.1 在无 BOM 时会按 ANSI 代码页解码脚本。
pnpm install --frozen-lockfile
pnpm build # 清理并重建完整的 lib/ 目录
pnpm build:check # 在临时目录重建并逐文件比较 lib/ 全量产物
pnpm test # 先构建,再运行单元/集成/打包测试
pnpm smoke # 校验浏览器 bundle 的模块 id 与导出契约
pnpm verify # test + smoke + 全目录可复现检查
pnpm notify-test # 仓库克隆,macOS:通过构建后的渠道发送一条真实通知
pnpm notify-test:win # 仓库克隆,Windows:通过构建后的渠道发送一条真实 toast
用入库的 overlay 模板让 DSH 直接加载本 checkout(本地副本被 Git 忽略):
cp dev/notix.patch.example.yml dev/notix.patch.local.yml
# 把 name 改成当前 checkout 中 lib/index.js 的绝对路径
pnpm build
dsh --profile web --patch ./dev/notix.patch.local.yml --dump-config
发布为手工操作:改 version,然后在干净的 checkout 中执行 pnpm publish。npm 生命周期会先跑 prepublishOnly(pnpm verify),再跑 prepack(pnpm build)然后打包,因此 tarball 总是从仓库重新构建并验证。发布文件集为运行时产物加 macOS Helper 构建材料,详见包内容。
发布用的 tarball 也做过端到端验证:对打包产物执行 dsh plugin add 会同步 bundle 列表,dsh --dump-config 能组装出 notix 条目。
统一源码结构、渠道适配器契约、DSH 模块边界、source map 保证与发布流程见开发指南。
参与贡献
欢迎在 QiangXian/notix-dsh 提交 Issue 或 Pull Request。动手前请先读贡献指南与开发指南,提交 PR 前运行 pnpm verify;请勿提交 lib/(它由 src/ 全量生成)。
版本变更记录见 CHANGELOG.md;发版由维护者按发布手册执行。安全问题请按 SECURITY.md 私下报告;所有项目空间遵循行为准则。
许可证
MIT © Notix contributors