@linxin666/dsh-ssh 0.2.3 → 0.2.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/lib/client.js +21 -5
- package/lib/client.js.map +1 -1
- package/lib/index.js +2 -2
- package/lib/types/engine.d.ts +1 -1
- package/package.json +13 -13
- package/src/client/panel/TerminalTab.tsx +26 -5
- package/src/client/panel/panel.module.css +4 -2
- package/src/engine.ts +3 -3
package/lib/index.js
CHANGED
|
@@ -2137,11 +2137,11 @@ var SshEngine = class {
|
|
|
2137
2137
|
stopAllTunnels(this, alias);
|
|
2138
2138
|
disposeRecord(this, alias);
|
|
2139
2139
|
}
|
|
2140
|
-
/** Probe connectivity
|
|
2140
|
+
/** Probe connectivity with a cross-platform shell command. */
|
|
2141
2141
|
async test(alias) {
|
|
2142
2142
|
const started = Date.now();
|
|
2143
2143
|
try {
|
|
2144
|
-
const result = await this.exec(alias, "
|
|
2144
|
+
const result = await this.exec(alias, "echo ok", 1e4);
|
|
2145
2145
|
return result.success ? {
|
|
2146
2146
|
ok: true,
|
|
2147
2147
|
latencyMs: result.durationMs
|
package/lib/types/engine.d.ts
CHANGED
|
@@ -81,7 +81,7 @@ export declare class SshEngine {
|
|
|
81
81
|
* connection — the next operation re-connects from the current config.
|
|
82
82
|
*/
|
|
83
83
|
dropAlias(alias: string): void;
|
|
84
|
-
/** Probe connectivity
|
|
84
|
+
/** Probe connectivity with a cross-platform shell command. */
|
|
85
85
|
test(alias: string): Promise<TestResult>;
|
|
86
86
|
/** Close every pooled connection and tunnel. */
|
|
87
87
|
dispose(): void;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linxin666/dsh-ssh",
|
|
3
3
|
"description": "Remote SSH operations for the dsh web GUI: host config store (~/.dsh/dsh-ssh.json, import from ~/.ssh/config), a persistent ssh2 connection pool with jump-host support, exec / PTY web terminal / SFTP transfer / local port-forward tunnels / cluster execution, plus agent tools (ssh_list, ssh_exec, ssh_upload, ssh_download, ssh_tunnel, ssh_cluster). Hot-pluggable — mounted via ~/.dsh/cordis.patch.yml + a profile node_modules symlink, no dsh source changes.",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.4",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": "^22.19.0 || >=24.0.0"
|
|
@@ -49,18 +49,18 @@
|
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
52
|
-
"@deepseek-ai/dsh-client-connection": "^0.1.0-rc.
|
|
53
|
-
"@deepseek-ai/dsh-client-locale": "^0.1.0-rc.
|
|
54
|
-
"@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.
|
|
55
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.
|
|
56
|
-
"@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.
|
|
57
|
-
"@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.
|
|
58
|
-
"@deepseek-ai/dsh-llm": "^0.1.0-rc.
|
|
59
|
-
"@deepseek-ai/dsh-scope": "^0.1.0-rc.
|
|
60
|
-
"@deepseek-ai/dsh-settings": "^0.1.0-rc.
|
|
61
|
-
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.
|
|
62
|
-
"@deepseek-ai/dsh-timeout": "^0.1.0-rc.
|
|
63
|
-
"@deepseek-ai/dsh-tools": "^0.1.0-rc.
|
|
52
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.0-rc.8",
|
|
53
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.0-rc.8",
|
|
54
|
+
"@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.8",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.8",
|
|
56
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.8",
|
|
57
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.8",
|
|
58
|
+
"@deepseek-ai/dsh-llm": "^0.1.0-rc.8",
|
|
59
|
+
"@deepseek-ai/dsh-scope": "^0.1.0-rc.8",
|
|
60
|
+
"@deepseek-ai/dsh-settings": "^0.1.0-rc.8",
|
|
61
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.8",
|
|
62
|
+
"@deepseek-ai/dsh-timeout": "^0.1.0-rc.8",
|
|
63
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.8",
|
|
64
64
|
"@types/node": "^22.20.0",
|
|
65
65
|
"@types/react": "~18.3.1",
|
|
66
66
|
"@types/react-dom": "^18.3.5",
|
|
@@ -124,17 +124,38 @@ export function TerminalTab({ api, presetAlias, requestId, terminalFont }: Termi
|
|
|
124
124
|
// Unmount cleanup (never touches state on an unmounting component).
|
|
125
125
|
useEffect(() => () => { teardown() }, [])
|
|
126
126
|
|
|
127
|
-
// Keep the terminal fitted to its container
|
|
127
|
+
// Keep the terminal fitted to its container. A window resize is only one
|
|
128
|
+
// trigger: the status banner appearing after connect, panel resizes, and
|
|
129
|
+
// sidebar toggles all change the container without a window resize, so the
|
|
130
|
+
// container itself is observed (otherwise the viewport keeps the pre-banner
|
|
131
|
+
// height and the last line is clipped below the fold). ResizeObserver may
|
|
132
|
+
// be absent (jsdom tests); the window listener then remains the only path.
|
|
128
133
|
useEffect(() => {
|
|
129
|
-
|
|
134
|
+
let lastCols = -1
|
|
135
|
+
let lastRows = -1
|
|
136
|
+
const sync = (): void => {
|
|
130
137
|
const term = termRef.current
|
|
131
138
|
const fit = fitRef.current
|
|
132
139
|
if (term === null || fit === null) return
|
|
133
140
|
fit.fit()
|
|
134
|
-
connRef.current
|
|
141
|
+
const conn = connRef.current
|
|
142
|
+
if (conn !== null && (term.cols !== lastCols || term.rows !== lastRows)) {
|
|
143
|
+
lastCols = term.cols
|
|
144
|
+
lastRows = term.rows
|
|
145
|
+
conn.resize(term.cols, term.rows)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
window.addEventListener('resize', sync)
|
|
149
|
+
const container = containerRef.current
|
|
150
|
+
if (container === null || typeof ResizeObserver === 'undefined') {
|
|
151
|
+
return () => { window.removeEventListener('resize', sync) }
|
|
152
|
+
}
|
|
153
|
+
const observer = new ResizeObserver(() => { sync() })
|
|
154
|
+
observer.observe(container)
|
|
155
|
+
return () => {
|
|
156
|
+
observer.disconnect()
|
|
157
|
+
window.removeEventListener('resize', sync)
|
|
135
158
|
}
|
|
136
|
-
window.addEventListener('resize', onResize)
|
|
137
|
-
return () => { window.removeEventListener('resize', onResize) }
|
|
138
159
|
}, [])
|
|
139
160
|
|
|
140
161
|
const connect = (): void => {
|
|
@@ -703,8 +703,10 @@ html[data-dsh-ssh-active]:not([data-dsh-taskboard-active]) [class*='centerCol']
|
|
|
703
703
|
|
|
704
704
|
.termContainer {
|
|
705
705
|
position: absolute;
|
|
706
|
-
|
|
707
|
-
|
|
706
|
+
/* Inset offsets, not padding: FitAddon measures this element's height as
|
|
707
|
+
the drawable area, so padding here would be measured as terminal space
|
|
708
|
+
and clip the bottom line under a global border-box reset. */
|
|
709
|
+
inset: 8px 10px;
|
|
708
710
|
}
|
|
709
711
|
|
|
710
712
|
.termPlaceholder {
|
package/src/engine.ts
CHANGED
|
@@ -148,11 +148,11 @@ export class SshEngine {
|
|
|
148
148
|
|
|
149
149
|
// ------------------------------------------------------------- misc
|
|
150
150
|
|
|
151
|
-
/** Probe connectivity
|
|
151
|
+
/** Probe connectivity with a cross-platform shell command. */
|
|
152
152
|
async test(alias: string): Promise<TestResult> {
|
|
153
153
|
const started = Date.now()
|
|
154
154
|
try {
|
|
155
|
-
const result = await this.exec(alias, '
|
|
155
|
+
const result = await this.exec(alias, 'echo ok', 10_000)
|
|
156
156
|
return result.success
|
|
157
157
|
? { ok: true, latencyMs: result.durationMs }
|
|
158
158
|
: { ok: false, latencyMs: result.durationMs, error: 'remote exit code ' + result.exitCode }
|
|
@@ -167,4 +167,4 @@ export class SshEngine {
|
|
|
167
167
|
for (const id of [...this.tunnels.keys()]) stopTunnel(this, id)
|
|
168
168
|
for (const alias of [...this.pool.keys()]) disposeRecord(this, alias)
|
|
169
169
|
}
|
|
170
|
-
}
|
|
170
|
+
}
|