gameswu
dsh-notifacation-frame
dsh通知消息统一管理框架
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 15, 2026
- Updated
- Aug 15, 2026
Introduction
dsh-notifacation-frame
DSH 通知框架:统一管理通知事件,允许派生插件注册自己的通知项,并在设置页为每个通知项提供配置卡片。内置了会话任务完成、agent 提问、进程崩溃与若干报错事件的通知实现。
功能
- 统一通知事件管理:所有通知项(内置 + 派生插件)走同一注册表、同一配置模型、同一投递管线(通道分发 + 历史环形缓冲)。
- 设置页配置卡片:Settings → 通知 页为每个通知项渲染一张卡片——启用开关、通道复选(网页内提示 / 系统通知 / 日志)、由字段元数据驱动的派生插件配置项、测试按钮、最近通知历史。修改热生效,无需重启。
- 派生插件支持:派生插件只需
inject: ['notificationFrame']并调用ctx.notificationFrame.register(definition);definition.fields声明的配置项由框架解析、校验、补默认后经env.config传入,配置修改时框架自动重激活(先 dispose 旧 setup,再以新配置重跑)。详见 派生插件开发指南 与 examples/dsh-notif-demo。 - 页内 toast + 系统通知 + 日志:host 经 WebSocket 推送通知到浏览器(右上角 toast 栈,点击可跳转会话);Windows / Linux / macOS 系统通知尽力而为(带冷却防刷屏);可选通知日志文件。
内置通知项
| 通知项 | 事件 | 默认通道 | 默认状态 |
|---|---|---|---|
session-complete | 会话 agent 完成任务(agent/status running→idle,可只通知顶层会话) | web | 开 |
ask-user-question | agent 调用询问问题工具(tools/result,工具名过滤,正文可带问题) | web + system | 开 |
process-crash | dsh 进程意外中止(uncaughtException / unhandledRejection / 非零退出码) | system + log | 开 |
agent-error | agent 的 step/turn 报错(agent/error) | web + log | 开 |
agent-loop-config-start-failed | 声明式 agent 启动失败 | web + system | 开 |
tool-error | 工具调用失败(tools/result isError,可按名单排除噪声工具) | web | 关(工具失败通常由模型自愈,按需开启) |
dsh-update | dsh 包新版本检查(npm registry dist-tags 对比本机安装版本,启动 + 每 24h 周期) | web + system | 开 |
报错事件的选择理由:agent/error、agent-loop/config-start-failed 直接影响任务成败,默认通知;tool-error 高频且模型通常自动重试,默认关闭;agent/request-error(单次请求失败、会重试)过于嘈杂,不接入。
安装
# 1. 构建插件模块
cd dsh-notifacation-frame
pnpm install
pnpm run build # 产出 lib/index.js(插件入口)+ lib/*.d.ts + lib/client.js(浏览器 bundle)
# 2. 将包装入目标 profile(以 web 为例)——一步完成,无需手改任何配置:
# dsh plugin 是 pnpm 转发器:安装后自动把声明了 dsh.bundle 的依赖登记进
# profile 的 dsh.profile.bundles,启动时按 bundle 顺序合并包自带的
# cordis.patch.yml(挂载行就在本仓库根目录的 cordis.patch.yml 里)
dsh plugin --profile web add "file:$(pwd)"
# 3. 重启 DSH 生效(启动日志出现 [dsh-notifacation-frame] notification framework active)
profile 自己的 cordis.patch.yml 是覆盖层,不是挂载行——只有当你需要覆盖
框架级配置(如 logFile)时才在里面按 id 重述该行:
- id: notifacation-frame
config:
logFile: /path/to/notifications.log
卸载:dsh plugin --profile web remove dsh-notifacation-frame(bundles 登记同步移除)。
配置
| 配置项 | 位置 | 默认 | 说明 |
|---|---|---|---|
| 各通知项开关 / 通道 / 派生字段 | Settings → 通知 页卡片 | 见内置表 | 热生效,写入用户设置层 |
logFile | 组合行 config | '' | 通知日志文件('' = 仅控制台) |
historyLimit | 组合行 config | 100 | 内存历史环形缓冲长度 |
systemCooldownMs | 组合行 config | 5000 | 系统通知冷却(防刷屏) |
systemTimeoutMs | 组合行 config | 8000 | 系统通知气泡展示时长 |
webSocketPath | 组合行 config | /notification-frame/ws | host→client 推送路径 |
组合行 config.* 是框架级 base 层;各通知项的用户配置存在 settings 命名空间
dsh-notifacation-frame({ items: { [id]: { enabled, channels, options } } }),
设置卡片经 Host 的 fenced JSON 路由 /notification-frame/api 读写(与
dsh-plugin-vscode-sidebar 的 /sidebar/api 同款通道:POST + {ok, value|error}
信封,信任栅栏与 /api 网关同源)。
派生插件(一分钟上手)
// 派生插件 host/plugin.ts
import type { NotifierDefinition } from 'dsh-notifacation-frame'
export const name = 'my-notifier'
export const inject = ['notificationFrame'] as string[]
const myItem: NotifierDefinition = {
id: 'my-event',
title: '我的事件',
description: '某个事件发生时提醒我。',
severity: 'info',
channels: ['web', 'system', 'log'],
defaultChannels: ['web'],
fields: [
{ key: 'minValue', label: '最小阈值', type: 'number', default: 10, min: 0, max: 100 },
{ key: 'greet', label: '问候语', type: 'string', default: 'hello' },
{ key: 'mode', label: '模式', type: 'select', options: [{ value: 'a', label: 'A' }, { value: 'b', label: 'B' }], default: 'a' },
],
setup(env) {
// env.config = { minValue, greet, mode } —— 已解析/校验/补默认,直接使用
const ctx = env.ctx as MyCtx
return ctx.on('some/event', (payload) => {
env.notify({ title: 'Something happened', body: 'value=' + payload.v })
})
},
}
export function apply(ctx: MyCtx): void {
ctx.effect(() => ctx.notificationFrame.register(myItem))
}
fields 就是派生插件的配置项:设置卡片自动渲染对应控件,用户修改后框架用新配置重跑 setup(热生效)。完整的解析规则、数据类型、生命周期与示例见 docs/derived-plugins.md 和 examples/dsh-notif-demo。
项目结构
dsh-notifacation-frame/
├── package.json # main = lib/index.js;dsh.client = web bundle
├── tsconfig.build.json # 宿主声明构建(tsc:lib/*.js + lib/*.d.ts,标准装饰器语义)
├── tsdown.config.ts # 客户端打包(lib/client.js + *.svg?raw 虚拟模块内联)
├── cordis.patch.yml # bundle 挂载层(插入框架行)
├── assets/
│ └── icons/ # 图标资源(bell-outline-16.svg 等,随包发布)
├── src/
│ ├── index.ts # 宿主打包入口(再导出 host/plugin.js 的类型与运行时面)
│ ├── shared.ts # 线缆模型:类型 + 派生配置解析(同构,纯函数)
│ ├── host/
│ │ ├── plugin.ts # 入口:Config / settings 命名空间 / fenced JSON API / WS 推送
│ │ ├── registry.ts # 通知注册表(注册、配置热生效、投递过滤、历史)
│ │ ├── channels.ts # 通道中枢(web 广播 / log 文件 / 系统通知)
│ │ ├── builtins.ts # 7 个内置通知项
│ │ ├── update-check.ts # dsh 新版本检查(semver 比较 + registry dist-tags)
│ │ ├── wire.ts # JSON API 线缆助手({ok, value|error} 信封,fenced 路由用)
│ │ ├── trust-fence.ts # WS/API 信任栅栏(回环 / --trusted-host)
│ │ └── types.ts # 宿主结构类型 + ctx.notificationFrame 增广
│ └── client/
│ └── entry.ts # 设置页卡片(settings.section)+ toast 栈(shell.overlay)+ WS 客户端
├── examples/
│ └── dsh-notif-demo/ # 派生插件完整示例(可独立安装)
├── docs/
│ └── derived-plugins.md # 派生插件开发与配置解析指南
└── tests/ # vitest:解析契约 / 注册表 / 通道 / 内置项行为 / 入口集成
构建管线与 dsh-plugin-vscode-sidebar 同源:宿主 JS 由 tsc 产出(
lib/下 与 .d.ts 并排,@Remote装饰器按标准语义编译),客户端由 tsdown 打包为 module-loader closure。
开发
pnpm install
pnpm run typecheck # 严格模式类型检查(含示例 workspace)
pnpm run build # 编译宿主 + 客户端 bundle
pnpm run test # vitest(58 个用例:配置解析、注册表热生效、通道、内置项、入口集成)
文档
许可证
MIT © 2026 gameswu