vskill 0.4.24 → 0.5.1

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.
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Skill Studio</title>
7
- <script type="module" crossorigin src="/assets/index-D8vqztpQ.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-CxHCKEhf.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/index-D2UkOol1.css">
9
9
  </head>
10
10
  <body>
@@ -0,0 +1,38 @@
1
+ import type { SkillSearchResult } from "../api/client.js";
2
+ /**
3
+ * Extract `owner/repo` from a GitHub URL.
4
+ */
5
+ export declare function extractBaseRepo(repoUrl: string | undefined): string | null;
6
+ /**
7
+ * Format skill display: `owner/repo/skill-name`.
8
+ * Uses slug fields when available, falls back to extracting from repoUrl/name.
9
+ */
10
+ export declare function formatSkillId(r: SkillSearchResult): string;
11
+ /**
12
+ * Build the verified-skill.com URL for a skill.
13
+ * Uses hierarchical slug fields (owner/repo/skill) when available,
14
+ * falls back to flat name.
15
+ */
16
+ export declare function getSkillUrl(r: SkillSearchResult): string;
17
+ /**
18
+ * Return a colored trust badge string.
19
+ * Prefers certTier (formal certification status shown on website)
20
+ * over trustTier (computed trust score tier).
21
+ */
22
+ export declare function getTrustBadge(certTier: string | undefined, trustTier: string | undefined): string;
23
+ /**
24
+ * Rank search results for display and selection.
25
+ *
26
+ * Sort order:
27
+ * 1. Blocked results at end
28
+ * 2. Exact skillSlug match (case-insensitive) promoted to first among non-blocked
29
+ * 3. Cert tier: CERTIFIED > VERIFIED > other
30
+ * 4. GitHub stars descending
31
+ * 5. Score descending
32
+ */
33
+ export declare function rankSearchResults(results: SkillSearchResult[], exactQuery?: string): SkillSearchResult[];
34
+ /**
35
+ * Format a single search result line for TTY display.
36
+ * Matches the `vskill find` output format.
37
+ */
38
+ export declare function formatResultLine(r: SkillSearchResult): string;
@@ -0,0 +1,121 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Shared skill display helpers — used by both `find` and `add` commands
3
+ // ---------------------------------------------------------------------------
4
+ import { bold, dim, cyan, yellow, green, red, link, formatInstalls } from "./output.js";
5
+ /**
6
+ * Extract `owner/repo` from a GitHub URL.
7
+ */
8
+ export function extractBaseRepo(repoUrl) {
9
+ if (!repoUrl)
10
+ return null;
11
+ const match = repoUrl.match(/([^/]+\/[^/]+?)(?:\/tree\/|\.git|$)/);
12
+ return match ? match[1] : null;
13
+ }
14
+ /**
15
+ * Format skill display: `owner/repo/skill-name`.
16
+ * Uses slug fields when available, falls back to extracting from repoUrl/name.
17
+ */
18
+ export function formatSkillId(r) {
19
+ const displayName = r.skillSlug || r.name.split("/").pop() || r.name;
20
+ const publisher = r.ownerSlug && r.repoSlug
21
+ ? `${r.ownerSlug}/${r.repoSlug}`
22
+ : extractBaseRepo(r.repoUrl);
23
+ return publisher ? `${publisher}/${displayName}` : displayName;
24
+ }
25
+ /**
26
+ * Build the verified-skill.com URL for a skill.
27
+ * Uses hierarchical slug fields (owner/repo/skill) when available,
28
+ * falls back to flat name.
29
+ */
30
+ export function getSkillUrl(r) {
31
+ if (r.ownerSlug && r.repoSlug && r.skillSlug) {
32
+ return `https://verified-skill.com/skills/${encodeURIComponent(r.ownerSlug)}/${encodeURIComponent(r.repoSlug)}/${encodeURIComponent(r.skillSlug)}`;
33
+ }
34
+ const parts = r.name.split("/");
35
+ if (parts.length === 3) {
36
+ return `https://verified-skill.com/skills/${parts.map(encodeURIComponent).join("/")}`;
37
+ }
38
+ // Fallback: derive owner/repo from repoUrl + use flat name as skill slug
39
+ const base = extractBaseRepo(r.repoUrl);
40
+ if (base) {
41
+ const skillName = r.name.split("/").pop() || r.name;
42
+ return `https://verified-skill.com/skills/${base.split("/").map(encodeURIComponent).join("/")}/${encodeURIComponent(skillName)}`;
43
+ }
44
+ return `https://verified-skill.com/skills/${encodeURIComponent(r.name)}`;
45
+ }
46
+ /**
47
+ * Return a colored trust badge string.
48
+ * Prefers certTier (formal certification status shown on website)
49
+ * over trustTier (computed trust score tier).
50
+ */
51
+ export function getTrustBadge(certTier, trustTier) {
52
+ // Prefer certTier — matches what the website displays
53
+ if (certTier === "CERTIFIED")
54
+ return green("\u2713 certified");
55
+ if (certTier === "VERIFIED")
56
+ return cyan("\u2713 verified");
57
+ // Fall back to trustTier
58
+ switch (trustTier) {
59
+ case "T4": return green("\u2713 certified");
60
+ case "T3": return cyan("\u2713 verified");
61
+ case "T2": return yellow("~ pending");
62
+ case "T1": return dim("~ pending");
63
+ default: return "";
64
+ }
65
+ }
66
+ /**
67
+ * Rank search results for display and selection.
68
+ *
69
+ * Sort order:
70
+ * 1. Blocked results at end
71
+ * 2. Exact skillSlug match (case-insensitive) promoted to first among non-blocked
72
+ * 3. Cert tier: CERTIFIED > VERIFIED > other
73
+ * 4. GitHub stars descending
74
+ * 5. Score descending
75
+ */
76
+ export function rankSearchResults(results, exactQuery) {
77
+ const sorted = [...results].sort((a, b) => {
78
+ // Blocked always at end
79
+ if (a.isBlocked && !b.isBlocked)
80
+ return 1;
81
+ if (!a.isBlocked && b.isBlocked)
82
+ return -1;
83
+ const certRank = (t) => t === "CERTIFIED" ? 0 : t === "VERIFIED" ? 1 : 2;
84
+ const certDiff = certRank(a.certTier) - certRank(b.certTier);
85
+ if (certDiff !== 0)
86
+ return certDiff;
87
+ const starDiff = (b.githubStars ?? 0) - (a.githubStars ?? 0);
88
+ if (starDiff !== 0)
89
+ return starDiff;
90
+ return (b.score ?? 0) - (a.score ?? 0);
91
+ });
92
+ // Promote exact skillSlug match to first position among non-blocked
93
+ if (exactQuery) {
94
+ const lowerQuery = exactQuery.toLowerCase();
95
+ const idx = sorted.findIndex((r) => !r.isBlocked && r.skillSlug?.toLowerCase() === lowerQuery);
96
+ if (idx > 0) {
97
+ const [match] = sorted.splice(idx, 1);
98
+ sorted.unshift(match);
99
+ }
100
+ }
101
+ return sorted;
102
+ }
103
+ /**
104
+ * Format a single search result line for TTY display.
105
+ * Matches the `vskill find` output format.
106
+ */
107
+ export function formatResultLine(r) {
108
+ const label = formatSkillId(r);
109
+ const url = getSkillUrl(r);
110
+ if (r.isBlocked) {
111
+ const parts = [r.severity, r.threatType].filter(Boolean);
112
+ const threatInfo = parts.length > 0 ? parts.join(" | ") : "blocked";
113
+ return `${red(bold(label))} ${red("BLOCKED")} ${red(threatInfo)}\n ${link(url, cyan(url))}`;
114
+ }
115
+ const stars = r.githubStars ?? 0;
116
+ const starsStr = `\u2605${formatInstalls(stars)}`;
117
+ const badge = getTrustBadge(r.certTier, r.trustTier);
118
+ const pluginBadge = r.pluginName ? dim(` [${r.pluginName}]`) : "";
119
+ return `${bold(label)}${pluginBadge} ${dim(starsStr)}${badge ? " " + badge : ""}\n ${link(url, cyan(url))}`;
120
+ }
121
+ //# sourceMappingURL=skill-display.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-display.js","sourceRoot":"","sources":["../../src/utils/skill-display.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vskill",
3
- "version": "0.4.24",
3
+ "version": "0.5.1",
4
4
  "type": "module",
