@qcobro/ctl 1.40.1 → 1.42.2
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/README.md +16 -8
- package/dist/commands/agents/eval.d.ts +7 -3
- package/dist/commands/agents/eval.d.ts.map +1 -1
- package/dist/commands/agents/eval.js +115 -29
- package/dist/commands/agents/eval.js.map +1 -1
- package/dist/evalReport.d.ts +47 -0
- package/dist/evalReport.d.ts.map +1 -0
- package/dist/evalReport.js +408 -0
- package/dist/evalReport.js.map +1 -0
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ $ npm install -g @qcobro/ctl
|
|
|
38
38
|
$ qcobro COMMAND
|
|
39
39
|
running command...
|
|
40
40
|
$ qcobro (--version)
|
|
41
|
-
@qcobro/ctl/1.
|
|
41
|
+
@qcobro/ctl/1.40.1 darwin-arm64 node-v22.17.0
|
|
42
42
|
$ qcobro --help [COMMAND]
|
|
43
43
|
USAGE
|
|
44
44
|
$ qcobro COMMAND
|
|
@@ -103,31 +103,39 @@ EXAMPLES
|
|
|
103
103
|
|
|
104
104
|
## `qcobro agents:eval`
|
|
105
105
|
|
|
106
|
-
evaluate a VOICE_AI/EMAIL/WHATSAPP agent's conversation logic — either an existing template plus a scenarios file, or a standalone YAML eval template (agent definition plus its own embedded scenarios) that is never created. Streams each turn's result as it happens, then a final pass/fail summary; exits non-zero when the run fails.
|
|
106
|
+
evaluate a VOICE_AI/EMAIL/WHATSAPP agent's conversation logic — either an existing template plus a scenarios file, or a standalone YAML eval template (agent definition plus its own embedded scenarios) that is never created. Streams each turn's result as it happens, then a final pass/fail summary; exits non-zero when the run fails. Use --format to pick the output (text stream, JSONL, or an html/pdf report) and --output to write it to a file. For a static SMS/VOICE_PRERECORDED render (no conversation), use `agents:preview` instead.
|
|
107
107
|
|
|
108
108
|
```
|
|
109
109
|
USAGE
|
|
110
|
-
$ qcobro agents:eval [--template-id <value>] [--scenarios <value>] [--file <value>] [--
|
|
110
|
+
$ qcobro agents:eval [--template-id <value>] [--scenarios <value>] [--file <value>] [--format
|
|
111
|
+
text|json|html|pdf] [--output <value>] [--title <value>]
|
|
111
112
|
|
|
112
113
|
FLAGS
|
|
113
114
|
--file=<value> path to a standalone YAML eval template (agent definition + embedded scenarios)
|
|
114
|
-
--
|
|
115
|
+
--format=<option> [default: text] text = human-readable stream (default); json = JSONL of raw events; html/pdf =
|
|
116
|
+
a self-contained evaluation report (requires --output)
|
|
117
|
+
<options: text|json|html|pdf>
|
|
118
|
+
--output=<value> write output to this file instead of stdout (required for html/pdf)
|
|
115
119
|
--scenarios=<value> path to a YAML file with the scenarios to run (used with --template-id)
|
|
116
120
|
--template-id=<value> an existing agent template id
|
|
121
|
+
--title=<value> report title for --format html/pdf (default is generic; pass a client name at run time if you
|
|
122
|
+
want one)
|
|
117
123
|
|
|
118
124
|
DESCRIPTION
|
|
119
125
|
evaluate a VOICE_AI/EMAIL/WHATSAPP agent's conversation logic — either an existing template plus a scenarios file, or
|
|
120
126
|
a standalone YAML eval template (agent definition plus its own embedded scenarios) that is never created. Streams each
|
|
121
|
-
turn's result as it happens, then a final pass/fail summary; exits non-zero when the run fails.
|
|
122
|
-
the
|
|
123
|
-
instead.
|
|
127
|
+
turn's result as it happens, then a final pass/fail summary; exits non-zero when the run fails. Use --format to pick
|
|
128
|
+
the output (text stream, JSONL, or an html/pdf report) and --output to write it to a file. For a static
|
|
129
|
+
SMS/VOICE_PRERECORDED render (no conversation), use `agents:preview` instead.
|
|
124
130
|
|
|
125
131
|
EXAMPLES
|
|
126
132
|
$ qcobro agents:eval --template-id <id> --scenarios scenarios.yaml
|
|
127
133
|
|
|
128
134
|
$ qcobro agents:eval --file eval-template.yaml
|
|
129
135
|
|
|
130
|
-
$ qcobro agents:eval --file eval-template.yaml --json
|
|
136
|
+
$ qcobro agents:eval --file eval-template.yaml --format json --output run.json
|
|
137
|
+
|
|
138
|
+
$ qcobro agents:eval --file eval-template.yaml --format pdf --output report.pdf
|
|
131
139
|
```
|
|
132
140
|
|
|
133
141
|
## `qcobro agents:preview`
|
|
@@ -6,15 +6,19 @@ export default class Eval extends AuthenticatedCommand<typeof Eval> {
|
|
|
6
6
|
"template-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
7
|
scenarios: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
8
|
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
-
|
|
9
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
output: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
title: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
12
|
};
|
|
11
13
|
run(): Promise<void>;
|
|
12
14
|
private buildInput;
|
|
15
|
+
/** Builds `ref -> { description, turnCount, account }` from the parsed `scenarios[]` (either input mode). */
|
|
16
|
+
private scenarioMeta;
|
|
13
17
|
/** Resolves a `--file` / `--scenarios` path, failing the command cleanly if it is missing. */
|
|
14
18
|
private resolvePath;
|
|
15
19
|
/** Whether an event signals a failed turn / scenario / run. */
|
|
16
20
|
private failed;
|
|
17
|
-
/** Renders one evaluation event
|
|
18
|
-
private
|
|
21
|
+
/** Renders one evaluation event as human-readable line(s) (no trailing newline). */
|
|
22
|
+
private humanLine;
|
|
19
23
|
}
|
|
20
24
|
//# sourceMappingURL=eval.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/eval.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/eval.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAerE,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,oBAAoB,CAAC,OAAO,IAAI,CAAC;IACjE,gBAAyB,WAAW,SAON;IAC9B,gBAAyB,QAAQ,WAK/B;IACF,gBAAyB,KAAK;;;;;;;MAuB5B;IAEW,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAqEjC,OAAO,CAAC,UAAU;IAuBlB,6GAA6G;IAC7G,OAAO,CAAC,YAAY;IA0BpB,8FAA8F;IAC9F,OAAO,CAAC,WAAW;IAQnB,+DAA+D;IAC/D,OAAO,CAAC,MAAM;IAOd,oFAAoF;IACpF,OAAO,CAAC,SAAS;CAkBlB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
1
|
+
import { appendFileSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
2
3
|
import { Flags } from "@oclif/core";
|
|
3
4
|
import { parse as parseYaml } from "yaml";
|
|
4
5
|
import { AuthenticatedCommand } from "../../AuthenticatedCommand.js";
|
|
@@ -7,13 +8,15 @@ export default class Eval extends AuthenticatedCommand {
|
|
|
7
8
|
static description = "evaluate a VOICE_AI/EMAIL/WHATSAPP agent's conversation logic — either an existing " +
|
|
8
9
|
"template plus a scenarios file, or a standalone YAML eval template (agent definition " +
|
|
9
10
|
"plus its own embedded scenarios) that is never created. Streams each turn's result as " +
|
|
10
|
-
"it happens, then a final pass/fail summary; exits non-zero when the run fails.
|
|
11
|
-
"--
|
|
12
|
-
"render (no conversation), use
|
|
11
|
+
"it happens, then a final pass/fail summary; exits non-zero when the run fails. Use " +
|
|
12
|
+
"--format to pick the output (text stream, JSONL, or an html/pdf report) and --output " +
|
|
13
|
+
"to write it to a file. For a static SMS/VOICE_PRERECORDED render (no conversation), use " +
|
|
14
|
+
"`agents:preview` instead.";
|
|
13
15
|
static examples = [
|
|
14
16
|
"<%= config.bin %> <%= command.id %> --template-id <id> --scenarios scenarios.yaml",
|
|
15
17
|
"<%= config.bin %> <%= command.id %> --file eval-template.yaml",
|
|
16
|
-
"<%= config.bin %> <%= command.id %> --file eval-template.yaml --json
|
|
18
|
+
"<%= config.bin %> <%= command.id %> --file eval-template.yaml --format json --output run.json",
|
|
19
|
+
"<%= config.bin %> <%= command.id %> --file eval-template.yaml --format pdf --output report.pdf"
|
|
17
20
|
];
|
|
18
21
|
static flags = {
|
|
19
22
|
"template-id": Flags.string({ description: "an existing agent template id" }),
|
|
@@ -23,24 +26,90 @@ export default class Eval extends AuthenticatedCommand {
|
|
|
23
26
|
file: Flags.string({
|
|
24
27
|
description: "path to a standalone YAML eval template (agent definition + embedded scenarios)"
|
|
25
28
|
}),
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
default:
|
|
29
|
+
format: Flags.string({
|
|
30
|
+
options: ["text", "json", "html", "pdf"],
|
|
31
|
+
default: "text",
|
|
32
|
+
description: "text = human-readable stream (default); json = JSONL of raw events; html/pdf = a " +
|
|
33
|
+
"self-contained evaluation report (requires --output)"
|
|
34
|
+
}),
|
|
35
|
+
output: Flags.string({
|
|
36
|
+
description: "write output to this file instead of stdout (required for html/pdf)"
|
|
37
|
+
}),
|
|
38
|
+
title: Flags.string({
|
|
39
|
+
description: "report title for --format html/pdf (default is generic; pass a client name at run " +
|
|
40
|
+
"time if you want one)"
|
|
29
41
|
})
|
|
30
42
|
};
|
|
31
43
|
async run() {
|
|
32
44
|
const { flags } = await this.parse(Eval);
|
|
45
|
+
const { format, output } = flags;
|
|
46
|
+
if ((format === "html" || format === "pdf") && !output) {
|
|
47
|
+
this.error(`--format ${format} requires --output <file>`, { exit: 1 });
|
|
48
|
+
}
|
|
49
|
+
const { input, scenariosMeta } = this.buildInput(flags);
|
|
33
50
|
const client = await this.createSdkClient();
|
|
51
|
+
const stdoutStream = !output && (format === "text" || format === "json");
|
|
52
|
+
if (output && (format === "text" || format === "json")) {
|
|
53
|
+
mkdirSync(dirname(output), { recursive: true });
|
|
54
|
+
writeFileSync(output, "");
|
|
55
|
+
}
|
|
56
|
+
const events = [];
|
|
34
57
|
let anyFailed = false;
|
|
35
|
-
|
|
36
|
-
|
|
58
|
+
let scenarioCount = 0;
|
|
59
|
+
let scenarioPass = 0;
|
|
60
|
+
for await (const event of client.agentEvaluations.evaluate(input)) {
|
|
61
|
+
if (event.type === "scenarioSummary") {
|
|
62
|
+
scenarioCount += 1;
|
|
63
|
+
if (event.overallPassed)
|
|
64
|
+
scenarioPass += 1;
|
|
65
|
+
}
|
|
66
|
+
if (format === "text") {
|
|
67
|
+
const line = this.humanLine(event);
|
|
68
|
+
if (stdoutStream)
|
|
69
|
+
this.log(line);
|
|
70
|
+
else
|
|
71
|
+
appendFileSync(output, `${line}\n`);
|
|
72
|
+
}
|
|
73
|
+
else if (format === "json") {
|
|
74
|
+
const line = JSON.stringify(event);
|
|
75
|
+
if (stdoutStream)
|
|
76
|
+
this.log(line);
|
|
77
|
+
else
|
|
78
|
+
appendFileSync(output, `${line}\n`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
events.push(event);
|
|
82
|
+
}
|
|
83
|
+
anyFailed = this.failed(event) || anyFailed;
|
|
84
|
+
if (!stdoutStream && event.type === "scenarioSummary") {
|
|
85
|
+
this.logToStderr(`[${event.scenarioRef}] ${event.overallPassed ? "PASSED" : "FAILED"}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
let model;
|
|
89
|
+
if (format === "html" || format === "pdf") {
|
|
90
|
+
const { buildReportModel, renderHtml, renderPdf } = await import("../../evalReport.js");
|
|
91
|
+
model = buildReportModel(events, scenariosMeta, { title: flags.title });
|
|
92
|
+
mkdirSync(dirname(output), { recursive: true });
|
|
93
|
+
if (format === "html") {
|
|
94
|
+
writeFileSync(output, renderHtml(model), "utf8");
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
writeFileSync(output, await renderPdf(model));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!stdoutStream) {
|
|
101
|
+
const pass = model?.summary.pass ?? scenarioPass;
|
|
102
|
+
const total = model?.summary.total ?? scenarioCount;
|
|
103
|
+
this.logToStderr(`wrote ${output} (${pass}/${total} scenarios)`);
|
|
37
104
|
}
|
|
38
105
|
if (anyFailed)
|
|
39
106
|
this.exit(1);
|
|
40
107
|
}
|
|
41
108
|
buildInput(flags) {
|
|
42
109
|
if (flags.file) {
|
|
43
|
-
|
|
110
|
+
const yaml = readFileSync(this.resolvePath(flags.file), "utf8");
|
|
111
|
+
const parsed = parseYaml(yaml);
|
|
112
|
+
return { input: { yaml }, scenariosMeta: this.scenarioMeta(parsed?.scenarios) };
|
|
44
113
|
}
|
|
45
114
|
if (flags["template-id"] && flags.scenarios) {
|
|
46
115
|
const parsed = parseYaml(readFileSync(this.resolvePath(flags.scenarios), "utf8"));
|
|
@@ -48,12 +117,35 @@ export default class Eval extends AuthenticatedCommand {
|
|
|
48
117
|
? parsed
|
|
49
118
|
: (parsed.scenarios ?? parsed);
|
|
50
119
|
return {
|
|
51
|
-
agentTemplateId: flags["template-id"],
|
|
52
|
-
|
|
120
|
+
input: { agentTemplateId: flags["template-id"], scenarios: scenarios },
|
|
121
|
+
scenariosMeta: this.scenarioMeta(scenarios)
|
|
53
122
|
};
|
|
54
123
|
}
|
|
55
124
|
return this.error("Provide --file, or both --template-id and --scenarios.", { exit: 1 });
|
|
56
125
|
}
|
|
126
|
+
/** Builds `ref -> { description, turnCount, account }` from the parsed `scenarios[]` (either input mode). */
|
|
127
|
+
scenarioMeta(raw) {
|
|
128
|
+
const meta = new Map();
|
|
129
|
+
if (!Array.isArray(raw))
|
|
130
|
+
return meta;
|
|
131
|
+
for (const entry of raw) {
|
|
132
|
+
if (!entry || typeof entry !== "object")
|
|
133
|
+
continue;
|
|
134
|
+
const scenario = entry;
|
|
135
|
+
if (typeof scenario.ref !== "string")
|
|
136
|
+
continue;
|
|
137
|
+
meta.set(scenario.ref, {
|
|
138
|
+
description: typeof scenario.description === "string" ? scenario.description : "",
|
|
139
|
+
turnCount: Array.isArray(scenario.turns) ? scenario.turns.length : 0,
|
|
140
|
+
account: scenario.account &&
|
|
141
|
+
typeof scenario.account === "object" &&
|
|
142
|
+
!Array.isArray(scenario.account)
|
|
143
|
+
? scenario.account
|
|
144
|
+
: undefined
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return meta;
|
|
148
|
+
}
|
|
57
149
|
/** Resolves a `--file` / `--scenarios` path, failing the command cleanly if it is missing. */
|
|
58
150
|
resolvePath(input) {
|
|
59
151
|
try {
|
|
@@ -73,30 +165,24 @@ export default class Eval extends AuthenticatedCommand {
|
|
|
73
165
|
return event.verdict === "fail";
|
|
74
166
|
return true; // error
|
|
75
167
|
}
|
|
76
|
-
/** Renders one evaluation event
|
|
77
|
-
|
|
78
|
-
if (asJson) {
|
|
79
|
-
this.log(JSON.stringify(event));
|
|
80
|
-
return this.failed(event);
|
|
81
|
-
}
|
|
168
|
+
/** Renders one evaluation event as human-readable line(s) (no trailing newline). */
|
|
169
|
+
humanLine(event) {
|
|
82
170
|
if (event.type === "turn") {
|
|
83
171
|
const verdict = event.result.passed === undefined ? "" : event.result.passed ? " ✓" : " ✗";
|
|
84
172
|
const detail = event.result.action ?? event.result.aiResponse ?? event.result.input;
|
|
85
|
-
|
|
173
|
+
let line = `[${event.scenarioRef}] turn ${event.result.turnIndex}: ${detail}${verdict}`;
|
|
86
174
|
if (event.result.passed === false && event.result.errorMessage) {
|
|
87
|
-
|
|
175
|
+
line += `\n ↳ ${event.result.errorMessage}`;
|
|
88
176
|
}
|
|
177
|
+
return line;
|
|
89
178
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
else if (event.type === "summary") {
|
|
94
|
-
this.log(`Overall: ${event.verdict.toUpperCase()} (${event.scenarios.length} scenario(s))`);
|
|
179
|
+
if (event.type === "scenarioSummary") {
|
|
180
|
+
return `[${event.scenarioRef}] scenario ${event.overallPassed ? "PASSED" : "FAILED"}`;
|
|
95
181
|
}
|
|
96
|
-
|
|
97
|
-
|
|
182
|
+
if (event.type === "summary") {
|
|
183
|
+
return `Overall: ${event.verdict.toUpperCase()} (${event.scenarios.length} scenario(s))`;
|
|
98
184
|
}
|
|
99
|
-
return
|
|
185
|
+
return `Error: ${event.message}`;
|
|
100
186
|
}
|
|
101
187
|
}
|
|
102
188
|
//# sourceMappingURL=eval.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval.js","sourceRoot":"","sources":["../../../src/commands/agents/eval.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"eval.js","sourceRoot":"","sources":["../../../src/commands/agents/eval.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { EvalEvent } from "@qcobro/common";
|
|
2
|
+
export interface ReportTurn {
|
|
3
|
+
index: number;
|
|
4
|
+
input: string;
|
|
5
|
+
expected?: string;
|
|
6
|
+
actual?: string;
|
|
7
|
+
evaluationType?: "EXACT" | "SIMILAR";
|
|
8
|
+
passed?: boolean;
|
|
9
|
+
errorMessage?: string;
|
|
10
|
+
tools?: Array<{
|
|
11
|
+
expected: string;
|
|
12
|
+
actual?: string;
|
|
13
|
+
passed: boolean;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
export interface ReportScenario {
|
|
17
|
+
ref: string;
|
|
18
|
+
description: string;
|
|
19
|
+
/** The scenario's `account` block — the per-call metadata handed to the agent. */
|
|
20
|
+
metadata?: Record<string, unknown>;
|
|
21
|
+
passed: boolean;
|
|
22
|
+
turns: ReportTurn[];
|
|
23
|
+
}
|
|
24
|
+
export interface ReportModel {
|
|
25
|
+
title: string;
|
|
26
|
+
generatedAt: string;
|
|
27
|
+
summary: {
|
|
28
|
+
pass: number;
|
|
29
|
+
total: number;
|
|
30
|
+
verdict: "pass" | "fail";
|
|
31
|
+
};
|
|
32
|
+
scenarios: ReportScenario[];
|
|
33
|
+
errors: string[];
|
|
34
|
+
}
|
|
35
|
+
/** Walk the streamed events once and fold them into a render-ready model. */
|
|
36
|
+
export declare function buildReportModel(events: EvalEvent[], scenariosMeta: Map<string, {
|
|
37
|
+
description: string;
|
|
38
|
+
turnCount: number;
|
|
39
|
+
account?: Record<string, unknown>;
|
|
40
|
+
}>, opts?: {
|
|
41
|
+
title?: string;
|
|
42
|
+
}): ReportModel;
|
|
43
|
+
/** Render the model as one self-contained HTML document string. */
|
|
44
|
+
export declare function renderHtml(model: ReportModel): string;
|
|
45
|
+
/** Render the model as a PDF document. */
|
|
46
|
+
export declare function renderPdf(model: ReportModel): Promise<Buffer>;
|
|
47
|
+
//# sourceMappingURL=evalReport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evalReport.d.ts","sourceRoot":"","sources":["../src/evalReport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAgBhD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACnE,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EAAE,EACnB,aAAa,EAAE,GAAG,CAChB,MAAM,EACN;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAC9E,EACD,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5B,WAAW,CAoEb;AA6HD,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CA6ErD;AA+GD,0CAA0C;AAC1C,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAyC7D"}
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import pdfMake from "pdfmake/build/pdfmake.js";
|
|
2
|
+
import pdfFonts from "pdfmake/build/vfs_fonts.js";
|
|
3
|
+
/**
|
|
4
|
+
* Pure, oclif-free builders for the `agents:eval` html/pdf report. The report is
|
|
5
|
+
* deliberately GENERIC — no customer names, no per-scenario copy, no hardcoded
|
|
6
|
+
* scenario maps — so it is safe to hand to anyone. A caller who wants a client
|
|
7
|
+
* name on the cover passes `--title` at run time.
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_TITLE = "Reporte de Evaluación — Agente Conversacional";
|
|
10
|
+
const ACCENT = "#12805a";
|
|
11
|
+
const AMBER = "#b45309";
|
|
12
|
+
/** Walk the streamed events once and fold them into a render-ready model. */
|
|
13
|
+
export function buildReportModel(events, scenariosMeta, opts = {}) {
|
|
14
|
+
const byRef = new Map();
|
|
15
|
+
const errors = [];
|
|
16
|
+
let summaryPass;
|
|
17
|
+
let summaryTotal;
|
|
18
|
+
let summaryVerdict;
|
|
19
|
+
const ensure = (ref) => {
|
|
20
|
+
let scenario = byRef.get(ref);
|
|
21
|
+
if (!scenario) {
|
|
22
|
+
scenario = {
|
|
23
|
+
ref,
|
|
24
|
+
description: scenariosMeta.get(ref)?.description ?? "",
|
|
25
|
+
metadata: scenariosMeta.get(ref)?.account,
|
|
26
|
+
passed: false,
|
|
27
|
+
turns: []
|
|
28
|
+
};
|
|
29
|
+
byRef.set(ref, scenario);
|
|
30
|
+
}
|
|
31
|
+
return scenario;
|
|
32
|
+
};
|
|
33
|
+
for (const event of events) {
|
|
34
|
+
if (event.type === "turn") {
|
|
35
|
+
const r = event.result;
|
|
36
|
+
ensure(event.scenarioRef).turns.push({
|
|
37
|
+
index: r.turnIndex,
|
|
38
|
+
input: r.input,
|
|
39
|
+
expected: r.expectedResponse,
|
|
40
|
+
actual: r.aiResponse,
|
|
41
|
+
evaluationType: r.evaluationType,
|
|
42
|
+
passed: r.passed,
|
|
43
|
+
errorMessage: r.errorMessage,
|
|
44
|
+
tools: r.toolEvaluations?.map((t) => ({
|
|
45
|
+
expected: t.expectedTool,
|
|
46
|
+
actual: t.actualTool,
|
|
47
|
+
passed: t.passed
|
|
48
|
+
}))
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
else if (event.type === "scenarioSummary") {
|
|
52
|
+
ensure(event.scenarioRef).passed = event.overallPassed;
|
|
53
|
+
}
|
|
54
|
+
else if (event.type === "summary") {
|
|
55
|
+
summaryVerdict = event.verdict;
|
|
56
|
+
summaryTotal = event.scenarios.length;
|
|
57
|
+
summaryPass = event.scenarios.filter((s) => s.overallPassed).length;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
errors.push(event.message);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const scenarios = [...byRef.values()];
|
|
64
|
+
const summary = summaryVerdict !== undefined
|
|
65
|
+
? { pass: summaryPass ?? 0, total: summaryTotal ?? scenarios.length, verdict: summaryVerdict }
|
|
66
|
+
: (() => {
|
|
67
|
+
const total = scenarios.length;
|
|
68
|
+
const pass = scenarios.filter((s) => s.passed).length;
|
|
69
|
+
const verdict = pass === total ? "pass" : "fail";
|
|
70
|
+
return { pass, total, verdict };
|
|
71
|
+
})();
|
|
72
|
+
return {
|
|
73
|
+
title: opts.title?.trim() || DEFAULT_TITLE,
|
|
74
|
+
generatedAt: new Date().toISOString(),
|
|
75
|
+
summary,
|
|
76
|
+
scenarios,
|
|
77
|
+
errors
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/** HTML-escape a value for safe interpolation into the report markup. */
|
|
81
|
+
function esc(value) {
|
|
82
|
+
return String(value ?? "")
|
|
83
|
+
.replace(/&/g, "&")
|
|
84
|
+
.replace(/</g, "<")
|
|
85
|
+
.replace(/>/g, ">")
|
|
86
|
+
.replace(/"/g, """);
|
|
87
|
+
}
|
|
88
|
+
/** Turn an ISO timestamp into something a human wants to read. */
|
|
89
|
+
function readableDate(iso) {
|
|
90
|
+
return `${iso.replace("T", " ").slice(0, 16)} UTC`;
|
|
91
|
+
}
|
|
92
|
+
/** The `account` block as printable `[key, value]` pairs, dropping empty/nullish fields. */
|
|
93
|
+
function metadataPairs(md) {
|
|
94
|
+
if (!md)
|
|
95
|
+
return [];
|
|
96
|
+
const pairs = [];
|
|
97
|
+
for (const [key, value] of Object.entries(md)) {
|
|
98
|
+
if (value === null || value === undefined || value === "")
|
|
99
|
+
continue;
|
|
100
|
+
pairs.push([key, typeof value === "object" ? JSON.stringify(value) : String(value)]);
|
|
101
|
+
}
|
|
102
|
+
return pairs;
|
|
103
|
+
}
|
|
104
|
+
/** One line describing any failed tool / function call on a turn, or "" if none failed. */
|
|
105
|
+
function toolFailureNote(tools) {
|
|
106
|
+
const failed = (tools ?? []).filter((t) => !t.passed);
|
|
107
|
+
if (!failed.length)
|
|
108
|
+
return "";
|
|
109
|
+
return failed
|
|
110
|
+
.map((t) => t.actual
|
|
111
|
+
? `llamada a función: se esperaba "${t.expected}", se invocó "${t.actual}"`
|
|
112
|
+
: `llamada a función: se esperaba "${t.expected}", no se invocó`)
|
|
113
|
+
.join("; ");
|
|
114
|
+
}
|
|
115
|
+
function turnRows(turns) {
|
|
116
|
+
return turns
|
|
117
|
+
.map((turn) => {
|
|
118
|
+
const mark = turn.passed === undefined ? "" : turn.passed ? "✓" : "✗";
|
|
119
|
+
const type = turn.evaluationType
|
|
120
|
+
? ` <span class="muted">${esc(turn.evaluationType)}</span>`
|
|
121
|
+
: "";
|
|
122
|
+
const failLines = [];
|
|
123
|
+
if (turn.passed === false && turn.errorMessage)
|
|
124
|
+
failLines.push(esc(turn.errorMessage));
|
|
125
|
+
if (turn.passed === false) {
|
|
126
|
+
const note = toolFailureNote(turn.tools);
|
|
127
|
+
if (note)
|
|
128
|
+
failLines.push(esc(note));
|
|
129
|
+
}
|
|
130
|
+
const err = failLines.length ? `<div class="err">${failLines.join("<br>")}</div>` : "";
|
|
131
|
+
const main = `<tr>
|
|
132
|
+
<td>${esc(turn.index)}</td>
|
|
133
|
+
<td>${esc(turn.input)}</td>
|
|
134
|
+
<td>${esc(turn.expected ?? "")}</td>
|
|
135
|
+
<td>${esc(turn.actual ?? "")}</td>
|
|
136
|
+
<td>${mark}${type}${err}</td>
|
|
137
|
+
</tr>`;
|
|
138
|
+
if (!turn.tools?.length)
|
|
139
|
+
return main;
|
|
140
|
+
const tools = turn.tools
|
|
141
|
+
.map((t) => `${t.passed ? "✓" : "✗"} ${esc(t.expected)}${t.actual && t.actual !== t.expected ? ` → ${esc(t.actual)}` : ""}`)
|
|
142
|
+
.join("<br>");
|
|
143
|
+
return `${main}
|
|
144
|
+
<tr class="tools"><td></td><td colspan="4"><strong>Herramientas:</strong><br>${tools}</td></tr>`;
|
|
145
|
+
})
|
|
146
|
+
.join("\n");
|
|
147
|
+
}
|
|
148
|
+
function scenarioSection(scenario) {
|
|
149
|
+
const badgeColor = scenario.passed ? ACCENT : AMBER;
|
|
150
|
+
const badgeText = scenario.passed ? "PASSED" : "FAILED";
|
|
151
|
+
const description = scenario.description
|
|
152
|
+
? `<p class="muted">${esc(scenario.description)}</p>`
|
|
153
|
+
: "";
|
|
154
|
+
const pairs = metadataPairs(scenario.metadata);
|
|
155
|
+
const metaBlock = pairs.length
|
|
156
|
+
? `<p class="meta"><strong>Metadata de la llamada:</strong> ${pairs
|
|
157
|
+
.map(([key, value]) => `${esc(key)}: ${esc(value)}`)
|
|
158
|
+
.join(" · ")}</p>`
|
|
159
|
+
: "";
|
|
160
|
+
return `<section class="scenario" id="${esc(scenario.ref)}">
|
|
161
|
+
<h2>${esc(scenario.ref)}</h2>
|
|
162
|
+
${description}
|
|
163
|
+
${metaBlock}
|
|
164
|
+
<p><span class="badge" style="background:${badgeColor}">${badgeText}</span></p>
|
|
165
|
+
<table>
|
|
166
|
+
<thead>
|
|
167
|
+
<tr><th>#</th><th>Entrada</th><th>Esperado</th><th>Obtenido</th><th>Estado</th></tr>
|
|
168
|
+
</thead>
|
|
169
|
+
<tbody>
|
|
170
|
+
${turnRows(scenario.turns)}
|
|
171
|
+
</tbody>
|
|
172
|
+
</table>
|
|
173
|
+
</section>`;
|
|
174
|
+
}
|
|
175
|
+
/** The up-front table: every scenario with its id, description and status. */
|
|
176
|
+
function summaryTable(scenarios) {
|
|
177
|
+
const rows = scenarios
|
|
178
|
+
.map((s, i) => `<tr>
|
|
179
|
+
<td>${i + 1}</td>
|
|
180
|
+
<td><a href="#${esc(s.ref)}">${esc(s.ref)}</a></td>
|
|
181
|
+
<td class="muted">${esc(s.description)}</td>
|
|
182
|
+
<td class="${s.passed ? "st-ok" : "st-fail"}">${s.passed ? "PASSED" : "FAILED"}</td>
|
|
183
|
+
</tr>`)
|
|
184
|
+
.join("\n");
|
|
185
|
+
return `<section class="summary">
|
|
186
|
+
<h2>Resumen</h2>
|
|
187
|
+
<table>
|
|
188
|
+
<thead><tr><th>#</th><th>ID</th><th>Descripción</th><th>Estado</th></tr></thead>
|
|
189
|
+
<tbody>${rows}</tbody>
|
|
190
|
+
</table>
|
|
191
|
+
</section>`;
|
|
192
|
+
}
|
|
193
|
+
/** Render the model as one self-contained HTML document string. */
|
|
194
|
+
export function renderHtml(model) {
|
|
195
|
+
const errorsSection = model.errors.length
|
|
196
|
+
? `<section class="errors">
|
|
197
|
+
<h2>Errores</h2>
|
|
198
|
+
<ul>${model.errors.map((e) => `<li>${esc(e)}</li>`).join("")}</ul>
|
|
199
|
+
</section>`
|
|
200
|
+
: "";
|
|
201
|
+
return `<!doctype html>
|
|
202
|
+
<html lang="es">
|
|
203
|
+
<head>
|
|
204
|
+
<meta charset="utf-8">
|
|
205
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
206
|
+
<title>${esc(model.title)}</title>
|
|
207
|
+
<style>
|
|
208
|
+
:root { color-scheme: light; }
|
|
209
|
+
body {
|
|
210
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
211
|
+
color: #1a1a1a;
|
|
212
|
+
background: #fff;
|
|
213
|
+
margin: 0;
|
|
214
|
+
padding: 32px 20px;
|
|
215
|
+
}
|
|
216
|
+
.sheet { max-width: 820px; margin: 0 auto; }
|
|
217
|
+
.wordmark { font-size: 20px; font-weight: 700; color: ${ACCENT}; }
|
|
218
|
+
.wordmark .sub { font-weight: 400; color: #6b7280; font-size: 13px; }
|
|
219
|
+
h1 { font-size: 22px; margin: 16px 0 4px; }
|
|
220
|
+
h2 { font-size: 16px; margin: 0 0 6px; }
|
|
221
|
+
.muted { color: #6b7280; }
|
|
222
|
+
.meta { color: #374151; font-size: 11px; margin: 4px 0 8px; }
|
|
223
|
+
.score {
|
|
224
|
+
border: 1px solid #e5e7eb;
|
|
225
|
+
border-radius: 8px;
|
|
226
|
+
padding: 16px 20px;
|
|
227
|
+
margin: 20px 0 28px;
|
|
228
|
+
}
|
|
229
|
+
.score .big { font-size: 32px; font-weight: 700; color: ${ACCENT}; }
|
|
230
|
+
.badge {
|
|
231
|
+
display: inline-block;
|
|
232
|
+
color: #fff;
|
|
233
|
+
font-size: 11px;
|
|
234
|
+
font-weight: 700;
|
|
235
|
+
letter-spacing: 0.04em;
|
|
236
|
+
padding: 2px 8px;
|
|
237
|
+
border-radius: 4px;
|
|
238
|
+
}
|
|
239
|
+
table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
|
240
|
+
th, td { border: 1px solid #e5e7eb; padding: 6px 8px; text-align: left; vertical-align: top; }
|
|
241
|
+
th { background: #f9fafb; }
|
|
242
|
+
tr.tools td { background: #f9fafb; font-size: 11px; }
|
|
243
|
+
.err { color: ${AMBER}; margin-top: 4px; font-size: 11px; }
|
|
244
|
+
.scenario { margin-bottom: 28px; }
|
|
245
|
+
.summary { margin-bottom: 28px; }
|
|
246
|
+
.st-ok { color: ${ACCENT}; font-weight: 700; }
|
|
247
|
+
.st-fail { color: ${AMBER}; font-weight: 700; }
|
|
248
|
+
@media print {
|
|
249
|
+
body { padding: 0; }
|
|
250
|
+
.summary { break-after: page; }
|
|
251
|
+
.scenario { break-before: page; }
|
|
252
|
+
}
|
|
253
|
+
</style>
|
|
254
|
+
</head>
|
|
255
|
+
<body>
|
|
256
|
+
<div class="sheet">
|
|
257
|
+
<div class="wordmark">QCobro <span class="sub">· producto de Fonoster</span></div>
|
|
258
|
+
<h1>${esc(model.title)}</h1>
|
|
259
|
+
<p class="muted">Generado: ${esc(readableDate(model.generatedAt))}</p>
|
|
260
|
+
<div class="score">
|
|
261
|
+
<div><span class="big">${model.summary.pass}/${model.summary.total}</span> escenarios aprobados</div>
|
|
262
|
+
<div class="muted">Veredicto: ${esc(model.summary.verdict.toUpperCase())}</div>
|
|
263
|
+
</div>
|
|
264
|
+
${summaryTable(model.scenarios)}
|
|
265
|
+
${model.scenarios.map(scenarioSection).join("\n")}
|
|
266
|
+
${errorsSection}
|
|
267
|
+
</div>
|
|
268
|
+
</body>
|
|
269
|
+
</html>`;
|
|
270
|
+
}
|
|
271
|
+
// pdfmake ships no first-class ESM types for its build entry points; cast through
|
|
272
|
+
// `unknown` to a narrow local shape (this adapter is the one pdfmake boundary).
|
|
273
|
+
const fontModule = pdfFonts;
|
|
274
|
+
const resolvedVfs = fontModule.vfs ?? fontModule.pdfMake?.vfs ?? pdfFonts;
|
|
275
|
+
pdfMake.vfs = resolvedVfs;
|
|
276
|
+
function pdfTurnRows(turns) {
|
|
277
|
+
const rows = [];
|
|
278
|
+
for (const turn of turns) {
|
|
279
|
+
// Plain-text markers: pdfmake's bundled Roboto has no ✓/✗ glyphs.
|
|
280
|
+
const mark = turn.passed === undefined ? "—" : turn.passed ? "OK" : "FALLA";
|
|
281
|
+
const detail = [];
|
|
282
|
+
if (turn.passed === false && turn.errorMessage) {
|
|
283
|
+
detail.push({ text: turn.errorMessage, fontSize: 7, color: AMBER });
|
|
284
|
+
}
|
|
285
|
+
if (turn.passed === false) {
|
|
286
|
+
const note = toolFailureNote(turn.tools);
|
|
287
|
+
if (note)
|
|
288
|
+
detail.push({ text: note, fontSize: 7, color: AMBER });
|
|
289
|
+
}
|
|
290
|
+
const status = detail.length
|
|
291
|
+
? {
|
|
292
|
+
stack: [{ text: `${mark} ${turn.evaluationType ?? ""}`.trim(), color: AMBER }, ...detail]
|
|
293
|
+
}
|
|
294
|
+
: {
|
|
295
|
+
text: `${mark} ${turn.evaluationType ?? ""}`.trim(),
|
|
296
|
+
color: turn.passed === false ? AMBER : turn.passed ? ACCENT : undefined
|
|
297
|
+
};
|
|
298
|
+
rows.push([String(turn.index), turn.input, turn.expected ?? "", turn.actual ?? "", status]);
|
|
299
|
+
if (turn.tools?.length) {
|
|
300
|
+
const toolText = turn.tools
|
|
301
|
+
.map((t) => `${t.passed ? "OK" : "FALLA"} ${t.expected}${t.actual && t.actual !== t.expected ? ` -> ${t.actual}` : ""}`)
|
|
302
|
+
.join("\n");
|
|
303
|
+
rows.push(["", { text: `Herramientas:\n${toolText}`, colSpan: 4, fontSize: 7 }, {}, {}, {}]);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return rows;
|
|
307
|
+
}
|
|
308
|
+
/** The up-front table: every scenario with its id, description and status. */
|
|
309
|
+
function pdfSummaryTable(scenarios) {
|
|
310
|
+
const header = [
|
|
311
|
+
{ text: "#", bold: true },
|
|
312
|
+
{ text: "ID", bold: true },
|
|
313
|
+
{ text: "Descripción", bold: true },
|
|
314
|
+
{ text: "Estado", bold: true }
|
|
315
|
+
];
|
|
316
|
+
const rows = scenarios.map((s, i) => [
|
|
317
|
+
String(i + 1),
|
|
318
|
+
s.ref,
|
|
319
|
+
{ text: s.description, color: "#6b7280" },
|
|
320
|
+
{ text: s.passed ? "PASSED" : "FAILED", bold: true, color: s.passed ? ACCENT : AMBER }
|
|
321
|
+
]);
|
|
322
|
+
return {
|
|
323
|
+
table: { headerRows: 1, widths: ["auto", "auto", "*", "auto"], body: [header, ...rows] },
|
|
324
|
+
layout: "lightHorizontalLines",
|
|
325
|
+
margin: [0, 0, 0, 12]
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
function pdfScenario(scenario) {
|
|
329
|
+
const body = [
|
|
330
|
+
[
|
|
331
|
+
{ text: "#", bold: true },
|
|
332
|
+
{ text: "Entrada", bold: true },
|
|
333
|
+
{ text: "Esperado", bold: true },
|
|
334
|
+
{ text: "Obtenido", bold: true },
|
|
335
|
+
{ text: "Estado", bold: true }
|
|
336
|
+
],
|
|
337
|
+
...pdfTurnRows(scenario.turns)
|
|
338
|
+
];
|
|
339
|
+
const pairs = metadataPairs(scenario.metadata);
|
|
340
|
+
const metaLine = pairs.map(([key, value]) => `${key}: ${value}`).join(" · ");
|
|
341
|
+
return [
|
|
342
|
+
{ text: scenario.ref, style: "h2", pageBreak: "before" },
|
|
343
|
+
...(scenario.description
|
|
344
|
+
? [{ text: scenario.description, color: "#6b7280", margin: [0, 0, 0, 2] }]
|
|
345
|
+
: []),
|
|
346
|
+
...(metaLine
|
|
347
|
+
? [
|
|
348
|
+
{
|
|
349
|
+
text: [{ text: "Metadata de la llamada: ", bold: true }, metaLine],
|
|
350
|
+
fontSize: 7,
|
|
351
|
+
color: "#374151",
|
|
352
|
+
margin: [0, 0, 0, 4]
|
|
353
|
+
}
|
|
354
|
+
]
|
|
355
|
+
: []),
|
|
356
|
+
{
|
|
357
|
+
text: scenario.passed ? "PASSED" : "FAILED",
|
|
358
|
+
bold: true,
|
|
359
|
+
color: scenario.passed ? ACCENT : AMBER,
|
|
360
|
+
margin: [0, 0, 0, 4]
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
table: { headerRows: 1, widths: ["auto", "*", "*", "*", 90], body },
|
|
364
|
+
layout: "lightHorizontalLines"
|
|
365
|
+
}
|
|
366
|
+
];
|
|
367
|
+
}
|
|
368
|
+
/** Render the model as a PDF document. */
|
|
369
|
+
export function renderPdf(model) {
|
|
370
|
+
const content = [
|
|
371
|
+
{
|
|
372
|
+
stack: [
|
|
373
|
+
{ text: "QCobro", color: ACCENT, bold: true, fontSize: 14 },
|
|
374
|
+
{ text: model.title, fontSize: 13 },
|
|
375
|
+
{ text: `Generado: ${readableDate(model.generatedAt)}`, fontSize: 8, color: "#6b7280" }
|
|
376
|
+
],
|
|
377
|
+
margin: [0, 0, 0, 10]
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
text: `${model.summary.pass}/${model.summary.total} escenarios aprobados · ` +
|
|
381
|
+
`veredicto: ${model.summary.verdict}`,
|
|
382
|
+
margin: [0, 0, 0, 12]
|
|
383
|
+
},
|
|
384
|
+
{ text: "Resumen", style: "h2", margin: [0, 4, 0, 4] },
|
|
385
|
+
pdfSummaryTable(model.scenarios),
|
|
386
|
+
...model.scenarios.flatMap((scenario) => pdfScenario(scenario))
|
|
387
|
+
];
|
|
388
|
+
if (model.errors.length) {
|
|
389
|
+
content.push({ text: "Errores", style: "h2", margin: [0, 12, 0, 4] });
|
|
390
|
+
content.push({ ul: model.errors });
|
|
391
|
+
}
|
|
392
|
+
const docDefinition = {
|
|
393
|
+
pageSize: "A4",
|
|
394
|
+
pageMargins: [40, 50, 40, 40],
|
|
395
|
+
defaultStyle: { fontSize: 8 },
|
|
396
|
+
styles: { h2: { fontSize: 11, bold: true, margin: [0, 8, 0, 4] } },
|
|
397
|
+
content
|
|
398
|
+
};
|
|
399
|
+
return new Promise((resolve, reject) => {
|
|
400
|
+
try {
|
|
401
|
+
pdfMake.createPdf(docDefinition).getBuffer((buf) => resolve(Buffer.from(buf)));
|
|
402
|
+
}
|
|
403
|
+
catch (err) {
|
|
404
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
//# sourceMappingURL=evalReport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evalReport.js","sourceRoot":"","sources":["../src/evalReport.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qcobro/ctl",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.42.2",
|
|
4
4
|
"description": "Command-line tool for QCobro developers, built on @qcobro/sdk.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,16 +41,18 @@
|
|
|
41
41
|
"@oclif/core": "^4.0.34",
|
|
42
42
|
"@oclif/plugin-warn-if-update-available": "^3.1.28",
|
|
43
43
|
"@qcobro/common": "^1.40.1",
|
|
44
|
-
"@qcobro/sdk": "^1.
|
|
44
|
+
"@qcobro/sdk": "^1.42.2",
|
|
45
45
|
"chalk": "^5.3.0",
|
|
46
46
|
"cliui": "^8.0.1",
|
|
47
|
+
"pdfmake": "^0.2",
|
|
47
48
|
"yaml": "^2.9.0",
|
|
48
49
|
"zod": "^4.0.0"
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|
|
51
52
|
"@oclif/test": "^4.1.3",
|
|
52
|
-
"@qcobro/apiserver": "^1.
|
|
53
|
+
"@qcobro/apiserver": "^1.42.2",
|
|
53
54
|
"@types/node": "22.10.1",
|
|
55
|
+
"@types/pdfmake": "^0.2",
|
|
54
56
|
"oclif": "^4.17.46",
|
|
55
57
|
"tsx": "^4.0.0",
|
|
56
58
|
"typescript": "^5.9.0"
|