@dsh-enhanced/dsh-rsi-cli 0.1.48

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.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +231 -0
  3. package/bin/dsh-rsi.js +11 -0
  4. package/lib/backup.d.ts +16 -0
  5. package/lib/backup.d.ts.map +1 -0
  6. package/lib/backup.js +27 -0
  7. package/lib/backup.js.map +1 -0
  8. package/lib/diagnose.d.ts +33 -0
  9. package/lib/diagnose.d.ts.map +1 -0
  10. package/lib/diagnose.js +145 -0
  11. package/lib/diagnose.js.map +1 -0
  12. package/lib/index.d.ts +46 -0
  13. package/lib/index.d.ts.map +1 -0
  14. package/lib/index.js +592 -0
  15. package/lib/index.js.map +1 -0
  16. package/lib/install.d.ts +33 -0
  17. package/lib/install.d.ts.map +1 -0
  18. package/lib/install.js +64 -0
  19. package/lib/install.js.map +1 -0
  20. package/lib/paths.d.ts +61 -0
  21. package/lib/paths.d.ts.map +1 -0
  22. package/lib/paths.js +168 -0
  23. package/lib/paths.js.map +1 -0
  24. package/lib/process-guard.d.ts +51 -0
  25. package/lib/process-guard.d.ts.map +1 -0
  26. package/lib/process-guard.js +143 -0
  27. package/lib/process-guard.js.map +1 -0
  28. package/lib/purge.d.ts +58 -0
  29. package/lib/purge.d.ts.map +1 -0
  30. package/lib/purge.js +204 -0
  31. package/lib/purge.js.map +1 -0
  32. package/lib/run.d.ts +27 -0
  33. package/lib/run.d.ts.map +1 -0
  34. package/lib/run.js +53 -0
  35. package/lib/run.js.map +1 -0
  36. package/lib/secrets.d.ts +22 -0
  37. package/lib/secrets.d.ts.map +1 -0
  38. package/lib/secrets.js +107 -0
  39. package/lib/secrets.js.map +1 -0
  40. package/lib/services.d.ts +89 -0
  41. package/lib/services.d.ts.map +1 -0
  42. package/lib/services.js +339 -0
  43. package/lib/services.js.map +1 -0
  44. package/lib/update.d.ts +59 -0
  45. package/lib/update.d.ts.map +1 -0
  46. package/lib/update.js +160 -0
  47. package/lib/update.js.map +1 -0
  48. package/lib/version.d.ts +2 -0
  49. package/lib/version.d.ts.map +1 -0
  50. package/lib/version.js +2 -0
  51. package/lib/version.js.map +1 -0
  52. package/lib/weburl.d.ts +36 -0
  53. package/lib/weburl.d.ts.map +1 -0
  54. package/lib/weburl.js +106 -0
  55. package/lib/weburl.js.map +1 -0
  56. package/package.json +54 -0
