@whyshu/argent 0.1.11 → 0.1.12
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 +6 -3
- package/bin/argent.mjs +16 -7
- package/lib/index.mjs +38 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,9 +47,12 @@ npx -y @whyshu/argent@latest update check --registry https://registry.npmmirror.
|
|
|
47
47
|
1. 读取 npm `@whyshu/argent` 的 `latest` 版本;
|
|
48
48
|
2. 备份 profile 的 `package.json` / patch / lock;
|
|
49
49
|
3. 用目标版本启动器执行 `runtime install`;
|
|
50
|
-
4.
|
|
51
|
-
5. 执行 `
|
|
52
|
-
6.
|
|
50
|
+
4. **原地更新现有 profile 的插件版本**(不重建 profile、不丢 bundles);
|
|
51
|
+
5. 用客户机**真实 dsh** 执行 `dsh plugin --profile argent install`;
|
|
52
|
+
6. 用真实 dsh 执行 `health --json` 验收;
|
|
53
|
+
7. 返回 `restartRequired: true`,由空闲窗口重启宿主。
|
|
54
|
+
|
|
55
|
+
⛔ dsh 版本不等于启动器 exact pin 时,`update run` 会在改任何文件前停止;先升级宿主。
|
|
53
56
|
|
|
54
57
|
失败不会静默:保留更新前 profile 清单备份,并打印分步重试命令。当前不做自动重启。
|
|
55
58
|
|
package/bin/argent.mjs
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
DSH_EXACT_VERSION, PROFILE_NAME, PROD_BUNDLES, buildLaunchdPlist, buildProfile, dshHomeOf, runnerScriptPath,
|
|
19
19
|
depsInstalled, health, installDeps, loginWithPhone, pairRunner, probeDshVersion, readAuthToken, repoRoot, runnerConfigPath, sendLoginCode, versionMatches,
|
|
20
20
|
engineRoot, materializeRuntime, checkForUpdate, compareVersions, launcherVersion,
|
|
21
|
+
PUBLISHED_BUNDLE_VERSIONS, resolveDshBin, updateProfilePluginVersions,
|
|
21
22
|
} from '../lib/index.mjs';
|
|
22
23
|
|
|
23
24
|
const argv = process.argv.slice(2);
|
|
@@ -42,6 +43,7 @@ const opts = {
|
|
|
42
43
|
target: val('--target', join(homedir(), '.argent-dsh')),
|
|
43
44
|
skillsTarget: has('--no-skills') ? '' : val('--skills-target', join(dshHomeOf(val('--dsh-home')), 'skills')),
|
|
44
45
|
registry: val('--registry', process.env.ARGENT_NPM_REGISTRY || 'https://registry.npmjs.org'),
|
|
46
|
+
dshBin: val('--dsh-bin', resolveDshBin()),
|
|
45
47
|
extraBundles: (() => { const raw = val('--bundles', '').split(',').map((x) => x.trim()).filter(Boolean); return raw.flatMap((x) => (x === 'prod' ? PROD_BUNDLES : [x])); })(),
|
|
46
48
|
};
|
|
47
49
|
|
|
@@ -131,7 +133,7 @@ async function webCommand() {
|
|
|
131
133
|
}
|
|
132
134
|
|
|
133
135
|
async function healthCommand() {
|
|
134
|
-
const h = health({ dshHome: opts.dshHome, profile: opts.profile, repo: opts.repo, port: opts.port });
|
|
136
|
+
const h = health({ dshHome: opts.dshHome, profile: opts.profile, repo: opts.repo, port: opts.port, dshBin: opts.dshBin });
|
|
135
137
|
if (JSON_OUT) console.log(JSON.stringify(h, null, 2));
|
|
136
138
|
else {
|
|
137
139
|
console.log(`dsh: ${h.dsh.ok ? h.dsh.version : '(未找到)'} ${h.dsh.matchesExact ? '✅ exact' : `❌ 期望 ${h.expectedDsh}`}`);
|
|
@@ -250,10 +252,14 @@ async function updateCommand(sub) {
|
|
|
250
252
|
const npx = process.platform === 'win32' ? 'npx.cmd' : 'npx'
|
|
251
253
|
const common = ['--yes', `@whyshu/argent@${targetVersion}`]
|
|
252
254
|
const installArgs = [...common, 'runtime', 'install', '--target', opts.target, '--skills-target', opts.skillsTarget]
|
|
253
|
-
const
|
|
254
|
-
const healthArgs = [...common, 'health', '--dsh-home', opts.dshHome, '--json']
|
|
255
|
+
const healthArgs = [...common, 'health', '--dsh-home', opts.dshHome, '--json', '--dsh-bin', opts.dshBin]
|
|
255
256
|
if (DRY_RUN) {
|
|
256
|
-
print({ ok: true, dryRun: true, current, targetVersion,
|
|
257
|
+
print({ ok: true, dryRun: true, current, targetVersion, dshBin: opts.dshBin, commands: [
|
|
258
|
+
[npx, ...installArgs].join(' '),
|
|
259
|
+
`update profile plugin versions (${Object.keys(PUBLISHED_BUNDLE_VERSIONS).join(', ')})`,
|
|
260
|
+
`${opts.dshBin} plugin --profile ${opts.profile} install # DSH_HOME=${opts.dshHome}`,
|
|
261
|
+
[npx, ...healthArgs].join(' '),
|
|
262
|
+
] })
|
|
257
263
|
return
|
|
258
264
|
}
|
|
259
265
|
if (!has('--yes')) {
|
|
@@ -261,7 +267,7 @@ async function updateCommand(sub) {
|
|
|
261
267
|
process.exit(2)
|
|
262
268
|
}
|
|
263
269
|
// 宿主版本不匹配时绝不能先改 profile(新插件可能要求新 dsh;改完再 health 失败会留下半升级)。
|
|
264
|
-
const dshProbe = probeDshVersion()
|
|
270
|
+
const dshProbe = probeDshVersion({ dshBin: opts.dshBin })
|
|
265
271
|
if (!dshProbe.ok || !versionMatches(dshProbe.version)) {
|
|
266
272
|
console.error(`⛔ 宿主 dsh 版本不匹配:当前 ${dshProbe.ok ? dshProbe.version : '(未找到)'},启动器要求 ${DSH_EXACT_VERSION}。`)
|
|
267
273
|
console.error(' 请先按客户机 dsh 升级流程升级宿主,再重跑 update run;本次未改任何文件。')
|
|
@@ -278,12 +284,15 @@ async function updateCommand(sub) {
|
|
|
278
284
|
const env = { NPM_CONFIG_REGISTRY: opts.registry }
|
|
279
285
|
try {
|
|
280
286
|
runCli(npx, installArgs, { env })
|
|
281
|
-
|
|
287
|
+
// 不调用 setup:setup 会重建 profile,可能丢掉客户现有 bundles/依赖结构(2026-10-22 实测)。
|
|
288
|
+
const prof = updateProfilePluginVersions({ dshHome: opts.dshHome, profile: opts.profile, versions: PUBLISHED_BUNDLE_VERSIONS })
|
|
289
|
+
if (!prof.ok) throw new Error(`更新 profile 插件版本失败:${prof.message}`)
|
|
290
|
+
runCli(opts.dshBin, ['plugin', '--profile', opts.profile, 'install'], { env: { ...env, DSH_HOME: opts.dshHome }, cwd: opts.dshHome })
|
|
282
291
|
runCli(npx, healthArgs, { env })
|
|
283
292
|
} catch (e) {
|
|
284
293
|
console.error(`❌ 更新失败:${e.message}`)
|
|
285
294
|
console.error(` 已保留更新前 profile 清单备份:${backupDir}`)
|
|
286
|
-
console.error(' 可分步重试:npx -y @whyshu/argent@' + targetVersion + ' runtime install
|
|
295
|
+
console.error(' 可分步重试:npx -y @whyshu/argent@' + targetVersion + ' runtime install,再按 dsh plugin install 重试;必要时用备份恢复 package.json/patch。')
|
|
287
296
|
process.exit(2)
|
|
288
297
|
}
|
|
289
298
|
print({ ok: true, from: current, to: targetVersion, runtimeTarget: opts.target, profile: profileDir, backupDir, restartRequired: true, next: '空闲窗口重启 dsh web(service install/launchd 或现有重启脚本)' })
|
package/lib/index.mjs
CHANGED
|
@@ -445,3 +445,41 @@ export async function checkForUpdate({
|
|
|
445
445
|
runtime, runtimeTarget: target,
|
|
446
446
|
}
|
|
447
447
|
}
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
/** 解析客户机**真实的** dsh(npx 启动器的依赖里也带一个 dsh,PATH 会被 npx 改写,不能直接用裸 `dsh`)。 */
|
|
451
|
+
export function resolveDshBin({ env = process.env, home = homedir() } = {}) {
|
|
452
|
+
const explicit = String(env.ARGENT_DSH_BIN || env.DSH_BIN || '').trim()
|
|
453
|
+
if (explicit && existsSync(explicit)) return explicit
|
|
454
|
+
const pathEntries = String(env.PATH || '').split(':').filter(Boolean)
|
|
455
|
+
.filter((p) => !p.includes('_npx') && !p.replace(/\/+$/, '').endsWith('node_modules/.bin'))
|
|
456
|
+
for (const dir of pathEntries) {
|
|
457
|
+
const p = join(dir, process.platform === 'win32' ? 'dsh.cmd' : 'dsh')
|
|
458
|
+
if (existsSync(p)) return p
|
|
459
|
+
}
|
|
460
|
+
for (const p of [
|
|
461
|
+
join(home, '.local', 'node', 'bin', 'dsh'),
|
|
462
|
+
'/opt/homebrew/bin/dsh',
|
|
463
|
+
'/usr/local/bin/dsh',
|
|
464
|
+
]) if (existsSync(p)) return p
|
|
465
|
+
return 'dsh'
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/** 更新 profile 里已存在的插件版本;不重建 profile、不丢 bundles/依赖结构。 */
|
|
469
|
+
export function updateProfilePluginVersions({
|
|
470
|
+
dshHome = dshHomeOf(), profile = PROFILE_NAME, versions = PUBLISHED_BUNDLE_VERSIONS,
|
|
471
|
+
} = {}) {
|
|
472
|
+
const file = join(profileDir(dshHome, profile), 'package.json')
|
|
473
|
+
let pkg = null
|
|
474
|
+
try { pkg = JSON.parse(readFileSync(file, 'utf8')) } catch { return { ok: false, code: 'profile_missing', message: `profile 不存在:${file}` } }
|
|
475
|
+
if (!pkg.dependencies || typeof pkg.dependencies !== 'object') return { ok: false, code: 'profile_shape', message: 'profile package.json 缺 dependencies' }
|
|
476
|
+
const changed = []
|
|
477
|
+
for (const [name, want] of Object.entries(versions || {})) {
|
|
478
|
+
const have = String(pkg.dependencies[name] || '')
|
|
479
|
+
if (!have || have.startsWith('file:') || have === want) continue
|
|
480
|
+
pkg.dependencies[name] = want
|
|
481
|
+
changed.push({ name, from: have, to: want })
|
|
482
|
+
}
|
|
483
|
+
if (changed.length) writeFileSync(file, JSON.stringify(pkg, null, 2) + '\n')
|
|
484
|
+
return { ok: true, file, changed }
|
|
485
|
+
}
|