agent-skill-evals 0.1.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.
@@ -0,0 +1,113 @@
1
+ import { t as AssertionEntryError } from "../assertion-entries-CfmNt-fp.mjs";
2
+ //#region src/skill-checks/skill.d.ts
3
+ interface SkillFrontmatter {
4
+ name?: string;
5
+ description?: string;
6
+ [key: string]: unknown;
7
+ }
8
+ interface ParsedSkill {
9
+ /** Absolute path to the SKILL.md file. */
10
+ skillMdPath: string;
11
+ /** Absolute path to the skill folder (parent of SKILL.md). */
12
+ skillDir: string;
13
+ frontmatter: SkillFrontmatter;
14
+ /** Raw markdown body (after frontmatter). */
15
+ body: string;
16
+ /** Total lines in SKILL.md (including frontmatter). */
17
+ totalLines: number;
18
+ /** Relative paths referenced from SKILL.md (markdown links + script paths). */
19
+ references: string[];
20
+ /** Subset of references that don't exist on disk. */
21
+ missingReferences: string[];
22
+ }
23
+ declare function parseSkillMd(skillMdPath: string): Promise<ParsedSkill>;
24
+ //#endregion
25
+ //#region src/skill-checks/tests-pack.d.ts
26
+ interface ParsedTest {
27
+ /** Absolute path of the YAML file containing this test. */
28
+ filePath: string;
29
+ description?: string;
30
+ vars: Record<string, unknown>;
31
+ /** Effect-type strings referenced by preconditions/should/should_not. */
32
+ effectTypes: string[];
33
+ /** Whether `vars.fixture` was set (or `fixtureless` flagged). */
34
+ hasFixture: boolean;
35
+ /** True if the test is `kind: negative` (or has no positive should + has should_not). */
36
+ isNegative: boolean;
37
+ /** True if the test declares any precondition. */
38
+ hasPrecondition: boolean;
39
+ /** True if the test declares an Agent Skill Evals token budget assertion. */
40
+ hasTokenBudget: boolean;
41
+ /** True if the file or vars marks the test as draft. */
42
+ isDraft: boolean;
43
+ /** Authoring diagnostics for malformed Agent Skill Evals assertion entries. */
44
+ entryErrors: AssertionEntryError[];
45
+ }
46
+ interface ParsedTestsPack {
47
+ /** YAML files matched by `testsGlob`. */
48
+ matchedFiles: string[];
49
+ /** All test cases discovered. */
50
+ tests: ParsedTest[];
51
+ /** Files that failed to parse (with error messages). */
52
+ parseErrors: Array<{
53
+ filePath: string;
54
+ error: string;
55
+ }>;
56
+ /** Verifier scripts referenced by `verifier.succeeds`/`verifier.fails`. */
57
+ verifierScripts: string[];
58
+ /** Verifier scripts that don't exist on disk. */
59
+ missingVerifierScripts: string[];
60
+ /** Verifier scripts that exist but are not executable by the current user. */
61
+ nonExecutableVerifierScripts: string[];
62
+ /** Fixture paths referenced by tests. */
63
+ fixturePaths: string[];
64
+ /** Fixture paths that don't exist on disk. */
65
+ missingFixturePaths: string[];
66
+ /** Effect types not in the supplied known-types set. */
67
+ unresolvedEffectTypes: string[];
68
+ }
69
+ declare function parseTestsPack(input: {
70
+ testsGlob: string;
71
+ baseDir: string;
72
+ knownEffectTypes: ReadonlySet<string>;
73
+ }): Promise<ParsedTestsPack>;
74
+ //#endregion
75
+ //#region src/skill-checks/index.d.ts
76
+ interface StaticProviderConfig {
77
+ /** Override for the cwd Promptfoo was launched from. */
78
+ baseDir?: string;
79
+ }
80
+ interface PromptfooContext {
81
+ vars?: Record<string, unknown>;
82
+ test?: {
83
+ vars?: Record<string, unknown>;
84
+ };
85
+ }
86
+ interface ProviderResponse {
87
+ output: string;
88
+ metadata?: Record<string, unknown>;
89
+ error?: string;
90
+ }
91
+ interface StaticProviderMetadata {
92
+ skill: ParsedSkill | null;
93
+ tests: ParsedTestsPack | null;
94
+ /** Combined missing files: skill references + verifier scripts + fixtures. */
95
+ missingFiles: string[];
96
+ /** Effect types referenced by tests but not in `knownEffectTypes`. */
97
+ unresolvedEffectTypes: string[];
98
+ warnings: string[];
99
+ }
100
+ declare class AgentSkillEvalsStaticProvider {
101
+ config: StaticProviderConfig;
102
+ private readonly configError?;
103
+ id: () => string;
104
+ constructor(options?: {
105
+ config?: StaticProviderConfig;
106
+ id?: string;
107
+ });
108
+ callApi(_prompt: string, context?: PromptfooContext): Promise<ProviderResponse>;
109
+ private callApiEffect;
110
+ }
111
+ //#endregion
112
+ export { AgentSkillEvalsStaticProvider, AgentSkillEvalsStaticProvider as default, type ParsedSkill, type ParsedTestsPack, StaticProviderConfig, StaticProviderMetadata, parseSkillMd, parseTestsPack };
113
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/skill-checks/skill.ts","../../src/skill-checks/tests-pack.ts","../../src/skill-checks/index.ts"],"mappings":";;UASiB,gBAAA;EACf,IAAA;EACA,WAAA;EAAA,CACC,GAAA;AAAA;AAAA,UAGc,WAAA;EANgB;EAQ/B,WAAA;EANA;EAQA,QAAA;EACA,WAAA,EAAa,gBAAA;EARD;EAUZ,IAAA;EAP0B;EAS1B,UAAA;EAJ6B;EAM7B,UAAA;EAPA;EASA,iBAAA;AAAA;AAAA,iBAKoB,YAAA,CAAa,WAAA,WAAsB,OAAA,CAAQ,WAAA;;;UChBhD,UAAA;;EAEf,QAAA;EACA,WAAA;EACA,IAAA,EAAM,MAAA;EDZyB;ECc/B,WAAA;EDZA;ECcA,UAAA;EDbY;ECeZ,UAAA;EDZe;ECcf,eAAA;;EAEA,cAAA;EDdA;ECgBA,OAAA;EDbA;ECeA,WAAA,EAAa,mBAAA;AAAA;AAAA,UAGE,eAAA;EDZf;ECcA,YAAA;EDZiB;ECcjB,KAAA,EAAO,UAAA;EDTa;ECWpB,WAAA,EAAa,KAAA;IAAQ,QAAA;IAAkB,KAAA;EAAA;EDXgB;ECavD,eAAA;EDb0E;ECe1E,sBAAA;;EAEA,4BAAA;;EAEA,YAAA;EAnCyB;EAqCzB,mBAAA;EAnBgC;EAqBhC,qBAAA;AAAA;AAAA,iBAGoB,cAAA,CAAe,KAAA;EACnC,SAAA;EACA,OAAA;EACA,gBAAA,EAAkB,WAAA;AAAA,IAChB,OAAA,CAAQ,eAAA;;;UChDK,oBAAA;;EAEf,OAAA;AAAA;AAAA,UAOQ,gBAAA;EACR,IAAA,GAAO,MAAA;EACP,IAAA;IAAS,IAAA,GAAO,MAAA;EAAA;AAAA;AAAA,UAGR,gBAAA;EACR,MAAA;EACA,QAAA,GAAW,MAAA;EACX,KAAA;AAAA;AAAA,UAGe,sBAAA;EACf,KAAA,EAAO,WAAA;EACP,KAAA,EAAO,eAAA;EFjBP;EEmBA,YAAA;EFjBA;EEmBA,qBAAA;EACA,QAAA;AAAA;AAAA,cAGI,6BAAA;EACJ,MAAA,EAAQ,oBAAA;EAAA,iBACS,WAAA;EACjB,EAAA;cAEY,OAAA;IAAW,MAAA,GAAS,oBAAA;IAAsB,EAAA;EAAA;EAYhD,OAAA,CACJ,OAAA,UACA,OAAA,GAAS,gBAAA,GACR,OAAA,CAAQ,gBAAA;EAAA,QAMH,aAAA;AAAA"}
@@ -0,0 +1,408 @@
1
+ import { a as pathExecutable, c as parseRuntimeTestFields, i as YamlParser, l as RUNTIME_CHECK_TYPES, n as FileSystem, o as pathExists, r as NodeServicesLive, s as parseAssertionEntries, t as Environment } from "../internal-services-5-mRgNls.mjs";
2
+ import { dirname, isAbsolute, join, resolve } from "node:path";
3
+ import * as Either from "effect/Either";
4
+ import * as Effect from "effect/Effect";
5
+ import * as ParseResult from "effect/ParseResult";
6
+ import * as Schema from "effect/Schema";
7
+ //#region src/skill-checks/skill.ts
8
+ const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
9
+ async function parseSkillMd(skillMdPath) {
10
+ return Effect.runPromise(parseSkillMdEffect(skillMdPath).pipe(Effect.provide(NodeServicesLive)));
11
+ }
12
+ function parseSkillMdEffect(skillMdPath) {
13
+ return Effect.gen(function* () {
14
+ const skillDir = dirname(skillMdPath);
15
+ const fs = yield* FileSystem;
16
+ const yaml = yield* YamlParser;
17
+ const raw = yield* fs.readText(skillMdPath);
18
+ const totalLines = raw.split(/\r?\n/).length;
19
+ let frontmatter = {};
20
+ let body = raw;
21
+ const fmMatch = raw.match(FRONTMATTER_RE);
22
+ if (fmMatch) {
23
+ const parsed = yield* yaml.parse(fmMatch[1]);
24
+ if (parsed && typeof parsed === "object") frontmatter = parsed;
25
+ body = raw.slice(fmMatch[0].length);
26
+ }
27
+ const references = extractReferences(body);
28
+ const missingReferences = [];
29
+ for (const ref of references) if (!(yield* pathExists(isAbsolute(ref) ? ref : resolve(skillDir, ref)))) missingReferences.push(ref);
30
+ return {
31
+ skillMdPath,
32
+ skillDir,
33
+ frontmatter,
34
+ body,
35
+ totalLines,
36
+ references,
37
+ missingReferences
38
+ };
39
+ });
40
+ }
41
+ /**
42
+ * Extract relative paths from a SKILL.md body. Captures:
43
+ * - Markdown links: [text](path)
44
+ * - Bare relative paths in code/inline-code: ./foo, ../foo, foo/bar.sh
45
+ * Skips http(s):// URLs.
46
+ */
47
+ function extractReferences(body) {
48
+ const refs = /* @__PURE__ */ new Set();
49
+ const linkRe = /\[[^\]]*\]\(([^)\s]+)\)/g;
50
+ let m;
51
+ while ((m = linkRe.exec(body)) !== null) {
52
+ const target = m[1];
53
+ if (target.startsWith("http://") || target.startsWith("https://")) continue;
54
+ if (target.startsWith("#")) continue;
55
+ refs.add(target);
56
+ }
57
+ const codeRe = /`((?:\.{1,2}\/)?[a-zA-Z0-9_./-]+\.[a-zA-Z0-9]{1,5})`/g;
58
+ while ((m = codeRe.exec(body)) !== null) {
59
+ const target = m[1];
60
+ if (target.includes("://")) continue;
61
+ refs.add(target);
62
+ }
63
+ return [...refs];
64
+ }
65
+ //#endregion
66
+ //#region src/skill-checks/schemas.ts
67
+ const UnknownRecordSchema = Schema.Unknown.pipe(Schema.filter((value) => isRecord(value), {
68
+ identifier: "UnknownRecord",
69
+ message: () => "must be an object"
70
+ }));
71
+ const UnknownArraySchema = Schema.Array(Schema.Unknown);
72
+ function decodeTestPackDocument(value) {
73
+ if (Array.isArray(value)) try {
74
+ return { cases: Schema.decodeUnknownSync(UnknownArraySchema)(value) };
75
+ } catch (err) {
76
+ return {
77
+ cases: [],
78
+ parseError: schemaErrorMessage(err)
79
+ };
80
+ }
81
+ if (decodeRecord(value) !== null) return { cases: [value] };
82
+ return {
83
+ cases: [],
84
+ parseError: "test pack document must be an object or array of objects"
85
+ };
86
+ }
87
+ function decodeStaticTestCase(value) {
88
+ const caseRecord = decodeRecord(value);
89
+ if (caseRecord === null) return {
90
+ caseRecord: {},
91
+ vars: {},
92
+ entryErrors: [{
93
+ field: "case",
94
+ reason: "must be an object"
95
+ }]
96
+ };
97
+ const rawVars = caseRecord.vars;
98
+ if (rawVars === void 0 || rawVars === null) return {
99
+ caseRecord,
100
+ vars: {},
101
+ entryErrors: []
102
+ };
103
+ const vars = decodeRecord(rawVars);
104
+ if (vars === null) return {
105
+ caseRecord,
106
+ vars: {},
107
+ entryErrors: [{
108
+ field: "vars",
109
+ reason: "must be an object"
110
+ }]
111
+ };
112
+ return {
113
+ caseRecord,
114
+ vars,
115
+ entryErrors: []
116
+ };
117
+ }
118
+ function decodeRecord(value) {
119
+ try {
120
+ return Schema.decodeUnknownSync(UnknownRecordSchema)(value);
121
+ } catch {
122
+ return null;
123
+ }
124
+ }
125
+ function isRecord(value) {
126
+ return typeof value === "object" && value !== null && !Array.isArray(value);
127
+ }
128
+ function schemaErrorMessage(err) {
129
+ return err instanceof Error ? err.message : String(err);
130
+ }
131
+ //#endregion
132
+ //#region src/skill-checks/tests-pack.ts
133
+ async function parseTestsPack(input) {
134
+ return Effect.runPromise(parseTestsPackEffect(input).pipe(Effect.provide(NodeServicesLive)));
135
+ }
136
+ function parseTestsPackEffect(input) {
137
+ return Effect.gen(function* () {
138
+ const fs = yield* FileSystem;
139
+ const yaml = yield* YamlParser;
140
+ const files = yield* expandGlobEffect(input.testsGlob, input.baseDir);
141
+ const tests = [];
142
+ const parseErrors = [];
143
+ for (const file of files) {
144
+ const parsedFile = yield* Effect.either(Effect.gen(function* () {
145
+ const raw = yield* fs.readText(file);
146
+ const document = decodeTestPackDocument(yield* yaml.parse(raw));
147
+ if (document.parseError) return { error: document.parseError };
148
+ return { cases: document.cases.map((c) => parseCase(file, c)) };
149
+ }));
150
+ if (parsedFile._tag === "Left") parseErrors.push({
151
+ filePath: file,
152
+ error: String(parsedFile.left)
153
+ });
154
+ else if ("error" in parsedFile.right && parsedFile.right.error !== void 0) parseErrors.push({
155
+ filePath: file,
156
+ error: parsedFile.right.error
157
+ });
158
+ else tests.push(...parsedFile.right.cases);
159
+ }
160
+ const verifierScripts = uniq(tests.flatMap((t) => {
161
+ const fixtureRoot = typeof t.vars.fixture === "string" ? isAbsolute(t.vars.fixture) ? t.vars.fixture : resolve(input.baseDir, t.vars.fixture) : input.baseDir;
162
+ return collectVerifierScripts(t.vars).map((p) => absolveScript(p, fixtureRoot));
163
+ }));
164
+ const missingVerifierScripts = [];
165
+ const nonExecutableVerifierScripts = [];
166
+ for (const s of verifierScripts) if (!(yield* pathExists(s))) missingVerifierScripts.push(s);
167
+ else if (!(yield* pathExecutable(s))) nonExecutableVerifierScripts.push(s);
168
+ const fixturePaths = uniq(tests.map((t) => typeof t.vars.fixture === "string" ? t.vars.fixture : null).filter((p) => p !== null).map((p) => isAbsolute(p) ? p : resolve(input.baseDir, p)));
169
+ const missingFixturePaths = [];
170
+ for (const p of fixturePaths) if (!(yield* pathExists(p))) missingFixturePaths.push(p);
171
+ return {
172
+ matchedFiles: files,
173
+ tests,
174
+ parseErrors,
175
+ verifierScripts,
176
+ missingVerifierScripts,
177
+ nonExecutableVerifierScripts,
178
+ fixturePaths,
179
+ missingFixturePaths,
180
+ unresolvedEffectTypes: uniq(tests.flatMap((t) => t.effectTypes)).filter((e) => !input.knownEffectTypes.has(e))
181
+ };
182
+ });
183
+ }
184
+ function parseCase(filePath, input) {
185
+ const decoded = decodeStaticTestCase(input);
186
+ const c = decoded.caseRecord;
187
+ const vars = decoded.vars;
188
+ const description = typeof c.description === "string" ? c.description : void 0;
189
+ const parsed = parseRuntimeTestFields(vars);
190
+ const effectTypes = uniq([
191
+ ...parsed.preconditions,
192
+ ...parsed.should,
193
+ ...parsed.should_not
194
+ ].map((entry) => entry.type));
195
+ const entryErrors = [...decoded.entryErrors, ...parsed.errors];
196
+ const isNegative = vars.kind === "negative" || Array.isArray(vars.should_not) && vars.should_not.length > 0 && (!Array.isArray(vars.should) || vars.should.length === 0);
197
+ return {
198
+ filePath,
199
+ description,
200
+ vars,
201
+ effectTypes,
202
+ hasFixture: typeof vars.fixture === "string" || vars.fixtureless === true,
203
+ isNegative,
204
+ hasPrecondition: Array.isArray(vars.preconditions) && vars.preconditions.length > 0,
205
+ hasTokenBudget: declaresTokenBudget(c.assert),
206
+ isDraft: vars.draft === true || typeof c.metadata === "object" && c.metadata !== null && c.metadata.draft === true,
207
+ entryErrors
208
+ };
209
+ }
210
+ function declaresTokenBudget(assertions) {
211
+ if (!Array.isArray(assertions)) return false;
212
+ return assertions.some((assertion) => {
213
+ if (!assertion || typeof assertion !== "object" || Array.isArray(assertion)) return false;
214
+ const record = assertion;
215
+ if (record.metric === "skill.budget") return true;
216
+ return (record.config && typeof record.config === "object" && !Array.isArray(record.config) ? record.config : {}).metric === "skill.budget";
217
+ });
218
+ }
219
+ function collectVerifierScripts(vars) {
220
+ const out = [];
221
+ const parsed = {
222
+ preconditions: parseAssertionEntries(vars.preconditions, "preconditions", { allowMissing: true }),
223
+ should: parseAssertionEntries(vars.should, "should", { allowMissing: true }),
224
+ should_not: parseAssertionEntries(vars.should_not, "should_not", { allowMissing: true })
225
+ };
226
+ for (const entries of Object.values(parsed)) for (const entry of entries.entries) {
227
+ if (!isVerifierEntry(entry)) continue;
228
+ if (entry.args && typeof entry.args === "object" && typeof entry.args.run === "string") out.push(entry.args.run);
229
+ }
230
+ return out;
231
+ }
232
+ function isVerifierEntry(entry) {
233
+ return entry.type === "verifier.succeeds" || entry.type === "verifier.fails";
234
+ }
235
+ function absolveScript(scriptPath, fixtureRoot) {
236
+ if (isAbsolute(scriptPath)) return scriptPath;
237
+ return resolve(fixtureRoot, scriptPath);
238
+ }
239
+ function uniq(xs) {
240
+ return [...new Set(xs)];
241
+ }
242
+ /**
243
+ * Tiny glob expander. Handles literal paths, `**\/*.yaml`, and a single `*`
244
+ * segment. Sufficient for Agent Skill Evals conventions.
245
+ */
246
+ function expandGlobEffect(pattern, baseDir) {
247
+ return Effect.gen(function* () {
248
+ const fs = yield* FileSystem;
249
+ const abs = isAbsolute(pattern) ? pattern : resolve(baseDir, pattern);
250
+ const absStat = yield* fs.stat(abs).pipe(Effect.either);
251
+ if (absStat._tag === "Right" && absStat.right.isFile()) return [abs];
252
+ if (absStat._tag === "Right" && absStat.right.isDirectory()) return yield* listYamlEffect(abs);
253
+ const idx = abs.search(/\*\*?|\*/);
254
+ if (idx < 0) return [];
255
+ const root = abs.slice(0, idx).replace(/\/$/, "") || "/";
256
+ const tail = abs.slice(idx);
257
+ const matches = [];
258
+ yield* walkEffect(root, (p) => Effect.sync(() => {
259
+ if (matchesGlob(p, root, tail)) matches.push(p);
260
+ }));
261
+ return matches;
262
+ });
263
+ }
264
+ function listYamlEffect(dir) {
265
+ return Effect.gen(function* () {
266
+ const out = [];
267
+ yield* walkEffect(dir, (p) => Effect.sync(() => {
268
+ if (p.endsWith(".yaml") || p.endsWith(".yml")) out.push(p);
269
+ }));
270
+ return out;
271
+ });
272
+ }
273
+ function walkEffect(dir, visit) {
274
+ return Effect.gen(function* () {
275
+ const entries = yield* (yield* FileSystem).readDirectory(dir).pipe(Effect.catchAll(() => Effect.succeed([])));
276
+ for (const e of entries) {
277
+ const p = join(dir, e.name);
278
+ if (e.isDirectory()) {
279
+ if (e.name === "node_modules" || e.name === ".git") continue;
280
+ yield* walkEffect(p, visit);
281
+ } else if (e.isFile()) yield* visit(p);
282
+ }
283
+ });
284
+ }
285
+ function matchesGlob(p, root, tail) {
286
+ if (!p.startsWith(root)) return false;
287
+ const rel = p.slice(root.length).replace(/^\//, "");
288
+ return new RegExp("^" + tail.replace(/^\//, "").replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*\//g, "(?:.*/)?").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*") + "$").test(rel);
289
+ }
290
+ //#endregion
291
+ //#region src/skill-checks/index.ts
292
+ const StaticProviderConfigSchema = Schema.Struct({ baseDir: Schema.optional(Schema.String) });
293
+ var AgentSkillEvalsStaticProvider = class {
294
+ config;
295
+ configError;
296
+ id;
297
+ constructor(options = {}) {
298
+ const config = decodeStaticProviderConfig(options.config ?? {});
299
+ if ("error" in config) {
300
+ this.config = {};
301
+ this.configError = config.error;
302
+ } else this.config = config;
303
+ const label = options.id ?? "agent-skill-evals-static";
304
+ this.id = () => label;
305
+ }
306
+ async callApi(_prompt, context = {}) {
307
+ return Effect.runPromise(this.callApiEffect(_prompt, context).pipe(Effect.provide(NodeServicesLive)));
308
+ }
309
+ callApiEffect(_prompt, context = {}) {
310
+ const self = this;
311
+ return Effect.gen(function* () {
312
+ if (self.configError) return {
313
+ output: "",
314
+ error: self.configError
315
+ };
316
+ const vars = context.vars ?? context.test?.vars ?? {};
317
+ const cwd = yield* (yield* Environment).cwd;
318
+ const baseDir = self.config.baseDir ?? cwd;
319
+ const knownTypes = new Set(RUNTIME_CHECK_TYPES);
320
+ const skillPath = stringVar(vars, "skillPath");
321
+ const testsGlob = stringVar(vars, "testsGlob");
322
+ const warnings = [];
323
+ if (!skillPath) return {
324
+ output: "",
325
+ error: "skill checks: vars.skillPath is required (example: skillPath: ./skills/bugfix-workflow)"
326
+ };
327
+ if (!testsGlob) return {
328
+ output: "",
329
+ error: "skill checks: vars.testsGlob is required (example: testsGlob: ./tests/bugfix-workflow.yaml)"
330
+ };
331
+ let skill = null;
332
+ const skillAbs = isAbsolute(skillPath) ? skillPath : resolve(baseDir, skillPath);
333
+ const skillMd = yield* ensureSkillMdEffect(skillAbs);
334
+ if (skillMd === null) return {
335
+ output: "",
336
+ error: `skill checks: SKILL.md not found at ${skillAbs}`
337
+ };
338
+ const parsedSkill = yield* Effect.either(parseSkillMdEffect(skillMd));
339
+ if (Either.isLeft(parsedSkill)) return {
340
+ output: "",
341
+ error: `skill checks: failed to parse SKILL.md at ${skillMd}: ${parsedSkill.left instanceof Error ? parsedSkill.left.message : String(parsedSkill.left)}`
342
+ };
343
+ skill = parsedSkill.right;
344
+ let tests = null;
345
+ tests = yield* parseTestsPackEffect({
346
+ testsGlob,
347
+ baseDir,
348
+ knownEffectTypes: knownTypes
349
+ });
350
+ const missingFiles = [];
351
+ if (skill) for (const ref of skill.missingReferences) missingFiles.push(`${skill.skillDir}/${ref}`);
352
+ if (tests) {
353
+ missingFiles.push(...tests.missingVerifierScripts);
354
+ missingFiles.push(...tests.missingFixturePaths);
355
+ }
356
+ const metadata = {
357
+ skill,
358
+ tests,
359
+ missingFiles,
360
+ unresolvedEffectTypes: tests?.unresolvedEffectTypes ?? [],
361
+ warnings
362
+ };
363
+ return {
364
+ output: summarise(metadata),
365
+ metadata
366
+ };
367
+ });
368
+ }
369
+ };
370
+ function decodeStaticProviderConfig(input) {
371
+ const decoded = Schema.decodeUnknownEither(StaticProviderConfigSchema, { errors: "all" })(input ?? {});
372
+ if (Either.isRight(decoded)) return decoded.right;
373
+ return { error: `skill checks: invalid config: ${ParseResult.TreeFormatter.formatErrorSync(decoded.left)}` };
374
+ }
375
+ function stringVar(vars, key) {
376
+ const value = vars[key];
377
+ return typeof value === "string" && value.length > 0 ? value : void 0;
378
+ }
379
+ function ensureSkillMdEffect(skillPath) {
380
+ return Effect.gen(function* () {
381
+ const fs = yield* FileSystem;
382
+ const statResult = yield* fs.stat(skillPath).pipe(Effect.either);
383
+ if (Either.isRight(statResult)) {
384
+ const s = statResult.right;
385
+ if (s.isFile()) return skillPath;
386
+ if (s.isDirectory()) {
387
+ const candidate = join(skillPath, "SKILL.md");
388
+ const cs = yield* fs.stat(candidate).pipe(Effect.catchAll(() => Effect.succeed(null)));
389
+ return cs && cs.isFile() ? candidate : null;
390
+ }
391
+ return null;
392
+ }
393
+ return null;
394
+ });
395
+ }
396
+ function summarise(m) {
397
+ const lines = ["Agent Skill Evals skill check input loaded:"];
398
+ if (m.skill) lines.push(`- skill: ${m.skill.frontmatter.name ?? "?"} (${m.skill.skillMdPath})`);
399
+ if (m.tests) lines.push(`- tests: ${m.tests.tests.length} case(s) from ${m.tests.matchedFiles.length} file(s)`);
400
+ if (m.missingFiles.length) lines.push(`- missing files: ${m.missingFiles.length}`);
401
+ if (m.unresolvedEffectTypes.length) lines.push(`- unresolved effect types: ${m.unresolvedEffectTypes.length}`);
402
+ lines.push(m.warnings.length ? `- warnings: ${m.warnings.join("; ")}` : "- warnings: none");
403
+ return lines.join("\n");
404
+ }
405
+ //#endregion
406
+ export { AgentSkillEvalsStaticProvider, AgentSkillEvalsStaticProvider as default, parseSkillMd, parseTestsPack };
407
+
408
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["resolvePath","resolvePath"],"sources":["../../src/skill-checks/skill.ts","../../src/skill-checks/schemas.ts","../../src/skill-checks/tests-pack.ts","../../src/skill-checks/index.ts"],"sourcesContent":["import { join, dirname, isAbsolute, resolve as resolvePath } from \"node:path\";\nimport * as Effect from \"effect/Effect\";\nimport {\n FileSystem,\n NodeServicesLive,\n pathExists,\n YamlParser,\n} from \"../internal-services.js\";\n\nexport interface SkillFrontmatter {\n name?: string;\n description?: string;\n [key: string]: unknown;\n}\n\nexport interface ParsedSkill {\n /** Absolute path to the SKILL.md file. */\n skillMdPath: string;\n /** Absolute path to the skill folder (parent of SKILL.md). */\n skillDir: string;\n frontmatter: SkillFrontmatter;\n /** Raw markdown body (after frontmatter). */\n body: string;\n /** Total lines in SKILL.md (including frontmatter). */\n totalLines: number;\n /** Relative paths referenced from SKILL.md (markdown links + script paths). */\n references: string[];\n /** Subset of references that don't exist on disk. */\n missingReferences: string[];\n}\n\nconst FRONTMATTER_RE = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/;\n\nexport async function parseSkillMd(skillMdPath: string): Promise<ParsedSkill> {\n return Effect.runPromise(parseSkillMdEffect(skillMdPath).pipe(Effect.provide(NodeServicesLive)));\n}\n\nexport function parseSkillMdEffect(\n skillMdPath: string,\n): Effect.Effect<ParsedSkill, unknown, FileSystem | YamlParser> {\n return Effect.gen(function* () {\n const skillDir = dirname(skillMdPath);\n const fs = yield* FileSystem;\n const yaml = yield* YamlParser;\n const raw = yield* fs.readText(skillMdPath);\n const totalLines = raw.split(/\\r?\\n/).length;\n\n let frontmatter: SkillFrontmatter = {};\n let body = raw;\n const fmMatch = raw.match(FRONTMATTER_RE);\n if (fmMatch) {\n const parsed = yield* yaml.parse(fmMatch[1]!);\n if (parsed && typeof parsed === \"object\") {\n frontmatter = parsed as SkillFrontmatter;\n }\n body = raw.slice(fmMatch[0].length);\n }\n\n const references = extractReferences(body);\n const missingReferences: string[] = [];\n for (const ref of references) {\n const abs = isAbsolute(ref) ? ref : resolvePath(skillDir, ref);\n if (!(yield* pathExists(abs))) missingReferences.push(ref);\n }\n\n return {\n skillMdPath,\n skillDir,\n frontmatter,\n body,\n totalLines,\n references,\n missingReferences,\n };\n });\n}\n\n/**\n * Extract relative paths from a SKILL.md body. Captures:\n * - Markdown links: [text](path)\n * - Bare relative paths in code/inline-code: ./foo, ../foo, foo/bar.sh\n * Skips http(s):// URLs.\n */\nfunction extractReferences(body: string): string[] {\n const refs = new Set<string>();\n const linkRe = /\\[[^\\]]*\\]\\(([^)\\s]+)\\)/g;\n let m: RegExpExecArray | null;\n while ((m = linkRe.exec(body)) !== null) {\n const target = m[1]!;\n if (target.startsWith(\"http://\") || target.startsWith(\"https://\")) continue;\n if (target.startsWith(\"#\")) continue;\n refs.add(target);\n }\n // Inline-code relative paths like `./script.sh` or `path/to/file.ext`.\n const codeRe = /`((?:\\.{1,2}\\/)?[a-zA-Z0-9_./-]+\\.[a-zA-Z0-9]{1,5})`/g;\n while ((m = codeRe.exec(body)) !== null) {\n const target = m[1]!;\n if (target.includes(\"://\")) continue;\n refs.add(target);\n }\n return [...refs];\n}\n\nexport async function fileExists(p: string): Promise<boolean> {\n return Effect.runPromise(pathExists(p).pipe(Effect.provide(NodeServicesLive)));\n}\n\nexport function joinSkill(skillDir: string, rel: string): string {\n return isAbsolute(rel) ? rel : join(skillDir, rel);\n}\n","import * as Schema from \"effect/Schema\";\nimport type { AssertionEntryError } from \"../assertion-entries.js\";\n\nexport interface DecodedTestPackDocument {\n cases: readonly unknown[];\n parseError?: string;\n}\n\nexport interface DecodedStaticTestCase {\n caseRecord: Record<string, unknown>;\n vars: Record<string, unknown>;\n entryErrors: AssertionEntryError[];\n}\n\nconst UnknownRecordSchema = Schema.Unknown.pipe(\n Schema.filter(\n (value): value is Record<string, unknown> => isRecord(value),\n {\n identifier: \"UnknownRecord\",\n message: () => \"must be an object\",\n },\n ),\n);\n\nconst UnknownArraySchema = Schema.Array(Schema.Unknown);\n\nexport function decodeTestPackDocument(value: unknown): DecodedTestPackDocument {\n if (Array.isArray(value)) {\n try {\n return { cases: Schema.decodeUnknownSync(UnknownArraySchema)(value) };\n } catch (err) {\n return { cases: [], parseError: schemaErrorMessage(err) };\n }\n }\n\n if (decodeRecord(value) !== null) {\n return { cases: [value] };\n }\n\n return {\n cases: [],\n parseError: \"test pack document must be an object or array of objects\",\n };\n}\n\nexport function decodeStaticTestCase(value: unknown): DecodedStaticTestCase {\n const caseRecord = decodeRecord(value);\n if (caseRecord === null) {\n return {\n caseRecord: {},\n vars: {},\n entryErrors: [{ field: \"case\", reason: \"must be an object\" }],\n };\n }\n\n const rawVars = caseRecord.vars;\n if (rawVars === undefined || rawVars === null) {\n return { caseRecord, vars: {}, entryErrors: [] };\n }\n\n const vars = decodeRecord(rawVars);\n if (vars === null) {\n return {\n caseRecord,\n vars: {},\n entryErrors: [{ field: \"vars\", reason: \"must be an object\" }],\n };\n }\n\n return { caseRecord, vars, entryErrors: [] };\n}\n\nfunction decodeRecord(value: unknown): Record<string, unknown> | null {\n try {\n return Schema.decodeUnknownSync(UnknownRecordSchema)(value);\n } catch {\n return null;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction schemaErrorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","import { join, isAbsolute, resolve as resolvePath } from \"node:path\";\nimport * as Effect from \"effect/Effect\";\nimport {\n parseAssertionEntries,\n parseRuntimeTestFields,\n type AssertionEntry,\n type AssertionEntryError,\n} from \"../assertion-entries.js\";\nimport { decodeStaticTestCase, decodeTestPackDocument } from \"./schemas.js\";\nimport {\n FileSystem,\n NodeServicesLive,\n pathExecutable,\n pathExists,\n YamlParser,\n} from \"../internal-services.js\";\n\nexport interface ParsedTest {\n /** Absolute path of the YAML file containing this test. */\n filePath: string;\n description?: string;\n vars: Record<string, unknown>;\n /** Effect-type strings referenced by preconditions/should/should_not. */\n effectTypes: string[];\n /** Whether `vars.fixture` was set (or `fixtureless` flagged). */\n hasFixture: boolean;\n /** True if the test is `kind: negative` (or has no positive should + has should_not). */\n isNegative: boolean;\n /** True if the test declares any precondition. */\n hasPrecondition: boolean;\n /** True if the test declares an Agent Skill Evals token budget assertion. */\n hasTokenBudget: boolean;\n /** True if the file or vars marks the test as draft. */\n isDraft: boolean;\n /** Authoring diagnostics for malformed Agent Skill Evals assertion entries. */\n entryErrors: AssertionEntryError[];\n}\n\nexport interface ParsedTestsPack {\n /** YAML files matched by `testsGlob`. */\n matchedFiles: string[];\n /** All test cases discovered. */\n tests: ParsedTest[];\n /** Files that failed to parse (with error messages). */\n parseErrors: Array<{ filePath: string; error: string }>;\n /** Verifier scripts referenced by `verifier.succeeds`/`verifier.fails`. */\n verifierScripts: string[];\n /** Verifier scripts that don't exist on disk. */\n missingVerifierScripts: string[];\n /** Verifier scripts that exist but are not executable by the current user. */\n nonExecutableVerifierScripts: string[];\n /** Fixture paths referenced by tests. */\n fixturePaths: string[];\n /** Fixture paths that don't exist on disk. */\n missingFixturePaths: string[];\n /** Effect types not in the supplied known-types set. */\n unresolvedEffectTypes: string[];\n}\n\nexport async function parseTestsPack(input: {\n testsGlob: string;\n baseDir: string;\n knownEffectTypes: ReadonlySet<string>;\n}): Promise<ParsedTestsPack> {\n return Effect.runPromise(parseTestsPackEffect(input).pipe(Effect.provide(NodeServicesLive)));\n}\n\nexport function parseTestsPackEffect(input: {\n testsGlob: string;\n baseDir: string;\n knownEffectTypes: ReadonlySet<string>;\n}): Effect.Effect<ParsedTestsPack, never, FileSystem | YamlParser> {\n return Effect.gen(function* () {\n const fs = yield* FileSystem;\n const yaml = yield* YamlParser;\n const files = yield* expandGlobEffect(input.testsGlob, input.baseDir);\n const tests: ParsedTest[] = [];\n const parseErrors: Array<{ filePath: string; error: string }> = [];\n\n for (const file of files) {\n const parsedFile = yield* Effect.either(Effect.gen(function* () {\n const raw = yield* fs.readText(file);\n const parsed = yield* yaml.parse(raw);\n const document = decodeTestPackDocument(parsed);\n if (document.parseError) {\n return { error: document.parseError };\n }\n return { cases: document.cases.map((c) => parseCase(file, c)) };\n }));\n if (parsedFile._tag === \"Left\") {\n parseErrors.push({ filePath: file, error: String(parsedFile.left) });\n } else if (\"error\" in parsedFile.right && parsedFile.right.error !== undefined) {\n parseErrors.push({ filePath: file, error: parsedFile.right.error });\n } else {\n tests.push(...parsedFile.right.cases);\n }\n }\n\n const verifierScripts = uniq(\n tests.flatMap((t) => {\n const fixtureRoot =\n typeof t.vars.fixture === \"string\"\n ? isAbsolute(t.vars.fixture)\n ? t.vars.fixture\n : resolvePath(input.baseDir, t.vars.fixture)\n : input.baseDir;\n return collectVerifierScripts(t.vars).map((p) =>\n absolveScript(p, fixtureRoot),\n );\n }),\n );\n const missingVerifierScripts: string[] = [];\n const nonExecutableVerifierScripts: string[] = [];\n for (const s of verifierScripts) {\n if (!(yield* pathExists(s))) {\n missingVerifierScripts.push(s);\n } else if (!(yield* pathExecutable(s))) {\n nonExecutableVerifierScripts.push(s);\n }\n }\n\n const fixturePaths = uniq(\n tests\n .map((t) => (typeof t.vars.fixture === \"string\" ? t.vars.fixture : null))\n .filter((p): p is string => p !== null)\n .map((p) => (isAbsolute(p) ? p : resolvePath(input.baseDir, p))),\n );\n const missingFixturePaths: string[] = [];\n for (const p of fixturePaths) {\n if (!(yield* pathExists(p))) missingFixturePaths.push(p);\n }\n\n const allEffectTypes = uniq(tests.flatMap((t) => t.effectTypes));\n const unresolvedEffectTypes = allEffectTypes.filter(\n (e) => !input.knownEffectTypes.has(e),\n );\n\n return {\n matchedFiles: files,\n tests,\n parseErrors,\n verifierScripts,\n missingVerifierScripts,\n nonExecutableVerifierScripts,\n fixturePaths,\n missingFixturePaths,\n unresolvedEffectTypes,\n };\n });\n}\n\nfunction parseCase(filePath: string, input: unknown): ParsedTest {\n const decoded = decodeStaticTestCase(input);\n const c = decoded.caseRecord;\n const vars = decoded.vars;\n const description = typeof c.description === \"string\" ? c.description : undefined;\n const parsed = parseRuntimeTestFields(vars);\n const allEntries = [...parsed.preconditions, ...parsed.should, ...parsed.should_not];\n const effectTypes = uniq(allEntries.map((entry) => entry.type));\n const entryErrors = [...decoded.entryErrors, ...parsed.errors];\n const isNegative =\n vars.kind === \"negative\" ||\n (Array.isArray(vars.should_not) && vars.should_not.length > 0 &&\n (!Array.isArray(vars.should) || vars.should.length === 0));\n const hasFixture =\n typeof vars.fixture === \"string\" || vars.fixtureless === true;\n const hasPrecondition =\n Array.isArray(vars.preconditions) && vars.preconditions.length > 0;\n const hasTokenBudget = declaresTokenBudget(c.assert);\n const isDraft =\n vars.draft === true ||\n (typeof c.metadata === \"object\" &&\n c.metadata !== null &&\n (c.metadata as Record<string, unknown>).draft === true);\n return {\n filePath,\n description,\n vars,\n effectTypes,\n hasFixture,\n isNegative,\n hasPrecondition,\n hasTokenBudget,\n isDraft,\n entryErrors,\n };\n}\n\nfunction declaresTokenBudget(assertions: unknown): boolean {\n if (!Array.isArray(assertions)) return false;\n return assertions.some((assertion) => {\n if (!assertion || typeof assertion !== \"object\" || Array.isArray(assertion)) {\n return false;\n }\n const record = assertion as Record<string, unknown>;\n if (record.metric === \"skill.budget\") return true;\n const config = record.config && typeof record.config === \"object\" && !Array.isArray(record.config)\n ? record.config as Record<string, unknown>\n : {};\n return config.metric === \"skill.budget\";\n });\n}\n\nfunction collectVerifierScripts(vars: Record<string, unknown>): string[] {\n const out: string[] = [];\n const parsed = {\n preconditions: parseAssertionEntries(vars.preconditions, \"preconditions\", { allowMissing: true }),\n should: parseAssertionEntries(vars.should, \"should\", { allowMissing: true }),\n should_not: parseAssertionEntries(vars.should_not, \"should_not\", { allowMissing: true }),\n };\n for (const entries of Object.values(parsed)) {\n for (const entry of entries.entries) {\n if (!isVerifierEntry(entry)) continue;\n if (\n entry.args &&\n typeof entry.args === \"object\" &&\n typeof (entry.args as { run?: unknown }).run === \"string\"\n ) {\n out.push((entry.args as { run: string }).run);\n }\n }\n }\n return out;\n}\n\nfunction isVerifierEntry(entry: AssertionEntry): boolean {\n return entry.type === \"verifier.succeeds\" || entry.type === \"verifier.fails\";\n}\n\nfunction absolveScript(scriptPath: string, fixtureRoot: string): string {\n if (isAbsolute(scriptPath)) return scriptPath;\n // Verifier `run` paths are relative to the fixture root (since the agent\n // executes with cwd = world/fixture).\n return resolvePath(fixtureRoot, scriptPath);\n}\n\nfunction uniq<T>(xs: readonly T[]): T[] {\n return [...new Set(xs)];\n}\n\n/**\n * Tiny glob expander. Handles literal paths, `**\\/*.yaml`, and a single `*`\n * segment. Sufficient for Agent Skill Evals conventions.\n */\nfunction expandGlobEffect(\n pattern: string,\n baseDir: string,\n): Effect.Effect<string[], never, FileSystem> {\n return Effect.gen(function* () {\n const fs = yield* FileSystem;\n const abs = isAbsolute(pattern) ? pattern : resolvePath(baseDir, pattern);\n // Literal file\n const absStat = yield* fs.stat(abs).pipe(Effect.either);\n if (absStat._tag === \"Right\" && absStat.right.isFile()) return [abs];\n // Literal directory: list yaml files\n if (absStat._tag === \"Right\" && absStat.right.isDirectory()) {\n return yield* listYamlEffect(abs);\n }\n // Pattern: split into root + glob\n const idx = abs.search(/\\*\\*?|\\*/);\n if (idx < 0) return [];\n const root = abs.slice(0, idx).replace(/\\/$/, \"\") || \"/\";\n const tail = abs.slice(idx);\n const matches: string[] = [];\n yield* walkEffect(root, (p) => Effect.sync(() => {\n if (matchesGlob(p, root, tail)) matches.push(p);\n }));\n return matches;\n });\n}\n\nfunction listYamlEffect(dir: string): Effect.Effect<string[], never, FileSystem> {\n return Effect.gen(function* () {\n const out: string[] = [];\n yield* walkEffect(dir, (p) => Effect.sync(() => {\n if (p.endsWith(\".yaml\") || p.endsWith(\".yml\")) out.push(p);\n }));\n return out;\n });\n}\n\nfunction walkEffect(\n dir: string,\n visit: (p: string) => Effect.Effect<void, never, FileSystem>,\n): Effect.Effect<void, never, FileSystem> {\n return Effect.gen(function* () {\n const fs = yield* FileSystem;\n const entries = yield* fs.readDirectory(dir).pipe(\n Effect.catchAll(() => Effect.succeed([])),\n );\n for (const e of entries) {\n const p = join(dir, e.name);\n if (e.isDirectory()) {\n if (e.name === \"node_modules\" || e.name === \".git\") continue;\n yield* walkEffect(p, visit);\n } else if (e.isFile()) {\n yield* visit(p);\n }\n }\n });\n}\n\nfunction matchesGlob(p: string, root: string, tail: string): boolean {\n if (!p.startsWith(root)) return false;\n const rel = p.slice(root.length).replace(/^\\//, \"\");\n const re = new RegExp(\n \"^\" +\n tail\n .replace(/^\\//, \"\")\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*\\*\\//g, \"(?:.*/)?\")\n .replace(/\\*\\*/g, \".*\")\n .replace(/\\*/g, \"[^/]*\") +\n \"$\",\n );\n return re.test(rel);\n}\n","import { join, isAbsolute, resolve } from \"node:path\";\nimport * as Either from \"effect/Either\";\nimport * as Effect from \"effect/Effect\";\nimport * as ParseResult from \"effect/ParseResult\";\nimport * as Schema from \"effect/Schema\";\nimport { parseSkillMdEffect, type ParsedSkill } from \"./skill.js\";\nimport { parseTestsPackEffect, type ParsedTestsPack } from \"./tests-pack.js\";\nimport { RUNTIME_CHECK_TYPES } from \"../runtime-checks/check-set.js\";\nimport {\n Environment,\n FileSystem,\n NodeServicesLive,\n YamlParser,\n} from \"../internal-services.js\";\n\nexport interface StaticProviderConfig {\n /** Override for the cwd Promptfoo was launched from. */\n baseDir?: string;\n}\n\nconst StaticProviderConfigSchema = Schema.Struct({\n baseDir: Schema.optional(Schema.String),\n});\n\ninterface PromptfooContext {\n vars?: Record<string, unknown>;\n test?: { vars?: Record<string, unknown> };\n}\n\ninterface ProviderResponse {\n output: string;\n metadata?: Record<string, unknown>;\n error?: string;\n}\n\nexport interface StaticProviderMetadata {\n skill: ParsedSkill | null;\n tests: ParsedTestsPack | null;\n /** Combined missing files: skill references + verifier scripts + fixtures. */\n missingFiles: string[];\n /** Effect types referenced by tests but not in `knownEffectTypes`. */\n unresolvedEffectTypes: string[];\n warnings: string[];\n}\n\nclass AgentSkillEvalsStaticProvider {\n config: StaticProviderConfig;\n private readonly configError?: string;\n id: () => string;\n\n constructor(options: { config?: StaticProviderConfig; id?: string } = {}) {\n const config = decodeStaticProviderConfig(options.config ?? {});\n if (\"error\" in config) {\n this.config = {};\n this.configError = config.error;\n } else {\n this.config = config;\n }\n const label = options.id ?? \"agent-skill-evals-static\";\n this.id = () => label;\n }\n\n async callApi(\n _prompt: string,\n context: PromptfooContext = {},\n ): Promise<ProviderResponse> {\n return Effect.runPromise(\n this.callApiEffect(_prompt, context).pipe(Effect.provide(NodeServicesLive)),\n );\n }\n\n private callApiEffect(\n _prompt: string,\n context: PromptfooContext = {},\n ): Effect.Effect<ProviderResponse, never, FileSystem | Environment | YamlParser> {\n const self = this;\n return Effect.gen(function* () {\n if (self.configError) {\n return { output: \"\", error: self.configError };\n }\n const vars = (context.vars ?? context.test?.vars ?? {}) as Record<string, unknown>;\n const environment = yield* Environment;\n const cwd = yield* environment.cwd;\n const baseDir = self.config.baseDir ?? cwd;\n const knownTypes = new Set<string>(RUNTIME_CHECK_TYPES);\n\n const skillPath = stringVar(vars, \"skillPath\");\n const testsGlob = stringVar(vars, \"testsGlob\");\n const warnings: string[] = [];\n\n if (!skillPath) {\n return {\n output: \"\",\n error: 'skill checks: vars.skillPath is required (example: skillPath: ./skills/bugfix-workflow)',\n };\n }\n if (!testsGlob) {\n return {\n output: \"\",\n error: 'skill checks: vars.testsGlob is required (example: testsGlob: ./tests/bugfix-workflow.yaml)',\n };\n }\n\n let skill: ParsedSkill | null = null;\n const skillAbs = isAbsolute(skillPath) ? skillPath : resolve(baseDir, skillPath);\n const skillMd = yield* ensureSkillMdEffect(skillAbs);\n if (skillMd === null) {\n return {\n output: \"\",\n error: `skill checks: SKILL.md not found at ${skillAbs}`,\n };\n }\n const parsedSkill = yield* Effect.either(parseSkillMdEffect(skillMd));\n if (Either.isLeft(parsedSkill)) {\n return {\n output: \"\",\n error: `skill checks: failed to parse SKILL.md at ${skillMd}: ${parsedSkill.left instanceof Error ? parsedSkill.left.message : String(parsedSkill.left)}`,\n };\n }\n skill = parsedSkill.right;\n\n let tests: ParsedTestsPack | null = null;\n tests = yield* parseTestsPackEffect({ testsGlob, baseDir, knownEffectTypes: knownTypes });\n\n const missingFiles: string[] = [];\n if (skill) {\n for (const ref of skill.missingReferences) missingFiles.push(`${skill.skillDir}/${ref}`);\n }\n if (tests) {\n missingFiles.push(...tests.missingVerifierScripts);\n missingFiles.push(...tests.missingFixturePaths);\n }\n\n const metadata: StaticProviderMetadata = {\n skill,\n tests,\n missingFiles,\n unresolvedEffectTypes: tests?.unresolvedEffectTypes ?? [],\n warnings,\n };\n\n return {\n output: summarise(metadata),\n metadata: metadata as unknown as Record<string, unknown>,\n };\n });\n }\n}\n\nfunction decodeStaticProviderConfig(input: unknown): StaticProviderConfig | { error: string } {\n const decoded = Schema.decodeUnknownEither(StaticProviderConfigSchema, {\n errors: \"all\",\n })(input ?? {});\n if (Either.isRight(decoded)) return decoded.right;\n return {\n error: `skill checks: invalid config: ${ParseResult.TreeFormatter.formatErrorSync(decoded.left)}`,\n };\n}\n\nfunction stringVar(vars: Record<string, unknown>, key: string): string | undefined {\n const value = vars[key];\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction ensureSkillMdEffect(\n skillPath: string,\n): Effect.Effect<string | null, never, FileSystem> {\n return Effect.gen(function* () {\n const fs = yield* FileSystem;\n // Accept either `…/SKILL.md` directly or a directory containing it.\n const statResult = yield* fs.stat(skillPath).pipe(Effect.either);\n if (Either.isRight(statResult)) {\n const s = statResult.right;\n if (s.isFile()) return skillPath;\n if (s.isDirectory()) {\n const candidate = join(skillPath, \"SKILL.md\");\n const cs = yield* fs.stat(candidate).pipe(\n Effect.catchAll(() => Effect.succeed(null)),\n );\n return cs && cs.isFile() ? candidate : null;\n }\n return null;\n }\n return null;\n });\n}\n\nfunction summarise(m: StaticProviderMetadata): string {\n const lines: string[] = [\"Agent Skill Evals skill check input loaded:\"];\n if (m.skill) {\n lines.push(`- skill: ${m.skill.frontmatter.name ?? \"?\"} (${m.skill.skillMdPath})`);\n }\n if (m.tests) {\n lines.push(`- tests: ${m.tests.tests.length} case(s) from ${m.tests.matchedFiles.length} file(s)`);\n }\n if (m.missingFiles.length) lines.push(`- missing files: ${m.missingFiles.length}`);\n if (m.unresolvedEffectTypes.length) {\n lines.push(`- unresolved effect types: ${m.unresolvedEffectTypes.length}`);\n }\n lines.push(\n m.warnings.length\n ? `- warnings: ${m.warnings.join(\"; \")}`\n : \"- warnings: none\",\n );\n return lines.join(\"\\n\");\n}\n\nexport default AgentSkillEvalsStaticProvider;\nexport { AgentSkillEvalsStaticProvider };\nexport { parseSkillMd } from \"./skill.js\";\nexport { parseTestsPack } from \"./tests-pack.js\";\nexport type { ParsedSkill, ParsedTestsPack };\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "agent-skill-evals",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "exports": {
6
+ "./agent": {
7
+ "types": "./dist/agent/index.d.mts",
8
+ "import": "./dist/agent/index.mjs"
9
+ },
10
+ "./skill-checks": {
11
+ "types": "./dist/skill-checks/index.d.mts",
12
+ "import": "./dist/skill-checks/index.mjs"
13
+ },
14
+ "./assertions": {
15
+ "types": "./dist/assertions/index.d.mts",
16
+ "import": "./dist/assertions/index.mjs"
17
+ }
18
+ },
19
+ "scripts": {
20
+ "build": "tsdown",
21
+ "typecheck": "tsc --noEmit -p tsconfig.json"
22
+ },
23
+ "dependencies": {
24
+ "@effect/platform": "^0.96.1",
25
+ "@effect/platform-node": "^0.106.0",
26
+ "effect": "^3.21.2",
27
+ "yaml": "^2.6.0"
28
+ },
29
+ "devDependencies": {
30
+ "typescript": "^5.6.2"
31
+ },
32
+ "description": "Promptfoo-native core package for evaluating reusable agent skills.",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/akshay5995/agent-skill-evals.git",
37
+ "directory": "packages/promptfoo"
38
+ },
39
+ "homepage": "https://akshay5995.github.io/agent-skill-evals/",
40
+ "bugs": {
41
+ "url": "https://github.com/akshay5995/agent-skill-evals/issues"
42
+ },
43
+ "keywords": [
44
+ "agent-skills",
45
+ "evals",
46
+ "promptfoo",
47
+ "testing"
48
+ ],
49
+ "files": [
50
+ "dist",
51
+ "README.md"
52
+ ],
53
+ "publishConfig": {
54
+ "access": "public"
55
+ }
56
+ }