Skip to content

feat: support official Desktop transport and native remote sidebar (experimental) - #31

Merged
flymysql merged 1 commit into
flymysql:mainfrom
dahaipeng:feat/official-desktop-transport
Sep 15, 2026
Merged

flymysql merged 1 commit into
flymysql:mainfrom
dahaipeng:feat/official-desktop-transport

Conversation

@dahaipeng

@dahaipeng dahaipeng commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Motivation

The official deepseek-ai/deepseek-harness Desktop composition disables the
legacy webServer and webRuntime rows. With dsh-remote 0.8.15, the hard
webServer injection and bundled legacy sidebar prevent that composition from
starting. I would like to reuse dsh-remote instead of maintaining a separate
SSH implementation in a downstream Desktop distribution.

This is a compatibility proposal, not a request to release the current
branch as production-ready Desktop support. Feedback on the transport and
native sidebar integration approach would be especially helpful.

Changes

  • Make the host's Web transport reactive/optional while preserving the existing
    SSH tools and legacy /dsh-remote/* handlers.
  • Adapt the bounded JSON handlers to ctx.connection.fetch exact routes under
    /api/dsh-remote/*. Desktop requests use the dsh-app: carrier, without a
    new HTTP listener, proxy, fake WebServer service, or core patch. Authentication
    remains the carrier's responsibility.
  • Enforce a 1 MiB request cap before dispatch and preserve UTF-8 across IPC
    chunks. Select the route prefix before sending; do not retry POSTs on another
    transport.
  • Skip the embedded legacy sidebar when the core Web-server row is explicitly
    disabled. Retain the existing standalone-sidebar/order-independence guard.
  • Add native sidebarRightTabs / sidebar.right.pane.tab registrations reusing
    the remote explorer and file editor, with dedicated session-scoped remote
    resource addresses rather than treating remote paths as local Files paths.
  • Add regression tests and document the experimental scope in English/Chinese.

Verification performed

  • npm ci --ignore-scripts --legacy-peer-deps --no-audit --no-fund
  • npm test: 112 passed, 0 failed (existing suite plus 10 new checks).
  • node check.mjs, node --check lib/client.js,
    node --check lib/http-transport.js, git diff --check: passed.
  • Packed the plugin and started an isolated profile using a
    0.1.5-rc.2-derived packaged Desktop Host, with product-specific composition
    removed. Host reported ready; /api/dsh-remote/status returned HTTP 200 over
    the real Desktop IPC carrier. No user profile was reused.
  • In an isolated Electron window, opened the original dsh-remote settings UI
    and imported a synthetic ~/.ssh/config Host entry successfully.
  • Via the Desktop IPC carrier, performed real SSH connect, directory listing,
    and a bounded SFTP text read. All returned HTTP 200; no remote writes or
    port forwarding were exercised
    . Machine details/credentials are not included.

The isolated package fixture explicitly disabled the optional ssh2 and
cpu-features build scripts; this PR does not change a Desktop installer's
allowlist. Installation acceptance under an unmodified stock shell policy is
therefore not being claimed.

Before marking ready for release

  • Validate the final install flow under the stock official Desktop shell
    and agree on the optional native-build dependency policy.
  • Exercise native right-sidebar file open/edit/sync end to end (current
    native slot/resource/lifecycle tests use component doubles).
  • Bind sidebar file operations to their session's machine, and test two
    concurrent sessions on different hosts. Existing /ls, /read, /write,
    etc. use the active-machine pool; session-scoped resource addresses alone do
    not fix that backend behavior. This is a release blocker for multi-host use.
  • Run the complete legacy Web UI regression on the supported Web version.
  • Validate non-macOS remotes/hosts and failure/cancellation UX.

No version bump or npm publication is included. Existing SSH verification and
approval policies are not relaxed by this patch.

@dahaipeng
dahaipeng marked this pull request as ready for review September 14, 2026 08:58
@flymysql
flymysql merged commit aa73dfe into flymysql:main Sep 15, 2026
1 check passed
flymysql pushed a commit that referenced this pull request Sep 15, 2026
…tion fault-tolerant

Follow-up review of PR #31, no behaviour change on Web (113 tests pass).

1. connectionRoute() no longer requires `route.kind === 'exact'`. `kind`
   (WebRouteKind) belongs to dsh-host-webserver's registry; Connection's
   ConnectionFetchRoute has no such field and the real assertFetchRoute() only
   validates the path shape and methods. Requiring a field the API never
   defines meant a future route omitting it would throw.

2. Register Connection Fetch routes one at a time. The old single .map()
   aborted at the first bad route, silently dropping every route AFTER it and
   leaking the disposers of those before it. Because this runs inside a
   ctx.inject child fiber, the loader only logs the throw and the parent plugin
   stays ACTIVE, so a partial registration was invisible. Partial failures are
   now reported via console.warn.

   Verified against the real @deepseek-ai/dsh-client-connection 0.1.5-rc.2:
   a route without `kind` registers, a route with it still registers, real
   dispatch returns 200, and a bad middle route no longer drops later ones.

3. CI syntax-checks lib/*.js via glob instead of a hand-maintained list, which
   had drifted by four files (binding.js, registry.js, update.js, and this
   release's http-transport.js).

4. Declare @deepseek-ai/dsh-client-connection as an optional peer and mark the
   dsh-host-webserver peer optional: the Desktop composition disables that row
   and the plugin no longer hard-depends on it.
flymysql pushed a commit that referenced this pull request Sep 15, 2026
…eview hardening

Ships PR #31 (@dahaipeng) as an experimental compatibility path for the official
DeepSeek Harness Desktop, plus four hardening fixes found in review.

PR #31 — official Desktop transport and native right sidebar:
- The Web transport becomes reactive/optional: `inject` narrows from
  ['tools','systemPrompt','webServer'] to ['tools','systemPrompt'] and each UI
  transport mounts through its own ctx.inject, so JSON routes survive either
  service arriving late. Verified with real cordis: the plugin now activates
  before webServer exists and still registers all 25 routes.
- New Connection Fetch routes (lib/http-transport.js) expose the same bounded
  JSON handlers under /api/dsh-remote/* for the portless dsh-app: carrier, while
  the legacy /dsh-remote/* routes stay as they were.
- A 1 MiB request cap is enforced before dispatch (413, never degrading into an
  empty object), UTF-8 is preserved across IPC chunks, and the route prefix is
  chosen before sending so a POST is never retried on another transport.
- The bundled legacy sidebar stays disabled when the core Web-server row is
  explicitly disabled, keeping the standalone-sidebar guard intact.
- Native sidebarRightTabs / sidebar.right.pane.tab registrations reuse the
  remote explorer and editor with session-scoped dsh-resource:// addresses.

Hardening (no behaviour change on Web, 113/113 tests):
- Drop the route.kind === 'exact' requirement: `kind` is a dsh-host-webserver
  concept and Connection's ConnectionFetchRoute has no such field.
- Register Fetch routes one at a time so one bad route can no longer silently
  drop every later route and leak the earlier disposers.
- CI syntax-checks lib/*.js via glob; the hand-maintained list had drifted by
  four files.
- Declare the client-connection peer optional and mark host-webserver optional,
  since the Desktop composition disables that row.

Desktop support remains experimental: multi-host endpoint binding, native file
edit/sync acceptance and the full legacy Web UI regression are still release
gates, documented in the README compatibility note.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants