@lyra-ai/toolkit 0.2.7 → 0.2.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/QUICKSTART.md CHANGED
@@ -131,9 +131,6 @@ skillhub install code-review --agent claude-code --agent cursor
131
131
  # 查看已安装
132
132
  skillhub list --json
133
133
 
134
- # 诊断问题
135
- skillhub doctor
136
-
137
134
  # 移除
138
135
  skillhub remove code-review --scope user
139
136
  ```
@@ -147,14 +144,13 @@ skillhub publish ./my-skill
147
144
  ## skillhub 工作流
148
145
 
149
146
  ```
150
- login(认证) → search(发现) → install(安装) → list/doctor(管理)
147
+ login(认证) → search(发现) → install(安装) → list(管理)
151
148
  ```
152
149
 
153
150
  - **`login`** 存储 registry token
154
151
  - **`search`** 在 registry 搜索技能包
155
152
  - **`install`** 下载并安装到指定 scope
156
153
  - **`list`** 列出本地已安装技能包
157
- - **`doctor`** 诊断安装问题(缺失文件、冲突等)
158
154
 
159
155
  ## skillhub Agent 集成要点
160
156
 
@@ -168,7 +164,7 @@ login(认证) → search(发现) → install(安装) → list/doctor
168
164
  skillhub login --token "$SKILLHUB_TOKEN"
169
165
  skillhub search code-review --json --limit 5
170
166
  skillhub install code-review --scope project --agent claude-code
171
- skillhub doctor --json
167
+ skillhub list --json
172
168
  ```
173
169
 
174
170
  ## skillhub 配置参考
package/README.md CHANGED
@@ -106,7 +106,6 @@ cd <本目录> && npm link
106
106
 
107
107
  AI 技能包管理器:搜索、安装、发布、管理 AI coding agent 技能包。
108
108
 
109
- - `skillhub version [--json]` → 输出版本号
110
109
  - `skillhub help [topic]` → 帮助信息(`topic` 为命令名)
111
110
  - `skillhub login --token <token> [--registry <url>]` → 登录 registry
112
111
  - `skillhub logout` → 清除本地凭证
@@ -115,7 +114,6 @@ AI 技能包管理器:搜索、安装、发布、管理 AI coding agent 技能
115
114
  - `skillhub install <slug> [--namespace <ns>] [--agent <profile>] [--scope user|project] [--max-file-size <size>] [--json]` → 安装技能包
116
115
  - `skillhub list [--scope user|project] [--json]` → 列出已安装技能包
117
116
  - `skillhub remove <slug> [--scope user|project] [--agent <profile>] [--json]` → 移除技能包
118
- - `skillhub doctor [--fix] [--json]` → 诊断技能包安装状态
119
117
  - `skillhub publish <path> [--json]` → 发布技能包到 registry
120
118
 
121
119
  ### Agent profiles(`--agent`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyra-ai/toolkit",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "面向 AI agent 的零依赖开发工具集",
5
5
  "type": "module",
