@whyshu/argent 0.1.11 → 0.1.13

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 CHANGED
@@ -38,7 +38,7 @@ npx -y @whyshu/argent@latest update run --yes
38
38
 
39
39
  # 看计划 / 指定版本 / 国内镜像
40
40
  npx -y @whyshu/argent@latest update run --dry-run
41
- npx -y @whyshu/argent@latest update run --yes --to 0.1.9
41
+ npx -y @whyshu/argent@latest update run --yes --to 0.1.12
42
42
  npx -y @whyshu/argent@latest update check --registry https://registry.npmmirror.com
43
43
  ```
44
44
 
@@ -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. 执行 `setup --force-install` 更新 profile 插件;
51
- 5. 执行 `health --json` 验收;
52
- 6. 返回 `restartRequired: true`,由空闲窗口重启宿主。
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 setupArgs = [...common, 'setup', '--dsh-home', opts.dshHome, '--force-install']
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, commands: [installArgs, setupArgs, healthArgs].map((args) => [npx, ...args].join(' ')) })
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
- runCli(npx, setupArgs, { env })
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 / setup --force-install;必要时用备份恢复 package.json/patch。')
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
@@ -74,8 +74,8 @@ export function pluginDirs({ repo = repoRoot() } = {}) {
74
74
  export const PUBLISHED_BUNDLE_VERSIONS = {
75
75
  '@whyshu/argent-presets': '0.1.1',
76
76
  '@whyshu/argent-core': '0.1.5',
77
- '@whyshu/argent-dsh': '0.1.9',
78
- '@whyshu/argent-skin': '0.1.4',
77
+ '@whyshu/argent-dsh': '0.1.10',
78
+ '@whyshu/argent-skin': '0.1.14',
79
79
  '@whyshu/argent-gateway': '0.2.3',
80
80
  '@whyshu/argent-flow': '0.1.0',
81
81
  '@whyshu/argent-ml': '0.1.0',
@@ -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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whyshu/argent",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Argent 启动器:一条命令启动「打包好的 dsh + Argent 插件/角色预设」,并管理本机 runner 常驻。",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,7 +15,7 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@deepseek-ai/dsh": "0.2.1-rc.2",
18
- "@whyshu/argent-engine": "0.7.6"
18
+ "@whyshu/argent-engine": "0.7.7"
19
19
  },
20
20
  "files": [
21
21
  "bin/",