@canary-builds/dsh-wpa 1.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/CHANGELOG.md +14 -0
- package/LICENSE +21 -0
- package/README.md +67 -0
- package/cordis.patch.yml +10 -0
- package/lib/client.js +171 -0
- package/lib/index.js +40 -0
- package/package.json +60 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.1.0 — 2026-09-06
|
|
4
|
+
|
|
5
|
+
- Rename the project to DSH WPA and the package to `@canary-builds/dsh-wpa`.
|
|
6
|
+
- Move the repository to `Canary-Builds/dsh-wpa`.
|
|
7
|
+
- Add a Profile Bundle patch for one-command installation.
|
|
8
|
+
- Update browser module registration to match the scoped package name.
|
|
9
|
+
- Add contract checks, package validation, version-aware npm publishing and GitHub release assets.
|
|
10
|
+
- Preserve Splash's mobile and standalone-window UI behavior.
|
|
11
|
+
|
|
12
|
+
## 1.0.2 and earlier
|
|
13
|
+
|
|
14
|
+
Published as `dsh-plugin-splash`. Historical Git tags are preserved.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mareekkk
|
|
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.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# DSH WPA
|
|
2
|
+
|
|
3
|
+
A mobile/PWA-first UI redesign for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH) web GUI, delivered as one Cordis plugin with a host half and a browser half. minimal, app-like: the sidebar gets out of your way, the reading area wins, and the app installs as a proper standalone window.
|
|
4
|
+
|
|
5
|
+
Everything visual is scoped to app windows and touch devices (`display-mode: standalone/fullscreen/minimal-ui`, or `hover:none` + `pointer:coarse`). **Desktop browser tabs are untouched** and render the stock UI.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
**Sidebar (app-style)**
|
|
10
|
+
- Collapsing the sidebar hides the 56px icon rail entirely — the chat area spans the full screen width
|
|
11
|
+
- A floating whale launcher (the DSH whale mark, theme-following) appears centered in the first column's header band; click to expand
|
|
12
|
+
- Expanding opens the sidebar as a **fullscreen overlay** covering the chat instead of pushing it
|
|
13
|
+
- Opening a session from the list **auto-collapses** the sidebar (workspace group rows and row menus are ignored)
|
|
14
|
+
|
|
15
|
+
**Top bar**
|
|
16
|
+
- Title row spans the full width; tab row (Chat / Trajectory) gains two right-aligned controls: the agent-preset mode chip (abbreviated to `STD` / `PTC` / `MIN` / `CTR`, en+zh) and the session-log export as a bare icon-only button
|
|
17
|
+
|
|
18
|
+
**Settings**
|
|
19
|
+
- The settings sheet fills the entire screen (no margins, no radius)
|
|
20
|
+
- Section nav collapses to an icon-only rail (labels stay in the accessibility tree)
|
|
21
|
+
- Picker rows (Permission / Agent preset / Enter behavior): selector on top full-width, description filling the area below
|
|
22
|
+
|
|
23
|
+
**Chat area**
|
|
24
|
+
- Side padding reduced (32px → 12px left / 6px right), reserved scrollbar gutter removed
|
|
25
|
+
- User bubbles: fit-content size, right-anchored, uncapped width (extend all the way left when long), square right corners, overflow-safe
|
|
26
|
+
|
|
27
|
+
**PWA**
|
|
28
|
+
- Host route serves a standalone-window manifest (`display: standalone` + `display_override`), so the GUI installs as a real app window — the Android notification bar stays visible (the shipped manifest uses `fullscreen`, which hides it)
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
Requires Node.js 22.19+ and DeepSeek Harness. Install into your web profile:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
dsh plugin --profile web add @canary-builds/dsh-wpa
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Restart DSH and refresh the browser. To update, run the same command again and restart. The package includes its Profile Bundle patch and prebuilt browser module; no separate installer, build, or manual composition row is needed for a fresh install.
|
|
39
|
+
|
|
40
|
+
### Migrating from Splash
|
|
41
|
+
|
|
42
|
+
This is the successor to `dsh-plugin-splash` in the renamed `Canary-Builds/dsh-wpa` repository. Remove the old `splash` row that names `dsh-plugin-splash` from your profile's `cordis.patch.yml`, then run:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
dsh plugin --profile web remove dsh-plugin-splash
|
|
46
|
+
dsh plugin --profile web add @canary-builds/dsh-wpa
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Restart DSH. Keep other profile overrides intact. Do not load both packages together; both own the same UI behavior and manifest route. GitHub redirects the previous repository URL, but npm package names do not redirect automatically.
|
|
50
|
+
|
|
51
|
+
## Compatibility
|
|
52
|
+
|
|
53
|
+
The redesign is implemented as scoped CSS keyed off the shipped UI's DOM: stable public attributes (`data-sidebar-collapsed`, `data-details-collapsed`, slot wrappers) wherever possible, plus CSS-module class hashes for elements that expose nothing else. **Those hashes are build-specific** — the plugin targets the `0.1.1-rc.x` DSH web frontend and may silently no-op (never break) on a version whose bundles re-hash. If a feature stops applying after a DSH upgrade, update the hashes in `lib/client.js` (serve `/plugins/@deepseek-ai/dsh-client-ui-*/client.js` on your install and grep the new prefixes).
|
|
54
|
+
|
|
55
|
+
## Behavior notes
|
|
56
|
+
|
|
57
|
+
- The manifest override takes precedence over the dist fallback server; disabling the plugin row restores the shipped manifest on restart
|
|
58
|
+
- All effects are fiber-owned: removing the plugin row cleanly reverts every style, slot entry, listener, and route
|
|
59
|
+
- The floating launcher and auto-collapse never run in desktop browser tabs
|
|
60
|
+
|
|
61
|
+
## License
|
|
62
|
+
|
|
63
|
+
MIT
|
|
64
|
+
|
|
65
|
+
## Development and releases
|
|
66
|
+
|
|
67
|
+
Run `npm test` and `npm run test:package`. See [RELEASING.md](RELEASING.md) for automated npm publication and GitHub releases. [Report an issue](https://github.com/Canary-Builds/dsh-wpa/issues) · [Canary Builds](https://canarybuilds.com).
|
package/cordis.patch.yml
ADDED
package/lib/client.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// Client half of @canary-builds/dsh-wpa: app-style collapsed sidebar.
|
|
2
|
+
// Graduated from dynamic plugin whale-1/pkg-1. Hand-written static client
|
|
3
|
+
// module in the served ModuleLoader format (identical to the shipped
|
|
4
|
+
// bundles): window.__ModuleLoader__.load({ id, factory }) with require
|
|
5
|
+
// limited to the seeded externals (react, ...).
|
|
6
|
+
//
|
|
7
|
+
// Effects, all owned by this plugin's fiber:
|
|
8
|
+
// - one <style> tag (data-plugin-css) with the redesign rules;
|
|
9
|
+
// - one shell.overlay list entry ("whale-fab"): a floating whale button,
|
|
10
|
+
// top-left, visible only while the sidebar is collapsed; clicking it
|
|
11
|
+
// calls ctx.layout.toggleSidebar().
|
|
12
|
+
//
|
|
13
|
+
// The collapse redesign is pure CSS keyed off the frame's public
|
|
14
|
+
// data-sidebar-collapsed attribute (set by ui-layout's AppFrame):
|
|
15
|
+
// - [data-sidebar-collapsed]>.pI_x6G_sidebarCol -> visibility:hidden
|
|
16
|
+
// (the 56px icon rail disappears entirely);
|
|
17
|
+
// - [data-sidebar-collapsed]>.pI_x6G_centerCol -> margin-left:-56px
|
|
18
|
+
// (the chat area reclaims the full rail width);
|
|
19
|
+
// - [data-sidebar-collapsed] .wSkVaW_header -> padding-left:60px
|
|
20
|
+
// (the session title clears the floating whale);
|
|
21
|
+
// - .nL4_yW_sessionLogButton -> icon-only 32x32 pill,
|
|
22
|
+
// absolutely positioned into the header's tab row, right-aligned
|
|
23
|
+
// (the "Session log" text stays in the a11y tree, visually hidden);
|
|
24
|
+
// - .SVAs4q_label (the agent-preset mode chip) -> relocated into the
|
|
25
|
+
// same tab row, left of the download button; preset name abbreviated
|
|
26
|
+
// to three letters (STD/PTC/MIN/CTR via the label's title prefix).
|
|
27
|
+
|
|
28
|
+
window.__ModuleLoader__.load({
|
|
29
|
+
id: "@canary-builds/dsh-wpa",
|
|
30
|
+
factory: (require) => {
|
|
31
|
+
var module = { exports: {} };
|
|
32
|
+
var exports = module.exports;
|
|
33
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
34
|
+
const React = require("react");
|
|
35
|
+
|
|
36
|
+
//#region styles (one style tag per document)
|
|
37
|
+
// PWA/mobile-only: rules apply to real app windows (standalone,
|
|
38
|
+
// fullscreen, minimal-ui) AND to touch devices (phones reached via a
|
|
39
|
+
// home-screen shortcut still report display-mode browser); desktop
|
|
40
|
+
// browser tabs (hover + fine pointer + browser mode) stay stock.
|
|
41
|
+
const SCOPE = "(display-mode: standalone),(display-mode: fullscreen),(display-mode: minimal-ui),(hover:none) and (pointer:coarse)";
|
|
42
|
+
const css = "@media " + SCOPE + "{" + [
|
|
43
|
+
".whalefab-button{position:absolute;top:25.5px;left:10px;z-index:30;display:none;align-items:center;justify-content:center;box-sizing:border-box;width:36px;height:36px;padding:0;border:none;border-radius:10px;background:transparent;color:var(--dsw-alias-label-primary);cursor:pointer}",
|
|
44
|
+
".whalefab-button:hover{background:var(--dsw-alias-interactive-bg-hover)}",
|
|
45
|
+
".whalefab-button:active{background:var(--dsw-alias-interactive-bg-active)}",
|
|
46
|
+
".whalefab-button:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}",
|
|
47
|
+
".whalefab-mark{display:block;width:26px;height:26px;background-color:currentColor;-webkit-mask-image:url(/favicon.svg);mask-image:url(/favicon.svg);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center;-webkit-mask-size:contain;mask-size:contain;transform:translateY(1.7px)}",
|
|
48
|
+
".pI_x6G_centerCol{transition:margin-left var(--ds-transition-duration-slow) var(--ds-ease-in-out)}",
|
|
49
|
+
"[data-sidebar-collapsed] .whalefab-button{display:flex}",
|
|
50
|
+
"[data-sidebar-collapsed]>.pI_x6G_sidebarCol{visibility:hidden;pointer-events:none}",
|
|
51
|
+
"[data-sidebar-collapsed]>.pI_x6G_centerCol{margin-left:-56px}",
|
|
52
|
+
"[data-sidebar-collapsed] .wSkVaW_header{padding-left:50px;padding-right:0}",
|
|
53
|
+
// v3 — fullscreen sidebar: when open (and details closed), the sidebar
|
|
54
|
+
// column overlays the whole frame instead of pushing the chat; the
|
|
55
|
+
// chat keeps full width underneath.
|
|
56
|
+
".pI_x6G_frame:not([data-sidebar-collapsed])[data-details-collapsed]{grid-template-columns:0px minmax(0,1fr) 0px!important}",
|
|
57
|
+
".pI_x6G_frame:not([data-sidebar-collapsed])[data-details-collapsed]>.pI_x6G_sidebarCol{position:absolute;inset:0;z-index:15}",
|
|
58
|
+
".pI_x6G_frame:not([data-sidebar-collapsed])[data-details-collapsed]>.pI_x6G_handle[data-side=sidebar]{display:none}",
|
|
59
|
+
".pI_x6G_frame:not([data-sidebar-collapsed])[data-details-collapsed] .hHd-Xa_root{width:100%!important}",
|
|
60
|
+
".nL4_yW_sessionLogButton{min-width:0;width:32px;height:32px;padding:0;position:absolute;top:40px;right:28px;z-index:2;border:none;border-radius:0;background:transparent}",
|
|
61
|
+
".nL4_yW_sessionLogButton>span{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}",
|
|
62
|
+
// v9 — settings nav as a top tab strip: no side column, content
|
|
63
|
+
// gets the full width; tabs are icon+label, scrollable horizontally.
|
|
64
|
+
".VOzbGW_panel{flex-direction:column}",
|
|
65
|
+
".VOzbGW_nav{width:auto;flex:none;flex-direction:row;align-items:center;gap:8px;padding:10px 16px 0;border-bottom:1px solid var(--dsw-alias-border-l2)}",
|
|
66
|
+
".VOzbGW_navTitle{visibility:visible;padding:0 8px 0 4px}",
|
|
67
|
+
".VOzbGW_navList{flex-direction:row;gap:4px;flex-wrap:nowrap;overflow-x:auto}",
|
|
68
|
+
// v10 — settings tabs: icon-only cells; Close swaps to the left of
|
|
69
|
+
// the settings-document (open conf file) action via header reversal.
|
|
70
|
+
// v12b — tabs stay icon-only; the General page gains a "General"
|
|
71
|
+
// heading (styled like the Models page title) since its section
|
|
72
|
+
// ships without one.
|
|
73
|
+
".VOzbGW_navCell{height:36px;flex:none;flex-direction:row;justify-content:center;gap:0;width:40px;padding:0;border-radius:10px 10px 0 0}",
|
|
74
|
+
".VOzbGW_navLabel{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}",
|
|
75
|
+
"._WvWnq_section::before{content:\"General\";color:var(--dsw-alias-label-primary);margin:0 0 12px;font-size:20px;font-weight:500;line-height:28px;display:block}",
|
|
76
|
+
// v11 — header row (open conf, then close at the far right) above
|
|
77
|
+
// the tab strip: content's children become direct panel items via
|
|
78
|
+
// display:contents.
|
|
79
|
+
".VOzbGW_content{display:contents}",
|
|
80
|
+
".VOzbGW_header{order:1}",
|
|
81
|
+
".VOzbGW_nav{order:2}",
|
|
82
|
+
".VOzbGW_options{order:3}",
|
|
83
|
+
// v6 — settings modal fills the entire screen: no margins, no radius.
|
|
84
|
+
".VOzbGW_panel{width:100vw;max-width:100vw;height:100vh;height:100dvh;border-radius:0;box-shadow:none}",
|
|
85
|
+
// v5 — settings preset/permission/enter-behavior rows: the selector
|
|
86
|
+
// moves to the top (full-width), the title + description fill the
|
|
87
|
+
// area below.
|
|
88
|
+
".oY77xG_row,._5QVD0a_row,.T1PP_q_row{flex-direction:column;align-items:stretch;gap:8px}",
|
|
89
|
+
".oY77xG_rowText,._5QVD0a_rowText,.T1PP_q_rowText{order:2;padding-right:0}",
|
|
90
|
+
".oY77xG_selector,._5QVD0a_selector,.T1PP_q_selector{align-self:stretch}",
|
|
91
|
+
// v7 — chat area side padding: 32px/side down to 6px, with the
|
|
92
|
+
// composer clearance variable following so the composer aligns.
|
|
93
|
+
".Md3f7G_scroll{padding-left:12px;padding-right:6px}",
|
|
94
|
+
".wSkVaW_scrollBody{scrollbar-gutter:auto}",
|
|
95
|
+
// v8 — user messages: right-anchored, fit-content size, uncapped so
|
|
96
|
+
// long text extends all the way to the left; square right corners.
|
|
97
|
+
".gdEzaW_userRow{align-items:flex-end}",
|
|
98
|
+
".gdEzaW_userStack{max-width:100%;align-items:flex-end}",
|
|
99
|
+
".gdEzaW_bubble{box-sizing:border-box;overflow-wrap:anywhere;border-radius:22px 22px 0 22px}",
|
|
100
|
+
".FJxK0a_root{padding-left:6px;padding-right:6px}",
|
|
101
|
+
".wSkVaW_root{--dsh-composer-side-clearance:6px}",
|
|
102
|
+
// v2 — agent-preset mode chip (标准模式/创造模式/PTC/极简): relocate
|
|
103
|
+
// into the header tab row, left of the download button, and abbreviate
|
|
104
|
+
// the name to three letters keyed off the label's title (the preset
|
|
105
|
+
// description). The composer write-access control is NOT touched.
|
|
106
|
+
".SVAs4q_label{position:absolute;top:45px;right:70px;z-index:2;font-size:0}",
|
|
107
|
+
".SVAs4q_label::after{font-size:13px;font-weight:500}",
|
|
108
|
+
".SVAs4q_label[title^=\"Full coding agent\"]::after,.SVAs4q_label[title^=\"功能完整\"]::after{content:\"STD\"}",
|
|
109
|
+
".SVAs4q_label[title^=\"All Standard mode\"]::after,.SVAs4q_label[title^=\"具备标准\"]::after{content:\"PTC\"}",
|
|
110
|
+
".SVAs4q_label[title^=\"Two-tool coding agent\"]::after,.SVAs4q_label[title^=\"仅提供持久\"]::after{content:\"MIN\"}",
|
|
111
|
+
".SVAs4q_label[title^=\"Built for creating\"]::after,.SVAs4q_label[title^=\"用于创建\"]::after{content:\"CTR\"}",
|
|
112
|
+
].join("") + "}";
|
|
113
|
+
const tagId = "@canary-builds/dsh-wpa/whale.css";
|
|
114
|
+
if (typeof document !== "undefined") {
|
|
115
|
+
// drop a stale tag from the pre-rename name if this page still carries one
|
|
116
|
+
document.querySelectorAll("style[data-plugin=\"dsh-plugin-whale\"]").forEach((t) => t.remove());
|
|
117
|
+
const existing = document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]");
|
|
118
|
+
if (existing !== null) existing.textContent = css;
|
|
119
|
+
else {
|
|
120
|
+
const tag = document.createElement("style");
|
|
121
|
+
tag.dataset.plugin = "@canary-builds/dsh-wpa";
|
|
122
|
+
tag.dataset.pluginCss = tagId;
|
|
123
|
+
tag.textContent = css;
|
|
124
|
+
document.head.appendChild(tag);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
//#endregion
|
|
128
|
+
|
|
129
|
+
function apply(ctx) {
|
|
130
|
+
const FloatingWhale = function () {
|
|
131
|
+
return React.createElement("button", {
|
|
132
|
+
type: "button",
|
|
133
|
+
className: "whalefab-button",
|
|
134
|
+
"aria-label": "Open sidebar",
|
|
135
|
+
title: "Open sidebar",
|
|
136
|
+
onClick: function () { ctx.layout.toggleSidebar(); },
|
|
137
|
+
}, React.createElement("span", { className: "whalefab-mark" }));
|
|
138
|
+
};
|
|
139
|
+
ctx.effect(() => ctx.slots.inject("shell.overlay", () =>
|
|
140
|
+
ctx.slots.register(
|
|
141
|
+
{ name: "shell.overlay", id: "whale-fab", order: 0, label: "Open sidebar" },
|
|
142
|
+
function () { return React.createElement(FloatingWhale); },
|
|
143
|
+
)
|
|
144
|
+
), "dsh-wpa: overlay entry");
|
|
145
|
+
// v3 — auto-collapse: opening a session from the sidebar list closes
|
|
146
|
+
// the sidebar again (app-style). Session rows carry the hashed
|
|
147
|
+
// YDXeBa_sessionRow class; workspace group rows do not. Clicks on
|
|
148
|
+
// inner controls (row menu buttons) are ignored, and the sidebar is
|
|
149
|
+
// only collapsed when it is actually expanded.
|
|
150
|
+
ctx.effect(() => {
|
|
151
|
+
const onClick = (event) => {
|
|
152
|
+
if (window.matchMedia("(display-mode: standalone),(display-mode: fullscreen),(display-mode: minimal-ui),(hover:none) and (pointer:coarse)").matches === false) return;
|
|
153
|
+
const target = event.target;
|
|
154
|
+
if (!(target instanceof Element)) return;
|
|
155
|
+
if (target.closest("button, a, input, [role=menuitem]") !== null) return;
|
|
156
|
+
if (target.closest(".YDXeBa_sessionRow") === null) return;
|
|
157
|
+
if (document.querySelector(".pI_x6G_frame:not([data-sidebar-collapsed])") === null) return;
|
|
158
|
+
ctx.layout.toggleSidebar();
|
|
159
|
+
};
|
|
160
|
+
document.addEventListener("click", onClick, true);
|
|
161
|
+
return () => document.removeEventListener("click", onClick);
|
|
162
|
+
}, "dsh-wpa: auto-collapse on session open");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
exports.apply = apply;
|
|
166
|
+
exports.inject = ["slots", "layout"];
|
|
167
|
+
return module.exports;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
//# sourceMappingURL=client.js.map
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// @canary-builds/dsh-wpa — host half: standalone PWA manifest route.
|
|
2
|
+
//
|
|
3
|
+
// Graduated from the dynamic plugin whale-1/pkg-1 (2026-08-28). Registers a
|
|
4
|
+
// named exact route on the webServer service that takes precedence over the
|
|
5
|
+
// dist fallback server's shipped /manifest.webmanifest (display: fullscreen)
|
|
6
|
+
// and serves a standalone manifest instead, so the GUI installs as a proper
|
|
7
|
+
// app window with its own taskbar icon. Route disposal rides the plugin
|
|
8
|
+
// fiber, so disabling the plugin row removes the override cleanly.
|
|
9
|
+
|
|
10
|
+
export const inject = ['webServer']
|
|
11
|
+
|
|
12
|
+
const MANIFEST = JSON.stringify({
|
|
13
|
+
id: '/',
|
|
14
|
+
name: 'DeepSeek Harness',
|
|
15
|
+
short_name: 'DSH',
|
|
16
|
+
description: 'DeepSeek Harness - local agent workspace.',
|
|
17
|
+
start_url: '/',
|
|
18
|
+
scope: '/',
|
|
19
|
+
display: 'standalone',
|
|
20
|
+
display_override: ['standalone'],
|
|
21
|
+
background_color: '#ffffff',
|
|
22
|
+
theme_color: '#ffffff',
|
|
23
|
+
icons: [
|
|
24
|
+
{ src: '/favicon.svg', sizes: 'any', type: 'image/svg+xml', purpose: 'any' },
|
|
25
|
+
],
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
export function apply(ctx) {
|
|
29
|
+
ctx.effect(() => ctx.webServer.register({
|
|
30
|
+
kind: 'exact',
|
|
31
|
+
path: '/manifest.webmanifest',
|
|
32
|
+
handler: (req, res) => {
|
|
33
|
+
res.writeHead(200, {
|
|
34
|
+
'Content-Type': 'application/manifest+json; charset=utf-8',
|
|
35
|
+
'Cache-Control': 'no-cache',
|
|
36
|
+
})
|
|
37
|
+
res.end(MANIFEST)
|
|
38
|
+
},
|
|
39
|
+
}), 'dsh-wpa: PWA manifest route')
|
|
40
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@canary-builds/dsh-wpa",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Mobile/PWA-first redesign for the DeepSeek Harness web GUI: app-style collapsible sidebar with a floating whale launcher, fullscreen overlay sidebar, compact top bar (icon-only session-log export, abbreviated mode chips), fullscreen settings sheet with icon-only nav, full-width user bubbles, and a standalone-window PWA manifest.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./lib/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./lib/index.js",
|
|
10
|
+
"./client": "./lib/client.js",
|
|
11
|
+
"./package.json": "./package.json"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"lib",
|
|
15
|
+
"cordis.patch.yml",
|
|
16
|
+
"README.md",
|
|
17
|
+
"CHANGELOG.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"keywords": [
|
|
21
|
+
"dsh",
|
|
22
|
+
"deepseek-harness",
|
|
23
|
+
"cordis",
|
|
24
|
+
"pwa",
|
|
25
|
+
"ui",
|
|
26
|
+
"dsh-plugin"
|
|
27
|
+
],
|
|
28
|
+
"dsh": {
|
|
29
|
+
"client": {
|
|
30
|
+
"platform": "web",
|
|
31
|
+
"inject": [
|
|
32
|
+
"@deepseek-ai/dsh-client-runtime",
|
|
33
|
+
"@deepseek-ai/dsh-client-ui-layout"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
"bundle": {
|
|
37
|
+
"patch": "./cordis.patch.yml"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/Canary-Builds/dsh-wpa.git"
|
|
43
|
+
},
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/Canary-Builds/dsh-wpa/issues"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://github.com/Canary-Builds/dsh-wpa#readme",
|
|
48
|
+
"author": "Canary Builds",
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=22.19.0"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public",
|
|
54
|
+
"registry": "https://registry.npmjs.org/"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"test": "node --test test/*.test.mjs",
|
|
58
|
+
"test:package": "node scripts/check-package.mjs"
|
|
59
|
+
}
|
|
60
|
+
}
|