dsh-code-server-app 0.2.4 → 0.2.6
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 +108 -21
- package/README.md +85 -13
- package/assets/extensions/dshcs-open-file/extension.js +11 -3
- package/assets/extensions/dshcs-open-file/package.json +2 -2
- package/cordis.patch.yml +4 -5
- package/lib/client.js +3 -3
- package/lib/index.js +51 -77
- package/lib/launcher.mjs +7 -14
- package/lib/native.js +1 -1
- package/lib/vendor.js +0 -18
- package/package.json +2 -2
- package/scripts/vendor-repacks.mjs +13 -21
- package/vendor/VENDOR.json +1 -1
package/README.en.md
CHANGED
|
@@ -16,7 +16,7 @@ A static profile plugin (npm package with host + client bundle) that ships the *
|
|
|
16
16
|
|
|
17
17
|
| DSH version | Carrier | Entry points |
|
|
18
18
|
|---|---|---|
|
|
19
|
-
| **>= 0.1.5-alpha.1** (has `sidebarRight` / `sidebarRightTabs`) | **Right-sidebar tab** (kind `code-server`, chip `Code Server`) | ① the **Code Server box** on the sidebar's guide ("开始") page;
|
|
19
|
+
| **>= 0.1.5-alpha.1** (has `sidebarRight` / `sidebarRightTabs`) | **Right-sidebar tab** (kind `code-server`, chip `Code Server`), which also **claims file addresses** (see below) | ① DSH's own **produced-file chips / presented-file card previews / inline file names in prose** (since 0.2.5, via the official `openFile` → file address → this tab); ② the **Code Server box** on the sidebar's guide ("开始") page; ③ Settings → Plugins → Code Server → **"Open in right sidebar"** |
|
|
20
20
|
| older (no sidebar service) | **Unsupported**: nothing but one notice on the settings page | none (Settings → Plugins → Code Server shows an upgrade notice) |
|
|
21
21
|
|
|
22
22
|
- Detection: first a synchronous `ctx.get('sidebarRightTabs') / ctx.get('sidebarRight')` probe; because the services may come up after this plugin, `ctx.inject(['sidebarRightTabs','sidebarRight'], …)` is awaited and a **2.5 s timeout marks the DSH as legacy** (no version comparison, and the plugin's own activation is never blocked).
|
|
@@ -27,14 +27,51 @@ A static profile plugin (npm package with host + client bundle) that ships the *
|
|
|
27
27
|
- services arriving late automatically revoke the legacy verdict, register the sidebar, and report `{sidebar:true}` so the host re-enables;
|
|
28
28
|
- a failed registration is no longer silent: it logs an error and the card's entry row says "right-sidebar services were found but the tab could not be registered".
|
|
29
29
|
- **0.2.3 dropped legacy-DSH compatibility**: the floating ball and the internal floating window are **deleted**. When the DSH is detected as legacy the plugin
|
|
30
|
-
- registers only the settings card (an upgrade notice) — no ball, no floating window, no
|
|
30
|
+
- registers only the settings card (an upgrade notice) — no ball, no floating window, **no file-address claim**, no IDE preload;
|
|
31
31
|
- reports `/api/code-server/ui-mode { sidebar:false }` to the host (after the 10 s grace above); the host then **recycles an instance it auto-prestarted** and stops prestarting (a user-started/adopted instance is never touched), and `{sidebar:true}` reverses that if the services show up later;
|
|
32
32
|
- upgrading DSH needs **no reinstall** — refresh the page and the card turns back into the full settings card.
|
|
33
33
|
- The sidebar tab hosts the code-server page (iframe) and follows the current session workspace; the panel can be collapsed/split/floated/fullscreened by DSH's right sidebar.
|
|
34
34
|
- **Resident IDE (0.2.2, on by default)**: switching to another tab or collapsing the sidebar and coming back **no longer reloads** code-server — unsaved editor buffers, terminals and debug sessions all stay put (see "Why switching tabs no longer reloads" below).
|
|
35
|
-
- The settings card
|
|
36
|
-
`
|
|
37
|
-
|
|
35
|
+
- The settings card has exactly **two settings**: "**Claim scope**" and "Resident in background"; plus one "Entry" action row and two read-only info sections (dependency install, environment check).
|
|
36
|
+
The old `windowedOpen` (open in a window) and `reserveComposer` were **removed in 0.2.6**: leftover keys in an old settings document neither fail nor apply (they are no longer part of the schema).
|
|
37
|
+
To use the IDE in a browser tab, visit the loopback address `http://127.0.0.1:<port>/` (or DSH's `/code-server/` under `serve: dsh`).
|
|
38
|
+
|
|
39
|
+
## Opening files (official entry points since 0.2.5)
|
|
40
|
+
|
|
41
|
+
DSH names files with **resource addresses**; `openFile` only hands the address to the right sidebar, which decides who draws it:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
DSH's produced-file chip / presented-file card preview / inline prose mention
|
|
45
|
+
→ openFile(path, { line? }) (provided by ui-chat)
|
|
46
|
+
→ dsh-resource://file/session/<sessionId>/<path> (or …/file/absolute/<path>)
|
|
47
|
+
→ ctx.sidebarRight.openResource(address)
|
|
48
|
+
→ claimed by the tab type whose patterns match (band extension(3) > builtin(2) > fallback(1),
|
|
49
|
+
then the longest matching pattern, then registration order)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
This plugin registers:
|
|
53
|
+
|
|
54
|
+
| Field | Value | Effect |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| `patterns` | `['dsh-resource://file/**']` | claims file addresses (a pattern containing `:` is matched against the **whole address**) |
|
|
57
|
+
| `priority` | `'extension'` | beats the built-in plain-text preview, which sits in `fallback` on purpose — DSH's own comment calls that band "the position VS Code's text editor holds among its editors", i.e. one any more specific type should beat |
|
|
58
|
+
| `canOpen` | see below | vetoes by the "claim scope" setting; unclaimed addresses fall back to DSH's built-in preview |
|
|
59
|
+
| `title` | last address segment (= file name) | the tab chip shows the file name; a page tab (`sidebar://code-server`) still reads `Code Server` |
|
|
60
|
+
|
|
61
|
+
- **Claim scope** (switchable in the settings card, `fileOpenScope`):
|
|
62
|
+
- `session` (default) — claim only `dsh-resource://file/session/…` (everything a session produces: deliverables, declared deliveries, prose mentions, tool views);
|
|
63
|
+
- `all` — also claim session-less `dsh-resource://file/absolute/…` addresses.
|
|
64
|
+
- **How the tab body locates the file**: it parses `useTabInfo().tab.navigation.address`
|
|
65
|
+
(`src/address.js`, same grammar as DSH's `parseFileAddress`), expands a workspace-relative path with that
|
|
66
|
+
session's cwd, and posts the absolute path (plus optional `line`) to the host's
|
|
67
|
+
`/api/code-server/open-file`; the bundled extension (`dshcs-open-file`) then calls `showTextDocument`
|
|
68
|
+
(positioned at the line when given).
|
|
69
|
+
- **One address = one tab** (DSH semantics: `contentId` *is* the address): three files mean three chips, but they
|
|
70
|
+
share the single resident workbench — switching tabs just re-aims the workbench at the corresponding file.
|
|
71
|
+
- **Why the bundled extension stays**: VS Code Web has no official "open this file from outside" API (the only
|
|
72
|
+
entry is `?folder=`, which picks the workspace), so aiming the workbench at a file has to be done by an
|
|
73
|
+
extension inside the tree. The host writes a signal file, the extension polls it and calls
|
|
74
|
+
`showTextDocument`, keeping the signal for retry when no window is connected yet.
|
|
38
75
|
|
|
39
76
|
## Why switching tabs no longer reloads (resident IDE)
|
|
40
77
|
|
|
@@ -108,7 +145,7 @@ state preserved (no full reload). Full evidence and probe scripts: `docs/analysi
|
|
|
108
145
|
> background. Upgrade DSH to a version with the right sidebar (>= 0.1.5-alpha.1): Code Server then appears as a
|
|
109
146
|
> right-sidebar tab, this page shows the full settings again, and no reinstall is needed — a page refresh is enough.
|
|
110
147
|
|
|
111
|
-
- **No other UI**: no `shell.overlay` registration (floating ball), no
|
|
148
|
+
- **No other UI**: no `shell.overlay` registration (floating ball), no file-address claim, no resident preload.
|
|
112
149
|
- **Host side**: the client posts `/api/code-server/ui-mode { sidebar:false }`; the host then ① stops auto-prestarting
|
|
113
150
|
the IDE (`maybePrestart` returns immediately) and ② **recycles** an instance it had just auto-prestarted (unless it
|
|
114
151
|
was adopted), so no unusable IDE process or port is left behind. A user-started/adopted instance is never stopped.
|
|
@@ -333,12 +370,15 @@ persisted via the official settings domain (`settingsScope`, namespace `code-ser
|
|
|
333
370
|
|
|
334
371
|
| Key | Default | Description |
|
|
335
372
|
|---|---|---|
|
|
336
|
-
| `
|
|
373
|
+
| `fileOpenScope` | `session` | **Claim scope** (0.2.5): `session` claims only session-scoped file addresses (`dsh-resource://file/session/…` — DSH's produced files, declared deliveries, prose mentions); `all` also claims session-less `…/file/absolute/…`. Unclaimed addresses fall back to DSH's built-in preview |
|
|
337
374
|
| `keepResident` | `true` | **Resident in background**: on, the host preloads the IDE into a parked surface right after start — switching tabs or collapsing the sidebar never reloads it and the first open needs no cold start; off loads it only when the panel is opened (saves memory) |
|
|
338
|
-
| ~~`reserveComposer`~~ | `true` | **Deprecated in 0.2.3**: it only ever affected the deleted internal floating window. An old value in the settings document is still accepted but ignored (the key is kept so old settings documents keep validating) |
|
|
339
375
|
|
|
340
|
-
|
|
341
|
-
|
|
376
|
+
(Since 0.2.6 the card keeps only those two settings; `windowedOpen` and `reserveComposer` are gone — leftover keys in an old
|
|
377
|
+
settings document neither fail nor apply. `serve` remains a key in the settings namespace (usable from a settings document) but
|
|
378
|
+
has **no card row** — see "Serving mode".)
|
|
379
|
+
|
|
380
|
+
> Card changes take effect immediately via `scope.watch` (the host status API returns `keepResident` and
|
|
381
|
+
> `fileOpenScope`; the client applies them at once); no dsh restart needed. **After adding new setting keys, restart dsh web before first use**,
|
|
342
382
|
> so the host re-registers the settings namespace (schema includes the new key); otherwise save/validation of the new key won't work.
|
|
343
383
|
|
|
344
384
|
The bottom of the card is **Environment check** (click "Check environment" to read the host `status.env`): entry,
|
|
@@ -392,20 +432,67 @@ Host/Origin fence and browser auth); in the desktop profile `apps/desktop-host`
|
|
|
392
432
|
|
|
393
433
|
- The host half is `inject = ['connection', 'settings']` (**no `webServer`**) — the desktop profile disables webserver/web-runtime
|
|
394
434
|
and the plugin still works: `/api/*` requests travel Electron `dsh-app://` protocol handler → IPC framed pipe → `createSharedFetchHandler('/api')`.
|
|
395
|
-
- The right-sidebar tab, guide entry box,
|
|
435
|
+
- The right-sidebar tab, guide entry box, file-address claim, and settings card behave the same as in web (code-server remains an
|
|
396
436
|
iframe to the local `http://127.0.0.1:<port>`; the desktop renderer uses `webSecurity: true` with no CSP, so the cross-origin iframe loads).
|
|
397
437
|
The desktop build ships `dsh-client-ui-sidebar-right` in its seed package set as well, so the 0.2.3 "right-sidebar DSH only" rule is
|
|
398
438
|
not a regression for desktop; the only difference is the missing `webServer`, where `serve: dsh` falls back to loopback.
|
|
399
|
-
- Install into the desktop profile
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
(
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
439
|
+
- Install into the desktop profile through the **desktop plugin manager** (not the CLI, see below).
|
|
440
|
+
- **Desktop installs face a 24-hour supply-chain policy (measured 2026-09-10; this is how 0.2.4 got installed)**:
|
|
441
|
+
- the CLI path is unavailable: `dsh plugin --profile desktop …` is rejected (*"profile "desktop" is managed exclusively by the
|
|
442
|
+
Electron application"*), so desktop installs only go through the app's package transaction (`pnpm add <spec> --save-exact`,
|
|
443
|
+
executed in `~/.dsh/desktop/staging/<uuid>/profile` before activation);
|
|
444
|
+
- that transaction's pnpm (the app bundles **11.7.0**, patched by DeepSeek) runs a **lockfile supply-chain verification** before
|
|
445
|
+
`add` ("Verifying lockfile against supply-chain policies (717 entries)") which requires packages to be **at least 24 h old**,
|
|
446
|
+
otherwise `ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION`;
|
|
447
|
+
- **the two stages behave differently (measured)**:
|
|
448
|
+
- verifying an **existing lockfile**: `minimumReleaseAgeExclude` is *not* honoured (exact versions and bare package names
|
|
449
|
+
were both tried);
|
|
450
|
+
- **resolution** (no lockfile to verify, e.g. after `pnpm clean --lockfile`): the list *is* honoured, and pnpm even appends
|
|
451
|
+
entries itself (the install log prints *"Added N entries to minimumReleaseAgeExclude…"*);
|
|
452
|
+
- so the working recipe for a **just-published** (<24 h) version on desktop is to start from a clean, lockfile-free profile:
|
|
453
|
+
1. `pnpm clean --lockfile` (**note: it also deletes `node_modules`**, leaving the profile to be reinstalled);
|
|
454
|
+
2. with the app's bundled runtime, run `add <spec> --save-exact --trust-lockfile` in the profile directory
|
|
455
|
+
(runtime/store/config live under `~/.dsh/desktop/pnpm/{store,cache,state,config,home}`,
|
|
456
|
+
`--config.userconfig=…/config/npmrc`, otherwise pnpm fails with `ERR_PNPM_UNEXPECTED_STORE` /
|
|
457
|
+
`…UNEXPECTED_VIRTUAL_STORE`);
|
|
458
|
+
3. the app's boot command (`install --offline --frozen-lockfile --trust-lockfile`) then passes (lockfile matches
|
|
459
|
+
package.json, packages are in the store); if the plugin name is already in `dsh.profile.bundles` nothing else is needed.
|
|
460
|
+
- do **not** try to bypass it with `minimumReleaseAge: 0`: it does clear the check, but that key is **not** one of the policy
|
|
461
|
+
sections the app tolerates (`project-manager.ts` ignores only `minimumReleaseAgeExclude:` / `trustPolicyExclude:` and validates
|
|
462
|
+
the manifest before every `mutate()`), so persisting it makes the app fail with
|
|
463
|
+
*"core package mapping does not match desktop-packages.json"*.
|
|
464
|
+
- Alternatively **wait out the 24 h** and install normally from the plugin manager. The web profile is unaffected: its
|
|
465
|
+
`pnpm-workspace.yaml` sets `minimumReleaseAge: false`.
|
|
466
|
+
- this plugin's closure contains platform native sub-packages (`@jinsiyu/dsh-code-server-runtime-win32-*`) published together with
|
|
467
|
+
the plugin itself, so every new version hits that policy on desktop.
|
|
468
|
+
- **Desktop client bundles are cached by Electron; restarting the app does not guarantee a new one** (measured 2026-09, hit while shipping 0.2.5):
|
|
469
|
+
- symptom: `lib/client.js` in the profile is the new version, yet the renderer keeps running the old code —
|
|
470
|
+
`%APPDATA%\@deepseek-ai\dsh-desktop\Code Cache\js` only contains strings unique to the old version (e.g. `dshcs-artifacts`)
|
|
471
|
+
and none unique to the new one (`fileOpenScope`), and `Cache\` still holds an old response body referencing
|
|
472
|
+
`dsh-code-server-app`. The same applies to first-party plugins (the cached `ui-deliverables` even lacks the current
|
|
473
|
+
`data-presented-files-row` marker);
|
|
474
|
+
- diagnosis (byte level — do **not** use `Select-String`, which reads files with the console encoding and gives false
|
|
475
|
+
negatives on non-ASCII markers): search `Code Cache\js` for an **ASCII** marker unique to the new version
|
|
476
|
+
(ours is `fileOpenScope`); a hit proves the new bundle really was compiled;
|
|
477
|
+
- fix: fully close the app, delete the `Cache`, `Code Cache` and `GPUCache` directories, then start it (cache only —
|
|
478
|
+
profiles, sessions and settings are untouched):
|
|
479
|
+
```powershell
|
|
480
|
+
Remove-Item -Recurse -Force "$env:APPDATA\@deepseek-ai\dsh-desktop\Cache","$env:APPDATA\@deepseek-ai\dsh-desktop\Code Cache","$env:APPDATA\@deepseek-ai\dsh-desktop\GPUCache"
|
|
481
|
+
```
|
|
482
|
+
- scope: this is not specific to this plugin — **any** client plugin may keep running old code after an upgrade;
|
|
483
|
+
after a release, confirm with the marker trick above that the renderer actually swapped bundles.
|
|
484
|
+
|
|
485
|
+
## File-open plumbing (what the plugin itself still does)
|
|
486
|
+
|
|
487
|
+
DSH's own chips and preview buttons are what users click (see "Opening files" above); this plugin adds no row of its own.
|
|
488
|
+
What remains on the plugin side:
|
|
489
|
+
|
|
490
|
+
- the tab body parses `navigation.address` and posts the absolute path (plus an optional `line`) to
|
|
491
|
+
`/api/code-server/open-file`, which writes a signal file;
|
|
492
|
+
- the bundled `dshcs-open-file` extension polls that file and calls `showTextDocument` — VS Code Web has no official
|
|
493
|
+
"open this file from outside" API, so this is the only way to aim the workbench at a file. It is installed as a
|
|
494
|
+
**built-in** extension (in `lib/vscode/extensions`), so users cannot remove it from the extensions panel, and the
|
|
495
|
+
installer re-syncs it whenever its content changes.
|
|
409
496
|
|
|
410
497
|
## Known limitations
|
|
411
498
|
|
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
| DSH 版本 | 载体 | 入口 |
|
|
28
28
|
|---|---|---|
|
|
29
|
-
| **≥ 0.1.5-alpha.1**(有 `sidebarRight` / `sidebarRightTabs` 服务) | **右侧栏标签**(kind=`code-server`,标签名 `Code Server`) | ① 右侧栏「开始」页的 **Code Server
|
|
29
|
+
| **≥ 0.1.5-alpha.1**(有 `sidebarRight` / `sidebarRightTabs` 服务) | **右侧栏标签**(kind=`code-server`,标签名 `Code Server`),并**认领文件地址**(见下) | ① **DSH 官方的产物 chip / 「交付」卡片预览 / 正文里的文件名**(0.2.5 起,走官方 `openFile` → 文件地址 → 本 tab);② 右侧栏「开始」页的 **Code Server 入口框**;③ 设置 → 插件 → Code Server → **「在右侧栏打开」** |
|
|
30
30
|
| 更早(无右侧栏服务) | **不受支持**:除设置页的一条提示外**不提供任何入口** | 无(设置 → 插件 → Code Server 显示升级提示) |
|
|
31
31
|
|
|
32
32
|
- 检测方式:先 `ctx.get('sidebarRightTabs') / ctx.get('sidebarRight')` 同步探测;
|
|
@@ -39,16 +39,51 @@
|
|
|
39
39
|
- 服务晚到 → 自动撤销旧版判定、补注册侧栏,并上报 `{sidebar:true}` 让 host 恢复;
|
|
40
40
|
- 注册失败不再静默:控制台报错,设置卡入口行显示"已探测到右侧栏服务,但标签注册失败"。
|
|
41
41
|
- **0.2.3 起不再兼容旧版 DSH**:悬浮球与内部浮动窗口回退**已删除**。判定为旧版时:
|
|
42
|
-
- 只注册设置卡片,内容是一条升级提示(见下)
|
|
42
|
+
- 只注册设置卡片,内容是一条升级提示(见下),不注册悬浮球/浮窗/**文件地址认领**,也不预热 IDE;
|
|
43
43
|
- 客户端向 host 上报 `/api/code-server/ui-mode { sidebar:false }`(在上面的 10 s 宽限之后),host 据此**回收自动预启动的实例**
|
|
44
44
|
并停止预启动(用户手动启动的实例不受影响);服务随后才出现时会再上报 `{sidebar:true}` 撤销;
|
|
45
45
|
- 升级 DSH 后**无需重装插件**,刷新页面即可,本页会恢复为完整设置卡片。
|
|
46
46
|
- 侧栏标签内即 code-server 页面(iframe),跟随当前会话工作区;面板可折叠/分屏/浮动/全屏(由 DSH 右侧栏提供)。
|
|
47
47
|
- **IDE 常驻(0.2.2 起,默认开)**:切到别的标签/收起侧栏再回来**不再重载** code-server——
|
|
48
48
|
未保存的编辑缓冲区、终端、调试会话都留在原处(见下方「为什么切标签不再重载」)。
|
|
49
|
-
-
|
|
50
|
-
`
|
|
51
|
-
|
|
49
|
+
- 设置卡片只有**两个设置**:「**认领范围**」与「**后台常驻(切标签不重载)**」;另有一行「入口」(在右侧栏打开)与两段只读信息(依赖安装、环境检测)。
|
|
50
|
+
旧版的 `windowedOpen`(窗口化打开)、`reserveComposer` 已在 0.2.6 移除:旧设置文档里残留的这两个键不会报错,只是被忽略(不再出现在 schema 里)。
|
|
51
|
+
需要在新标签页用 IDE 时,直接访问回环地址 `http://127.0.0.1:<port>/`(`serve: dsh` 时为 DSH 的 `/code-server/`)。
|
|
52
|
+
|
|
53
|
+
## 文件打开(0.2.5 起走官方入口)
|
|
54
|
+
|
|
55
|
+
DSH 用**资源地址**命名文件,`openFile` 只负责把地址交给右侧栏去认领:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
官方产物 chip / 「交付」卡片预览 / 正文内联提及
|
|
59
|
+
→ openFile(path, { line? }) (ui-chat 提供)
|
|
60
|
+
→ dsh-resource://file/session/<sessionId>/<path> (或 …/file/absolute/<path>)
|
|
61
|
+
→ ctx.sidebarRight.openResource(address)
|
|
62
|
+
→ 由注册了匹配 patterns 的 tab 类型认领(优先级 extension(3) > builtin(2) > fallback(1),
|
|
63
|
+
同带内按 pattern 长度、再按注册顺序)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
本插件注册时带上:
|
|
67
|
+
|
|
68
|
+
| 字段 | 值 | 作用 |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `patterns` | `['dsh-resource://file/**']` | 认领文件地址(含 `:` 的 pattern 按**整址** glob 匹配) |
|
|
71
|
+
| `priority` | `'extension'` | 高于官方纯文本预览的 `fallback`——DSH 源码注释写明后者是"VS Code 文本编辑器在编辑器中的位次,任何更具体的类型都应当击败它" |
|
|
72
|
+
| `canOpen` | 见下 | 按「认领范围」设置否决,未认领的地址由官方预览兜底 |
|
|
73
|
+
| `title` | 地址末段(=文件名) | tab chip 显示文件名;页面 tab(`sidebar://code-server`)仍是 `Code Server` |
|
|
74
|
+
|
|
75
|
+
- **认领范围**(设置卡片可切,`fileOpenScope`):
|
|
76
|
+
- `session`(默认)= 只认领 `dsh-resource://file/session/…`(会话里的产物、交付、正文提及、工具视图都走这条);
|
|
77
|
+
- `all` = 连不带会话的 `dsh-resource://file/absolute/…` 也认领("所有文件"模式)。
|
|
78
|
+
- **tab body 怎么定位文件**:从 `useTabInfo().tab.navigation.address` 解析出会话与路径
|
|
79
|
+
(`src/address.js`,与 DSH `parseFileAddress` 同语义),相对路径按该会话 cwd 展开成绝对路径,
|
|
80
|
+
再把绝对路径 + 可选 `line` 交给 host 的 `/api/code-server/open-file`;内建扩展
|
|
81
|
+
(`dshcs-open-file`)在 workbench 里 `showTextDocument`(带行号时定位到该行)。
|
|
82
|
+
- **一个地址 = 一个 tab**(官方语义,`contentId` 就是地址):打开三个文件会有三个 chip,
|
|
83
|
+
但它们共用同一个常驻 workbench(我们的 IDE 是单实例),切换时只是让 workbench 定位到对应文件。
|
|
84
|
+
- **为什么还留着那个内建扩展**:VS Code Web 没有"从外部打开文件"的官方 API(唯一入口是
|
|
85
|
+
`?folder=` 指定工作区),所以"让 workbench 定位到某个文件"只能由树内的扩展完成;
|
|
86
|
+
host 写信号文件、扩展轮询并 `showTextDocument`,失败保留重试(实例尚未就绪时也不会丢)。
|
|
52
87
|
|
|
53
88
|
## 为什么切标签不再重载(IDE 常驻)
|
|
54
89
|
|
|
@@ -92,7 +127,7 @@
|
|
|
92
127
|
| **`loopback`(默认)** | 插件自己起一个回环端口(`host:port`),右侧栏 iframe 跨源直连;进程可被 adopt(DSH host 重启后接管) | 无 |
|
|
93
128
|
| **`dsh`** | IDE 挂到 **DSH 自己的 HTTP 端口**上的 `/code-server/*`(HTTP prefix 路由)+ `/code-server/<quality>-<commit>`(WS 精确路由),转发到 launcher 的**命名管道**;**没有额外端口**;每条请求(含 WS 握手)先过 `ctx.connection.requestRejection()` —— 与 `/api` 同一套 Host/Origin fence + 浏览器 cookie 认证 | DSH 提供 `webServer` 服务(web profile);desktop 无此服务 → 自动回退 loopback |
|
|
94
129
|
|
|
95
|
-
- 在 `cordis.patch.yml` 的 `config.serve`
|
|
130
|
+
- 在 `cordis.patch.yml` 的 `config.serve`(或设置文档里的 `code-server.serve`)切换,下次启动生效 —— **设置卡片不提供这一行**(卡片只有认领范围/后台常驻两个设置)。
|
|
96
131
|
- `dsh` 模式的实际收益:单一 URL/单一端口(远程访问 DSH 即可用 IDE)、不再暴露额外回环端口、认证与 DSH 同级。
|
|
97
132
|
- `dsh` 模式的两点**已知取舍**:
|
|
98
133
|
1. iframe 与 DSH **同源** → 该模式下不再挂 `sandbox`(同源 + `allow-same-origin` 可被 frame 自行摘除,属"看起来有防护");
|
|
@@ -114,7 +149,7 @@
|
|
|
114
149
|
> 也不会后台启动 IDE。升级 DSH 到带右侧栏的版本(≥ 0.1.5-alpha.1)后,Code Server 会出现在右侧栏标签里,
|
|
115
150
|
> 本页同时显示完整设置项;升级后无需重装本插件,刷新页面即可。
|
|
116
151
|
|
|
117
|
-
- **没有任何其他 UI**:不注册 `shell.overlay`(悬浮球)
|
|
152
|
+
- **没有任何其他 UI**:不注册 `shell.overlay`(悬浮球)、不认领文件地址、不做常驻预热。
|
|
118
153
|
- **host 侧**:客户端会 `POST /api/code-server/ui-mode { sidebar:false }`;host 收到后
|
|
119
154
|
① 不再自动预启动 IDE(`maybePrestart` 直接返回),② 若 IDE 是本插件刚自动预启动且尚未被 adopt,则**回收**该进程,
|
|
120
155
|
避免留下一个用不上的 IDE 与端口。用户手动启动的实例(`adopted`)不会被停。
|
|
@@ -345,16 +380,18 @@ host 探测顺序:`@jinsiyu/dshcs-vscode-server/vscode`(**0.2.0+ 正式布局**)
|
|
|
345
380
|
|
|
346
381
|
| 键 | 默认 | 说明 |
|
|
347
382
|
|---|---|---|
|
|
348
|
-
| `
|
|
383
|
+
| `fileOpenScope` | `session` | **认领范围**(0.2.5):`session` = 只认领会话作用域的文件地址(`dsh-resource://file/session/…`,即官方产物/交付/正文提及);`all` = 连无会话的绝对路径(`…/file/absolute/…`)也认领。未认领的地址由 DSH 自带预览兜底 |
|
|
349
384
|
| `keepResident` | `true` | **后台常驻**:开启后宿主启动即把 IDE 预加载到"停放区",切标签/收起侧栏不重载、首次打开免等待;关闭则只在打开面板时加载(省内存) |
|
|
350
|
-
|
|
385
|
+
|
|
386
|
+
(0.2.6 起卡片只留上面两个设置;`windowedOpen` 与 `reserveComposer` 已移除 —— 旧设置文档里残留的键既不报错也不生效。
|
|
387
|
+
`serve` 仍是设置命名空间里的键(便于用设置文档切换),但**没有卡片行**,见「服务方式」。)
|
|
351
388
|
|
|
352
389
|
卡片底部是**环境检测**(点「检测环境」读取 host `status.env`):
|
|
353
390
|
树版本 / `productPath` / server 入口、VS Code 内部依赖、**预编译原生包**(平台聚合包名 + 已解析模块数)。
|
|
354
391
|
0.1.36 起没有「安装环境」按钮 —— 依赖由包管理器安装,卡片里只显示结果。
|
|
355
392
|
|
|
356
|
-
> 卡片改动经 `scope.watch` 实时生效(host 端 status API 同步返回 `
|
|
357
|
-
> `
|
|
393
|
+
> 卡片改动经 `scope.watch` 实时生效(host 端 status API 同步返回 `keepResident` 与
|
|
394
|
+
> `fileOpenScope`,客户端立即生效);无需重启 dsh。**新增设置键后首次使用前需重启 dsh web**,
|
|
358
395
|
> 让 host 重新注册设置命名空间(schema 含新键),否则新键的保存与校验不生效。
|
|
359
396
|
|
|
360
397
|
## 配置(cordis.patch.yml 的 `config`,均有默认值)
|
|
@@ -402,11 +439,46 @@ desktop profile 由 `apps/desktop-host` 把 `/api/*` 交给同一个 `createShar
|
|
|
402
439
|
|
|
403
440
|
- host 半部 `inject = ['connection', 'settings']`(**不含 `webServer`**)——desktop profile 关掉了 webserver/web-runtime,
|
|
404
441
|
本插件照常工作;`/api/*` 请求由 Electron `dsh-app://` 协议处理器 → IPC 帧管道 → `createSharedFetchHandler('/api')`。
|
|
405
|
-
- 右侧栏标签、guide
|
|
442
|
+
- 右侧栏标签、guide 入口框、文件地址认领、设置卡片在 desktop 下与 web 相同(code-server 仍是本机 `http://127.0.0.1:<port>` 的 iframe;
|
|
406
443
|
桌面端 `webSecurity: true` 且页面无 CSP 限制,跨源 iframe 正常加载)。
|
|
407
444
|
桌面端同样自带 `dsh-client-ui-sidebar-right`(见 desktop 构建 seed 包列表),因此 0.2.3 的
|
|
408
445
|
"只支持带右侧栏的 DSH" 对 desktop 不构成降级;唯一差别是 desktop 无 `webServer`,`serve: dsh` 会自动回退 loopback。
|
|
409
|
-
- 安装到 desktop profile
|
|
446
|
+
- 安装到 desktop profile:桌面端插件管理窗(**不是** CLI,见下)。
|
|
447
|
+
- **桌面端安装的 24 小时供应链策略(实测,2026-09-10,已用它装上 0.2.4)**:
|
|
448
|
+
- CLI 路径不可用:`dsh plugin --profile desktop …` 会被拒绝(*"profile "desktop" is managed exclusively by the Electron application"*),
|
|
449
|
+
桌面端只能走应用内的包事务(`pnpm add <spec> --save-exact`,在 `~/.dsh/desktop/staging/<uuid>/profile` 里执行后激活)。
|
|
450
|
+
- 该事务用的 pnpm(应用自带 **11.7.0**,DeepSeek 打过补丁)在 `add` 前先做**锁文件供应链校验**:
|
|
451
|
+
"Verifying lockfile against supply-chain policies (717 entries)",默认要求**发布满 24 小时**,
|
|
452
|
+
否则 `ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION`。
|
|
453
|
+
- **关键区别(两者行为不同,实测)**:
|
|
454
|
+
- 校验**已有锁文件**时:不接受 `minimumReleaseAgeExclude`(精确版本、裸包名都试过,不放行);
|
|
455
|
+
- **解析**(没有锁文件可校验时,如 `pnpm clean --lockfile` 之后):**认**这份名单,而且 pnpm 自己会往
|
|
456
|
+
`pnpm-workspace.yaml` 追加条目(安装日志会打印 *"Added N entries to minimumReleaseAgeExclude…"*)。
|
|
457
|
+
- 因此桌面端装**刚发布**(<24h)版本的可行路径是 **从"没有锁文件"的干净起点安装**:
|
|
458
|
+
1. `pnpm clean --lockfile`(**注意:它会连 `node_modules` 一起删**,profile 变成待重装状态);
|
|
459
|
+
2. 用应用自带的 runtime 在 profile 目录里 `add <spec> --save-exact --trust-lockfile`
|
|
460
|
+
(运行时/仓库/配置目录都在 `~/.dsh/desktop/pnpm/{store,cache,state,config,home}`,`--config.userconfig=…/config/npmrc`,
|
|
461
|
+
否则会出现 `ERR_PNPM_UNEXPECTED_STORE` / `…UNEXPECTED_VIRTUAL_STORE`);
|
|
462
|
+
3. 安装后应用启动用的 `install --offline --frozen-lockfile --trust-lockfile` 可正常通过(锁文件与 package.json 一致、
|
|
463
|
+
包已在 store);`dsh.profile.bundles` 里已有插件名时不需要再改。
|
|
464
|
+
- 不要用 `minimumReleaseAge: 0` 绕过:它确实能让校验通过,但那个键**不在应用容忍的 policy 段里**
|
|
465
|
+
(`project-manager.ts` 只忽略 `minimumReleaseAgeExclude:` / `trustPolicyExclude:`,且每次 `mutate()` 前都会校验),
|
|
466
|
+
写进去会让应用报 *"core package mapping does not match desktop-packages.json"*。
|
|
467
|
+
- 也可以选择 **等满 24 小时**再在插件管理里正常安装;web profile 不受影响(它的 `pnpm-workspace.yaml` 是 `minimumReleaseAge: false`)。
|
|
468
|
+
- 本插件的依赖闭包里含平台原生子包(`@jinsiyu/dsh-code-server-runtime-win32-*`),它们与插件本身**同批发布**,
|
|
469
|
+
因此每次新版本在桌面端都会受这条策略约束。
|
|
470
|
+
- **桌面端的客户端 bundle 会被 Electron 缓存,重启应用不保证换新**(2026-09 实测,0.2.5 踩到):
|
|
471
|
+
- 现象:profile 里 `lib/client.js` 已是新版本,但渲染器仍跑旧代码——`%APPDATA%\@deepseek-ai\dsh-desktop\Code Cache\js`
|
|
472
|
+
里只有旧版本独有的字符串(如 `dshcs-artifacts`),新版本独有的字符串(如 `fileOpenScope`)一个都没有;
|
|
473
|
+
`Cache\` 里也存着一份引用 `dsh-code-server-app` 的旧响应体。官方插件同理(缓存里那份 `ui-deliverables`
|
|
474
|
+
连当前的 `data-presented-files-row` 都没有)。
|
|
475
|
+
- 诊断手法(字节级,注意别用按控制台编码读文件的 `Select-String`,中文标记会假阴性):
|
|
476
|
+
在 `Code Cache\js` 里搜本版本独有的**ASCII** 标记(我们用 `fileOpenScope`),命中即说明新 bundle 真的被编译过。
|
|
477
|
+
- 修法:完全关闭应用后删 `Cache`、`Code Cache`、`GPUCache` 三个目录再启动(只清缓存,不动 profile/会话/设置):
|
|
478
|
+
```powershell
|
|
479
|
+
Remove-Item -Recurse -Force "$env:APPDATA\@deepseek-ai\dsh-desktop\Cache","$env:APPDATA\@deepseek-ai\dsh-desktop\Code Cache","$env:APPDATA\@deepseek-ai\dsh-desktop\GPUCache"
|
|
480
|
+
```
|
|
481
|
+
- 影响面:不只本插件——**任何**客户端插件升级后都可能继续跑旧代码;发布后请按上面的标记法确认渲染器真的换了 bundle。
|
|
410
482
|
|
|
411
483
|
## 已知限制
|
|
412
484
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// dshcs-open-file:DSH host
|
|
1
|
+
// dshcs-open-file:DSH host 通过信号文件请求打开文件(可带 1 基行号)。
|
|
2
2
|
// host 写入 <user-data>/User/dshcs-open.json 后,本扩展在已连接的窗口中打开该文件。
|
|
3
3
|
// 信号路径优先取环境变量 DSHCS_OPEN_FILE_SIGNAL(host 注入);
|
|
4
4
|
// 取不到时用 context.globalStorageUri 推导(=<user-data>/User/globalStorage/<id> 的上两级)。
|
|
@@ -25,14 +25,22 @@ function processSignal(signal) {
|
|
|
25
25
|
return; // 尚无信号
|
|
26
26
|
}
|
|
27
27
|
let file = null;
|
|
28
|
+
let line = null;
|
|
28
29
|
try {
|
|
29
|
-
|
|
30
|
+
const parsed = JSON.parse(raw);
|
|
31
|
+
file = parsed.file;
|
|
32
|
+
line = typeof parsed.line === 'number' && Number.isSafeInteger(parsed.line) && parsed.line > 0 ? parsed.line : null;
|
|
30
33
|
} catch {
|
|
31
34
|
return;
|
|
32
35
|
}
|
|
33
36
|
if (typeof file !== 'string' || file === '') return;
|
|
34
37
|
const uri = vscode.Uri.file(file);
|
|
35
|
-
|
|
38
|
+
const options = { preview: false };
|
|
39
|
+
if (line !== null) {
|
|
40
|
+
const at = new vscode.Position(line - 1, 0);
|
|
41
|
+
options.selection = new vscode.Range(at, at);
|
|
42
|
+
}
|
|
43
|
+
vscode.window.showTextDocument(uri, options).then(
|
|
36
44
|
() => {
|
|
37
45
|
try {
|
|
38
46
|
fs.unlinkSync(signal);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dshcs-open-file",
|
|
3
3
|
"displayName": "DSH Code Server Open File",
|
|
4
|
-
"description": "Opens files requested by the DSH host through a signal file (dshcs-open.json).",
|
|
5
|
-
"version": "0.0.
|
|
4
|
+
"description": "Opens files requested by the DSH host through a signal file (dshcs-open.json), optionally at a line.",
|
|
5
|
+
"version": "0.0.2",
|
|
6
6
|
"publisher": "dsh-code-server-app",
|
|
7
7
|
"engines": {
|
|
8
8
|
"vscode": "^1.80.0"
|
package/cordis.patch.yml
CHANGED
|
@@ -30,8 +30,7 @@
|
|
|
30
30
|
locale: ''
|
|
31
31
|
# 启动就绪探测超时(ms)。
|
|
32
32
|
readyTimeoutMs: 60000
|
|
33
|
-
#
|
|
34
|
-
# 卡片控制,持久化于官方 settings 域(命名空间 code-server
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
# 旧版上只在设置页给一条升级提示,不提供任何入口,也不预启动 IDE。
|
|
33
|
+
# 注:后台常驻(keepResident,默认 true)与认领范围(fileOpenScope,默认 session)由
|
|
34
|
+
# "设置 → 插件 → Code Server"卡片控制,持久化于官方 settings 域(命名空间 code-server),
|
|
35
|
+
# 卡片修改即时生效。服务方式(serve)没有卡片行:改这里的 config.serve 或设置文档。
|
|
36
|
+
# 另:不再兼容旧版 DSH(无 sidebarRightTabs/sidebarRight 服务),旧版上仅给设置页提示。
|
package/lib/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
window.__ModuleLoader__.load({id:'dsh-code-server-app',factory:function(require){var module={exports:{}};var exports=module.exports;
|
|
2
|
-
var z=Object.defineProperty;var pe=Object.getOwnPropertyDescriptor;var be=Object.getOwnPropertyNames;var he=Object.prototype.hasOwnProperty;var ve=(e,r)=>{for(var n in r)z(e,n,{get:r[n],enumerable:!0})},me=(e,r,n,s)=>{if(r&&typeof r=="object"||typeof r=="function")for(let l of be(r))!he.call(e,l)&&l!==n&&z(e,l,{get:()=>r[l],enumerable:!(s=pe(r,l))||s.enumerable});return e};var ge=e=>me(z({},"__esModule",{value:!0}),e);var $e={};ve($e,{apply:()=>Je,inject:()=>Xe,name:()=>Ke});module.exports=ge($e);var C=typeof Element!="undefined"&&typeof Element.prototype.moveBefore=="function",ye=-2e4,t={park:null,frame:null,currentSrc:null,sameOrigin:null,owner:null,lastRect:null,parkStrategy:"offscreen",degraded:!1,preloaded:!1,nudgeCount:0,nudgeEnabled:!0,lastNudgeAt:0,listeners:new Set};function I(){return{ready:t.frame!==null,docked:t.owner!==null,owner:t.owner,src:t.currentSrc,sameOrigin:t.sameOrigin,parkStrategy:t.parkStrategy,degraded:t.degraded,preloaded:t.preloaded,supportsMoveBefore:C,nudgeCount:t.nudgeCount,lastNudgeAt:t.lastNudgeAt}}function T(){var e=I();t.listeners.forEach(function(r){try{r(e)}catch(n){}})}function J(e){return t.listeners.add(e),function(){t.listeners.delete(e)}}function q(){return I()}function we(e){e!=="offscreen"&&e!=="behind"||t.parkStrategy!==e&&(t.parkStrategy=e,t.frame!==null&&t.owner===null&&P(),T())}function xe(){return t.parkStrategy}function ke(){var e=t.lastRect;e!==null&&(t.park.style.width=Math.max(1,Math.round(e.width))+"px",t.park.style.height=Math.max(1,Math.round(e.height))+"px")}function P(){if(t.park!==null){if(ke(),t.parkStrategy==="behind"&&t.lastRect!==null){t.park.style.left=Math.round(t.lastRect.left)+"px",t.park.style.top=Math.round(t.lastRect.top)+"px",t.park.style.visibility="visible",t.park.style.zIndex="0";return}t.park.style.left=ye+"px",t.park.style.top="0px",t.park.style.visibility="hidden",t.park.style.zIndex="0"}}function X(){t.frame!==null&&(t.frame.setAttribute("inert",""),t.frame.setAttribute("aria-hidden","true"))}function Se(){t.frame!==null&&(t.frame.removeAttribute("inert"),t.frame.removeAttribute("aria-hidden"))}function Ee(){var e=document.createElement("div");e.className="dshcs-park",e.setAttribute("data-dshcs-park",""),e.setAttribute("aria-hidden","true");var r=document.createElement("iframe");return r.className="dshcs-frame",r.setAttribute("title","code-server"),r.setAttribute("allow","clipboard-read; clipboard-write"),r.setAttribute("data-dshcs-resident",""),r.src="about:blank",e.appendChild(r),document.body.appendChild(e),t.park=e,t.frame=r,t.currentSrc="about:blank",t.owner=null,P(),X(),r}function Ne(e){var r=t.frame;if(r!==null){var n=t.sameOrigin!==e;!n&&r.hasAttribute("data-dshcs-attrs")||(e===!0?r.removeAttribute("sandbox"):e===!1&&r.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-modals allow-popups allow-pointer-lock allow-clipboard-read allow-clipboard-write"),r.setAttribute("data-dshcs-attrs",e===!0?"same-origin":"cross-origin"),t.sameOrigin=e)}}function H(e){var r=e||{};return t.frame===null&&Ee(),typeof r.sameOrigin=="boolean"&&Ne(r.sameOrigin),typeof r.src=="string"&&r.src!==""&&r.src!==t.currentSrc&&Ce(r.src),t.frame}function Ce(e){t.frame===null||typeof e!="string"||e===""||e===t.currentSrc||(t.currentSrc=e,t.frame.src=e,T())}function K(){var e=t.frame;if(t.nudgeEnabled!==!0||e===null||e.isConnected!==!0)return!1;var r=e.style.display;return e.style.display="none",e.offsetHeight,e.style.display=r,t.nudgeCount+=1,t.lastNudgeAt=Date.now(),!0}function Te(e){return t.nudgeEnabled=e!==!1,t.nudgeEnabled}function $(e){if(t.frame!==null){if(C)try{e.moveBefore(t.frame,null);return}catch(r){t.degraded=!0,t.lastMoveError=(r&&r.name?r.name+": ":"")+(r&&r.message?r.message:String(r))}else t.degraded=!0;e.appendChild(t.frame)}}function U(e,r){if(!(t.frame===null||e==null)){var n=t.owner===null,s=e.getBoundingClientRect();s.width>=1&&s.height>=1&&(t.lastRect={left:s.left,top:s.top,width:s.width,height:s.height}),t.owner=r===void 0?null:r,Se(),t.park.setAttribute("aria-hidden","true"),$(e),n&&K(),T()}}function L(e){t.frame!==null&&(e!==void 0&&t.owner!==e||(t.owner=null,P(),X(),t.park.setAttribute("aria-hidden","true"),$(t.park),T()))}function B(e){var r=e||{};return H(r),t.owner===null&&(typeof r.src=="string"&&r.src!==""&&(t.preloaded=!0),L()),t.frame}function Le(){t.park!==null&&t.park.parentNode!==null&&t.park.parentNode.removeChild(t.park),t.park=null,t.frame=null,t.currentSrc=null,t.sameOrigin=null,t.owner=null,t.lastRect=null,t.degraded=!1,t.preloaded=!1,t.nudgeCount=0,t.lastNudgeAt=0,T()}typeof window!="undefined"&&(window.__dshcsSurface={snapshot:I,setParkStrategy:we,getParkStrategy:xe,preload:B,dock:U,park:L,nudge:K,setNudgeEnabled:Te,destroy:Le});var a=require("react"),V=new Set,R={status:null,busy:!1,sidebarActive:!1,sidebarUi:"unknown",sidebarRegisterFailed:!1};function k(e){R=Object.assign({},R,e),V.forEach(function(r){r()})}function Oe(e){return V.add(e),function(){V.delete(e)}}function W(){return R}function D(){return a.useSyncExternalStore(Oe,W)}var Re="/api",le="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMTQ3IDE0NyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8c3R5bGU+QG1lZGlhIChwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyaykgeyogeyBmaWxsOiB3aGl0ZTsgfX08L3N0eWxlPgogIDxwYXRoIGQ9Im00Mi40MjE0LDM5LjY1NWMtMjQuNDA1NywwIC00Mi4xNTU0LDEzLjE3MjEgLTQyLjE1NTQsMzMuODQ1YzAsMjAuNTgxNCAxOC40ODkyLDMzLjg0NSA0Mi4xNTU0LDMzLjg0NWMyMy42NjYyLDAgMzguMTgwMywtMTEuNjE3MSAzOC43MzQ5LC0yOC43MjI1bC0yMS4wNzc3LC0wLjQ1NzRjLTAuOTI0NCw5LjMzMDMgLTkuMTA1OSwxNS4xODQ1IC0xNy42NTcyLDE1LjE4NDVjLTExLjc0MDYsMCAtMjAuNDMwNiwtNy41OTIyIC0yMC40MzA2LC0xOS44NDk2YzAsLTEyLjI1NzQgOC42OSwtMTkuOTg2OCAyMC40MzA2LC0yMC4yMTU1YzguNTUxMywtMC4xODMgMTYuOTE3Nyw1Ljk0NTcgMTcuNDcyMywxNS4yNzZsMjEuMDc3NywtMC42NDAzYy0wLjQ2MjIsLTE2LjgzMTEgLTE0LjE0NDIsLTI4LjI2NTIgLTM4LjU1LC0yOC4yNjUyem00OC44NDQ2LDJsNTUuNDY4LDBsMCw2NC4wMzExbC01NS40NjgsMGwwLC02NC4wMzExeiIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz4KPC9zdmc+Cg==";async function x(e,r){var n={method:r===void 0?"GET":"POST",headers:{}};r!==void 0&&(n.headers["content-type"]="application/json",n.body=JSON.stringify(r));var s=await fetch(Re+e,n),l=await s.text(),i=null;try{i=l===""?null:JSON.parse(l)}catch(d){i=null}return s.ok?i!==null?i:{ok:!1,error:"invalid JSON response"}:{ok:!1,error:"HTTP "+s.status+(i!==null&&i.error!==void 0?": "+i.error:"")}}function M(e,r){try{var n=e(function(p){return p}),s=r===null?null:typeof r=="function"?r(function(p){return p}):null,l=n!=null?n.current:void 0;if(l!==void 0&&n!=null&&n.byId!=null){var i=n.byId[l];if(i!=null&&typeof i.cwd=="string"&&i.cwd!=="")return i.cwd}var d=s!=null&&Array.isArray(s.items)?s.items:[];if(l!==void 0)for(var c=0;c<d.length;c++){var v=d[c];if(v.sessionIds!=null&&v.sessionIds.indexOf(l)!==-1&&typeof v.path=="string"&&v.path!=="")return v.path}var u=s!=null?s.recentWorkspaceId:void 0;if(u!==void 0){for(var b=0;b<d.length;b++)if(d[b].workspaceId===u&&typeof d[b].path=="string"&&d[b].path!=="")return d[b].path}if(d.length>0&&typeof d[0].path=="string"&&d[0].path!=="")return d[0].path}catch(p){}}function F(e,r){if(e==null||typeof e.url!="string"||e.url==="")return null;var n=typeof r=="string"&&r!==""?r:e!=null&&e.cwd!=null?e.cwd:null;if(n==null||n==="")return e.url;var s=n.replace(/\\/g,"/"),l=s;return(/^[A-Za-z]:\//.test(s)||s.charCodeAt(0)!==47)&&(l="/"+s),e.url+"?folder="+encodeURIComponent(l)}function Me(e){var r=e.status,n=e.pageUrl,s=e.reloadTick,l=e.owner,i=a.useRef(null),d=r!=null&&r.ok===!0&&r.running===!0,c=r!=null&&r.status==="starting",v=r!=null&&r.ok===!1,u=r!=null&&r.serve==="dsh";if(a.useLayoutEffect(function(){if(!d||n===null){L(l);return}H({src:n,sameOrigin:u}),i.current!==null&&U(i.current,l)},[d,n,u,s,l]),a.useLayoutEffect(function(){return function(){L(l)}},[l]),d&&n!==null)return a.createElement("div",{ref:i,className:"dshcs-slot","data-code-server-slot":l!=null?l:"code-server"});if(c)return a.createElement("div",{className:"dshcs-loading"},"\u6B63\u5728\u542F\u52A8 code-server\u2026");var b=v&&r!=null&&r.error?r.error:"code-server \u672A\u8FD0\u884C",p=u?"\u5F53\u524D\u4EE5 DSH \u540C\u6E90\u8DEF\u5F84 "+(r!=null&&r.url||"/code-server/")+" \u63D0\u4F9B(\u65E0\u72EC\u7ACB\u7AEF\u53E3)\u3002":"\u5F53\u524D\u4EE5\u72EC\u7ACB\u56DE\u73AF\u7AEF\u53E3\u63D0\u4F9B(\u7AEF\u53E3 "+(r!=null&&r.port!=null?r.port:"8090")+" \u88AB\u5360\u7528\u65F6\u8BF7\u91CA\u653E\u6216\u4FEE\u6539 port \u914D\u7F6E)\u3002",m=C?"\u5E38\u9A7B\u9762:\u53EF\u7528(\u5207\u6807\u7B7E/\u6536\u8D77\u4FA7\u680F\u4E0D\u91CD\u8F7D)\u3002":"\u5E38\u9A7B\u9762:\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301 Element.moveBefore \u2014\u2014 \u5207\u6807\u7B7E\u4F1A\u6574\u9875\u91CD\u8F7D(\u5347\u7EA7\u6D4F\u89C8\u5668\u540E\u81EA\u52A8\u53EF\u7528)\u3002";return a.createElement("div",{className:"dshcs-empty"},a.createElement("div",{className:"dshcs-emptybox"},a.createElement("div",null,v?"code-server \u542F\u52A8\u5931\u8D25":"code-server \u672A\u8FD0\u884C"),a.createElement("pre",{className:"dshcs-error"},b),a.createElement("p",{className:"dshcs-hint"},"VS Code \u6811\u968F\u63D2\u4EF6\u5305\u5185\u7F6E\u3001\u5C31\u5730\u8FD0\u884C(\u65E0\u9700\u5168\u5C40\u5B89\u88C5\u3001\u65E0\u9700\u8054\u7F51\u5B89\u88C5\u3001\u65E0\u300C\u5B89\u88C5\u73AF\u5883\u300D\u6B65\u9AA4);\u5185\u90E8\u4F9D\u8D56\u4E0E\u9884\u7F16\u8BD1\u539F\u751F\u6A21\u5757\u7531\u5305\u7BA1\u7406\u5668\u5728\u5B89\u88C5\u63D2\u4EF6\u65F6\u4E00\u5E76\u88C5\u597D(\u65E0\u9700 C++ \u5DE5\u5177\u94FE)\u3002\u82E5\u6B64\u5904\u957F\u671F\u672A\u8FD0\u884C,\u8BF7\u5230 \u8BBE\u7F6E \u2192 \u63D2\u4EF6 \u2192 Code Server \u70B9\u300C\u68C0\u6D4B\u73AF\u5883\u300D\u67E5\u770B\u539F\u56E0\u3002"+p+m)))}function Ae(e){var r=D(),n=r.status,s=n!=null&&n.ok===!0&&n.running===!0,l=n!=null&&n.keepResident===!0,i=M(e&&e.useSessions,e&&e.useWorkspaces),d=s?F(n,i):null;return a.useEffect(function(){!l||!s||d===null||B({src:d,sameOrigin:n!=null&&n.serve==="dsh"})},[l,s,d,n!=null?n.serve:null]),null}function ee(e){var r=function(s){var l=F(s,e);l!=null&&typeof window.open=="function"&&window.open(l,"_blank","noopener")},n=W().status;if(n!=null&&n.running===!0){r(n);return}W().busy!==!0&&(k({busy:!0}),x("/code-server/start",typeof e=="string"?{cwd:e}:{}).then(function(s){k({status:s,busy:!1}),r(s)}).catch(function(){k({busy:!1})}))}var De=".dshcs-artbtn{appearance:none;display:inline-grid;place-items:center;width:22px;height:22px;padding:0;border:1px solid var(--dsw-alias-border-l2,#dfe3eb);border-radius:6px;color:var(--dsw-alias-label-secondary,#566174);background:color-mix(in srgb,var(--dsw-alias-bg-base,#fff) 60%,transparent);cursor:pointer;transition:color .12s ease,background .12s ease,border-color .12s ease;vertical-align:middle}.dshcs-artbtn:hover{color:var(--dsw-alias-label-primary,#172033);border-color:color-mix(in srgb,var(--dshcs-accent,#5b6cff) 40%,var(--dsw-alias-border-l2,#dfe3eb));background:color-mix(in srgb,var(--dshcs-accent,#5b6cff) 8%,transparent)}.dshcs-artbtn:active{transform:scale(.94)}.dshcs-artbtn:focus-visible{outline:2px solid color-mix(in srgb,var(--dshcs-accent,#5b6cff) 65%,transparent);outline-offset:1px}.dshcs-artifacts{display:grid;grid-template-columns:max-content minmax(0,1fr);align-items:center;gap:6px 8px;margin-top:16px;font-size:13px;line-height:22px;position:relative}.dshcs-artlabel{color:var(--dsw-alias-label-tertiary,#7d8798);grid-area:1/1}.dshcs-artrow{flex-wrap:nowrap;grid-area:1/2;align-items:center;gap:8px;min-width:0;display:flex;overflow:hidden}.dshcs-artitem{display:inline-flex;align-items:center;gap:4px;flex:none;min-width:0}.dshcs-artfile{text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-interactive-bg-hover);max-width:320px;color:var(--dsw-alias-label-secondary,#566174);font:inherit;cursor:pointer;border:none;border-radius:6px;margin:0;padding:0 8px;overflow:hidden}.dshcs-artfile:hover{color:var(--dsw-alias-label-primary,#172033);text-decoration:underline}.dshcs-artfile:focus-visible{box-shadow:inset 0 0 0 2px var(--dsw-alias-border-l3);outline:none}.dshcs-artmore{white-space:nowrap;color:var(--dsw-alias-label-tertiary,#7d8798);flex:none}.dshcs-frame{display:block;position:absolute;inset:0;z-index:1;width:100%;height:100%;border:0;background:var(--dsw-alias-bg-base,#fff)}.dshcs-tabroot{position:relative;display:flex;flex-direction:column;width:100%;height:100%;min-width:0;min-height:0;background:var(--dsw-alias-bg-base,#fff)}.dshcs-slot{position:relative;display:block;width:100%;height:100%;min-width:0;min-height:0;overflow:hidden;background:var(--dsw-alias-bg-base,#fff)}.dshcs-park{position:fixed;left:-20000px;top:0;width:320px;height:200px;overflow:hidden;pointer-events:none;z-index:0;visibility:hidden;contain:strict}.dshcs-loading{position:absolute;inset:0;z-index:2;display:grid;place-items:center;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-tertiary,#7d8798);font-size:13px}.dshcs-empty{position:relative;z-index:2;flex:1;display:flex;align-items:center;justify-content:center;padding:44px 24px 24px}.dshcs-emptybox{max-width:560px;text-align:left;background:var(--dsw-alias-bg-layer-2,#f7f8fb);border:1px solid var(--dsw-alias-border-l2,#dfe3eb);border-radius:12px;padding:16px 18px}.dshcs-error{color:var(--dsw-alias-label-error,#d92d20);white-space:pre-wrap;word-break:break-all;font-family:ui-monospace,Consolas,monospace;font-size:12px;margin:8px 0 0}.dshcs-hint{color:var(--dsw-alias-label-tertiary,#7d8798);font-size:12px;margin:6px 0 0}.dshcs-legacy{color:var(--dsw-alias-label-warning,#b54708);font-size:12px;font-weight:600;margin:0 0 6px}",re="dsh-code-server/styles";typeof document!="undefined"&&document.querySelector("style[data-dshcs="+JSON.stringify(re)+"]")===null&&(O=document.createElement("style"),O.setAttribute("data-dshcs",re),O.textContent=De,document.head.appendChild(O));var O,_="code-server",ae="dsh-code-server-app",je=2500,ze=1e4,Ie=1500,N={openTab:null};function Pe(e){var r=e!=null&&typeof e.size=="number"?e.size:16;return a.createElement("img",{src:le,alt:"","aria-hidden":!0,draggable:!1,className:e!=null?e.className:void 0,style:{width:r,height:r,display:"block",objectFit:"contain",WebkitUserDrag:"none",userSelect:"none"}})}function He(e){var r=e.useTabInfo(),n=r.tab,s=D(),l=s.status,i=M(e.useSessions,null),d=a.useRef(void 0),[c,v]=a.useState(0),u=n.navigation,b=u!=null&&typeof u.revision=="number"?u.revision:0;return a.useEffect(function(){if(!(typeof i!="string"||i==="")&&d.current!==i){var p=d.current!==void 0;d.current=i;var m=!1;return x("/code-server/start",{cwd:i}).then(function(f){m||(k({status:f}),p&&f!=null&&f.ok===!0&&f.running===!0&&v(function(w){return w+1}))}).catch(function(){}),function(){m=!0}}},[i]),a.useEffect(function(){x("/code-server/status").then(function(m){m!=null&&k({status:m})}).catch(function(){});var p=window.setInterval(function(){x("/code-server/status").then(function(m){k({status:m})}).catch(function(){})},3e3);return function(){window.clearInterval(p)}},[]),a.useEffect(function(){var p=u!=null?u.params:null,m=p!=null&&typeof p.path=="string"?p.path:"";m!==""&&x("/code-server/open-file",{file:m}).catch(function(){})},[b]),a.createElement("div",{className:"dshcs-tabroot","data-code-server-tab":"body"},a.createElement(Me,{status:l,pageUrl:F(l,i),reloadTick:c,owner:"tab:"+n.id}))}function G(e,r){if(e==null)return null;var n=e[r];if(n!=null)return n;if(typeof e.get=="function"){var s=e.get(r);if(s!=null)return s}return null}function Ue(e){var r=G(e,"sidebarRightTabs"),n=G(e,"sidebarRight");if(r==null||n==null)return console.error("[code-server] \u53F3\u4FA7\u680F\u670D\u52A1\u4E0A\u4E0B\u6587\u4E0D\u53EF\u89C1(sidebarRightTabs="+(r!=null)+", sidebarRight="+(n!=null)+"):\u8DF3\u8FC7\u4FA7\u680F\u6CE8\u518C"),!1;var s=G(e,"slots");if(e.effect(function(){return r.register({id:ae,kind:_,priority:"extension",title:function(){return"Code Server"},guide:[{order:20,title:function(){return"Code Server"},description:function(){return"\u5728\u53F3\u4FA7\u680F\u6807\u7B7E\u91CC\u8FD0\u884C VS Code \u7F51\u9875\u7248,\u8DDF\u968F\u5F53\u524D\u4F1A\u8BDD\u5DE5\u4F5C\u533A\u3002"},icon:Pe}]})},"code-server: sidebar tab type"),s!=null)e.effect(function(){return s.inject("sidebar.right.pane.tab",function(){return s.register({name:"sidebar.right.pane.tab",key:ae},He)})},"code-server: sidebar tab body");else return console.error("[code-server] slots \u670D\u52A1\u4E0D\u53EF\u89C1:\u4FA7\u680F\u6807\u7B7E body \u672A\u6CE8\u518C"),!1;return N.openTab=function(l){try{return n.openTab(_,l!=null?{params:l}:void 0),!0}catch(i){return console.warn("[code-server] sidebar openTab failed:",i!=null&&i.message!=null?i.message:String(i)),!1}},e.effect(function(){return function(){N.openTab=null,k({sidebarActive:!1,sidebarUi:"unknown"})}},"code-server: sidebar mode reset"),console.log("[code-server] right-sidebar tab registered (kind="+_+")"),!0}var Be=".dshcs-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.dshcs-card:hover{border-color:var(--dsw-alias-label-dimmed,var(--dsw-alias-border-l2))}.dshcs-cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed,var(--dsw-alias-border-l2))}.dshcs-cardHeader{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.dshcs-cardHeader:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.dshcs-cardHeadText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.dshcs-cardName{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.dshcs-cardDescription{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));font-size:13px;line-height:1.5}.dshcs-cardChevron{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));flex:none;transition:transform .16s;display:inline-flex}.dshcs-cardChevronOpen{transform:rotate(180deg)}.dshcs-cardBody{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.dshcs-cardReadOnly{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));margin:12px 0 0;font-size:12px;line-height:1.5}.dshcs-pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform,var(--dsw-alias-bg-layer-2));color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.dshcs-cardFooter{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.dshcs-cardFailed{min-width:0;color:var(--dsw-alias-label-error,var(--dsw-alias-state-error-primary));flex:1;margin:0;font-size:12px;line-height:1.5}.dshcs-cbtn{appearance:none;font:inherit;cursor:pointer;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5;border:1px solid transparent;transition:color .12s ease,background .12s ease}.dshcs-cbtn:disabled{opacity:.4;cursor:default}.dshcs-cbtn:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.dshcs-cbtnOutline{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.dshcs-cbtnOutline:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover,transparent)}.dshcs-cbtnPrimary{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3);border-color:var(--dsw-alias-label-primary);font-weight:600}.dshcs-cbtnPrimary:hover:not(:disabled){filter:brightness(.95)}.dshcs-cbtnPrimary:active:not(:disabled){filter:brightness(.9)}.dshcs-field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.dshcs-field+.dshcs-field{border-top:1px solid var(--dsw-alias-border-l2)}.dshcs-fieldHead{align-items:center;gap:8px;display:flex}.dshcs-fieldLabel{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.dshcs-hint{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));margin:0;font-size:12px;line-height:1.5}.dshcs-check{display:flex;align-items:center;gap:8px;cursor:pointer}.dshcs-check input{accent-color:var(--dsw-alias-brand-primary);width:15px;height:15px;margin:0;flex:none}.dshcs-check input:disabled{cursor:default}.dshcs-badges{align-items:center;gap:8px;display:inline-flex}.dshcs-badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform,var(--dsw-alias-bg-layer-2));color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.dshcs-reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.dshcs-reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.dshcs-reset:disabled{cursor:default}",_e="dsh-code-server/Card.module.css";function Ge(e,r){if(typeof document!="undefined"&&document.querySelector("style[data-plugin-css="+JSON.stringify(e)+"]")===null){var n=document.createElement("style");n.dataset.plugin="dsh-code-server",n.dataset.pluginCss=e,n.textContent=r,document.head.appendChild(n)}}Ge(_e,Be);function Ve(e){return a.createElement("svg",{width:14,height:14,viewBox:"0 0 14 14",fill:"none","aria-hidden":!0,className:e.className},a.createElement("path",{d:"M3.5 5.25L7 8.75L10.5 5.25",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round"}))}function A(e){return a.createElement("button",{type:"button",className:"dshcs-cbtn "+(e.variant==="primary"?"dshcs-cbtnPrimary":"dshcs-cbtnOutline"),disabled:e.disabled===!0,onClick:e.onClick},e.children)}function te(e){return a.createElement("label",{className:"dshcs-check"},a.createElement("input",{type:"checkbox",checked:e.checked===!0,disabled:e.disabled===!0,onChange:function(r){e.onChange(r.target.checked)}}),a.createElement("span",{className:"dshcs-hint"},e.children))}function ne(e){var r=[];return e.overridden===!0&&(r.push(a.createElement("span",{className:"dshcs-badge"},e.overriddenLabel)),r.push(a.createElement("button",{type:"button",className:"dshcs-reset",disabled:e.disabled===!0,onClick:e.onReset},e.resetLabel))),r.length===0?null:a.createElement("span",{className:"dshcs-badges"},...r)}function se(e){var[r,n]=a.useState(e.defaultOpen===!0),s=e.state;if(s==null||s.available!==!0)return null;var l=e.title,i=e.noticeOnly===!0,d=s.dirty!==!0||s.invalid===!0||s.saving===!0;return a.createElement("li",{className:"dshcs-card"+(r?" dshcs-cardOpen":"")},a.createElement("button",{type:"button",className:"dshcs-cardHeader","aria-expanded":r,onClick:function(){n(!r)}},a.createElement("span",{className:"dshcs-cardHeadText"},a.createElement("span",{className:"dshcs-cardName"},l),a.createElement("span",{className:"dshcs-cardDescription"},e.description)),s.dirty===!0?a.createElement("span",{className:"dshcs-pending"},e.unsavedLabel):null,a.createElement(Ve,{className:"dshcs-cardChevron"+(r?" dshcs-cardChevronOpen":"")})),r===!0?a.createElement("div",{className:"dshcs-cardBody"},i===!0?null:s.writable!==!0?a.createElement("p",{className:"dshcs-cardReadOnly",role:"status"},e.readOnlyLabel):null,e.children,i===!0?null:a.createElement("div",{className:"dshcs-cardFooter"},s.failed===!0?a.createElement("p",{className:"dshcs-cardFailed",role:"status"},e.saveFailedLabel):null,a.createElement(A,{disabled:s.dirty!==!0||s.saving===!0,onClick:e.onDiscard},e.discardLabel),a.createElement(A,{variant:"primary",disabled:d,onClick:e.onSave},s.saving===!0?e.savingLabel:e.saveLabel))):null)}function We(e){try{let E=function(){x("/code-server/status").then(function(h){h!=null&&typeof h=="object"&&k({status:h})}).catch(function(){})};var r=e.scope,[n,s]=a.useState(function(){return r!==void 0?r.getSnapshot():null}),[l,i]=a.useState(null),[d,c]=a.useState(!1),[v,u]=a.useState(!1),b=D(),[p,m]=a.useState(q());if(a.useEffect(function(){return J(function(h){m(h)})},[]),a.useEffect(function(){if(r===void 0||typeof r.subscribe!="function")return;function h(){try{s(r.getSnapshot())}catch(rr){}}var S=r.subscribe(h);return function(){typeof S=="function"&&S()}},[r]),r===void 0)return console.error("[code-server] card scope missing"),null;if(n==null||n.status!=="ready")return n!=null&&n.status==="unavailable"&&console.warn("[code-server] settings scope unavailable:",n.status),null;var f=n.value!==void 0&&n.value!==null?n.value:{},w=n.user,y={windowedOpen:f.windowedOpen===!0,keepResident:f.keepResident!==!1};if(b!=null&&b.sidebarUi==="legacy")return a.createElement(se,{title:"Code Server",description:"\u5F53\u524D DSH \u7248\u672C\u4E0D\u53D7\u652F\u6301(\u7F3A\u5C11\u53F3\u4FA7\u680F\u670D\u52A1)",defaultOpen:!0,noticeOnly:!0,state:{available:!0,writable:!1,dirty:!1,invalid:!1,saving:!1,failed:!1}},a.createElement("div",{className:"dshcs-field"},a.createElement("div",{className:"dshcs-legacy"},"\u672C\u63D2\u4EF6\u81EA 0.2.3 \u8D77\u4E0D\u518D\u517C\u5BB9\u65E7\u7248 DSH\u3002"),a.createElement("div",{className:"dshcs-hint",style:{marginTop:0}},`\u672A\u68C0\u6D4B\u5230\u53F3\u4FA7\u680F\u63D2\u4EF6\u670D\u52A1 sidebarRightTabs / sidebarRight,\u56E0\u6B64\u63D2\u4EF6\u4E0D\u63D0\u4F9B\u4EFB\u4F55\u5165\u53E3(\u65E7\u7248\u7684\u60AC\u6D6E\u7403\u4E0E\u6D6E\u52A8\u7A97\u53E3\u5DF2\u79FB\u9664),\u4E5F\u4E0D\u4F1A\u540E\u53F0\u542F\u52A8 IDE\u3002
|
|
3
|
-
\u5347\u7EA7 DSH \u5230\u5E26\u53F3\u4FA7\u680F\u7684\u7248\u672C(\u2265 0.1.5-alpha.1)\u540E,Code Server \u4F1A\u51FA\u73B0\u5728\u53F3\u4FA7\u680F\u6807\u7B7E\u91CC,\u672C\u9875\u540C\u65F6\u663E\u793A\u5B8C\u6574\u8BBE\u7F6E\u9879;\u5347\u7EA7\u540E\u65E0\u9700\u91CD\u88C5\u672C\u63D2\u4EF6,\u5237\u65B0\u9875\u9762\u5373\u53EF\u3002`)));var g=
|
|
4
|
-
\u5378\u8F7D: dsh plugin --profile web remove dsh-code-server-app`));return
|
|
2
|
+
var P=Object.defineProperty;var ge=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var we=Object.prototype.hasOwnProperty;var Se=(e,r)=>{for(var t in r)P(e,t,{get:r[t],enumerable:!0})},xe=(e,r,t,s)=>{if(r&&typeof r=="object"||typeof r=="function")for(let l of ye(r))!we.call(e,l)&&l!==t&&P(e,l,{get:()=>r[l],enumerable:!(s=ge(r,l))||s.enumerable});return e};var ke=e=>xe(P({},"__esModule",{value:!0}),e);var dr={};Se(dr,{apply:()=>nr,inject:()=>sr,name:()=>ir});module.exports=ke(dr);var X="dsh-resource://file/",Ee="sidebar://",q="session";function I(e){return typeof e=="string"&&e.startsWith(Ee)}function M(e){if(typeof e!="string"||!e.startsWith(X))return null;for(var r=e.length,t=0;t<e.length;t+=1){var s=e.charAt(t);if(s==="?"||s==="#"){r=t;break}}var l=e.slice(X.length,r).split("/"),i=l.shift();try{if(i==="session"){var d=l.shift();return d===void 0||d===""||l.length===0?null:{scope:"session",sessionId:decodeURIComponent(d),path:K(l)}}if(i==="absolute"){var p=l[0]===""&&l.length>1,v=p?l.slice(1):l,c=K(v);return(c===""||c.charAt(0)==="/")&&!p?null:p?{scope:"absolute",path:"//"+c}:c===""?null:{scope:"absolute",path:$(c)?c:"/"+c}}}catch(o){return null}return null}function K(e){for(var r=[],t=0;t<e.length;t+=1)r.push(decodeURIComponent(e[t]));return r.join("/")}function $(e){return/^[A-Za-z]:($|\/)/.test(e)}function Ne(e){return typeof e!="string"||e===""?!1:e.charAt(0)==="/"?!0:$(e)}function ee(e){var r=M(e);if(r===null)return"";var t=r.path.replace(/[/\\]+$/,""),s=Math.max(t.lastIndexOf("/"),t.lastIndexOf("\\")),l=s===-1?t:t.slice(s+1);return l}function re(e,r){if(e===null||e==null)return null;var t=typeof e.path=="string"?e.path:"";if(t==="")return null;if(Ne(t))return t;if(typeof r!="string"||r==="")return null;var s=r.indexOf("\\")!==-1?"\\":"/",l=r.replace(/[\\/]+$/,"");return l+s+(s==="\\"?t.replace(/\//g,"\\"):t)}function te(e,r){return e===null||e==null?!1:e.scope==="session"?!0:r==="all"}var T=typeof Element!="undefined"&&typeof Element.prototype.moveBefore=="function",Ce=-2e4,a={park:null,frame:null,currentSrc:null,sameOrigin:null,owner:null,lastRect:null,parkStrategy:"offscreen",degraded:!1,preloaded:!1,nudgeCount:0,nudgeEnabled:!0,lastNudgeAt:0,listeners:new Set};function H(){return{ready:a.frame!==null,docked:a.owner!==null,owner:a.owner,src:a.currentSrc,sameOrigin:a.sameOrigin,parkStrategy:a.parkStrategy,degraded:a.degraded,preloaded:a.preloaded,supportsMoveBefore:T,nudgeCount:a.nudgeCount,lastNudgeAt:a.lastNudgeAt}}function A(){var e=H();a.listeners.forEach(function(r){try{r(e)}catch(t){}})}function ae(e){return a.listeners.add(e),function(){a.listeners.delete(e)}}function ne(){return H()}function Oe(e){e!=="offscreen"&&e!=="behind"||a.parkStrategy!==e&&(a.parkStrategy=e,a.frame!==null&&a.owner===null&&U(),A())}function Te(){return a.parkStrategy}function Ae(){var e=a.lastRect;e!==null&&(a.park.style.width=Math.max(1,Math.round(e.width))+"px",a.park.style.height=Math.max(1,Math.round(e.height))+"px")}function U(){if(a.park!==null){if(Ae(),a.parkStrategy==="behind"&&a.lastRect!==null){a.park.style.left=Math.round(a.lastRect.left)+"px",a.park.style.top=Math.round(a.lastRect.top)+"px",a.park.style.visibility="visible",a.park.style.zIndex="0";return}a.park.style.left=Ce+"px",a.park.style.top="0px",a.park.style.visibility="hidden",a.park.style.zIndex="0"}}function le(){a.frame!==null&&(a.frame.setAttribute("inert",""),a.frame.setAttribute("aria-hidden","true"))}function Le(){a.frame!==null&&(a.frame.removeAttribute("inert"),a.frame.removeAttribute("aria-hidden"))}function Re(){var e=document.createElement("div");e.className="dshcs-park",e.setAttribute("data-dshcs-park",""),e.setAttribute("aria-hidden","true");var r=document.createElement("iframe");return r.className="dshcs-frame",r.setAttribute("title","code-server"),r.setAttribute("allow","clipboard-read; clipboard-write"),r.setAttribute("data-dshcs-resident",""),r.src="about:blank",e.appendChild(r),document.body.appendChild(e),a.park=e,a.frame=r,a.currentSrc="about:blank",a.owner=null,U(),le(),r}function Me(e){var r=a.frame;if(r!==null){var t=a.sameOrigin!==e;!t&&r.hasAttribute("data-dshcs-attrs")||(e===!0?r.removeAttribute("sandbox"):e===!1&&r.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-modals allow-popups allow-pointer-lock allow-clipboard-read allow-clipboard-write"),r.setAttribute("data-dshcs-attrs",e===!0?"same-origin":"cross-origin"),a.sameOrigin=e)}}function _(e){var r=e||{};return a.frame===null&&Re(),typeof r.sameOrigin=="boolean"&&Me(r.sameOrigin),typeof r.src=="string"&&r.src!==""&&r.src!==a.currentSrc&&De(r.src),a.frame}function De(e){a.frame===null||typeof e!="string"||e===""||e===a.currentSrc||(a.currentSrc=e,a.frame.src=e,A())}function se(){var e=a.frame;if(a.nudgeEnabled!==!0||e===null||e.isConnected!==!0)return!1;var r=e.style.display;return e.style.display="none",e.offsetHeight,e.style.display=r,a.nudgeCount+=1,a.lastNudgeAt=Date.now(),!0}function ze(e){return a.nudgeEnabled=e!==!1,a.nudgeEnabled}function ie(e){if(a.frame!==null){if(T)try{e.moveBefore(a.frame,null);return}catch(r){a.degraded=!0,a.lastMoveError=(r&&r.name?r.name+": ":"")+(r&&r.message?r.message:String(r))}else a.degraded=!0;e.appendChild(a.frame)}}function B(e,r){if(!(a.frame===null||e==null)){var t=a.owner===null,s=e.getBoundingClientRect();s.width>=1&&s.height>=1&&(a.lastRect={left:s.left,top:s.top,width:s.width,height:s.height}),a.owner=r===void 0?null:r,Le(),a.park.setAttribute("aria-hidden","true"),ie(e),t&&se(),A()}}function L(e){a.frame!==null&&(e!==void 0&&a.owner!==e||(a.owner=null,U(),le(),a.park.setAttribute("aria-hidden","true"),ie(a.park),A()))}function F(e){var r=e||{};return _(r),a.owner===null&&(typeof r.src=="string"&&r.src!==""&&(a.preloaded=!0),L()),a.frame}function je(){a.park!==null&&a.park.parentNode!==null&&a.park.parentNode.removeChild(a.park),a.park=null,a.frame=null,a.currentSrc=null,a.sameOrigin=null,a.owner=null,a.lastRect=null,a.degraded=!1,a.preloaded=!1,a.nudgeCount=0,a.lastNudgeAt=0,A()}typeof window!="undefined"&&(window.__dshcsSurface={snapshot:H,setParkStrategy:Oe,getParkStrategy:Te,preload:F,dock:B,park:L,nudge:se,setNudgeEnabled:ze,destroy:je});var n=require("react"),V=new Set,R={status:null,busy:!1,sidebarActive:!1,sidebarUi:"unknown",sidebarRegisterFailed:!1};function N(e){R=Object.assign({},R,e),V.forEach(function(r){r()})}function Pe(e){return V.add(e),function(){V.delete(e)}}function Ie(){return R}function W(){return n.useSyncExternalStore(Pe,Ie)}var He="/api",Ue="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMTQ3IDE0NyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8c3R5bGU+QG1lZGlhIChwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyaykgeyogeyBmaWxsOiB3aGl0ZTsgfX08L3N0eWxlPgogIDxwYXRoIGQ9Im00Mi40MjE0LDM5LjY1NWMtMjQuNDA1NywwIC00Mi4xNTU0LDEzLjE3MjEgLTQyLjE1NTQsMzMuODQ1YzAsMjAuNTgxNCAxOC40ODkyLDMzLjg0NSA0Mi4xNTU0LDMzLjg0NWMyMy42NjYyLDAgMzguMTgwMywtMTEuNjE3MSAzOC43MzQ5LC0yOC43MjI1bC0yMS4wNzc3LC0wLjQ1NzRjLTAuOTI0NCw5LjMzMDMgLTkuMTA1OSwxNS4xODQ1IC0xNy42NTcyLDE1LjE4NDVjLTExLjc0MDYsMCAtMjAuNDMwNiwtNy41OTIyIC0yMC40MzA2LC0xOS44NDk2YzAsLTEyLjI1NzQgOC42OSwtMTkuOTg2OCAyMC40MzA2LC0yMC4yMTU1YzguNTUxMywtMC4xODMgMTYuOTE3Nyw1Ljk0NTcgMTcuNDcyMywxNS4yNzZsMjEuMDc3NywtMC42NDAzYy0wLjQ2MjIsLTE2LjgzMTEgLTE0LjE0NDIsLTI4LjI2NTIgLTM4LjU1LC0yOC4yNjUyem00OC44NDQ2LDJsNTUuNDY4LDBsMCw2NC4wMzExbC01NS40NjgsMGwwLC02NC4wMzExeiIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz4KPC9zdmc+Cg==";async function k(e,r){var t={method:r===void 0?"GET":"POST",headers:{}};r!==void 0&&(t.headers["content-type"]="application/json",t.body=JSON.stringify(r));var s=await fetch(He+e,t),l=await s.text(),i=null;try{i=l===""?null:JSON.parse(l)}catch(d){i=null}return s.ok?i!==null?i:{ok:!1,error:"invalid JSON response"}:{ok:!1,error:"HTTP "+s.status+(i!==null&&i.error!==void 0?": "+i.error:"")}}function fe(e,r){try{var t=e(function(b){return b}),s=r===null?null:typeof r=="function"?r(function(b){return b}):null,l=t!=null?t.current:void 0;if(l!==void 0&&t!=null&&t.byId!=null){var i=t.byId[l];if(i!=null&&typeof i.cwd=="string"&&i.cwd!=="")return i.cwd}var d=s!=null&&Array.isArray(s.items)?s.items:[];if(l!==void 0)for(var p=0;p<d.length;p++){var v=d[p];if(v.sessionIds!=null&&v.sessionIds.indexOf(l)!==-1&&typeof v.path=="string"&&v.path!=="")return v.path}var c=s!=null?s.recentWorkspaceId:void 0;if(c!==void 0){for(var o=0;o<d.length;o++)if(d[o].workspaceId===c&&typeof d[o].path=="string"&&d[o].path!=="")return d[o].path}if(d.length>0&&typeof d[0].path=="string"&&d[0].path!=="")return d[0].path}catch(b){}}function pe(e,r){if(e==null||typeof e.url!="string"||e.url==="")return null;var t=typeof r=="string"&&r!==""?r:e!=null&&e.cwd!=null?e.cwd:null;if(t==null||t==="")return e.url;var s=t.replace(/\\/g,"/"),l=s;return(/^[A-Za-z]:\//.test(s)||s.charCodeAt(0)!==47)&&(l="/"+s),e.url+"?folder="+encodeURIComponent(l)}function _e(e){var r=e.status,t=e.pageUrl,s=e.reloadTick,l=e.owner,i=n.useRef(null),d=r!=null&&r.ok===!0&&r.running===!0,p=r!=null&&r.status==="starting",v=r!=null&&r.ok===!1,c=r!=null&&r.serve==="dsh";if(n.useLayoutEffect(function(){if(!d||t===null){L(l);return}_({src:t,sameOrigin:c}),i.current!==null&&B(i.current,l)},[d,t,c,s,l]),n.useLayoutEffect(function(){return function(){L(l)}},[l]),d&&t!==null)return n.createElement("div",{ref:i,className:"dshcs-slot","data-code-server-slot":l!=null?l:"code-server"});if(p)return n.createElement("div",{className:"dshcs-loading"},"\u6B63\u5728\u542F\u52A8 code-server\u2026");var o=v&&r!=null&&r.error?r.error:"code-server \u672A\u8FD0\u884C",b=c?"\u5F53\u524D\u4EE5 DSH \u540C\u6E90\u8DEF\u5F84 "+(r!=null&&r.url||"/code-server/")+" \u63D0\u4F9B(\u65E0\u72EC\u7ACB\u7AEF\u53E3)\u3002":"\u5F53\u524D\u4EE5\u72EC\u7ACB\u56DE\u73AF\u7AEF\u53E3\u63D0\u4F9B(\u7AEF\u53E3 "+(r!=null&&r.port!=null?r.port:"8090")+" \u88AB\u5360\u7528\u65F6\u8BF7\u91CA\u653E\u6216\u4FEE\u6539 port \u914D\u7F6E)\u3002",w=T?"\u5E38\u9A7B\u9762:\u53EF\u7528(\u5207\u6807\u7B7E/\u6536\u8D77\u4FA7\u680F\u4E0D\u91CD\u8F7D)\u3002":"\u5E38\u9A7B\u9762:\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301 Element.moveBefore \u2014\u2014 \u5207\u6807\u7B7E\u4F1A\u6574\u9875\u91CD\u8F7D(\u5347\u7EA7\u6D4F\u89C8\u5668\u540E\u81EA\u52A8\u53EF\u7528)\u3002";return n.createElement("div",{className:"dshcs-empty"},n.createElement("div",{className:"dshcs-emptybox"},n.createElement("div",null,v?"code-server \u542F\u52A8\u5931\u8D25":"code-server \u672A\u8FD0\u884C"),n.createElement("pre",{className:"dshcs-error"},o),n.createElement("p",{className:"dshcs-hint"},"VS Code \u6811\u968F\u63D2\u4EF6\u5305\u5185\u7F6E\u3001\u5C31\u5730\u8FD0\u884C(\u65E0\u9700\u5168\u5C40\u5B89\u88C5\u3001\u65E0\u9700\u8054\u7F51\u5B89\u88C5\u3001\u65E0\u300C\u5B89\u88C5\u73AF\u5883\u300D\u6B65\u9AA4);\u5185\u90E8\u4F9D\u8D56\u4E0E\u9884\u7F16\u8BD1\u539F\u751F\u6A21\u5757\u7531\u5305\u7BA1\u7406\u5668\u5728\u5B89\u88C5\u63D2\u4EF6\u65F6\u4E00\u5E76\u88C5\u597D(\u65E0\u9700 C++ \u5DE5\u5177\u94FE)\u3002\u82E5\u6B64\u5904\u957F\u671F\u672A\u8FD0\u884C,\u8BF7\u5230 \u8BBE\u7F6E \u2192 \u63D2\u4EF6 \u2192 Code Server \u70B9\u300C\u68C0\u6D4B\u73AF\u5883\u300D\u67E5\u770B\u539F\u56E0\u3002"+b+w)))}function Be(e){var r=W(),t=r.status,s=t!=null&&t.ok===!0&&t.running===!0,l=t!=null&&t.keepResident===!0,i=fe(e&&e.useSessions,e&&e.useWorkspaces),d=s?pe(t,i):null;return n.useEffect(function(){!l||!s||d===null||F({src:d,sameOrigin:t!=null&&t.serve==="dsh"})},[l,s,d,t!=null?t.serve:null]),null}var Fe=".dshcs-frame{display:block;position:absolute;inset:0;z-index:1;width:100%;height:100%;border:0;background:var(--dsw-alias-bg-base,#fff)}.dshcs-tabroot{position:relative;display:flex;flex-direction:column;width:100%;height:100%;min-width:0;min-height:0;background:var(--dsw-alias-bg-base,#fff)}.dshcs-slot{position:relative;display:block;width:100%;height:100%;min-width:0;min-height:0;overflow:hidden;background:var(--dsw-alias-bg-base,#fff)}.dshcs-park{position:fixed;left:-20000px;top:0;width:320px;height:200px;overflow:hidden;pointer-events:none;z-index:0;visibility:hidden;contain:strict}.dshcs-loading{position:absolute;inset:0;z-index:2;display:grid;place-items:center;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-tertiary,#7d8798);font-size:13px}.dshcs-empty{position:relative;z-index:2;flex:1;display:flex;align-items:center;justify-content:center;padding:44px 24px 24px}.dshcs-emptybox{max-width:560px;text-align:left;background:var(--dsw-alias-bg-layer-2,#f7f8fb);border:1px solid var(--dsw-alias-border-l2,#dfe3eb);border-radius:12px;padding:16px 18px}.dshcs-error{color:var(--dsw-alias-label-error,#d92d20);white-space:pre-wrap;word-break:break-all;font-family:ui-monospace,Consolas,monospace;font-size:12px;margin:8px 0 0}.dshcs-hint{color:var(--dsw-alias-label-tertiary,#7d8798);font-size:12px;margin:6px 0 0}.dshcs-legacy{color:var(--dsw-alias-label-warning,#b54708);font-size:12px;font-weight:600;margin:0 0 6px}",de="dsh-code-server/styles";typeof document!="undefined"&&document.querySelector("style[data-dshcs="+JSON.stringify(de)+"]")===null&&(D=document.createElement("style"),D.setAttribute("data-dshcs",de),D.textContent=Fe,document.head.appendChild(D));var D,G="code-server",ce="dsh-code-server-app",Ge=2500,Qe=1e4,Ve=1500,z={openTab:null};function We(e){var r=e!=null&&typeof e.size=="number"?e.size:16;return n.createElement("img",{src:Ue,alt:"","aria-hidden":!0,draggable:!1,className:e!=null?e.className:void 0,style:{width:r,height:r,display:"block",objectFit:"contain",WebkitUserDrag:"none",userSelect:"none"}})}function Ye(){var e=R.status;return e!=null&&e.fileOpenScope==="all"?"all":q}function Ze(e,r){try{var t=e(function(l){return l});if(t!=null&&r!=null&&t.byId!=null){var s=t.byId[r];if(s!=null&&typeof s.cwd=="string"&&s.cwd!=="")return s.cwd}}catch(l){}}function Je(e){var r=e.useTabInfo(),t=r.tab,s=W(),l=s.status,i=t.navigation,d=i!=null&&typeof i.revision=="number"?i.revision:0,p=i!=null&&typeof i.address=="string"?i.address:"",v=I(p)?null:M(p),c=Ze(e.useSessions,v!=null?v.sessionId:void 0),o=c!==void 0?c:fe(e.useSessions,null),b=re(v,o),w=i!=null&&i.params!=null&&typeof i.params.line=="number"?i.params.line:null,f=n.useRef(void 0),[y,m]=n.useState(0);return n.useEffect(function(){if(!(typeof o!="string"||o==="")&&f.current!==o){var g=f.current!==void 0;f.current=o;var S=!1;return k("/code-server/start",{cwd:o}).then(function(C){S||(N({status:C}),g&&C!=null&&C.ok===!0&&C.running===!0&&m(function(O){return O+1}))}).catch(function(){}),function(){S=!0}}},[o]),n.useEffect(function(){k("/code-server/status").then(function(S){S!=null&&N({status:S})}).catch(function(){});var g=window.setInterval(function(){k("/code-server/status").then(function(S){N({status:S})}).catch(function(){})},3e3);return function(){window.clearInterval(g)}},[]),n.useEffect(function(){b!==null&&k("/code-server/open-file",w===null?{file:b}:{file:b,line:w}).catch(function(){})},[d,b,w]),n.createElement("div",{className:"dshcs-tabroot","data-code-server-tab":"body"},n.createElement(_e,{status:l,pageUrl:pe(l,o),reloadTick:y,owner:"tab:"+t.id}))}function Q(e,r){if(e==null)return null;var t=e[r];if(t!=null)return t;if(typeof e.get=="function"){var s=e.get(r);if(s!=null)return s}return null}function Xe(e){var r=Q(e,"sidebarRightTabs"),t=Q(e,"sidebarRight");if(r==null||t==null)return console.error("[code-server] \u53F3\u4FA7\u680F\u670D\u52A1\u4E0A\u4E0B\u6587\u4E0D\u53EF\u89C1(sidebarRightTabs="+(r!=null)+", sidebarRight="+(t!=null)+"):\u8DF3\u8FC7\u4FA7\u680F\u6CE8\u518C"),!1;var s=Q(e,"slots");if(e.effect(function(){return r.register({id:ce,kind:G,priority:"extension",patterns:["dsh-resource://file/**"],canOpen:function(l){return te(M(l),Ye())},title:function(l){if(I(l)||l===void 0||l===null||l==="")return"Code Server";var i=ee(l);return i===""?"Code Server":i},guide:[{order:20,title:function(){return"Code Server"},description:function(){return"\u5728\u53F3\u4FA7\u680F\u6807\u7B7E\u91CC\u8FD0\u884C VS Code \u7F51\u9875\u7248,\u8DDF\u968F\u5F53\u524D\u4F1A\u8BDD\u5DE5\u4F5C\u533A;\u4EA7\u7269/\u4EA4\u4ED8\u6587\u4EF6\u70B9\u51FB\u540E\u5728\u6B64\u6253\u5F00\u3002"},icon:We}]})},"code-server: sidebar tab type"),s!=null)e.effect(function(){return s.inject("sidebar.right.pane.tab",function(){return s.register({name:"sidebar.right.pane.tab",key:ce},Je)})},"code-server: sidebar tab body");else return console.error("[code-server] slots \u670D\u52A1\u4E0D\u53EF\u89C1:\u4FA7\u680F\u6807\u7B7E body \u672A\u6CE8\u518C"),!1;return z.openTab=function(l){try{return t.openTab(G,l!=null?{params:l}:void 0),!0}catch(i){return console.warn("[code-server] sidebar openTab failed:",i!=null&&i.message!=null?i.message:String(i)),!1}},e.effect(function(){return function(){z.openTab=null,N({sidebarActive:!1,sidebarUi:"unknown"})}},"code-server: sidebar mode reset"),console.log("[code-server] right-sidebar tab registered (kind="+G+")"),!0}var Ke=".dshcs-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.dshcs-card:hover{border-color:var(--dsw-alias-label-dimmed,var(--dsw-alias-border-l2))}.dshcs-cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed,var(--dsw-alias-border-l2))}.dshcs-cardHeader{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.dshcs-cardHeader:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.dshcs-cardHeadText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.dshcs-cardName{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.dshcs-cardDescription{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));font-size:13px;line-height:1.5}.dshcs-cardChevron{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));flex:none;transition:transform .16s;display:inline-flex}.dshcs-cardChevronOpen{transform:rotate(180deg)}.dshcs-cardBody{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.dshcs-cardReadOnly{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));margin:12px 0 0;font-size:12px;line-height:1.5}.dshcs-pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform,var(--dsw-alias-bg-layer-2));color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.dshcs-cardFooter{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.dshcs-cardFailed{min-width:0;color:var(--dsw-alias-label-error,var(--dsw-alias-state-error-primary));flex:1;margin:0;font-size:12px;line-height:1.5}.dshcs-cbtn{appearance:none;font:inherit;cursor:pointer;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5;border:1px solid transparent;transition:color .12s ease,background .12s ease}.dshcs-cbtn:disabled{opacity:.4;cursor:default}.dshcs-cbtn:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.dshcs-cbtnOutline{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.dshcs-cbtnOutline:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover,transparent)}.dshcs-cbtnPrimary{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3);border-color:var(--dsw-alias-label-primary);font-weight:600}.dshcs-cbtnPrimary:hover:not(:disabled){filter:brightness(.95)}.dshcs-cbtnPrimary:active:not(:disabled){filter:brightness(.9)}.dshcs-field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.dshcs-field+.dshcs-field{border-top:1px solid var(--dsw-alias-border-l2)}.dshcs-fieldHead{align-items:center;gap:8px;display:flex}.dshcs-fieldLabel{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.dshcs-card .dshcs-hint{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));margin:0;font-size:12px;line-height:1.5}.dshcs-check{display:flex;align-items:center;gap:8px;cursor:pointer}.dshcs-check input{accent-color:var(--dsw-alias-brand-primary);width:15px;height:15px;margin:0;flex:none}.dshcs-check input:disabled{cursor:default}.dshcs-select{display:inline-flex;align-items:center}.dshcs-select select{font:inherit;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3,transparent);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:4px 8px;min-width:220px;cursor:pointer}.dshcs-select select:disabled{opacity:.5;cursor:default}.dshcs-badges{align-items:center;gap:8px;display:inline-flex}.dshcs-badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform,var(--dsw-alias-bg-layer-2));color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.dshcs-reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.dshcs-reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.dshcs-reset:disabled{cursor:default}",qe="dsh-code-server/Card.module.css";function $e(e,r){if(typeof document!="undefined"&&document.querySelector("style[data-plugin-css="+JSON.stringify(e)+"]")===null){var t=document.createElement("style");t.dataset.plugin="dsh-code-server",t.dataset.pluginCss=e,t.textContent=r,document.head.appendChild(t)}}$e(qe,Ke);function er(e){return n.createElement("svg",{width:14,height:14,viewBox:"0 0 14 14",fill:"none","aria-hidden":!0,className:e.className},n.createElement("path",{d:"M3.5 5.25L7 8.75L10.5 5.25",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round"}))}function j(e){return n.createElement("button",{type:"button",className:"dshcs-cbtn "+(e.variant==="primary"?"dshcs-cbtnPrimary":"dshcs-cbtnOutline"),disabled:e.disabled===!0,onClick:e.onClick},e.children)}function rr(e){return n.createElement("label",{className:"dshcs-check"},n.createElement("input",{type:"checkbox",checked:e.checked===!0,disabled:e.disabled===!0,onChange:function(r){e.onChange(r.target.checked)}}),n.createElement("span",{className:"dshcs-hint"},e.children))}function tr(e){var r=Array.isArray(e.options)?e.options:[];return n.createElement("label",{className:"dshcs-select"},n.createElement("select",{value:e.value,disabled:e.disabled===!0,onChange:function(t){e.onChange(t.target.value)}},r.map(function(t){return n.createElement("option",{key:t.value,value:t.value},t.label)})))}function oe(e){var r=[];return e.overridden===!0&&(r.push(n.createElement("span",{className:"dshcs-badge"},e.overriddenLabel)),r.push(n.createElement("button",{type:"button",className:"dshcs-reset",disabled:e.disabled===!0,onClick:e.onReset},e.resetLabel))),r.length===0?null:n.createElement("span",{className:"dshcs-badges"},...r)}function ue(e){var[r,t]=n.useState(e.defaultOpen===!0),s=e.state;if(s==null||s.available!==!0)return null;var l=e.title,i=e.noticeOnly===!0,d=s.dirty!==!0||s.invalid===!0||s.saving===!0;return n.createElement("li",{className:"dshcs-card"+(r?" dshcs-cardOpen":"")},n.createElement("button",{type:"button",className:"dshcs-cardHeader","aria-expanded":r,onClick:function(){t(!r)}},n.createElement("span",{className:"dshcs-cardHeadText"},n.createElement("span",{className:"dshcs-cardName"},l),n.createElement("span",{className:"dshcs-cardDescription"},e.description)),s.dirty===!0?n.createElement("span",{className:"dshcs-pending"},e.unsavedLabel):null,n.createElement(er,{className:"dshcs-cardChevron"+(r?" dshcs-cardChevronOpen":"")})),r===!0?n.createElement("div",{className:"dshcs-cardBody"},i===!0?null:s.writable!==!0?n.createElement("p",{className:"dshcs-cardReadOnly",role:"status"},e.readOnlyLabel):null,e.children,i===!0?null:n.createElement("div",{className:"dshcs-cardFooter"},s.failed===!0?n.createElement("p",{className:"dshcs-cardFailed",role:"status"},e.saveFailedLabel):null,n.createElement(j,{disabled:s.dirty!==!0||s.saving===!0,onClick:e.onDiscard},e.discardLabel),n.createElement(j,{variant:"primary",disabled:d,onClick:e.onSave},s.saving===!0?e.savingLabel:e.saveLabel))):null)}function ar(e){try{let E=function(){k("/code-server/status").then(function(h){h!=null&&typeof h=="object"&&N({status:h})}).catch(function(){})};var r=e.scope,[t,s]=n.useState(function(){return r!==void 0?r.getSnapshot():null}),[l,i]=n.useState(null),[d,p]=n.useState(!1),[v,c]=n.useState(!1),o=W(),[b,w]=n.useState(ne());if(n.useEffect(function(){return ae(function(h){w(h)})},[]),n.useEffect(function(){if(r===void 0||typeof r.subscribe!="function")return;function h(){try{s(r.getSnapshot())}catch(or){}}var x=r.subscribe(h);return function(){typeof x=="function"&&x()}},[r]),r===void 0)return console.error("[code-server] card scope missing"),null;if(t==null||t.status!=="ready")return t!=null&&t.status==="unavailable"&&console.warn("[code-server] settings scope unavailable:",t.status),null;var f=t.value!==void 0&&t.value!==null?t.value:{},y=t.user,m={keepResident:f.keepResident!==!1,fileOpenScope:f.fileOpenScope==="all"?"all":"session"};if(o!=null&&o.sidebarUi==="legacy")return n.createElement(ue,{title:"Code Server",description:"\u5F53\u524D DSH \u7248\u672C\u4E0D\u53D7\u652F\u6301(\u7F3A\u5C11\u53F3\u4FA7\u680F\u670D\u52A1)",defaultOpen:!0,noticeOnly:!0,state:{available:!0,writable:!1,dirty:!1,invalid:!1,saving:!1,failed:!1}},n.createElement("div",{className:"dshcs-field"},n.createElement("div",{className:"dshcs-legacy"},"\u672C\u63D2\u4EF6\u81EA 0.2.3 \u8D77\u4E0D\u518D\u517C\u5BB9\u65E7\u7248 DSH\u3002"),n.createElement("div",{className:"dshcs-hint",style:{marginTop:0}},`\u672A\u68C0\u6D4B\u5230\u53F3\u4FA7\u680F\u63D2\u4EF6\u670D\u52A1 sidebarRightTabs / sidebarRight,\u56E0\u6B64\u63D2\u4EF6\u4E0D\u63D0\u4F9B\u4EFB\u4F55\u5165\u53E3(\u65E7\u7248\u7684\u60AC\u6D6E\u7403\u4E0E\u6D6E\u52A8\u7A97\u53E3\u5DF2\u79FB\u9664),\u4E5F\u4E0D\u4F1A\u540E\u53F0\u542F\u52A8 IDE\u3002
|
|
3
|
+
\u5347\u7EA7 DSH \u5230\u5E26\u53F3\u4FA7\u680F\u7684\u7248\u672C(\u2265 0.1.5-alpha.1)\u540E,Code Server \u4F1A\u51FA\u73B0\u5728\u53F3\u4FA7\u680F\u6807\u7B7E\u91CC,\u672C\u9875\u540C\u65F6\u663E\u793A\u5B8C\u6574\u8BBE\u7F6E\u9879;\u5347\u7EA7\u540E\u65E0\u9700\u91CD\u88C5\u672C\u63D2\u4EF6,\u5237\u65B0\u9875\u9762\u5373\u53EF\u3002`)));var g=y!=null&&Object.prototype.hasOwnProperty.call(y,"keepResident"),S=y!=null&&Object.prototype.hasOwnProperty.call(y,"fileOpenScope"),C=o!=null&&o.sidebarActive===!0,O=l!==null&&(l.keepResident!==m.keepResident||l.fileOpenScope!==m.fileOpenScope),cr=!O||d,ve={available:!0,writable:t.writable,dirty:O,invalid:!1,saving:d,failed:v};async function me(){if(O&&!d){p(!0),c(!1);try{var h=l!==null?l:m;await e.scope.set("keepResident",h.keepResident===!0),await e.scope.set("fileOpenScope",h.fileOpenScope==="all"?"all":"session"),i(null),E()}catch(x){c(!0)}p(!1)}}async function J(){if(!(d||t.writable!==!0)){p(!0),c(!1);try{typeof e.scope.unset=="function"?(await e.scope.unset("keepResident"),await e.scope.unset("fileOpenScope")):(await e.scope.set("keepResident",f.keepResident===void 0||f.keepResident===null?!0:f.keepResident),await e.scope.set("fileOpenScope",f.fileOpenScope==="all"?"all":"session")),i(null),E()}catch(h){c(!0)}p(!1)}}var[u,he]=n.useState(null),[Y,Z]=n.useState(!1),be=n.createElement("div",{className:"dshcs-field"},n.createElement("div",{className:"dshcs-fieldHead"},n.createElement("span",{className:"dshcs-fieldLabel"},"\u73AF\u5883\u68C0\u6D4B"),n.createElement("span",{className:"dshcs-badges"},n.createElement(j,{variant:"primary",disabled:Y,onClick:async function(){Z(!0);var h=await k("/code-server/status");he(h!=null&&h.env!=null?h.env:{error:"status \u672A\u8FD4\u56DE env"}),Z(!1)}},Y?"\u68C0\u6D4B\u4E2D\u2026":"\u68C0\u6D4B\u73AF\u5883"))),u!=null?n.createElement("div",{className:"dshcs-hint",style:{marginTop:6}},u.error!=null?n.createElement("span",null,"\u68C0\u6D4B\u5931\u8D25: "+u.error):n.createElement("span",null,"\u72B6\u6001: "+(u.ok===!0?"\u2705 \u5C31\u7EEA":"\u274C \u4E0D\u901A\u8FC7")+(u.treeVersion!=null?" \xB7 VS Code \u6811: "+u.treeVersion:"")+(u.upToDate===!1&&u.vendored!=null?"(\u5185\u7F6E "+u.vendored+") ":"")+(u.productPath!=null?" \xB7 \u5BA2\u6237\u7AEF\u8DEF\u5F84: "+u.productPath:"")+(u.entry!=null?" \xB7 \u5165\u53E3: "+u.entry:" \xB7 \u5165\u53E3\u7F3A\u5931")+" \xB7 VS Code \u5185\u90E8\u4F9D\u8D56: "+(u.vscodeInner===!0?"\u2705":"\u274C")+" \xB7 \u9884\u7F16\u8BD1\u539F\u751F\u5305: "+(u.nativeRuntime!=null&&u.nativeRuntime.packages>0?"\u2705 "+u.nativeRuntime.name+"@"+(u.nativeRuntime.version!=null?u.nativeRuntime.version:"?")+"("+u.nativeRuntime.packages+" \u5305)":"\u274C \u672A\u5B89\u88C5("+(u.nativeRuntime!=null&&u.nativeRuntime.name!=null?u.nativeRuntime.name:"\u5E73\u53F0\u805A\u5408\u5305")+")"))):n.createElement("div",{className:"dshcs-hint",style:{marginTop:6}},'\u70B9\u51FB"\u68C0\u6D4B\u73AF\u5883"\u67E5\u770B VS Code \u6811\u72B6\u6001(\u4F9D\u8D56\u7531\u5305\u7BA1\u7406\u5668\u5B89\u88C5,\u65E0\u9700\u5B89\u88C5\u6B65\u9AA4)'),n.createElement("div",{className:"dshcs-hint",style:{marginTop:10,color:"var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary))"}},"\u8FD0\u884C\u4F4D\u7F6E: "+(u!=null&&u.tree!=null?u.tree:"<\u63D2\u4EF6\u76EE\u5F55>\\vendor\\vscode")+`
|
|
4
|
+
\u5378\u8F7D: dsh plugin --profile web remove dsh-code-server-app`));return n.createElement(ue,{title:"Code Server",description:"\u5165\u53E3:\u53F3\u4FA7\u680F\u6807\u7B7E(DSH \u2265 0.1.5-alpha.1);\u8BA4\u9886\u8303\u56F4\u51B3\u5B9A\u54EA\u4E9B\u6587\u4EF6\u4EA4\u7ED9 Code Server \u6253\u5F00",state:ve,unsavedLabel:"\u672A\u4FDD\u5B58",readOnlyLabel:"\u672C\u90E8\u7F72\u7684\u8BBE\u7F6E\u4E3A\u53EA\u8BFB\u3002",saveFailedLabel:"\u672C\u90E8\u7F72\u6CA1\u6709\u63A5\u53D7\u8FD9\u4E9B\u503C\uFF0C\u5DF2\u4FDD\u7559\u4F9B\u4F60\u4FEE\u6539\u3002",discardLabel:"\u653E\u5F03\u4FEE\u6539",saveLabel:"\u4FDD\u5B58",savingLabel:"\u4FDD\u5B58\u4E2D\u2026",onSave:me,onDiscard:function(){i(null),c(!1)}},n.createElement("div",{className:"dshcs-field"},n.createElement("div",{className:"dshcs-fieldHead"},n.createElement("span",{className:"dshcs-fieldLabel"},"\u5165\u53E3"),n.createElement("span",{className:"dshcs-badges"},n.createElement(j,{disabled:C!==!0,onClick:function(){z.openTab!==null&&z.openTab(null)}},"\u5728\u53F3\u4FA7\u680F\u6253\u5F00"))),n.createElement("div",{className:"dshcs-hint",style:{marginTop:6}},o!=null&&o.sidebarRegisterFailed===!0?"\u26A0 \u5DF2\u63A2\u6D4B\u5230\u53F3\u4FA7\u680F\u670D\u52A1,\u4F46\u6807\u7B7E\u6CE8\u518C\u5931\u8D25(\u63A7\u5236\u53F0\u6709 [code-server] \u62A5\u9519);\u8BF7\u4FEE\u597D\u540E\u5237\u65B0\u9875\u9762\u3002":'\u5F53\u524D:\u53F3\u4FA7\u680F\u6807\u7B7E,\u5E76**\u8BA4\u9886\u6587\u4EF6\u5730\u5740**\u2014\u2014DSH \u5B98\u65B9\u7684\u4EA7\u7269 chip\u3001"\u4EA4\u4ED8"\u5361\u7247\u9884\u89C8\u3001\u6B63\u6587\u91CC\u7684\u6587\u4EF6\u540D\u70B9\u51FB\u90FD\u4F1A\u5728 Code Server \u91CC\u6253\u5F00\u3002')),n.createElement("div",{className:"dshcs-field"},n.createElement("div",{className:"dshcs-fieldHead"},n.createElement("span",{className:"dshcs-fieldLabel"},"\u8BA4\u9886\u8303\u56F4(\u54EA\u4E9B\u6587\u4EF6\u4EA4\u7ED9 Code Server)"),S===!0?n.createElement(oe,{overridden:!0,disabled:t.writable!==!0,overriddenLabel:"\u5DF2\u8986\u76D6",resetLabel:"\u6062\u590D\u9ED8\u8BA4",onReset:function(){J()}}):null),n.createElement(tr,{value:l!==null?l.fileOpenScope:m.fileOpenScope,disabled:t.writable!==!0,options:[{value:"session",label:"\u4EC5\u4F1A\u8BDD\u5185\u6587\u4EF6(\u63A8\u8350)"},{value:"all",label:"\u6240\u6709\u6587\u4EF6(\u542B\u5DE5\u4F5C\u533A\u5916\u7684\u7EDD\u5BF9\u8DEF\u5F84)"}],onChange:function(h){i(function(x){return Object.assign({},x!==null?x:m,{fileOpenScope:h==="all"?"all":"session"})}),c(!1)}}),n.createElement("div",{className:"dshcs-hint",style:{marginTop:4}},"\u4F1A\u8BDD\u5185\u6587\u4EF6 = DSH \u7528 `dsh-resource://file/session/\u2026` \u547D\u540D\u7684\u6587\u4EF6(\u4EA7\u7269\u3001\u4EA4\u4ED8\u3001\u6B63\u6587\u63D0\u53CA\u3001\u5DE5\u5177\u89C6\u56FE);\u201C\u6240\u6709\u6587\u4EF6\u201D\u8FD8\u4F1A\u8BA4\u9886\u4E0D\u5E26\u4F1A\u8BDD\u7684\u7EDD\u5BF9\u8DEF\u5F84 `dsh-resource://file/absolute/\u2026`\u3002\u672A\u88AB\u8BA4\u9886\u7684\u5730\u5740\u7531 DSH \u81EA\u5E26\u9884\u89C8\u515C\u5E95\u3002")),n.createElement("div",{className:"dshcs-field"},n.createElement("div",{className:"dshcs-fieldHead"},n.createElement("span",{className:"dshcs-fieldLabel"},"\u540E\u53F0\u5E38\u9A7B(\u5207\u6807\u7B7E\u4E0D\u91CD\u8F7D)"),g===!0?n.createElement(oe,{overridden:!0,disabled:t.writable!==!0,overriddenLabel:"\u5DF2\u8986\u76D6",resetLabel:"\u6062\u590D\u9ED8\u8BA4",onReset:function(){J()}}):null),n.createElement(rr,{checked:l!==null?l.keepResident:m.keepResident,disabled:t.writable!==!0,onChange:function(h){i(function(x){return Object.assign({},x!==null?x:m,{keepResident:h===!0})}),c(!1)}},'\u5F00\u542F\u540E\u5BBF\u4E3B\u542F\u52A8\u5373\u628A IDE \u52A0\u8F7D\u5230\u540E\u53F0"\u505C\u653E\u533A":\u5207\u6362\u53F3\u4FA7\u680F\u6807\u7B7E\u3001\u6536\u8D77/\u5C55\u5F00\u4FA7\u680F\u3001\u62D6\u6210\u6D6E\u52A8\u7A97\u53E3\u90FD\u4E0D\u518D\u91CD\u8F7D,\u9996\u6B21\u6253\u5F00\u514D\u7B49\u5F85;\u5173\u95ED\u5219\u53EA\u5728\u6253\u5F00\u9762\u677F\u65F6\u52A0\u8F7D(\u7701\u5185\u5B58)'),n.createElement("div",{className:"dshcs-hint",style:{marginTop:4}},T?"\u5E38\u9A7B\u9762:"+(b.docked?"\u5DF2\u505C\u9760":b.ready?"\u5DF2\u505C\u653E(\u540E\u53F0\u8FD0\u884C\u4E2D)":"\u672A\u542F\u52A8")+(b.degraded?" \xB7 \u672C\u6B21\u53D1\u751F\u8FC7\u964D\u7EA7\u91CD\u8F7D":""):"\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301 Element.moveBefore(Chromium <133)\u2192 \u5E38\u9A7B\u4E0D\u53EF\u7528,\u5207\u6807\u7B7E\u4ECD\u4F1A\u6574\u9875\u91CD\u8F7D(\u5347\u7EA7\u6D4F\u89C8\u5668\u540E\u81EA\u52A8\u751F\u6548)")),n.createElement("div",{className:"dshcs-field"},n.createElement("div",{className:"dshcs-fieldHead"},n.createElement("span",{className:"dshcs-fieldLabel"},"\u4F9D\u8D56\u5B89\u88C5"),null),n.createElement("div",{className:"dshcs-hint",style:{marginTop:4}},"0.1.36 \u8D77 code-server \u672C\u4F53\u968F\u63D2\u4EF6\u5305\u53D1\u5E03,VS Code \u5185\u90E8\u4F9D\u8D56\u4E0E\u9884\u7F16\u8BD1\u539F\u751F\u6A21\u5757(\u5E73\u53F0\u805A\u5408\u5305)\u5168\u90E8\u7531\u5305\u7BA1\u7406\u5668\u5728 dsh plugin add \u65F6\u5B89\u88C5,\u4E0D\u518D\u9700\u8981\u300C\u5B89\u88C5\u73AF\u5883\u300D\u6B65\u9AA4\u3002")),be)}catch(E){return console.error("[code-server] card render error:",E!=null&&E.message!==void 0?E.message:String(E)),null}}function nr(e){try{lr(e)}catch(r){console.error("[code-server] apply failed:",r&&r.stack?r.stack:String(r));try{document.title="CS-ERR "+(r&&r.message||String(r))}catch(t){}}}function lr(e){var r=e.get("slots");if(r===void 0){console.error("[code-server] slots service unavailable");return}var t=e.settingsScope,s=null;if(t!==void 0&&typeof t.bind=="function")s=t.bind({namespace:"code-server"});else{console.error("[code-server] settingsScope unavailable (inject missing?); settings card disabled");return}k("/code-server/status").then(function(f){N({status:f})}).catch(function(){}),r.inject("settings.plugin.item",()=>r.register({name:"settings.plugin.item",key:"code-server",label:"Code Server",inject:function(){return{scope:s}}},ar));var l=!1;function i(f,y){if(!l){l=!0,o();var m=!1;try{m=Xe(f)}catch(g){console.error("[code-server] sidebar tab registration failed:",g!=null&&g.message!=null?g.message:String(g))}R.sidebarUi==="legacy"&&(console.log("[code-server] \u53F3\u4FA7\u680F\u670D\u52A1\u665A\u5230(\u7ECF "+y+"):\u64A4\u9500\u65E7\u7248 DSH \u5224\u5B9A"),k("/code-server/ui-mode",{sidebar:!0}).catch(function(){})),N({sidebarActive:m,sidebarUi:"modern",sidebarRegisterFailed:m!==!0}),r.inject("shell.overlay",()=>r.register({name:"shell.overlay",id:"code-server",order:70,label:"Code Server"},g=>n.createElement(Be,g))),console.log("[code-server] client registered via "+y+": sidebar tab="+m+"(claims dsh-resource://file/**) + resident preload + settings card")}}function d(f){N({sidebarActive:!1,sidebarUi:"legacy"}),console.warn("[code-server] \u672A\u63A2\u6D4B\u5230\u53F3\u4FA7\u680F\u670D\u52A1(sidebarRightTabs/sidebarRight): \u672C\u63D2\u4EF6\u81EA 0.2.3 \u8D77\u4E0D\u518D\u517C\u5BB9\u65E7\u7248 DSH \u2014\u2014 \u9664\u300C\u8BBE\u7F6E \u2192 \u63D2\u4EF6 \u2192 Code Server\u300D\u7684\u63D0\u793A\u5916\u4E0D\u63D0\u4F9B\u4EFB\u4F55\u5165\u53E3,\u4E5F\u4E0D\u9884\u70ED IDE\u3002\u8BF7\u5347\u7EA7 DSH\u3002"),f===!0&&k("/code-server/ui-mode",{sidebar:!1}).catch(function(){})}var p=null,v=null,c=null;function o(){p!==null&&(clearTimeout(p),p=null),v!==null&&(clearTimeout(v),v=null),c!==null&&(clearTimeout(c),c=null)}var b=!1;try{typeof e.inject=="function"&&(b=!0,e.inject(["sidebarRightTabs","sidebarRight"],function(f){i(f,"inject")}))}catch(f){console.warn("[code-server] sidebar inject failed:",f!=null&&f.message!=null?f.message:String(f))}var w=typeof e.get=="function"&&e.get("sidebarRightTabs")!==void 0&&e.get("sidebarRight")!==void 0;if(w){c=setTimeout(function(){l||(console.warn("[code-server] ctx.inject \u672A\u5728 1.5s \u5185\u56DE\u8C03,\u6539\u7528\u540C\u6B65\u670D\u52A1\u6CE8\u518C\u4FA7\u680F"),i(e,"sync-fallback"))},Ve);return}if(b!==!0){d(!0);return}p=setTimeout(function(){l||d(!1)},Ge),v=setTimeout(function(){l||d(!0)},Qe)}var sr=["slots","settingsScope"],ir="code-server";
|
|
5
5
|
return module.exports;}});
|
package/lib/index.js
CHANGED
|
@@ -1,43 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* dsh-code-server — host 半部:VS Code server 子进程(lib/launcher.mjs)
|
|
3
|
-
* + /api/code-server JSON API。
|
|
2
|
+
* dsh-code-server — host 半部:VS Code server 子进程(lib/launcher.mjs)的生命周期/状态 + /api/code-server JSON API。
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
* <树>/lib/vscode/out/server-main.js(树 = @<scope>/dshcs-vscode-server 的 vscode/ 子目录)
|
|
7
|
-
* 依据与实测见 docs/analysis-code-server-as-dsh-plugin.md。
|
|
4
|
+
* 模型:不运行 code-server 的 Node 服务层,直接由 lib/launcher.mjs 驱动树里的
|
|
5
|
+
* <树>/lib/vscode/out/server-main.js(树 = @<scope>/dshcs-vscode-server 的 vscode/ 子目录);
|
|
6
|
+
* 依据与实测见 docs/analysis-code-server-as-dsh-plugin.md。零外部依赖(只用 Node 内置模块)。
|
|
7
|
+
* 静态 profile 插件:exports.name 与 cordis.patch.yml 行 id 一致;inject = ['connection','settings']。
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* - apply(ctx, config) 在共享 /api 通道注册 6 条 exact Fetch 路由:
|
|
14
|
-
* status / start / stop / setup(兼容空操作) / open-file / ui-mode
|
|
9
|
+
* 路由经 ctx.connection.fetch.register 挂在 Connection 的共享 /api 通道上(**不依赖 webServer**):
|
|
10
|
+
* web profile 由 Connection 把 /api 挂到 webServer;desktop 由 apps/desktop-host 交给同一个
|
|
11
|
+
* createSharedFetchHandler('/api')(IPC 帧管道)→ 客户端只需同源 fetch('/api/code-server/<op>')。
|
|
12
|
+
* GET status | POST start{cwd?} | stop | setup(兼容空操作) | open-file{file,line?} | ui-mode{sidebar}
|
|
15
13
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* 通道选择(重要):**不依赖 webServer**。路由经 ctx.connection.fetch.register
|
|
20
|
-
* 挂在 Connection 服务的共享 /api 通道上:
|
|
21
|
-
* - web profile:Connection 自己把 /api 前缀挂到 webServer(带 Host/Origin + 浏览器鉴权);
|
|
22
|
-
* - desktop profile:apps/desktop-host 把 /api/* 交给同一个 createSharedFetchHandler('/api')
|
|
23
|
-
* (IPC 帧管道,无 HTTP 服务器)→ 插件在 desktop 下同样可用。
|
|
24
|
-
* 客户端因此只需同源 fetch('/api/code-server/<op>')(见 src/factory.js 的 api())。
|
|
25
|
-
*
|
|
26
|
-
* 设计要点:
|
|
27
|
-
* - 进程生命周期归本插件:启动写 pid.json,停止用树级终止(taskkill /T 或
|
|
28
|
-
* 进程组 SIGTERM→SIGKILL),退出监听更新状态。
|
|
29
|
-
* - host 重启后 adopt:pid.json 中的进程仍存活且 /healthz 响应 → 接管为
|
|
30
|
-
* running(不重复启动);否则清理 pid.json 视为 stopped。绝不误杀别的进程。
|
|
31
|
-
* - 就绪探测轮询 /healthz;失败时 status 携带启动日志尾部与错误信息。
|
|
32
|
-
* - auth=none 仅允许回环 host;非回环强制 password(未配置 token 则拒绝启动)。
|
|
33
|
-
* - 挂载于 ctx.effect:插件销毁(host 关闭/卸载)时回收自己启动的进程与路由。
|
|
34
|
-
*
|
|
35
|
-
* API(同源 fetch;web 与 desktop 同一套路径):
|
|
36
|
-
* GET /api/code-server/status → { ok, running, status, port, pid, cwd, url,
|
|
37
|
-
* version, error, logTail[, adopted] }
|
|
38
|
-
* POST /api/code-server/start { cwd? } → 幂等启动(换 cwd 则先停后启) → status
|
|
39
|
-
* POST /api/code-server/stop → 停止 → status
|
|
40
|
-
* POST /api/code-server/ui-mode { sidebar } → 客户端上报 UI 载体能力(旧版 DSH 上报 false)
|
|
14
|
+
* 不变量:进程生命周期归本插件(启动写 pid.json,停止树级终止);host 重启后按 pid.json + /healthz
|
|
15
|
+
* adopt 存活实例(不重复启动、不误杀);auth 固定 none(0.2.0 起不再支持口令);插件销毁时回收进程与路由。
|
|
16
|
+
* 旧版 DSH(客户端上报 {sidebar:false})会在此回收"自动预启动"的实例并停止预启动。
|
|
41
17
|
*/
|
|
42
18
|
|
|
43
19
|
import { spawn, execFile, execFileSync } from 'node:child_process';
|
|
@@ -49,7 +25,6 @@ import { fileURLToPath } from 'node:url';
|
|
|
49
25
|
import { createRequire } from 'node:module';
|
|
50
26
|
import {
|
|
51
27
|
PACKAGE_ROOT,
|
|
52
|
-
codeServerEntry,
|
|
53
28
|
codeServerPackageName,
|
|
54
29
|
legacyInstallRoot,
|
|
55
30
|
productPath,
|
|
@@ -91,20 +66,23 @@ export const inject = ['connection', 'settings'];
|
|
|
91
66
|
/** 设置命名空间:卡片经官方 settings 域读写,持久化到官方 settings 文档。 */
|
|
92
67
|
export const SETTINGS_NS = 'code-server';
|
|
93
68
|
|
|
94
|
-
/** 设置卡片 schema(
|
|
69
|
+
/** 设置卡片 schema(只留两个可改设置:keepResident / fileOpenScope)。
|
|
70
|
+
* 旧设置文档里残留的 reserveComposer / windowedOpen 不再出现在 schema 里 —— schemastery 的
|
|
71
|
+
* object 非 strict 会把未知键原样 merge 进解析结果,既不报错也不影响取值,故无需迁移。 */
|
|
95
72
|
export const Config = z.object({
|
|
96
|
-
/** 【0.2.3 起废弃】只对已删除的内部浮动窗口有意义;保留该键仅为兼容旧设置文件(读写均被忽略)。 */
|
|
97
|
-
reserveComposer: z.boolean().default(true),
|
|
98
|
-
/** windowedOpen=false(默认)在右侧栏标签里打开;
|
|
99
|
-
* true 时改为在浏览器新标签页打开 code-server(自动启动并跟随工作区)。 */
|
|
100
|
-
windowedOpen: z.boolean().default(false),
|
|
101
73
|
/** 服务方式:loopback(默认)独立回环端口;dsh 挂到 DSH webServer 的 /code-server
|
|
102
74
|
* (同源、无额外端口、复用 DSH 的 Host/Origin + cookie 防护;需要 DSH 提供 webServer 服务,
|
|
103
|
-
* 缺失或注册失败时自动回退 loopback)
|
|
75
|
+
* 缺失或注册失败时自动回退 loopback)。没有卡片行:改 cordis.patch.yml 的 config.serve
|
|
76
|
+
* 或设置文档里的 code-server.serve。 */
|
|
104
77
|
serve: z.union([z.const('loopback'), z.const('dsh')]).default('loopback'),
|
|
105
78
|
/** keepResident=true(默认)客户端在宿主 running 后把 IDE 预先加载到"停放区",
|
|
106
79
|
* 切标签/收起侧栏不再重载;false 则只在打开面板时才加载(省内存)。 */
|
|
107
80
|
keepResident: z.boolean().default(true),
|
|
81
|
+
/** 客户端认领哪些文件地址(哪些文件的点击交给 Code Server 打开):
|
|
82
|
+
* 'session'(默认)= 只认领会话作用域的 `dsh-resource://file/session/…`(产物、交付、
|
|
83
|
+
* 正文提及、工具视图都走这条);'all' = 连不带会话的 `dsh-resource://file/absolute/…` 也认领。
|
|
84
|
+
* 未认领的地址由 DSH 自带预览兜底。 */
|
|
85
|
+
fileOpenScope: z.union([z.const('session'), z.const('all')]).default('session'),
|
|
108
86
|
});
|
|
109
87
|
|
|
110
88
|
const DEFAULT_CONFIG = {
|
|
@@ -153,15 +131,6 @@ function launcherPath() {
|
|
|
153
131
|
return path.join(path.dirname(fileURLToPath(import.meta.url)), 'launcher.mjs');
|
|
154
132
|
}
|
|
155
133
|
|
|
156
|
-
/** code-server 兼容入口(旧全量树才有 out/node/entry.js);新树返回 null。 */
|
|
157
|
-
function bundledRuntimeEntry() {
|
|
158
|
-
try {
|
|
159
|
-
return codeServerEntry();
|
|
160
|
-
} catch {
|
|
161
|
-
return null;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
134
|
/** 扩展安装目标:VS Code「内置扩展」目录 = <树>/lib/vscode/extensions。
|
|
166
135
|
* (位于程序内置目录的扩展被 VS Code 视为内置——用户视图显示为"内置",不可卸载;
|
|
167
136
|
* --extensions-dir 的是用户级扩展,可被用户禁用/卸载。)
|
|
@@ -179,9 +148,9 @@ function extensionTarget(extensionsDir) {
|
|
|
179
148
|
return { dst: path.join(extensionsDir, 'dshcs-open-file'), builtin: false };
|
|
180
149
|
}
|
|
181
150
|
|
|
182
|
-
/** 内置扩展安装:dshcs-open-file(host 信号文件 → VS Code
|
|
151
|
+
/** 内置扩展安装:dshcs-open-file(host 信号文件 → VS Code 打开文件,可带行号)。
|
|
183
152
|
* 优先装进 code-server 内置扩展目录(不可卸载);同时清理用户级旧副本。
|
|
184
|
-
*
|
|
153
|
+
* 每次启动调用:缺失**或内容有变化**即同步(自愈,且插件升级后能更新已装的旧副本)。 */
|
|
185
154
|
function installBundledExtension(extensionsDir, userDataDir) {
|
|
186
155
|
try {
|
|
187
156
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -189,17 +158,26 @@ function installBundledExtension(extensionsDir, userDataDir) {
|
|
|
189
158
|
if (!fs.existsSync(path.join(src, 'package.json'))) return;
|
|
190
159
|
const target = extensionTarget(extensionsDir);
|
|
191
160
|
const dst = target.dst;
|
|
192
|
-
|
|
161
|
+
const files = ['package.json', 'extension.js'];
|
|
162
|
+
const stale = files.filter((name) => {
|
|
163
|
+
const to = path.join(dst, name);
|
|
164
|
+
if (!fs.existsSync(to)) return true;
|
|
165
|
+
try {
|
|
166
|
+
return fs.readFileSync(path.join(src, name), 'utf8') !== fs.readFileSync(to, 'utf8');
|
|
167
|
+
} catch {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
if (stale.length > 0) {
|
|
193
172
|
fs.mkdirSync(dst, { recursive: true });
|
|
194
|
-
fs.copyFileSync(path.join(src,
|
|
195
|
-
fs.copyFileSync(path.join(src, 'extension.js'), path.join(dst, 'extension.js'));
|
|
173
|
+
for (const name of stale) fs.copyFileSync(path.join(src, name), path.join(dst, name));
|
|
196
174
|
}
|
|
197
175
|
// 清理用户级旧副本(避免重复/可卸载副本)
|
|
198
176
|
const legacy = path.join(extensionsDir, 'dshcs-open-file');
|
|
199
177
|
if (legacy !== dst && fs.existsSync(legacy)) {
|
|
200
178
|
fs.rmSync(legacy, { recursive: true, force: true });
|
|
201
179
|
}
|
|
202
|
-
console.log(`[code-server] bundled extension dshcs-open-file -> ${dst}${target.builtin ? ' (内置,不可卸载)' : ' (用户级回退)'}`);
|
|
180
|
+
console.log(`[code-server] bundled extension dshcs-open-file -> ${dst}${target.builtin ? ' (内置,不可卸载)' : ' (用户级回退)'}${stale.length > 0 ? ` [更新 ${stale.join(',')}]` : ''}`);
|
|
203
181
|
} catch (err) {
|
|
204
182
|
console.warn('[code-server] bundled extension install failed:', err && err.message ? err.message : String(err));
|
|
205
183
|
}
|
|
@@ -387,30 +365,20 @@ export async function apply(ctx, config) {
|
|
|
387
365
|
console.error('[code-server] connection service unavailable; plugin registered but idle');
|
|
388
366
|
return;
|
|
389
367
|
}
|
|
390
|
-
let reserveComposer = true;
|
|
391
|
-
let windowedOpen = false;
|
|
392
368
|
let serveSetting = 'loopback';
|
|
393
369
|
let keepResident = true; // 客户端常驻预热(0.2.2)
|
|
370
|
+
let fileOpenScope = 'session'; // 客户端认领的文件地址范围(0.2.5)
|
|
394
371
|
if (settingsSvc !== undefined && typeof settingsSvc.register === 'function') {
|
|
395
372
|
try {
|
|
396
373
|
const scope = settingsSvc.register(SETTINGS_NS, Config);
|
|
397
374
|
const rawDoc = settingsSvc.get(SETTINGS_NS);
|
|
398
375
|
if (rawDoc !== undefined && rawDoc !== null) {
|
|
399
376
|
const resolved = scope.get();
|
|
400
|
-
reserveComposer = resolved && typeof resolved.reserveComposer === 'boolean' ? resolved.reserveComposer : true;
|
|
401
|
-
windowedOpen = resolved && typeof resolved.windowedOpen === 'boolean' ? resolved.windowedOpen : false;
|
|
402
377
|
serveSetting = resolved && resolved.serve === 'dsh' ? 'dsh' : 'loopback';
|
|
403
378
|
keepResident = resolved && typeof resolved.keepResident === 'boolean' ? resolved.keepResident : true;
|
|
379
|
+
fileOpenScope = resolved && resolved.fileOpenScope === 'all' ? 'all' : 'session';
|
|
404
380
|
}
|
|
405
381
|
scope.watch((next) => {
|
|
406
|
-
if (next != null && typeof next.reserveComposer === 'boolean') {
|
|
407
|
-
reserveComposer = next.reserveComposer;
|
|
408
|
-
console.log(`[code-server] reserveComposer updated: ${reserveComposer}`);
|
|
409
|
-
}
|
|
410
|
-
if (next != null && typeof next.windowedOpen === 'boolean') {
|
|
411
|
-
windowedOpen = next.windowedOpen;
|
|
412
|
-
console.log(`[code-server] windowedOpen updated: ${windowedOpen}`);
|
|
413
|
-
}
|
|
414
382
|
if (next != null && (next.serve === 'dsh' || next.serve === 'loopback')) {
|
|
415
383
|
if (next.serve !== serveSetting) {
|
|
416
384
|
serveSetting = next.serve;
|
|
@@ -421,9 +389,15 @@ export async function apply(ctx, config) {
|
|
|
421
389
|
keepResident = next.keepResident;
|
|
422
390
|
console.log(`[code-server] keepResident updated: ${keepResident}`);
|
|
423
391
|
}
|
|
392
|
+
if (next != null && (next.fileOpenScope === 'all' || next.fileOpenScope === 'session')) {
|
|
393
|
+
if (next.fileOpenScope !== fileOpenScope) {
|
|
394
|
+
fileOpenScope = next.fileOpenScope;
|
|
395
|
+
console.log(`[code-server] fileOpenScope updated: ${fileOpenScope}`);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
424
398
|
});
|
|
425
399
|
} catch (error) {
|
|
426
|
-
console.error(`[code-server] settings unavailable; using defaults (keepResident=true,
|
|
400
|
+
console.error(`[code-server] settings unavailable; using defaults (keepResident=true, fileOpenScope=session): ${error.message}`);
|
|
427
401
|
}
|
|
428
402
|
}
|
|
429
403
|
|
|
@@ -516,9 +490,8 @@ export async function apply(ctx, config) {
|
|
|
516
490
|
error: state.error,
|
|
517
491
|
logTail: state.logTail.slice(-LOG_TAIL_MAX),
|
|
518
492
|
adopted: state.adopted,
|
|
519
|
-
reserveComposer, // 0.2.3 起废弃(仅旧版浮窗用过);保留字段以免旧客户端读取时报错
|
|
520
|
-
windowedOpen,
|
|
521
493
|
keepResident,
|
|
494
|
+
fileOpenScope, // 客户端据此决定认领哪些文件地址(0.2.5)
|
|
522
495
|
sidebarUi: state.sidebarUi,
|
|
523
496
|
env: state.env,
|
|
524
497
|
setup: {
|
|
@@ -600,7 +573,6 @@ export async function apply(ctx, config) {
|
|
|
600
573
|
|
|
601
574
|
async function stop(reason) {
|
|
602
575
|
stopPolling();
|
|
603
|
-
const wasRunning = state.status === 'running' || state.status === 'starting';
|
|
604
576
|
const pid = state.pid;
|
|
605
577
|
if (child !== null) {
|
|
606
578
|
child.stdout?.removeAllListeners?.('data');
|
|
@@ -934,17 +906,19 @@ export async function apply(ctx, config) {
|
|
|
934
906
|
|
|
935
907
|
async function handleOpenFile(request) {
|
|
936
908
|
try {
|
|
937
|
-
// 打开文件:host 写信号文件,内置扩展(dshcs-open-file)在 VS Code
|
|
909
|
+
// 打开文件:host 写信号文件,内置扩展(dshcs-open-file)在 VS Code 中打开它。
|
|
910
|
+
// 0.2.5 起客户端只在"认领到文件地址"时调用本路由(address → 绝对路径);line 可选(1 基)。
|
|
938
911
|
const body = await readJsonBody(request);
|
|
939
912
|
const file = typeof body.file === 'string' ? body.file : null;
|
|
940
913
|
if (file === null || file === '') {
|
|
941
914
|
return jsonResponse({ ok: false, error: '需要 file 字段(要打开的绝对路径)' }, 400);
|
|
942
915
|
}
|
|
916
|
+
const line = Number.isSafeInteger(body.line) && body.line > 0 ? body.line : null;
|
|
943
917
|
const root = dataRoot(cfg);
|
|
944
918
|
const userDataDir = cfg.userDataDir || path.join(root, 'user-data');
|
|
945
919
|
const signal = openFileSignalPath(userDataDir);
|
|
946
920
|
fs.mkdirSync(path.dirname(signal), { recursive: true });
|
|
947
|
-
fs.writeFileSync(signal, JSON.stringify({ file, ts: Date.now() }), 'utf8');
|
|
921
|
+
fs.writeFileSync(signal, JSON.stringify(line === null ? { file, ts: Date.now() } : { file, line, ts: Date.now() }), 'utf8');
|
|
948
922
|
return jsonResponse({ ok: true, signal });
|
|
949
923
|
} catch (err) {
|
|
950
924
|
return failureResponse(err);
|
package/lib/launcher.mjs
CHANGED
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* lib/launcher.mjs — VS Code server 的最小启动器(取代 code-server 的 out/node/** 服务层)。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* /manifest.json PWA manifest(VS Code server 不提供)
|
|
8
|
-
* /_static/* 浏览器静态资源(favicon / PWA 图标 / serviceWorker.js)
|
|
9
|
-
* /proxy/:port/… 转发端口 HTTP 代理(Ports 面板;WS 版仅在 loopback 模式可用)
|
|
4
|
+
* 在**子进程**里加载 <tree>/lib/vscode/out/server-main.js,自建 node:http 把请求交给 VS Code 的
|
|
5
|
+
* handleRequest/handleUpgrade,并补齐 code-server 原先负责的少量 HTTP 面:/healthz(就绪探针)、
|
|
6
|
+
* /manifest.json(PWA)、/_static/*(favicon/PWA/serviceWorker)、/proxy/:port/…(端口转发)。
|
|
10
7
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* 且 node-pty/sqlite 崩溃时必须只带走 IDE,不能带走 DSH host。
|
|
14
|
-
*
|
|
15
|
-
* 用法(由 lib/index.js 调用,不面向用户):
|
|
16
|
-
* node lib/launcher.mjs --tree <VS Code 树根> --user-data-dir <dir> --extensions-dir <dir> \
|
|
17
|
-
* (--port <n> [--host 127.0.0.1] | --pipe <\\.\pipe\name|unix socket>) \
|
|
18
|
-
* [--parent-pid <pid>] [--locale zh-cn]
|
|
8
|
+
* 为什么独立进程:VS Code server 会改进程全局(win32 下 import 即 chdir、注册 SIGPIPE、patch
|
|
9
|
+
* Module 解析、多处 process.exit),且 node-pty/sqlite 崩溃时必须只带走 IDE、不能带走 DSH host。
|
|
19
10
|
*
|
|
11
|
+
* 用法(由 lib/index.js 调用):node lib/launcher.mjs --tree <树根> --user-data-dir <dir>
|
|
12
|
+
* --extensions-dir <dir> (--port <n> [--host 127.0.0.1] | --pipe <name>) [--parent-pid <pid>] [--locale zh-cn]
|
|
20
13
|
* 就绪信号:stdout 打印 `dshcs-ready <productPath> <mode> <addr>`。
|
|
21
14
|
*/
|
|
22
15
|
|
package/lib/native.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// 用 npm: 别名把它们装回**原始名字**。聚合包挂在插件 package.json 的
|
|
9
9
|
// optionalDependencies 上(os/cpu 限定)→ pnpm 一条命令按架构自动选中。
|
|
10
10
|
//
|
|
11
|
-
//
|
|
11
|
+
// 本模块只做三件事:
|
|
12
12
|
// 1. 找到本平台聚合包(以及它的依赖清单 = 期望可解析的原生模块名);
|
|
13
13
|
// 2. 从 code-server 运行位置出发校验这些模块是否真的能 require 到;
|
|
14
14
|
// 3. 必要时在 code-server 树里补齐别名 junction(ESM import 不认 NODE_PATH,只能靠目录链)。
|
package/lib/vendor.js
CHANGED
|
@@ -88,11 +88,6 @@ function rootOfPackage(name) {
|
|
|
88
88
|
return null;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
/** 是否是一棵「精简 VS Code 树」(含 lib/vscode/out/server-main.js,不含 code-server 服务层)。 */
|
|
92
|
-
export function isVscodeOnlyTree(root) {
|
|
93
|
-
return root !== null && existsSync(join(root, 'lib', 'vscode', 'out', 'server-main.js'));
|
|
94
|
-
}
|
|
95
|
-
|
|
96
91
|
/** VS Code 树根(新包 > 旧包 > 旧平台子包 > 包内 vendor/vscode > 包内 vendor/code-server)。
|
|
97
92
|
* @returns {string|null} 绝对路径,如 <profile>\node_modules\@jinsiyu\dshcs-vscode-server\vscode */
|
|
98
93
|
export function vsRoot() {
|
|
@@ -118,19 +113,6 @@ export function codeServerRoot() {
|
|
|
118
113
|
return vsRoot();
|
|
119
114
|
}
|
|
120
115
|
|
|
121
|
-
/** code-server 入口脚本(旧全量树的 out/node/entry.js);精简树下返回 null。 */
|
|
122
|
-
export function codeServerEntry() {
|
|
123
|
-
const root = vsRoot();
|
|
124
|
-
if (root === null) return null;
|
|
125
|
-
const entry = join(root, 'out', 'node', 'entry.js');
|
|
126
|
-
return existsSync(entry) ? entry : null;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/** code-server 运行根(旧名,脚本/调用方沿用)。 */
|
|
130
|
-
export function codeServerTarget() {
|
|
131
|
-
return vsRoot();
|
|
132
|
-
}
|
|
133
|
-
|
|
134
116
|
/** VS Code 客户端约定的产品路径(quality-commit);从 product.json 现算,禁止硬编码。 */
|
|
135
117
|
export function productPath(root = vsRoot()) {
|
|
136
118
|
if (root !== null) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-code-server-app",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "VS Code (from a code-server release) inside DSH: a right-sidebar tab driven by the plugin's own launcher over the in-process VS Code server (lib/launcher.mjs). The IDE is a resident surface moved with Element.moveBefore instead of being remounted, so switching sidebar tabs no longer reloads
|
|
3
|
+
"version": "0.2.6",
|
|
4
|
+
"description": "VS Code (from a code-server release) inside DSH: a right-sidebar tab driven by the plugin's own launcher over the in-process VS Code server (lib/launcher.mjs). The tab claims DSH file addresses (dsh-resource://file/**), so the product's own produced-file chips, delivered-file previews and inline prose mentions open in the workbench. The IDE is a resident surface moved with Element.moveBefore instead of being remounted, so switching sidebar tabs no longer reloads it. Requires a DSH with the right-sidebar services (sidebarRightTabs/sidebarRight, >= 0.1.5-alpha.1); older DSH versions get a single upgrade notice on the settings page and no other UI. Two serving modes: loopback port (default) or same-origin mount on DSH's own webServer (/code-server, protected by ctx.connection.requestRejection). No code-server Node layer, no argon2, no C++ toolchain.",
|
|
5
5
|
"homepage": "https://github.com/jinsiyu/dsh-code-server-app",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -1,29 +1,21 @@
|
|
|
1
|
-
// scripts/vendor-repacks.mjs — 打包期把「VS Code 树」与「pnpm
|
|
1
|
+
// scripts/vendor-repacks.mjs — 打包期把「VS Code 树」与「pnpm 拒绝安装」的原生包打成可安装的预编译包。
|
|
2
2
|
//
|
|
3
3
|
// 为什么:pnpm 认为「含安装脚本」或「含 binding.gyp / .hooks」的包需要构建,必须由宿主
|
|
4
|
-
// pnpm-workspace.yaml 的 allowBuilds 批准,否则 dsh plugin add 直接 exit 1
|
|
5
|
-
//
|
|
4
|
+
// pnpm-workspace.yaml 的 allowBuilds 批准,否则 dsh plugin add 直接 exit 1;VS Code 内部依赖里的一批
|
|
5
|
+
// 原生包都属于这一类。树本身则因为 npm 打包永远排除**包根** node_modules 而必须重打包。
|
|
6
6
|
//
|
|
7
|
-
// 产物(
|
|
8
|
-
// ① @<scope>/dshcs-vscode-server@<code-server 版本>
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
// ③ @<scope>/dsh-code-server-runtime-<platform>-<arch>@<插件版本> 平台聚合包:
|
|
15
|
-
// dependencies 用 npm: 别名把 ② 装回**原始名字**(node-pty / @vscode/sqlite3 / …),
|
|
16
|
-
// 这样 VS Code 的 require/import 不用改,插件只需按 os/cpu 声明 ①(常规依赖)+ ③(可选依赖)。
|
|
17
|
-
// (argon2 已随 code-server 服务层一起移除:auth=none 不再需要口令哈希。)
|
|
7
|
+
// 产物(全部由本脚本生成,再由 scripts/publish-repacks.mjs 发布):
|
|
8
|
+
// ① @<scope>/dshcs-vscode-server@<code-server 版本> vendor/vscode 的树(lib/vscode + out/browser
|
|
9
|
+
// + src/browser),不含 code-server 的 out/node 与它的 136 个依赖(那层由 lib/launcher.mjs 取代);
|
|
10
|
+
// ② @<scope>/dshcs-<名字>[-<platform>-<arch>]@<版本> 需要构建的原生包(node-pty / @vscode/sqlite3 /
|
|
11
|
+
// kerberos / koffi / ssh2 / …),依赖链上命中它们的包也一并重打包(含 optionalDependencies);
|
|
12
|
+
// ③ @<scope>/dsh-code-server-runtime-<platform>-<arch>@<插件版本> 平台聚合包:用 npm: 别名把 ② 装回
|
|
13
|
+
// 原始名字,VS Code 的 require/import 无需改动;插件按 os/cpu 声明 ①(常规)+ ③(可选)依赖。
|
|
18
14
|
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
// 用法:
|
|
22
|
-
// node scripts/vendor-repacks.mjs [--from <已完整安装的 code-server 树>] \
|
|
15
|
+
// 用法:node scripts/vendor-repacks.mjs [--from <已完整安装的 code-server 树>]
|
|
23
16
|
// [--target win32-arm64,win32-x64] [--scope @jinsiyu] [--pack]
|
|
24
|
-
// 不给 --from 时自动准备源树(按 vendor/VENDOR.json 的版本 npm install --ignore-scripts
|
|
25
|
-
//
|
|
26
|
-
// --pack 会用 npm pack 生成 repack/tgz/*.tgz(随后用 scripts/publish-repacks.mjs 发布)。
|
|
17
|
+
// 不给 --from 时自动准备源树(按 vendor/VENDOR.json 的版本 npm install --ignore-scripts,再在
|
|
18
|
+
// lib/vscode 里解包 + rebuild;耗时且需要工具链,维护者换版本时用)。--pack 生成 repack/tgz/*.tgz。
|
|
27
19
|
import { existsSync, readFileSync, readdirSync, mkdirSync, rmSync, writeFileSync, cpSync } from 'node:fs';
|
|
28
20
|
import { dirname, join, relative, resolve } from 'node:path';
|
|
29
21
|
import { fileURLToPath } from 'node:url';
|
package/vendor/VENDOR.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"vscodeVersion": "1.136.1",
|
|
4
4
|
"productPath": "stable-8d5f383f301ca20681f5b6606b8207d9dc87bdd8",
|
|
5
5
|
"layout": "vscode-only",
|
|
6
|
-
"preparedAt": "2026-09-
|
|
6
|
+
"preparedAt": "2026-09-10T17:10:32.317Z",
|
|
7
7
|
"source": "registry",
|
|
8
8
|
"node": "v24.13.1",
|
|
9
9
|
"platform": "win32",
|