ds-harness-remote 0.4.18 → 0.4.20
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.md +28 -58
- package/dist/client.github.js +44 -4
- package/dist/client.js +44 -4
- package/dist/client.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dsh-plugin.json +1 -1
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,23 +1,13 @@
|
|
|
1
1
|
# DeepSeek Harness Remote
|
|
2
2
|
|
|
3
|
-
Continue
|
|
3
|
+
Continue DeepSeek Harness sessions and experimental Codex workspaces from another device over an end-to-end encrypted connection.
|
|
4
4
|
|
|
5
5
|
[GitHub](https://github.com/liguobao/ds-harness-remote) · [Full guide](https://github.com/liguobao/ds-harness-remote#readme) · [中文说明](https://github.com/liguobao/ds-harness-remote/blob/main/README.zh.md) · [Remote Web](https://dsh.r2049.cn/app) · [Android](https://github.com/liguobao/ds-harness-remote/releases/latest)
|
|
6
6
|
|
|
7
|
-
`ds-harness-remote` is the Remote Host and workspace plugin for
|
|
7
|
+
`ds-harness-remote` is the Remote Host and workspace plugin for DeepSeek Harness. Harness keeps running on your work computer with its existing workspaces, tools, and permission controls; Remote gives authorized devices another window into that environment.
|
|
8
8
|
|
|
9
9
|
> Install this package with `dsh plugin`, not `npm install`. The DSH command updates the selected profile and adds the required bundle configuration.
|
|
10
10
|
|
|
11
|
-
## Highlights
|
|
12
|
-
|
|
13
|
-
- Continue active sessions and review progress from another computer, the web, or Android
|
|
14
|
-
- Send text and image prompts, answer questions, and handle permission requests
|
|
15
|
-
- Open workspaces on another authorized computer without replacing the native Harness interface
|
|
16
|
-
- Reach the Host without opening a public listening port or configuring router port forwarding
|
|
17
|
-
- Protect session traffic with authenticated end-to-end encryption
|
|
18
|
-
- Preview remote files through the optional, read-only `dsh-file-viewer` integration
|
|
19
|
-
- Open Host Codex projects in the existing Remote UI through the optional experimental Codex domain
|
|
20
|
-
|
|
21
11
|
## Install
|
|
22
12
|
|
|
23
13
|
### DSH Desktop
|
|
@@ -26,10 +16,10 @@ Continue your DeepSeek Harness sessions and experimental Codex workspaces from a
|
|
|
26
16
|
|
|
27
17
|
### Existing DSH installation
|
|
28
18
|
|
|
29
|
-
Add the
|
|
19
|
+
Add the current package version to the `web` profile, then restart Harness:
|
|
30
20
|
|
|
31
21
|
```sh
|
|
32
|
-
dsh plugin --profile web add -w ds-harness-remote@0.4.
|
|
22
|
+
dsh plugin --profile web add -w ds-harness-remote@0.4.20
|
|
33
23
|
```
|
|
34
24
|
|
|
35
25
|
### dsh-TUI Host
|
|
@@ -37,71 +27,51 @@ dsh plugin --profile web add -w ds-harness-remote@0.4.13
|
|
|
37
27
|
Remote can also run as a Host in a terminal-only [dsh-TUI](https://github.com/ccch1mneyyy/dsh-TUI) profile:
|
|
38
28
|
|
|
39
29
|
```sh
|
|
40
|
-
dsh plugin --profile dsh-tui add -w ds-harness-remote@0.4.
|
|
30
|
+
dsh plugin --profile dsh-tui add -w ds-harness-remote@0.4.20
|
|
41
31
|
```
|
|
42
32
|
|
|
43
|
-
After starting dsh-TUI, manage Remote with
|
|
33
|
+
After starting dsh-TUI, manage Remote with `/remote`, `/remote login`, `/remote status`, and `/remote logout`.
|
|
44
34
|
|
|
45
|
-
|
|
46
|
-
/remote
|
|
47
|
-
/remote login
|
|
48
|
-
/remote login github
|
|
49
|
-
/remote status
|
|
50
|
-
/remote logout
|
|
51
|
-
```
|
|
35
|
+
## Highlights
|
|
52
36
|
|
|
53
|
-
|
|
37
|
+
- Continue active Harness sessions and review progress from another computer, the web, or Android.
|
|
38
|
+
- Send text and image prompts, answer questions, and handle permission requests.
|
|
39
|
+
- Open workspaces on another authorized computer without replacing the native Harness interface.
|
|
40
|
+
- Use the official workspace file tree and bounded read-only previews on supported Harness versions.
|
|
41
|
+
- Use an optional Host-local terminal and authorized loopback development-service previews.
|
|
42
|
+
- Open Host Codex projects in the existing Remote UI through the optional experimental Codex domain.
|
|
43
|
+
- Reach the Host without opening a public listening port or configuring router port forwarding.
|
|
54
44
|
|
|
55
|
-
##
|
|
45
|
+
## Compatibility
|
|
56
46
|
|
|
57
|
-
1.
|
|
58
|
-
2. Sign in with GitHub or Zhihu QR authorization, or with your account and password.
|
|
59
|
-
3. Enable remote control for the computer that will remain running.
|
|
60
|
-
4. Sign in to the same account from DSH Desktop, [Remote Web](https://dsh.r2049.cn/app), or the [Android client](https://github.com/liguobao/ds-harness-remote/releases/latest).
|
|
61
|
-
5. Select the online Host and open one of its workspaces.
|
|
47
|
+
Plugin `0.4.20` primarily targets DeepSeek Harness `dsh-v0.1.7-rc.1` and also supports `dsh-v0.1.6-alpha.2` and earlier settings hosts. It supports:
|
|
62
48
|
|
|
63
|
-
|
|
49
|
+
- `dsh-v0.1.1-rc.2` through the official legacy `ApiProxy`;
|
|
50
|
+
- `dsh-v0.1.2-alpha.1` through `dsh-v0.1.2-rc.1` through the official Typert Remote Gateway;
|
|
51
|
+
- `dsh-v0.1.5-rc.1` and `dsh-v0.1.6-alpha.1` Session V3 through the official Typert Remote Gateway.
|
|
64
52
|
|
|
65
|
-
|
|
53
|
+
The same package feature-detects the older settings registry and the `0.1.7-rc.1` Volatile settings entry. Remote Web/Desktop and Android normalize released sessions that still report the retired `code` agent preset to `ptc`.
|
|
66
54
|
|
|
67
|
-
|
|
55
|
+
## Self-hosted Server
|
|
68
56
|
|
|
69
|
-
|
|
57
|
+
This repository includes a minimal, single-account self-hosted Relay Server in [`apps/server`](https://github.com/liguobao/ds-harness-remote/tree/main/apps/server). Configure `DSH_SERVER_ACCOUNT` and `DSH_SERVER_PASSWORD`, then point the Host and clients at the same server URL. It provides account login, device credentials, encrypted Control/Noise forwarding, Relay, and a device-status page. It does not provide the complete multi-account Server, Remote Web session UI, or WebRTC/TURN deployment.
|
|
70
58
|
|
|
71
59
|
## Security boundary
|
|
72
60
|
|
|
73
61
|
- Session traffic is encrypted on the Client and decrypted only by the selected Host using `Noise_IK_25519_ChaChaPoly_SHA256`.
|
|
74
62
|
- Account membership and the Host's locally pinned device identity must both authorize a connection.
|
|
75
63
|
- The Host creates outbound connections only; it does not listen on a public port.
|
|
76
|
-
- Remote does not expose
|
|
77
|
-
-
|
|
78
|
-
- The relay can observe necessary connection metadata but cannot read session messages, prompts, tool output, workspace paths, or file-preview content.
|
|
79
|
-
|
|
80
|
-
## Compatibility
|
|
81
|
-
|
|
82
|
-
Plugin `0.4.13` supports:
|
|
83
|
-
|
|
84
|
-
- DeepSeek Harness `dsh-v0.1.1-rc.2` through the official legacy `ApiProxy`
|
|
85
|
-
- DeepSeek Harness `dsh-v0.1.2-alpha.1` through `dsh-v0.1.2-rc.1` through the official Typert Remote Gateway
|
|
86
|
-
- DeepSeek Harness `dsh-v0.1.5-rc.1` Session V3 through the official Typert Remote Gateway
|
|
87
|
-
|
|
88
|
-
Remote Web/Desktop and Android clients normalize released sessions that still report the retired
|
|
89
|
-
`code` agent preset to `ptc`, so old sessions can resume on `dsh-v0.1.5-rc.1` without patching
|
|
90
|
-
DeepSeek Harness itself.
|
|
91
|
-
|
|
92
|
-
Desktop endpoints must use a compatible Harness carrier. Plugin `0.4.13` selects ApiProxy for rc.2 Hosts when available, and Session V3 Desktop clients can open legacy v0.1.2 Typert Remote Hosts through Remote-side normalization. Legacy Typert clients still reject Session V3 Hosts before mutations.
|
|
64
|
+
- Remote does not expose general tool RPC, remote desktop, or file-mutation APIs.
|
|
65
|
+
- Interactive terminals are disabled by default and require a Host-local setting; they run as the Host user independently of Agent approvals.
|
|
93
66
|
|
|
94
67
|
## Documentation
|
|
95
68
|
|
|
96
|
-
- [Complete
|
|
97
|
-
- [完整中文说明](https://github.com/liguobao/ds-harness-remote/blob/main/README.zh.md)
|
|
69
|
+
- [Complete guide](https://github.com/liguobao/ds-harness-remote#readme)
|
|
98
70
|
- [dsh-TUI Remote guide](https://github.com/liguobao/ds-harness-remote/blob/main/docs/dsh-tui.md)
|
|
71
|
+
- [Codex Remote technical notes](https://github.com/liguobao/ds-harness-remote/blob/main/docs/codex-remote.md)
|
|
99
72
|
- [End-to-end encryption](https://github.com/liguobao/ds-harness-remote/blob/main/docs/end-to-end-encryption.md)
|
|
100
73
|
- [Network and transport](https://github.com/liguobao/ds-harness-remote/blob/main/docs/network.md)
|
|
101
74
|
- [Protocol reference](https://github.com/liguobao/ds-harness-remote/blob/main/docs/protocol.md)
|
|
75
|
+
- [Changelog](https://github.com/liguobao/ds-harness-remote/blob/main/CHANGELOG.md)
|
|
102
76
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
This is an independent community project and is not an official DeepSeek product. DeepSeek and related names and marks belong to their respective owners.
|
|
106
|
-
|
|
107
|
-
Licensed under the [MIT License](https://github.com/liguobao/ds-harness-remote/blob/main/packages/plugin/LICENSE).
|
|
77
|
+
This is an independent community project and is not an official DeepSeek product. Licensed under the [MIT License](./LICENSE).
|
package/dist/client.github.js
CHANGED
|
@@ -1804,6 +1804,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
1804
1804
|
saving: "Saving\u2026",
|
|
1805
1805
|
signOut: "Sign out",
|
|
1806
1806
|
signingOut: "Signing out\u2026",
|
|
1807
|
+
hostName: "Host name",
|
|
1808
|
+
deviceId: "Device ID",
|
|
1807
1809
|
serverUrl: "Server URL",
|
|
1808
1810
|
serverUrlHint: "HTTPS origin used for account authorization and encrypted relay.",
|
|
1809
1811
|
serverSaved: "Server address saved. Restart DSH to apply it.",
|
|
@@ -2043,6 +2045,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2043
2045
|
saving: "\u4FDD\u5B58\u4E2D\u2026",
|
|
2044
2046
|
signOut: "\u9000\u51FA\u6388\u6743",
|
|
2045
2047
|
signingOut: "\u6B63\u5728\u9000\u51FA\u2026",
|
|
2048
|
+
hostName: "\u4E3B\u673A\u540D\u79F0",
|
|
2049
|
+
deviceId: "\u8BBE\u5907 ID",
|
|
2046
2050
|
serverUrl: "Server \u5730\u5740",
|
|
2047
2051
|
serverUrlHint: "\u7528\u4E8E\u8D26\u53F7\u6388\u6743\u548C\u52A0\u5BC6\u4E2D\u7EE7\u7684 HTTPS \u5730\u5740\u3002",
|
|
2048
2052
|
serverSaved: "Server \u5730\u5740\u5DF2\u4FDD\u5B58\uFF0C\u91CD\u542F DSH \u540E\u751F\u6548\u3002",
|
|
@@ -2440,7 +2444,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2440
2444
|
}
|
|
2441
2445
|
}
|
|
2442
2446
|
function RemotePluginOptions(props) {
|
|
2443
|
-
let { t } = props, [open, setOpen] = React.useState(props.view === "page"), [serverUrl, setServerUrl] = React.useState(""), [codexEnabled, setCodexEnabled] = React.useState(!0), [terminalEnabled, setTerminalEnabled] = React.useState(!1), [terminalBusy, setTerminalBusy] = React.useState(!1), [portsBusy, setPortsBusy] = React.useState(!1), [previewPorts, setPreviewPorts] = React.useState(""), role = "host", [registrationCode, setRegistrationCode] = React.useState(""), [associations, setAssociations] = React.useState({}), [loaded, setLoaded] = React.useState(!1), [writable, setWritable] = React.useState(!1), [busy, setBusy] = React.useState(!1), [codexBusy, setCodexBusy] = React.useState(!1), [acpBackends, setAcpBackends] = React.useState([]), [acpAvailability, setAcpAvailability] = React.useState({}), [acpChecking, setAcpChecking] = React.useState({}), [acpCheckResults, setAcpCheckResults] = React.useState({}), [addingAcp, setAddingAcp] = React.useState(!1), [acpName, setAcpName] = React.useState(""), [acpCommand, setAcpCommand] = React.useState(""), [acpArguments, setAcpArguments] = React.useState("acp"), [reconnectBusy, setReconnectBusy] = React.useState(!1), [hostStatus, setHostStatus] = React.useState(void 0), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0), [settingsView, setSettingsView] = React.useState(void 0), persistedServerUrl = settingsView?.config.serverUrl ?? "https://dsh.r2049.cn", association = associations.client ?? associations.host, serverDirty = settingsView !== void 0 && serverUrl !== persistedServerUrl, draftDirty = serverDirty, applyView = (view) => {
|
|
2447
|
+
let { t } = props, [open, setOpen] = React.useState(props.view === "page"), [serverUrl, setServerUrl] = React.useState(""), [codexEnabled, setCodexEnabled] = React.useState(!0), [terminalEnabled, setTerminalEnabled] = React.useState(!1), [terminalBusy, setTerminalBusy] = React.useState(!1), [portsBusy, setPortsBusy] = React.useState(!1), [previewPorts, setPreviewPorts] = React.useState(""), role = "host", [registrationCode, setRegistrationCode] = React.useState(""), [associations, setAssociations] = React.useState({}), [loaded, setLoaded] = React.useState(!1), [writable, setWritable] = React.useState(!1), [busy, setBusy] = React.useState(!1), [codexBusy, setCodexBusy] = React.useState(!1), [acpBackends, setAcpBackends] = React.useState([]), [acpAvailability, setAcpAvailability] = React.useState({}), [acpChecking, setAcpChecking] = React.useState({}), [acpCheckResults, setAcpCheckResults] = React.useState({}), [addingAcp, setAddingAcp] = React.useState(!1), [acpName, setAcpName] = React.useState(""), [acpCommand, setAcpCommand] = React.useState(""), [acpArguments, setAcpArguments] = React.useState("acp"), [reconnectBusy, setReconnectBusy] = React.useState(!1), [hostStatus, setHostStatus] = React.useState(void 0), [hostName, setHostName] = React.useState(""), [hostDeviceId, setHostDeviceId] = React.useState(""), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0), [settingsView, setSettingsView] = React.useState(void 0), persistedServerUrl = settingsView?.config.serverUrl ?? "https://dsh.r2049.cn", association = associations.client ?? associations.host, serverDirty = settingsView !== void 0 && serverUrl !== persistedServerUrl, draftDirty = serverDirty, applyView = (view) => {
|
|
2444
2448
|
setSettingsView(view), setServerUrl(view.config.serverUrl ?? "https://dsh.r2049.cn"), setCodexEnabled(view.config.codex?.enabled ?? !0), setTerminalEnabled(view.config.terminal?.enabled ?? !1), setPreviewPorts((view.config.loopback?.ports ?? []).join(", ")), setAcpBackends((view.config.acp?.backends ?? []).map((item) => ({ id: item.id, enabled: item.enabled !== !1 }))), setAcpAvailability(view.acpAvailability ?? {}), setAssociations(view.associations ?? (view.association === void 0 ? {} : { host: view.association })), setWritable(view.writable), setLoaded(!0);
|
|
2445
2449
|
}, load = async () => {
|
|
2446
2450
|
let [view, status] = await Promise.all([
|
|
@@ -2448,13 +2452,15 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2448
2452
|
props.control("status").catch(() => {
|
|
2449
2453
|
})
|
|
2450
2454
|
]);
|
|
2451
|
-
applyView(view), setHostStatus(status?.host);
|
|
2455
|
+
applyView(view), setHostStatus(status?.host), setHostName(status?.deviceName ?? ""), setHostDeviceId(status?.host?.deviceId ?? "");
|
|
2452
2456
|
};
|
|
2453
2457
|
React.useEffect(() => {
|
|
2454
2458
|
load().catch((reason) => setError(messageOf(reason)));
|
|
2455
2459
|
}, []), React.useEffect(() => {
|
|
2456
2460
|
if (association !== void 0)
|
|
2457
|
-
return props.statusFeed.subscribe((status) =>
|
|
2461
|
+
return props.statusFeed.subscribe((status) => {
|
|
2462
|
+
setHostStatus(status.host), setHostName(status.deviceName ?? ""), setHostDeviceId(status.host?.deviceId ?? "");
|
|
2463
|
+
});
|
|
2458
2464
|
}, [association !== void 0]);
|
|
2459
2465
|
let save = async (event) => {
|
|
2460
2466
|
if (event?.preventDefault(), !(!writable || !serverDirty)) {
|
|
@@ -2735,6 +2741,22 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2735
2741
|
React.createElement("p", null, association.account === void 0 ? serverUrl : t("authorizedOn", { role: "Remote", serverUrl }))
|
|
2736
2742
|
)
|
|
2737
2743
|
),
|
|
2744
|
+
React.createElement(
|
|
2745
|
+
"div",
|
|
2746
|
+
{ className: "dshRemoteHostIdentity" },
|
|
2747
|
+
React.createElement(
|
|
2748
|
+
"div",
|
|
2749
|
+
null,
|
|
2750
|
+
React.createElement("span", null, t("hostName")),
|
|
2751
|
+
React.createElement("strong", null, hostName || "\u2014")
|
|
2752
|
+
),
|
|
2753
|
+
React.createElement(
|
|
2754
|
+
"div",
|
|
2755
|
+
null,
|
|
2756
|
+
React.createElement("span", null, t("deviceId")),
|
|
2757
|
+
React.createElement("code", null, hostDeviceId || "\u2014")
|
|
2758
|
+
)
|
|
2759
|
+
),
|
|
2738
2760
|
React.createElement(
|
|
2739
2761
|
"div",
|
|
2740
2762
|
{ className: "dshRemoteField" },
|
|
@@ -2811,7 +2833,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2811
2833
|
React.Fragment,
|
|
2812
2834
|
null,
|
|
2813
2835
|
React.createElement("button", { type: "button", className: "dshRemoteDiscard", disabled: busy, onClick: discard }, t("discard")),
|
|
2814
|
-
React.createElement("button", { type: "button", className: "dshRemoteSave", disabled: busy || !writable, onClick: () => void save() }, t(busy ? "saving" : "save"))
|
|
2836
|
+
React.createElement("button", { type: "button", className: "dshRemoteSave", disabled: busy || !writable, onClick: () => void save() }, t(busy ? "saving" : "save")),
|
|
2837
|
+
React.createElement("button", { type: "button", className: "dshRemoteDiscard", disabled: busy || !writable, onClick: () => void logout() }, t(busy ? "signingOut" : "signOut"))
|
|
2815
2838
|
) : React.createElement("button", {
|
|
2816
2839
|
type: "button",
|
|
2817
2840
|
className: "dshRemoteDiscard",
|
|
@@ -2822,6 +2845,22 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2822
2845
|
) : React.createElement(
|
|
2823
2846
|
"form",
|
|
2824
2847
|
{ className: "dshRemoteSettings", noValidate: !0, onSubmit: (event) => void save(event) },
|
|
2848
|
+
React.createElement(
|
|
2849
|
+
"div",
|
|
2850
|
+
{ className: "dshRemoteHostIdentity" },
|
|
2851
|
+
React.createElement(
|
|
2852
|
+
"div",
|
|
2853
|
+
null,
|
|
2854
|
+
React.createElement("span", null, t("hostName")),
|
|
2855
|
+
React.createElement("strong", null, hostName || "\u2014")
|
|
2856
|
+
),
|
|
2857
|
+
React.createElement(
|
|
2858
|
+
"div",
|
|
2859
|
+
null,
|
|
2860
|
+
React.createElement("span", null, t("deviceId")),
|
|
2861
|
+
React.createElement("code", null, hostDeviceId || "\u2014")
|
|
2862
|
+
)
|
|
2863
|
+
),
|
|
2825
2864
|
React.createElement(
|
|
2826
2865
|
"div",
|
|
2827
2866
|
{ className: "dshRemoteField" },
|
|
@@ -4003,6 +4042,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
4003
4042
|
".dshRemotePluginCardHeader{display:flex;align-items:center}.dshRemotePluginCardToggle{appearance:none;width:100%;min-width:0;font:inherit;color:inherit;text-align:left;cursor:pointer;background:transparent;border:0;border-radius:12px;display:flex;align-items:center;gap:12px;padding:14px 16px}.dshRemotePluginCardToggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}",
|
|
4004
4043
|
".dshRemotePluginCardHeading{display:flex;flex-direction:column;gap:4px;min-width:0;flex:1}.dshRemotePluginCardHeading>strong{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.dshRemotePluginCardHeading>span{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.dshRemotePluginCardStatus{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.dshRemotePluginCardStatus.isOnline{color:var(--dsw-alias-state-success-primary)}.dshRemotePluginCardStatus.isReconnecting{color:var(--dsw-alias-state-warn-label)}.dshRemotePluginCardStatus.isOffline{color:var(--dsw-alias-state-error-primary)}.dshRemotePluginCardChevron{color:var(--dsw-alias-label-tertiary);font-size:18px;line-height:14px;transition:transform .16s}.dshRemotePluginCard.isOpen .dshRemotePluginCardChevron{transform:rotate(180deg)}",
|
|
4005
4044
|
".dshRemotePluginCardBody{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.dshRemoteSettings{display:flex;flex-direction:column;max-width:720px}.dshRemoteSettingsTop{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:12px 0}.dshRemoteSettingsState{margin:0;color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}",
|
|
4045
|
+
".dshRemoteHostIdentity{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;padding:12px 0;border-top:1px solid var(--dsw-alias-border-l2);border-bottom:1px solid var(--dsw-alias-border-l2)}.dshRemoteHostIdentity>div{min-width:0;display:flex;flex-direction:column;gap:3px}.dshRemoteHostIdentity span{color:var(--dsw-alias-label-tertiary);font-size:12px}.dshRemoteHostIdentity strong,.dshRemoteHostIdentity code{min-width:0;overflow-wrap:anywhere;color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500}.dshRemoteHostIdentity code{font-family:var(--dsw-font-mono,ui-monospace,SFMono-Regular,Menlo,monospace);font-weight:400}",
|
|
4006
4046
|
".dshRemoteField{display:flex;flex-direction:column;gap:6px;padding:12px 0}.dshRemoteField+.dshRemoteField{border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteField label{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}.dshRemoteField input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.dshRemoteField input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.dshRemoteField input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.dshRemoteField p{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}",
|
|
4007
4047
|
'.dshRemoteAuthorizationSetting{border-top:1px solid var(--dsw-alias-border-l2);display:flex;align-items:center;justify-content:space-between;gap:20px;padding:12px 0}.dshRemoteAuthorizationSetting>div{min-width:0}.dshRemoteAuthorizationSetting strong{font-size:13px;font-weight:500}.dshRemoteAuthorizationSetting p{margin:3px 0 0;color:var(--dsw-alias-label-tertiary);font-size:12px}.dshRemoteAuthorizationSetting>input{appearance:none;position:relative;width:38px;height:22px;flex:0 0 auto;margin:0;border:1px solid var(--dsw-alias-label-secondary);border-radius:999px;background:var(--dsw-alias-bg-layer-3);cursor:pointer;box-shadow:inset 0 0 0 1px var(--dsw-alias-border-l2);transition:background .16s ease-out,border-color .16s ease-out,box-shadow .16s ease-out}.dshRemoteAuthorizationSetting>input::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--dsw-alias-label-secondary);transition:transform .16s ease-out,background .16s ease-out}.dshRemoteAuthorizationSetting>input:checked{border-color:var(--dsw-alias-state-success-primary);background:var(--dsw-alias-state-success-primary);box-shadow:none}.dshRemoteAuthorizationSetting>input:checked::after{transform:translateX(16px);background:var(--dsw-alias-bg-layer-1)}.dshRemoteAuthorizationSetting>input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.dshRemoteAuthorizationSetting>input:disabled{opacity:.5;cursor:default}@media(prefers-reduced-motion:reduce){.dshRemoteAuthorizationSetting>input,.dshRemoteAuthorizationSetting>input::after{transition:none}}',
|
|
4008
4048
|
".dshRemoteAssociation{min-width:0;flex:1;display:flex;flex-direction:column;gap:4px}.dshRemoteAssociation>span{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}.dshRemoteAssociation strong{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:1.5}.dshRemoteAssociation p{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}",
|
package/dist/client.js
CHANGED
|
@@ -1804,6 +1804,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
1804
1804
|
saving: "Saving\u2026",
|
|
1805
1805
|
signOut: "Sign out",
|
|
1806
1806
|
signingOut: "Signing out\u2026",
|
|
1807
|
+
hostName: "Host name",
|
|
1808
|
+
deviceId: "Device ID",
|
|
1807
1809
|
serverUrl: "Server URL",
|
|
1808
1810
|
serverUrlHint: "HTTPS origin used for account authorization and encrypted relay.",
|
|
1809
1811
|
serverSaved: "Server address saved. Restart DSH to apply it.",
|
|
@@ -2043,6 +2045,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2043
2045
|
saving: "\u4FDD\u5B58\u4E2D\u2026",
|
|
2044
2046
|
signOut: "\u9000\u51FA\u6388\u6743",
|
|
2045
2047
|
signingOut: "\u6B63\u5728\u9000\u51FA\u2026",
|
|
2048
|
+
hostName: "\u4E3B\u673A\u540D\u79F0",
|
|
2049
|
+
deviceId: "\u8BBE\u5907 ID",
|
|
2046
2050
|
serverUrl: "Server \u5730\u5740",
|
|
2047
2051
|
serverUrlHint: "\u7528\u4E8E\u8D26\u53F7\u6388\u6743\u548C\u52A0\u5BC6\u4E2D\u7EE7\u7684 HTTPS \u5730\u5740\u3002",
|
|
2048
2052
|
serverSaved: "Server \u5730\u5740\u5DF2\u4FDD\u5B58\uFF0C\u91CD\u542F DSH \u540E\u751F\u6548\u3002",
|
|
@@ -2440,7 +2444,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2440
2444
|
}
|
|
2441
2445
|
}
|
|
2442
2446
|
function RemotePluginOptions(props) {
|
|
2443
|
-
let { t } = props, [open, setOpen] = React.useState(props.view === "page"), [serverUrl, setServerUrl] = React.useState(""), [codexEnabled, setCodexEnabled] = React.useState(!0), [terminalEnabled, setTerminalEnabled] = React.useState(!1), [terminalBusy, setTerminalBusy] = React.useState(!1), [portsBusy, setPortsBusy] = React.useState(!1), [previewPorts, setPreviewPorts] = React.useState(""), role = "host", [registrationCode, setRegistrationCode] = React.useState(""), [associations, setAssociations] = React.useState({}), [loaded, setLoaded] = React.useState(!1), [writable, setWritable] = React.useState(!1), [busy, setBusy] = React.useState(!1), [codexBusy, setCodexBusy] = React.useState(!1), [acpBackends, setAcpBackends] = React.useState([]), [acpAvailability, setAcpAvailability] = React.useState({}), [acpChecking, setAcpChecking] = React.useState({}), [acpCheckResults, setAcpCheckResults] = React.useState({}), [addingAcp, setAddingAcp] = React.useState(!1), [acpName, setAcpName] = React.useState(""), [acpCommand, setAcpCommand] = React.useState(""), [acpArguments, setAcpArguments] = React.useState("acp"), [reconnectBusy, setReconnectBusy] = React.useState(!1), [hostStatus, setHostStatus] = React.useState(void 0), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0), [settingsView, setSettingsView] = React.useState(void 0), persistedServerUrl = settingsView?.config.serverUrl ?? "https://dsh.r2049.cn", association = associations.client ?? associations.host, serverDirty = settingsView !== void 0 && serverUrl !== persistedServerUrl, draftDirty = serverDirty, applyView = (view) => {
|
|
2447
|
+
let { t } = props, [open, setOpen] = React.useState(props.view === "page"), [serverUrl, setServerUrl] = React.useState(""), [codexEnabled, setCodexEnabled] = React.useState(!0), [terminalEnabled, setTerminalEnabled] = React.useState(!1), [terminalBusy, setTerminalBusy] = React.useState(!1), [portsBusy, setPortsBusy] = React.useState(!1), [previewPorts, setPreviewPorts] = React.useState(""), role = "host", [registrationCode, setRegistrationCode] = React.useState(""), [associations, setAssociations] = React.useState({}), [loaded, setLoaded] = React.useState(!1), [writable, setWritable] = React.useState(!1), [busy, setBusy] = React.useState(!1), [codexBusy, setCodexBusy] = React.useState(!1), [acpBackends, setAcpBackends] = React.useState([]), [acpAvailability, setAcpAvailability] = React.useState({}), [acpChecking, setAcpChecking] = React.useState({}), [acpCheckResults, setAcpCheckResults] = React.useState({}), [addingAcp, setAddingAcp] = React.useState(!1), [acpName, setAcpName] = React.useState(""), [acpCommand, setAcpCommand] = React.useState(""), [acpArguments, setAcpArguments] = React.useState("acp"), [reconnectBusy, setReconnectBusy] = React.useState(!1), [hostStatus, setHostStatus] = React.useState(void 0), [hostName, setHostName] = React.useState(""), [hostDeviceId, setHostDeviceId] = React.useState(""), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0), [settingsView, setSettingsView] = React.useState(void 0), persistedServerUrl = settingsView?.config.serverUrl ?? "https://dsh.r2049.cn", association = associations.client ?? associations.host, serverDirty = settingsView !== void 0 && serverUrl !== persistedServerUrl, draftDirty = serverDirty, applyView = (view) => {
|
|
2444
2448
|
setSettingsView(view), setServerUrl(view.config.serverUrl ?? "https://dsh.r2049.cn"), setCodexEnabled(view.config.codex?.enabled ?? !0), setTerminalEnabled(view.config.terminal?.enabled ?? !1), setPreviewPorts((view.config.loopback?.ports ?? []).join(", ")), setAcpBackends((view.config.acp?.backends ?? []).map((item) => ({ id: item.id, enabled: item.enabled !== !1 }))), setAcpAvailability(view.acpAvailability ?? {}), setAssociations(view.associations ?? (view.association === void 0 ? {} : { host: view.association })), setWritable(view.writable), setLoaded(!0);
|
|
2445
2449
|
}, load = async () => {
|
|
2446
2450
|
let [view, status] = await Promise.all([
|
|
@@ -2448,13 +2452,15 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2448
2452
|
props.control("status").catch(() => {
|
|
2449
2453
|
})
|
|
2450
2454
|
]);
|
|
2451
|
-
applyView(view), setHostStatus(status?.host);
|
|
2455
|
+
applyView(view), setHostStatus(status?.host), setHostName(status?.deviceName ?? ""), setHostDeviceId(status?.host?.deviceId ?? "");
|
|
2452
2456
|
};
|
|
2453
2457
|
React.useEffect(() => {
|
|
2454
2458
|
load().catch((reason) => setError(messageOf(reason)));
|
|
2455
2459
|
}, []), React.useEffect(() => {
|
|
2456
2460
|
if (association !== void 0)
|
|
2457
|
-
return props.statusFeed.subscribe((status) =>
|
|
2461
|
+
return props.statusFeed.subscribe((status) => {
|
|
2462
|
+
setHostStatus(status.host), setHostName(status.deviceName ?? ""), setHostDeviceId(status.host?.deviceId ?? "");
|
|
2463
|
+
});
|
|
2458
2464
|
}, [association !== void 0]);
|
|
2459
2465
|
let save = async (event) => {
|
|
2460
2466
|
if (event?.preventDefault(), !(!writable || !serverDirty)) {
|
|
@@ -2735,6 +2741,22 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2735
2741
|
React.createElement("p", null, association.account === void 0 ? serverUrl : t("authorizedOn", { role: "Remote", serverUrl }))
|
|
2736
2742
|
)
|
|
2737
2743
|
),
|
|
2744
|
+
React.createElement(
|
|
2745
|
+
"div",
|
|
2746
|
+
{ className: "dshRemoteHostIdentity" },
|
|
2747
|
+
React.createElement(
|
|
2748
|
+
"div",
|
|
2749
|
+
null,
|
|
2750
|
+
React.createElement("span", null, t("hostName")),
|
|
2751
|
+
React.createElement("strong", null, hostName || "\u2014")
|
|
2752
|
+
),
|
|
2753
|
+
React.createElement(
|
|
2754
|
+
"div",
|
|
2755
|
+
null,
|
|
2756
|
+
React.createElement("span", null, t("deviceId")),
|
|
2757
|
+
React.createElement("code", null, hostDeviceId || "\u2014")
|
|
2758
|
+
)
|
|
2759
|
+
),
|
|
2738
2760
|
React.createElement(
|
|
2739
2761
|
"div",
|
|
2740
2762
|
{ className: "dshRemoteField" },
|
|
@@ -2811,7 +2833,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2811
2833
|
React.Fragment,
|
|
2812
2834
|
null,
|
|
2813
2835
|
React.createElement("button", { type: "button", className: "dshRemoteDiscard", disabled: busy, onClick: discard }, t("discard")),
|
|
2814
|
-
React.createElement("button", { type: "button", className: "dshRemoteSave", disabled: busy || !writable, onClick: () => void save() }, t(busy ? "saving" : "save"))
|
|
2836
|
+
React.createElement("button", { type: "button", className: "dshRemoteSave", disabled: busy || !writable, onClick: () => void save() }, t(busy ? "saving" : "save")),
|
|
2837
|
+
React.createElement("button", { type: "button", className: "dshRemoteDiscard", disabled: busy || !writable, onClick: () => void logout() }, t(busy ? "signingOut" : "signOut"))
|
|
2815
2838
|
) : React.createElement("button", {
|
|
2816
2839
|
type: "button",
|
|
2817
2840
|
className: "dshRemoteDiscard",
|
|
@@ -2822,6 +2845,22 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2822
2845
|
) : React.createElement(
|
|
2823
2846
|
"form",
|
|
2824
2847
|
{ className: "dshRemoteSettings", noValidate: !0, onSubmit: (event) => void save(event) },
|
|
2848
|
+
React.createElement(
|
|
2849
|
+
"div",
|
|
2850
|
+
{ className: "dshRemoteHostIdentity" },
|
|
2851
|
+
React.createElement(
|
|
2852
|
+
"div",
|
|
2853
|
+
null,
|
|
2854
|
+
React.createElement("span", null, t("hostName")),
|
|
2855
|
+
React.createElement("strong", null, hostName || "\u2014")
|
|
2856
|
+
),
|
|
2857
|
+
React.createElement(
|
|
2858
|
+
"div",
|
|
2859
|
+
null,
|
|
2860
|
+
React.createElement("span", null, t("deviceId")),
|
|
2861
|
+
React.createElement("code", null, hostDeviceId || "\u2014")
|
|
2862
|
+
)
|
|
2863
|
+
),
|
|
2825
2864
|
React.createElement(
|
|
2826
2865
|
"div",
|
|
2827
2866
|
{ className: "dshRemoteField" },
|
|
@@ -4003,6 +4042,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
4003
4042
|
".dshRemotePluginCardHeader{display:flex;align-items:center}.dshRemotePluginCardToggle{appearance:none;width:100%;min-width:0;font:inherit;color:inherit;text-align:left;cursor:pointer;background:transparent;border:0;border-radius:12px;display:flex;align-items:center;gap:12px;padding:14px 16px}.dshRemotePluginCardToggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}",
|
|
4004
4043
|
".dshRemotePluginCardHeading{display:flex;flex-direction:column;gap:4px;min-width:0;flex:1}.dshRemotePluginCardHeading>strong{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.dshRemotePluginCardHeading>span{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.dshRemotePluginCardStatus{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.dshRemotePluginCardStatus.isOnline{color:var(--dsw-alias-state-success-primary)}.dshRemotePluginCardStatus.isReconnecting{color:var(--dsw-alias-state-warn-label)}.dshRemotePluginCardStatus.isOffline{color:var(--dsw-alias-state-error-primary)}.dshRemotePluginCardChevron{color:var(--dsw-alias-label-tertiary);font-size:18px;line-height:14px;transition:transform .16s}.dshRemotePluginCard.isOpen .dshRemotePluginCardChevron{transform:rotate(180deg)}",
|
|
4005
4044
|
".dshRemotePluginCardBody{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.dshRemoteSettings{display:flex;flex-direction:column;max-width:720px}.dshRemoteSettingsTop{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:12px 0}.dshRemoteSettingsState{margin:0;color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}",
|
|
4045
|
+
".dshRemoteHostIdentity{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;padding:12px 0;border-top:1px solid var(--dsw-alias-border-l2);border-bottom:1px solid var(--dsw-alias-border-l2)}.dshRemoteHostIdentity>div{min-width:0;display:flex;flex-direction:column;gap:3px}.dshRemoteHostIdentity span{color:var(--dsw-alias-label-tertiary);font-size:12px}.dshRemoteHostIdentity strong,.dshRemoteHostIdentity code{min-width:0;overflow-wrap:anywhere;color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500}.dshRemoteHostIdentity code{font-family:var(--dsw-font-mono,ui-monospace,SFMono-Regular,Menlo,monospace);font-weight:400}",
|
|
4006
4046
|
".dshRemoteField{display:flex;flex-direction:column;gap:6px;padding:12px 0}.dshRemoteField+.dshRemoteField{border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteField label{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}.dshRemoteField input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.dshRemoteField input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.dshRemoteField input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.dshRemoteField p{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}",
|
|
4007
4047
|
'.dshRemoteAuthorizationSetting{border-top:1px solid var(--dsw-alias-border-l2);display:flex;align-items:center;justify-content:space-between;gap:20px;padding:12px 0}.dshRemoteAuthorizationSetting>div{min-width:0}.dshRemoteAuthorizationSetting strong{font-size:13px;font-weight:500}.dshRemoteAuthorizationSetting p{margin:3px 0 0;color:var(--dsw-alias-label-tertiary);font-size:12px}.dshRemoteAuthorizationSetting>input{appearance:none;position:relative;width:38px;height:22px;flex:0 0 auto;margin:0;border:1px solid var(--dsw-alias-label-secondary);border-radius:999px;background:var(--dsw-alias-bg-layer-3);cursor:pointer;box-shadow:inset 0 0 0 1px var(--dsw-alias-border-l2);transition:background .16s ease-out,border-color .16s ease-out,box-shadow .16s ease-out}.dshRemoteAuthorizationSetting>input::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--dsw-alias-label-secondary);transition:transform .16s ease-out,background .16s ease-out}.dshRemoteAuthorizationSetting>input:checked{border-color:var(--dsw-alias-state-success-primary);background:var(--dsw-alias-state-success-primary);box-shadow:none}.dshRemoteAuthorizationSetting>input:checked::after{transform:translateX(16px);background:var(--dsw-alias-bg-layer-1)}.dshRemoteAuthorizationSetting>input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.dshRemoteAuthorizationSetting>input:disabled{opacity:.5;cursor:default}@media(prefers-reduced-motion:reduce){.dshRemoteAuthorizationSetting>input,.dshRemoteAuthorizationSetting>input::after{transition:none}}',
|
|
4008
4048
|
".dshRemoteAssociation{min-width:0;flex:1;display:flex;flex-direction:column;gap:4px}.dshRemoteAssociation>span{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}.dshRemoteAssociation strong{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:1.5}.dshRemoteAssociation p{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}",
|