5
5
  "description": "Secure multi-platform AI skill installer — scan before you install",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- export {};
@@ -1,35 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { classifyError } from "../error-classifier.js";
3
- describe("classifyError", () => {
4
- describe("model_not_found (must take priority over provider_unavailable)", () => {
5
- it("classifies Ollama 'model not found' as model_not_found", () => {
6
- const err = new Error('Ollama model "mistral:7b" not found. Pull it first:\n ollama pull mistral:7b');
7
- const result = classifyError(err, "ollama");
8
- expect(result.category).toBe("model_not_found");
9
- expect(result.title).toBe("Model Not Found");
10
- expect(result.hint).toContain("ollama pull");
11
- expect(result.retryable).toBe(false);
12
- });
13
- it("classifies generic 'model not found' errors", () => {
14
- const err = new Error("model xyz not found");
15
- const result = classifyError(err, "ollama");
16
- expect(result.category).toBe("model_not_found");
17
- });
18
- it("does not classify 'command not found' as model_not_found", () => {
19
- const err = new Error("claude: command not found");
20
- const result = classifyError(err, "claude-cli");
21
- expect(result.category).toBe("provider_unavailable");
22
- });
23
- });
24
- describe("provider_unavailable still works for non-model errors", () => {
25
- it("classifies ECONNREFUSED as provider_unavailable", () => {
26
- const result = classifyError(new Error("connect ECONNREFUSED 127.0.0.1:11434"), "ollama");
27
- expect(result.category).toBe("provider_unavailable");
28
- });
29
- it("classifies ENOENT as provider_unavailable", () => {
30
- const result = classifyError(new Error("spawn claude ENOENT"), "claude-cli");
31
- expect(result.category).toBe("provider_unavailable");
32
- });
33
- });
34
- });
35
- //# sourceMappingURL=error-classifier.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"error-classifier.test.js","sourceRoot":"","sources":["../../../src/eval-server/__tests__/error-classifier.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,QAAQ,CAAC,gEAAgE,EAAE,GAAG,EAAE;QAC9E,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;YAChE,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,+EAA+E,CAAC,CAAC;YACvG,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAChD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC7C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YAC7C,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACrD,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;YAC7C,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;YAClE,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YACnD,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;YAChD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,uDAAuD,EAAE,GAAG,EAAE;QACrE,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACzD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,KAAK,CAAC,sCAAsC,CAAC,EAAE,QAAQ,CAAC,CAAC;YAC1F,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,EAAE,YAAY,CAAC,CAAC;YAC7E,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}