stepproof 0.2.22
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/LICENSE +21 -0
- package/README.md +319 -0
- package/dist/adapters/anthropic.d.ts +8 -0
- package/dist/adapters/anthropic.d.ts.map +1 -0
- package/dist/adapters/anthropic.js +46 -0
- package/dist/adapters/anthropic.js.map +1 -0
- package/dist/adapters/base.d.ts +4 -0
- package/dist/adapters/base.d.ts.map +1 -0
- package/dist/adapters/base.js +2 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/index.d.ts +4 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +13 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/openai.d.ts +8 -0
- package/dist/adapters/openai.d.ts.map +1 -0
- package/dist/adapters/openai.js +42 -0
- package/dist/adapters/openai.js.map +1 -0
- package/dist/assertions/engine.d.ts +6 -0
- package/dist/assertions/engine.d.ts.map +1 -0
- package/dist/assertions/engine.js +124 -0
- package/dist/assertions/engine.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +330 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +42 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/core/scenario-parser.d.ts +4 -0
- package/dist/core/scenario-parser.d.ts.map +1 -0
- package/dist/core/scenario-parser.js +92 -0
- package/dist/core/scenario-parser.js.map +1 -0
- package/dist/core/scenario-runner.d.ts +11 -0
- package/dist/core/scenario-runner.d.ts.map +1 -0
- package/dist/core/scenario-runner.js +85 -0
- package/dist/core/scenario-runner.js.map +1 -0
- package/dist/core/types.d.ts +71 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/reporters/json-reporter.d.ts +4 -0
- package/dist/reporters/json-reporter.d.ts.map +1 -0
- package/dist/reporters/json-reporter.js +9 -0
- package/dist/reporters/json-reporter.js.map +1 -0
- package/dist/reporters/junit-reporter.d.ts +3 -0
- package/dist/reporters/junit-reporter.d.ts.map +1 -0
- package/dist/reporters/junit-reporter.js +34 -0
- package/dist/reporters/junit-reporter.js.map +1 -0
- package/dist/reporters/sarif-reporter.d.ts +3 -0
- package/dist/reporters/sarif-reporter.d.ts.map +1 -0
- package/dist/reporters/sarif-reporter.js +47 -0
- package/dist/reporters/sarif-reporter.js.map +1 -0
- package/dist/reporters/terminal-reporter.d.ts +4 -0
- package/dist/reporters/terminal-reporter.d.ts.map +1 -0
- package/dist/reporters/terminal-reporter.js +73 -0
- package/dist/reporters/terminal-reporter.js.map +1 -0
- package/dist/telemetry.d.ts +32 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +93 -0
- package/dist/telemetry.js.map +1 -0
- package/package.json +62 -0
- package/schemas/scenario.schema.json +119 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export type Provider = 'openai' | 'anthropic';
|
|
2
|
+
export type AssertionType = 'contains' | 'not_contains' | 'regex' | 'json_schema' | 'llm_judge';
|
|
3
|
+
export interface Assertion {
|
|
4
|
+
type: AssertionType;
|
|
5
|
+
/** For contains, not_contains, regex */
|
|
6
|
+
value?: string;
|
|
7
|
+
/** For json_schema: path to JSON schema file (relative to scenario file) */
|
|
8
|
+
schema?: string;
|
|
9
|
+
/** For llm_judge: the evaluation prompt */
|
|
10
|
+
prompt?: string;
|
|
11
|
+
/** For llm_judge: the expected response prefix (default: "yes") */
|
|
12
|
+
pass_on?: string;
|
|
13
|
+
/** For llm_judge: override provider (default: anthropic) */
|
|
14
|
+
provider?: Provider;
|
|
15
|
+
/** For llm_judge: override model (default: claude-haiku or gpt-4o-mini) */
|
|
16
|
+
model?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface Step {
|
|
19
|
+
id: string;
|
|
20
|
+
provider: Provider;
|
|
21
|
+
model: string;
|
|
22
|
+
/** Prompt template. Use {{variable}} for variables, {{step_id.output}} for prior step outputs. */
|
|
23
|
+
prompt: string;
|
|
24
|
+
/** Optional system prompt */
|
|
25
|
+
system?: string;
|
|
26
|
+
/** Minimum pass rate threshold (0.0–1.0). Default: 0.8 */
|
|
27
|
+
min_pass_rate?: number;
|
|
28
|
+
assertions: Assertion[];
|
|
29
|
+
}
|
|
30
|
+
export interface Scenario {
|
|
31
|
+
name: string;
|
|
32
|
+
/** Number of iterations to run. Default: 10 */
|
|
33
|
+
iterations?: number;
|
|
34
|
+
/** Global variables for template substitution */
|
|
35
|
+
variables?: Record<string, string>;
|
|
36
|
+
steps: Step[];
|
|
37
|
+
}
|
|
38
|
+
export interface AssertionResult {
|
|
39
|
+
type: string;
|
|
40
|
+
passed: boolean;
|
|
41
|
+
message?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface StepResult {
|
|
44
|
+
stepId: string;
|
|
45
|
+
iteration: number;
|
|
46
|
+
output: string;
|
|
47
|
+
passed: boolean;
|
|
48
|
+
assertionResults: AssertionResult[];
|
|
49
|
+
error?: string;
|
|
50
|
+
durationMs: number;
|
|
51
|
+
}
|
|
52
|
+
export interface StepSummary {
|
|
53
|
+
stepId: string;
|
|
54
|
+
totalRuns: number;
|
|
55
|
+
passes: number;
|
|
56
|
+
failures: number;
|
|
57
|
+
passRate: number;
|
|
58
|
+
minPassRate: number;
|
|
59
|
+
belowThreshold: boolean;
|
|
60
|
+
}
|
|
61
|
+
export interface ScenarioReport {
|
|
62
|
+
scenarioName: string;
|
|
63
|
+
iterations: number;
|
|
64
|
+
startedAt: string;
|
|
65
|
+
completedAt: string;
|
|
66
|
+
durationMs: number;
|
|
67
|
+
steps: StepSummary[];
|
|
68
|
+
allPassed: boolean;
|
|
69
|
+
results: StepResult[];
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE9C,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,cAAc,GAAG,OAAO,GAAG,aAAa,GAAG,WAAW,CAAC;AAEhG,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,aAAa,CAAC;IACpB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,kGAAkG;IAClG,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/json-reporter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,wBAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAGhF;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAE/D"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
export function writeJsonReport(report, outputPath) {
|
|
3
|
+
const json = JSON.stringify(report, null, 2);
|
|
4
|
+
fs.writeFileSync(outputPath, json, 'utf-8');
|
|
5
|
+
}
|
|
6
|
+
export function formatJsonReport(report) {
|
|
7
|
+
return JSON.stringify(report, null, 2);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=json-reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-reporter.js","sourceRoot":"","sources":["../../src/reporters/json-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAG9B,MAAM,UAAU,eAAe,CAAC,MAAsB,EAAE,UAAkB;IACxE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7C,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"junit-reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/junit-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAWvD,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CA8B1D"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
function escapeXml(str) {
|
|
2
|
+
return str
|
|
3
|
+
.replace(/&/g, '&')
|
|
4
|
+
.replace(/</g, '<')
|
|
5
|
+
.replace(/>/g, '>')
|
|
6
|
+
.replace(/"/g, '"')
|
|
7
|
+
.replace(/'/g, ''');
|
|
8
|
+
}
|
|
9
|
+
export function formatJunit(report) {
|
|
10
|
+
const totalTests = report.steps.length;
|
|
11
|
+
const totalFailures = report.steps.filter((s) => s.belowThreshold).length;
|
|
12
|
+
const timeSeconds = (report.durationMs / 1000).toFixed(3);
|
|
13
|
+
const testCases = report.steps.map((step) => {
|
|
14
|
+
const passRatePct = (step.passRate * 100).toFixed(1);
|
|
15
|
+
const thresholdPct = (step.minPassRate * 100).toFixed(0);
|
|
16
|
+
const openTag = ` <testcase name="${escapeXml(step.stepId)}" classname="stepproof.steps" time="0">`;
|
|
17
|
+
if (step.belowThreshold) {
|
|
18
|
+
const failureMessage = `Pass rate ${passRatePct}% below threshold ${thresholdPct}%`;
|
|
19
|
+
const failureBody = `${escapeXml(step.stepId)}: ${step.passes}/${step.totalRuns} iterations passed`;
|
|
20
|
+
return `${openTag}\n <failure message="${escapeXml(failureMessage)}">${escapeXml(failureBody)}</failure>\n </testcase>`;
|
|
21
|
+
}
|
|
22
|
+
return `${openTag}\n </testcase>`;
|
|
23
|
+
});
|
|
24
|
+
const lines = [
|
|
25
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
26
|
+
`<testsuites name="stepproof" tests="${totalTests}" failures="${totalFailures}" time="${timeSeconds}">`,
|
|
27
|
+
` <testsuite name="${escapeXml(report.scenarioName)}" tests="${totalTests}" failures="${totalFailures}" time="${timeSeconds}">`,
|
|
28
|
+
...testCases,
|
|
29
|
+
' </testsuite>',
|
|
30
|
+
'</testsuites>',
|
|
31
|
+
];
|
|
32
|
+
return lines.join('\n');
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=junit-reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"junit-reporter.js","sourceRoot":"","sources":["../../src/reporters/junit-reporter.ts"],"names":[],"mappings":"AAEA,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAsB;IAChD,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;IACvC,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC;IAC1E,MAAM,WAAW,GAAG,CAAC,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAE1D,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC1C,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAEzD,MAAM,OAAO,GAAG,uBAAuB,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,yCAAyC,CAAC;QAEvG,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,MAAM,cAAc,GAAG,aAAa,WAAW,qBAAqB,YAAY,GAAG,CAAC;YACpF,MAAM,WAAW,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,oBAAoB,CAAC;YACpG,OAAO,GAAG,OAAO,6BAA6B,SAAS,CAAC,cAAc,CAAC,KAAK,SAAS,CAAC,WAAW,CAAC,6BAA6B,CAAC;QAClI,CAAC;QAED,OAAO,GAAG,OAAO,mBAAmB,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG;QACZ,wCAAwC;QACxC,uCAAuC,UAAU,eAAe,aAAa,WAAW,WAAW,IAAI;QACvG,sBAAsB,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,YAAY,UAAU,eAAe,aAAa,WAAW,WAAW,IAAI;QAChI,GAAG,SAAS;QACZ,gBAAgB;QAChB,eAAe;KAChB,CAAC;IAEF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sarif-reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/sarif-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAmD1D"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export function formatSarif(report) {
|
|
2
|
+
const rules = report.steps.map((step) => ({
|
|
3
|
+
id: step.stepId,
|
|
4
|
+
name: step.stepId,
|
|
5
|
+
shortDescription: {
|
|
6
|
+
text: `Step: ${step.stepId} — min pass rate ${(step.minPassRate * 100).toFixed(0)}%`,
|
|
7
|
+
},
|
|
8
|
+
}));
|
|
9
|
+
const results = report.steps.map((step) => {
|
|
10
|
+
const passRatePct = (step.passRate * 100).toFixed(1);
|
|
11
|
+
const thresholdPct = (step.minPassRate * 100).toFixed(0);
|
|
12
|
+
if (step.belowThreshold) {
|
|
13
|
+
return {
|
|
14
|
+
ruleId: step.stepId,
|
|
15
|
+
level: 'error',
|
|
16
|
+
message: {
|
|
17
|
+
text: `Step "${step.stepId}" pass rate ${passRatePct}% is below threshold ${thresholdPct}% (${step.passes}/${step.totalRuns} iterations passed)`,
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
ruleId: step.stepId,
|
|
23
|
+
level: 'none',
|
|
24
|
+
message: {
|
|
25
|
+
text: `Step "${step.stepId}" passed — ${passRatePct}% pass rate (${step.passes}/${step.totalRuns} iterations passed)`,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
const sarif = {
|
|
30
|
+
$schema: 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',
|
|
31
|
+
version: '2.1.0',
|
|
32
|
+
runs: [
|
|
33
|
+
{
|
|
34
|
+
tool: {
|
|
35
|
+
driver: {
|
|
36
|
+
name: 'stepproof',
|
|
37
|
+
version: '0.1.0',
|
|
38
|
+
rules,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
results,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
return JSON.stringify(sarif, null, 2);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=sarif-reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sarif-reporter.js","sourceRoot":"","sources":["../../src/reporters/sarif-reporter.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,WAAW,CAAC,MAAsB;IAChD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACxC,EAAE,EAAE,IAAI,CAAC,MAAM;QACf,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,gBAAgB,EAAE;YAChB,IAAI,EAAE,SAAS,IAAI,CAAC,MAAM,oBAAoB,CAAC,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;SACrF;KACF,CAAC,CAAC,CAAC;IAEJ,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACxC,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAEzD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,OAAO;gBACL,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,KAAK,EAAE,OAAO;gBACd,OAAO,EAAE;oBACP,IAAI,EAAE,SAAS,IAAI,CAAC,MAAM,eAAe,WAAW,wBAAwB,YAAY,MAAM,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,qBAAqB;iBACjJ;aACF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK,EAAE,MAAM;YACb,OAAO,EAAE;gBACP,IAAI,EAAE,SAAS,IAAI,CAAC,MAAM,cAAc,WAAW,gBAAgB,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,qBAAqB;aACtH;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG;QACZ,OAAO,EACL,gGAAgG;QAClG,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE;YACJ;gBACE,IAAI,EAAE;oBACJ,MAAM,EAAE;wBACN,IAAI,EAAE,WAAW;wBACjB,OAAO,EAAE,OAAO;wBAChB,KAAK;qBACN;iBACF;gBACD,OAAO;aACR;SACF;KACF,CAAC;IAEF,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ScenarioReport } from '../core/types.js';
|
|
2
|
+
export declare function printReport(report: ScenarioReport, reportPath?: string): void;
|
|
3
|
+
export declare function printProgress(stepId: string, iteration: number, total: number): void;
|
|
4
|
+
//# sourceMappingURL=terminal-reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/terminal-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,kBAAkB,CAAC;AAKpE,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAwB7E;AAsDD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAKpF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
const { version } = require('../../package.json');
|
|
5
|
+
export function printReport(report, reportPath) {
|
|
6
|
+
const { scenarioName, iterations, steps, allPassed, durationMs } = report;
|
|
7
|
+
console.log('');
|
|
8
|
+
console.log(chalk.bold('stepproof') + chalk.dim(` v${version}`));
|
|
9
|
+
console.log(chalk.dim('─'.repeat(50)));
|
|
10
|
+
console.log(`${chalk.bold('Scenario:')} ${scenarioName}`);
|
|
11
|
+
console.log(`${chalk.bold('Iterations:')} ${iterations}`);
|
|
12
|
+
console.log(`${chalk.bold('Duration:')} ${formatDuration(durationMs)}`);
|
|
13
|
+
console.log('');
|
|
14
|
+
for (const step of steps) {
|
|
15
|
+
printStepSummary(step, iterations);
|
|
16
|
+
}
|
|
17
|
+
console.log(chalk.dim('─'.repeat(50)));
|
|
18
|
+
printSummaryLine(allPassed, steps);
|
|
19
|
+
if (reportPath) {
|
|
20
|
+
console.log('');
|
|
21
|
+
console.log(chalk.dim(`Report written to: ${reportPath}`));
|
|
22
|
+
}
|
|
23
|
+
console.log('');
|
|
24
|
+
}
|
|
25
|
+
function printStepSummary(step, iterations) {
|
|
26
|
+
const { stepId, passes, totalRuns, passRate, minPassRate, belowThreshold, failures } = step;
|
|
27
|
+
const statusIcon = belowThreshold ? chalk.red('✗') : chalk.green('✓');
|
|
28
|
+
const rateColor = belowThreshold ? chalk.red : chalk.green;
|
|
29
|
+
const pct = (passRate * 100).toFixed(1);
|
|
30
|
+
const threshold = (minPassRate * 100).toFixed(0);
|
|
31
|
+
console.log(` ${statusIcon} ${chalk.bold(stepId)}`);
|
|
32
|
+
console.log(` ${renderBar(passes, totalRuns)} ${passes}/${totalRuns} iterations`);
|
|
33
|
+
console.log(` Pass rate: ${rateColor(`${pct}%`)} ${chalk.dim(`(threshold: ${threshold}%)`)}`);
|
|
34
|
+
if (belowThreshold) {
|
|
35
|
+
console.log(` ${chalk.red(`✗ BELOW THRESHOLD — ${failures} failure${failures === 1 ? '' : 's'}`)}`);
|
|
36
|
+
}
|
|
37
|
+
console.log('');
|
|
38
|
+
}
|
|
39
|
+
function renderBar(passes, total) {
|
|
40
|
+
const barWidth = 20;
|
|
41
|
+
const filled = Math.round((passes / total) * barWidth);
|
|
42
|
+
const empty = barWidth - filled;
|
|
43
|
+
const bar = chalk.green('█'.repeat(filled)) + chalk.dim('░'.repeat(empty));
|
|
44
|
+
return `[${bar}]`;
|
|
45
|
+
}
|
|
46
|
+
function printSummaryLine(allPassed, steps) {
|
|
47
|
+
const failing = steps.filter((s) => s.belowThreshold);
|
|
48
|
+
if (allPassed) {
|
|
49
|
+
console.log(chalk.bold.green('PASSED') + chalk.dim(' — all steps above threshold'));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const stepList = failing.map((s) => chalk.red(s.stepId)).join(', ');
|
|
53
|
+
console.log(chalk.bold.red('FAILED') +
|
|
54
|
+
chalk.dim(` — ${failing.length} step${failing.length === 1 ? '' : 's'} below threshold: `) +
|
|
55
|
+
stepList);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function formatDuration(ms) {
|
|
59
|
+
if (ms < 1000)
|
|
60
|
+
return `${ms}ms`;
|
|
61
|
+
if (ms < 60_000)
|
|
62
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
63
|
+
const mins = Math.floor(ms / 60_000);
|
|
64
|
+
const secs = ((ms % 60_000) / 1000).toFixed(0);
|
|
65
|
+
return `${mins}m ${secs}s`;
|
|
66
|
+
}
|
|
67
|
+
export function printProgress(stepId, iteration, total) {
|
|
68
|
+
process.stdout.write(`\r ${chalk.dim('Running')} ${stepId} — iteration ${iteration}/${total}...`);
|
|
69
|
+
if (iteration === total) {
|
|
70
|
+
process.stdout.write('\r' + ' '.repeat(60) + '\r');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=terminal-reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-reporter.js","sourceRoot":"","sources":["../../src/reporters/terminal-reporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anonymous telemetry for stepproof CLI.
|
|
3
|
+
*
|
|
4
|
+
* What we collect: install_id (random UUID, never tied to a person), command name,
|
|
5
|
+
* node version, OS platform, run outcome (pass/fail/error), CLI version.
|
|
6
|
+
*
|
|
7
|
+
* What we do NOT collect: file paths, file contents, usernames, email, IP (hashed server-side).
|
|
8
|
+
*
|
|
9
|
+
* Opt-out: set PREFLIGHT_NO_TELEMETRY=1 in your environment.
|
|
10
|
+
*
|
|
11
|
+
* Data goes to: https://content-grade.onrender.com/api/telemetry
|
|
12
|
+
* Stored in: SQLite on Render (cli_telemetry table)
|
|
13
|
+
*/
|
|
14
|
+
export interface TelemetryPayload {
|
|
15
|
+
command: string;
|
|
16
|
+
success: boolean;
|
|
17
|
+
version: string;
|
|
18
|
+
/** Optional: outcome label — 'pass' | 'fail' | 'error' | 'license_activated' | 'cta_shown' */
|
|
19
|
+
outcome?: string;
|
|
20
|
+
/** Process exit code */
|
|
21
|
+
exit_code?: number;
|
|
22
|
+
/** Command wall-clock duration in milliseconds */
|
|
23
|
+
duration_ms?: number;
|
|
24
|
+
/** True if user has a valid pro license at time of event */
|
|
25
|
+
is_pro?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Send a telemetry ping. Returns a Promise that resolves within 3 seconds.
|
|
29
|
+
* Always resolves — never throws or rejects.
|
|
30
|
+
*/
|
|
31
|
+
export declare function sendTelemetry(payload: TelemetryPayload): Promise<void>;
|
|
32
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAmCH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2CtE"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anonymous telemetry for stepproof CLI.
|
|
3
|
+
*
|
|
4
|
+
* What we collect: install_id (random UUID, never tied to a person), command name,
|
|
5
|
+
* node version, OS platform, run outcome (pass/fail/error), CLI version.
|
|
6
|
+
*
|
|
7
|
+
* What we do NOT collect: file paths, file contents, usernames, email, IP (hashed server-side).
|
|
8
|
+
*
|
|
9
|
+
* Opt-out: set PREFLIGHT_NO_TELEMETRY=1 in your environment.
|
|
10
|
+
*
|
|
11
|
+
* Data goes to: https://content-grade.onrender.com/api/telemetry
|
|
12
|
+
* Stored in: SQLite on Render (cli_telemetry table)
|
|
13
|
+
*/
|
|
14
|
+
import * as os from 'node:os';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
import * as fs from 'node:fs';
|
|
17
|
+
import * as crypto from 'node:crypto';
|
|
18
|
+
const TELEMETRY_URL = 'https://content-grade.onrender.com/api/telemetry/events';
|
|
19
|
+
const CONFIG_DIR = path.join(os.homedir(), '.config', 'stepproof');
|
|
20
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
21
|
+
/** Get or create a persistent anonymous install ID stored in ~/.config/stepproof/config.json */
|
|
22
|
+
function getOrCreateInstallId() {
|
|
23
|
+
try {
|
|
24
|
+
let config = {};
|
|
25
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
26
|
+
try {
|
|
27
|
+
config = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Corrupted config — start fresh
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (typeof config.install_id === 'string' && config.install_id.length > 0) {
|
|
34
|
+
return config.install_id;
|
|
35
|
+
}
|
|
36
|
+
const id = crypto.randomUUID();
|
|
37
|
+
config.install_id = id;
|
|
38
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
39
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config), 'utf8');
|
|
40
|
+
return id;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return 'unknown';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Send a telemetry ping. Returns a Promise that resolves within 3 seconds.
|
|
48
|
+
* Always resolves — never throws or rejects.
|
|
49
|
+
*/
|
|
50
|
+
export function sendTelemetry(payload) {
|
|
51
|
+
if (process.env.PREFLIGHT_NO_TELEMETRY === '1') {
|
|
52
|
+
return Promise.resolve();
|
|
53
|
+
}
|
|
54
|
+
const installId = getOrCreateInstallId();
|
|
55
|
+
const body = JSON.stringify({
|
|
56
|
+
installId,
|
|
57
|
+
package: 'stepproof',
|
|
58
|
+
event: 'run',
|
|
59
|
+
command: payload.command,
|
|
60
|
+
success: payload.success,
|
|
61
|
+
version: payload.version,
|
|
62
|
+
platform: process.platform,
|
|
63
|
+
nodeVersion: process.version,
|
|
64
|
+
outcome: payload.outcome,
|
|
65
|
+
exit_code: payload.exit_code,
|
|
66
|
+
duration_ms: payload.duration_ms,
|
|
67
|
+
is_pro: payload.is_pro,
|
|
68
|
+
});
|
|
69
|
+
return new Promise((resolve) => {
|
|
70
|
+
const timeout = setTimeout(resolve, 3000);
|
|
71
|
+
try {
|
|
72
|
+
const controller = new AbortController();
|
|
73
|
+
const abortTimer = setTimeout(() => controller.abort(), 2500);
|
|
74
|
+
fetch(TELEMETRY_URL, {
|
|
75
|
+
method: 'POST',
|
|
76
|
+
headers: { 'Content-Type': 'application/json' },
|
|
77
|
+
body,
|
|
78
|
+
signal: controller.signal,
|
|
79
|
+
})
|
|
80
|
+
.catch(() => { })
|
|
81
|
+
.finally(() => {
|
|
82
|
+
clearTimeout(abortTimer);
|
|
83
|
+
clearTimeout(timeout);
|
|
84
|
+
resolve();
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
clearTimeout(timeout);
|
|
89
|
+
resolve();
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "stepproof",
|
|
3
|
+
"version": "0.2.22",
|
|
4
|
+
"description": "Regression testing for multi-step AI workflows. Not observability — a CI gate.",
|
|
5
|
+
"main": "dist/cli.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"stepproof": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsx src/cli.ts",
|
|
13
|
+
"test": "vitest run",
|
|
14
|
+
"test:watch": "vitest",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"schemas",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
"keywords": [
|
|
24
|
+
"ai",
|
|
25
|
+
"testing",
|
|
26
|
+
"regression",
|
|
27
|
+
"agents",
|
|
28
|
+
"llm",
|
|
29
|
+
"cli",
|
|
30
|
+
"openai",
|
|
31
|
+
"anthropic",
|
|
32
|
+
"ci"
|
|
33
|
+
],
|
|
34
|
+
"author": "Bilko",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/StanislavBG/stepproof.git"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18.0.0"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@anthropic-ai/sdk": "^0.37.0",
|
|
48
|
+
"@bilkobibitkov/preflight-license": "^1.0.0",
|
|
49
|
+
"ajv": "^8.17.1",
|
|
50
|
+
"chalk": "^5.3.0",
|
|
51
|
+
"commander": "^12.1.0",
|
|
52
|
+
"js-yaml": "^4.1.0",
|
|
53
|
+
"openai": "^4.77.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/js-yaml": "^4.0.9",
|
|
57
|
+
"@types/node": "^20.17.0",
|
|
58
|
+
"tsx": "^4.19.0",
|
|
59
|
+
"typescript": "^5.7.0",
|
|
60
|
+
"vitest": "^3.2.4"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://stepproof.dev/schemas/scenario.schema.json",
|
|
4
|
+
"title": "StepProof Scenario",
|
|
5
|
+
"description": "Schema for a stepproof scenario YAML file",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["name", "steps"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"name": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Human-readable name for this scenario"
|
|
13
|
+
},
|
|
14
|
+
"iterations": {
|
|
15
|
+
"type": "integer",
|
|
16
|
+
"minimum": 1,
|
|
17
|
+
"maximum": 1000,
|
|
18
|
+
"default": 10,
|
|
19
|
+
"description": "Number of times to run the full scenario"
|
|
20
|
+
},
|
|
21
|
+
"variables": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"description": "Global variables available in prompt templates as {{variable_name}}",
|
|
24
|
+
"additionalProperties": { "type": "string" }
|
|
25
|
+
},
|
|
26
|
+
"steps": {
|
|
27
|
+
"type": "array",
|
|
28
|
+
"minItems": 1,
|
|
29
|
+
"description": "Ordered list of steps to execute per iteration",
|
|
30
|
+
"items": {
|
|
31
|
+
"$ref": "#/definitions/Step"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"definitions": {
|
|
36
|
+
"Step": {
|
|
37
|
+
"type": "object",
|
|
38
|
+
"required": ["id", "provider", "model", "prompt"],
|
|
39
|
+
"additionalProperties": false,
|
|
40
|
+
"properties": {
|
|
41
|
+
"id": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"pattern": "^[a-z][a-z0-9_]*$",
|
|
44
|
+
"description": "Unique step identifier (snake_case). Referenced as {{step_id.output}} in later steps."
|
|
45
|
+
},
|
|
46
|
+
"provider": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"enum": ["openai", "anthropic"],
|
|
49
|
+
"description": "LLM provider to use for this step"
|
|
50
|
+
},
|
|
51
|
+
"model": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"description": "Model ID (e.g., gpt-4o, claude-sonnet-4-6)"
|
|
54
|
+
},
|
|
55
|
+
"prompt": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"description": "Prompt template. Use {{variable}} for substitution, {{step_id.output}} for prior step outputs."
|
|
58
|
+
},
|
|
59
|
+
"system": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"description": "Optional system prompt"
|
|
62
|
+
},
|
|
63
|
+
"min_pass_rate": {
|
|
64
|
+
"type": "number",
|
|
65
|
+
"minimum": 0,
|
|
66
|
+
"maximum": 1,
|
|
67
|
+
"default": 0.8,
|
|
68
|
+
"description": "Minimum fraction of iterations that must pass assertions (0.0–1.0). CI exits 1 if below this."
|
|
69
|
+
},
|
|
70
|
+
"assertions": {
|
|
71
|
+
"type": "array",
|
|
72
|
+
"default": [],
|
|
73
|
+
"description": "List of assertions to run on the step output",
|
|
74
|
+
"items": {
|
|
75
|
+
"$ref": "#/definitions/Assertion"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"Assertion": {
|
|
81
|
+
"type": "object",
|
|
82
|
+
"required": ["type"],
|
|
83
|
+
"properties": {
|
|
84
|
+
"type": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"enum": ["contains", "not_contains", "regex", "json_schema", "llm_judge"],
|
|
87
|
+
"description": "Assertion type"
|
|
88
|
+
},
|
|
89
|
+
"value": {
|
|
90
|
+
"type": "string",
|
|
91
|
+
"description": "For contains/not_contains: the substring to check. For regex: the pattern."
|
|
92
|
+
},
|
|
93
|
+
"schema": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"description": "For json_schema: path to JSON schema file (relative to scenario file)"
|
|
96
|
+
},
|
|
97
|
+
"prompt": {
|
|
98
|
+
"type": "string",
|
|
99
|
+
"description": "For llm_judge: the evaluation prompt. The step output is appended automatically."
|
|
100
|
+
},
|
|
101
|
+
"pass_on": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"default": "yes",
|
|
104
|
+
"description": "For llm_judge: the expected response prefix (case-insensitive). Default: \"yes\""
|
|
105
|
+
},
|
|
106
|
+
"provider": {
|
|
107
|
+
"type": "string",
|
|
108
|
+
"enum": ["openai", "anthropic"],
|
|
109
|
+
"default": "anthropic",
|
|
110
|
+
"description": "For llm_judge: which provider to use. Default: anthropic"
|
|
111
|
+
},
|
|
112
|
+
"model": {
|
|
113
|
+
"type": "string",
|
|
114
|
+
"description": "For llm_judge: override model. Defaults to cheapest available (haiku/gpt-4o-mini)"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|