@wang121ye/skillmanager 0.0.6 → 0.0.8

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
@@ -230,15 +230,15 @@ skillmanager source remove superpowers
230
230
 
231
231
  ### 默认更新(推荐)
232
232
 
233
- 这会调用 `openskills update` 更新所有 openskills 已记录的来源,然后重新 `sync`:
233
+ 默认会优先按 profile 选择集更新(显式 `--profile` 优先,否则使用默认 profile):
234
234
 
235
235
  ```bash
236
236
  skillmanager update
237
237
  ```
238
238
 
239
- ### 如果你用了 profile 做"子集安装"(Web UI 勾选)
239
+ 如果目标 profile 不存在或没有有效选择集,会自动回退到 `openskills update`。
240
240
 
241
- 因为子集安装是按"本地目录复制安装"(为了兼容 Windows 下 openskills 的本地路径识别问题),`openskills update` 不一定能自动追踪来源;此时用 profile 方式更新最稳:
241
+ ### 指定 profile 更新(子集安装最稳)
242
242
 
243
243
  ```bash
244
244
  skillmanager update --profile laptop
@@ -251,6 +251,12 @@ skillmanager webui --profile laptop
251
251
  skillmanager update --profile laptop
252
252
  ```
253
253
 
254
+ ### 强制使用 openskills 原生更新链路
255
+
256
+ ```bash
257
+ skillmanager update --openskills
258
+ ```
259
+
254
260
  ## 卸载 skills
255
261
 
256
262
  ### 用 Web UI 勾选要卸载的已安装 skills(推荐)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wang121ye/skillmanager",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "Cross-platform agent skill manager (bootstrap + optional Web UI selection) built on top of openskills.",
