@quadient/skillshare 0.1.1 → 1.0.0
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 +3 -0
- package/dist/index.js +67 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,8 @@ bun run index.ts
|
|
|
9
9
|
bun run index.ts login
|
|
10
10
|
bun run index.ts login local
|
|
11
11
|
bun run index.ts list
|
|
12
|
+
bun run index.ts install
|
|
13
|
+
bun run index.ts install "Prompt Lint"
|
|
12
14
|
bun run index.ts upload ./examples/prompt-lint --version 0.1.0
|
|
13
15
|
bun run index.ts install 12 0.1.0 --target ./installed
|
|
14
16
|
bun run index.ts install --skill-version-id 42 --target ./installed
|
|
@@ -17,6 +19,7 @@ bun run index.ts install --skill-version-id 42 --target ./installed
|
|
|
17
19
|
Interactive behavior:
|
|
18
20
|
|
|
19
21
|
- If the current directory already contains SKILL.md, the TUI offers to upload it before showing the main action picker.
|
|
22
|
+
- `install` opens the guided installer. When you pass `<skillId|skillName>`, the installer opens with that skill already selected; adding `[version]` skips the version picker too.
|
|
20
23
|
- After install or upload, the CLI writes skillshare.metadata.json into the skill directory with the skill id, name, description, and installed or published version.
|
|
21
24
|
- When skillshare.metadata.json already exists, uploads publish a new version of that skill instead of creating a duplicate entry.
|
|
22
25
|
- New skill creation derives name and description from SKILL.md frontmatter when available, so the user usually only needs to enter the initial version.
|
package/dist/index.js
CHANGED
|
@@ -71,7 +71,9 @@ Commands:
|
|
|
71
71
|
list
|
|
72
72
|
show <skillId> [version]
|
|
73
73
|
upload <directory> --version <version> [--skill-id <id>] [--name <name> --description <desc>]
|
|
74
|
-
install
|
|
74
|
+
install
|
|
75
|
+
install <skillId|skillName> [version]
|
|
76
|
+
install <skillId|skillName> [version] --target <directory>
|
|
75
77
|
install --skill-version-id <id> --target <directory>
|
|
76
78
|
|
|
77
79
|
Options:
|
|
@@ -160,7 +162,7 @@ async function main() {
|
|
|
160
162
|
}
|
|
161
163
|
case 'install': {
|
|
162
164
|
const skillVersionId = options.flags['skill-version-id'];
|
|
163
|
-
const
|
|
165
|
+
const skillRef = options.positionals[0];
|
|
164
166
|
const version = options.positionals[1];
|
|
165
167
|
const target = options.flags.target;
|
|
166
168
|
if (skillVersionId) {
|
|
@@ -185,16 +187,24 @@ async function main() {
|
|
|
185
187
|
console.log(`Installed skillVersion ${parsedSkillVersionId} (${detail.skillId}@${detail.version}) to ${target}`);
|
|
186
188
|
return;
|
|
187
189
|
}
|
|
188
|
-
if (!
|
|
189
|
-
|
|
190
|
+
if (!target) {
|
|
191
|
+
await runInteractiveInstall(client, {
|
|
192
|
+
skillRef,
|
|
193
|
+
version,
|
|
194
|
+
});
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (!skillRef) {
|
|
198
|
+
throw new Error('install requires <skillId|skillName> [version] when --target <directory> is provided');
|
|
190
199
|
}
|
|
191
|
-
const
|
|
200
|
+
const skills = await client.get('/api/skills');
|
|
201
|
+
const skill = resolveSkillReference(skills, skillRef);
|
|
192
202
|
const effectiveVersion = version ?? skill.latestVersion;
|
|
193
203
|
if (!effectiveVersion) {
|
|
194
|
-
throw new Error(`Skill '${
|
|
204
|
+
throw new Error(`Skill '${skill.name}' does not have a published version.`);
|
|
195
205
|
}
|
|
196
|
-
const detail = await client.get(`/api/skills/${
|
|
197
|
-
await client.post(`/api/skills/${
|
|
206
|
+
const detail = await client.get(`/api/skills/${skill.id}/versions/${effectiveVersion}`);
|
|
207
|
+
await client.post(`/api/skills/${skill.id}/versions/${effectiveVersion}/downloads`);
|
|
198
208
|
await writeSkillVersionToDirectory(client, {
|
|
199
209
|
skillId: skill.id,
|
|
200
210
|
skillName: skill.name,
|
|
@@ -203,7 +213,7 @@ async function main() {
|
|
|
203
213
|
files: detail.files,
|
|
204
214
|
targetRoot: target,
|
|
205
215
|
});
|
|
206
|
-
console.log(`Installed ${
|
|
216
|
+
console.log(`Installed ${skill.name}@${effectiveVersion} to ${target}`);
|
|
207
217
|
return;
|
|
208
218
|
}
|
|
209
219
|
}
|
|
@@ -266,14 +276,18 @@ async function ensureInteractiveLogin(baseUrl) {
|
|
|
266
276
|
await login(baseUrl);
|
|
267
277
|
}
|
|
268
278
|
}
|
|
269
|
-
async function runInteractiveInstall(client) {
|
|
279
|
+
async function runInteractiveInstall(client, options) {
|
|
270
280
|
const skills = await client.get('/api/skills');
|
|
271
281
|
if (skills.length === 0) {
|
|
272
282
|
throw new Error('No skills available in the registry.');
|
|
273
283
|
}
|
|
274
|
-
const skill =
|
|
284
|
+
const skill = options?.skillRef
|
|
285
|
+
? resolveSkillReference(skills, options.skillRef)
|
|
286
|
+
: await promptForSkill(skills);
|
|
275
287
|
const detail = await client.get(`/api/skills/${skill.id}`);
|
|
276
|
-
const selectedVersion =
|
|
288
|
+
const selectedVersion = options?.version
|
|
289
|
+
? resolveSkillVersion(detail, options.version)
|
|
290
|
+
: await promptForVersion(detail);
|
|
277
291
|
const scope = await promptForInstallScope();
|
|
278
292
|
const selectedAgents = await promptForAgents(scope);
|
|
279
293
|
if (selectedAgents.length === 0) {
|
|
@@ -723,6 +737,47 @@ function normalizeText(value) {
|
|
|
723
737
|
const trimmed = value?.trim();
|
|
724
738
|
return trimmed ? trimmed : null;
|
|
725
739
|
}
|
|
740
|
+
function resolveSkillReference(skills, reference) {
|
|
741
|
+
const normalizedReference = normalizeText(reference)?.toLowerCase();
|
|
742
|
+
if (!normalizedReference) {
|
|
743
|
+
throw new Error('Skill reference is required.');
|
|
744
|
+
}
|
|
745
|
+
const idMatch = skills.find((skill) => String(skill.id) === normalizedReference);
|
|
746
|
+
if (idMatch) {
|
|
747
|
+
return idMatch;
|
|
748
|
+
}
|
|
749
|
+
const exactNameMatches = skills.filter((skill) => normalizeText(skill.name)?.toLowerCase() === normalizedReference);
|
|
750
|
+
const exactNameMatch = exactNameMatches[0];
|
|
751
|
+
if (exactNameMatches.length === 1 && exactNameMatch) {
|
|
752
|
+
return exactNameMatch;
|
|
753
|
+
}
|
|
754
|
+
if (exactNameMatches.length > 1) {
|
|
755
|
+
throw new Error(`Skill reference '${reference}' matches multiple skills: ${formatSkillMatches(exactNameMatches)}. Use the numeric skill id instead.`);
|
|
756
|
+
}
|
|
757
|
+
const slugMatches = skills.filter((skill) => createInstalledSkillDirectoryName(skill) === normalizedReference);
|
|
758
|
+
const slugMatch = slugMatches[0];
|
|
759
|
+
if (slugMatches.length === 1 && slugMatch) {
|
|
760
|
+
return slugMatch;
|
|
761
|
+
}
|
|
762
|
+
if (slugMatches.length > 1) {
|
|
763
|
+
throw new Error(`Skill reference '${reference}' matches multiple skills: ${formatSkillMatches(slugMatches)}. Use the numeric skill id instead.`);
|
|
764
|
+
}
|
|
765
|
+
throw new Error(`Skill '${reference}' was not found. Run "skillshare list" to inspect available skills.`);
|
|
766
|
+
}
|
|
767
|
+
function resolveSkillVersion(detail, version) {
|
|
768
|
+
const normalizedVersion = normalizeText(version);
|
|
769
|
+
if (!normalizedVersion) {
|
|
770
|
+
throw new Error('Version is required.');
|
|
771
|
+
}
|
|
772
|
+
const requestedVersion = detail.versions.find((item) => item.version === normalizedVersion);
|
|
773
|
+
if (!requestedVersion) {
|
|
774
|
+
throw new Error(`Skill '${detail.name}' does not have version '${normalizedVersion}'.`);
|
|
775
|
+
}
|
|
776
|
+
return requestedVersion.version;
|
|
777
|
+
}
|
|
778
|
+
function formatSkillMatches(skills) {
|
|
779
|
+
return skills.map((skill) => `${skill.id}:${skill.name}`).join(', ');
|
|
780
|
+
}
|
|
726
781
|
function filterSkills(skills, query) {
|
|
727
782
|
const normalized = query.trim().toLowerCase();
|
|
728
783
|
return skills.filter((skill) => skill.name.toLowerCase().includes(normalized) ||
|