@@ -0,0 +1,339 @@
1
+ import { readFile, rm, stat } from 'node:fs/promises';
2
+ import { open } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { defaultRunner } from "./run.js";
5
+ import { launchAgentTargets, listProfiles, profileLogPaths, systemdUnitName, systemdUserDirectory, SYSTEMD_UNIT_PATTERN, } from "./paths.js";
6
+ /** 受管 unit / plist 的内容指纹(lifecycle-profile.mjs rendererUnitPattern 与 launchd.ts createLaunchAgent)。 */
7
+ const MANAGED_UNIT_MARKER = 'DeepSeek Harness profile';
8
+ /** 判定一个 systemd unit 文件确为 dsh-enhanced 安装器渲染的受管 unit(lifecycle-profile.mjs rendererUnitPattern)。 */
9
+ async function isManagedUnitFile(path, profile) {
10
+ let source;
11
+ try {
12
+ source = await readFile(path, 'utf8');
13
+ }
14
+ catch {
15
+ return false;
16
+ }
17
+ return source.includes(MANAGED_UNIT_MARKER)
18
+ && source.includes(`--profile ${profile} `)
19
+ && source.includes('--no-open');
20
+ }
21
+ /**
22
+ * 判定 macOS plist 确为受管 LaunchAgent。
23
+ *
24
+ * launchd.ts 的 createLaunchAgent 不写入任何注释标记,所以判定依据是它实际渲染
25
+ * 的结构:Label 必须是受管前缀加该 profile,且 ProgramArguments 含
26
+ * `--profile <profile>` 与 `--no-open` 两项。这与 stopManagedService 对 systemd
27
+ * unit 的判定同样严格,避免把同名的用户自建 LaunchAgent 当成受管服务操作。
28
+ */
29
+ async function isManagedPlistFile(path, profile) {
30
+ let source;
31
+ try {
32
+ source = await readFile(path, 'utf8');
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ const { label } = launchAgentTargets('', profile);
38
+ return source.includes(`<string>${label}</string>`)
39
+ && source.includes('<string>--profile</string>')
40
+ && source.includes(`<string>${profile}</string>`)
41
+ && source.includes('<string>--no-open</string>');
42
+ }
43
+ /**
44
+ * 停用并注销一个 profile 的受管常驻服务。
45
+ * macOS:launchctl bootout + 删 ~/Library/LaunchAgents/<label>.plist。
46
+ * Linux:systemctl --user disable --now + reset-failed + 删受管 unit(及同名 .d)+ daemon-reload。
47
+ * 服务未注册/已停止不报错;任何非预期文件归属问题 fail-closed 只报告不删除。
48
+ */
49
+ export async function stopManagedService(platform, home, profile, runner, dryRun) {
50
+ const outcome = { profile, actions: [], skipped: [], errors: [] };
51
+ if (platform === 'darwin') {
52
+ const { label, plistPath } = launchAgentTargets(home, profile);
53
+ const target = `gui/${process.getuid?.() ?? process.env.UID}/${label}`;
54
+ outcome.actions.push(`launchctl bootout ${target}(未注册时忽略错误)`);
55
+ outcome.actions.push(`删除 ${plistPath}`);
56
+ if (dryRun)
57
+ return outcome;
58
+ // bootout 对未加载 label 返回非零(No such process),属预期。
59
+ runner('launchctl', ['bootout', target]);
60
+ await rm(plistPath, { force: true });
61
+ return outcome;
62
+ }
63
+ const unit = systemdUnitName(profile);
64
+ if (!SYSTEMD_UNIT_PATTERN.test(unit)) {
65
+ outcome.errors.push(`非法 profile 名,跳过服务注销:${profile}`);
66
+ return outcome;
67
+ }
68
+ const unitDirectory = systemdUserDirectory(home);
69
+ const fragmentPath = join(unitDirectory, unit);
70
+ const dropInPath = join(unitDirectory, `${unit}.d`);
71
+ let managed = false;
72
+ try {
73
+ await readFile(fragmentPath, 'utf8').then(source => {
74
+ managed = source.includes(MANAGED_UNIT_MARKER)
75
+ && source.includes(`--profile ${profile} `)
76
+ && source.includes('--no-open');
77
+ }, () => { managed = false; });
78
+ }
79
+ catch {
80
+ managed = false;
81
+ }
82
+ outcome.actions.push(`systemctl --user disable --now ${unit}(未注册时忽略错误)`);
83
+ outcome.actions.push(`systemctl --user reset-failed ${unit}`);
84
+ if (!managed) {
85
+ // 文件名虽匹配,但内容不是受管 unit(可能不存在或被人手工改写):不删文件。
86
+ const checked = await isManagedUnitFile(fragmentPath, profile);
87
+ if (!checked)
88
+ outcome.skipped.push(`${fragmentPath}(内容非受管 unit 或不存在,保留)`);
89
+ }
90
+ else {
91
+ outcome.actions.push(`删除受管 unit 文件 ${fragmentPath}`);
92
+ }
93
+ if (!dryRun) {
94
+ runner('systemctl', ['--user', 'disable', '--now', unit]);
95
+ runner('systemctl', ['--user', 'reset-failed', unit]);
96
+ if (managed) {
97
+ await rm(fragmentPath, { force: true });
98
+ await rm(dropInPath, { recursive: true, force: true });
99
+ }
100
+ runner('systemctl', ['--user', 'daemon-reload']);
101
+ }
102
+ outcome.actions.push('systemctl --user daemon-reload');
103
+ return outcome;
104
+ }
105
+ const ACTION_LABEL = {
106
+ start: '启动',
107
+ stop: '停止',
108
+ restart: '重启',
109
+ };
110
+ /**
111
+ * 结论措辞:dry-run 只是计划,必须说「将…」,只有真正执行过才说「已…」。
112
+ * 全部结论行都经由此函数,避免某个分支把计划报告成既成事实。
113
+ */
114
+ function actionResult(profile, action, dryRun, suffix = '') {
115
+ return `${profile}:${dryRun ? '将' : '已'}${ACTION_LABEL[action]}${suffix}`;
116
+ }
117
+ /**
118
+ * Return only the exact MainPID owned by an installer-managed Linux user unit.
119
+ * Other processes with the same --profile remain external and must block lifecycle work.
120
+ */
121
+ export async function managedServiceProcessIds(platform, home, profiles, runner = defaultRunner) {
122
+ const pids = [];
123
+ const errors = [];
124
+ if (platform !== 'linux')
125
+ return { pids, errors };
126
+ for (const profile of profiles) {
127
+ const presence = await inspectManagedService(platform, home, profile);
128
+ if (!presence.managed)
129
+ continue;
130
+ const unit = systemdUnitName(profile);
131
+ const result = runner('systemctl', ['--user', 'show', unit, '--property', 'MainPID', '--value']);
132
+ if (result.status !== 0) {
133
+ errors.push(`${profile}:无法读取受管服务 MainPID:${result.stderr.trim() || `systemctl 退出码 ${result.status}`}`);
134
+ continue;
135
+ }
136
+ const pid = Number(result.stdout.trim());
137
+ if (Number.isSafeInteger(pid) && pid > 0)
138
+ pids.push(pid);
139
+ }
140
+ return { pids: [...new Set(pids)], errors };
141
+ }
142
+ /**
143
+ * 检查一个 profile 的受管服务定义是否就绪。
144
+ * 只读文件系统,不执行 systemctl / launchctl。
145
+ */
146
+ export async function inspectManagedService(platform, home, profile) {
147
+ if (platform === 'darwin') {
148
+ const { plistPath } = launchAgentTargets(home, profile);
149
+ const managed = await isManagedPlistFile(plistPath, profile);
150
+ let exists = true;
151
+ try {
152
+ await stat(plistPath);
153
+ }
154
+ catch {
155
+ exists = false;
156
+ }
157
+ return { managed, definitionPath: plistPath, foreign: exists && !managed };
158
+ }
159
+ const unit = systemdUnitName(profile);
160
+ const definitionPath = join(systemdUserDirectory(home), unit);
161
+ const managed = await isManagedUnitFile(definitionPath, profile);
162
+ let exists = true;
163
+ try {
164
+ await stat(definitionPath);
165
+ }
166
+ catch {
167
+ exists = false;
168
+ }
169
+ return { managed, definitionPath, foreign: exists && !managed };
170
+ }
171
+ /**
172
+ * 对一个已注册的受管服务执行 start / stop / restart。
173
+ *
174
+ * 前置条件是服务定义文件已存在且确属受管:这个命令只切换运行状态,不承担安装
175
+ * 职责,未注册时返回可复制的 dsh-rsi install 指引而不是隐式注册一个
176
+ * 服务——隐式注册会绕过安装器的归属、路径与凭据校验。
177
+ *
178
+ * macOS 用 `launchctl kickstart -k`(重启)/ `kickstart`(启动)/ `bootout`(停止);
179
+ * 停止后 plist 仍在,所以随后可以再 start,这与 purge 的 bootout+删文件不同。
180
+ * Linux 直接用 `systemctl --user start|stop|restart`。
181
+ */
182
+ export async function controlManagedService(platform, home, profile, action, runner = defaultRunner, dryRun = false) {
183
+ const outcome = { profile, actions: [], messages: [], errors: [] };
184
+ const label = ACTION_LABEL[action];
185
+ if (platform !== 'darwin' && platform !== 'linux') {
186
+ outcome.errors.push(`${profile}:当前平台 ${platform} 没有受管常驻服务(仅 macOS launchd 与 Linux systemd --user)`);
187
+ return outcome;
188
+ }
189
+ const presence = await inspectManagedService(platform, home, profile);
190
+ if (!presence.managed) {
191
+ outcome.errors.push(presence.foreign
192
+ ? `${profile}:${presence.definitionPath} 存在但不是 dsh-enhanced 受管服务,已拒绝操作(请人工确认该文件归属)`
193
+ : `${profile}:尚未安装常驻服务(${presence.definitionPath} 不存在)。core/web 场景默认只提供按需启动的 Web/direct 能力,这是正常状态;如需 start/restart,请安装常驻场景:\n`
194
+ + ` dsh-rsi install --profile ${profile} --scenario lark\n`
195
+ + `或安装分级自治成长:\n`
196
+ + ` dsh-rsi install --profile ${profile} --scenario supervised\n`
197
+ + '安装完成前无需反复执行 start/restart。');
198
+ return outcome;
199
+ }
200
+ if (platform === 'darwin') {
201
+ const { label: agentLabel, plistPath } = launchAgentTargets(home, profile);
202
+ const domain = `gui/${process.getuid?.() ?? process.env.UID}`;
203
+ const target = `${domain}/${agentLabel}`;
204
+ if (action === 'stop') {
205
+ outcome.actions.push(`launchctl bootout ${target}`);
206
+ if (!dryRun) {
207
+ const result = runner('launchctl', ['bootout', target]);
208
+ // 未加载时 bootout 返回非零(No such process),对 stop 语义等价于已停止。
209
+ if (result.status !== 0 && !/No such process|not find/iu.test(`${result.stderr}${result.stdout}`)) {
210
+ outcome.errors.push(`${profile}:${label}失败:${result.stderr.trim() || `launchctl 退出码 ${result.status}`}`);
211
+ return outcome;
212
+ }
213
+ }
214
+ outcome.messages.push(actionResult(profile, action, dryRun, `(plist 保留在 ${plistPath},可再次 start)`));
215
+ return outcome;
216
+ }
217
+ // start / restart:plist 可能尚未 bootstrap(曾被 stop),先确保已载入再 kickstart。
218
+ outcome.actions.push(`launchctl bootstrap ${domain} ${plistPath}(已载入时忽略错误)`);
219
+ outcome.actions.push(`launchctl kickstart ${action === 'restart' ? '-k ' : ''}${target}`);
220
+ if (!dryRun) {
221
+ runner('launchctl', ['bootstrap', domain, plistPath]);
222
+ const kickstartArgs = action === 'restart' ? ['kickstart', '-k', target] : ['kickstart', target];
223
+ const result = runner('launchctl', kickstartArgs);
224
+ if (result.status !== 0) {
225
+ outcome.errors.push(`${profile}:${label}失败:${result.stderr.trim() || `launchctl 退出码 ${result.status}`}`);
226
+ return outcome;
227
+ }
228
+ }
229
+ outcome.messages.push(actionResult(profile, action, dryRun));
230
+ return outcome;
231
+ }
232
+ const unit = systemdUnitName(profile);
233
+ if (!SYSTEMD_UNIT_PATTERN.test(unit)) {
234
+ outcome.errors.push(`非法 profile 名,拒绝操作:${profile}`);
235
+ return outcome;
236
+ }
237
+ outcome.actions.push(`systemctl --user ${action} ${unit}`);
238
+ if (!dryRun) {
239
+ const result = runner('systemctl', ['--user', action, unit]);
240
+ if (result.status !== 0) {
241
+ outcome.errors.push(`${profile}:${label}失败:${result.stderr.trim() || `systemctl 退出码 ${result.status}`}`);
242
+ return outcome;
243
+ }
244
+ }
245
+ outcome.messages.push(actionResult(profile, action, dryRun));
246
+ return outcome;
247
+ }
248
+ /**
249
+ * 解析运维命令的目标 profile 集合。
250
+ * 显式 --profile 优先;否则取 DSH home 下全部 profile。
251
+ */
252
+ export async function resolveTargetProfiles(dshHome, profile) {
253
+ if (profile !== undefined)
254
+ return [profile];
255
+ return await listProfiles(dshHome);
256
+ }
257
+ /** 读取单个日志文件的末尾 N 行,只读末尾有界字节,避免把大日志整体载入内存。 */
258
+ export async function tailLogFile(path, lines, maxBytes = 1024 * 1024) {
259
+ let metadata;
260
+ try {
261
+ metadata = await stat(path);
262
+ }
263
+ catch {
264
+ return { path, empty: true, lines: [], bytes: 0 };
265
+ }
266
+ if (!metadata.isFile() || metadata.size === 0) {
267
+ return { path, empty: true, lines: [], bytes: metadata.size };
268
+ }
269
+ const length = Math.min(metadata.size, maxBytes);
270
+ const buffer = Buffer.alloc(length);
271
+ const file = await open(path, 'r');
272
+ try {
273
+ await file.read(buffer, 0, length, metadata.size - length);
274
+ }
275
+ finally {
276
+ await file.close();
277
+ }
278
+ const text = buffer.toString('utf8');
279
+ // 从中间截断时首行可能是残行,丢弃它以免呈现半行内容。
280
+ const all = text.split('\n');
281
+ if (length < metadata.size && all.length > 1)
282
+ all.shift();
283
+ const trimmed = all[all.length - 1] === '' ? all.slice(0, -1) : all;
284
+ return {
285
+ path,
286
+ empty: trimmed.length === 0,
287
+ lines: trimmed.slice(-lines),
288
+ bytes: metadata.size,
289
+ };
290
+ }
291
+ /**
292
+ * 读取若干 profile 的受管 stdout/stderr 日志尾部。
293
+ * `errorOnly` 只取 *-host.error.log。
294
+ */
295
+ export async function collectLogs(dshHome, profiles, lines, errorOnly) {
296
+ const collected = [];
297
+ for (const profile of profiles) {
298
+ const paths = profileLogPaths(dshHome, profile);
299
+ const selected = errorOnly ? paths.filter(path => path.endsWith('.error.log')) : paths;
300
+ const tails = [];
301
+ for (const path of selected)
302
+ tails.push(await tailLogFile(path, lines));
303
+ collected.push({ profile, tails });
304
+ }
305
+ return collected;
306
+ }
307
+ export function formatLogs(collected, lines) {
308
+ if (collected.length === 0)
309
+ return '日志:未找到任何 profile。';
310
+ const out = [];
311
+ for (const entry of collected) {
312
+ for (const tail of entry.tails) {
313
+ out.push(`==> ${tail.path}${tail.empty ? '(无内容)' : `(末 ${tail.lines.length} 行 / 共 ${tail.bytes} 字节)`}`);
314
+ for (const line of tail.lines)
315
+ out.push(line);
316
+ out.push('');
317
+ }
318
+ }
319
+ const body = out.join('\n').trimEnd();
320
+ return body.length > 0 ? body : `日志:无内容(已按末 ${lines} 行读取)。`;
321
+ }
322
+ export function formatServiceOutcomes(outcomes, action, dryRun) {
323
+ const lines = [];
324
+ if (dryRun)
325
+ lines.push(`【dry-run】以下是 ${ACTION_LABEL[action]} 将执行的动作,未做任何修改:`);
326
+ for (const outcome of outcomes) {
327
+ if (dryRun)
328
+ for (const item of outcome.actions)
329
+ lines.push(` ${outcome.profile}: ${item}`);
330
+ for (const message of outcome.messages)
331
+ lines.push(message);
332
+ for (const error of outcome.errors)
333
+ lines.push(`! ${error}`);
334
+ }
335
+ if (lines.length === 0)
336
+ lines.push(`${ACTION_LABEL[action]}:没有匹配的 profile。`);
337
+ return lines.join('\n');
338
+ }
339
+ //# sourceMappingURL=services.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services.js","sourceRoot":"","sources":["../src/services.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { type CommandRunner } from './run.ts';
2
+ /** 全局 dsh-rsi 自身的 npm 包名(新名)。 */
3
+ export declare const RSI_CLI_PACKAGE = "@dsh-enhanced/dsh-rsi-cli";
4
+ /**
5
+ * 历史包名。0.1.47 及更早版本以 `@dsh-enhanced/rsi-cli` 发布;该包已发布版本不可删除,
6
+ * 自升级时负责把旧全局安装迁移到新名,避免两个包同时提供 `dsh-rsi` bin 造成冲突。
7
+ */
8
+ export declare const LEGACY_RSI_CLI_PACKAGE = "@dsh-enhanced/rsi-cli";
9
+ /** 从真实 npm 全局包路径反推 prefix;两种包名后缀都识别,源码 checkout/测试环境回退 npm prefix -g。 */
10
+ export declare function prefixFromPackageRoot(packageRoot: string): string | undefined;
11
+ /**
12
+ * 判断当前进程实际由哪一个全局包加载。
13
+ * - `new`:新包 `@dsh-enhanced/dsh-rsi-cli`
14
+ * - `legacy`:旧包 `@dsh-enhanced/rsi-cli`(需要在本次 update 中迁移)
15
+ * - `unknown`:checkout / 临时目录运行(非全局安装),不做包名迁移。
16
+ */
17
+ export declare function runtimePackageKind(packageRoot: string): 'new' | 'legacy' | 'unknown';
18
+ export interface SelfUpdateReport {
19
+ /** 升级前当前进程所属的 dsh-rsi 版本。 */
20
+ fromVersion: string;
21
+ /** 请求的 selector(精确版本或 dist-tag),默认 latest。 */
22
+ selector: string;
23
+ /** npm 全局前缀,便于用户确认装到了哪里。 */
24
+ globalPrefix?: string;
25
+ /** registry 上 selector 解析出的精确版本;无法解析时为 undefined。 */
26
+ resolvedVersion?: string;
27
+ /** 实际安装成功的精确版本;供 update --all 选择同版本安装器 tag。 */
28
+ installedVersion?: string;
29
+ /** 已是目标版本、未执行安装。 */
30
+ alreadyCurrent: boolean;
31
+ /**
32
+ * 本次是否发生了「旧包名 → 新包名」的全局迁移。
33
+ * 旧包 `@dsh-enhanced/rsi-cli` 提供 `dsh-rsi` bin;新包安装成功后才卸载旧包。
34
+ */
35
+ migratedFrom: boolean;
36
+ /** 计划执行/已执行的命令描述。 */
37
+ actions: string[];
38
+ }
39
+ /**
40
+ * 升级全局 dsh-rsi 自身。
41
+ *
42
+ * 只做一件事:把 `@dsh-enhanced/dsh-rsi-cli@<selector>` 安装到全局;
43
+ * 若当前进程仍由旧包 `@dsh-enhanced/rsi-cli` 加载,则在新包安装成功后卸载旧包,
44
+ * 避免两个包同时提供 `dsh-rsi` bin。刻意不在同一次调用里「装完新版再用新代码继续干活」
45
+ * ——当前进程已把旧版代码载入内存,替换包不会改变它,混用两个版本的行为只会带来难以复现的问题。
46
+ * 因此本函数执行完就返回,由用户在下一次调用中使用新版本。
47
+ *
48
+ * 升级插件集合(cohort)不走这里:那属于安装器的 `--operation upgrade`,
49
+ * 由 `update --all` 薄委托过去,本模块不复制任何 cohort 升级逻辑。
50
+ */
51
+ export declare function runSelfUpdate(options: {
52
+ selector?: string;
53
+ dryRun?: boolean;
54
+ runner?: CommandRunner;
55
+ /** 测试注入;生产默认使用当前已加载 npm 包根目录。 */
56
+ packageRoot?: string;
57
+ }): Promise<SelfUpdateReport>;
58
+ export declare function formatSelfUpdateReport(report: SelfUpdateReport, dryRun: boolean): string;
59
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,UAAU,CAAA;AAG5D,iCAAiC;AACjC,eAAO,MAAM,eAAe,8BAA8B,CAAA;AAC1D;;;GAGG;AACH,eAAO,MAAM,sBAAsB,0BAA0B,CAAA;AAe7D,yEAAyE;AACzE,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAM7E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAKpF;AAED,MAAM,WAAW,gBAAgB;IAC/B,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAA;IACnB,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAA;IAChB,4BAA4B;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,oBAAoB;IACpB,cAAc,EAAE,OAAO,CAAA;IACvB;;;OAGG;IACH,YAAY,EAAE,OAAO,CAAA;IACrB,qBAAqB;IACrB,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAoF5B;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAqBxF"}
package/lib/update.js ADDED
@@ -0,0 +1,160 @@
1
+ import { dirname, resolve, sep } from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { PurgeError } from "./purge.js";
4
+ import { defaultRunner } from "./run.js";
5
+ import { version as VERSION } from "./version.js";
6
+ /** 全局 dsh-rsi 自身的 npm 包名(新名)。 */
7
+ export const RSI_CLI_PACKAGE = '@dsh-enhanced/dsh-rsi-cli';
8
+ /**
9
+ * 历史包名。0.1.47 及更早版本以 `@dsh-enhanced/rsi-cli` 发布;该包已发布版本不可删除,
10
+ * 自升级时负责把旧全局安装迁移到新名,避免两个包同时提供 `dsh-rsi` bin 造成冲突。
11
+ */
12
+ export const LEGACY_RSI_CLI_PACKAGE = '@dsh-enhanced/rsi-cli';
13
+ /** 精确版本或 dist-tag:只接受 x.y.z、带预发布后缀的 x.y.z-tag.n,或纯字母 dist-tag。 */
14
+ const SELECTOR_PATTERN = /^(?:\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?|[A-Za-z][A-Za-z0-9-]{0,63})$/u;
15
+ const runtimePackageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
16
+ /**
17
+ * 全局包在两种历史/现行布局下的路径后缀:
18
+ * <prefix>/lib/node_modules/@dsh-enhanced/dsh-rsi-cli (新)
19
+ * <prefix>/lib/node_modules/@dsh-enhanced/rsi-cli (旧,迁移期识别)
20
+ */
21
+ const GLOBAL_PACKAGE_SUFFIXES = [
22
+ `${sep}lib${sep}node_modules${sep}@dsh-enhanced${sep}dsh-rsi-cli`,
23
+ `${sep}lib${sep}node_modules${sep}@dsh-enhanced${sep}rsi-cli`,
24
+ ];
25
+ /** 从真实 npm 全局包路径反推 prefix;两种包名后缀都识别,源码 checkout/测试环境回退 npm prefix -g。 */
26
+ export function prefixFromPackageRoot(packageRoot) {
27
+ const normalized = resolve(packageRoot);
28
+ for (const suffix of GLOBAL_PACKAGE_SUFFIXES) {
29
+ if (normalized.endsWith(suffix))
30
+ return normalized.slice(0, -suffix.length);
31
+ }
32
+ return undefined;
33
+ }
34
+ /**
35
+ * 判断当前进程实际由哪一个全局包加载。
36
+ * - `new`:新包 `@dsh-enhanced/dsh-rsi-cli`
37
+ * - `legacy`:旧包 `@dsh-enhanced/rsi-cli`(需要在本次 update 中迁移)
38
+ * - `unknown`:checkout / 临时目录运行(非全局安装),不做包名迁移。
39
+ */
40
+ export function runtimePackageKind(packageRoot) {
41
+ const normalized = resolve(packageRoot);
42
+ if (normalized.endsWith(GLOBAL_PACKAGE_SUFFIXES[0]))
43
+ return 'new';
44
+ if (normalized.endsWith(GLOBAL_PACKAGE_SUFFIXES[1]))
45
+ return 'legacy';
46
+ return 'unknown';
47
+ }
48
+ /**
49
+ * 升级全局 dsh-rsi 自身。
50
+ *
51
+ * 只做一件事:把 `@dsh-enhanced/dsh-rsi-cli@<selector>` 安装到全局;
52
+ * 若当前进程仍由旧包 `@dsh-enhanced/rsi-cli` 加载,则在新包安装成功后卸载旧包,
53
+ * 避免两个包同时提供 `dsh-rsi` bin。刻意不在同一次调用里「装完新版再用新代码继续干活」
54
+ * ——当前进程已把旧版代码载入内存,替换包不会改变它,混用两个版本的行为只会带来难以复现的问题。
55
+ * 因此本函数执行完就返回,由用户在下一次调用中使用新版本。
56
+ *
57
+ * 升级插件集合(cohort)不走这里:那属于安装器的 `--operation upgrade`,
58
+ * 由 `update --all` 薄委托过去,本模块不复制任何 cohort 升级逻辑。
59
+ */
60
+ export async function runSelfUpdate(options) {
61
+ const runner = options.runner ?? defaultRunner;
62
+ const selector = options.selector ?? 'latest';
63
+ if (!SELECTOR_PATTERN.test(selector)) {
64
+ throw new PurgeError(`非法的版本 selector:${selector}(应为精确版本 x.y.z 或 dist-tag)`);
65
+ }
66
+ const packageRoot = options.packageRoot ?? runtimePackageRoot;
67
+ const report = {
68
+ fromVersion: VERSION,
69
+ selector,
70
+ alreadyCurrent: false,
71
+ migratedFrom: false,
72
+ actions: [],
73
+ };
74
+ const ownedPrefix = prefixFromPackageRoot(packageRoot);
75
+ if (ownedPrefix !== undefined) {
76
+ report.globalPrefix = ownedPrefix;
77
+ }
78
+ else {
79
+ const prefix = runner('npm', ['prefix', '-g']);
80
+ const prefixValue = prefix.stdout.trim();
81
+ if (prefixValue.length > 0)
82
+ report.globalPrefix = prefixValue;
83
+ }
84
+ // 先把 selector 解析成精确版本,这样「已是最新」可以直接跳过安装,
85
+ // 而且用户能在 dry-run 下看到将要装的确切版本而不只是一个 tag。
86
+ // 永远查询新包名:旧包 registry 上已停更,迁移必须落到新包。
87
+ const view = runner('npm', ['view', `${RSI_CLI_PACKAGE}@${selector}`, 'version', '--location=global']);
88
+ if (view.status === 0) {
89
+ // npm view 对 dist-tag 返回单行版本;对范围可能返回多行,取最后一行(最高版本)。
90
+ const lines = view.stdout.trim().split('\n').map(line => line.trim()).filter(line => line.length > 0);
91
+ const last = lines.at(-1);
92
+ if (last !== undefined) {
93
+ // 多版本行形如 `@dsh-enhanced/dsh-rsi-cli@0.1.47 '0.1.47'`,取末尾引号内的值。
94
+ const matched = /(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)'?$/u.exec(last);
95
+ const captured = matched?.[1];
96
+ if (captured !== undefined)
97
+ report.resolvedVersion = captured;
98
+ }
99
+ }
100
+ const kind = runtimePackageKind(packageRoot);
101
+ report.migratedFrom = kind === 'legacy';
102
+ // 「已是最新」只在当前已是新包时成立;旧包即使版本号相同也必须迁移一次。
103
+ if (report.resolvedVersion !== undefined && report.resolvedVersion === VERSION && kind === 'new') {
104
+ report.alreadyCurrent = true;
105
+ report.installedVersion = report.resolvedVersion;
106
+ return report;
107
+ }
108
+ const target = `${RSI_CLI_PACKAGE}@${selector}`;
109
+ const prefixArgs = report.globalPrefix === undefined ? [] : ['--prefix', report.globalPrefix];
110
+ report.actions.push(`npm install --global${report.globalPrefix === undefined ? '' : ` --prefix ${report.globalPrefix}`} ${target}`);
111
+ if (report.migratedFrom) {
112
+ report.actions.push(`npm uninstall --global${report.globalPrefix === undefined ? '' : ` --prefix ${report.globalPrefix}`} ${LEGACY_RSI_CLI_PACKAGE}`);
113
+ }
114
+ if (options.dryRun === true)
115
+ return report;
116
+ const install = runner('npm', ['install', '--global', ...prefixArgs, target, '--location=global']);
117
+ if (install.status !== 0) {
118
+ const detail = install.stderr.trim() || install.stdout.trim() || `npm 退出码 ${install.status}`;
119
+ throw new PurgeError(`升级 dsh-rsi 失败(前缀 ${report.globalPrefix ?? '未知'}):${detail}\n`
120
+ + `可手工执行:npm install --global ${target}`);
121
+ }
122
+ if (report.resolvedVersion !== undefined)
123
+ report.installedVersion = report.resolvedVersion;
124
+ // 新包安装成功后才卸载旧包;新包失败时上面已经抛出,旧包保持原样,bin 不冲突。
125
+ if (report.migratedFrom) {
126
+ const uninstall = runner('npm', ['uninstall', '--global', ...prefixArgs, LEGACY_RSI_CLI_PACKAGE, '--location=global']);
127
+ if (uninstall.status !== 0) {
128
+ const detail = uninstall.stderr.trim() || uninstall.stdout.trim() || `npm 退出码 ${uninstall.status}`;
129
+ throw new PurgeError(`dsh-rsi 已升级到新包名 ${RSI_CLI_PACKAGE},但卸载旧包 ${LEGACY_RSI_CLI_PACKAGE} 失败:${detail}\n`
130
+ + `新包已可用;可手工执行:npm uninstall --global ${LEGACY_RSI_CLI_PACKAGE}`);
131
+ }
132
+ }
133
+ return report;
134
+ }
135
+ export function formatSelfUpdateReport(report, dryRun) {
136
+ const lines = [];
137
+ const resolved = report.resolvedVersion ?? '(无法从 registry 解析,仍按 selector 安装)';
138
+ if (report.alreadyCurrent) {
139
+ lines.push(`dsh-rsi 已是 ${report.fromVersion},与 ${report.selector} 解析结果一致,无需升级。`);
140
+ if (report.globalPrefix !== undefined)
141
+ lines.push(`全局前缀:${report.globalPrefix}`);
142
+ return lines.join('\n');
143
+ }
144
+ lines.push(dryRun
145
+ ? `【dry-run】将升级 dsh-rsi:${report.fromVersion} → ${resolved}(selector ${report.selector})`
146
+ : `dsh-rsi 已升级:${report.fromVersion} → ${resolved}(selector ${report.selector})`);
147
+ if (report.globalPrefix !== undefined)
148
+ lines.push(`全局前缀:${report.globalPrefix}`);
149
+ if (report.migratedFrom) {
150
+ lines.push(`包名迁移:${LEGACY_RSI_CLI_PACKAGE} → ${RSI_CLI_PACKAGE}(bin 仍为 dsh-rsi;新包安装成功后才卸载旧包)`);
151
+ }
152
+ for (const action of report.actions)
153
+ lines.push(` ${dryRun ? '将执行' : '已执行'}:${action}`);
154
+ if (!dryRun) {
155
+ // 当前进程仍在运行旧版代码,必须明确告知,避免用户以为本次输出已来自新版。
156
+ lines.push('新版本在下一次执行 dsh-rsi 时生效(当前进程仍运行升级前的代码)。');
157
+ }
158
+ return lines.join('\n');
159
+ }
160
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const version = "0.1.48";
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,WAAW,CAAA"}
package/lib/version.js ADDED
@@ -0,0 +1,2 @@
1
+ export const version = '0.1.48';
2
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAA"}
@@ -0,0 +1,36 @@
1
+ import type { CommandRunner } from './run.ts';
2
+ /**
3
+ * Web URL:从运行中受管服务的 journal / host 日志中解析最新一次 `dsh web:` 行,
4
+ * 返回带 token 的完整授权 URL。绝不关闭或绕过 Web 认证——这里只是把 DSH 已经打印
5
+ * 在日志里的同一行 URL 取出来,免去用户翻 journal / 猜 token。
6
+ */
7
+ /**
8
+ * 从一段文本中提取最新一次 `dsh web: http://host:PORT/?token=...` 完整 URL。
9
+ * DSH 每次启动都会打印这一行;取最后一个匹配是为了拿到最近一次重启后的 token
10
+ * (token 随重启变化)。没有匹配时返回 undefined。
11
+ *
12
+ * 纯函数、不读文件、不执行命令,便于单元测试覆盖正常 / 缺 token / 多行场景。
13
+ */
14
+ export declare function extractWebUrlFromText(text: string): string | undefined;
15
+ export interface ProfileWebUrl {
16
+ profile: string;
17
+ /** 解析到的最新完整授权 URL(含 token);未找到时 undefined。 */
18
+ url?: string;
19
+ /** 来源描述:journal / host log 路径。 */
20
+ source?: string;
21
+ /** 服务未注册 / 未运行 / 日志中尚无 URL 等面向用户的提示(非错误)。 */
22
+ notice?: string;
23
+ errors: string[];
24
+ }
25
+ /**
26
+ * 解析一个 profile 受管服务当前有效的 Web 授权 URL。
27
+ *
28
+ * - Linux systemd --user:`journalctl --user -u dsh-profile-<profile>.service --output=cat -n N`
29
+ * - macOS launchd:读 `$DSH_HOME/logs/<profile>-host.log` 尾部
30
+ *
31
+ * 服务未注册时给出与 start/stop 一致的指引;服务未运行时明确提示先 start。
32
+ * 即使服务当前未运行,只要日志里还有历史 URL,也会返回并标注其可能已随重启失效。
33
+ */
34
+ export declare function resolveManagedWebUrl(platform: NodeJS.Platform, home: string, dshHome: string, profile: string, runner?: CommandRunner): Promise<ProfileWebUrl>;
35
+ export declare function formatWebUrlResult(entries: readonly ProfileWebUrl[]): string;
36
+ //# sourceMappingURL=weburl.d.ts.map