dsh-pocket 1.7.3 → 1.7.5
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 +5 -0
- package/README.md +5 -0
- package/lib/index.js +18 -2
- package/lib/proxy.mjs +10 -0
- package/lib/tunnel.mjs +21 -3
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -91,6 +91,11 @@ On the same page click "**Enable anywhere**" → wait for the tunnel (first run
|
|
|
91
91
|
- LAN mode exposes nothing publicly; only devices on the same network can reach it.
|
|
92
92
|
- Built for personal use; the PIN lives in `$DSH_HOME/dsh-pocket/token` and is re-rolled by restarting the public tunnel.
|
|
93
93
|
|
|
94
|
+
## 💻 DSH Desktop
|
|
95
|
+
|
|
96
|
+
- In the desktop app, **QR screen-mirroring works**; **update/restart are managed by the desktop app** (auto-disabled here).
|
|
97
|
+
- ⚠️ The desktop **advanced mode** doesn't support phone access yet (it disables the web layout; the phone gets no layout service → blank screen). Switch back to **compatibility** mode and restart; phones opening an advanced-mode page will see a clear notice overlay.
|
|
98
|
+
|
|
94
99
|
## 🩹 Troubleshooting (traps users step on)
|
|
95
100
|
|
|
96
101
|
| Symptom | Cause & fix |
|
package/README.md
CHANGED
|
@@ -91,6 +91,11 @@ npx @deepseek-ai/dsh web
|
|
|
91
91
|
- 局域网模式不暴露公网,只有同一网络内的设备能访问
|
|
92
92
|
- 适合个人自用;密码存本机 `$DSH_HOME/dsh-pocket/token`,可随时重开公网换新
|
|
93
93
|
|
|
94
|
+
## 💻 DSH Desktop(桌面版)
|
|
95
|
+
|
|
96
|
+
- 桌面版里 dsh-pocket 的**扫码同屏**正常可用;**更新/重启由桌面版管理**(插件内这两项自动停用)
|
|
97
|
+
- ⚠️ 桌面端 **advanced 模式**暂不支持手机访问(该模式禁用网页布局、手机拿不到 layout 服务,会白屏)——请切回 **compatibility** 模式后重启;advanced 模式下手机打开会看到明确的提示层
|
|
98
|
+
|
|
94
99
|
## 🩹 常见问题(别踩的坑)
|
|
95
100
|
|
|
96
101
|
| 现象 | 原因与解决 |
|
package/lib/index.js
CHANGED
|
@@ -19,7 +19,7 @@ import { homedir } from 'node:os';
|
|
|
19
19
|
import { createPocketService } from './service.mjs';
|
|
20
20
|
import { installPocketRpc } from './web-rpc.js';
|
|
21
21
|
import { restartHost } from './restart.js';
|
|
22
|
-
import { desktopEnvPatchScript, DEFAULT_INJECT } from './proxy.mjs';
|
|
22
|
+
import { desktopEnvPatchScript, advancedNoticeScript, DEFAULT_INJECT } from './proxy.mjs';
|
|
23
23
|
|
|
24
24
|
const name = 'dsh-pocket';
|
|
25
25
|
const inject = ['connection', 'webServer'];
|
|
@@ -152,6 +152,19 @@ export function apply(ctx, config = {}, internals = {}) {
|
|
|
152
152
|
logger.info('dsh-pocket: DSH Desktop detected — update/restart disabled here | 检测到桌面端环境,更新/重启已关闭');
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
// 桌面端 advanced 模式检测(issue #19):dsh-plugin-desktop 的 mode 配置存在
|
|
156
|
+
// $DSH_HOME/settings.yaml 的 dsh-plugin-desktop 命名空间下。advanced 组合禁用网页版
|
|
157
|
+
// ui-layout、手机页面又拿不到桌面 layout → 手机访问白屏,这里注入覆盖层提示用户切回。
|
|
158
|
+
const desktopAdvanced = isDesktop && (() => {
|
|
159
|
+
try {
|
|
160
|
+
const raw = readFileSync(join(process.env.DSH_HOME ?? join(homedir(), '.dsh'), 'settings.yaml'), 'utf8');
|
|
161
|
+
return /dsh-plugin-desktop\s*:\s*[\s\S]{0,300}?mode\s*:\s*advanced/i.test(raw);
|
|
162
|
+
} catch { return false; }
|
|
163
|
+
})();
|
|
164
|
+
if (desktopAdvanced) {
|
|
165
|
+
logger.warn('dsh-pocket: DSH Desktop advanced mode — phone access unsupported, injecting notice | 桌面端 advanced 模式:手机访问暂不支持,已注入提示');
|
|
166
|
+
}
|
|
167
|
+
|
|
155
168
|
const service = internals.service ?? createPocketService({
|
|
156
169
|
dshPort,
|
|
157
170
|
port: internals.port ?? config.port ?? 3081,
|
|
@@ -160,7 +173,10 @@ export function apply(ctx, config = {}, internals = {}) {
|
|
|
160
173
|
// 桌面端:手机扫码访问的页面缺 dsh-desktop-mode/platform 参数会让 dsh-plugin-desktop
|
|
161
174
|
// client 崩溃(issue #3/#4)。给代理注入「桌面参数补丁」(history.replaceState 补齐参数,
|
|
162
175
|
// 无跳转;compatibility 模式不套桌面布局,避免移动端按钮叠加)。保留默认 polyfill。
|
|
163
|
-
|
|
176
|
+
// advanced 模式再加警告覆盖层(issue #19)。
|
|
177
|
+
injectHtml: isDesktop
|
|
178
|
+
? DEFAULT_INJECT + desktopEnvPatchScript(process.platform) + (desktopAdvanced ? advancedNoticeScript() : '')
|
|
179
|
+
: undefined,
|
|
164
180
|
// 公网访问密码(issue #13):仅公网隧道 Host 强制;局域网免密码
|
|
165
181
|
auth: {
|
|
166
182
|
getToken: () => getAccessToken(),
|
package/lib/proxy.mjs
CHANGED
|
@@ -52,6 +52,16 @@ function isCompressed(headers) {
|
|
|
52
52
|
/** 默认注入到经代理的 HTML 文档里:crypto.randomUUID polyfill(非安全上下文必需)。 */
|
|
53
53
|
export const DEFAULT_INJECT = RANDOM_UUID_POLYFILL;
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* DSH Desktop advanced 模式不支持的提示覆盖层(issue #19)。
|
|
57
|
+
* advanced 组合会禁用网页版 ui-layout,而桌面 layout 只在 advanced client 提供——
|
|
58
|
+
* 手机页面被注入 compatibility 后无任何 layout 服务 → 启动白屏(Failed to load plugins)。
|
|
59
|
+
* 该脚本在页面上叠加一个固定警告层,让用户明确知道原因(而不是无解白屏)。
|
|
60
|
+
*/
|
|
61
|
+
export function advancedNoticeScript() {
|
|
62
|
+
return `<script data-dsh-pocket-advanced-notice="1">!function(){try{var d=document.createElement('div');d.style.cssText='position:fixed;inset:0;z-index:2147483647;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.55);color:#fff;font:15px/1.7 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;text-align:center;padding:24px';d.textContent='DSH 桌面端处于 advanced 模式,手机访问暂不支持。请在桌面端设置中切回 compatibility 模式后重启。| DSH Desktop is in advanced mode — phone access is not supported yet. Switch back to compatibility in the desktop app and restart.';document.documentElement.appendChild(d);}catch(e){}}();</script>`;
|
|
63
|
+
}
|
|
64
|
+
|
|
55
65
|
// ---------- 可选访问令牌认证(issue #13) ----------
|
|
56
66
|
// 只对公网隧道 Host(trycloudflare.com)强制;局域网免密码。
|
|
57
67
|
// 登录成功后种 HttpOnly 会话 cookie(浏览器关闭失效)→ SPA 内部 API/WS 自动携带。
|
package/lib/tunnel.mjs
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// 无密码模式:URL 即钥匙(dsh web 能执行代码,请勿把二维码/URL 发给别人)。
|
|
5
5
|
|
|
6
6
|
import { spawn, execSync } from 'node:child_process';
|
|
7
|
-
import { mkdir, access, chmod, rm, stat, rename, cp } from 'node:fs/promises';
|
|
7
|
+
import { mkdir, access, chmod, rm, stat, rename, cp, open } from 'node:fs/promises';
|
|
8
8
|
import { homedir } from 'node:os';
|
|
9
9
|
import { join, dirname } from 'node:path';
|
|
10
10
|
import { pipeline } from 'node:stream/promises';
|
|
@@ -146,13 +146,15 @@ export async function downloadFile(url, dest, { signal, segments = PARALLEL_SEGM
|
|
|
146
146
|
|
|
147
147
|
/**
|
|
148
148
|
* 清华 TUNA 镜像的 cloudflared Homebrew bottle URL(国内 CDN,实测 ~3MB/s)。
|
|
149
|
-
*
|
|
149
|
+
* **仅 macOS**——Linux 的 Homebrew bottle 其 ELF 解释器是 `@@HOMEBREW_PREFIX@@`
|
|
150
|
+
* 占位符(需 brew install 时 patchelf 替换),没装 Homebrew 的机器直接 spawn 会
|
|
151
|
+
* ENOENT(issue #22);Linux 走官方 GitHub tgz(解压即用)+ 加速源。
|
|
150
152
|
* 匹配按 CPU 架构取清华目录里版本号最新的 bottle——Homebrew 构建时部署目标
|
|
151
153
|
* 设得较老、向后兼容,所以旧系统(如 Ventura)也能用新一点的 bottle。
|
|
152
154
|
* 抓目录失败/无匹配 → null(调用方回退 GitHub/加速源,不影响可用性)。
|
|
153
155
|
*/
|
|
154
156
|
async function tsinghuaBottleUrl({ os, a }) {
|
|
155
|
-
if (os !== 'darwin'
|
|
157
|
+
if (os !== 'darwin') return null;
|
|
156
158
|
let res;
|
|
157
159
|
try {
|
|
158
160
|
res = await fetch(TUNA_BOTTLES, { signal: AbortSignal.timeout(20_000) });
|
|
@@ -303,6 +305,22 @@ export async function resolveCloudflared({ home, onPhase = () => {}, signal } =
|
|
|
303
305
|
for (const bin of candidates) {
|
|
304
306
|
try {
|
|
305
307
|
await access(bin);
|
|
308
|
+
// Linux:识别并丢弃 Homebrew bottle 坏缓存(issue #22)——其 ELF 解释器是
|
|
309
|
+
// @@HOMEBREW_PREFIX@@ 占位符,直接 spawn 报 ENOENT;读文件头(解释器路径在
|
|
310
|
+
// ELF 头部附近)即可识别,命中则删掉走重新下载
|
|
311
|
+
if (os === 'linux') {
|
|
312
|
+
try {
|
|
313
|
+
const fd = await open(bin, 'r');
|
|
314
|
+
const head = Buffer.alloc(8192);
|
|
315
|
+
await fd.read(head, 0, 8192, 0);
|
|
316
|
+
await fd.close();
|
|
317
|
+
if (head.includes('@@HOMEBREW_PREFIX@@')) {
|
|
318
|
+
await rm(bin, { force: true }).catch(() => {});
|
|
319
|
+
console.warn('dsh-pocket: discarding unusable Homebrew-bottle cloudflared cache | 丢弃不可用的 Homebrew bottle 缓存,重新下载');
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
} catch { /* 读失败按正常缓存处理 */ }
|
|
323
|
+
}
|
|
306
324
|
return bin; // 缓存命中,秒开
|
|
307
325
|
} catch { /* 继续找下一个 */ }
|
|
308
326
|
}
|
package/package.json
CHANGED