@whyshu/argent 0.1.3 → 0.1.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/bin/argent.mjs CHANGED
@@ -9,12 +9,12 @@
9
9
  *
10
10
  * 公共参数:--dsh-home <dir> --profile <name> --repo <dir> --json --dry-run
11
11
  */
12
- import { spawn } from 'node:child_process';
13
- import { mkdirSync, writeFileSync, rmSync, existsSync } from 'node:fs';
14
- import { join } from 'node:path';
12
+ import { spawn, spawnSync } from 'node:child_process';
13
+ import { mkdirSync, writeFileSync, rmSync, existsSync, copyFileSync, chmodSync, readFileSync } from 'node:fs';
14
+ import { join, dirname } from 'node:path';
15
15
  import { homedir } from 'node:os';
16
16
  import {
17
- DSH_EXACT_VERSION, PROFILE_NAME, PROD_BUNDLES, buildLaunchdPlist, buildProfile, dshHomeOf,
17
+ DSH_EXACT_VERSION, PROFILE_NAME, PROD_BUNDLES, buildLaunchdPlist, buildProfile, dshHomeOf, runnerScriptPath,
18
18
  depsInstalled, health, installDeps, loginWithPhone, pairRunner, probeDshVersion, readAuthToken, repoRoot, runnerConfigPath, sendLoginCode, versionMatches,
19
19
  } from '../lib/index.mjs';
20
20
 
@@ -45,6 +45,24 @@ function print(obj) {
45
45
  else for (const [k, v] of Object.entries(obj)) console.log(`${k}: ${typeof v === 'object' ? JSON.stringify(v) : v}`);
46
46
  }
47
47
 
48
+ function ensureBundleDeps() {
49
+ const dir = join(opts.dshHome, 'profiles', opts.profile);
50
+ let pkg;
51
+ try { pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')); } catch { return; }
52
+ for (const [name, version] of Object.entries(pkg.dependencies || {})) {
53
+ const depDir = join(dir, 'node_modules', ...name.split('/'));
54
+ if (existsSync(depDir)) continue;
55
+ console.error(`→ 补装缺失 bundle ${name}@${version} …`);
56
+ const r = spawnSync('dsh', ['plugin', '--profile', opts.profile, 'add', `${name}@${version}`], {
57
+ cwd: dir, stdio: 'inherit', env: { ...process.env, DSH_HOME: opts.dshHome },
58
+ });
59
+ if (r.status !== 0) {
60
+ console.error(`❌ 补装失败:${name}(exit ${r.status})`);
61
+ process.exit(2);
62
+ }
63
+ }
64
+ }
65
+
48
66
  function ensureProfile({ install = true } = {}) {
49
67
  const built = buildProfile({ dshHome: opts.dshHome, profile: opts.profile, repo: opts.repo, extraBundles: opts.extraBundles });
50
68
  if (!built.ok) {
@@ -61,6 +79,7 @@ function ensureProfile({ install = true } = {}) {
61
79
  }
62
80
  console.error('✅ profile 依赖装配完成');
63
81
  }
82
+ if (install && !has('--no-install')) ensureBundleDeps();
64
83
  return built;
65
84
  }
66
85
 
@@ -161,7 +180,16 @@ function setupCommand() {
161
180
  }
162
181
 
163
182
  function serviceCommand(sub) {
164
- const plist = buildLaunchdPlist({ dshHome: opts.dshHome, repo: opts.repo });
183
+ const bundled = runnerScriptPath({ repo: opts.repo });
184
+ // 固定 runner 路径:复制进 DSH_HOME,避免 launchd 指向 npx 临时缓存(缓存清理后失效)
185
+ const stableRunner = join(opts.dshHome, 'argent', 'runner', 'argent-runner.mjs');
186
+ const runnerPath = bundled ? stableRunner : '';
187
+ const plist = buildLaunchdPlist({ dshHome: opts.dshHome, repo: opts.repo, runnerPath });
188
+ if (sub === 'install' && bundled && !has('--print-only')) {
189
+ mkdirSync(dirname(stableRunner), { recursive: true });
190
+ copyFileSync(bundled, stableRunner);
191
+ chmodSync(stableRunner, 0o755);
192
+ }
165
193
  const outDir = val('--plist-dir', '');
166
194
  const targetDir = outDir || join(homedir(), 'Library', 'LaunchAgents');
167
195
  const target = join(targetDir, plist.file);
package/lib/index.mjs CHANGED
@@ -112,13 +112,16 @@ export function buildProfile({ dshHome = dshHomeOf(), profile = PROFILE_NAME, re
112
112
  dsh: { profile: { bundles } },
113
113
  };
114
114
  writeFileSync(join(dir, 'package.json'), JSON.stringify(pkg, null, 2) + '\n');
115
- const patch = [
115
+ const patchLines = [
116
116
  '# @whyshu/argent 生成(幂等;手工改动会在此文件重生成时被覆盖)',
117
117
  '- id: agent-preset-registry',
118
118
  ' config:',
119
119
  ` default: ${DEFAULT_PRESET}`,
120
- '',
121
- ].join('\n');
120
+ ];
121
+ if (bundles.includes('@linxin666/dsh-client-ui-task-board')) {
122
+ patchLines.push('- insert:', ' - id: ui-task-board', " name: '@linxin666/dsh-client-ui-task-board'");
123
+ }
124
+ const patch = patchLines.join('\n') + '\n';
122
125
  writeFileSync(join(dir, 'cordis.patch.yml'), patch);
123
126
  // pnpm 配置必须与现有 web profile 同口径:否则 pnpm 会尝试从 registry 自动装 peer(含未发布版本)⇒ 安装失败
124
127
  writeFileSync(join(dir, 'pnpm-workspace.yaml'), 'packages:\n - .\nnodeLinker: hoisted\nautoInstallPeers: false\nallowBuilds:\n protobufjs: true\n');
@@ -190,8 +193,8 @@ export function runnerScriptPath({ repo = repoRoot() } = {}) {
190
193
  }
191
194
 
192
195
  /** P4 runner 的 launchd plist(macOS);Linux 可换 systemd unit(TODO 发布前补) */
193
- export function buildLaunchdPlist({ dshHome = dshHomeOf(), repo = repoRoot(), nodeBin = process.execPath } = {}) {
194
- const script = runnerScriptPath({ repo });
196
+ export function buildLaunchdPlist({ dshHome = dshHomeOf(), repo = repoRoot(), nodeBin = process.execPath, runnerPath = '' } = {}) {
197
+ const script = runnerPath || runnerScriptPath({ repo });
195
198
  const logDir = join(dshHome, 'argent', 'runner', 'logs');
196
199
  return {
197
200
  file: `${RUNNER_LABEL}.plist`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whyshu/argent",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Argent 启动器:一条命令启动「打包好的 dsh + Argent 插件/角色预设」,并管理本机 runner 常驻。",
5
5
  "type": "module",
6
6
  "bin": {