@fffangchenghao/dsh-autoupdater 0.6.2 → 0.6.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/README.md +2 -1
- package/main.js +42 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -97,6 +97,7 @@ dsh plugin --profile web add github:fangchenghao/dsh-autoupdater
|
|
|
97
97
|
- **`dsh.cmd` 调用**:PATH / sibling 找到的 `.cmd` 经 `cmd.exe` 执行并正确加引号;超时用 `taskkill /T /F` 结束整棵进程树,避免留下 pnpm 子进程。
|
|
98
98
|
- **环境变量**:没有 `HOME` 时用 `homedir()`(Windows 的 `USERPROFILE`);PATH 兼容 `Path` 键,并额外查找 `%APPDATA%\npm` / `%LOCALAPPDATA%\pnpm`。
|
|
99
99
|
- Windows 上不执行 DSH 本体更新(交给安装器/App 自带更新器),插件换版后同样只提示重启。
|
|
100
|
+
- **多 profile 选择**:优先使用桌面 App 注入的 `DSH_PROFILE_DIR` / `DSH_PROFILE`;桌面版在两者都缺失时默认 `desktop`,不会因为某个测试 profile 的 `node_modules` 更新时间更近而误选。
|
|
100
101
|
|
|
101
102
|
开发机是 macOS;Windows 分支是按 Node/Electron 的跨平台语义改的,并做了逻辑测试,但**尚未在真实 Windows 机器上端到端跑过**。如果 Windows 上仍失败,请把面板日志和 `%USERPROFILE%\.dsh\autoupdater\history.jsonl` 发到 GitHub issue。
|
|
102
103
|
|
|
@@ -104,7 +105,7 @@ dsh plugin --profile web add github:fangchenghao/dsh-autoupdater
|
|
|
104
105
|
|
|
105
106
|
- 上游项目:[niubi6668889595/dsh-autoupdater](https://github.com/niubi6668889595/dsh-autoupdater)(MIT)。
|
|
106
107
|
- 本分支新增:桌面版 CLI 换版、npmmirror 优先、跳过 `link:`/git 来源、只有真正升级成功才算“已应用”、Windows 空闲判定/.cmd 调用适配;完整差异见 git log。
|
|
107
|
-
- 发布渠道:npm `@fffangchenghao/dsh-autoupdater`,GitHub `fangchenghao/dsh-autoupdater`,tag `v0.6.
|
|
108
|
+
- 发布渠道:npm `@fffangchenghao/dsh-autoupdater`,GitHub `fangchenghao/dsh-autoupdater`,tag `v0.6.3`。
|
|
108
109
|
- 与上游同步:把上游加为 remote,rebase/merge 到本分支后重新发版即可。
|
|
109
110
|
|
|
110
111
|
## 安全模型
|
package/main.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFile, writeFile, mkdir, appendFile } from 'node:fs/promises';
|
|
2
2
|
import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';
|
|
3
3
|
import { execFileSync, spawn } from 'node:child_process';
|
|
4
|
-
import { basename, delimiter, dirname, join } from 'node:path';
|
|
4
|
+
import { basename, delimiter, dirname, join, resolve } from 'node:path';
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
|
|
7
7
|
/** 本插件的真实包名(上游名或发布用的 scoped 名),用于把自己排除在自动更新之外。 */
|
|
@@ -140,6 +140,20 @@ async function readJson(path) {
|
|
|
140
140
|
try { return JSON.parse(await readFile(path, 'utf8')); } catch { return null; }
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
/**
|
|
144
|
+
* 与 @deepseek-ai/dsh-home-paths 的 resolveDshHome 对齐:
|
|
145
|
+
* $DSH_HOME 优先(支持 ~ / ~\ 前缀,空/全空白视为未设置),否则 ~/.dsh。
|
|
146
|
+
* 这样 Windows 上没有 HOME、只设置 DSH_HOME 或 USERPROFILE 时都能落到同一目录。
|
|
147
|
+
*/
|
|
148
|
+
function resolveDshHome(env = process.env) {
|
|
149
|
+
const raw = typeof env.DSH_HOME === 'string' ? env.DSH_HOME : '';
|
|
150
|
+
if (raw.trim().length === 0) return join(homedir(), '.dsh');
|
|
151
|
+
let expanded = raw;
|
|
152
|
+
if (raw === '~') expanded = homedir();
|
|
153
|
+
else if (raw.startsWith('~/') || raw.startsWith('~\\')) expanded = join(homedir(), raw.slice(2));
|
|
154
|
+
return resolve(expanded);
|
|
155
|
+
}
|
|
156
|
+
|
|
143
157
|
/**
|
|
144
158
|
* 递归找出目录里最新的文件 mtime(毫秒)。
|
|
145
159
|
* 目录不存在 → 0(没有会话 = 空闲);根目录读不了 → 抛错(调用方保守当忙)。
|
|
@@ -244,7 +258,7 @@ export const inject = ['agents', 'pluginManager', 'webServer'];
|
|
|
244
258
|
|
|
245
259
|
export function apply(ctx, rawConfig = {}) {
|
|
246
260
|
// Windows 上通常没有 HOME,只有 USERPROFILE;homedir() 会选对。
|
|
247
|
-
const home =
|
|
261
|
+
const home = resolveDshHome();
|
|
248
262
|
const stateDir = join(home, 'autoupdater');
|
|
249
263
|
const statePath = join(stateDir, 'status.json');
|
|
250
264
|
const historyPath = join(stateDir, 'history.jsonl');
|
|
@@ -262,28 +276,38 @@ export function apply(ctx, rawConfig = {}) {
|
|
|
262
276
|
if (hot) config = normalizeConfig({ ...rawConfig, ...hot });
|
|
263
277
|
}
|
|
264
278
|
|
|
279
|
+
/** 是否运行在 Electron 桌面 App 的进程里(macOS/Windows 安装包)。 */
|
|
280
|
+
const isDesktopApp = () => typeof process.versions?.electron === 'string';
|
|
281
|
+
|
|
265
282
|
// ── profile 目录探测(磁盘版本回读用)──
|
|
266
|
-
// DSH_PROFILE_DIR
|
|
267
|
-
//
|
|
283
|
+
// 优先级与 DSH 自身一致:DSH_PROFILE_DIR → DSH_PROFILE → 扫描 profiles。
|
|
284
|
+
// 桌面版在 DSH_PROFILE 缺失时默认 desktop,避免多 profile 时误选最近修改的测试 profile。
|
|
268
285
|
let profileDir = process.env.DSH_PROFILE_DIR || null;
|
|
286
|
+
if (profileDir && !existsSync(profileDir)) profileDir = null;
|
|
287
|
+
if (!profileDir) {
|
|
288
|
+
const configuredProfile = process.env.DSH_PROFILE || (isDesktopApp() ? 'desktop' : '');
|
|
289
|
+
if (configuredProfile) {
|
|
290
|
+
const candidate = join(home, 'profiles', configuredProfile);
|
|
291
|
+
if (existsSync(candidate)) profileDir = candidate;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
269
294
|
try {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
295
|
+
if (!profileDir) {
|
|
296
|
+
const base = join(home, 'profiles');
|
|
297
|
+
const candidates = readdirSync(base)
|
|
298
|
+
.map((name) => join(base, name))
|
|
299
|
+
.filter((dir) => existsSync(join(dir, 'node_modules')));
|
|
300
|
+
if (candidates.length === 1) {
|
|
301
|
+
profileDir = candidates[0];
|
|
302
|
+
} else if (candidates.length > 1) {
|
|
303
|
+
profileDir = candidates
|
|
304
|
+
.map((dir) => ({ dir, m: statSync(join(dir, 'node_modules')).mtimeMs }))
|
|
305
|
+
.sort((a, b) => b.m - a.m)[0].dir;
|
|
306
|
+
}
|
|
280
307
|
}
|
|
281
308
|
if (profileDir && config.verbose) log('profileDir detected:', profileDir);
|
|
282
309
|
} catch {}
|
|
283
310
|
|
|
284
|
-
/** 是否运行在 Electron 桌面 App 的进程里(macOS/Windows 安装包)。 */
|
|
285
|
-
const isDesktopApp = () => typeof process.versions?.electron === 'string';
|
|
286
|
-
|
|
287
311
|
/**
|
|
288
312
|
* 找一条能真正写 profile 的 `dsh plugin` 入口。
|
|
289
313
|
*
|
|
@@ -476,7 +500,7 @@ export function apply(ctx, rawConfig = {}) {
|
|
|
476
500
|
async function runPluginCliAdd(pkg, version) {
|
|
477
501
|
const cli = resolvePluginCli();
|
|
478
502
|
if (!cli) {
|
|
479
|
-
const reason =
|
|
503
|
+
const reason = `找不到可用的 dsh CLI(platform=${process.platform}, resourcesPath=${process.resourcesPath ?? 'n/a'}, execPath=${process.execPath})`;
|
|
480
504
|
log('CLI add:', reason);
|
|
481
505
|
return { ok: false, code: -1, output: '', reason };
|
|
482
506
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fffangchenghao/dsh-autoupdater",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Maintained fork of dsh-autoupdater with macOS/Windows desktop fixes. Scheduled update checks for DSH itself and installed plugins, applied only in idle windows.",
|