5
5
  "keywords": [
6
6
  "skillmanager",
package/src/cli.js CHANGED
@@ -26,7 +26,7 @@ async function main() {
26
26
  .option('--global', '安装到全局(默认:当前项目)', false)
27
27
  .option('--universal', '使用通用目录 .agent/skills(默认:.claude/skills)', false)
28
28
  .option('--output <path>', 'sync 输出文件(默认:AGENTS.md)')
29
- .option('--no-sync', '跳过 openskills sync', false)
29
+ .option('--no-sync', '跳过 openskills sync')
30
30
  .option('--dry-run', '仅打印将执行的内容,不实际安装', false)
31
31
  .option('--concurrency <n>', '选择模式下的并发扫描数(默认:3)', '3')
32
32
  .option('--profile <name>', '选择配置名(默认:来自 config 或 SKILLMANAGER_PROFILE 环境变量)')
@@ -43,7 +43,7 @@ async function main() {
43
43
  .option('--global', '作用:把目标切到全局目录(~/.claude/skills 或 ~/.agent/skills)', false)
44
44
  .option('--universal', '作用:使用 .agent/skills(通用 AGENTS.md 场景;默认是 .claude/skills)', false)
45
45
  .option('--output <path>', '作用:sync 输出文件路径(默认:AGENTS.md)')
46
- .option('--no-sync', '作用:不执行 openskills sync(仅安装/卸载,不更新 AGENTS.md)', false)
46
+ .option('--no-sync', '作用:不执行 openskills sync(仅安装/卸载,不更新 AGENTS.md)')
47
47
  .option('--concurrency <n>', '作用:install 模式下并发拉取/扫描来源仓库,提高速度(默认:3)', '3')
48
48
  .option('--force-refresh', '强制刷新来源仓库缓存(重新拉取)', false)
49
49
  .action(async (opts) => {
@@ -59,12 +59,13 @@ async function main() {
59
59
 
60
60
  program
61
61
  .command('update')
62
- .description('更新 skills,并同步生成/更新 AGENTS.md')
62
+ .description('更新 skills,并同步生成/更新 AGENTS.md(默认按 profile 更新)。')
63
63
  .option('--global', '安装到全局(默认:当前项目)', false)
64
64
  .option('--universal', '使用通用目录 .agent/skills(默认:.claude/skills)', false)
65
65
  .option('--output <path>', 'sync 输出文件(默认:AGENTS.md)')
66
- .option('--no-sync', '跳过 openskills sync', false)
66
+ .option('--no-sync', '跳过 openskills sync')
67
67
  .option('--profile <name>', '按 profile 选择集更新(会重新安装选中的 skills)')
68
+ .option('--openskills', '强制走 openskills update(忽略 profile 选择集)', false)
68
69
  .option('--concurrency <n>', '选择模式下的并发扫描数(默认:3)', '3')
69
70
  .option('--force-refresh', '强制刷新来源仓库缓存(重新拉取)', false)
70
71
  .action(async (opts) => {
@@ -79,7 +80,7 @@ async function main() {
79
80
  .option('--universal', '使用通用目录 .agent/skills(默认:.claude/skills)', false)
80
81
  .option('--all', '卸载目标目录下所有已安装 skills', false)
81
82
  .option('--output <path>', 'sync 输出文件(默认:AGENTS.md)')
82
- .option('--no-sync', '跳过 openskills sync', false)
83
+ .option('--no-sync', '跳过 openskills sync')
83
84
  .action(async (skillNames, opts) => {
84
85
  await uninstall(opts, skillNames);
85
86
  });
@@ -179,4 +180,3 @@ main().catch((err) => {
179
180
  console.error(err?.stack || String(err));
180
181
  process.exitCode = 1;
181
182
  });
182
-
@@ -17,31 +17,46 @@ function uniq(arr) {
17
17
  return Array.from(new Set(arr));
18
18
  }
19
19
 
20
+ async function runFallbackOpenSkillsUpdate(opts) {
21
+ // eslint-disable-next-line no-console
22
+ console.log('正在执行 openskills update(更新所有已记录来源)…');
23
+ await runOpenSkills(['update']);
24
+ if (opts?.sync !== false) {
25
+ await syncAgents({ output: opts?.output, cwd: process.cwd() });
26
+ }
27
+ // eslint-disable-next-line no-console
28
+ console.log('\n完成。');
29
+ }
30
+
20
31
  async function update(opts) {
21
32
  await warnPrereqs({ needGit: true, needOpenSkills: true });
22
33
  const globalInstall = !!opts?.global;
23
34
  const universal = !!opts?.universal;
24
35
 
25
- const profileName = opts?.profile;
26
- const wantsSelection = !!profileName;
36
+ if (opts?.openskills) {
37
+ await runFallbackOpenSkillsUpdate(opts);
38
+ return;
39
+ }
27
40
 
28
- if (!wantsSelection) {
29
- // Default: ask openskills to update everything it has tracked.
30
- // eslint-disable-next-line no-console
31
- console.log('正在执行 openskills update(更新所有已记录来源)…');
32
- await runOpenSkills(['update']);
33
- if (opts?.sync !== false) {
34
- await syncAgents({ output: opts?.output, cwd: process.cwd() });
35
- }
41
+ // Default path: profile-based update (explicit profile > default profile).
42
+ const paths = getAppPaths();
43
+ await ensureDir(paths.profilesDir);
44
+ const effectiveProfileName = opts?.profile || (await getEffectiveDefaultProfile());
45
+ const existing = await loadProfile({ profilesDir: paths.profilesDir, profileName: effectiveProfileName });
46
+ const hasSelection = Array.isArray(existing?.selectedSkillIds);
47
+
48
+ if (!hasSelection) {
36
49
  // eslint-disable-next-line no-console
37
- console.log('\n完成。');
50
+ console.warn(
51
+ `未找到可用 profile 选择集:${effectiveProfileName},将回退到 openskills update。` +
52
+ `可先运行 skillmanager webui --profile ${effectiveProfileName} 保存选择集。`
53
+ );
54
+ await runFallbackOpenSkillsUpdate(opts);
38
55
  return;
39
56
  }
40
57
 
41
58
  // Profile-based update: refresh repos cache and re-install selected skill dirs.
42
- const paths = getAppPaths();
43
59
  await ensureDir(paths.reposDir);
44
- await ensureDir(paths.profilesDir);
45
60
 
46
61
  const { sources } = await loadSourcesManifest();
47
62
  const enabledSources = sources.filter((s) => s && s.enabled !== false);
@@ -73,21 +88,16 @@ async function update(opts) {
73
88
  for (const sk of skills) skillsById.set(sk.id, sk);
74
89
  }
75
90
 
76
- const allSkills = Array.from(skillsById.values());
77
-
78
- const effectiveProfileName = profileName || (await getEffectiveDefaultProfile());
79
- const existing = await loadProfile({ profilesDir: paths.profilesDir, profileName: effectiveProfileName });
80
- let selectedIds =
81
- existing?.selectedSkillIds && Array.isArray(existing.selectedSkillIds)
82
- ? existing.selectedSkillIds
83
- : allSkills.map((s) => s.id);
91
+ let selectedIds = existing.selectedSkillIds;
84
92
 
85
93
  // 交互式选择已迁移到:skillmanager webui(mode=install),先保存 profile 再 update --profile
86
94
 
87
95
  selectedIds = uniq(selectedIds).filter((id) => skillsById.has(id));
88
96
 
89
97
  // eslint-disable-next-line no-console
90
- console.log(`将更新/重装 ${selectedIds.length} 个 skills(global=${globalInstall}, universal=${universal})…`);
98
+ console.log(
99
+ `将按 profile=${effectiveProfileName} 更新/重装 ${selectedIds.length} 个 skills(global=${globalInstall}, universal=${universal})…`
100
+ );
91
101
 
92
102
  for (const id of selectedIds) {
93
103
  const skill = skillsById.get(id);
@@ -109,4 +119,3 @@ async function update(opts) {
109
119
  }
110
120
 
111
121
  module.exports = { update };
112
-