|
1 | 1 | import { test } from "node:test"; |
2 | 2 | import assert from "node:assert/strict"; |
3 | | -import { readdirSync, readFileSync } from "node:fs"; |
4 | | -import { join } from "node:path"; |
5 | | -import { pkgPath } from "../src/core/paths.ts"; |
| 3 | +import { readFileSync } from "node:fs"; |
6 | 4 |
|
7 | | -/** |
8 | | - * Skills are prose we ship into other people's agents, so the usual tests say |
9 | | - * nothing about them. This one encodes a single lesson from a real regression: |
10 | | - * a skill offered `--js-render --premium-proxy` as an ordinary example, and the |
11 | | - * agent then recommended that pair for routine work. It is 25 credits per |
12 | | - * request against 1, and `mode=auto` reaches the same place only when the |
13 | | - * target needs it. |
14 | | - * |
15 | | - * The rule is narrow on purpose. It fires on a runnable example that turns both |
16 | | - * on with no price attached. A synopsis listing optional flags in brackets is |
17 | | - * documentation, not a recommendation, and prose about escalating after a |
18 | | - * failure is the behaviour we want. |
19 | | - */ |
20 | | -const SKILLS_DIR = pkgPath("skills"); |
21 | | -const COSTLY_PAIR = /--js-render/.source; |
22 | | -const skillFiles = readdirSync(SKILLS_DIR, { withFileTypes: true }) |
23 | | - .filter((e) => e.isDirectory()) |
24 | | - .map((e) => ({ name: e.name, path: join(SKILLS_DIR, e.name, "SKILL.md") })); |
25 | | - |
26 | | -/** A runnable example, as opposed to a synopsis with `[--optional]` flags. */ |
27 | | -function isRunnableExample(line: string): boolean { |
28 | | - return /\bzenrows\s/.test(line) && !/\[--/.test(line); |
29 | | -} |
30 | | - |
31 | | -function enablesBothEscalations(line: string): boolean { |
32 | | - return /--js-render\b/.test(line) && /--premium-proxy\b/.test(line); |
33 | | -} |
34 | | - |
35 | | -function statesCost(line: string): boolean { |
36 | | - return /\bcredits?\b|\bcosts?\b|\b25\b/i.test(line); |
37 | | -} |
38 | | - |
39 | | -test("every skill directory ships a SKILL.md", () => { |
40 | | - assert.ok(skillFiles.length > 0, "skills/ is not empty"); |
41 | | - for (const s of skillFiles) { |
42 | | - assert.doesNotThrow(() => readFileSync(s.path, "utf8"), `${s.name} has a SKILL.md`); |
43 | | - } |
44 | | -}); |
45 | | - |
46 | | -test("a runnable example that enables both escalations states its cost", () => { |
47 | | - const offenders: string[] = []; |
48 | | - for (const s of skillFiles) { |
49 | | - readFileSync(s.path, "utf8").split("\n").forEach((line, i) => { |
50 | | - if (isRunnableExample(line) && enablesBothEscalations(line) && !statesCost(line)) { |
51 | | - offenders.push(`${s.name}/SKILL.md:${i + 1}: ${line.trim()}`); |
52 | | - } |
53 | | - }); |
54 | | - } |
55 | | - assert.deepEqual( |
56 | | - offenders, |
57 | | - [], |
58 | | - `--js-render with --premium-proxy is 25 credits per request. An example that turns both on must say so on the same line, or use mode=auto instead:\n${offenders.join("\n")}`, |
59 | | - ); |
60 | | -}); |
61 | | - |
62 | | -test("skills that show an escalation also point at auto mode somewhere", () => { |
63 | | - for (const s of skillFiles) { |
64 | | - const text = readFileSync(s.path, "utf8"); |
65 | | - if (!new RegExp(COSTLY_PAIR).test(text)) continue; |
66 | | - assert.match( |
67 | | - text, |
68 | | - /mode=auto|auto mode|Adaptive Stealth/i, |
69 | | - `${s.name}/SKILL.md shows an escalation flag but never mentions auto mode`, |
70 | | - ); |
71 | | - } |
| 5 | +test("SKILL documents auto-signup and claim", () => { |
| 6 | + const skill = readFileSync("skills/zenrows/SKILL.md", "utf8"); |
| 7 | + assert.match(skill, /auto[- ]?signup|automatically create/i); |
| 8 | + assert.match(skill, /claim/i); |
| 9 | + assert.match(skill, /--no-signup/); |
72 | 10 | }); |
0 commit comments