vskill 0.2.80 → 0.2.82
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/commands/eval/__tests__/generate-all.test.js +2 -2
- package/dist/commands/eval/__tests__/generate-all.test.js.map +1 -1
- package/dist/commands/eval/__tests__/init.test.js +1 -1
- package/dist/commands/eval/__tests__/init.test.js.map +1 -1
- package/dist/commands/eval/__tests__/run.test.js +8 -8
- package/dist/commands/eval/__tests__/run.test.js.map +1 -1
- package/dist/eval-server/api-routes.js +35 -20
- package/dist/eval-server/api-routes.js.map +1 -1
- package/dist/eval-server/benchmark-runner.js +2 -2
- package/dist/eval-server/benchmark-runner.js.map +1 -1
- package/dist/eval-server/eval-server.js +2 -0
- package/dist/eval-server/eval-server.js.map +1 -1
- package/dist/eval-server/improve-routes.js +16 -6
- package/dist/eval-server/improve-routes.js.map +1 -1
- package/dist/eval-server/skill-create-routes.d.ts +2 -0
- package/dist/eval-server/skill-create-routes.js +239 -0
- package/dist/eval-server/skill-create-routes.js.map +1 -0
- package/dist/eval-server/sse-helpers.d.ts +6 -0
- package/dist/eval-server/sse-helpers.js +22 -0
- package/dist/eval-server/sse-helpers.js.map +1 -1
- package/dist/eval-ui/assets/index-BN2q4IPq.js +85 -0
- package/dist/eval-ui/assets/index-DHuFS9ka.css +1 -0
- package/dist/eval-ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/eval-ui/assets/index-BnKAmjEZ.js +0 -73
- package/dist/eval-ui/assets/index-CcHgd5W_.css +0 -1
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// skill-create-routes.ts -- Skill creation & project layout detection
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
import { existsSync, readdirSync, mkdirSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { join, basename } from "node:path";
|
|
6
|
+
import { homedir } from "node:os";
|
|
7
|
+
import { sendJson, readBody } from "./router.js";
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Helpers
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
const EXCLUDE_DIRS = new Set([
|
|
12
|
+
"skills", "plugins", "node_modules", ".git", ".specweave",
|
|
13
|
+
"dist", "evals", ".claude", ".cursor", ".agents", "coverage",
|
|
14
|
+
]);
|
|
15
|
+
/** List subdirs of a skills/ dir that contain SKILL.md */
|
|
16
|
+
function listSkillDirs(skillsDir) {
|
|
17
|
+
if (!existsSync(skillsDir))
|
|
18
|
+
return [];
|
|
19
|
+
try {
|
|
20
|
+
return readdirSync(skillsDir, { withFileTypes: true })
|
|
21
|
+
.filter((d) => d.isDirectory() && existsSync(join(skillsDir, d.name, "SKILL.md")))
|
|
22
|
+
.map((d) => d.name);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** Detect project layout — mirrors scanSkills() logic from skill-scanner.ts */
|
|
29
|
+
function detectProjectLayout(root) {
|
|
30
|
+
const layouts = [];
|
|
31
|
+
const allSkills = [];
|
|
32
|
+
// Layout 4: Self — root IS the skill
|
|
33
|
+
if (existsSync(join(root, "SKILL.md"))) {
|
|
34
|
+
layouts.push({
|
|
35
|
+
layout: 4,
|
|
36
|
+
label: "Self (root is the skill)",
|
|
37
|
+
pathTemplate: `${root}/SKILL.md`,
|
|
38
|
+
existingPlugins: [],
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
// Layout 3: Root skills/ directory
|
|
42
|
+
const rootSkillsDir = join(root, "skills");
|
|
43
|
+
if (existsSync(rootSkillsDir)) {
|
|
44
|
+
const skills = listSkillDirs(rootSkillsDir);
|
|
45
|
+
const pluginName = basename(root) || "default";
|
|
46
|
+
layouts.push({
|
|
47
|
+
layout: 3,
|
|
48
|
+
label: "Root skills/",
|
|
49
|
+
pathTemplate: "{root}/skills/{skill}/",
|
|
50
|
+
existingPlugins: [pluginName],
|
|
51
|
+
});
|
|
52
|
+
for (const s of skills)
|
|
53
|
+
allSkills.push({ plugin: pluginName, skill: s });
|
|
54
|
+
}
|
|
55
|
+
// Layout 1: Direct plugin dirs — {root}/{plugin}/skills/{skill}/
|
|
56
|
+
const directPlugins = [];
|
|
57
|
+
try {
|
|
58
|
+
const entries = readdirSync(root, { withFileTypes: true })
|
|
59
|
+
.filter((d) => d.isDirectory() && !EXCLUDE_DIRS.has(d.name) && !d.name.startsWith("."));
|
|
60
|
+
for (const entry of entries) {
|
|
61
|
+
const skillsPath = join(root, entry.name, "skills");
|
|
62
|
+
if (existsSync(skillsPath)) {
|
|
63
|
+
directPlugins.push(entry.name);
|
|
64
|
+
const skills = listSkillDirs(skillsPath);
|
|
65
|
+
for (const s of skills)
|
|
66
|
+
allSkills.push({ plugin: entry.name, skill: s });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch { /* ignore */ }
|
|
71
|
+
if (directPlugins.length > 0) {
|
|
72
|
+
layouts.push({
|
|
73
|
+
layout: 1,
|
|
74
|
+
label: "Direct plugins",
|
|
75
|
+
pathTemplate: "{root}/{plugin}/skills/{skill}/",
|
|
76
|
+
existingPlugins: directPlugins,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
// Layout 2: Nested plugins/ dir — {root}/plugins/{plugin}/skills/{skill}/
|
|
80
|
+
const pluginsDir = join(root, "plugins");
|
|
81
|
+
if (existsSync(pluginsDir)) {
|
|
82
|
+
const nestedPlugins = [];
|
|
83
|
+
try {
|
|
84
|
+
const entries = readdirSync(pluginsDir, { withFileTypes: true })
|
|
85
|
+
.filter((d) => d.isDirectory());
|
|
86
|
+
for (const entry of entries) {
|
|
87
|
+
const skillsPath = join(pluginsDir, entry.name, "skills");
|
|
88
|
+
if (existsSync(skillsPath)) {
|
|
89
|
+
nestedPlugins.push(entry.name);
|
|
90
|
+
const skills = listSkillDirs(skillsPath);
|
|
91
|
+
for (const s of skills)
|
|
92
|
+
allSkills.push({ plugin: entry.name, skill: s });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch { /* ignore */ }
|
|
97
|
+
if (nestedPlugins.length > 0) {
|
|
98
|
+
layouts.push({
|
|
99
|
+
layout: 2,
|
|
100
|
+
label: "Nested plugins/",
|
|
101
|
+
pathTemplate: "{root}/plugins/{plugin}/skills/{skill}/",
|
|
102
|
+
existingPlugins: nestedPlugins,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Suggestion priority: Layout 2 > Layout 1 > Layout 3
|
|
107
|
+
let suggestedLayout = 3;
|
|
108
|
+
if (layouts.find((l) => l.layout === 2))
|
|
109
|
+
suggestedLayout = 2;
|
|
110
|
+
else if (layouts.find((l) => l.layout === 1))
|
|
111
|
+
suggestedLayout = 1;
|
|
112
|
+
return { root, detectedLayouts: layouts, suggestedLayout, existingSkills: allSkills };
|
|
113
|
+
}
|
|
114
|
+
/** Build SKILL.md content from form fields */
|
|
115
|
+
function buildSkillMd(data) {
|
|
116
|
+
const lines = ["---"];
|
|
117
|
+
// Description — always quote to handle special chars
|
|
118
|
+
lines.push(`description: "${data.description.replace(/"/g, '\\"')}"`);
|
|
119
|
+
if (data.allowedTools?.trim()) {
|
|
120
|
+
lines.push(`allowed-tools: ${data.allowedTools.trim()}`);
|
|
121
|
+
}
|
|
122
|
+
if (data.model) {
|
|
123
|
+
lines.push(`model: ${data.model}`);
|
|
124
|
+
}
|
|
125
|
+
lines.push("---");
|
|
126
|
+
lines.push("");
|
|
127
|
+
if (data.body.trim()) {
|
|
128
|
+
lines.push(data.body.trim());
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
lines.push(`# /${data.name}`);
|
|
132
|
+
lines.push("");
|
|
133
|
+
lines.push("You are a helpful assistant. Describe what this skill does.");
|
|
134
|
+
}
|
|
135
|
+
return lines.join("\n") + "\n";
|
|
136
|
+
}
|
|
137
|
+
/** Compute target directory for a new skill based on layout */
|
|
138
|
+
function computeSkillDir(root, layout, plugin, name) {
|
|
139
|
+
switch (layout) {
|
|
140
|
+
case 1: return join(root, plugin, "skills", name);
|
|
141
|
+
case 2: return join(root, "plugins", plugin, "skills", name);
|
|
142
|
+
case 3: return join(root, "skills", name);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/** Check if skill-creator skill is installed */
|
|
146
|
+
function checkSkillCreatorInstalled() {
|
|
147
|
+
const home = homedir();
|
|
148
|
+
const candidates = [
|
|
149
|
+
join(home, ".claude", "skills", "skill-creator"),
|
|
150
|
+
join(home, ".claude", "plugins", "cache", "skill-creator"),
|
|
151
|
+
];
|
|
152
|
+
for (const dir of candidates) {
|
|
153
|
+
if (existsSync(dir))
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
// Also check for plugin with nested structure
|
|
157
|
+
try {
|
|
158
|
+
const pluginsCache = join(home, ".claude", "plugins", "cache");
|
|
159
|
+
if (existsSync(pluginsCache)) {
|
|
160
|
+
const entries = readdirSync(pluginsCache, { withFileTypes: true });
|
|
161
|
+
for (const entry of entries) {
|
|
162
|
+
if (entry.isDirectory() && entry.name.includes("skill-creator"))
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch { /* ignore */ }
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
// Route registration
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
export function registerSkillCreateRoutes(router, root) {
|
|
174
|
+
// GET /api/project-layout — detect project layout and suggest placement
|
|
175
|
+
router.get("/api/project-layout", async (_req, res) => {
|
|
176
|
+
try {
|
|
177
|
+
const layout = detectProjectLayout(root);
|
|
178
|
+
sendJson(res, layout, 200, _req);
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
sendJson(res, { error: err.message }, 500, _req);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
// POST /api/skills/create — create a new skill
|
|
185
|
+
router.post("/api/skills/create", async (req, res) => {
|
|
186
|
+
const body = (await readBody(req));
|
|
187
|
+
// Validate name
|
|
188
|
+
if (!body.name || !/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(body.name)) {
|
|
189
|
+
sendJson(res, { error: "Name must be kebab-case (lowercase letters, numbers, hyphens)" }, 400, req);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (!body.description?.trim()) {
|
|
193
|
+
sendJson(res, { error: "Description is required" }, 400, req);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (!body.layout || ![1, 2, 3].includes(body.layout)) {
|
|
197
|
+
sendJson(res, { error: "Layout must be 1, 2, or 3" }, 400, req);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (body.layout !== 3 && !body.plugin?.trim()) {
|
|
201
|
+
sendJson(res, { error: "Plugin name is required for this layout" }, 400, req);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const targetDir = computeSkillDir(root, body.layout, body.plugin || "", body.name);
|
|
205
|
+
// Check if already exists
|
|
206
|
+
if (existsSync(join(targetDir, "SKILL.md"))) {
|
|
207
|
+
sendJson(res, { error: `Skill already exists at ${targetDir}` }, 409, req);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
try {
|
|
211
|
+
// Create directories
|
|
212
|
+
mkdirSync(targetDir, { recursive: true });
|
|
213
|
+
mkdirSync(join(targetDir, "evals"), { recursive: true });
|
|
214
|
+
// Write SKILL.md
|
|
215
|
+
const content = buildSkillMd(body);
|
|
216
|
+
const skillMdPath = join(targetDir, "SKILL.md");
|
|
217
|
+
writeFileSync(skillMdPath, content, "utf-8");
|
|
218
|
+
sendJson(res, {
|
|
219
|
+
ok: true,
|
|
220
|
+
plugin: body.layout === 3 ? (basename(root) || "default") : body.plugin,
|
|
221
|
+
skill: body.name,
|
|
222
|
+
dir: targetDir,
|
|
223
|
+
skillMdPath,
|
|
224
|
+
}, 201, req);
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
sendJson(res, { error: `Failed to create skill: ${err.message}` }, 500, req);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
// GET /api/skill-creator-status — check if skill-creator is installed
|
|
231
|
+
router.get("/api/skill-creator-status", async (_req, res) => {
|
|
232
|
+
const installed = checkSkillCreatorInstalled();
|
|
233
|
+
sendJson(res, {
|
|
234
|
+
installed,
|
|
235
|
+
installCommand: "vskill install skill-creator:skill-creator",
|
|
236
|
+
}, 200, _req);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=skill-create-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-create-routes.js","sourceRoot":"","sources":["../../src/eval-server/skill-create-routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,3 +2,9 @@ import type * as http from "node:http";
|
|
|
2
2
|
export declare function initSSE(res: http.ServerResponse, req?: http.IncomingMessage): void;
|
|
3
3
|
export declare function sendSSE(res: http.ServerResponse, event: string, data: unknown): void;
|
|
4
4
|
export declare function sendSSEDone(res: http.ServerResponse, data: unknown): void;
|
|
5
|
+
/**
|
|
6
|
+
* Wrap an async operation with periodic heartbeat SSE events.
|
|
7
|
+
* Emits a progress event every `intervalMs` with elapsed time so the
|
|
8
|
+
* frontend knows the system is still alive during long LLM calls.
|
|
9
|
+
*/
|
|
10
|
+
export declare function withHeartbeat<T>(res: http.ServerResponse, evalId: number, phase: string, messagePrefix: string, fn: () => Promise<T>, intervalMs?: number): Promise<T>;
|
|
@@ -21,4 +21,26 @@ export function sendSSEDone(res, data) {
|
|
|
21
21
|
sendSSE(res, "done", data);
|
|
22
22
|
res.end();
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Wrap an async operation with periodic heartbeat SSE events.
|
|
26
|
+
* Emits a progress event every `intervalMs` with elapsed time so the
|
|
27
|
+
* frontend knows the system is still alive during long LLM calls.
|
|
28
|
+
*/
|
|
29
|
+
export async function withHeartbeat(res, evalId, phase, messagePrefix, fn, intervalMs = 3000) {
|
|
30
|
+
const start = Date.now();
|
|
31
|
+
const timer = setInterval(() => {
|
|
32
|
+
const elapsed = Math.round((Date.now() - start) / 1000);
|
|
33
|
+
sendSSE(res, "progress", {
|
|
34
|
+
eval_id: evalId,
|
|
35
|
+
phase,
|
|
36
|
+
message: `${messagePrefix} (${elapsed}s)`,
|
|
37
|
+
});
|
|
38
|
+
}, intervalMs);
|
|
39
|
+
try {
|
|
40
|
+
return await fn();
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
clearInterval(timer);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
24
46
|
//# sourceMappingURL=sse-helpers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse-helpers.js","sourceRoot":"","sources":["../../src/eval-server/sse-helpers.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,iDAAiD;AACjD,8EAA8E;AAI9E,MAAM,UAAU,OAAO,CACrB,GAAwB,EACxB,GAA0B;IAE1B,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,mBAAmB;QACnC,eAAe,EAAE,UAAU;QAC3B,UAAU,EAAE,YAAY;QACxB,mBAAmB,EAAE,IAAI;KAC1B,CAAC;IACF,MAAM,MAAM,GAAG,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC;IACpC,IAAI,MAAM,IAAI,8CAA8C,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1E,OAAO,CAAC,6BAA6B,CAAC,GAAG,MAAM,CAAC;IAClD,CAAC;IACD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,OAAO,CACrB,GAAwB,EACxB,KAAa,EACb,IAAa;IAEb,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,WAAW,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,GAAwB,EACxB,IAAa;IAEb,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC3B,GAAG,CAAC,GAAG,EAAE,CAAC;AACZ,CAAC"}
|
|
1
|
+
{"version":3,"file":"sse-helpers.js","sourceRoot":"","sources":["../../src/eval-server/sse-helpers.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,iDAAiD;AACjD,8EAA8E;AAI9E,MAAM,UAAU,OAAO,CACrB,GAAwB,EACxB,GAA0B;IAE1B,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,mBAAmB;QACnC,eAAe,EAAE,UAAU;QAC3B,UAAU,EAAE,YAAY;QACxB,mBAAmB,EAAE,IAAI;KAC1B,CAAC;IACF,MAAM,MAAM,GAAG,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC;IACpC,IAAI,MAAM,IAAI,8CAA8C,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1E,OAAO,CAAC,6BAA6B,CAAC,GAAG,MAAM,CAAC;IAClD,CAAC;IACD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,OAAO,CACrB,GAAwB,EACxB,KAAa,EACb,IAAa;IAEb,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,WAAW,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,GAAwB,EACxB,IAAa;IAEb,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC3B,GAAG,CAAC,GAAG,EAAE,CAAC;AACZ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAwB,EACxB,MAAc,EACd,KAAa,EACb,aAAqB,EACrB,EAAoB,EACpB,UAAU,GAAG,IAAI;IAEjB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,EAAE,UAAU,EAAE;YACvB,OAAO,EAAE,MAAM;YACf,KAAK;YACL,OAAO,EAAE,GAAG,aAAa,KAAK,OAAO,IAAI;SAC1C,CAAC,CAAC;IACL,CAAC,EAAE,UAAU,CAAC,CAAC;IAEf,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,aAAa,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
|