@hyzyn/dsh-tty 0.18.0 → 0.18.2
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.en.md +42 -2
- package/README.md +37 -2
- package/client.js +26 -26
- package/lib/index.js +50 -24
- package/lib/index.js.map +1 -1
- package/lib/shell-integration.d.ts +20 -2
- package/lib/shell-integration.js +61 -7
- package/lib/shell-integration.js.map +1 -1
- package/lib/tmux.js +2 -5
- package/lib/tmux.js.map +1 -1
- package/package.json +3 -3
package/lib/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import { definePlugin } from '@hyzyn/dsh-kit';
|
|
|
16
16
|
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
17
17
|
import { spawnSsh, sshTarget, expandHome, setCredentialResolver } from './ssh.js';
|
|
18
18
|
import { probeSsh } from './probe.js';
|
|
19
|
-
import { buildCommandSpawn, buildShellSpawn } from './shell-integration.js';
|
|
19
|
+
import { buildCommandSpawn, buildShellSpawn, defaultShellPath } from './shell-integration.js';
|
|
20
20
|
import { parseSshConfig } from './ssh-config.js';
|
|
21
21
|
import { parseKnownHosts } from './known-hosts.js';
|
|
22
22
|
import { TunnelManager } from './tunnels.js';
|
|
@@ -1709,9 +1709,10 @@ function readCredentialRefNames() {
|
|
|
1709
1709
|
}
|
|
1710
1710
|
}
|
|
1711
1711
|
/**
|
|
1712
|
-
* 设置卡片「Shell
|
|
1713
|
-
*
|
|
1714
|
-
*
|
|
1712
|
+
* 设置卡片「Shell 路径」候选(可选可输入的数据源):POSIX 走 /etc/shells + $SHELL +
|
|
1713
|
+
* 常见安装路径;**Windows 走 %COMSPEC% + Windows PowerShell + PowerShell 7**(原先这套
|
|
1714
|
+
* 候选在 Windows 上恒为空——/bin/zsh 那批路径一个都不存在)。去重后过滤「存在且可执行」,
|
|
1715
|
+
* 默认 shell 排最前。只回路径,不做任何执行。
|
|
1715
1716
|
*/
|
|
1716
1717
|
function listCandidateShells() {
|
|
1717
1718
|
const candidates = [];
|
|
@@ -1720,24 +1721,40 @@ function listCandidateShells() {
|
|
|
1720
1721
|
if (path !== '' && !candidates.includes(path))
|
|
1721
1722
|
candidates.push(path);
|
|
1722
1723
|
};
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1724
|
+
const fallback = defaultShellPath();
|
|
1725
|
+
if (process.platform === 'win32') {
|
|
1726
|
+
const systemRoot = process.env.SystemRoot?.trim() || 'C:\\Windows';
|
|
1727
|
+
const programFiles = process.env.ProgramFiles?.trim() || 'C:\\Program Files';
|
|
1728
|
+
const localAppData = process.env.LOCALAPPDATA?.trim() || '';
|
|
1729
|
+
// 全给**绝对路径**:候选的过滤口径是「存在且可执行」,裸命令名(pwsh.exe)在这里判不了,
|
|
1730
|
+
// 而这三处覆盖了 Windows 上实际存在的 shell(%COMSPEC% 必在,Windows PowerShell 必在,
|
|
1731
|
+
// PowerShell 7 装了才有)。
|
|
1732
|
+
push(process.env.COMSPEC);
|
|
1733
|
+
push(join(systemRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe'));
|
|
1734
|
+
push(join(programFiles, 'PowerShell', '7', 'pwsh.exe'));
|
|
1735
|
+
if (localAppData !== '')
|
|
1736
|
+
push(join(localAppData, 'Microsoft', 'WindowsApps', 'pwsh.exe'));
|
|
1737
|
+
}
|
|
1738
|
+
else {
|
|
1739
|
+
try {
|
|
1740
|
+
for (const line of readFileSync('/etc/shells', 'utf8').split('\n')) {
|
|
1741
|
+
const path = line.trim();
|
|
1742
|
+
if (path !== '' && !path.startsWith('#'))
|
|
1743
|
+
push(path);
|
|
1744
|
+
}
|
|
1728
1745
|
}
|
|
1746
|
+
catch {
|
|
1747
|
+
/* 无 /etc/shells 时跳过 */
|
|
1748
|
+
}
|
|
1749
|
+
push(process.env.SHELL);
|
|
1750
|
+
for (const path of [
|
|
1751
|
+
'/bin/zsh', '/usr/bin/zsh', '/usr/local/bin/zsh', '/opt/homebrew/bin/zsh',
|
|
1752
|
+
'/bin/bash', '/usr/bin/bash', '/usr/local/bin/bash', '/opt/homebrew/bin/bash',
|
|
1753
|
+
'/bin/fish', '/usr/bin/fish', '/usr/local/bin/fish', '/opt/homebrew/bin/fish',
|
|
1754
|
+
'/bin/sh', '/bin/dash', '/bin/ksh', '/bin/tcsh', '/bin/csh',
|
|
1755
|
+
])
|
|
1756
|
+
push(path);
|
|
1729
1757
|
}
|
|
1730
|
-
catch {
|
|
1731
|
-
/* 无 /etc/shells(如 Windows)时跳过 */
|
|
1732
|
-
}
|
|
1733
|
-
push(process.env.SHELL);
|
|
1734
|
-
for (const path of [
|
|
1735
|
-
'/bin/zsh', '/usr/bin/zsh', '/usr/local/bin/zsh', '/opt/homebrew/bin/zsh',
|
|
1736
|
-
'/bin/bash', '/usr/bin/bash', '/usr/local/bin/bash', '/opt/homebrew/bin/bash',
|
|
1737
|
-
'/bin/fish', '/usr/bin/fish', '/usr/local/bin/fish', '/opt/homebrew/bin/fish',
|
|
1738
|
-
'/bin/sh', '/bin/dash', '/bin/ksh', '/bin/tcsh', '/bin/csh',
|
|
1739
|
-
])
|
|
1740
|
-
push(path);
|
|
1741
1758
|
const usable = candidates.filter((path) => {
|
|
1742
1759
|
try {
|
|
1743
1760
|
accessSync(path, fsConstants.X_OK);
|
|
@@ -1747,8 +1764,7 @@ function listCandidateShells() {
|
|
|
1747
1764
|
return false;
|
|
1748
1765
|
}
|
|
1749
1766
|
});
|
|
1750
|
-
|
|
1751
|
-
usable.sort((a, b) => (a === shell ? -1 : b === shell ? 1 : a.localeCompare(b)));
|
|
1767
|
+
usable.sort((a, b) => (a === fallback ? -1 : b === fallback ? 1 : a.localeCompare(b)));
|
|
1752
1768
|
return usable;
|
|
1753
1769
|
}
|
|
1754
1770
|
/**
|
|
@@ -1890,14 +1906,19 @@ const plugin = definePlugin({
|
|
|
1890
1906
|
if (config?.enabled === false)
|
|
1891
1907
|
return;
|
|
1892
1908
|
const live = new LiveConfig({
|
|
1893
|
-
|
|
1909
|
+
// 默认 shell 按平台取(Windows 没有 $SHELL,回落 /bin/zsh 会让本地终端一条都开不起来;
|
|
1910
|
+
// 见 defaultShellPath)。用户显式填了「Shell 路径」就照用。
|
|
1911
|
+
shell: config?.shell?.trim() || defaultShellPath(),
|
|
1894
1912
|
term: config?.term?.trim() || 'xterm-256color',
|
|
1895
1913
|
colorTerm: config?.colorTerm?.trim() || 'truecolor',
|
|
1896
1914
|
cwd: config?.cwd?.trim() || process.cwd(),
|
|
1897
1915
|
reconnectGraceSec: typeof config?.reconnectGraceSec === 'number' && Number.isInteger(config.reconnectGraceSec) && config.reconnectGraceSec >= 0 ? config.reconnectGraceSec : DEFAULT_RECONNECT_GRACE_SEC,
|
|
1898
1916
|
sshHosts: Array.isArray(config?.sshHosts) ? config.sshHosts : [],
|
|
1899
1917
|
hostKeys: Array.isArray(config?.hostKeys) ? config.hostKeys : [],
|
|
1900
|
-
|
|
1918
|
+
// shell 集成(OSC 133/7)靠 POSIX rc 注入 + `-c` 包装层:Windows 上的 cmd / PowerShell
|
|
1919
|
+
// 两者都不成立(实测 cmd 忽略 -c 空跑、PowerShell 报 export 不存在),所以恒关。
|
|
1920
|
+
// 配置项照旧留着(快照里会显示 false),界面上也说明原因。
|
|
1921
|
+
shellIntegration: process.platform !== 'win32' && config?.shellIntegration !== false,
|
|
1901
1922
|
tunnels: Array.isArray(config?.tunnels) ? config.tunnels : [],
|
|
1902
1923
|
persistence: config?.persistence === 'tmux' ? 'tmux' : 'off',
|
|
1903
1924
|
endOnPageClose: config?.endOnPageClose === true,
|
|
@@ -1967,6 +1988,11 @@ const plugin = definePlugin({
|
|
|
1967
1988
|
statsEnabled: live.statsEnabled,
|
|
1968
1989
|
sftpLimits: live.sftpLimits,
|
|
1969
1990
|
toolsRegistered: stateRef.toolsRegistered,
|
|
1991
|
+
/**
|
|
1992
|
+
* 宿主平台(`process.platform`):客户端据此把「Shell 路径 / shell 集成」的说明与候选
|
|
1993
|
+
* 按平台写(Windows 上不提 zsh/bash 那套,也不摆一个恒关闭的集成开关)。
|
|
1994
|
+
*/
|
|
1995
|
+
platform: process.platform,
|
|
1970
1996
|
});
|
|
1971
1997
|
/** 规范化并应用一份配置补丁(settings/updated 事件与 HTTP POST 共用;幂等)。 */
|
|
1972
1998
|
const applyPatch = (section) => {
|