dsh-code-server-app 0.1.43 → 0.2.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/README.en.md CHANGED
@@ -10,7 +10,7 @@
10
10
  > - Microsoft **open-source** extensions (Python, TypeScript debugger, ESLint, …) are mirrored on Open VSX and install normally by search;
11
11
  > - **If you need a proprietary Microsoft extension**: download the `.vsix` from the Marketplace page and install it manually with `code-server --install-extension <file>` (or drop it into `--extensions-dir`).
12
12
 
13
- A static profile plugin (npm package with host + client bundle) that ships [code-server](https://github.com/coder/code-server) as a **platform-independent dependency package** (a pack-time artifact at `vendor/code-server` → `@jinsiyu/dshcs-code-server`, with no install scripts and no postinstall); its binaries (argon2 plus 16 native modules) come from `@jinsiyu/dshcs-*-win32-<arch>` platform packages selected automatically per architecture by the platform aggregator. VS Code's inner dependencies and the prebuilt native modules are **all installed by the package manager together with the plugin** — no global npm install, no `bin` configuration, no profile config changes, no second install command.
13
+ A static profile plugin (npm package with host + client bundle) that ships the **VS Code server tree** from a [code-server](https://github.com/coder/code-server) release as a **platform-independent dependency package** (pack-time artifact `vendor/vscode` → `@jinsiyu/dshcs-vscode-server`, no install scripts, no postinstall). The code-server **Node service layer is replaced by the plugin's own `lib/launcher.mjs`**: it drives `<tree>/lib/vscode/out/server-main.js` (`loadCodeWithNls()` / `createServer()` / `handleRequest()` / `handleUpgrade()`) directly and re-adds the few HTTP endpoints code-server used to provide (`/healthz`, `/manifest.json`, `/_static/*`, `/proxy/:port`). The 16 native modules (node-pty / @vscode/sqlite3 / spdlog / …) come from `@jinsiyu/dshcs-*-win32-<arch>` platform packages selected automatically per architecture by the platform aggregator. VS Code's inner dependencies and the prebuilt native modules are **all installed by the package manager together with the plugin** — no global npm install, no `bin` configuration, no profile config changes, no second install command, **no argon2/C++ toolchain**.
14
14
 
15
15
  ## UI carrier (chosen by the DSH version, feature-detected at runtime)
16
16
 
@@ -25,7 +25,26 @@ A static profile plugin (npm package with host + client bundle) that ships [code
25
25
  - In sidebar mode the settings card hides "Reserve space above the composer" (floating-window geometry only). "Open in a window (new tab)" still applies to every entry point.
26
26
  - `windowedOpen` has the highest priority: when on, entry buttons always open a browser tab.
27
27
 
28
- ## Floating ball / window (legacy-DSH fallback path only)
28
+ ## Serving mode (`serve`)
29
+
30
+ | Mode | What it does | Requires |
31
+ |---|---|---|
32
+ | **`loopback` (default)** | the plugin listens on its own loopback port (`host:port`) and the sidebar iframe connects cross-origin; the process can be adopted after a DSH host restart | nothing |
33
+ | **`dsh`** | the IDE is mounted on **DSH's own HTTP port** at `/code-server/*` (HTTP prefix route) plus `/code-server/<quality>-<commit>` (exact WebSocket route), forwarded to the launcher's **named pipe**; **no extra port**; every request (including the WS handshake) first passes `ctx.connection.requestRejection()` — the same Host/Origin fence and browser-cookie authentication as `/api` | DSH providing `webServer` (web profile); desktop falls back to loopback automatically |
34
+
35
+ - Switch it in `config.serve` in `cordis.patch.yml` or in Settings → Plugins → Code Server (takes effect on the next start).
36
+ - Benefits of `dsh`: a single URL/port (remote access to DSH gives you the IDE), no extra loopback listener, authentication on par with DSH.
37
+ - Two **known trade-offs** of `dsh`: the iframe shares DSH's origin, so `sandbox` is dropped there (same-origin plus
38
+ `allow-same-origin` is escapable by the frame itself; in `loopback` mode the iframe is cross-origin and `sandbox` stays
39
+ as real protection — clipboard is still granted via `allow="clipboard-read; clipboard-write"`); and forwarded-port
40
+ **WebSockets** cannot be routed because `registerUpgrade` matches exact paths while `/proxy/:port` carries the port in
41
+ the path (HTTP forwarding works; use `loopback` when you need WS forwarding).
42
+
43
+ - In `loopback` mode every upgrade passes a **code-server-equivalent Origin check** (since 0.2.1): when an `Origin`
44
+ header is present its host must equal `Host` (honouring `Forwarded: host=` / `X-Forwarded-Host`, like code-server),
45
+ otherwise the handshake gets `403`; non-browser requests without `Origin` are allowed. Without that check any local
46
+ browser page could complete a handshake against `ws://127.0.0.1:<port>/stable-<commit>` and drive the IDE.
47
+
29
48
 
30
49
  - **Floating ball** (bottom-right, official code-server icon, above the composer): click to **expand the floating window and light it up** (blue glow), click again to **collapse**; **drag to any position** (remembered across refreshes; no accidental click after drag);
31
50
  no sidebar button, no window control button group (the ball is the only entry/toggle); the ball carries a status dot (green = running / amber = starting / red = error);
@@ -46,20 +65,21 @@ A static profile plugin (npm package with host + client bundle) that ships [code
46
65
  crash/exit updates status live; after a DSH host restart the plugin **adopts** a still-running instance (verifies pid + `/healthz`), without duplicate start or killing unrelated processes;
47
66
  - `node_modules` and the pack-time artifact `vendor/` are git-ignored; after cloning, follow
48
67
  "Install the plugin (script-free install; code-server bundled)" below — `pnpm install` → `pnpm run build:client` →
49
- `pnpm run vendor:code-server` → `pnpm pack` + `dsh plugin --profile web add`.
68
+ `pnpm run vendor:vscode` → `pnpm pack` + `dsh plugin --profile web add`.
50
69
 
51
70
  > Verified locally (BM: Windows 11 ARM64): `code-server@4.136.2` (with Code 1.136.1) bundled in the plugin,
52
71
  > placed offline at activation → VS Code internal deps installed → started → healthz 200 →
53
72
  > cwd switch restart while running → stopped → fully recycled.
54
73
 
74
+ ## Floating ball / window (legacy-DSH fallback path only)
55
75
  ## Packaging (how to build the tarball)
56
76
 
57
77
  ```powershell
58
78
  cd C:\Users\User\Desktop\dsh-code-server-app
59
79
  pnpm install # dev deps (esbuild + motion); allowBuilds is explicit → no postinstall runs
60
80
  pnpm run build:client # src/factory.js → lib/client.js (not committed; must be built first)
61
- pnpm run vendor:check # optional: show the bundled code-server version vs npm latest
62
- pnpm run vendor:code-server # ① produce vendor/code-server (the upstream tree)
81
+ pnpm run vendor:check # optional: show the bundled tree version vs the latest code-server release
82
+ pnpm run vendor:vscode # ① produce vendor/vscode (the trimmed VS Code tree, ~197MB)
63
83
  pnpm run repack:build -- --target win32-arm64,win32-x64 --pack # ② one script builds every sub-package
64
84
  pnpm run publish:repacks # ③ publish every @jinsiyu/* sub-package (default dist-tag: next)
65
85
  pnpm pack # ④ → dsh-code-server-app-<version>.tgz (~107KB)
@@ -81,18 +101,17 @@ pnpm run promote -- <version>
81
101
 
82
102
  | Sub-package | Content | os/cpu |
83
103
  |---|---|---|
84
- | `@jinsiyu/dshcs-code-server@<code-server version>` | the code-server tree (`out/` + `lib/vscode` + its 136 runtime deps), **no machine-specific binary** | platform-independent |
85
- | `@jinsiyu/dshcs-argon2-win32-arm64` / `-x64` | the argon2 module plus its compiled `.node` for that architecture (arm64 0xaa64 / x64 0x8664) | win32-<arch> |
104
+ | `@jinsiyu/dshcs-vscode-server@<code-server version>` | the trimmed VS Code tree (`lib/vscode` + `out/browser` + `src/browser`; **without** code-server's `out/node` and its 136 runtime deps) | platform-independent |
86
105
  | `@jinsiyu/dshcs-<name>[-win32-<arch>]` ×24 | the VS Code inner packages that need building (node-pty / @vscode/sqlite3 / kerberos / koffi / ssh2 / …) | gated when platform-specific |
87
- | `@jinsiyu/dsh-code-server-runtime-win32-<arch>` | platform aggregator: its `dependencies` map those 16 natives **plus argon2** back to their original names via `npm:` aliases | win32-<arch> |
106
+ | `@jinsiyu/dsh-code-server-runtime-win32-<arch>` | platform aggregator: its `dependencies` map those 16 natives back to their original names via `npm:` aliases | win32-<arch> |
88
107
 
89
108
  | Goal | Command |
90
109
  |---|---|
91
- | **Build the latest code-server from npm** | `pnpm run vendor:latest` (= `--force`): snapshots `code-server@latest` into `vendor/code-server`; afterwards you **must** re-run `repack:build` and republish every sub-package |
92
- | **Pin a version** | `pnpm run vendor:code-server -- --version 4.136.2` |
93
- | **Snapshot from an existing tree** | `pnpm run vendor:code-server -- --from <code-server dir>` (seconds) |
110
+ | **Build from the latest upstream release** | `pnpm run vendor:latest` (= `--force`): pulls `code-server@latest`'s tree into `vendor/vscode`; afterwards you **must** re-run `repack:build` and republish every sub-package |
111
+ | **Pin a version** | `pnpm run vendor:vscode -- --version 4.136.2` |
112
+ | **Snapshot from an existing tree** | `pnpm run vendor:vscode -- --from <code-server dir>` (seconds) |
94
113
  | **Rebuild every sub-package** | `pnpm run repack:build -- --target win32-arm64,win32-x64 --pack` (without `--from` it npm-installs and compiles the source tree itself — slow) |
95
- | **Rebuild only the code-server/argon2 packages** | `node scripts/vendor-repacks.mjs --reuse --target win32-arm64,win32-x64 --pack` (reuses the natives already in `repack/build`, no source-tree analysis) |
114
+ | **Rebuild only the tree/aggregator packages** | `node scripts/vendor-repacks.mjs --reuse --target win32-arm64,win32-x64 --pack` (reuses the natives already in `repack/build`) |
96
115
  | **Publish sub-packages** | `pnpm run publish:repacks` (`--dry-run` to preview; `--only <substr>` to filter; `--otp <code>` / `--limit N` for 2FA) |
97
116
  | **Publish the plugin itself** | `pnpm run publish:plugin` (publishes the exact tarball that was verified; no re-packing; default dist-tag `next`) |
98
117
  | **Promote `latest`** | `pnpm run promote -- <version>` (only after the user restarted and confirmed; `--dry-run` shows the current tags first) |
@@ -107,90 +126,73 @@ pnpm run promote -- <version>
107
126
 
108
127
  ```powershell
109
128
  # no postinstall in the package → no pnpm approve-builds / allowBuilds; one command installs everything
110
- dsh plugin --profile web add dsh-code-server-app@0.1.40
129
+ dsh plugin --profile web add dsh-code-server-app@0.2.1
111
130
  # a local tarball works the same way:
112
- dsh plugin --profile web add C:\Users\User\Desktop\dsh-code-server-app\dsh-code-server-app-0.1.40.tgz
131
+ dsh plugin --profile web add C:\Users\User\Desktop\dsh-code-server-app\dsh-code-server-app-0.2.1.tgz
113
132
  ```
114
133
 
115
134
  Ready to use immediately — **no second step, no "Install environment", no install-guide modal**.
116
- Since 0.1.40 the main package is only **~107KB** (the plugin's own code); everything else is dependencies:
135
+ The main package is only **~110KB** (the plugin's own code plus the launcher); everything else is dependencies:
117
136
 
118
- - **the code-server tree** (`lib/vscode` 196.9MB + its own 136 runtime dependencies) is a **platform-independent
119
- package** `@jinsiyu/dshcs-code-server@<code-server version>` declared in the plugin's `dependencies`; it runs from
120
- `<profile>\node_modules\@jinsiyu\dshcs-code-server\code-server`;
137
+ - **the VS Code tree** (`lib/vscode` 196.9MB + `out/browser` + `src/browser`) is a **platform-independent package**
138
+ `@jinsiyu/dshcs-vscode-server@<code-server version>` declared in the plugin's `dependencies`; it runs from
139
+ `<profile>\node_modules\@jinsiyu\dshcs-vscode-server\vscode` (the legacy full tree at
140
+ `@jinsiyu/dshcs-code-server/code-server` is still recognised as a fallback);
121
141
  - the **pure-JS part** of VS Code's inner dependencies (35 packages: xterm / katex / typescript / ws / tar …) is
122
142
  declared in the plugin's `dependencies` and installed by pnpm into the profile's `node_modules` (hoisted);
123
- - the **binary part** comes entirely from `@jinsiyu/dshcs-*` platform packages (one per platform, `os`/`cpu` gated):
124
- `@jinsiyu/dshcs-argon2-win32-<arch>` and 16 native packages, mapped back to their **original names**
125
- (`argon2` / `node-pty` / `@vscode/sqlite3` / …) by the **platform aggregator**
143
+ - the **binary part** comes entirely from `@jinsiyu/dshcs-*` platform packages: 16 native packages mapped back to their
144
+ **original names** (`node-pty` / `@vscode/sqlite3` / `@vscode/spdlog` / …) by the **platform aggregator**
126
145
  `@jinsiyu/dsh-code-server-runtime-win32-<arch>` using `npm:` aliases; the aggregators sit in the plugin's
127
146
  `optionalDependencies`, so pnpm auto-selects the right platform;
128
147
  - consequently the dependency graph contains **no package with pre/install/postinstall or a `binding.gyp`** →
129
148
  no profile `allowBuilds`, no build script ever runs, and **the user machine needs no C++ toolchain**;
130
- - **upgrading the plugin no longer re-downloads code-server**: the tree package is cached by version, so only a
131
- code-server version change pulls those ~60MB again (the argon2 platform package is only ~1.5MB).
149
+ - **upgrading the plugin no longer re-downloads the tree**: the tree package is cached by version
150
+ (~60MB, ~197MB unpacked).
132
151
 
133
152
  ### Install mechanism (why it is built this way)
134
153
 
135
154
  - **The pnpm 11 hard constraint**: any package in the dependency graph whose manifest has
136
- `preinstall|install|postinstall` (or whose tarball contains `binding.gyp`/`.hooks`) is treated as
137
- "requires build" and must be approved through the **host profile's** `pnpm-workspace.yaml` (`allowBuilds`),
138
- otherwise `dsh plugin add` exits 1 with `[ERR_PNPM_IGNORED_BUILDS]`. A dependency's own `pnpm.allowBuilds`,
139
- `.npmrc`, the `patch:` protocol and `optionalDependencies` are all ineffective (measured 2026-09, pnpm 11.25);
140
- - **the code-server tree** is prepared at pack time with `npm install code-server@<version> --ignore-scripts`
141
- (skips the official `sh ./postinstall.sh` there is no `sh` on Windows and the script only accepts npm/yarn
142
- user agents, so it always fails under pnpm) supply the argon2 native binary (no Windows prebuild exists;
143
- compile with `node-gyp-build`, or reuse an existing `argon2.node` via `DSHCS_ARGON2_BINARY`) strip leftover
144
- install scripts snapshot to `vendor/code-server/`;
145
- - the same script then builds the **platform-independent tree package**: the tree lives in an inner `code-server/`
146
- directory (npm/pnpm packing **always excludes the package root's `node_modules`**; a subdirectory covered by
147
- `files` is included), the package declares **no `dependencies`** (those 136 packages are already files inside
148
- `code-server/node_modules`; declaring them would make pnpm install a second copy) and its
149
- `node_modules/argon2` is removed entirely;
150
- - **argon2** becomes two platform packages (`@jinsiyu/dshcs-argon2-win32-arm64` / `-x64`) built with the very same
151
- rules as the other natives (delete `scripts`/`files`/`binding.gyp`, delete `prebuilds/` so both always load
152
- `build/Release`), each compiled with `node-gyp rebuild --arch=<arch>` and PE-checked (0xaa64 / 0x8664);
153
- - **packages that need compiling** are repacked into `@jinsiyu/dshcs-*`:
154
- copy the already-compiled package directory **delete `scripts` / `files` / `binding.gyp` / `.hooks` /
155
- `.npmignore`** (keeping the compiled `.node` and every runtime file) rewrite dependencies that belong to the
156
- same set to `npm:` aliases platform-specific ones get an `os`/`cpu` pair and a `-<platform>-<arch>` suffix;
157
- - **the platform aggregator** maps those repacks and argon2 back to their original names (e.g.
158
- `"node-pty": "npm:@jinsiyu/dshcs-node-pty@1.2.0-beta.15"`, `"argon2": "npm:@jinsiyu/dshcs-argon2-win32-arm64@0.44.0"`),
159
- so code-server's and VS Code's `require(...)` calls need no change. The aggregator itself is `os`/`cpu` gated,
160
- and the plugin declares both win32-arm64 and win32-x64 in `optionalDependencies` → one command picks the right one;
161
- - **resolution path**: the host resolves the runtime root with
162
- `require.resolve('@jinsiyu/dshcs-code-server/package.json')` (then the inner `code-server/` directory) and
163
- launches `code-server/out/node/entry.js`; inner dependencies resolve upward from there
164
- (`code-server/node_modules` the package's `node_modules` `<profile>/node_modules`).
165
- - **pnpm's nesting gotcha and the safety net**: `os`/`cpu`-gated packages are often installed **nested inside the
166
- aggregator** (e.g. `<profile>/node_modules/@jinsiyu/dsh-code-server-runtime-win32-arm64/node_modules/argon2`),
167
- i.e. neither at the profile root nor inside the code-server tree → the host adds that directory to the child
168
- process's **`NODE_PATH`**, and the environment check resolves against both anchors
169
- (code-server root + aggregator directory) see `lib/native.js`.
170
-
171
- > **Size note**: the plugin tarball is **~107KB**; `@jinsiyu/dshcs-code-server` is **~60.5MB** (242MB unpacked);
172
- > each argon2 platform package is **~1.5MB**; the 16 native packages add ~250MB. A full install downloads
173
- > roughly 315MB. Neither `vendor/` nor `repack/` is tracked by git (see `.gitignore`).
174
-
175
- > **Upgrading from 0.1.39**: code-server moved from a platform-specific sub-package to **one
176
- > platform-independent package plus two argon2 platform packages**, and every binary is now produced by the single
177
- > repack script. The upgrade command is unchanged
178
- > (`dsh plugin --profile web add dsh-code-server-app@<version>`); the old `dshcs-code-server-win32-*`
179
- > sub-packages are removed by pnpm.
180
-
181
- > **Upgrading from ≤ 0.1.35**: the old install root `<profile>\.code-server-app` (with ~1.4GB of inner
182
- > dependencies) and the "Install environment" step are gone. The new version detects the old root and logs that it
183
- > can be safely deleted: `Remove-Item -Recurse -Force <profile>\.code-server-app`. Old
184
- > `dsh-code-server-app: false` entries in the profile's `pnpm-workspace.yaml` can be removed too (no build
185
- > approval is needed any more).
186
-
187
- > **Uninstall**: `dsh plugin --profile web remove dsh-code-server-app` is enough; the tree package, argon2 and the
188
- > natives are separate dependencies, so to remove everything run e.g.
189
- > `dsh plugin --profile web remove @jinsiyu/dshcs-code-server` (or `pnpm remove` inside the profile);
190
- > if an old install root is still around, delete `<profile>\.code-server-app` manually.
191
-
192
- > After install/dependency changes, **restart `dsh web`** (the static plugin row and host probe paths load at startup).
193
-
155
+ `preinstall|install|postinstall` (or that ships a `binding.gyp`/`.hooks`) counts as "needs building" and must be
156
+ approved by the **host profile's** `pnpm-workspace.yaml` via `allowBuilds`, otherwise `dsh plugin add` exits 1 with
157
+ `[ERR_PNPM_IGNORED_BUILDS]`. A dependency's own `pnpm.allowBuilds`, `.npmrc`, `patch:` protocol and
158
+ `optionalDependencies` do not help (measured 2026-09, pnpm 11.25);
159
+ - **the tree** is prepared at pack time with `npm install code-server@<version> --ignore-scripts` (skipping the official
160
+ `sh ./postinstall.sh`, which cannot run on Windows), then `scripts/vendor-vscode-server.mjs` keeps **only the VS Code
161
+ tree**: `lib/vscode/**`, `out/browser/**`, `src/browser/**` plus the license files are copied to `vendor/vscode/`, and a
162
+ generated root `package.json` records the upstream code-server version. code-server's own `out/node/**` and its 136
163
+ runtime dependencies **no longer ship** — they are replaced by `lib/launcher.mjs`;
164
+ - **the packages that need a toolchain** are repacked into `@jinsiyu/dshcs-*` by `scripts/vendor-repacks.mjs`:
165
+ the compiled package directory is copied and its `scripts` / `files` / `binding.gyp` / `.hooks` / `.npmignore` are
166
+ **removed** (the built `.node` and every runtime file stay) sibling packages in its dependency list become `npm:`
167
+ aliases platform-specific ones get `os`/`cpu` plus a `-<platform>-<arch>` suffix. For win32 targets the script also
168
+ verifies each `.node` PE machine (0x8664=x64 / 0xaa64=arm64) so a cross-compiled artifact cannot ship the wrong arch;
169
+ - **the platform aggregator** maps those repacks back to their original names (e.g.
170
+ `"node-pty": "npm:@jinsiyu/dshcs-node-pty@1.2.0-beta.15"`), so VS Code's `import('node-pty')` needs no change; the
171
+ aggregator is itself `os`/`cpu` gated, and the plugin declares both win32-arm64 and win32-x64 in
172
+ `optionalDependencies`, so one command picks the right one;
173
+ - **resolution path**: the host finds the tree with `require.resolve('@jinsiyu/dshcs-vscode-server/package.json')`
174
+ (then the inner `vscode/` directory) and the entry is `vscode/lib/vscode/out/server-main.js`; VS Code's inner deps are
175
+ resolved upwards from that root (`vscode/lib/vscode/node_modules`package `node_modules` `<profile>/node_modules`).
176
+ The legacy full tree (`@jinsiyu/dshcs-code-server/code-server`) is still recognised as a fallback;
177
+ - **runtime layout self-healing** (`ensureRuntimeLayout()` in `lib/native.js`, idempotent, run **at activation before
178
+ `envCheck` and again before every start**): the host adds two kinds of **junctions** (Windows junctions / POSIX dir
179
+ symlinks) into the tree:
180
+ 1. `ensureAliasLinks()`: re-links the native aliases the aggregator carries into `<tree>/node_modules` — pnpm nests
181
+ `os`/`cpu`-gated packages under the aggregator's own `node_modules`, and `lib/vscode/out/server-main.js` uses
182
+ **ESM imports** (ESM ignores `NODE_PATH`), so a missing link means an immediate 500;
183
+ 2. `ensureInnerModuleLinks()`: restores VS Code's **inner dependency directories**
184
+ `lib/vscode/node_modules` and `lib/vscode/extensions/node_modules` from the two `package.json` files the trimmed
185
+ tree ships neither, and code that builds dependency paths explicitly (e.g. the bundled TypeScript extension looking
186
+ for `<ext>/../node_modules/typescript/lib/tsserver.js`) otherwise reports
187
+ "VS Code's tsserver was deleted by another application…" (measured with 1.136.1).
188
+ > **Size note**: the plugin tarball is **~110KB**; `@jinsiyu/dshcs-vscode-server` is **~60MB** (~197MB unpacked);
189
+ > the 16 native packages add ~250MB. A full install downloads roughly 310MB. Neither `vendor/` nor `repack/` is committed to git (see `.gitignore`).
190
+
191
+ > **Upgrading from 0.1.43**: the tree package changed from `@jinsiyu/dshcs-code-server` (the full code-server tree with
192
+ > `out/node` and 136 runtime deps) to `@jinsiyu/dshcs-vscode-server` (the trimmed tree). **The new code defaults to
193
+ > `serve: loopback`, which behaves exactly like 0.1.43**; switch to `serve: dsh` for same-origin mounting. The install
194
+ > command is unchanged (`dsh plugin --profile web add dsh-code-server-app@<version>`), and pnpm drops the old
195
+ > `dshcs-code-server` sub-package.
194
196
  ### Development: install from source (changes take effect immediately)
195
197
 
196
198
  ```powershell
@@ -198,7 +200,7 @@ dsh plugin --profile web add C:\Users\User\Desktop\dsh-code-server-app
198
200
  ```
199
201
 
200
202
  > A source path installs via `link:`. On a dev machine without `vendor/code-server`, run
201
- > `pnpm run vendor:code-server` first. Dependencies (inner JS deps + the platform aggregator) are installed by pnpm
203
+ > `pnpm run vendor:vscode -- --dev-links` first. Dependencies (inner JS deps + the platform aggregator) are installed by pnpm
202
204
  > too — but the not-yet-published local `@jinsiyu/*` packages must either be published first, or the
203
205
  > `repack/tgz/*.tgz` files must be installed into the profile as `file:` dependencies.
204
206
  >
@@ -214,7 +216,7 @@ dsh plugin --profile web add C:\Users\User\Desktop\dsh-code-server-app
214
216
  |---|---|---|---|
215
217
  | Node.js | **v24.x** (latest code-server requirement; v24.13.1 here) | required | required |
216
218
  | npm / pnpm | npm ships with Node; pnpm comes from DSH | required (installs deps) | required |
217
- | **MSVC build tools** | **VS Community 2026 + C++ desktop workload** | ❌ **not needed** | pack time (16 native packages + argon2) |
219
+ | **MSVC build tools** | **VS Community 2026 + C++ desktop workload** | ❌ **not needed** | pack time (16 native packages) |
218
220
  | **VS Spectre-mitigated libs** | one set for ARM64 **and** one for x86/x64 ("MSVC v14x Spectre-mitigated libs") | ❌ not needed | pack time (otherwise MSB8040) |
219
221
  | Python | **3.13.x** | ❌ not needed | pack time (node-gyp) |
220
222
  | node-gyp | **13.x** (older versions don't recognize VS 2026) | ❌ not needed | pack time |
@@ -235,30 +237,30 @@ dsh plugin --profile web add C:\Users\User\Desktop\dsh-code-server-app
235
237
  - If you don't need the self-contained install (e.g. a global code-server already exists), skip it:
236
238
  the plugin falls back to a configured/PATH `bin` (see the "Config" table).
237
239
 
238
- ### Upgrading the code-server version
240
+ ### Upgrading the VS Code tree (upstream = a code-server release)
239
241
 
240
- - **The version is decided at pack time**: `pnpm run vendor:latest` (= `--force`) rebuilds with the npm
241
- **latest** version; or use `pnpm run vendor:code-server -- --version 4.136.2` / `DSHCS_CODE_SERVER_VERSION`.
242
- With an existing `vendor/code-server`, a plain `pnpm pack` never upgrades (it is a no-op).
243
- - **Check first**: `pnpm run vendor:check` prints the bundled version / npm latest.
242
+ - **The version is decided at pack time**: `pnpm run vendor:latest` (= `--force`) pulls the tree of the npm **latest**
243
+ release; or use `pnpm run vendor:vscode -- --version 4.136.2` / `DSHCS_CODE_SERVER_VERSION`.
244
+ With an existing `vendor/vscode`, a plain `pnpm pack` never upgrades (it is a no-op).
245
+ - **Check first**: `pnpm run vendor:check` prints the bundled version / upstream latest.
244
246
  - **A version bump means rebuilding and republishing the sub-packages** (all with the same script):
245
247
  1. `pnpm run repack:build -- --target win32-arm64,win32-x64 --pack` → the new tree package
246
- (`@jinsiyu/dshcs-code-server@<new version>`), the new argon2 platform packages and the natives rebuilt
247
- against the new inner dependencies (the script also rewrites the plugin's pure-JS `dependencies` and both
248
- aggregator versions);
249
- 2. `pnpm run publish:repacks` → publish; then bump the plugin version → `pnpm pack` → publish the plugin.
248
+ (`@jinsiyu/dshcs-vscode-server@<new version>`) and the natives rebuilt against the new inner dependencies (the
249
+ script also rewrites the plugin's pure-JS `dependencies` and both aggregator versions);
250
+ 2. `pnpm run republish:repacks` (`pnpm run publish:repacks`) → publish; then bump the plugin version → `pnpm pack`
251
+ → publish the plugin.
252
+ - `productPath` (`<quality>-<commit>`, part of the client WebSocket path) is **computed from `lib/vscode/product.json`**,
253
+ so upgrading the tree needs no code change — but the routes are registered at activation, so restart `dsh web` afterwards.
250
254
  - **No runtime auto-upgrade anymore**: nothing fetches latest at startup; the version is fully determined by the bundled artifact.
251
- - Bundled locally right now: `code-server@4.136.2` (with Code 1.136.1).
255
+ - Bundled locally right now: the tree of `code-server@4.136.2` (VS Code 1.136.1, `productPath=stable-8d5f383f…`).
252
256
 
253
257
  ### Compatibility with the old install locations
254
258
 
255
- Host probe order: `@jinsiyu/dshcs-code-server/code-server` (**the real layout since 0.1.40**) >
259
+ Host probe order: `@jinsiyu/dshcs-vscode-server/vscode` (**the real layout since 0.2.0**) >
260
+ `@jinsiyu/dshcs-code-server/code-server` (the full tree, 0.1.40–0.1.43) >
256
261
  `@jinsiyu/dshcs-code-server-<platform>-<arch>/code-server` (the 0.1.37 platform sub-packages) >
257
- the in-package `vendor/code-server` (0.1.36 and earlier / development) > the old install root
258
- `<profile>\.code-server-app\node_modules\code-server` (0.1.35 and earlier) > plugin-internal
259
- `node_modules/code-server` (development) > PATH/config `bin`. The old root is only mentioned in a startup log
260
- line; nothing writes to it any more.
261
-
262
+ the in-package `vendor/vscode` > the in-package `vendor/code-server` (development). The old install root
263
+ `<profile>\.code-server-app` is only mentioned in a startup log line; nothing writes to it any more.
262
264
  ## Settings card (Settings → Plugins → Code Server)
263
265
 
264
266
  Modeled after dsh-auto-open-web's custom card, registered on the `settings.plugin.item` slot,
@@ -274,7 +276,7 @@ persisted via the official settings domain (`settingsScope`, namespace `code-ser
274
276
  > so the host re-registers the settings namespace (schema includes the new key); otherwise save/validation of the new key won't work.
275
277
 
276
278
  The bottom of the card is **Environment check** (click "Check environment" to read the host `status.env`): entry,
277
- `native` (argon2), VS Code inner dependencies, and **prebuilt native packages** (platform aggregator name +
279
+ the tree version / `productPath` / server entry, VS Code inner dependencies, and **prebuilt native packages** (platform aggregator name +
278
280
  resolved module count). Since 0.1.36 there is no "Install environment" button — dependencies are installed by the
279
281
  package manager, and the card only reports the result.
280
282
 
@@ -339,9 +341,19 @@ so users cannot remove it from the extensions panel.
339
341
 
340
342
  ## Known limitations
341
343
 
342
- - **No sub-path**: the code-server front-end uses root paths/WebSocket/Service Worker, so it must be a direct iframe on its own port;
343
- no DSH webServer reverse proxy; `--base-path` is not officially supported.
344
- - **Single instance across sessions**: one shared code-server per host; switching cwd requires a restart (the sidebar tab / floating window handles it and hints).
345
- - **Sidebar tab switching reloads**: DSH's right sidebar renders only the active tab's body, so switching away and back remounts the iframe (a full code-server reload); keep the tab active or float it for long-running sessions.
346
- - **Remote access**: default is loopback + no auth. Cross-machine access requires `host` + `auth: password` + `passwordToken`,
347
- and the browser must be able to reach that host directly (the plugin's "open in new tab" builds the URL from `host:port`).
344
+ - ~~No sub-path~~ **no longer true (corrected with measurements in 0.2.0)**: the workbench HTML VS Code renders references
345
+ **only relative URLs** (9 references measured, 0 absolute; `serverBasePath="."`, `rootEndpoint="."`), and the client
346
+ builds its WebSocket path from `location.pathname + join(serverBasePath ?? '/', <quality>-<commit>)`. The IDE can
347
+ therefore be mounted directly under DSH's own `/code-server/*` (`serve: dsh`) no second port, no HTML rewriting.
348
+ Item-by-item evidence: `docs/analysis-code-server-as-dsh-plugin.md`.
349
+ - **`serve: dsh` cannot proxy forwarded-port WebSockets**: `registerUpgrade` matches exact paths while `/proxy/:port`
350
+ carries the port in the path, so WebSocket forwarding for the Ports panel is unavailable in that mode (HTTP forwarding
351
+ works). Use `serve: loopback` when you need it.
352
+ - **`serve: dsh` shares DSH's origin**, so the iframe is not sandboxed there (same-origin plus `allow-same-origin` is
353
+ escapable by the frame itself); in `loopback` mode the iframe is cross-origin and `sandbox` stays as real protection.
354
+ - **Single instance across sessions**: one shared IDE per host; switching cwd requires a restart (the sidebar tab /
355
+ floating window handles it and hints).
356
+ - **Sidebar tab switching reloads**: DSH's right sidebar renders only the active tab's body, so switching away and back
357
+ remounts the iframe (a full VS Code reload); keep the tab active or float it for long-running sessions.
358
+ - **Remote access**: with `serve: dsh` the browser only needs to reach DSH itself (one port, protected exactly like `/api`);
359
+ `serve: loopback` stays loopback-only with `auth: none`, and 0.2.0 no longer supports `auth: password`.