dsh-auto-open-web 0.1.9 → 0.1.11

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 CHANGED
@@ -1,211 +1,214 @@
1
- # dsh-auto-open-web
2
-
3
- A persistent plugin for the `dsh web` profile that automatically opens the DSH Web GUI in an app-style
4
- window (or browser tab) on profile start, with a configuration card under Settings → Plugin
5
- configuration (manually maintained browser path, etc.).
6
-
7
- ## Behavior
8
-
9
- On startup (after the HTTP service binds and the actual listening port is known), the window type is
10
- selected by `windowKind`:
11
-
12
- 1. **WebView2 host** (`windowKind: webview2`, default, Windows only): launches the bundled
13
- `DshAppWindow.exe` (WinForms + WebView2, own process, no tab/address bar),
14
- **loading the GUI root address directly** (no iframe, no wrapper page, no injected scripts).
15
- **Taskbar/window icon = DSH icon** (the window is owned by the host process, which sets
16
- `Form.Icon` directly, independent of browser taskbar identity rules).
17
- **Exits with DSH** (the host watches the parent process PID).
18
- **Remembers window size/position/maximized state**
19
- (`%LOCALAPPDATA%\DeepSeekHarness\window-state.json`, saved on close and restored on start;
20
- falls back to centering when the display layout changes).
21
- 2. **Browser app window** (`windowKind: browser`): a **dedicated Edge/Chrome instance** via `--app`
22
- (`--user-data-dir=~/.dsh/<browser>-app-profile`, isolated process tree and storage,
23
- **shares no processes/Cookies/cache with the normal browser**; `--no-first-run` skips the
24
- first-run welcome page).
25
- **Exits with DSH (including force-kill)**: the browser instance is placed into a **Job Object**
26
- (`JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE`, koffi-driven `JOBOBJECT_EXTENDED_LIMIT_INFORMATION`
27
- structure, 144 bytes verified); whether DSH exits normally or is force-killed
28
- (`taskkill /F`, crash, shutdown, etc.), the Windows kernel terminates every process in the job
29
- when its last handle closes — the whole dedicated instance process tree dies with it, with no
30
- reliance on any exit event. Two extra safety nets: on normal DSH exit a `process 'exit'` handler
31
- kills the dedicated instance process tree (matching only our own user-data-dir, never the normal
32
- browser); instances left behind by a force-kill are cleaned up before the next launch.
33
- 3. If the selected type is unavailable (host missing / browser not found / non-Windows, etc.) →
34
- **falls back to the official default-browser handoff** — the URL is given to the OS default
35
- browser (plain tab), so the user can always reach the GUI. The implementation mirrors exactly
36
- how the DSH core (web-app bundle) opens the page at startup: it prefers the `open` package
37
- shipped with the DSH deployment (win32 = PowerShell Start, darwin = `open`, linux = `xdg-open`);
38
- when the package is unavailable it falls back to a native platform launch
39
- (win32 = `cmd /c start`, darwin = `open`, linux = `xdg-open`).
40
- `appWindow: false` opens nothing automatically.
41
-
42
- The port comes from the real listening value of the webServer service (`--port` overrides and
43
- `--port 0` both work). **No waiting needed**: the plugin declares webServer as a hard dependency
44
- (`inject`), so Cordis only activates it after the webServer plugin's `Service.init()` completes
45
- (HTTP socket bound, port written) the port is directly available in `apply`.
46
- Both modes close with DSH: the webview2 host watches the parent process; the
47
- browser dedicated instance is ended by the Job Object (also effective on force-kill) plus exit
48
- cleanup.
49
-
50
- > **Relationship with DSH's core browser handoff**: the DSH core (web-app bundle) opens the GUI
51
- > in the system default browser at startup by default (`openBrowser: true` a plain tab/window,
52
- > not an app window). Installing this plugin flips `web-runtime.openBrowser` to `false` via the
53
- > plugin's bundle patch, so only the plugin's app-style window opens and no ordinary browser page
54
- > pops up; uninstalling the plugin restores the default behavior (or use `dsh web --no-open`
55
- > to disable it temporarily).
56
-
57
- ### WebView2 host requirements (webview2 mode only)
58
-
59
- - Windows 10 1803+ / Windows 11 / Windows Server 2016+
60
- (Win7/8.1 reached end of support in 2023-01, see Microsoft announcements)
61
- - WebView2 Runtime (evergreen, usually preinstalled with Edge; verified with 151.x locally)
62
- - .NET 10 runtime (installed with the SDK; can be switched to a self-contained publish if needed)
63
-
64
- ## Configuration
65
-
66
- Two equivalent ways:
67
-
68
- 1. **Settings card** (recommended): Settings → Plugin configuration → the "自动打开网页"
69
- (auto-open web) card. Editable fields:
70
- `appWindow` (independent app window), `windowKind` (WebView2 host / browser app window),
71
- `browserPath` (browser executable, with a native "Browse" file dialog; located below the
72
- window-type field and enabled only when "Browser app window" is selected),
73
- `exitOnWindowClose` (exit DSH when the window closes, off by default).
74
- After saving, values persist through the **official settings domain** (client `settingsScope`)
75
- to the settings document (namespace `auto-open-web`); once saved,
76
- settings take precedence over row configuration. The host keeps only the "Browse" / "Test"
77
- helper routes (capabilities the official channel cannot cover).
78
- 2. **Row configuration** (`cordis.patch.yml`): acts as the startup seed, effective until the
79
- settings card is saved.
80
-
81
- | Field | Default | Description |
82
- | --- | --- | --- |
83
- | `appWindow` | `true` | Automatically open the independent app window on start; `false` opens nothing |
84
- | `windowKind` | `webview2` | `webview2` = WebView2 host (own process, DSH taskbar icon, exits with DSH); `browser` = dedicated `--app` browser instance. If the selected type is unavailable, it falls back to the default-browser handoff (official open method, plain tab) |
85
- | `exitOnWindowClose` | `false` | **(Experimental)** Exit DSH when the auto-opened window closes (off by default; only effective while `appWindow` is on). Triggered only when the window process exits **normally** (user closes the window) → `process.exit(0)`; startup failures/crashes/force-kills (non-zero exit code) do not trigger, preventing accidental exits. **Takes effect immediately in the current session after saving** (the exit listener is always registered; behavior is driven by a live flag), no restart needed |
86
- | `browserPath` | `''` | Manual browser executable path (single entry, e.g. `C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe`; used only in browser mode), preferred over the built-in candidates Edge Chrome; a non-existent path is skipped with a warning. The "Browse" button on the card opens a **native file dialog**: same mechanism as the official workspace directory picker (child process + koffi-driven `IFileOpenDialog`; the dialog is the child's first window and is automatically brought to front; no PowerShell). The "Test" button **actually launches** a dedicated `--app` test instance (separate user-data-dir `~/.dsh/<browser>-test-profile`, never pollutes the real instance): after confirming the browser main process stays alive it reports success, then automatically ends that test process tree after a few seconds of display (exact pid, never touches the real instance; the test instance is also placed in the Job Object when available as an exit safety net); the test uses the currently typed path (works even when unsaved), and failures show the reason |
87
-
88
- ### `browserPath` row configuration example
89
-
90
- Override the row's config by id in `~/.dsh/profiles/web/cordis.patch.yml` (the override replaces the
91
- whole config; fields not listed fall back to defaults):
92
-
93
- ```yaml
94
- - id: auto-open-web
95
- config:
96
- browserPath: 'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe'
97
- ```
98
-
99
- ## Packaging and installation
100
-
101
- This package is a **bundle**: an npm package carrying a configuration layer — `dsh.bundle` in
102
- `package.json` declares the patch file (`cordis.patch.yml`), and a profile activates the plugin row
103
- by package name when installed. Published to the **npm registry** (`dsh-auto-open-web@0.1.5`) and
104
- **GitHub** (https://github.com/jinsiyu/dsh-auto-open-web, `main` branch).
105
-
106
- ### Packaging
107
-
108
- ```bash
109
- cd dsh-auto-open-web
110
- pnpm pack # the prepack hook compiles the WebView2 host first (dotnet publish), producing dsh-auto-open-web-0.1.5.tgz
111
- ```
112
-
113
- ### Installation (pick one)
114
-
115
- **Option 1: source checkout link (development; changes take effect immediately)**
116
-
117
- ```bash
118
- # absolute path to avoid pnpm self-linking
119
- dsh plugin --profile web add C:\path\to\dsh-auto-open-web
120
- ```
121
-
122
- **Option 2: tarball (published artifact, recommended for delivery; no build permission needed)**
123
-
124
- ```bash
125
- dsh plugin --profile web add ./dsh-auto-open-web-0.1.5.tgz
126
- ```
127
-
128
- **Option 3: npm registry (after publishing)**
129
-
130
- ```bash
131
- dsh plugin --profile web add dsh-auto-open-web
132
- ```
133
-
134
- **Option 4: GitHub source**
135
-
136
- ```bash
137
- dsh plugin --profile web add github:jinsiyu/dsh-auto-open-web#main
138
- ```
139
-
140
- ### Uninstall
141
-
142
- ```bash
143
- dsh plugin --profile web remove dsh-auto-open-web # removes the dependency and its configuration layer together
144
- ```
145
-
146
- ### Effect and layer order
147
-
148
- After installation: pnpm adds the package to `profiles/web/node_modules`, and `dsh` appends
149
- `dsh-auto-open-web` to `dsh.profile.bundles`; at startup the bundle's `cordis.patch.yml` inserts the
150
- plugin row (`name: auto-open-web`, resolved by package name). After restarting `dsh web`, the
151
- "自动打开网页" card appears in the settings page (the client bundle is scanned into the browser
152
- manifest at startup via the modules line, per the `dsh.client` declaration).
153
-
154
- The effective configuration is composed layer by layer in this order (later layers win per row,
155
- replacing the whole row's config rather than deep-merging): each bundle's patch (in bundles list
156
- order) → the profile's own `cordis.patch.yml` → the global `$DSH_HOME/cordis.patch.yml` → the
157
- `--patch` overlay. Users can override this package's row in their own profile's `cordis.patch.yml`
158
- without touching the package.
159
-
160
- ### Notes
161
-
162
- - **Zero dependencies**: every runtime dependency is provided by the **DSH deployment** and
163
- declared as an optional peer (no install warnings):
164
- - `@deepseek-ai/dsh` (the host; declares the compatibility range `>=0.1.0-rc.7 <0.2.0` —
165
- `settings.plugin.item` became a keyed slot in that release, registration requires
166
- `options.key`; no runtime version check is performed)
167
- - `@deepseek-ai/schemastery` (config schema validator; resolved at runtime: normal import
168
- first, then the DSH deployment copy under the Windows global npm layout)
169
- - `koffi` (Windows only: Job Object / process verification / native file dialog; same runtime
170
- deployment-copy resolution, failure only degrades)
171
- So no platform ever hits build-script blocking HarmonyOS and other environments without
172
- koffi prebuilds install out of the box; posix platforms use the posix fallback adapter (browser
173
- mode works; webview2 / native dialog unavailable), and the platform adapter is loaded
174
- conditionally so win32.js is never evaluated on posix.
175
- - This package does not depend on `@deepseek-ai/cordis` (zero code references; the plugin identity
176
- comes from the `dsh.bundle` / `dsh.client` fields, and Cordis is provided by the DSH deployment
177
- at runtime), so installation produces no peer warnings.
178
- - **The npm package already contains the compiled WebView2 host** (built by the prepack hook before
179
- publishing); the **GitHub `main` branch and source-checkout installs do not** include
180
- `host-publish/` (build artifacts are .gitignore'd): for webview2 mode, run
181
- `pnpm run build:host` inside `node_modules/dsh-auto-open-web` first (requires the .NET SDK);
182
- browser mode needs no build.
183
- - If installing by editing `package.json` manually (not via the `dsh plugin` command), you must add
184
- both the `dependencies` entry and `dsh.profile.bundles`; when using a local `file:` dependency,
185
- `dsh web` normalizes `file:` to `^0.1.5` at startup, which does not affect runtime.
186
-
187
- ## Icons
188
-
189
- - GUI page icon: the GUI ships its own `/favicon.svg` (same as index.html).
190
- - **Taskbar/window icon (WebView2 host)**: the host process sets `Form.Icon` directly to the
191
- plugin-generated DSH .ico (`~/.dsh/auto-open-web-icon.ico`), independent of browser taskbar
192
- identity rules. The .ico is built by fetching the local `favicon.svg` and rasterizing it with
193
- **sharp** (bundled with the deployment, resolved upward at runtime, not declared as a dependency)
194
- into 16/32/48/64/128/256 PNGs; when sharp is unavailable the host falls back to the default window
195
- icon.
196
-
197
- ## Platform support
198
-
199
- - Windows: `windowKind: webview2` (default, DSH taskbar icon) or `windowKind: browser` (dedicated
200
- `--app` instance); falls back to the default-browser handoff (official open method, plain tab) if the selected type is unavailable
201
- - macOS/Linux: `webview2` mode is unavailable (falls back to the default-browser handoff); `browser` mode is untested
202
- (dedicated `--app` instance)
203
-
204
- ## Edge cases
205
-
206
- - Normal restart: in webview2 mode the old host window exits with the old DSH process; the new DSH
207
- opens a new host window
208
- - `browser` mode: after a restart the old window stays as-is (needs a manual refresh; may briefly
209
- coexist with the new window); when DSH is force-killed (`taskkill /F`, crash), the dedicated
210
- instance is ended by the Job Object without leftovers
211
- - Plugin removed: no injected code, no leftover routes, zero residual impact
1
+ # dsh-auto-open-web
2
+
3
+ A persistent plugin for the `dsh web` profile that automatically opens the DSH Web GUI in an app-style
4
+ window (or browser tab) on profile start, with a configuration card under Settings → Plugin
5
+ configuration (manually maintained browser path, etc.).
6
+
7
+ ## Behavior
8
+
9
+ On startup (after the HTTP service binds and the actual listening port is known), the window type is
10
+ selected by `windowKind`:
11
+
12
+ 1. **WebView2 host** (`windowKind: webview2`, default, Windows only): launches the bundled
13
+ `DshAppWindow.exe` (WinForms + WebView2, own process, no tab/address bar),
14
+ **loading the GUI root address directly** (no iframe, no wrapper page, no injected scripts).
15
+ **Taskbar/window icon = DSH icon** (the window is owned by the host process, which sets
16
+ `Form.Icon` directly, independent of browser taskbar identity rules).
17
+ **Exits with DSH** (the host watches the parent process PID).
18
+ **Remembers window size/position/maximized state**
19
+ (`%LOCALAPPDATA%\DeepSeekHarness\window-state.json`, saved on close and restored on start;
20
+ falls back to centering when the display layout changes).
21
+ 2. **Browser app window** (`windowKind: browser`): a **dedicated Edge/Chrome instance** via `--app`
22
+ (`--user-data-dir=~/.dsh/<browser>-app-profile`, isolated process tree and storage,
23
+ **shares no processes/Cookies/cache with the normal browser**; `--no-first-run` skips the
24
+ first-run welcome page).
25
+ **Exits with DSH (including force-kill)**: the browser instance is placed into a **Job Object**
26
+ (`JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE`, koffi-driven `JOBOBJECT_EXTENDED_LIMIT_INFORMATION`
27
+ structure, 144 bytes verified); whether DSH exits normally or is force-killed
28
+ (`taskkill /F`, crash, shutdown, etc.), the Windows kernel terminates every process in the job
29
+ when its last handle closes — the whole dedicated instance process tree dies with it, with no
30
+ reliance on any exit event. Two extra safety nets: on normal DSH exit a `process 'exit'` handler
31
+ kills the dedicated instance process tree (matching only our own user-data-dir, never the normal
32
+ browser); instances left behind by a force-kill are cleaned up before the next launch.
33
+ 3. If the selected type is unavailable (host missing / browser not found / non-Windows, etc.) →
34
+ **falls back to the official default-browser handoff** — the URL is given to the OS default
35
+ browser (plain tab), so the user can always reach the GUI. The implementation mirrors exactly
36
+ how the DSH core (web-app bundle) opens the page at startup: it prefers the `open` package
37
+ shipped with the DSH deployment (win32 = PowerShell Start, darwin = `open`, linux = `xdg-open`);
38
+ when the package is unavailable it falls back to a native platform launch
39
+ (win32 = `cmd /c start`, darwin = `open`, linux = `xdg-open`).
40
+ `appWindow: false` behaves **exactly like the official core**: the GUI is opened in the
41
+ system default browser (plain tab, official `open` method).
42
+
43
+ The port comes from the real listening value of the webServer service (`--port` overrides and
44
+ `--port 0` both work). **No waiting needed**: the plugin declares webServer as a hard dependency
45
+ (`inject`), so Cordis only activates it after the webServer plugin's `Service.init()` completes
46
+ (HTTP socket bound, port written) the port is directly available in `apply`.
47
+ Both modes close with DSH: the webview2 host watches the parent process; the
48
+ browser dedicated instance is ended by the Job Object (also effective on force-kill) plus exit
49
+ cleanup.
50
+
51
+ > **Relationship with DSH's core browser handoff**: the DSH core (web-app bundle) opens the GUI
52
+ > in the system default browser at startup by default (`openBrowser: true` a plain tab/window,
53
+ > not an app window). Installing this plugin flips `web-runtime.openBrowser` to `false` via the
54
+ > plugin's bundle patch, so the opening behavior is fully owned by the plugin: with
55
+ > `appWindow: true` the app-style window opens and no ordinary browser page pops up; with
56
+ > `appWindow: false` the plugin performs **the same default-browser handoff as the official core**
57
+ > (open package native platform launch), matching the no-plugin behavior. Uninstalling the
58
+ > plugin restores the official default (or use `dsh web --no-open` to disable it temporarily).
59
+
60
+ ### WebView2 host requirements (webview2 mode only)
61
+
62
+ - Windows 10 1803+ / Windows 11 / Windows Server 2016+
63
+ (Win7/8.1 reached end of support in 2023-01, see Microsoft announcements)
64
+ - WebView2 Runtime (evergreen, usually preinstalled with Edge; verified with 151.x locally)
65
+ - .NET 10 runtime (installed with the SDK; can be switched to a self-contained publish if needed)
66
+
67
+ ## Configuration
68
+
69
+ Two equivalent ways:
70
+
71
+ 1. **Settings card** (recommended): Settings Plugin configuration the "自动打开网页"
72
+ (auto-open web) card. Editable fields:
73
+ `appWindow` (independent app window), `windowKind` (WebView2 host / browser app window),
74
+ `browserPath` (browser executable, with a native "Browse" file dialog; located below the
75
+ window-type field and enabled only when "Browser app window" is selected),
76
+ `exitOnWindowClose` (exit DSH when the window closes, off by default).
77
+ After saving, values persist through the **official settings domain** (client `settingsScope`)
78
+ to the settings document (namespace `auto-open-web`); once saved,
79
+ settings take precedence over row configuration. The host keeps only the "Browse" / "Test"
80
+ helper routes (capabilities the official channel cannot cover).
81
+ 2. **Row configuration** (`cordis.patch.yml`): acts as the startup seed, effective until the
82
+ settings card is saved.
83
+
84
+ | Field | Default | Description |
85
+ | --- | --- | --- |
86
+ | `appWindow` | `true` | Automatically open the independent app window on start; `false` matches the official core the GUI opens in the system default browser (plain tab, official `open` method) |
87
+ | `windowKind` | `webview2` | `webview2` = WebView2 host (own process, DSH taskbar icon, exits with DSH); `browser` = dedicated `--app` browser instance. If the selected type is unavailable, it falls back to the default-browser handoff (official open method, plain tab) |
88
+ | `exitOnWindowClose` | `false` | **(Experimental)** Exit DSH when the auto-opened window closes (off by default; only effective while `appWindow` is on). Triggered only when the window process exits **normally** (user closes the window) → `process.exit(0)`; startup failures/crashes/force-kills (non-zero exit code) do not trigger, preventing accidental exits. **Takes effect immediately in the current session after saving** (the exit listener is always registered; behavior is driven by a live flag), no restart needed |
89
+ | `browserPath` | `''` | Manual browser executable path (single entry, e.g. `C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe`; used only in browser mode), preferred over the built-in candidates Edge → Chrome; a non-existent path is skipped with a warning. The "Browse" button on the card opens a **native file dialog**: same mechanism as the official workspace directory picker (child process + koffi-driven `IFileOpenDialog`; the dialog is the child's first window and is automatically brought to front; no PowerShell). The "Test" button **actually launches** a dedicated `--app` test instance (separate user-data-dir `~/.dsh/<browser>-test-profile`, never pollutes the real instance): after confirming the browser main process stays alive it reports success, then automatically ends that test process tree after a few seconds of display (exact pid, never touches the real instance; the test instance is also placed in the Job Object when available as an exit safety net); the test uses the currently typed path (works even when unsaved), and failures show the reason |
90
+
91
+ ### `browserPath` row configuration example
92
+
93
+ Override the row's config by id in `~/.dsh/profiles/web/cordis.patch.yml` (the override replaces the
94
+ whole config; fields not listed fall back to defaults):
95
+
96
+ ```yaml
97
+ - id: auto-open-web
98
+ config:
99
+ browserPath: 'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe'
100
+ ```
101
+
102
+ ## Packaging and installation
103
+
104
+ This package is a **bundle**: an npm package carrying a configuration layer — `dsh.bundle` in
105
+ `package.json` declares the patch file (`cordis.patch.yml`), and a profile activates the plugin row
106
+ by package name when installed. Published to the **npm registry** (`dsh-auto-open-web@0.1.5`) and
107
+ **GitHub** (https://github.com/jinsiyu/dsh-auto-open-web, `main` branch).
108
+
109
+ ### Packaging
110
+
111
+ ```bash
112
+ cd dsh-auto-open-web
113
+ pnpm pack # the prepack hook compiles the WebView2 host first (dotnet publish), producing dsh-auto-open-web-0.1.5.tgz
114
+ ```
115
+
116
+ ### Installation (pick one)
117
+
118
+ **Option 1: source checkout link (development; changes take effect immediately)**
119
+
120
+ ```bash
121
+ # absolute path to avoid pnpm self-linking
122
+ dsh plugin --profile web add C:\path\to\dsh-auto-open-web
123
+ ```
124
+
125
+ **Option 2: tarball (published artifact, recommended for delivery; no build permission needed)**
126
+
127
+ ```bash
128
+ dsh plugin --profile web add ./dsh-auto-open-web-0.1.5.tgz
129
+ ```
130
+
131
+ **Option 3: npm registry (after publishing)**
132
+
133
+ ```bash
134
+ dsh plugin --profile web add dsh-auto-open-web
135
+ ```
136
+
137
+ **Option 4: GitHub source**
138
+
139
+ ```bash
140
+ dsh plugin --profile web add github:jinsiyu/dsh-auto-open-web#main
141
+ ```
142
+
143
+ ### Uninstall
144
+
145
+ ```bash
146
+ dsh plugin --profile web remove dsh-auto-open-web # removes the dependency and its configuration layer together
147
+ ```
148
+
149
+ ### Effect and layer order
150
+
151
+ After installation: pnpm adds the package to `profiles/web/node_modules`, and `dsh` appends
152
+ `dsh-auto-open-web` to `dsh.profile.bundles`; at startup the bundle's `cordis.patch.yml` inserts the
153
+ plugin row (`name: auto-open-web`, resolved by package name). After restarting `dsh web`, the
154
+ "自动打开网页" card appears in the settings page (the client bundle is scanned into the browser
155
+ manifest at startup via the modules line, per the `dsh.client` declaration).
156
+
157
+ The effective configuration is composed layer by layer in this order (later layers win per row,
158
+ replacing the whole row's config rather than deep-merging): each bundle's patch (in bundles list
159
+ order) → the profile's own `cordis.patch.yml` → the global `$DSH_HOME/cordis.patch.yml` → the
160
+ `--patch` overlay. Users can override this package's row in their own profile's `cordis.patch.yml`
161
+ without touching the package.
162
+
163
+ ### Notes
164
+
165
+ - **Zero dependencies**: every runtime dependency is provided by the **DSH deployment** and
166
+ declared as an optional peer (no install warnings):
167
+ - `@deepseek-ai/dsh` (the host; declares the compatibility range `>=0.1.0-rc.7 <0.2.0` —
168
+ `settings.plugin.item` became a keyed slot in that release, registration requires
169
+ `options.key`; no runtime version check is performed)
170
+ - `@deepseek-ai/schemastery` (config schema validator; resolved at runtime: normal import
171
+ first, then the DSH deployment copy under the Windows global npm layout)
172
+ - `koffi` (Windows only: Job Object / process verification / native file dialog; same runtime
173
+ deployment-copy resolution, failure only degrades)
174
+ So no platform ever hits build-script blocking — HarmonyOS and other environments without
175
+ koffi prebuilds install out of the box; posix platforms use the posix fallback adapter (browser
176
+ mode works; webview2 / native dialog unavailable), and the platform adapter is loaded
177
+ conditionally so win32.js is never evaluated on posix.
178
+ - This package does not depend on `@deepseek-ai/cordis` (zero code references; the plugin identity
179
+ comes from the `dsh.bundle` / `dsh.client` fields, and Cordis is provided by the DSH deployment
180
+ at runtime), so installation produces no peer warnings.
181
+ - **The npm package already contains the compiled WebView2 host** (built by the prepack hook before
182
+ publishing); the **GitHub `main` branch and source-checkout installs do not** include
183
+ `host-publish/` (build artifacts are .gitignore'd): for webview2 mode, run
184
+ `pnpm run build:host` inside `node_modules/dsh-auto-open-web` first (requires the .NET SDK);
185
+ browser mode needs no build.
186
+ - If installing by editing `package.json` manually (not via the `dsh plugin` command), you must add
187
+ both the `dependencies` entry and `dsh.profile.bundles`; when using a local `file:` dependency,
188
+ `dsh web` normalizes `file:` to `^0.1.5` at startup, which does not affect runtime.
189
+
190
+ ## Icons
191
+
192
+ - GUI page icon: the GUI ships its own `/favicon.svg` (same as index.html).
193
+ - **Taskbar/window icon (WebView2 host)**: the host process sets `Form.Icon` directly to the
194
+ plugin-generated DSH .ico (`~/.dsh/auto-open-web-icon.ico`), independent of browser taskbar
195
+ identity rules. The .ico is built by fetching the local `favicon.svg` and rasterizing it with
196
+ **sharp** (bundled with the deployment, resolved upward at runtime, not declared as a dependency)
197
+ into 16/32/48/64/128/256 PNGs; when sharp is unavailable the host falls back to the default window
198
+ icon.
199
+
200
+ ## Platform support
201
+
202
+ - Windows: `windowKind: webview2` (default, DSH taskbar icon) or `windowKind: browser` (dedicated
203
+ `--app` instance); falls back to the default-browser handoff (official open method, plain tab) if the selected type is unavailable
204
+ - macOS/Linux: `webview2` mode is unavailable (falls back to the default-browser handoff); `browser` mode is untested
205
+ (dedicated `--app` instance)
206
+
207
+ ## Edge cases
208
+
209
+ - Normal restart: in webview2 mode the old host window exits with the old DSH process; the new DSH
210
+ opens a new host window
211
+ - `browser` mode: after a restart the old window stays as-is (needs a manual refresh; may briefly
212
+ coexist with the new window); when DSH is force-killed (`taskkill /F`, crash), the dedicated
213
+ instance is ended by the Job Object without leftovers
214
+ - Plugin removed: no injected code, no leftover routes, zero residual impact