@linxin666/dsh-ssh 0.4.4 → 0.4.5

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.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # node scripts/verify-docs.mjs --write <dir>
5
- README.md: e477f468d33c808362bab0fd246dc6eb2bfefb62
6
- README.zh.md: d37b585d6e6a18f1a9bb22e8d9e223fb39b91076
5
+ README.md: bd5c0cb0afa9dc65e65b1fdfb6ba5205b66019df
6
+ README.zh.md: 84f564e99c5c7a42ae2a48fce5772b940d18ff3e
package/README.md CHANGED
@@ -1,8 +1,21 @@
1
- # dsh-ssh — Remote SSH operations plugin for DSH
1
+ # dsh-ssh · Web SSH Terminal, SFTP Transfer & Remote Operations for DeepSeek Harness (DSH)
2
2
 
3
3
  English | [中文](README.zh.md)
4
4
 
5
- Built on the capability list of [badseal/ssh-skill](https://github.com/badseal/ssh-skill), a remote SSH plugin tailored for DeepSeek Harness (DSH): a persistent connection pool inside the Host process + a Web GUI host-management panel + a Web terminal + Agent tools, all implemented through the official NPM SDK without modifying DSH source.
5
+ <p align="center">
6
+ <img src="https://img.shields.io/npm/v/@linxin666/dsh-ssh?style=flat-square" alt="Version">
7
+ &nbsp;
8
+ <img src="https://img.shields.io/badge/DSH-%3E%3D0.2.0--rc.2-4c6ef5?style=flat-square&amp;labelColor=454a54" alt="DSH">
9
+ &nbsp;
10
+ <img src="https://img.shields.io/badge/license-Apache--2.0-blue?style=flat-square" alt="License">
11
+ </p>
12
+
13
+ <p align="center">
14
+ <strong>Remote Linux Server Operations & Web SSH Suite for DeepSeek Harness (DSH)</strong><br>
15
+ <em>xterm.js Web Terminal · Visual SFTP Transfer · Port Forwarding Tunnels · Cluster Execution · 6 Agent Tools</em>
16
+ </p>
17
+
18
+ A dedicated remote Linux server operations and cluster management plugin for DeepSeek Harness (DSH) Web GUI and official desktop client: in-process persistent connection pool, Web GUI host inventory management, xterm.js terminal, visual SFTP file transfer, port forwarding tunnels, and 6 dedicated agent tools implemented on top of official NPM SDKs without modifying DSH core source code.
6
19
 
7
20
  ## Capabilities
8
21
 
package/README.zh.md CHANGED
@@ -1,8 +1,21 @@
1
- # dsh-ssh — 远程 SSH 运维插件(DSH 版 ssh-skill)
1
+ # dsh-ssh · DeepSeek Harness (DSH) 网页版 SSH 终端、SFTP 文件传输与集群运维插件
2
2
 
3
3
  [English](README.md) | 中文
4
4
 
5
- 基于 [badseal/ssh-skill](https://github.com/badseal/ssh-skill) 的能力清单,为 DeepSeek Harness(DSH)定制的远程 SSH 插件:Host 进程内的持久连接池 + Web GUI 主机管理面板 + Web 终端 + Agent 工具,全部通过官方 NPM SDK 实现,不修改 DSH 源码。
5
+ <p align="center">
6
+ <img src="https://img.shields.io/npm/v/@linxin666/dsh-ssh?style=flat-square" alt="Version">
7
+ &nbsp;
8
+ <img src="https://img.shields.io/badge/DSH-%3E%3D0.2.0--rc.2-4c6ef5?style=flat-square&amp;labelColor=454a54" alt="DSH">
9
+ &nbsp;
10
+ <img src="https://img.shields.io/badge/license-Apache--2.0-blue?style=flat-square" alt="License">
11
+ </p>
12
+
13
+ <p align="center">
14
+ <strong>DeepSeek Harness(DSH)官方 Web GUI 与桌面客户端专属远程 Linux 服务器运维套件</strong><br>
15
+ <em>xterm.js Web 终端 · 可视化 SFTP 传输 · 本地端口转发隧道 · 集群并发命令 · 6 大 Agent 工具</em>
16
+ </p>
17
+
18
+ 专为 DeepSeek Harness(DSH)Web GUI 与官方桌面客户端定制的远程 Linux 服务器运维与集群管理插件:Host 进程内的持久连接池 + Web GUI 主机管理面板 + 基于 xterm.js 的 Web 终端 + 可视化 SFTP 传输 + 6 大专用 Agent 工具,全部通过官方 NPM SDK 实现,零修改侵入 DSH 官方源码。
6
19
 
7
20
  ## 能力
8
21
 
package/lib/client.js CHANGED
@@ -115,7 +115,7 @@ window.__ModuleLoader__.load({
115
115
  "terminal.ready": "终端已连接({alias})",
116
116
  "terminal.exited": "终端已退出({alias})",
117
117
  "terminal.error": "终端错误:{error}",
118
- "terminal.noWebSocket": "当前页面不支持 WebSocket(应用外壳只转发 HTTP),请改用浏览器打开的 Web 界面使用终端。",
118
+ "terminal.noWebSocket": "当前页面不支持 WebSocket(应用外壳没有可连接的本地主机地址),请改用浏览器打开的 Web 界面使用终端。",
119
119
  "terminal.auth.title": "二次身份验证 (2FA / 交互式认证)",
120
120
  "terminal.auth.submit": "提交验证码",
121
121
  "terminal.auth.cancel": "取消",
@@ -271,7 +271,7 @@ window.__ModuleLoader__.load({
271
271
  "terminal.ready": "Terminal connected ({alias})",
272
272
  "terminal.exited": "Terminal exited ({alias})",
273
273
  "terminal.error": "Terminal error: {error}",
274
- "terminal.noWebSocket": "This page cannot carry a WebSocket (the application shell forwards HTTP only). Open the Web UI in a browser to use the terminal.",
274
+ "terminal.noWebSocket": "This page cannot carry a WebSocket (the application shell published no local host address to reach). Open the Web UI in a browser to use the terminal.",
275
275
  "terminal.auth.title": "Two-Factor Authentication (2FA)",
276
276
  "terminal.auth.submit": "Submit Code",
277
277
  "terminal.auth.cancel": "Cancel",
@@ -453,23 +453,71 @@ window.__ModuleLoader__.load({
453
453
  * The WebSocket URL the terminal route is reached at, or undefined when this
454
454
  * page cannot carry one.
455
455
  *
456
- * A page delivered by an application on this machine (the official DSH
457
- * Desktop shell serves its Web GUI from `dsh-app://app/`) has no WebSocket
458
- * transport: its scheme handler forwards HTTP requests to the local host but
459
- * cannot upgrade a socket, so `ws://app/...` never connects and the terminal
460
- * reports "connection error" (issue #1744). Every other page is a web page and
461
- * resolves the socket against its own origin, exactly as before.
456
+ * A web page resolves the socket against its own origin, exactly as before.
462
457
  *
463
- * A blank authority is treated the same as an application scheme: there is
464
- * nothing to dial, and the caller gets the actionable reason instead of a
465
- * socket that can only fail.
458
+ * A page delivered by an application on this machine (the official DSH Desktop
459
+ * shell serves its Web GUI from `dsh-app://app/`) cannot carry a socket on its
460
+ * own scheme: the protocol handler forwards HTTP to the local Host but has no
461
+ * upgrade to forward. That is exactly the case the official transport hook
462
+ * covers - the shell publishes `__DSH_TRANSPORT__.streamBaseUrl`, the loopback
463
+ * authority of the Host it owns and already forwards every other request to
464
+ * (issue #1744). The socket is therefore dialed there instead, with the `ws`/
465
+ * `wss` scheme derived from that base, which is what the shell's
466
+ * `onBeforeSendHeaders` hook expects to see before it attaches its
467
+ * authority-bound credential.
468
+ *
469
+ * The base is used only on an application-delivered page. A web page that
470
+ * somehow carries the hook (the remote channel grants `ownsHost` to a paired
471
+ * LAN page, and that page is fenced behind a pairing channel) keeps resolving
472
+ * against its own origin, so this cannot reroute gated traffic onto a host the
473
+ * page is not entitled to reach. A blank authority is treated the same as an
474
+ * application scheme with no base: there is nothing to dial, and the caller
475
+ * gets the actionable reason instead of a socket that can only fail.
466
476
  *
467
477
  * @param location - the page location to read.
468
478
  * @param search - the query string carrying `alias` or `session`.
479
+ * @param streamBaseUrl - `__DSH_TRANSPORT__.streamBaseUrl`, when the shell published one.
469
480
  * @returns the absolute `ws:`/`wss:` URL, or undefined when the page cannot carry one.
470
481
  */
471
- function terminalSocketUrl(location, search) {
482
+ function terminalSocketUrl(location, search, streamBaseUrl) {
472
483
  if (WEB_PAGE_PROTOCOLS.includes(location.protocol)) return (location.protocol === "https:" ? "wss" : "ws") + "://" + location.host + SSH_API.terminal + search;
484
+ const base = hostAuthorityOf(streamBaseUrl);
485
+ if (base === void 0) return void 0;
486
+ return (base.protocol === "https:" ? "wss" : "ws") + "://" + base.authority + SSH_API.terminal + search;
487
+ }
488
+ /**
489
+ * The authority and scheme of a shell-owned Host base, or undefined when the
490
+ * value is absent, unparsable, or not a network origin this Host can serve
491
+ * (an application scheme could only resolve back to the page that has no
492
+ * socket transport in the first place).
493
+ * @param base - the raw `streamBaseUrl` as published by the transport hook.
494
+ */
495
+ function hostAuthorityOf(base) {
496
+ if (base === void 0 || base === "") return void 0;
497
+ let url;
498
+ try {
499
+ url = new URL(base);
500
+ } catch {
501
+ return;
502
+ }
503
+ if (url.protocol !== "http:" && url.protocol !== "https:") return void 0;
504
+ if (url.username !== "" || url.password !== "") return void 0;
505
+ if (url.host === "") return void 0;
506
+ return {
507
+ protocol: url.protocol,
508
+ authority: url.host
509
+ };
510
+ }
511
+ /**
512
+ * The shell-owned Host authority the page is told to reach, read from the
513
+ * official transport hook. The global is written by the shell before any boot
514
+ * entry runs, so it is absent on every page it does not own.
515
+ * @param globals - the global object to read (defaults to the real one).
516
+ * @returns the published base URL, or undefined when the page carries none.
517
+ */
518
+ function transportStreamBaseUrl(globals = globalThis) {
519
+ const published = globals.__DSH_TRANSPORT__?.streamBaseUrl;
520
+ return typeof published === "string" ? published : void 0;
473
521
  }
474
522
  /**
475
523
  * Schemes a network page can be delivered with. Every other scheme belongs to
@@ -733,7 +781,7 @@ window.__ModuleLoader__.load({
733
781
  }
734
782
  /** One terminal socket over either an alias (open) or a session id (attach). */
735
783
  terminalSocket(search) {
736
- const target = terminalSocketUrl(window.location, search);
784
+ const target = terminalSocketUrl(window.location, search, transportStreamBaseUrl());
737
785
  if (target === void 0) return failedTerminal(tt("terminal.noWebSocket"));
738
786
  let socket;
739
787
  try {
@@ -16367,7 +16415,7 @@ window.__ModuleLoader__.load({
16367
16415
  /** The building package's version, when the bundle carries it. */
16368
16416
  function bakedVersion() {
16369
16417
  try {
16370
- return "0.4.4";
16418
+ return "0.4.5";
16371
16419
  } catch {
16372
16420
  return;
16373
16421
  }