dsh-remote 0.8.2 → 0.8.3
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/lib/client.js +47 -32
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -106,6 +106,7 @@ window.__ModuleLoader__.load({
|
|
|
106
106
|
const [auditLines, setAuditLines] = React.useState([])
|
|
107
107
|
const [sshEntries, setSshEntries] = React.useState(null)
|
|
108
108
|
const [workspaces, setWorkspaces] = React.useState([])
|
|
109
|
+
const [advOpen, setAdvOpen] = React.useState(false) // 高级配置折叠
|
|
109
110
|
|
|
110
111
|
const testConn = () => {
|
|
111
112
|
if (!form.host.trim() || tst === 'testing') return
|
|
@@ -171,15 +172,21 @@ window.__ModuleLoader__.load({
|
|
|
171
172
|
|
|
172
173
|
const setF = (k) => (ev) => setForm({ ...form, [k]: ev.target.value })
|
|
173
174
|
const setFb = (k) => (ev) => setForm({ ...form, [k]: ev.target.checked })
|
|
174
|
-
const startEdit = (m) =>
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
175
|
+
const startEdit = (m) => {
|
|
176
|
+
setForm({
|
|
177
|
+
name: m.name, host: m.host, port: String(m.port || 22), username: m.username || 'root',
|
|
178
|
+
password: '', privateKeyPath: m.privateKeyPath || '', passphrase: '', workspace: m.workspace || '',
|
|
179
|
+
hostKeyMode: m.hostKeyMode || '', useAgent: !!m.useAgent, keyboardInteractive: !!m.keyboardInteractive,
|
|
180
|
+
encryptPassword: !!(m.credentialBackend && m.credentialBackend !== 'plain'),
|
|
181
|
+
proxyHost: (m.proxy && m.proxy.host) || '', proxyPort: String((m.proxy && m.proxy.port) || 22),
|
|
182
|
+
proxyUser: (m.proxy && m.proxy.username) || '', proxyPassword: '', proxyKey: (m.proxy && m.proxy.privateKeyPath) || '',
|
|
183
|
+
id: m.id,
|
|
184
|
+
})
|
|
185
|
+
// 编辑时若该机器用了高级配置(私钥/agent/跳板/钥匙串等),自动展开折叠区
|
|
186
|
+
if (m.privateKeyPath || m.useAgent || m.keyboardInteractive || m.workspace || (m.proxy && m.proxy.host) || (m.credentialBackend && m.credentialBackend !== 'plain')) {
|
|
187
|
+
setAdvOpen(true)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
183
190
|
const clearForm = () => setForm({ name: '', host: '', port: '22', username: 'root', password: '', privateKeyPath: '', passphrase: '', workspace: '', hostKeyMode: '', useAgent: false, keyboardInteractive: false, encryptPassword: false, proxyHost: '', proxyPort: '22', proxyUser: '', proxyPassword: '', proxyKey: '', id: '' })
|
|
184
191
|
const save = (action) => {
|
|
185
192
|
setBusy(true); setErr(''); setMsg('')
|
|
@@ -268,31 +275,39 @@ window.__ModuleLoader__.load({
|
|
|
268
275
|
row('端口', React.createElement('input', { value: form.port, onChange: setF('port'), placeholder: '22', style: { ...inputS, width: 70 } }), 'p'),
|
|
269
276
|
row('用户', React.createElement('input', { value: form.username, onChange: setF('username'), placeholder: 'root', style: inputS }), 'u'),
|
|
270
277
|
row('密码', React.createElement('input', { type: 'password', value: form.password, onChange: setF('password'), placeholder: 'SSH 无 key 时用(不回显)', style: inputS }), 'w'),
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
React.createElement('
|
|
279
|
-
|
|
280
|
-
React.createElement('
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
React.createElement('
|
|
284
|
-
|
|
285
|
-
React.createElement('
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
278
|
+
// 高级配置折叠开关
|
|
279
|
+
React.createElement('button', {
|
|
280
|
+
type: 'button',
|
|
281
|
+
onClick: () => setAdvOpen(!advOpen),
|
|
282
|
+
style: { ...buttonS, width: '100%', marginBottom: advOpen ? 10 : 0, color: advOpen ? T.primary : 'inherit', fontWeight: advOpen ? 600 : 400, borderStyle: 'dashed' },
|
|
283
|
+
}, advOpen ? '▲ 收起高级配置' : '▼ 高级配置(私钥 / 跳板机 / agent 等)'),
|
|
284
|
+
advOpen ? React.createElement('div', { key: 'adv', style: { paddingTop: 2 } },
|
|
285
|
+
row('私钥路径', React.createElement('input', { value: form.privateKeyPath, onChange: setF('privateKeyPath'), placeholder: '留空用密码或 agent', style: inputS }), 'k'),
|
|
286
|
+
row('Passphrase', React.createElement('input', { type: 'password', value: form.passphrase, onChange: setF('passphrase'), placeholder: '私钥加密时使用', style: inputS }), 'pp'),
|
|
287
|
+
row('默认工作区', React.createElement('input', { value: form.workspace, onChange: setF('workspace'), placeholder: '可选:该机器的默认远程目录', style: inputS }), 'ws'),
|
|
288
|
+
row('HostKey 模式', React.createElement('select', { value: form.hostKeyMode, onChange: setF('hostKeyMode'), style: { ...inputS, maxWidth: 220 } },
|
|
289
|
+
React.createElement('option', { value: '' }, '(默认 accept-new)'),
|
|
290
|
+
React.createElement('option', { value: 'accept-new' }, 'accept-new(信任首次,之后校验)'),
|
|
291
|
+
React.createElement('option', { value: 'verify' }, 'verify(严格:拒绝陌生主机)'),
|
|
292
|
+
React.createElement('option', { value: 'off' }, 'off(不校验,不推荐)')), 'hkm'),
|
|
293
|
+
React.createElement('div', { style: { display: 'flex', gap: 16, paddingLeft: 90, flexWrap: 'wrap', marginBottom: 8 } },
|
|
294
|
+
React.createElement('label', { style: { fontSize: 12, display: 'flex', gap: 4, alignItems: 'center' } },
|
|
295
|
+
React.createElement('input', { type: 'checkbox', checked: form.useAgent, onChange: setFb('useAgent') }), 'SSH agent(SSH_AUTH_SOCK)'),
|
|
296
|
+
React.createElement('label', { style: { fontSize: 12, display: 'flex', gap: 4, alignItems: 'center' } },
|
|
297
|
+
React.createElement('input', { type: 'checkbox', checked: form.keyboardInteractive, onChange: setFb('keyboardInteractive') }), 'keyboard-interactive(OTP/动态码)'),
|
|
298
|
+
React.createElement('label', { style: { fontSize: 12, display: 'flex', gap: 4, alignItems: 'center' } },
|
|
299
|
+
React.createElement('input', { type: 'checkbox', checked: form.encryptPassword, onChange: setFb('encryptPassword') }), '加密保存密码(系统钥匙串)')),
|
|
300
|
+
row('跳板机', React.createElement('input', { value: form.proxyHost, onChange: setF('proxyHost'), placeholder: '经此主机中转(可选)', style: inputS }), 'ph'),
|
|
301
|
+
row('端口/用户', React.createElement('div', { style: { display: 'flex', gap: 6, flex: 1, flexWrap: 'wrap' } },
|
|
302
|
+
React.createElement('input', { value: form.proxyPort, onChange: setF('proxyPort'), placeholder: '端口(22)', style: { ...inputS, minWidth: 90, maxWidth: 120 } }),
|
|
303
|
+
React.createElement('input', { value: form.proxyUser, onChange: setF('proxyUser'), placeholder: '跳板用户', style: { ...inputS, minWidth: 140 } }),
|
|
304
|
+
React.createElement('input', { type: 'password', value: form.proxyPassword, onChange: setF('proxyPassword'), placeholder: '跳板密码', style: { ...inputS, minWidth: 140 } })), 'pu'),
|
|
305
|
+
row('跳板私钥', React.createElement('input', { value: form.proxyKey, onChange: setF('proxyKey'), placeholder: '跳板私钥路径(可选)', style: inputS }), 'pk'),
|
|
306
|
+
) : null,
|
|
292
307
|
React.createElement('div', { style: { display: 'flex', gap: 8, justifyContent: 'flex-end', alignItems: 'center', flexWrap: 'wrap', marginTop: 4 } },
|
|
293
308
|
msg ? React.createElement('span', { style: { color: T.ok, fontSize: 12, marginRight: 'auto' } }, msg) : null,
|
|
294
309
|
form.id ? React.createElement('button', { style: buttonS, onClick: () => save('delete') }, '删除') : null,
|
|
295
|
-
React.createElement('button', { style: buttonS, onClick: () => { clearForm(); setErr(''); setTst('idle') } }, form.id ? '取消编辑' : '清空'),
|
|
310
|
+
React.createElement('button', { style: buttonS, onClick: () => { clearForm(); setErr(''); setTst('idle'); setAdvOpen(false) } }, form.id ? '取消编辑' : '清空'),
|
|
296
311
|
React.createElement('button', { style: { ...buttonS, fontFamily: 'monospace', whiteSpace: 'nowrap' }, onClick: testConn, disabled: busy || !form.host.trim() || tst === 'testing' },
|
|
297
312
|
tst === 'testing' ? '连接中…' : tst === 'ok' ? '✓ 连接成功' : '测试连接'),
|
|
298
313
|
React.createElement('button', { style: { ...buttonS, fontWeight: 700 }, onClick: () => save(form.id ? 'update' : 'add'), disabled: busy || !form.host.trim() }, busy ? '保存中…' : '保存'),
|
|
@@ -363,7 +378,7 @@ window.__ModuleLoader__.load({
|
|
|
363
378
|
React.createElement('a', { href: 'https://github.com/flymysql/dsh-remote', target: '_blank', rel: 'noopener noreferrer', style: { color: 'inherit' } }, '⭐ 去 GitHub 点个 Star'),
|
|
364
379
|
React.createElement('span', {}, '·'),
|
|
365
380
|
React.createElement('a', { href: 'https://github.com/flymysql/dsh-remote/issues/new', target: '_blank', rel: 'noopener noreferrer', style: { color: 'inherit' } }, '💬 反馈建议 / 提 issue'),
|
|
366
|
-
React.createElement('span', { style: { marginLeft: 'auto', opacity: 0.5 } }, 'dsh-remote v0.8.
|
|
381
|
+
React.createElement('span', { style: { marginLeft: 'auto', opacity: 0.5 } }, 'dsh-remote v0.8.3'),
|
|
367
382
|
),
|
|
368
383
|
)
|
|
369
384
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-remote",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "Remote-work assistant for DeepSeek Harness: connect SSH (password/key/agent/keyboard-interactive/proxy jump), pick a remote workspace, operate on it with 21 rw_* tools (incl. rw_edit/rw_stat/rw_mkdir/rw_remove/rw_move/rw_forward), conflict-aware mirror sync, port forwarding, side-bar remote file editing, audit log, keychain passwords.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "flymysql <flyphp@outlook.com>",
|