dsh-enhancement 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +90 -0
- package/README.md +128 -2
- package/assets/apple-touch-icon-180.png +0 -0
- package/assets/icon-1600.webp +0 -0
- package/assets/icon-192.png +0 -0
- package/assets/icon-512.png +0 -0
- package/assets/icon-maskable-512.png +0 -0
- package/cordis.patch.yml +10 -0
- package/lib/client.js +708 -0
- package/lib/control.d.ts +8 -0
- package/lib/control.d.ts.map +1 -0
- package/lib/control.js +460 -0
- package/lib/control.js.map +1 -0
- package/lib/focus.d.ts +21 -0
- package/lib/focus.d.ts.map +1 -0
- package/lib/focus.js +71 -0
- package/lib/focus.js.map +1 -0
- package/lib/gateway.d.ts +42 -0
- package/lib/gateway.d.ts.map +1 -0
- package/lib/gateway.js +714 -0
- package/lib/gateway.js.map +1 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +83 -0
- package/lib/index.js.map +1 -0
- package/lib/notify.d.ts +49 -0
- package/lib/notify.d.ts.map +1 -0
- package/lib/notify.js +378 -0
- package/lib/notify.js.map +1 -0
- package/lib/push.d.ts +37 -0
- package/lib/push.d.ts.map +1 -0
- package/lib/push.js +96 -0
- package/lib/push.js.map +1 -0
- package/lib/pwa.d.ts +26 -0
- package/lib/pwa.d.ts.map +1 -0
- package/lib/pwa.js +272 -0
- package/lib/pwa.js.map +1 -0
- package/lib/state.d.ts +136 -0
- package/lib/state.d.ts.map +1 -0
- package/lib/state.js +354 -0
- package/lib/state.js.map +1 -0
- package/lib/tls.d.ts +42 -0
- package/lib/tls.d.ts.map +1 -0
- package/lib/tls.js +265 -0
- package/lib/tls.js.map +1 -0
- package/lib/types.d.ts +94 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +2 -0
- package/lib/types.js.map +1 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +77 -3
- package/src/client/index.tsx +1170 -0
- package/src/control.ts +414 -0
- package/src/focus.ts +82 -0
- package/src/gateway.ts +733 -0
- package/src/index.ts +83 -0
- package/src/notify.ts +397 -0
- package/src/push.ts +118 -0
- package/src/pwa.ts +276 -0
- package/src/state.ts +453 -0
- package/src/tls.ts +299 -0
- package/src/types.ts +104 -0
package/README.en.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# dsh-enhancement
|
|
2
|
+
|
|
3
|
+
DSH enhancement suite: a standalone **password gateway** for DSH Web, plus **PWA install/icons**, **desktop notifications**, and **PWA Web Push**. Useful for exposing DSH on a LAN, adding it to a phone home screen, or reaching it remotely without the `?token=` URL printed by `dsh web`.
|
|
4
|
+
|
|
5
|
+
> Status: Phases 1–4 implemented; Phase 5 (docs/deps/cleanup) in progress. The gateway and push are disabled by default.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
The settings card is organized into expanded **Gateway / Access / PWA / Notifications** sections, each with its own save action, dirty indicator, inline feedback, and DSH `--dsw-alias-*` styling. Gateway settings, HTTPS, and listener options live in one block with a single save.
|
|
10
|
+
|
|
11
|
+
### Secure gateway
|
|
12
|
+
|
|
13
|
+
- Independent listener (default `3088`, disabled by default); configurable interface, port, password and session lifetime.
|
|
14
|
+
- scrypt password hashing; login failures are rate-limited per IP. Normal requests are not globally throttled.
|
|
15
|
+
- DSH-styled dark login page; `HttpOnly; SameSite=Strict` session cookie, `Secure` under HTTPS.
|
|
16
|
+
- Does not need DSH's `?token=`: the plugin reads the persistent signing secret from DSH `credentials` and mints a short-lived `dsh-auth-*` cookie per proxied request.
|
|
17
|
+
- Rewrites upstream Host to the DSH bind address, strips Origin, and enforces same-origin/CSRF itself — no `--trusted-host` change or `dsh-web.service` edit.
|
|
18
|
+
- HTTP + WebSocket reverse proxy; SSE is not buffered.
|
|
19
|
+
|
|
20
|
+
### HTTPS
|
|
21
|
+
|
|
22
|
+
`off`, `uploaded` (certificate chain + key), `ca` (uploaded CA signs a leaf for the listener), `selfsigned` (plugin-generated local CA; CA certificate downloadable). Private keys stay in `$DSH_HOME/profiles/<profile>/fengyifan-dsh-enhancement/tls/` (current user only). Mobile devices must trust a self-signed/private CA.
|
|
23
|
+
|
|
24
|
+
### PWA
|
|
25
|
+
|
|
26
|
+
Takes over `/manifest.webmanifest`, icons, `apple-touch-icon`, `/sw.js` and the install prompt; replaces `dsh-pwa-icon`. Default icon set: 192/512 `any`, 512 `maskable`, 1600 WebP, iOS 180. Per-platform slots can be replaced by PNG upload (192, 512, maskable 512, Apple 180). Chromium gets `beforeinstallprompt`; iOS gets a manual “Share → Add to Home Screen” hint. HTTPS is required for installation, Service Worker and push.
|
|
27
|
+
|
|
28
|
+
### Desktop notifications
|
|
29
|
+
|
|
30
|
+
Linux uses a small `notify-send --action` shim because `node-notifier@11.0.0`'s Linux backend drops actions/clicks; macOS/Windows use `node-notifier`. Clicking opens `<base>/?dsh-session=<id>`; the browser half calls `uiWorkspace.openSession(id)`. PWA notification clicks focus an existing window or post a message through the Service Worker.
|
|
31
|
+
|
|
32
|
+
Types: task complete, waiting for answer (`ask_user_question`), approval requested, approval denied, subagent finished, goal complete/blocked, background job settled (unawaited jobs only).
|
|
33
|
+
|
|
34
|
+
### PWA Web Push
|
|
35
|
+
|
|
36
|
+
`web-push` + VAPID. Subscription records and the VAPID private key live in `state.json` (current user only). HTTPS is mandatory; iOS/iPadOS 16.4+ requires the app to be installed on the Home Screen, and permission must be requested from a user gesture. The settings card offers subscribe/unsubscribe/test and shows permission/subscription state.
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
From npm:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
dsh plugin --profile web add dsh-enhancement
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The bundle patch inserts the plugin row and also inserts `dsh-web-mobile` and `dsh-vertical-layout`; do **not** enable those two bundles separately.
|
|
47
|
+
|
|
48
|
+
Local development (link the source):
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
cd ~/dev/projects/github/fengyifan/dsh-plugins
|
|
52
|
+
pnpm --filter dsh-enhancement build
|
|
53
|
+
cd ~/.dsh/profiles/web
|
|
54
|
+
pnpm add link:../../dev/projects/github/fengyifan/dsh-plugins/packages/dsh-enhancement
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Add `dsh-enhancement` to `dsh.profile.bundles`; mobile/vertical are inserted by its patch.
|
|
58
|
+
|
|
59
|
+
## Configuration and test isolation
|
|
60
|
+
|
|
61
|
+
Runtime state lives at `$DSH_HOME/profiles/<profile>/fengyifan-dsh-enhancement/state.json` (current user only) and `tls/`. Passwords/private keys never go into the profile patch.
|
|
62
|
+
|
|
63
|
+
For multi-instance or test profiles, override the state directory:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
DSH_HOME="$HOME/.local/state/dsh-enhancement-test/home" \
|
|
67
|
+
dsh --profile enhancement-test --host 10.0.0.2 --port 3090 --no-open
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Use a separate gateway port (e.g. 3098) so the production gateway on 3088 is not taken. Host-side code changes then only require restarting the test process, not the DSH instance hosting your current session.
|
|
71
|
+
|
|
72
|
+
## Known limitations
|
|
73
|
+
|
|
74
|
+
- Linux click support depends on a notification daemon that implements actions; without `notify-send`/actions, notifications are display-only.
|
|
75
|
+
- Native click opens/focuses a browser tab; exact focus of an existing tab is handled by the PWA Service Worker path.
|
|
76
|
+
- iOS Web Push only works in an installed Home Screen web app on 16.4+; Safari tabs cannot receive push.
|
|
77
|
+
- Self-signed certificates require installing the CA on every device.
|
|
78
|
+
- Real-device iOS/Android acceptance and user-provided icon assets are still pending.
|
|
79
|
+
|
|
80
|
+
## Development
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pnpm --filter dsh-enhancement verify
|
|
84
|
+
pnpm --filter dsh-enhancement build
|
|
85
|
+
node scripts/smoke-plugin.mjs --package dsh-enhancement # from repo root
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
MIT
|
package/README.md
CHANGED
|
@@ -1,3 +1,129 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-enhancement
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**简体中文** | [English](README.en.md)
|
|
4
|
+
|
|
5
|
+
DSH 增强套件:在 DSH Web 之外提供一个**独立的密码网关**,并整合 **PWA 安装/图标**、**桌面通知**与 **PWA Web Push**。适用于把 DSH 暴露到局域网、手机主屏或远程网络,同时不依赖 DSH 启动时打印的 `?token=`。
|
|
6
|
+
|
|
7
|
+
> 状态:Phase 1–4 已实现,Phase 5(文档/依赖/清理)进行中。当前默认不启用网关、不启用 PWA 推送;先在“设置 → 插件 → dsh-enhancement”里配置。
|
|
8
|
+
|
|
9
|
+
## 功能
|
|
10
|
+
|
|
11
|
+
设置页按**网关配置 / 访问控制 / PWA / 通知**分区展开,每个配置块有独立保存按钮、未保存提示和块内保存反馈;表单使用 DSH 的 `--dsw-alias-*` 设计变量。网关配置把监听、访问与 HTTPS 收在同一块,只保留一个保存动作。
|
|
12
|
+
|
|
13
|
+
### 1. 安全访问网关
|
|
14
|
+
|
|
15
|
+
- 独立监听地址/端口(默认 `3088`,默认关闭),可配置网卡 IP、密码、会话有效期。
|
|
16
|
+
- 密码只存 scrypt 哈希;登录失败按 IP 节流(可关)。普通请求**不做全局限流**,避免误伤 DSH 的静态资源/WS/SSE。
|
|
17
|
+
- 登录页复用 DSH 深色风格;网关会话 cookie 为 `HttpOnly; SameSite=Strict`,HTTPS 下加 `Secure`。
|
|
18
|
+
- **不需要 DSH `?token=`**:插件从 DSH 的 `credentials` 服务读取持久签名密钥,每次代理请求即时签发一个短时 `dsh-auth-*` cookie 注入上游;浏览器永远看不到它。
|
|
19
|
+
- 上游 Host 改写为 DSH 绑定地址并剥离 Origin;网关自己校验同源 / `Sec-Fetch-Site` / CSRF。这样不需要修改 `dsh-web.service` 的 `--trusted-host`。
|
|
20
|
+
- 支持 HTTP 与 WebSocket(`/api/remote.mux`)反向代理;SSE 不缓冲。
|
|
21
|
+
|
|
22
|
+
### 2. HTTPS
|
|
23
|
+
|
|
24
|
+
四种模式:
|
|
25
|
+
|
|
26
|
+
| 模式 | 说明 |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `off` | 纯 HTTP(PWA 安装/推送不可用) |
|
|
29
|
+
| `uploaded` | 上传证书链 + 私钥,直接使用 |
|
|
30
|
+
| `ca` | 上传 CA 证书 + CA 私钥,由插件为当前监听地址签发 leaf |
|
|
31
|
+
| `selfsigned` | 插件生成本地 CA + leaf,并提供 CA 证书下载 |
|
|
32
|
+
|
|
33
|
+
- 私钥写入 `$DSH_HOME/profiles/<profile>/fengyifan-dsh-enhancement/tls/`(仅当前用户可读)。
|
|
34
|
+
- 自签/私有 CA 需要设备安装并信任 CA:iOS 在“设置 → 通用 → VPN 与设备管理”安装描述文件,再到“关于本机 → 证书信任设置”开启完全信任;Android 在“安全 → 加密与凭据 → 安装证书”安装。
|
|
35
|
+
- 上传证书的 SAN 必须覆盖访问地址/IP,否则浏览器会报证书错误。
|
|
36
|
+
|
|
37
|
+
### 3. PWA
|
|
38
|
+
|
|
39
|
+
- 接管 `/manifest.webmanifest`、图标路由、`apple-touch-icon`、`/sw.js` 与安装提示;取代 `dsh-pwa-icon`。
|
|
40
|
+
- 默认图标集:192/512 `any`、512 `maskable`、1600 WebP、iOS 180。
|
|
41
|
+
- 桌面/安卓/iOS 没有 OS 专用的 manifest 图标字段;效果通过 `any`(桌面)+ `maskable`(Android 自适应)+ `apple-touch-icon`(iOS,优先级最高)组合实现。
|
|
42
|
+
- Chromium/Edge 支持 `beforeinstallprompt`,页面会显示 DSH 风格的安装浮层;iOS 只能显示“分享 → 添加到主屏幕”的手动指引。
|
|
43
|
+
- PWA 安装、Service Worker、Web Push 都要求 HTTPS(localhost 例外)。
|
|
44
|
+
|
|
45
|
+
### 4. 通知(桌面 + PWA 推送)
|
|
46
|
+
|
|
47
|
+
- 原生通知通道:Linux 调用 `notify-send --action`(因为 `node-notifier@11.0.0` 的 Linux 后端不透传 actions/click),macOS/Windows 使用 `node-notifier`。
|
|
48
|
+
- 点击原生通知时优先通过 SSE 通知已打开的 DSH 页面:页面 `window.focus()` 后调用 `uiWorkspace.openSession(id)`,不再新开标签页;没有已打开页面时才回退到 `<网关或 DSH>/?dsh-session=<id>` 深链。PWA 通知仍由 Service Worker 聚焦已有窗口或打开新窗口。
|
|
49
|
+
- 通知事件(默认开启):任务完成、等待回答、等待审批、审批被拒绝、子任务结束、目标完成/受阻、后台任务结束(仅未 await 的后台任务,避免每条命令都弹)。事件勾选同时作用于桌面通知和 PWA 推送;两个渠道在设置页独立开关。
|
|
50
|
+
- 生命周期事件来自 DSH 公共事件:`agent/status`、`session/event`(`tool/call` / `approval/*`)、`subagent/end`、`goal/changed`、`jobs.events`。
|
|
51
|
+
- PWA 推送:`web-push` + VAPID;订阅记录与 VAPID 私钥存 `state.json`(仅当前用户可读)。VAPID subject 只是推送服务要求的联系方式,收在高级选项,默认值即可。
|
|
52
|
+
- PWA 推送必须 HTTPS;iOS/iPadOS 16.4+ 且必须“添加到主屏幕”,权限必须由用户点按钮触发。设置页提供“订阅本设备 / 取消订阅 / 发送测试推送”,并显示当前通知权限和订阅数。
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
## 安装
|
|
56
|
+
|
|
57
|
+
从 npm:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
dsh plugin --profile web add dsh-enhancement
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
插件行由包内 `cordis.patch.yml` 自动插入;`dsh-web-mobile`、`dsh-vertical-layout` 也由同一个 patch 一并插入,**不要**在 profile 里再重复启用这两个 bundle。
|
|
64
|
+
|
|
65
|
+
本机开发(link 源码):
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
cd ~/dev/projects/github/fengyifan/dsh-plugins
|
|
69
|
+
pnpm --filter dsh-enhancement build
|
|
70
|
+
cd ~/.dsh/profiles/web
|
|
71
|
+
pnpm add link:../../dev/projects/github/fengyifan/dsh-plugins/packages/dsh-enhancement
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
profile 的 `dsh.profile.bundles` 加入 `dsh-enhancement`;mobile/vertical 不用再单独加入。
|
|
75
|
+
|
|
76
|
+
## 配置
|
|
77
|
+
|
|
78
|
+
打开 DSH → 设置 → 插件 → `dsh-enhancement`。运行配置与秘密都在:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
$DSH_HOME/profiles/<profile>/fengyifan-dsh-enhancement/state.json # 仅当前用户可读:密码哈希、网关签名密钥、VAPID、订阅
|
|
82
|
+
$DSH_HOME/profiles/<profile>/fengyifan-dsh-enhancement/tls/ # 仅当前用户可读:证书与私钥
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
插件行本身只负责加载;`cordis.patch.yml` 不存放密码/私钥。
|
|
86
|
+
|
|
87
|
+
## 与现有入口共存
|
|
88
|
+
|
|
89
|
+
- 本插件默认监听 `3088`,与现有 `3081`(Envoy + `dsh-bootstrap`)互不影响。
|
|
90
|
+
- 浏览器原有的 `dsh-auth-*` cookie 在网关代理时会被过滤,只使用插件即时签发的短时 cookie。
|
|
91
|
+
|
|
92
|
+
## 已知限制
|
|
93
|
+
|
|
94
|
+
- `node-notifier@11.0.0` 的 Linux 后端不支持点击,所以 Linux 点击由本插件的 `notify-send` shim 实现;如果系统没有 `notify-send` 或通知守护不支持 actions,只能显示、不能点击。
|
|
95
|
+
- 原生通知点击是“打开 URL”,通常会新开/聚焦浏览器标签;精确聚焦已有标签由 PWA Service Worker 通道完成。
|
|
96
|
+
- iOS Web Push 仅 16.4+ 且必须已添加到主屏幕;Safari 标签页不能收推送。
|
|
97
|
+
- 自签证书需要每台设备安装 CA;不想装 CA 就用上传证书模式。
|
|
98
|
+
- PWA 图标上传(桌面/Android/iOS 分别替换)在资产提供后加入;当前使用包内默认图标。
|
|
99
|
+
|
|
100
|
+
## 开发与隔离测试
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
pnpm --filter dsh-enhancement verify
|
|
104
|
+
pnpm --filter dsh-enhancement build
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
不要在正在使用的 `web` profile 里反复重启 DSH 做测试。为多实例/测试隔离,本插件支持状态目录覆盖:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# 1) 建一个只加载本插件(及 base/web-app)的测试 profile,例如 ~/.dsh/profiles/enhancement-test
|
|
111
|
+
# package.json 的 dsh.profile.bundles 里放:
|
|
112
|
+
# @deepseek-ai/dsh-base, @deepseek-ai/dsh-web-app, dsh-enhancement
|
|
113
|
+
# 2) 用独立状态目录启动另一个 DSH 进程(不同端口,避免与 3080/3088 冲突)
|
|
114
|
+
DSH_HOME="$HOME/.local/state/dsh-enhancement-test/home" \
|
|
115
|
+
dsh --profile enhancement-test --host 10.0.0.2 --port 3090 --no-open
|
|
116
|
+
# 3) 测试网关用另一个端口(例如 3098),不要把生产网关的 3088 抢掉
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
状态默认放在当前 profile 目录下:`$DSH_HOME/profiles/<profile>/fengyifan-dsh-enhancement/`。`DSH_ENHANCEMENT_STATE_DIR` 仅用于特殊隔离测试,必须是绝对路径。测试 profile 的网关/密码/证书/推送订阅全部落在该目录,不会影响正在使用的 profile。测试环境应使用持久目录(例如 `~/.local/state/dsh-enhancement-test/home`),不要用 `/tmp`。
|
|
120
|
+
|
|
121
|
+
宿主侧代码变更需要重启**测试进程**(测试进程不托管当前 Agent 会话);主 `web` profile 只在最终验收时重启一次。
|
|
122
|
+
|
|
123
|
+
- 宿主半侧:`src/index.ts`、`src/gateway.ts`、`src/control.ts`、`src/tls.ts`、`src/pwa.ts`、`src/notify.ts`、`src/push.ts`。
|
|
124
|
+
- 浏览器半侧:`src/client/index.tsx`,构建为 `lib/client.js`(`scripts/build-client.mjs`)。
|
|
125
|
+
- 测试:`pnpm --filter dsh-enhancement verify`;HTTPS/证书与 PWA 路由可用临时 `DSH_HOME` 做进程内集成测试。
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# dsh-enhancement bundle patch:把本插件依赖的两个外部组件连同插件一起插入。
|
|
2
|
+
# 状态保存在当前 profile 目录下 fengyifan-dsh-enhancement/(state.json 0600)。
|
|
3
|
+
# 是否监听网关端口由设置页控制。
|
|
4
|
+
- insert:
|
|
5
|
+
- id: vertical-layout
|
|
6
|
+
name: dsh-vertical-layout
|
|
7
|
+
- id: dsh-web-mobile
|
|
8
|
+
name: dsh-web-mobile
|
|
9
|
+
- id: dsh-enhancement
|
|
10
|
+
name: dsh-enhancement
|