dsh-clean-desktop-shell 0.1.0 → 0.1.1
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/LICENSE +21 -21
- package/README.en.md +91 -91
- package/README.md +90 -90
- package/cordis.patch.yml +4 -4
- package/electron/config.js +48 -48
- package/electron/error.html +113 -0
- package/electron/main.js +6 -1
- package/electron/preload.js +14 -1
- package/electron/progress-preload.js +11 -0
- package/electron/progress.html +79 -0
- package/electron/progress.js +56 -0
- package/electron/service.js +181 -47
- package/electron/tray.js +96 -47
- package/electron/update.js +74 -74
- package/electron/window.js +179 -5
- package/lib/client.js +10 -10
- package/lib/index.js +13 -13
- package/package.json +104 -104
- package/scripts/build.mjs +12 -12
- package/scripts/gen-icons.mjs +70 -70
- package/src/client/client.js +10 -10
- package/src/host/index.js +13 -13
- package/version.txt +1 -1
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Icather
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Icather
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
CHANGED
|
@@ -1,91 +1,91 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
|
-
# dsh-clean-desktop-shell
|
|
4
|
-
|
|
5
|
-
**A clean desktop shell for DeepSeek Harness, shipped as a DSH plugin**
|
|
6
|
-
|
|
7
|
-
Does exactly one thing: wraps your already-configured DSH Web in a clean native desktop window — system tray, single instance, auto-launch, just like a normal app. No frosted glass, no fancy materials. **Clean.**
|
|
8
|
-
|
|
9
|
-
[English](README.en.md) · [中文](README.md)
|
|
10
|
-
|
|
11
|
-
[](https://github.com/Icather/dsh-clean-desktop-shell)
|
|
12
|
-
[](LICENSE)
|
|
13
|
-
[](https://github.com/Icather/dsh-clean-desktop-shell/releases/latest)
|
|
14
|
-
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
15
|
-
|
|
16
|
-
</div>
|
|
17
|
-
|
|
18
|
-
## What is this
|
|
19
|
-
|
|
20
|
-
`dsh-clean-desktop-shell` is a **DSH-plugin-shaped clean desktop shell**: it wraps an already-running DSH Web (default `http://127.0.0.1:3080`) in a native desktop window — system tray, single instance, auto-launch, so it behaves like any normal desktop app. **No visual changes at all**: no frosted glass, no skinning — purely a window shell.
|
|
21
|
-
|
|
22
|
-
Key differences from other desktop clients in the ecosystem:
|
|
23
|
-
|
|
24
|
-
| | Other desktop clients (e.g. dsh-desktop family) | This plugin |
|
|
25
|
-
|:--|:--|:--|
|
|
26
|
-
| **Form** | Standalone Electron app with its own profile | **DSH plugin** mounted into your existing profile |
|
|
27
|
-
| **Profile** | New `desktop` profile, plugins/config must be reinstalled | **Reuses your web profile**, zero migration |
|
|
28
|
-
| **Visual changes** | Custom title bar / frosted glass etc. | **None** — pure window shell |
|
|
29
|
-
| **Upstream** | Pinned version | **Tracks rc.7** |
|
|
30
|
-
|
|
31
|
-
## Architecture
|
|
32
|
-
|
|
33
|
-
```
|
|
34
|
-
┌─────────────────── Core (dsh web / headless service) ───────────────────┐
|
|
35
|
-
│ Sessions · Agent · Plugins · Memory live here, decoupled from UI │
|
|
36
|
-
└─────────────────────────────────────────────────────────────────────────┘
|
|
37
|
-
▲
|
|
38
|
-
┌───────────────┴───────────────┐
|
|
39
|
-
│ dsh-clean-desktop-shell │
|
|
40
|
-
│ Electron shell (client) │
|
|
41
|
-
│ tray · single-instance · │
|
|
42
|
-
│ auto-launch │
|
|
43
|
-
└────────────────────────────────┘
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
- **Default**: loads the local `127.0.0.1:3080` (your configured web profile, zero migration).
|
|
47
|
-
- **Remote-capable**: configure any remote DSH address; the shell is just a window. Phones / Linux / other devices can reach the core via browser or PWA — the shell is never bound to a local service.
|
|
48
|
-
|
|
49
|
-
### Platform matrix
|
|
50
|
-
|
|
51
|
-
| Platform | Shell | Status |
|
|
52
|
-
|:--|:--|:--|
|
|
53
|
-
| Windows | ✅ Electron (frameless + native window buttons) | First release target |
|
|
54
|
-
| macOS | ✅ Electron (hiddenInset) | Planned |
|
|
55
|
-
| Linux | — (browser / PWA to the core) | Not planned |
|
|
56
|
-
| Termux / phone / tablet | — (headless / PWA to the core) | Covered by remote core access |
|
|
57
|
-
|
|
58
|
-
## Install
|
|
59
|
-
|
|
60
|
-
```sh
|
|
61
|
-
dsh plugin --profile web add dsh-clean-desktop-shell
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Restart `dsh web`, then launch the shell from the tray / shortcut.
|
|
65
|
-
|
|
66
|
-
> The shell needs a reachable `dsh web` service (local or configured remote address). See Usage.
|
|
67
|
-
|
|
68
|
-
## Usage
|
|
69
|
-
|
|
70
|
-
1. Start `dsh web` (or configure a remote service address).
|
|
71
|
-
2. Launch the shell: it auto-detects local 3080; if not running it starts the service per configuration.
|
|
72
|
-
3. Drag the window by its top area (right side reserved for native buttons); close minimizes to tray by default.
|
|
73
|
-
|
|
74
|
-
## Development
|
|
75
|
-
|
|
76
|
-
```sh
|
|
77
|
-
npm install
|
|
78
|
-
npm run build # build the plugin bundle
|
|
79
|
-
npm run dev # launch the shell (dev mode)
|
|
80
|
-
npm run pack # package NSIS (Win) / DMG (mac)
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## Changelog
|
|
84
|
-
|
|
85
|
-
### 0.1.0
|
|
86
|
-
- Initial release: Electron shell skeleton, system tray / single instance / auto-launch, DSH plugin mounting.
|
|
87
|
-
|
|
88
|
-
## Credits
|
|
89
|
-
|
|
90
|
-
- [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) — the core.
|
|
91
|
-
- Architecture inspired by [Hermes Agent Desktop](https://github.com/NousResearch/hermes-agent)'s shell/core separation.
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# dsh-clean-desktop-shell
|
|
4
|
+
|
|
5
|
+
**A clean desktop shell for DeepSeek Harness, shipped as a DSH plugin**
|
|
6
|
+
|
|
7
|
+
Does exactly one thing: wraps your already-configured DSH Web in a clean native desktop window — system tray, single instance, auto-launch, just like a normal app. No frosted glass, no fancy materials. **Clean.**
|
|
8
|
+
|
|
9
|
+
[English](README.en.md) · [中文](README.md)
|
|
10
|
+
|
|
11
|
+
[](https://github.com/Icather/dsh-clean-desktop-shell)
|
|
12
|
+
[](LICENSE)
|
|
13
|
+
[](https://github.com/Icather/dsh-clean-desktop-shell/releases/latest)
|
|
14
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
## What is this
|
|
19
|
+
|
|
20
|
+
`dsh-clean-desktop-shell` is a **DSH-plugin-shaped clean desktop shell**: it wraps an already-running DSH Web (default `http://127.0.0.1:3080`) in a native desktop window — system tray, single instance, auto-launch, so it behaves like any normal desktop app. **No visual changes at all**: no frosted glass, no skinning — purely a window shell.
|
|
21
|
+
|
|
22
|
+
Key differences from other desktop clients in the ecosystem:
|
|
23
|
+
|
|
24
|
+
| | Other desktop clients (e.g. dsh-desktop family) | This plugin |
|
|
25
|
+
|:--|:--|:--|
|
|
26
|
+
| **Form** | Standalone Electron app with its own profile | **DSH plugin** mounted into your existing profile |
|
|
27
|
+
| **Profile** | New `desktop` profile, plugins/config must be reinstalled | **Reuses your web profile**, zero migration |
|
|
28
|
+
| **Visual changes** | Custom title bar / frosted glass etc. | **None** — pure window shell |
|
|
29
|
+
| **Upstream** | Pinned version | **Tracks rc.7** |
|
|
30
|
+
|
|
31
|
+
## Architecture
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
┌─────────────────── Core (dsh web / headless service) ───────────────────┐
|
|
35
|
+
│ Sessions · Agent · Plugins · Memory live here, decoupled from UI │
|
|
36
|
+
└─────────────────────────────────────────────────────────────────────────┘
|
|
37
|
+
▲
|
|
38
|
+
┌───────────────┴───────────────┐
|
|
39
|
+
│ dsh-clean-desktop-shell │
|
|
40
|
+
│ Electron shell (client) │
|
|
41
|
+
│ tray · single-instance · │
|
|
42
|
+
│ auto-launch │
|
|
43
|
+
└────────────────────────────────┘
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- **Default**: loads the local `127.0.0.1:3080` (your configured web profile, zero migration).
|
|
47
|
+
- **Remote-capable**: configure any remote DSH address; the shell is just a window. Phones / Linux / other devices can reach the core via browser or PWA — the shell is never bound to a local service.
|
|
48
|
+
|
|
49
|
+
### Platform matrix
|
|
50
|
+
|
|
51
|
+
| Platform | Shell | Status |
|
|
52
|
+
|:--|:--|:--|
|
|
53
|
+
| Windows | ✅ Electron (frameless + native window buttons) | First release target |
|
|
54
|
+
| macOS | ✅ Electron (hiddenInset) | Planned |
|
|
55
|
+
| Linux | — (browser / PWA to the core) | Not planned |
|
|
56
|
+
| Termux / phone / tablet | — (headless / PWA to the core) | Covered by remote core access |
|
|
57
|
+
|
|
58
|
+
## Install
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
dsh plugin --profile web add dsh-clean-desktop-shell
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Restart `dsh web`, then launch the shell from the tray / shortcut.
|
|
65
|
+
|
|
66
|
+
> The shell needs a reachable `dsh web` service (local or configured remote address). See Usage.
|
|
67
|
+
|
|
68
|
+
## Usage
|
|
69
|
+
|
|
70
|
+
1. Start `dsh web` (or configure a remote service address).
|
|
71
|
+
2. Launch the shell: it auto-detects local 3080; if not running it starts the service per configuration.
|
|
72
|
+
3. Drag the window by its top area (right side reserved for native buttons); close minimizes to tray by default.
|
|
73
|
+
|
|
74
|
+
## Development
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
npm install
|
|
78
|
+
npm run build # build the plugin bundle
|
|
79
|
+
npm run dev # launch the shell (dev mode)
|
|
80
|
+
npm run pack # package NSIS (Win) / DMG (mac)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Changelog
|
|
84
|
+
|
|
85
|
+
### 0.1.0
|
|
86
|
+
- Initial release: Electron shell skeleton, system tray / single instance / auto-launch, DSH plugin mounting.
|
|
87
|
+
|
|
88
|
+
## Credits
|
|
89
|
+
|
|
90
|
+
- [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) — the core.
|
|
91
|
+
- Architecture inspired by [Hermes Agent Desktop](https://github.com/NousResearch/hermes-agent)'s shell/core separation.
|
package/README.md
CHANGED
|
@@ -1,90 +1,90 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
|
-
# dsh-clean-desktop-shell
|
|
4
|
-
|
|
5
|
-
**DeepSeek Harness 的纯净桌面壳(DSH 插件形态)**
|
|
6
|
-
|
|
7
|
-
只做一件事:给已配置好的 DSH Web 加一层干净的桌面窗口——系统托盘、单实例、开机自启、像普通软件一样用。无毛玻璃、无花哨材质,**纯净**。
|
|
8
|
-
|
|
9
|
-
[English](README.en.md) · [中文](README.md)
|
|
10
|
-
|
|
11
|
-
[](https://github.com/Icather/dsh-clean-desktop-shell)
|
|
12
|
-
[](LICENSE)
|
|
13
|
-
[](https://github.com/Icather/dsh-clean-desktop-shell/releases/latest)
|
|
14
|
-
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
15
|
-
|
|
16
|
-
</div>
|
|
17
|
-
|
|
18
|
-
## 这是什么
|
|
19
|
-
|
|
20
|
-
`dsh-clean-desktop-shell` 是一个 **DSH 插件形态** 的纯净桌面壳:它给已经跑起来的 DSH Web(默认 `http://127.0.0.1:3080`)套一层原生桌面窗口——系统托盘、单实例、开机自启,像普通桌面软件一样使用。**不做任何视觉改造**:不加毛玻璃、不改界面,纯粹是"窗口壳"。
|
|
21
|
-
|
|
22
|
-
与生态里其他桌面端方案的最大区别:
|
|
23
|
-
|
|
24
|
-
| | 其他桌面端(如 dsh-desktop 系列) | 本插件 |
|
|
25
|
-
|:--|:--|:--|
|
|
26
|
-
| **形态** | 独立 Electron 应用,自带独立 profile | **DSH 插件**,挂载进现有 profile |
|
|
27
|
-
| **Profile** | 新建 desktop profile,插件/配置要重装 | **复用现有 web profile**,零迁移 |
|
|
28
|
-
| **视觉改造** | 自绘标题栏 / 毛玻璃等 | **零改造**,纯净窗口壳 |
|
|
29
|
-
| **跟随上游** | 固定版本 | **跟随 rc.7** |
|
|
30
|
-
|
|
31
|
-
## 架构
|
|
32
|
-
|
|
33
|
-
```
|
|
34
|
-
┌──────────────────── 内核(dsh web / headless 服务) ────────────────────┐
|
|
35
|
-
│ 会话 · Agent · 插件 · 记忆 都在这层,与界面解耦 │
|
|
36
|
-
└─────────────────────────────────────────────────────────────────────────┘
|
|
37
|
-
▲
|
|
38
|
-
┌───────────────┴───────────────┐
|
|
39
|
-
│ dsh-clean-desktop-shell │
|
|
40
|
-
│ Electron 壳(客户端) │
|
|
41
|
-
│ 托盘 · 单实例 · 开机自启 │
|
|
42
|
-
└────────────────────────────────┘
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
- **默认**:加载本地 `127.0.0.1:3080`(已配置好的 web profile,零迁移)。
|
|
46
|
-
- **可配远程**:在设置里填入任意远程 DSH 地址,壳只当窗口——手机 / Linux / 其他设备通过浏览器或 PWA 也能接入内核,壳本身不绑定本地服务。
|
|
47
|
-
|
|
48
|
-
### 平台矩阵
|
|
49
|
-
|
|
50
|
-
| 平台 | 壳 | 状态 |
|
|
51
|
-
|:--|:--|:--|
|
|
52
|
-
| Windows | ✅ Electron(无边框 + 原生窗口按钮) | 首发目标 |
|
|
53
|
-
| macOS | ✅ Electron(hiddenInset) | 规划中 |
|
|
54
|
-
| Linux | —(浏览器 / PWA 直连内核) | 不做 |
|
|
55
|
-
| Termux / 手机 / 平板 | —(headless / PWA 直连内核) | 由内核远程访问支持 |
|
|
56
|
-
|
|
57
|
-
## 安装
|
|
58
|
-
|
|
59
|
-
```sh
|
|
60
|
-
dsh plugin --profile web add dsh-clean-desktop-shell
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
重启 `dsh web` 后,从系统托盘/快捷方式启动桌面壳即可。
|
|
64
|
-
|
|
65
|
-
> 桌面壳需要本机有可用的 `dsh web` 服务(或配置的远程地址)。见下方「使用」。
|
|
66
|
-
|
|
67
|
-
## 使用
|
|
68
|
-
|
|
69
|
-
1. 启动 `dsh web`(或配置远程服务地址)。
|
|
70
|
-
2. 启动桌面壳:自动检测本地 3080;未运行时按配置拉起服务。
|
|
71
|
-
3. 窗口顶部(右侧留系统按钮)可拖动窗口;关闭默认缩到托盘。
|
|
72
|
-
|
|
73
|
-
## 开发
|
|
74
|
-
|
|
75
|
-
```sh
|
|
76
|
-
npm install
|
|
77
|
-
npm run build # 构建插件 bundle
|
|
78
|
-
npm run dev # 启动壳(开发模式)
|
|
79
|
-
npm run pack # 打包 NSIS (Win) / DMG (mac)
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## 更新历史
|
|
83
|
-
|
|
84
|
-
### 0.1.0
|
|
85
|
-
- 初始版本:Electron 壳骨架,系统托盘/单实例/开机自启,DSH 插件挂载。
|
|
86
|
-
|
|
87
|
-
## 致谢
|
|
88
|
-
|
|
89
|
-
- [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) —— 内核本体。
|
|
90
|
-
- 架构参考 [Hermes Agent Desktop](https://github.com/NousResearch/hermes-agent) 的壳/内核分离设计。
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# dsh-clean-desktop-shell
|
|
4
|
+
|
|
5
|
+
**DeepSeek Harness 的纯净桌面壳(DSH 插件形态)**
|
|
6
|
+
|
|
7
|
+
只做一件事:给已配置好的 DSH Web 加一层干净的桌面窗口——系统托盘、单实例、开机自启、像普通软件一样用。无毛玻璃、无花哨材质,**纯净**。
|
|
8
|
+
|
|
9
|
+
[English](README.en.md) · [中文](README.md)
|
|
10
|
+
|
|
11
|
+
[](https://github.com/Icather/dsh-clean-desktop-shell)
|
|
12
|
+
[](LICENSE)
|
|
13
|
+
[](https://github.com/Icather/dsh-clean-desktop-shell/releases/latest)
|
|
14
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
## 这是什么
|
|
19
|
+
|
|
20
|
+
`dsh-clean-desktop-shell` 是一个 **DSH 插件形态** 的纯净桌面壳:它给已经跑起来的 DSH Web(默认 `http://127.0.0.1:3080`)套一层原生桌面窗口——系统托盘、单实例、开机自启,像普通桌面软件一样使用。**不做任何视觉改造**:不加毛玻璃、不改界面,纯粹是"窗口壳"。
|
|
21
|
+
|
|
22
|
+
与生态里其他桌面端方案的最大区别:
|
|
23
|
+
|
|
24
|
+
| | 其他桌面端(如 dsh-desktop 系列) | 本插件 |
|
|
25
|
+
|:--|:--|:--|
|
|
26
|
+
| **形态** | 独立 Electron 应用,自带独立 profile | **DSH 插件**,挂载进现有 profile |
|
|
27
|
+
| **Profile** | 新建 desktop profile,插件/配置要重装 | **复用现有 web profile**,零迁移 |
|
|
28
|
+
| **视觉改造** | 自绘标题栏 / 毛玻璃等 | **零改造**,纯净窗口壳 |
|
|
29
|
+
| **跟随上游** | 固定版本 | **跟随 rc.7** |
|
|
30
|
+
|
|
31
|
+
## 架构
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
┌──────────────────── 内核(dsh web / headless 服务) ────────────────────┐
|
|
35
|
+
│ 会话 · Agent · 插件 · 记忆 都在这层,与界面解耦 │
|
|
36
|
+
└─────────────────────────────────────────────────────────────────────────┘
|
|
37
|
+
▲
|
|
38
|
+
┌───────────────┴───────────────┐
|
|
39
|
+
│ dsh-clean-desktop-shell │
|
|
40
|
+
│ Electron 壳(客户端) │
|
|
41
|
+
│ 托盘 · 单实例 · 开机自启 │
|
|
42
|
+
└────────────────────────────────┘
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- **默认**:加载本地 `127.0.0.1:3080`(已配置好的 web profile,零迁移)。
|
|
46
|
+
- **可配远程**:在设置里填入任意远程 DSH 地址,壳只当窗口——手机 / Linux / 其他设备通过浏览器或 PWA 也能接入内核,壳本身不绑定本地服务。
|
|
47
|
+
|
|
48
|
+
### 平台矩阵
|
|
49
|
+
|
|
50
|
+
| 平台 | 壳 | 状态 |
|
|
51
|
+
|:--|:--|:--|
|
|
52
|
+
| Windows | ✅ Electron(无边框 + 原生窗口按钮) | 首发目标 |
|
|
53
|
+
| macOS | ✅ Electron(hiddenInset) | 规划中 |
|
|
54
|
+
| Linux | —(浏览器 / PWA 直连内核) | 不做 |
|
|
55
|
+
| Termux / 手机 / 平板 | —(headless / PWA 直连内核) | 由内核远程访问支持 |
|
|
56
|
+
|
|
57
|
+
## 安装
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
dsh plugin --profile web add dsh-clean-desktop-shell
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
重启 `dsh web` 后,从系统托盘/快捷方式启动桌面壳即可。
|
|
64
|
+
|
|
65
|
+
> 桌面壳需要本机有可用的 `dsh web` 服务(或配置的远程地址)。见下方「使用」。
|
|
66
|
+
|
|
67
|
+
## 使用
|
|
68
|
+
|
|
69
|
+
1. 启动 `dsh web`(或配置远程服务地址)。
|
|
70
|
+
2. 启动桌面壳:自动检测本地 3080;未运行时按配置拉起服务。
|
|
71
|
+
3. 窗口顶部(右侧留系统按钮)可拖动窗口;关闭默认缩到托盘。
|
|
72
|
+
|
|
73
|
+
## 开发
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
npm install
|
|
77
|
+
npm run build # 构建插件 bundle
|
|
78
|
+
npm run dev # 启动壳(开发模式)
|
|
79
|
+
npm run pack # 打包 NSIS (Win) / DMG (mac)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 更新历史
|
|
83
|
+
|
|
84
|
+
### 0.1.0
|
|
85
|
+
- 初始版本:Electron 壳骨架,系统托盘/单实例/开机自启,DSH 插件挂载。
|
|
86
|
+
|
|
87
|
+
## 致谢
|
|
88
|
+
|
|
89
|
+
- [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) —— 内核本体。
|
|
90
|
+
- 架构参考 [Hermes Agent Desktop](https://github.com/NousResearch/hermes-agent) 的壳/内核分离设计。
|
package/cordis.patch.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# dsh bundle patch: inserts this plugin into a profile's layer stack.
|
|
2
|
-
- insert:
|
|
3
|
-
- id: clean-desktop-shell
|
|
4
|
-
name: 'dsh-clean-desktop-shell'
|
|
1
|
+
# dsh bundle patch: inserts this plugin into a profile's layer stack.
|
|
2
|
+
- insert:
|
|
3
|
+
- id: clean-desktop-shell
|
|
4
|
+
name: 'dsh-clean-desktop-shell'
|
package/electron/config.js
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shell config persistence (userData/config.json).
|
|
3
|
-
*
|
|
4
|
-
* Fields:
|
|
5
|
-
* - targetUrl: default 'http://127.0.0.1:3080' — set to any remote
|
|
6
|
-
* DSH address to run the shell as a pure window.
|
|
7
|
-
* - autoStartService: default true — only applies to the local default URL.
|
|
8
|
-
* - closeToTray: default true.
|
|
9
|
-
* - windowMode: 'advanced' (mica/vibrancy) | 'compatibility'.
|
|
10
|
-
* - autoLaunch: open at login.
|
|
11
|
-
*/
|
|
12
|
-
import { app } from 'electron'
|
|
13
|
-
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs'
|
|
14
|
-
import { dirname, join } from 'node:path'
|
|
15
|
-
|
|
16
|
-
const DEFAULTS = {
|
|
17
|
-
targetUrl: 'http://127.0.0.1:3080',
|
|
18
|
-
autoStartService: true,
|
|
19
|
-
closeToTray: true,
|
|
20
|
-
windowMode: 'advanced',
|
|
21
|
-
autoLaunch: false,
|
|
22
|
-
backendPath: null,
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
let cached = null
|
|
26
|
-
|
|
27
|
-
function configPath() {
|
|
28
|
-
return join(app.getPath('userData'), 'config.json')
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function loadConfig() {
|
|
32
|
-
if (cached) return cached
|
|
33
|
-
try {
|
|
34
|
-
const raw = readFileSync(configPath(), 'utf8')
|
|
35
|
-
cached = { ...DEFAULTS, ...JSON.parse(raw) }
|
|
36
|
-
} catch {
|
|
37
|
-
cached = { ...DEFAULTS }
|
|
38
|
-
}
|
|
39
|
-
return cached
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function saveConfig(next) {
|
|
43
|
-
cached = { ...DEFAULTS, ...next }
|
|
44
|
-
const file = configPath()
|
|
45
|
-
mkdirSync(dirname(file), { recursive: true })
|
|
46
|
-
writeFileSync(file, JSON.stringify(cached, null, 2), 'utf8')
|
|
47
|
-
return cached
|
|
48
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Shell config persistence (userData/config.json).
|
|
3
|
+
*
|
|
4
|
+
* Fields:
|
|
5
|
+
* - targetUrl: default 'http://127.0.0.1:3080' — set to any remote
|
|
6
|
+
* DSH address to run the shell as a pure window.
|
|
7
|
+
* - autoStartService: default true — only applies to the local default URL.
|
|
8
|
+
* - closeToTray: default true.
|
|
9
|
+
* - windowMode: 'advanced' (mica/vibrancy) | 'compatibility'.
|
|
10
|
+
* - autoLaunch: open at login.
|
|
11
|
+
*/
|
|
12
|
+
import { app } from 'electron'
|
|
13
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs'
|
|
14
|
+
import { dirname, join } from 'node:path'
|
|
15
|
+
|
|
16
|
+
const DEFAULTS = {
|
|
17
|
+
targetUrl: 'http://127.0.0.1:3080',
|
|
18
|
+
autoStartService: true,
|
|
19
|
+
closeToTray: true,
|
|
20
|
+
windowMode: 'advanced',
|
|
21
|
+
autoLaunch: false,
|
|
22
|
+
backendPath: null,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let cached = null
|
|
26
|
+
|
|
27
|
+
function configPath() {
|
|
28
|
+
return join(app.getPath('userData'), 'config.json')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function loadConfig() {
|
|
32
|
+
if (cached) return cached
|
|
33
|
+
try {
|
|
34
|
+
const raw = readFileSync(configPath(), 'utf8')
|
|
35
|
+
cached = { ...DEFAULTS, ...JSON.parse(raw) }
|
|
36
|
+
} catch {
|
|
37
|
+
cached = { ...DEFAULTS }
|
|
38
|
+
}
|
|
39
|
+
return cached
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function saveConfig(next) {
|
|
43
|
+
cached = { ...DEFAULTS, ...next }
|
|
44
|
+
const file = configPath()
|
|
45
|
+
mkdirSync(dirname(file), { recursive: true })
|
|
46
|
+
writeFileSync(file, JSON.stringify(cached, null, 2), 'utf8')
|
|
47
|
+
return cached
|
|
48
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'unsafe-inline'; script-src 'unsafe-inline'" />
|
|
6
|
+
<title>后端未连接</title>
|
|
7
|
+
<style>
|
|
8
|
+
html, body {
|
|
9
|
+
height: 100%;
|
|
10
|
+
margin: 0;
|
|
11
|
+
background: #10131A;
|
|
12
|
+
color: #9aa3b2;
|
|
13
|
+
font-family: system-ui, "Segoe UI", "Microsoft YaHei", sans-serif;
|
|
14
|
+
-webkit-user-select: none;
|
|
15
|
+
user-select: none;
|
|
16
|
+
}
|
|
17
|
+
.wrap {
|
|
18
|
+
height: 100%;
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
gap: 10px;
|
|
24
|
+
}
|
|
25
|
+
.whale {
|
|
26
|
+
width: 72px;
|
|
27
|
+
height: 72px;
|
|
28
|
+
border-radius: 18px;
|
|
29
|
+
background: #1b2330;
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: center;
|
|
33
|
+
font-size: 22px;
|
|
34
|
+
font-weight: 700;
|
|
35
|
+
letter-spacing: 0.5px;
|
|
36
|
+
color: #cdd3de;
|
|
37
|
+
filter: drop-shadow(0 8px 24px rgba(0, 0, 0, 0.45));
|
|
38
|
+
}
|
|
39
|
+
h2 {
|
|
40
|
+
margin: 0;
|
|
41
|
+
font-size: 17px;
|
|
42
|
+
font-weight: 600;
|
|
43
|
+
color: #e8eaf0;
|
|
44
|
+
}
|
|
45
|
+
p {
|
|
46
|
+
margin: 0;
|
|
47
|
+
font-size: 13px;
|
|
48
|
+
}
|
|
49
|
+
button {
|
|
50
|
+
padding: 9px 22px;
|
|
51
|
+
font-size: 13px;
|
|
52
|
+
color: #e8eaf0;
|
|
53
|
+
background: #232d3d;
|
|
54
|
+
border: 1px solid #33405a;
|
|
55
|
+
border-radius: 8px;
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
}
|
|
58
|
+
button:hover { background: #2b3750; }
|
|
59
|
+
button:active { background: #202a3c; }
|
|
60
|
+
.actions {
|
|
61
|
+
display: flex;
|
|
62
|
+
gap: 10px;
|
|
63
|
+
margin-top: 4px;
|
|
64
|
+
}
|
|
65
|
+
.folder-btn {
|
|
66
|
+
margin-top: 2px;
|
|
67
|
+
padding: 4px 8px;
|
|
68
|
+
font-size: 12px;
|
|
69
|
+
color: #6b7686;
|
|
70
|
+
background: none;
|
|
71
|
+
border: none;
|
|
72
|
+
border-radius: 6px;
|
|
73
|
+
text-decoration: underline;
|
|
74
|
+
}
|
|
75
|
+
.folder-btn:hover { color: #9aa3b2; background: none; }
|
|
76
|
+
.hint {
|
|
77
|
+
font-size: 12px;
|
|
78
|
+
opacity: 0.55;
|
|
79
|
+
}
|
|
80
|
+
</style>
|
|
81
|
+
</head>
|
|
82
|
+
<body>
|
|
83
|
+
<div class="wrap">
|
|
84
|
+
<div class="whale">DSH</div>
|
|
85
|
+
<h2>后端未连接</h2>
|
|
86
|
+
<p>请启动 dsh 后端,或使用下方按钮</p>
|
|
87
|
+
<button id="retry">重新加载</button>
|
|
88
|
+
<div class="actions">
|
|
89
|
+
<button id="start">启动后端</button>
|
|
90
|
+
<button id="detect">自动探测后端</button>
|
|
91
|
+
</div>
|
|
92
|
+
<button id="folder" class="folder-btn">设置后端安装文件夹</button>
|
|
93
|
+
<p class="hint">后端启动后本窗口会自动刷新</p>
|
|
94
|
+
</div>
|
|
95
|
+
<script>
|
|
96
|
+
// Injected by preload (sandbox-safe). Falls back to a plain reload.
|
|
97
|
+
var api = window.shellAPI || {};
|
|
98
|
+
document.getElementById('retry').addEventListener('click', function () {
|
|
99
|
+
if (api.reload) api.reload();
|
|
100
|
+
else location.reload();
|
|
101
|
+
});
|
|
102
|
+
var startBtn = document.getElementById('start');
|
|
103
|
+
if (api.startBackend) startBtn.addEventListener('click', api.startBackend);
|
|
104
|
+
else startBtn.style.display = 'none';
|
|
105
|
+
var detectBtn = document.getElementById('detect');
|
|
106
|
+
if (api.detectBackend) detectBtn.addEventListener('click', api.detectBackend);
|
|
107
|
+
else detectBtn.style.display = 'none';
|
|
108
|
+
var folderBtn = document.getElementById('folder');
|
|
109
|
+
if (api.chooseBackendFolder) folderBtn.addEventListener('click', api.chooseBackendFolder);
|
|
110
|
+
else folderBtn.style.display = 'none';
|
|
111
|
+
</script>
|
|
112
|
+
</body>
|
|
113
|
+
</html>
|
package/electron/main.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* The main window is a pure shell — all backend controls live in the tray.
|
|
10
10
|
*/
|
|
11
11
|
import { app, BrowserWindow } from 'electron'
|
|
12
|
-
import { createMainWindow } from './window.js'
|
|
12
|
+
import { createMainWindow, reloadWindow } from './window.js'
|
|
13
13
|
import { createTray, refreshTrayMenu } from './tray.js'
|
|
14
14
|
import { loadConfig, saveConfig } from './config.js'
|
|
15
15
|
import { detect, start } from './service.js'
|
|
@@ -89,6 +89,11 @@ if (!gotLock) {
|
|
|
89
89
|
saveConfig({ ...config, autoLaunch: enabled })
|
|
90
90
|
app.setLoginItemSettings({ openAtLogin: enabled })
|
|
91
91
|
},
|
|
92
|
+
onReload: () => {
|
|
93
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
94
|
+
reloadWindow(mainWindow, loadConfig().targetUrl || 'http://127.0.0.1:3080')
|
|
95
|
+
}
|
|
96
|
+
},
|
|
92
97
|
onQuit: () => {
|
|
93
98
|
app.isQuitting = true
|
|
94
99
|
app.quit()
|