@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 +2 -6
- package/README.md +0 -2
- package/package.json +1 -1
- package/src/skillhub.mjs +5 -233
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
|
|
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
|
|
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
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:
|