dsh-remote 0.1.2 → 0.1.4
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/cordis.patch.yml +6 -0
- package/lib/client.js +118 -101
- package/package.json +14 -3
package/cordis.patch.yml
ADDED
package/lib/client.js
CHANGED
|
@@ -4,118 +4,135 @@
|
|
|
4
4
|
// hosts and the exact SSH tunnel / reverse-tunnel / reverse-proxy commands,
|
|
5
5
|
// with a copy button. Data comes from the host half's JSON endpoint
|
|
6
6
|
// (GET /dsh-remote/info) served by the official `webServer` service.
|
|
7
|
-
|
|
7
|
+
//
|
|
8
|
+
// Client entries must be classic scripts that register via
|
|
9
|
+
// window.__ModuleLoader__.load({ id, factory }); the factory receives a
|
|
10
|
+
// synchronous `require` and returns the module exports.
|
|
11
|
+
window.__ModuleLoader__.load({
|
|
12
|
+
id: 'dsh-remote',
|
|
13
|
+
factory: (require) => {
|
|
14
|
+
var module = { exports: {} }
|
|
15
|
+
var exports = module.exports
|
|
16
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
|
|
8
17
|
|
|
9
|
-
|
|
18
|
+
const React = require('react')
|
|
10
19
|
|
|
11
|
-
|
|
12
|
-
const q = target ? '?target=' + encodeURIComponent(target) : ''
|
|
13
|
-
const res = await fetch('/dsh-remote/info' + q)
|
|
14
|
-
const data = await res.json().catch(() => ({}))
|
|
15
|
-
if (!res.ok) throw new Error((data && data.error) || 'HTTP ' + res.status)
|
|
16
|
-
return data
|
|
17
|
-
}
|
|
20
|
+
const name = 'dsh-remote'
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
async function fetchInfo(target) {
|
|
23
|
+
const q = target ? '?target=' + encodeURIComponent(target) : ''
|
|
24
|
+
const res = await fetch('/dsh-remote/info' + q)
|
|
25
|
+
const data = await res.json().catch(() => ({}))
|
|
26
|
+
if (!res.ok) throw new Error((data && data.error) || 'HTTP ' + res.status)
|
|
27
|
+
return data
|
|
28
|
+
}
|
|
22
29
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
function RemotePage() {
|
|
31
|
+
const [info, setInfo] = React.useState(null)
|
|
32
|
+
const [error, setError] = React.useState('')
|
|
33
|
+
const [target, setTarget] = React.useState('')
|
|
34
|
+
const [copied, setCopied] = React.useState(false)
|
|
28
35
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
const refresh = (t) => {
|
|
37
|
+
fetchInfo(t || '')
|
|
38
|
+
.then(setInfo)
|
|
39
|
+
.catch((err) => setError(String((err && err.message) || err)))
|
|
40
|
+
}
|
|
34
41
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
42
|
+
React.useEffect(() => {
|
|
43
|
+
refresh('')
|
|
44
|
+
}, [])
|
|
38
45
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
const copy = (text) => {
|
|
47
|
+
if (navigator && navigator.clipboard) {
|
|
48
|
+
navigator.clipboard
|
|
49
|
+
.writeText(text)
|
|
50
|
+
.then(() => {
|
|
51
|
+
setCopied(true)
|
|
52
|
+
setTimeout(() => setCopied(false), 1500)
|
|
53
|
+
})
|
|
54
|
+
.catch(() => {})
|
|
55
|
+
}
|
|
48
56
|
}
|
|
49
|
-
}
|
|
50
57
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
58
|
+
const block = (title, code) =>
|
|
59
|
+
React.createElement(
|
|
60
|
+
'div',
|
|
61
|
+
{ key: title, style: { display: 'flex', flexDirection: 'column', gap: '6px' } },
|
|
62
|
+
React.createElement('div', { style: { fontSize: '13px', fontWeight: 600 } }, title),
|
|
63
|
+
React.createElement('code', {
|
|
64
|
+
style: {
|
|
65
|
+
display: 'block',
|
|
66
|
+
padding: '8px 10px',
|
|
67
|
+
borderRadius: '6px',
|
|
68
|
+
border: '1px solid rgba(128,128,128,0.35)',
|
|
69
|
+
fontSize: '12px',
|
|
70
|
+
whiteSpace: 'pre-wrap',
|
|
71
|
+
wordBreak: 'break-all',
|
|
72
|
+
},
|
|
73
|
+
}, code),
|
|
74
|
+
React.createElement('button', { onClick: () => copy(code), style: { alignSelf: 'flex-start' } }, '复制'),
|
|
75
|
+
)
|
|
69
76
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
77
|
+
if (error)
|
|
78
|
+
return React.createElement('div', { style: { color: '#e06c75', padding: 16 } }, error)
|
|
79
|
+
if (!info)
|
|
80
|
+
return React.createElement('div', { style: { padding: 16, opacity: 0.6 } }, '加载中…')
|
|
74
81
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
82
|
+
const c = info.commands || {}
|
|
83
|
+
const lan = Array.isArray(info.lanAddresses) ? info.lanAddresses : []
|
|
84
|
+
const trusted = Array.isArray(info.trustedHosts) ? info.trustedHosts : []
|
|
78
85
|
|
|
79
|
-
|
|
80
|
-
'div',
|
|
81
|
-
{ style: { padding: '16px', display: 'flex', flexDirection: 'column', gap: '14px' } },
|
|
82
|
-
React.createElement('div', { style: { fontWeight: 600 } }, '远程访问(dsh-remote)'),
|
|
83
|
-
React.createElement(
|
|
86
|
+
return React.createElement(
|
|
84
87
|
'div',
|
|
85
|
-
{ style: {
|
|
86
|
-
React.createElement('
|
|
87
|
-
React.createElement(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
: null,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
React.createElement('
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
88
|
+
{ style: { padding: '16px', display: 'flex', flexDirection: 'column', gap: '14px' } },
|
|
89
|
+
React.createElement('div', { style: { fontWeight: 600 } }, '远程访问(dsh-remote)'),
|
|
90
|
+
React.createElement(
|
|
91
|
+
'div',
|
|
92
|
+
{ style: { display: 'flex', gap: '16px', flexWrap: 'wrap', fontSize: '13px' } },
|
|
93
|
+
React.createElement('span', null, 'Web GUI: ', React.createElement('code', null, info.url)),
|
|
94
|
+
React.createElement('span', null, '端口: ', React.createElement('code', null, String(info.port))),
|
|
95
|
+
lan.length
|
|
96
|
+
? React.createElement('span', null, '局域网: ', React.createElement('code', null, lan.join(', ')))
|
|
97
|
+
: null,
|
|
98
|
+
trusted.length
|
|
99
|
+
? React.createElement('span', null, 'trusted hosts: ', React.createElement('code', null, trusted.join(', ')))
|
|
100
|
+
: null,
|
|
101
|
+
),
|
|
102
|
+
React.createElement('div', { style: { fontSize: '12px', opacity: 0.75 } },
|
|
103
|
+
'跨机器访问请用 SSH 隧道。harness 默认只监听 127.0.0.1,这是官方安全设计(GUI 无鉴权,--host 0.0.0.0 被刻意拒绝)。可选:输入 user@host 生成具体命令。',
|
|
104
|
+
),
|
|
105
|
+
React.createElement('div', { style: { display: 'flex', gap: '8px' } },
|
|
106
|
+
React.createElement('input', {
|
|
107
|
+
value: target,
|
|
108
|
+
onChange: (ev) => setTarget(ev.target.value),
|
|
109
|
+
placeholder: 'user@remote-host(可选)',
|
|
110
|
+
style: { flex: 1 },
|
|
111
|
+
}),
|
|
112
|
+
React.createElement('button', { onClick: () => refresh(target) }, '生成'),
|
|
113
|
+
),
|
|
114
|
+
c.localForward ? block('本机 → 远程(ssh 本地转发,推荐)', c.localForward) : null,
|
|
115
|
+
c.localForwardAuto ? block('autossh 保活版本', c.localForwardAuto) : null,
|
|
116
|
+
c.reverseForward ? block('远程 → 本机(反向隧道,NAT 友好)', c.reverseForward) : null,
|
|
117
|
+
c.trustedFlag ? block('反向代理直达(需自行加鉴权)', c.trustedFlag) : null,
|
|
118
|
+
copied ? React.createElement('div', { style: { fontSize: '12px', opacity: 0.7 } }, '已复制 ✓') : null,
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function apply(ctx) {
|
|
123
|
+
const slots = ctx.get('slots')
|
|
124
|
+
if (slots === undefined) return
|
|
125
|
+
|
|
126
|
+
slots.inject('settings.section', () =>
|
|
127
|
+
slots.register(
|
|
128
|
+
{ name: 'settings.section', id: 'dsh-remote', order: 40, label: () => '远程访问' },
|
|
129
|
+
() => React.createElement(RemotePage, null),
|
|
130
|
+
),
|
|
131
|
+
)
|
|
132
|
+
}
|
|
114
133
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
)
|
|
121
|
-
}
|
|
134
|
+
exports.name = name
|
|
135
|
+
exports.apply = apply
|
|
136
|
+
return module.exports
|
|
137
|
+
},
|
|
138
|
+
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-remote",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Remote-access assistant for DeepSeek Harness: /remote command and a settings page that print the exact SSH tunnel / reverse-tunnel / reverse-proxy commands for this instance (harness intentionally binds loopback only).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -16,14 +16,22 @@
|
|
|
16
16
|
"exports": {
|
|
17
17
|
".": "./lib/index.js",
|
|
18
18
|
"./client": "./lib/client.js",
|
|
19
|
-
"./package.json": "./package.json"
|
|
19
|
+
"./package.json": "./package.json",
|
|
20
|
+
"./cordis.patch.yml": "./cordis.patch.yml"
|
|
20
21
|
},
|
|
21
22
|
"files": [
|
|
22
|
-
"lib"
|
|
23
|
+
"lib",
|
|
24
|
+
"cordis.patch.yml"
|
|
23
25
|
],
|
|
24
26
|
"license": "MIT",
|
|
25
27
|
"dsh": {
|
|
28
|
+
"bundle": {
|
|
29
|
+
"patch": "./cordis.patch.yml"
|
|
30
|
+
},
|
|
26
31
|
"client": {
|
|
32
|
+
"inject": [
|
|
33
|
+
"@deepseek-ai/dsh-client-runtime"
|
|
34
|
+
],
|
|
27
35
|
"platform": "web"
|
|
28
36
|
}
|
|
29
37
|
},
|
|
@@ -31,5 +39,8 @@
|
|
|
31
39
|
"@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
|
|
32
40
|
"@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
|
|
33
41
|
"@deepseek-ai/cordis": "^4.0.1"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@deepseek-ai/schemastery": "^3.18.1"
|
|
34
45
|
}
|
|
35
46
|
}
|