skills 1.5.16 → 1.5.18
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/dist/cli.mjs +89 -72
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -9,7 +9,6 @@ import { require_dist } from "./_chunks/libs/@vercel/detect-agent.mjs";
|
|
|
9
9
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "fs";
|
|
10
10
|
import { basename, dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from "path";
|
|
11
11
|
import { fileURLToPath } from "url";
|
|
12
|
-
import { createHash } from "node:crypto";
|
|
13
12
|
import { stripVTControlCharacters } from "node:util";
|
|
14
13
|
import { homedir, platform, tmpdir } from "os";
|
|
15
14
|
import * as readline from "readline";
|
|
@@ -18,7 +17,8 @@ import { promisify } from "util";
|
|
|
18
17
|
import { execFile, execSync, spawn, spawnSync } from "child_process";
|
|
19
18
|
import { access, chmod, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, realpath, rm, stat, symlink, writeFile } from "fs/promises";
|
|
20
19
|
import { parse } from "yaml";
|
|
21
|
-
import { createHash
|
|
20
|
+
import { createHash } from "crypto";
|
|
21
|
+
import { createHash as createHash$1 } from "node:crypto";
|
|
22
22
|
import { gunzipSync, inflateRawSync } from "node:zlib";
|
|
23
23
|
var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
24
24
|
function getOwnerRepo(parsed) {
|
|
@@ -319,7 +319,7 @@ async function searchMultiselect(options) {
|
|
|
319
319
|
const lockedTitle = `${import_picocolors.default.bold(lockedSection.title)} ${import_picocolors.default.dim("── always included")}`;
|
|
320
320
|
lines.push(`${S_BAR} ${S_BAR_H}${S_BAR_H} ${lockedTitle} ${S_BAR_H.repeat(12)}`);
|
|
321
321
|
for (const item of lockedSection.items) lines.push(`${S_BAR} ${S_BULLET} ${import_picocolors.default.bold(item.label)}`);
|
|
322
|
-
if (lockedSection.hiddenCount && lockedSection.hiddenCount > 0) lines.push(`${S_BAR} ${import_picocolors.default.dim(
|
|
322
|
+
if (lockedSection.hiddenCount && lockedSection.hiddenCount > 0) lines.push(`${S_BAR} ${import_picocolors.default.dim(`…and ${lockedSection.hiddenCount} more`)}`);
|
|
323
323
|
lines.push(`${S_BAR}`);
|
|
324
324
|
lines.push(`${S_BAR} ${S_BAR_H}${S_BAR_H} ${import_picocolors.default.bold("Additional agents")} ${S_BAR_H.repeat(29)}`);
|
|
325
325
|
}
|
|
@@ -492,23 +492,44 @@ function isGitHubSsoAuthError(message) {
|
|
|
492
492
|
function isAuthFailure(message) {
|
|
493
493
|
return message.includes("Authentication failed") || message.includes("could not read Username") || message.includes("Permission denied") || message.includes("Repository not found") || message.includes("requested URL returned error: 403") || isGitHubSsoAuthError(message);
|
|
494
494
|
}
|
|
495
|
-
function createGitClient(
|
|
496
|
-
|
|
495
|
+
function createGitClient(sshCommand) {
|
|
496
|
+
const git = esm_default({
|
|
497
497
|
timeout: { block: CLONE_TIMEOUT_MS },
|
|
498
|
-
env: {
|
|
499
|
-
...process.env,
|
|
500
|
-
GIT_TERMINAL_PROMPT: "0",
|
|
501
|
-
GIT_LFS_SKIP_SMUDGE: "1",
|
|
502
|
-
...extraEnv
|
|
503
|
-
},
|
|
504
498
|
config: [
|
|
505
499
|
"filter.lfs.required=false",
|
|
506
500
|
"filter.lfs.smudge=",
|
|
507
501
|
"filter.lfs.clean=",
|
|
508
502
|
"filter.lfs.process="
|
|
509
503
|
],
|
|
510
|
-
unsafe: {
|
|
504
|
+
unsafe: {
|
|
505
|
+
allowUnsafeAlias: true,
|
|
506
|
+
allowUnsafeAskPass: true,
|
|
507
|
+
allowUnsafeConfigEnvCount: true,
|
|
508
|
+
allowUnsafeConfigPaths: true,
|
|
509
|
+
allowUnsafeCredentialHelper: true,
|
|
510
|
+
allowUnsafeDiffExternal: true,
|
|
511
|
+
allowUnsafeDiffTextConv: true,
|
|
512
|
+
allowUnsafeEditor: true,
|
|
513
|
+
allowUnsafeFilter: true,
|
|
514
|
+
allowUnsafeFsMonitor: true,
|
|
515
|
+
allowUnsafeGpgProgram: true,
|
|
516
|
+
allowUnsafeGitProxy: true,
|
|
517
|
+
allowUnsafeHooksPath: true,
|
|
518
|
+
allowUnsafeMergeDriver: true,
|
|
519
|
+
allowUnsafePack: true,
|
|
520
|
+
allowUnsafePager: true,
|
|
521
|
+
allowUnsafeProtocolOverride: true,
|
|
522
|
+
allowUnsafeSshCommand: true,
|
|
523
|
+
allowUnsafeTemplateDir: true
|
|
524
|
+
}
|
|
511
525
|
});
|
|
526
|
+
git.env({
|
|
527
|
+
...process.env,
|
|
528
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
529
|
+
GIT_LFS_SKIP_SMUDGE: "1",
|
|
530
|
+
...sshCommand ? { GIT_SSH_COMMAND: sshCommand } : {}
|
|
531
|
+
});
|
|
532
|
+
return git;
|
|
512
533
|
}
|
|
513
534
|
async function resetTempDir(dir) {
|
|
514
535
|
await rm(dir, {
|
|
@@ -593,7 +614,7 @@ async function cloneRepo(url, ref) {
|
|
|
593
614
|
} catch {}
|
|
594
615
|
try {
|
|
595
616
|
await resetTempDir(tempDir);
|
|
596
|
-
await createGitClient(
|
|
617
|
+
await createGitClient(process.env.GIT_SSH_COMMAND ?? "ssh -o BatchMode=yes").clone(repo.sshUrl, tempDir, cloneOptions);
|
|
597
618
|
return tempDir;
|
|
598
619
|
} catch {}
|
|
599
620
|
}
|
|
@@ -721,7 +742,7 @@ async function computeSkillFolderHash(skillDir) {
|
|
|
721
742
|
const files = [];
|
|
722
743
|
await collectFiles(skillDir, skillDir, files);
|
|
723
744
|
files.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
724
|
-
const hash = createHash
|
|
745
|
+
const hash = createHash("sha256");
|
|
725
746
|
for (const file of files) {
|
|
726
747
|
hash.update(file.relativePath);
|
|
727
748
|
hash.update(file.content);
|
|
@@ -795,6 +816,9 @@ function normalizeSkillName(name) {
|
|
|
795
816
|
function normalizeRelativePath(path) {
|
|
796
817
|
return path.split(sep).join("/").replace(/\/+/g, "/");
|
|
797
818
|
}
|
|
819
|
+
function isRecord(value) {
|
|
820
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
821
|
+
}
|
|
798
822
|
function shouldInstallInternalSkills() {
|
|
799
823
|
const envValue = process.env.INSTALL_INTERNAL_SKILLS;
|
|
800
824
|
return envValue === "1" || envValue === "true";
|
|
@@ -812,13 +836,14 @@ async function parseSkillMd(skillMdPath, options) {
|
|
|
812
836
|
const { data } = parseFrontmatter(content);
|
|
813
837
|
if (!data.name || !data.description) return null;
|
|
814
838
|
if (typeof data.name !== "string" || typeof data.description !== "string") return null;
|
|
815
|
-
|
|
839
|
+
const metadata = isRecord(data.metadata) ? data.metadata : void 0;
|
|
840
|
+
if (metadata?.internal === true && !shouldInstallInternalSkills() && !options?.includeInternal) return null;
|
|
816
841
|
return {
|
|
817
842
|
name: sanitizeMetadata(data.name),
|
|
818
843
|
description: sanitizeMetadata(data.description),
|
|
819
844
|
path: dirname(skillMdPath),
|
|
820
845
|
rawContent: content,
|
|
821
|
-
metadata
|
|
846
|
+
metadata
|
|
822
847
|
};
|
|
823
848
|
} catch {
|
|
824
849
|
return null;
|
|
@@ -2680,7 +2705,7 @@ var WellKnownProvider = class {
|
|
|
2680
2705
|
}
|
|
2681
2706
|
}
|
|
2682
2707
|
computeDigest(bytes) {
|
|
2683
|
-
return `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
|
|
2708
|
+
return `sha256:${createHash$1("sha256").update(bytes).digest("hex")}`;
|
|
2684
2709
|
}
|
|
2685
2710
|
extractArchive(bytes, artifactUrl, contentType) {
|
|
2686
2711
|
if (this.isZipArchive(bytes, artifactUrl, contentType)) return this.extractZip(bytes);
|
|
@@ -2849,7 +2874,7 @@ function getGitHubToken() {
|
|
|
2849
2874
|
if (process.env.GITHUB_TOKEN) return process.env.GITHUB_TOKEN;
|
|
2850
2875
|
if (process.env.GH_TOKEN) return process.env.GH_TOKEN;
|
|
2851
2876
|
if (!_ghWarningShown) {
|
|
2852
|
-
process.stderr.write(`${import_picocolors.default.
|
|
2877
|
+
process.stderr.write(`${import_picocolors.default.dim("│ GitHub API request limit reached; checking existing ")}${import_picocolors.default.cyan("gh")}${import_picocolors.default.dim(" authentication…\n")}`);
|
|
2853
2878
|
_ghWarningShown = true;
|
|
2854
2879
|
}
|
|
2855
2880
|
try {
|
|
@@ -3103,7 +3128,7 @@ async function fetchSkillDownload(source, slug) {
|
|
|
3103
3128
|
}
|
|
3104
3129
|
}
|
|
3105
3130
|
function computeSnapshotHash(files) {
|
|
3106
|
-
const hash = createHash("sha256");
|
|
3131
|
+
const hash = createHash$1("sha256");
|
|
3107
3132
|
for (const file of [...files].sort((a, b) => a.path.localeCompare(b.path))) {
|
|
3108
3133
|
hash.update(file.path);
|
|
3109
3134
|
hash.update(file.contents);
|
|
@@ -3183,7 +3208,7 @@ async function tryBlobInstall(ownerRepo, options = {}) {
|
|
|
3183
3208
|
tree
|
|
3184
3209
|
};
|
|
3185
3210
|
}
|
|
3186
|
-
var version$1 = "1.5.
|
|
3211
|
+
var version$1 = "1.5.18";
|
|
3187
3212
|
const isCancelled$1 = (value) => typeof value === "symbol";
|
|
3188
3213
|
const EVE_AGENT_LABEL = "eve agent";
|
|
3189
3214
|
async function isSourcePrivate(source) {
|
|
@@ -3254,12 +3279,6 @@ function shortenPath$2(fullPath, cwd) {
|
|
|
3254
3279
|
if (fullPath === cwd || fullPath.startsWith(cwd + sep)) return "." + fullPath.slice(cwd.length);
|
|
3255
3280
|
return fullPath;
|
|
3256
3281
|
}
|
|
3257
|
-
function computeSingleFileSkillHash(contents) {
|
|
3258
|
-
const hash = createHash("sha256");
|
|
3259
|
-
hash.update("SKILL.md");
|
|
3260
|
-
hash.update(contents);
|
|
3261
|
-
return hash.digest("hex");
|
|
3262
|
-
}
|
|
3263
3282
|
function formatList$1(items, maxShow = 5) {
|
|
3264
3283
|
if (items.length <= maxShow) return items.join(", ");
|
|
3265
3284
|
const shown = items.slice(0, maxShow);
|
|
@@ -3409,7 +3428,7 @@ async function selectAgentsInteractive(options) {
|
|
|
3409
3428
|
}
|
|
3410
3429
|
setVersion(version$1);
|
|
3411
3430
|
async function handleWellKnownSkills(source, url, options, spinner) {
|
|
3412
|
-
spinner.start("Discovering skills from well-known endpoint
|
|
3431
|
+
spinner.start("Discovering skills from well-known endpoint…");
|
|
3413
3432
|
const skills = await wellKnownProvider.fetchAllSkills(url);
|
|
3414
3433
|
if (skills.length === 0) {
|
|
3415
3434
|
spinner.stop(import_picocolors.default.red("No skills found"));
|
|
@@ -3459,7 +3478,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
3459
3478
|
options: skills.map((s) => ({
|
|
3460
3479
|
value: s,
|
|
3461
3480
|
label: s.installName,
|
|
3462
|
-
hint: s.description.length > 60 ? s.description.slice(0, 57) + "
|
|
3481
|
+
hint: s.description.length > 60 ? s.description.slice(0, 57) + "…" : s.description
|
|
3463
3482
|
})),
|
|
3464
3483
|
required: true
|
|
3465
3484
|
});
|
|
@@ -3483,7 +3502,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
3483
3502
|
}
|
|
3484
3503
|
targetAgents = options.agent;
|
|
3485
3504
|
} else {
|
|
3486
|
-
spinner.start("Loading agents
|
|
3505
|
+
spinner.start("Loading agents…");
|
|
3487
3506
|
const installedAgents = await detectInstalledAgents();
|
|
3488
3507
|
const totalAgents = Object.keys(agents).length;
|
|
3489
3508
|
spinner.stop(`${totalAgents} agents`);
|
|
@@ -3593,7 +3612,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
3593
3612
|
}
|
|
3594
3613
|
const sourceIdentifier = wellKnownProvider.getSourceIdentifier(url);
|
|
3595
3614
|
const wellKnownPrivacyPromise = isSourcePrivate(sourceIdentifier).catch(() => null);
|
|
3596
|
-
spinner.start("Installing skills
|
|
3615
|
+
spinner.start("Installing skills…");
|
|
3597
3616
|
const results = [];
|
|
3598
3617
|
for (const skill of selectedSkills) for (const agent of targetAgents) {
|
|
3599
3618
|
const result = await installWellKnownSkillForAgent(skill, agent, {
|
|
@@ -3663,9 +3682,13 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
3663
3682
|
const firstResult = skillResults[0];
|
|
3664
3683
|
if (firstResult.mode === "copy") {
|
|
3665
3684
|
resultLines.push(`${import_picocolors.default.green("✓")} ${skillName} ${import_picocolors.default.dim("(copied)")}`);
|
|
3685
|
+
const shortPathsSet = /* @__PURE__ */ new Set();
|
|
3666
3686
|
for (const r of skillResults) {
|
|
3667
3687
|
const shortPath = shortenPath$2(r.path, cwd);
|
|
3668
|
-
|
|
3688
|
+
if (!shortPathsSet.has(shortPath)) {
|
|
3689
|
+
shortPathsSet.add(shortPath);
|
|
3690
|
+
resultLines.push(` ${import_picocolors.default.dim("→")} ${shortPath}`);
|
|
3691
|
+
}
|
|
3669
3692
|
}
|
|
3670
3693
|
} else {
|
|
3671
3694
|
if (firstResult.canonicalPath) {
|
|
@@ -3731,7 +3754,7 @@ async function runAdd(args, options = {}) {
|
|
|
3731
3754
|
let tempDir = null;
|
|
3732
3755
|
try {
|
|
3733
3756
|
const spinner$3 = spinner();
|
|
3734
|
-
spinner$3.start("Parsing source
|
|
3757
|
+
spinner$3.start("Parsing source…");
|
|
3735
3758
|
const parsed = parseSource(source);
|
|
3736
3759
|
spinner$3.stop(`Source: ${parsed.type === "local" ? parsed.localPath : parsed.url}${parsed.ref ? ` @ ${import_picocolors.default.yellow(parsed.ref)}` : ""}${parsed.subpath ? ` (${parsed.subpath})` : ""}${parsed.skillFilter ? ` ${import_picocolors.default.dim("@")}${import_picocolors.default.cyan(parsed.skillFilter)}` : ""}`);
|
|
3737
3760
|
const ownerRepoRaw = getOwnerRepo(parsed);
|
|
@@ -3753,14 +3776,14 @@ async function runAdd(args, options = {}) {
|
|
|
3753
3776
|
let skills;
|
|
3754
3777
|
let blobResult = null;
|
|
3755
3778
|
if (parsed.type === "local") {
|
|
3756
|
-
spinner$3.start("Validating local path
|
|
3779
|
+
spinner$3.start("Validating local path…");
|
|
3757
3780
|
if (!existsSync(parsed.localPath)) {
|
|
3758
3781
|
spinner$3.stop(import_picocolors.default.red("Path not found"));
|
|
3759
3782
|
outro(import_picocolors.default.red(`Local path does not exist: ${parsed.localPath}`));
|
|
3760
3783
|
process.exit(1);
|
|
3761
3784
|
}
|
|
3762
3785
|
spinner$3.stop("Local path validated");
|
|
3763
|
-
spinner$3.start("Discovering skills
|
|
3786
|
+
spinner$3.start("Discovering skills…");
|
|
3764
3787
|
skills = await discoverSkills(parsed.localPath, parsed.subpath, {
|
|
3765
3788
|
includeInternal,
|
|
3766
3789
|
fullDepth: options.fullDepth
|
|
@@ -3775,7 +3798,7 @@ async function runAdd(args, options = {}) {
|
|
|
3775
3798
|
const owner = ownerRepo?.split("/")[0]?.toLowerCase();
|
|
3776
3799
|
const isSelfHostedRepo = !!ownerRepo && Object.hasOwn(BLOB_ALLOWED_REPOS, ownerRepo.toLowerCase());
|
|
3777
3800
|
if (ownerRepo && owner && (isSelfHostedRepo || BLOB_ALLOWED_OWNERS.includes(owner))) {
|
|
3778
|
-
spinner$3.start("Fetching skills
|
|
3801
|
+
spinner$3.start("Fetching skills…");
|
|
3779
3802
|
blobResult = await tryBlobInstall(ownerRepo, {
|
|
3780
3803
|
subpath: parsed.subpath,
|
|
3781
3804
|
skillFilter: parsed.skillFilter,
|
|
@@ -3783,26 +3806,26 @@ async function runAdd(args, options = {}) {
|
|
|
3783
3806
|
getToken: getGitHubToken,
|
|
3784
3807
|
includeInternal
|
|
3785
3808
|
});
|
|
3786
|
-
if (!blobResult) spinner$3.stop(import_picocolors.default.dim("Falling back to clone
|
|
3809
|
+
if (!blobResult) spinner$3.stop(import_picocolors.default.dim("Falling back to clone…"));
|
|
3787
3810
|
}
|
|
3788
3811
|
if (blobResult) {
|
|
3789
3812
|
skills = blobResult.skills;
|
|
3790
3813
|
spinner$3.stop(`Found ${import_picocolors.default.green(skills.length)} skill${skills.length > 1 ? "s" : ""}`);
|
|
3791
3814
|
} else {
|
|
3792
|
-
spinner$3.start("Cloning repository
|
|
3815
|
+
spinner$3.start("Cloning repository…");
|
|
3793
3816
|
tempDir = await cloneRepo(parsed.url, parsed.ref);
|
|
3794
3817
|
spinner$3.stop("Repository cloned");
|
|
3795
|
-
spinner$3.start("Discovering skills
|
|
3818
|
+
spinner$3.start("Discovering skills…");
|
|
3796
3819
|
skills = await discoverSkills(tempDir, parsed.subpath, {
|
|
3797
3820
|
includeInternal,
|
|
3798
3821
|
fullDepth: options.fullDepth
|
|
3799
3822
|
});
|
|
3800
3823
|
}
|
|
3801
3824
|
} else {
|
|
3802
|
-
spinner$3.start("Cloning repository
|
|
3825
|
+
spinner$3.start("Cloning repository…");
|
|
3803
3826
|
tempDir = await cloneRepo(parsed.url, parsed.ref);
|
|
3804
3827
|
spinner$3.stop("Repository cloned");
|
|
3805
|
-
spinner$3.start("Discovering skills
|
|
3828
|
+
spinner$3.start("Discovering skills…");
|
|
3806
3829
|
skills = await discoverSkills(tempDir, parsed.subpath, {
|
|
3807
3830
|
includeInternal,
|
|
3808
3831
|
fullDepth: options.fullDepth
|
|
@@ -3887,7 +3910,7 @@ async function runAdd(args, options = {}) {
|
|
|
3887
3910
|
grouped[groupName].push({
|
|
3888
3911
|
value: s,
|
|
3889
3912
|
label: getSkillDisplayName(s),
|
|
3890
|
-
hint: s.description.length > 60 ? s.description.slice(0, 57) + "
|
|
3913
|
+
hint: s.description.length > 60 ? s.description.slice(0, 57) + "…" : s.description
|
|
3891
3914
|
});
|
|
3892
3915
|
}
|
|
3893
3916
|
selected = await groupMultiselect({
|
|
@@ -3900,7 +3923,7 @@ async function runAdd(args, options = {}) {
|
|
|
3900
3923
|
options: sortedSkills.map((s) => ({
|
|
3901
3924
|
value: s,
|
|
3902
3925
|
label: getSkillDisplayName(s),
|
|
3903
|
-
hint: s.description.length > 60 ? s.description.slice(0, 57) + "
|
|
3926
|
+
hint: s.description.length > 60 ? s.description.slice(0, 57) + "…" : s.description
|
|
3904
3927
|
})),
|
|
3905
3928
|
required: true
|
|
3906
3929
|
});
|
|
@@ -3928,7 +3951,7 @@ async function runAdd(args, options = {}) {
|
|
|
3928
3951
|
}
|
|
3929
3952
|
targetAgents = options.agent;
|
|
3930
3953
|
} else {
|
|
3931
|
-
spinner$3.start("Loading agents
|
|
3954
|
+
spinner$3.start("Loading agents…");
|
|
3932
3955
|
const installedAgents = await detectInstalledAgents();
|
|
3933
3956
|
const totalAgents = Object.keys(agents).length;
|
|
3934
3957
|
spinner$3.stop(`${totalAgents} agents`);
|
|
@@ -4131,7 +4154,7 @@ async function runAdd(args, options = {}) {
|
|
|
4131
4154
|
process.exit(0);
|
|
4132
4155
|
}
|
|
4133
4156
|
}
|
|
4134
|
-
spinner$3.start("Installing skills
|
|
4157
|
+
spinner$3.start("Installing skills…");
|
|
4135
4158
|
const results = [];
|
|
4136
4159
|
for (const skill of selectedSkills) for (const target of installTargets) {
|
|
4137
4160
|
const { agent, subagent } = target;
|
|
@@ -4146,17 +4169,7 @@ async function runAdd(args, options = {}) {
|
|
|
4146
4169
|
mode: installMode,
|
|
4147
4170
|
eveSubagent: subagent
|
|
4148
4171
|
});
|
|
4149
|
-
} else
|
|
4150
|
-
installName: skill.name,
|
|
4151
|
-
files: [{
|
|
4152
|
-
path: "SKILL.md",
|
|
4153
|
-
contents: skill.rawContent
|
|
4154
|
-
}]
|
|
4155
|
-
}, agent, {
|
|
4156
|
-
global: installGlobally,
|
|
4157
|
-
mode: installMode
|
|
4158
|
-
});
|
|
4159
|
-
else result = await installSkillForAgent(skill, agent, {
|
|
4172
|
+
} else result = await installSkillForAgent(skill, agent, {
|
|
4160
4173
|
global: installGlobally,
|
|
4161
4174
|
mode: installMode,
|
|
4162
4175
|
eveSubagent: subagent
|
|
@@ -4237,7 +4250,7 @@ async function runAdd(args, options = {}) {
|
|
|
4237
4250
|
for (const skill of selectedSkills) {
|
|
4238
4251
|
const skillDisplayName = getSkillDisplayName(skill);
|
|
4239
4252
|
if (successfulSkillNames.has(skillDisplayName)) try {
|
|
4240
|
-
const computedHash = blobResult && "snapshotHash" in skill ? skill.snapshotHash :
|
|
4253
|
+
const computedHash = blobResult && "snapshotHash" in skill ? skill.snapshotHash : await computeSkillFolderHash(skill.path);
|
|
4241
4254
|
const skillPathValue = skillFiles[skill.name];
|
|
4242
4255
|
await addSkillToLocalLock(skill.name, {
|
|
4243
4256
|
source: lockSource || parsed.url,
|
|
@@ -4275,9 +4288,13 @@ async function runAdd(args, options = {}) {
|
|
|
4275
4288
|
const firstResult = skillResults[0];
|
|
4276
4289
|
if (firstResult.mode === "copy") {
|
|
4277
4290
|
resultLines.push(`${import_picocolors.default.green("✓")} ${entry.skill} ${import_picocolors.default.dim("(copied)")}`);
|
|
4291
|
+
const shortPathsSet = /* @__PURE__ */ new Set();
|
|
4278
4292
|
for (const r of skillResults) {
|
|
4279
4293
|
const shortPath = shortenPath$2(r.path, cwd);
|
|
4280
|
-
|
|
4294
|
+
if (!shortPathsSet.has(shortPath)) {
|
|
4295
|
+
shortPathsSet.add(shortPath);
|
|
4296
|
+
resultLines.push(` ${import_picocolors.default.dim("→")} ${shortPath}`);
|
|
4297
|
+
}
|
|
4281
4298
|
}
|
|
4282
4299
|
} else {
|
|
4283
4300
|
if (firstResult.canonicalPath) {
|
|
@@ -4355,7 +4372,7 @@ async function promptForFindSkills(options, targetAgents) {
|
|
|
4355
4372
|
const findSkillsAgents = targetAgents?.filter((a) => a !== "replit");
|
|
4356
4373
|
if (!findSkillsAgents || findSkillsAgents.length === 0) return;
|
|
4357
4374
|
console.log();
|
|
4358
|
-
log.step("Installing find-skills skill
|
|
4375
|
+
log.step("Installing find-skills skill…");
|
|
4359
4376
|
try {
|
|
4360
4377
|
await runAdd(["vercel-labs/skills"], {
|
|
4361
4378
|
skill: ["find-skills"],
|
|
@@ -4528,7 +4545,7 @@ async function runSearchPrompt(initialQuery = "", owner) {
|
|
|
4528
4545
|
lines.push(`${TEXT$2}Search skills:${RESET$3} ${query}${cursor}`);
|
|
4529
4546
|
lines.push("");
|
|
4530
4547
|
if (!query || query.length < 2) lines.push(`${DIM$3}Start typing to search (min 2 chars)${RESET$3}`);
|
|
4531
|
-
else if (results.length === 0 && loading) lines.push(`${DIM$3}Searching
|
|
4548
|
+
else if (results.length === 0 && loading) lines.push(`${DIM$3}Searching…${RESET$3}`);
|
|
4532
4549
|
else if (results.length === 0) lines.push(`${DIM$3}No skills found${RESET$3}`);
|
|
4533
4550
|
else {
|
|
4534
4551
|
const visible = results.slice(0, 8);
|
|
@@ -4540,7 +4557,7 @@ async function runSearchPrompt(initialQuery = "", owner) {
|
|
|
4540
4557
|
const source = skill.source ? ` ${DIM$3}${skill.source}${RESET$3}` : "";
|
|
4541
4558
|
const installs = formatInstalls(skill.installs);
|
|
4542
4559
|
const installsBadge = installs ? ` ${CYAN$1}${installs}${RESET$3}` : "";
|
|
4543
|
-
const loadingIndicator = loading && i === 0 ? ` ${DIM$3}
|
|
4560
|
+
const loadingIndicator = loading && i === 0 ? ` ${DIM$3}…${RESET$3}` : "";
|
|
4544
4561
|
lines.push(` ${arrow} ${name}${source}${installsBadge}${loadingIndicator}`);
|
|
4545
4562
|
}
|
|
4546
4563
|
}
|
|
@@ -4694,7 +4711,7 @@ ${DIM$3} 2) npx skills add <owner/repo@skill>${RESET$3}`;
|
|
|
4694
4711
|
const pkg = selected.source || selected.slug;
|
|
4695
4712
|
const skillName = selected.name;
|
|
4696
4713
|
console.log();
|
|
4697
|
-
console.log(`${TEXT$2}Installing ${BOLD$3}${skillName}${RESET$3} from ${DIM$3}${pkg}${RESET$3}
|
|
4714
|
+
console.log(`${TEXT$2}Installing ${BOLD$3}${skillName}${RESET$3} from ${DIM$3}${pkg}${RESET$3}…`);
|
|
4698
4715
|
console.log();
|
|
4699
4716
|
const { source, options: addOptions } = parseAddOptions([
|
|
4700
4717
|
pkg,
|
|
@@ -4797,7 +4814,7 @@ async function runSync(args, options = {}) {
|
|
|
4797
4814
|
if (!agentResult.isAgent) intro(import_picocolors.default.bgCyan(import_picocolors.default.black(" skills experimental_sync ")));
|
|
4798
4815
|
if (agentResult.isAgent) log.info(import_picocolors.default.bgCyan(import_picocolors.default.black(import_picocolors.default.bold(` ${agentResult.agent.name} `))) + " Agent detected — installing non-interactively");
|
|
4799
4816
|
const spinner$2 = spinner();
|
|
4800
|
-
spinner$2.start("Scanning node_modules for skills
|
|
4817
|
+
spinner$2.start("Scanning node_modules for skills…");
|
|
4801
4818
|
const discoveredSkills = await discoverNodeModuleSkills(cwd);
|
|
4802
4819
|
if (discoveredSkills.length === 0) {
|
|
4803
4820
|
spinner$2.stop(import_picocolors.default.yellow("No skills found"));
|
|
@@ -4850,7 +4867,7 @@ async function runSync(args, options = {}) {
|
|
|
4850
4867
|
}
|
|
4851
4868
|
targetAgents = options.agent;
|
|
4852
4869
|
} else {
|
|
4853
|
-
spinner$2.start("Loading agents
|
|
4870
|
+
spinner$2.start("Loading agents…");
|
|
4854
4871
|
const installedAgents = await detectInstalledAgents();
|
|
4855
4872
|
const totalAgents = Object.keys(agents).length;
|
|
4856
4873
|
spinner$2.stop(`${totalAgents} agents`);
|
|
@@ -4924,7 +4941,7 @@ async function runSync(args, options = {}) {
|
|
|
4924
4941
|
process.exit(0);
|
|
4925
4942
|
}
|
|
4926
4943
|
}
|
|
4927
|
-
spinner$2.start("Syncing skills
|
|
4944
|
+
spinner$2.start("Syncing skills…");
|
|
4928
4945
|
const results = [];
|
|
4929
4946
|
for (const skill of toInstall) for (const agent of targetAgents) {
|
|
4930
4947
|
const result = await installSkillForAgent(skill, agent, {
|
|
@@ -5261,7 +5278,7 @@ async function removeCommand(skillNames, options) {
|
|
|
5261
5278
|
const isGlobal = options.global ?? false;
|
|
5262
5279
|
const cwd = process.cwd();
|
|
5263
5280
|
const spinner$1 = spinner();
|
|
5264
|
-
spinner$1.start("Scanning for installed skills
|
|
5281
|
+
spinner$1.start("Scanning for installed skills…");
|
|
5265
5282
|
const skillNamesSet = /* @__PURE__ */ new Set();
|
|
5266
5283
|
const scanDir = async (dir) => {
|
|
5267
5284
|
try {
|
|
@@ -5335,7 +5352,7 @@ async function removeCommand(skillNames, options) {
|
|
|
5335
5352
|
process.exit(0);
|
|
5336
5353
|
}
|
|
5337
5354
|
}
|
|
5338
|
-
spinner$1.start("Removing skills
|
|
5355
|
+
spinner$1.start("Removing skills…");
|
|
5339
5356
|
const results = [];
|
|
5340
5357
|
for (const skillName of selectedSkills) try {
|
|
5341
5358
|
const canonicalPath = getCanonicalPath(skillName, {
|
|
@@ -5586,7 +5603,7 @@ async function checkAndPromptForDeletions(source, allLockedForSource, lockSkills
|
|
|
5586
5603
|
else {
|
|
5587
5604
|
const confirmed = await confirm({ message: `Would you like to remove the local copies of these deleted skills?` });
|
|
5588
5605
|
if (confirmed && !isCancel(confirmed)) for (const s of deletedSkills) {
|
|
5589
|
-
console.log(`${DIM$1}Removing${RESET$1} ${s}
|
|
5606
|
+
console.log(`${DIM$1}Removing${RESET$1} ${s}…`);
|
|
5590
5607
|
await removeCommand([s], {
|
|
5591
5608
|
yes: true,
|
|
5592
5609
|
global: isGlobal
|
|
@@ -5720,7 +5737,7 @@ async function updateGlobalSkills(options = {}) {
|
|
|
5720
5737
|
console.log();
|
|
5721
5738
|
for (const update of updates) {
|
|
5722
5739
|
const safeName = sanitizeMetadata(update.name);
|
|
5723
|
-
console.log(`${TEXT$1}Updating ${safeName}
|
|
5740
|
+
console.log(`${TEXT$1}Updating ${safeName}…${RESET$1}`);
|
|
5724
5741
|
const installUrl = buildUpdateInstallSource(update.entry);
|
|
5725
5742
|
if (!installUrl) {
|
|
5726
5743
|
failCount++;
|
|
@@ -5801,7 +5818,7 @@ async function updateProjectSkills(options = {}) {
|
|
|
5801
5818
|
if (hasUniversal) targetParts.push("Universal");
|
|
5802
5819
|
targetParts.push(...targetAgentNames);
|
|
5803
5820
|
if (targetParts.length > 0) console.log(`${TEXT$1}Updating for: ${targetParts.join(", ")}${RESET$1}`);
|
|
5804
|
-
console.log(`${TEXT$1}Refreshing ${updatable.length} skill(s)
|
|
5821
|
+
console.log(`${TEXT$1}Refreshing ${updatable.length} skill(s)…${RESET$1}`);
|
|
5805
5822
|
console.log();
|
|
5806
5823
|
const bySource = /* @__PURE__ */ new Map();
|
|
5807
5824
|
for (const skill of updatable) {
|
|
@@ -5846,7 +5863,7 @@ async function updateProjectSkills(options = {}) {
|
|
|
5846
5863
|
const remainingSkills = skillsForSource.filter((s) => !deletedSkills.includes(s.name));
|
|
5847
5864
|
for (const skill of remainingSkills) {
|
|
5848
5865
|
const safeName = sanitizeMetadata(skill.name);
|
|
5849
|
-
console.log(`${TEXT$1}Updating ${safeName}
|
|
5866
|
+
console.log(`${TEXT$1}Updating ${safeName}…${RESET$1}`);
|
|
5850
5867
|
const installUrl = buildLocalUpdateSource(skill.entry);
|
|
5851
5868
|
if (!installUrl) {
|
|
5852
5869
|
failCount++;
|
|
@@ -5900,8 +5917,8 @@ function printLegacyProjectSkills(legacy) {
|
|
|
5900
5917
|
async function runUpdate(args = []) {
|
|
5901
5918
|
const options = parseUpdateOptions(args);
|
|
5902
5919
|
const scope = await resolveUpdateScope(options);
|
|
5903
|
-
if (options.skills) console.log(`${TEXT$1}Updating ${options.skills.join(", ")}
|
|
5904
|
-
else console.log(`${TEXT$1}Checking for skill updates
|
|
5920
|
+
if (options.skills) console.log(`${TEXT$1}Updating ${options.skills.join(", ")}…${RESET$1}`);
|
|
5921
|
+
else console.log(`${TEXT$1}Checking for skill updates…${RESET$1}`);
|
|
5905
5922
|
console.log();
|
|
5906
5923
|
let totalSuccess = 0;
|
|
5907
5924
|
let totalFail = 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skills",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.18",
|
|
4
4
|
"description": "The open agent skills ecosystem",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
"obuild": "^0.4.22",
|
|
131
131
|
"picocolors": "^1.1.1",
|
|
132
132
|
"prettier": "^3.8.1",
|
|
133
|
-
"simple-git": "^3.
|
|
133
|
+
"simple-git": "^3.36.0",
|
|
134
134
|
"typescript": "^5.9.3",
|
|
135
135
|
"vitest": "^4.0.17",
|
|
136
136
|
"xdg-basedir": "^5.1.0"
|