6
6
  "bin": {
package/src/skillhub.mjs CHANGED
@@ -3385,8 +3385,6 @@ async function promptMultiselect(message, choices) {
3385
3385
  // === Version Info ===
3386
3386
  // ==================================================================
3387
3387
 
3388
- const PKG_VERSION = "0.1.8";
3389
-
3390
3388
  // ==================================================================
3391
3389
  // === Source: shared/errors ===
3392
3390
  // ==================================================================
@@ -3405,7 +3403,6 @@ class CliError extends Error {
3405
3403
  // ==================================================================
3406
3404
 
3407
3405
  const DEFAULT_REGISTRY = '';
3408
- const CLI_VERSION = PKG_VERSION;
3409
3406
  const EXIT = {
3410
3407
  generic: 1,
3411
3408
  auth: 2,
@@ -4264,6 +4261,8 @@ async function installSkill(options) {
4264
4261
  try {
4265
4262
  await rename2(tempDir, skillDir);
4266
4263
  } catch (error) {
4264
+ console.error("安装失败!请检查是否有执行中的" + target.agent);
4265
+ console.error(error);
4267
4266
  if (!options.force && await pathExists(skillDir)) {
4268
4267
  throw new CliError(`skill already installed at ${skillDir}`, EXIT.filesystem, {
4269
4268
  path: skillDir,
@@ -4330,8 +4329,7 @@ async function removeLocalSkill(options) {
4330
4329
  for (const { item, target } of targetsToRemove) {
4331
4330
  if (!target.rootDir || !isPathUnder(target.installDir, target.rootDir)) {
4332
4331
  throw new CliError(`unsafe remove path: ${target.installDir} is not under ${target.rootDir ?? 'unknown root'}`, EXIT.filesystem, {
4333
- path: target.installDir,
4334
- next: 'verify inventory integrity with `skillhub doctor`'
4332
+ path: target.installDir
4335
4333
  });
4336
4334
  }
4337
4335
 
@@ -4353,172 +4351,6 @@ async function removeLocalSkill(options) {
4353
4351
  return { removed };
4354
4352
  }
4355
4353
 
4356
- // ==================================================================
4357
- // === Source: services/doctor-service ===
4358
- // ==================================================================
4359
-
4360
- import { lstat, readdir as readdir2, writeFile as writeFile6, readFile as readFile5 } from 'node:fs/promises';
4361
- import { join as join4 } from 'node:path';
4362
-
4363
- async function runDoctor(cwd, home) {
4364
- const store = new InventoryStore(home);
4365
- const skipped = [];
4366
- const conflicts = [];
4367
-
4368
- const entries = await scanMetadata(cwd, skipped);
4369
-
4370
- const groups = new Map();
4371
- for (const entry of entries) {
4372
- const key = `${entry.metadata.registry}|${entry.metadata.namespace}|${entry.metadata.slug}`;
4373
- if (!groups.has(key)) groups.set(key, []);
4374
- groups.get(key).push(entry);
4375
- }
4376
-
4377
- const scannedItems = [];
4378
- for (const [key, group] of groups) {
4379
- const versions = new Set(group.map(e => e.metadata.version));
4380
- if (versions.size > 1) {
4381
- conflicts.push({ key, versions: [...versions] });
4382
- continue;
4383
- }
4384
- const first = group[0];
4385
- const targets = group.map(e => ({
4386
- agent: e.metadata.agent,
4387
- rootDir: join4(e.installDir, '..'),
4388
- installDir: e.installDir,
4389
- installedAt: e.metadata.installedAt
4390
- }));
4391
- scannedItems.push({
4392
- registry: first.metadata.registry,
4393
- namespace: first.metadata.namespace,
4394
- slug: first.metadata.slug,
4395
- version: first.metadata.version,
4396
- targets
4397
- });
4398
- }
4399
-
4400
- let oldInventory;
4401
- try {
4402
- oldInventory = await store.read();
4403
- } catch {
4404
- oldInventory = { items: [] };
4405
- }
4406
-
4407
- const scannedInstallDirs = new Set();
4408
- for (const item of scannedItems) {
4409
- for (const target of item.targets) {
4410
- scannedInstallDirs.add(target.installDir);
4411
- }
4412
- }
4413
-
4414
- const preservedItems = [];
4415
- for (const oldItem of oldInventory.items) {
4416
- const preservedTargets = oldItem.targets.filter(t => !scannedInstallDirs.has(t.installDir));
4417
- if (preservedTargets.length > 0) {
4418
- preservedItems.push({
4419
- ...oldItem,
4420
- targets: preservedTargets
4421
- });
4422
- }
4423
- }
4424
-
4425
- const items = [...scannedItems, ...preservedItems];
4426
-
4427
- let backupPath = null;
4428
- try {
4429
- const oldContent = await readFile5(store.path, 'utf-8');
4430
- backupPath = `${store.path}.bak`;
4431
- await writeFile6(backupPath, oldContent);
4432
- } catch {
4433
- }
4434
-
4435
- const newInventory = { items };
4436
- await store.writeAtomic(newInventory);
4437
-
4438
- return {
4439
- inventoryPath: store.path,
4440
- backupPath,
4441
- itemsScanned: scannedItems.length,
4442
- targetsScanned: scannedItems.reduce((sum, item) => sum + item.targets.length, 0),
4443
- itemsPreserved: preservedItems.length,
4444
- targetsPreserved: preservedItems.reduce((sum, item) => sum + item.targets.length, 0),
4445
- skipped,
4446
- conflicts
4447
- };
4448
- }
4449
-
4450
- async function scanMetadata(cwd, skipped) {
4451
- const results = [];
4452
-
4453
- let topEntries;
4454
- try {
4455
- topEntries = await readdir2(cwd);
4456
- } catch {
4457
- throw new CliError('cannot read project directory', EXIT.filesystem, { path: cwd });
4458
- }
4459
-
4460
- for (const dirName of topEntries) {
4461
- if (!dirName.startsWith('.')) continue;
4462
- const agentDir = join4(cwd, dirName);
4463
- try {
4464
- const st = await lstat(agentDir);
4465
- if (st.isSymbolicLink() || !st.isDirectory()) {
4466
- skipped.push({ path: agentDir, reason: 'not a regular directory' });
4467
- continue;
4468
- }
4469
- } catch {
4470
- skipped.push({ path: agentDir, reason: 'cannot stat' });
4471
- continue;
4472
- }
4473
- const skillsDir = join4(agentDir, 'skills');
4474
- let slugDirs;
4475
- try {
4476
- slugDirs = await readdir2(skillsDir);
4477
- } catch {
4478
- continue;
4479
- }
4480
-
4481
- for (const slug of slugDirs) {
4482
- const slugPath = join4(skillsDir, slug);
4483
- try {
4484
- const st = await lstat(slugPath);
4485
- if (st.isSymbolicLink() || !st.isDirectory()) {
4486
- skipped.push({ path: slugPath, reason: 'not a regular directory' });
4487
- continue;
4488
- }
4489
- } catch {
4490
- skipped.push({ path: slugPath, reason: 'cannot stat' });
4491
- continue;
4492
- }
4493
- const skillhubDir = join4(slugPath, '.skillhub');
4494
- try {
4495
- const skillhubSt = await lstat(skillhubDir);
4496
- if (skillhubSt.isSymbolicLink() || !skillhubSt.isDirectory()) {
4497
- skipped.push({ path: slugPath, reason: '.skillhub is not a regular directory' });
4498
- continue;
4499
- }
4500
- } catch {
4501
- skipped.push({ path: slugPath, reason: 'no .skillhub directory' });
4502
- continue;
4503
- }
4504
- const metadataPath = join4(skillhubDir, 'metadata.json');
4505
- try {
4506
- const content = await readFile5(metadataPath, 'utf-8');
4507
- const metadata = JSON.parse(content);
4508
- if (!metadata.registry || !metadata.namespace || !metadata.slug || !metadata.version || !metadata.agent || !metadata.installedAt) {
4509
- skipped.push({ path: slugPath, reason: 'incomplete metadata' });
4510
- continue;
4511
- }
4512
- results.push({ metadata, installDir: slugPath });
4513
- } catch {
4514
- skipped.push({ path: slugPath, reason: 'no .skillhub/metadata.json' });
4515
- }
4516
- }
4517
- }
4518
-
4519
- return results;
4520
- }
4521
-
4522
4354
  // ==================================================================
4523
4355
  // === Source: agents/profiles/make-profile ===
4524
4356
  // ==================================================================
@@ -4565,6 +4397,7 @@ const traeProfile = makeProfile('trae', 'Trae', '.trae/skills', '.trae/skills');
4565
4397
  const traeCnProfile = makeProfile('trae-cn', 'Trae CN', '.trae-cn/skills', '.trae-cn/skills');
4566
4398
  const opencodeProfile = makeProfile('opencode', 'OpenCode', '.opencode/skills', '.opencode/skills');
4567
4399
  const kiloProfile = makeProfile('kilo', 'Kilo', '.kilo/skills', '.kilo/skills');
4400
+ const qoderProfile = makeProfile('qoder', 'qoder', '.qoder/skills', '.qoder/skills');
4568
4401
  const genericFallbackProfile = makeProfile('generic', 'Generic Fallback', '.agents/skills', '.agents/skills');
4569
4402
 
4570
4403
  // ==================================================================
@@ -4575,7 +4408,7 @@ const allProfiles = [
4575
4408
  claudeCodeProfile, codexProfile, cursorProfile, githubCopilotProfile,
4576
4409
  geminiCliProfile, openhandsProfile, windsurfProfile, openclawProfile,
4577
4410
  kiroCliProfile, rooProfile, traeProfile, traeCnProfile,
4578
- opencodeProfile, kiloProfile
4411
+ opencodeProfile, kiloProfile, qoderProfile
4579
4412
  ];
4580
4413
 
4581
4414
  const profileMap = new Map(allProfiles.map(p => [p.id, p]));
@@ -4737,11 +4570,6 @@ const commands = {
4737
4570
  usage: 'skillhub help [command] [--json]',
4738
4571
  examples: ['skillhub help', 'skillhub help install', 'skillhub help --json']
4739
4572
  },
4740
- version: {
4741
- summary: 'Show installed CLI version',
4742
- usage: 'skillhub version [--json]',
4743
- examples: ['skillhub version', 'skillhub version --json']
4744
- },
4745
4573
  login: {
4746
4574
  summary: 'Save registry and token',
4747
4575
  usage: 'skillhub login [--token <token>] [--registry <url>] [--json]',
@@ -4781,11 +4609,6 @@ const commands = {
4781
4609
  usage: 'skillhub remove <slug> [--agent <profile>] [--all] [--remote] [--hard] [--namespace <slug>] [--json]',
4782
4610
  examples: ['skillhub remove pdf-parser', 'skillhub remove pdf-parser --remote --hard']
4783
4611
  },
4784
- doctor: {
4785
- summary: 'Scan project and merge into local inventory (preserves entries outside scan scope)',
4786
- usage: 'skillhub doctor [--json]',
4787
- examples: ['skillhub doctor', 'skillhub doctor --json']
4788
- },
4789
4612
  publish: {
4790
4613
  summary: 'Publish a local skill package',
4791
4614
  usage: 'skillhub publish <path> [--namespace <slug>] [--visibility <public|namespace-only|private>] [--registry <url>] [--json]',
@@ -4822,15 +4645,6 @@ async function helpCommand(args) {
4822
4645
  return formatCommandList();
4823
4646
  }
4824
4647
 
4825
- // ==================================================================
4826
- // === Source: commands/version ===
4827
- // ==================================================================
4828
-
4829
- async function versionCommand(args) {
4830
- const json = args.includes('--json');
4831
- return printResult(json ? { ok: true, version: CLI_VERSION } : `SkillHub CLI ${CLI_VERSION}`, json);
4832
- }
4833
-
4834
4648
  // ==================================================================
4835
4649
  // === Source: commands/login ===
4836
4650
  // ==================================================================
@@ -5084,38 +4898,6 @@ async function removeCommand(skillNameArg, options) {
5084
4898
  ).join('\n');
5085
4899
  }
5086
4900
 
5087
- // ==================================================================
5088
- // === Source: commands/doctor ===
5089
- // ==================================================================
5090
-
5091
- async function doctorCommand(options) {
5092
- const result = await runDoctor(process.cwd());
5093
- if (options.json) {
5094
- return JSON.stringify({
5095
- ok: true,
5096
- inventoryPath: result.inventoryPath,
5097
- backupPath: result.backupPath,
5098
- itemsScanned: result.itemsScanned,
5099
- targetsScanned: result.targetsScanned,
5100
- itemsPreserved: result.itemsPreserved,
5101
- targetsPreserved: result.targetsPreserved,
5102
- skipped: result.skipped,
5103
- conflicts: result.conflicts
5104
- });
5105
- }
5106
- const lines = [
5107
- `Inventory: ${result.inventoryPath}`,
5108
- result.backupPath ? `Backup: ${result.backupPath}` : null,
5109
- `Scanned: ${result.itemsScanned} items, ${result.targetsScanned} targets`,
5110
- result.itemsPreserved > 0
5111
- ? `Preserved (outside scan): ${result.itemsPreserved} items, ${result.targetsPreserved} targets`
5112
- : null,
5113
- result.skipped.length > 0 ? `Skipped: ${result.skipped.length} directories` : null,
5114
- result.conflicts.length > 0 ? `Conflicts: ${result.conflicts.length} groups` : null
5115
- ].filter(Boolean);
5116
- return lines.join('\n');
5117
- }
5118
-
5119
4901
  // ==================================================================
5120
4902
  // === Source: commands/publish ===
5121
4903
  // ==================================================================
@@ -5371,9 +5153,6 @@ function readUnknownCommand(argv) {
5371
5153
  cli.command('help [command]', 'Show help')
5372
5154
  .option('--json', 'Output JSON');
5373
5155
 
5374
- cli.command('version', 'Show CLI version')
5375
- .option('--json', 'Output JSON');
5376
-
5377
5156
  cli.command('login', 'Save registry and token')
5378
5157
  .option('--registry <url>', 'Registry URL')
5379
5158
  .option('--token <token>', 'API token')
@@ -5422,9 +5201,6 @@ cli.command('remove <slug>', 'Remove local or remote skill')
5422
5201
  .option('--token <token>', 'API token')
5423
5202
  .option('--json', 'Output JSON');
5424
5203
 
5425
- cli.command('doctor', 'Scan project and merge into local inventory')
5426
- .option('--json', 'Output JSON');
5427
-
5428
5204
  cli.command('publish <path>', 'Publish a local skill package')
5429
5205
  .option('--namespace <slug>', 'Namespace')
5430
5206
  .option('--visibility <v>', 'Visibility (public|namespace-only|private)')
@@ -5439,8 +5215,6 @@ async function dispatchCommand(commandName, args, options) {
5439
5215
  switch (commandName) {
5440
5216
  case 'help':
5441
5217
  return helpCommand([...args, ...(options.json ? ['--json'] : [])]);
5442
- case 'version':
5443
- return versionCommand(options.json ? ['--json'] : []);
5444
5218
  case 'login':
5445
5219
  return loginCommand(options);
5446
5220
  case 'logout':
@@ -5455,8 +5229,6 @@ async function dispatchCommand(commandName, args, options) {
5455
5229
  return listCommand({ ...options, agent: toArray(options.agent) });
5456
5230
  case 'remove':
5457
5231
  return removeCommand(args[0], { ...options, agent: toArray(options.agent) });
5458
- case 'doctor':
5459
- return doctorCommand(options);
5460
5232
  case 'publish':
5461
5233
  return publishCommand(args[0], options);
5462
5234
  default: