skills 1.5.26 → 1.6.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 +12 -1
- package/dist/cli.mjs +46 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,13 @@ The CLI for the open agent skills ecosystem.
|
|
|
6
6
|
Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [75 more](#supported-agents).
|
|
7
7
|
<!-- agent-list:end -->
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
<p>
|
|
10
|
+
<a href="https://vercel.com/labs#labs-products"><img alt="Vercel Labs Product" src="https://img.shields.io/badge/LABS-PRODUCT-0a0a0a.svg?style=for-the-badge&logo=Vercel&labelColor=000000" height="28"></a>
|
|
11
|
+
<a href="https://www.npmjs.com/package/skills"><img alt="npm version: skills" src="https://img.shields.io/npm/v/skills.svg?style=for-the-badge&labelColor=000000" height="28"></a>
|
|
12
|
+
<a href="https://github.com/vercel-labs/skills/blob/main/LICENSE"><img alt="License: MIT" src="https://img.shields.io/github/license/vercel-labs/skills.svg?style=for-the-badge&labelColor=000000" height="28"></a>
|
|
13
|
+
<a href="https://www.npmjs.com/package/skills"><img alt="npm downloads per month: skills" src="https://img.shields.io/npm/dm/skills.svg?style=for-the-badge&labelColor=000000&label=npm%20downloads" height="28"></a>
|
|
14
|
+
<a href="https://skills.sh/vercel-labs/skills"><img alt="skills.sh" src="https://skills.sh/b/vercel-labs/skills?style=for-the-badge" height="28"></a>
|
|
15
|
+
</p>
|
|
10
16
|
|
|
11
17
|
## Install a Skill
|
|
12
18
|
|
|
@@ -40,6 +46,10 @@ npx skills add https://github.com/vercel-labs/agent-skills/tree/main/skills/web-
|
|
|
40
46
|
# GitLab URL
|
|
41
47
|
npx skills add https://gitlab.com/org/repo
|
|
42
48
|
|
|
49
|
+
# Azure Repos (Azure DevOps Services or Server)
|
|
50
|
+
npx skills add https://dev.azure.com/org/project/_git/repo
|
|
51
|
+
npx skills add https://dev.azure.com/org/project/_git/repo?path=/skills/web-design&version=GBmain
|
|
52
|
+
|
|
43
53
|
# Any git URL
|
|
44
54
|
npx skills add git@github.com:vercel-labs/agent-skills.git
|
|
45
55
|
|
|
@@ -61,6 +71,7 @@ npx skills add ssh://git@git.example.com/acme/private-skills.git
|
|
|
61
71
|
|
|
62
72
|
# HTTPS on any Git host (uses your configured Git credential helper)
|
|
63
73
|
npx skills add https://git.example.com/acme/private-skills.git
|
|
74
|
+
npx skills add https://dev.azure.com/org/project/_git/private-skills
|
|
64
75
|
```
|
|
65
76
|
|
|
66
77
|
For GitHub HTTPS and shorthand sources, `skills` first uses normal Git credentials. If that fails and GitHub CLI is authenticated, it tries `gh repo clone`, followed by SSH. It does not execute `gh auth token` or copy the stored GitHub CLI credential into the Node.js process.
|
package/dist/cli.mjs
CHANGED
|
@@ -91,6 +91,46 @@ function sanitizeSubpath(subpath) {
|
|
|
91
91
|
for (const segment of segments) if (segment === "..") throw new Error(`Unsafe subpath: "${subpath}" contains path traversal segments. Subpaths must not contain ".." components.`);
|
|
92
92
|
return subpath;
|
|
93
93
|
}
|
|
94
|
+
function azureReposVersionToRef(version) {
|
|
95
|
+
if (!version) return;
|
|
96
|
+
return /^(?:GB|GT)(.+)$/i.exec(version)?.[1] || void 0;
|
|
97
|
+
}
|
|
98
|
+
function parseAzureReposSource(input, fragmentRef, fragmentSkillFilter) {
|
|
99
|
+
if (!input.startsWith("http://") && !input.startsWith("https://")) return null;
|
|
100
|
+
let parsed;
|
|
101
|
+
try {
|
|
102
|
+
parsed = new URL(input);
|
|
103
|
+
} catch {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
const segments = parsed.pathname.split("/").filter(Boolean);
|
|
107
|
+
const gitIndex = segments.indexOf("_git");
|
|
108
|
+
if (gitIndex < 0 || gitIndex === segments.length - 1) return null;
|
|
109
|
+
const repo = segments[gitIndex + 1].replace(/\.git$/, "");
|
|
110
|
+
if (!repo) return null;
|
|
111
|
+
const clonePath = "/" + [
|
|
112
|
+
...segments.slice(0, gitIndex),
|
|
113
|
+
"_git",
|
|
114
|
+
repo
|
|
115
|
+
].map((segment) => {
|
|
116
|
+
try {
|
|
117
|
+
return encodeURIComponent(decodeURIComponent(segment));
|
|
118
|
+
} catch {
|
|
119
|
+
return encodeURIComponent(segment);
|
|
120
|
+
}
|
|
121
|
+
}).join("/");
|
|
122
|
+
const cloneUrl = `${parsed.protocol}//${parsed.host}${clonePath}`;
|
|
123
|
+
const ref = azureReposVersionToRef(parsed.searchParams.get("version")) || fragmentRef;
|
|
124
|
+
const pathParam = parsed.searchParams.get("path");
|
|
125
|
+
const subpath = pathParam ? sanitizeSubpath(pathParam.replace(/^\/+/, "")) : void 0;
|
|
126
|
+
return {
|
|
127
|
+
type: "git",
|
|
128
|
+
url: cloneUrl,
|
|
129
|
+
...ref ? { ref } : {},
|
|
130
|
+
...subpath ? { subpath } : {},
|
|
131
|
+
...fragmentSkillFilter ? { skillFilter: fragmentSkillFilter } : {}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
94
134
|
function isLocalPath(input) {
|
|
95
135
|
return isAbsolute(input) || input.startsWith("./") || input.startsWith("../") || input === "." || input === ".." || /^[a-zA-Z]:[/\\]/.test(input);
|
|
96
136
|
}
|
|
@@ -113,6 +153,9 @@ function looksLikeGitSource(input) {
|
|
|
113
153
|
const pathname = parsed.pathname;
|
|
114
154
|
if (isGitHubHost(parsed.host)) return /^\/[^/]+\/[^/]+(?:\.git)?(?:\/tree\/[^/]+(?:\/.*)?)?\/?$/.test(pathname);
|
|
115
155
|
if (parsed.hostname === "gitlab.com") return /^\/.+?\/[^/]+(?:\.git)?(?:\/-\/tree\/[^/]+(?:\/.*)?)?\/?$/.test(pathname);
|
|
156
|
+
const azureSegments = pathname.split("/").filter(Boolean);
|
|
157
|
+
const azureGitIndex = azureSegments.indexOf("_git");
|
|
158
|
+
if (azureGitIndex >= 0 && azureGitIndex < azureSegments.length - 1) return true;
|
|
116
159
|
} catch {}
|
|
117
160
|
if (/^https?:\/\/.+\.git(?:$|[/?])/i.test(input)) return true;
|
|
118
161
|
return !input.includes(":") && !input.startsWith(".") && !input.startsWith("/") && /^([^/]+)\/([^/]+)(?:\/(.+)|@(.+))?$/.test(input);
|
|
@@ -245,6 +288,8 @@ function parseSource(input) {
|
|
|
245
288
|
...fragmentRef ? { ref: fragmentRef } : {}
|
|
246
289
|
};
|
|
247
290
|
}
|
|
291
|
+
const azureRepos = parseAzureReposSource(input, fragmentRef, fragmentSkillFilter);
|
|
292
|
+
if (azureRepos) return azureRepos;
|
|
248
293
|
const githubHost = getGitHubHost();
|
|
249
294
|
const shorthandSourceType = githubHost === "github.com" ? "github" : "git";
|
|
250
295
|
const atSkillMatch = input.match(/^([^/]+)\/([^/@]+)@(.+)$/);
|
|
@@ -4124,7 +4169,7 @@ async function tryBlobInstall(ownerRepo, options = {}) {
|
|
|
4124
4169
|
tree
|
|
4125
4170
|
};
|
|
4126
4171
|
}
|
|
4127
|
-
var version$1 = "1.
|
|
4172
|
+
var version$1 = "1.6.0";
|
|
4128
4173
|
const isCancelled$1 = (value) => typeof value === "symbol";
|
|
4129
4174
|
const EVE_AGENT_LABEL = "eve agent";
|
|
4130
4175
|
async function isSourcePrivate(source) {
|