@inspectr/mcplab-reporting 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.
package/dist/html.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { ResultsJson } from '@inspectr/mcplab-core';
2
+ export declare function renderHtml(results: ResultsJson): string;
3
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAiBzD,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CA6UvD"}
package/dist/html.js ADDED
@@ -0,0 +1,324 @@
1
+ function escapeHtml(value) {
2
+ // Convert value to string first
3
+ const str = value == null ? '' : String(value);
4
+ return str
5
+ .replace(/&/g, '&')
6
+ .replace(/</g, '&lt;')
7
+ .replace(/>/g, '&gt;')
8
+ .replace(/"/g, '&quot;')
9
+ .replace(/'/g, '&#39;');
10
+ }
11
+ function formatPercent(value) {
12
+ return `${(value * 100).toFixed(1)}%`;
13
+ }
14
+ export function renderHtml(results) {
15
+ const scenarioRows = results.scenarios
16
+ .map((scenario) => {
17
+ const toolCalls = scenario.runs.reduce((sum, run) => sum + run.tool_call_count, 0);
18
+ const passRate = formatPercent(scenario.pass_rate);
19
+ const sequences = Object.keys(scenario.distinct_sequences).length;
20
+ const status = scenario.pass_rate === 1 ? 'pass' : scenario.pass_rate === 0 ? 'fail' : 'mixed';
21
+ return `
22
+ <tr data-status="${status}">
23
+ <td><a href="#scenario-${escapeHtml(scenario.scenario_id)}">${escapeHtml(scenario.scenario_id)}</a></td>
24
+ <td>${escapeHtml(scenario.agent)}</td>
25
+ <td>${scenario.runs.length}</td>
26
+ <td>${passRate}</td>
27
+ <td>${toolCalls}</td>
28
+ <td>${sequences}</td>
29
+ </tr>
30
+ `;
31
+ })
32
+ .join('\n');
33
+ const details = results.scenarios
34
+ .map((scenario) => {
35
+ const sequenceRows = Object.entries(scenario.distinct_sequences)
36
+ .map(([seq, count]) => {
37
+ return `<tr><td><code>${escapeHtml(seq)}</code></td><td>${count}</td></tr>`;
38
+ })
39
+ .join('\n');
40
+ const allowedSequences = scenario.eval?.tool_sequence?.allow ?? [];
41
+ const allowedRows = allowedSequences
42
+ .map((seq) => `<tr><td><code>${escapeHtml(JSON.stringify(seq))}</code></td></tr>`)
43
+ .join('\n');
44
+ const requiredTools = scenario.eval?.tool_constraints?.required_tools ?? [];
45
+ const forbiddenTools = scenario.eval?.tool_constraints?.forbidden_tools ?? [];
46
+ const requiredStats = scenario.tool_constraints_stats?.required ?? {};
47
+ const forbiddenStats = scenario.tool_constraints_stats?.forbidden ?? {};
48
+ const requiredRows = requiredTools
49
+ .map((tool) => {
50
+ const count = requiredStats[tool] ?? 0;
51
+ return `<tr><td>${escapeHtml(tool)}</td><td>${count}/${scenario.runs.length}</td></tr>`;
52
+ })
53
+ .join('\n');
54
+ const forbiddenRows = forbiddenTools
55
+ .map((tool) => {
56
+ const count = forbiddenStats[tool] ?? 0;
57
+ return `<tr><td>${escapeHtml(tool)}</td><td>${count}/${scenario.runs.length}</td></tr>`;
58
+ })
59
+ .join('\n');
60
+ const toolRows = Object.entries(scenario.tool_usage_frequency)
61
+ .map(([tool, count]) => `<tr><td>${escapeHtml(tool)}</td><td>${count}</td></tr>`)
62
+ .join('\n');
63
+ const extractSections = Object.entries(scenario.extracted_values)
64
+ .map(([name, values]) => {
65
+ const rows = Object.entries(values)
66
+ .map(([value, count]) => `<tr><td>${escapeHtml(value)}</td><td>${count}</td></tr>`)
67
+ .join('\n');
68
+ return `
69
+ <h4>${escapeHtml(name)}</h4>
70
+ <table>
71
+ <thead><tr><th>Value</th><th>Count</th></tr></thead>
72
+ <tbody>${rows || '<tr><td colspan="2">No values</td></tr>'}</tbody>
73
+ </table>
74
+ `;
75
+ })
76
+ .join('\n');
77
+ return `
78
+ <section id="scenario-${escapeHtml(scenario.scenario_id)}" class="scenario">
79
+ <h3>${escapeHtml(scenario.scenario_id)}</h3>
80
+ <p><strong>Agent:</strong> ${escapeHtml(scenario.agent)} | <strong>Runs:</strong> ${scenario.runs.length} | <strong>Pass rate:</strong> ${formatPercent(scenario.pass_rate)}</p>
81
+
82
+ <h4>Distinct tool sequences</h4>
83
+ <table>
84
+ <thead><tr><th>Sequence</th><th>Count</th></tr></thead>
85
+ <tbody>${sequenceRows || '<tr><td colspan="2">No tool calls</td></tr>'}</tbody>
86
+ </table>
87
+
88
+ <h4>Allowed sequences</h4>
89
+ <table>
90
+ <thead><tr><th>Sequence</th></tr></thead>
91
+ <tbody>${allowedRows || '<tr><td>No constraints</td></tr>'}</tbody>
92
+ </table>
93
+
94
+ <h4>Required tools</h4>
95
+ <table>
96
+ <thead><tr><th>Tool</th><th>Used (runs)</th></tr></thead>
97
+ <tbody>${requiredRows || '<tr><td colspan="2">No required tools</td></tr>'}</tbody>
98
+ </table>
99
+
100
+ <h4>Forbidden tools</h4>
101
+ <table>
102
+ <thead><tr><th>Tool</th><th>Used (runs)</th></tr></thead>
103
+ <tbody>${forbiddenRows || '<tr><td colspan="2">No forbidden tools</td></tr>'}</tbody>
104
+ </table>
105
+
106
+ <h4>Tool usage</h4>
107
+ <table>
108
+ <thead><tr><th>Tool</th><th>Count</th></tr></thead>
109
+ <tbody>${toolRows || '<tr><td colspan="2">No tool calls</td></tr>'}</tbody>
110
+ </table>
111
+
112
+ ${extractSections ? `<h4>Extracted values</h4>${extractSections}` : ''}
113
+
114
+ <details>
115
+ <summary>Last final answer</summary>
116
+ <pre>${escapeHtml(scenario.last_final_answer || '')}</pre>
117
+ </details>
118
+ </section>
119
+ `;
120
+ })
121
+ .join('\n');
122
+ return `
123
+ <!doctype html>
124
+ <html lang="en">
125
+ <head>
126
+ <meta charset="utf-8" />
127
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
128
+ <title>MCPLab Report</title>
129
+ <style>
130
+ :root {
131
+ color-scheme: light;
132
+ --bg: #f6f7fb;
133
+ --card: #ffffff;
134
+ --text: #1b1f29;
135
+ --muted: #5d6472;
136
+ --accent: #f97316;
137
+ --pass: #1f7a3a;
138
+ --fail: #bb1f1f;
139
+ --mixed: #c77d19;
140
+ }
141
+ body {
142
+ margin: 0;
143
+ font-family: "IBM Plex Sans", "Space Grotesk", system-ui, sans-serif;
144
+ background: var(--bg);
145
+ color: var(--text);
146
+ }
147
+ header {
148
+ padding: 32px;
149
+ background: radial-gradient(circle at top left, #dfe7ff, var(--bg));
150
+ border-bottom: 1px solid #e0e4ef;
151
+ }
152
+ h1 {
153
+ margin: 0 0 8px 0;
154
+ font-size: 28px;
155
+ }
156
+ .meta {
157
+ color: var(--muted);
158
+ font-size: 14px;
159
+ }
160
+ main {
161
+ padding: 24px 32px 48px;
162
+ max-width: 1100px;
163
+ margin: 0 auto;
164
+ }
165
+ .tiles {
166
+ display: grid;
167
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
168
+ gap: 16px;
169
+ margin-bottom: 24px;
170
+ }
171
+ .tile {
172
+ background: var(--card);
173
+ padding: 16px;
174
+ border-radius: 12px;
175
+ box-shadow: 0 8px 20px rgba(20, 24, 35, 0.06);
176
+ }
177
+ table {
178
+ width: 100%;
179
+ border-collapse: collapse;
180
+ background: var(--card);
181
+ border-radius: 12px;
182
+ overflow: hidden;
183
+ box-shadow: 0 8px 20px rgba(20, 24, 35, 0.05);
184
+ margin-bottom: 24px;
185
+ }
186
+ th, td {
187
+ padding: 12px 14px;
188
+ text-align: left;
189
+ border-bottom: 1px solid #edf0f6;
190
+ font-size: 14px;
191
+ }
192
+ th {
193
+ background: #f0f3fb;
194
+ color: var(--muted);
195
+ font-weight: 600;
196
+ letter-spacing: 0.02em;
197
+ text-transform: uppercase;
198
+ font-size: 12px;
199
+ }
200
+ tr:last-child td {
201
+ border-bottom: none;
202
+ }
203
+ .controls {
204
+ display: flex;
205
+ gap: 8px;
206
+ margin-bottom: 16px;
207
+ }
208
+ .controls button {
209
+ border: none;
210
+ border-radius: 999px;
211
+ padding: 8px 14px;
212
+ cursor: pointer;
213
+ background: #e4e9f8;
214
+ }
215
+ .controls button.active {
216
+ background: var(--accent);
217
+ color: white;
218
+ }
219
+ .scenario {
220
+ background: var(--card);
221
+ padding: 16px 20px;
222
+ border-radius: 14px;
223
+ margin-bottom: 20px;
224
+ box-shadow: 0 8px 20px rgba(20, 24, 35, 0.05);
225
+ }
226
+ pre {
227
+ white-space: pre-wrap;
228
+ }
229
+ code {
230
+ background: #eef1f7;
231
+ padding: 2px 6px;
232
+ border-radius: 6px;
233
+ }
234
+ </style>
235
+ </head>
236
+ <body>
237
+ <header>
238
+ <h1>MCPLab Report</h1>
239
+ <div class="meta">
240
+ Run ID: ${escapeHtml(results.metadata.run_id)}<br />
241
+ Timestamp: ${escapeHtml(results.metadata.timestamp)}<br />
242
+ Config hash: ${escapeHtml(results.metadata.config_hash)}<br />
243
+ CLI version: ${escapeHtml(results.metadata.cli_version)}
244
+ ${results.metadata.git_commit
245
+ ? `<br />Git commit: ${escapeHtml(results.metadata.git_commit)}`
246
+ : ''}
247
+ </div>
248
+ </header>
249
+
250
+ <main>
251
+ <section class="tiles">
252
+ <div class="tile"><strong>Total scenarios</strong><div>${results.summary.total_scenarios}</div></div>
253
+ <div class="tile"><strong>Total runs</strong><div>${results.summary.total_runs}</div></div>
254
+ <div class="tile"><strong>Pass rate</strong><div>${formatPercent(results.summary.pass_rate)}</div></div>
255
+ <div class="tile"><strong>Avg tool calls/run</strong><div>${results.summary.avg_tool_calls_per_run.toFixed(2)}</div></div>
256
+ <div class="tile"><strong>Avg tool latency</strong><div>${results.summary.avg_tool_latency_ms === null
257
+ ? 'n/a'
258
+ : `${results.summary.avg_tool_latency_ms.toFixed(1)} ms`}</div></div>
259
+ </section>
260
+
261
+ <section>
262
+ <h2>Scenarios</h2>
263
+ <div class="controls">
264
+ <button class="active" data-filter="all">All</button>
265
+ <button data-filter="pass">Pass</button>
266
+ <button data-filter="fail">Fail</button>
267
+ <button data-filter="mixed">Mixed</button>
268
+ </div>
269
+ <table>
270
+ <thead>
271
+ <tr>
272
+ <th>Scenario</th>
273
+ <th>Agent</th>
274
+ <th>Runs</th>
275
+ <th>Pass rate</th>
276
+ <th>Tool calls</th>
277
+ <th>Distinct sequences</th>
278
+ </tr>
279
+ </thead>
280
+ <tbody>
281
+ ${scenarioRows}
282
+ </tbody>
283
+ </table>
284
+ </section>
285
+
286
+ <section>
287
+ <h2>Scenario details</h2>
288
+ ${details}
289
+ </section>
290
+
291
+ <section>
292
+ <h2>Trace files</h2>
293
+ <ul>
294
+ <li><a href="trace.jsonl">trace.jsonl</a></li>
295
+ <li><a href="results.json">results.json</a></li>
296
+ </ul>
297
+ </section>
298
+ </main>
299
+
300
+ <script>
301
+ const buttons = document.querySelectorAll('.controls button');
302
+ const rows = document.querySelectorAll('table tbody tr');
303
+
304
+ buttons.forEach(btn => {
305
+ btn.addEventListener('click', () => {
306
+ buttons.forEach(b => b.classList.remove('active'));
307
+ btn.classList.add('active');
308
+ const filter = btn.getAttribute('data-filter');
309
+ rows.forEach(row => {
310
+ const status = row.getAttribute('data-status');
311
+ if (filter === 'all' || status === filter) {
312
+ row.style.display = '';
313
+ } else {
314
+ row.style.display = 'none';
315
+ }
316
+ });
317
+ });
318
+ });
319
+ </script>
320
+ </body>
321
+ </html>
322
+ `.trim();
323
+ }
324
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AAEA,SAAS,UAAU,CAAC,KAAmD;IACrE,gCAAgC;IAChC,MAAM,GAAG,GAAG,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/C,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,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAoB;IAC7C,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS;SACnC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QAChB,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;QACnF,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACnD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC;QAClE,MAAM,MAAM,GACV,QAAQ,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QAClF,OAAO;2BACc,MAAM;mCACE,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,UAAU,CAC1E,QAAQ,CAAC,WAAW,CACrB;gBACS,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAC1B,QAAQ,CAAC,IAAI,CAAC,MAAM;gBACpB,QAAQ;gBACR,SAAS;gBACT,SAAS;;OAElB,CAAC;IACJ,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS;SAC9B,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QAChB,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;aAC7D,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YACpB,OAAO,iBAAiB,UAAU,CAAC,GAAG,CAAC,mBAAmB,KAAK,YAAY,CAAC;QAC9E,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,MAAM,gBAAgB,GAAG,QAAQ,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC;QACnE,MAAM,WAAW,GAAG,gBAAgB;aACjC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,iBAAiB,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,mBAAmB,CAAC;aACjF,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,EAAE,gBAAgB,EAAE,cAAc,IAAI,EAAE,CAAC;QAC5E,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,EAAE,gBAAgB,EAAE,eAAe,IAAI,EAAE,CAAC;QAC9E,MAAM,aAAa,GAAG,QAAQ,CAAC,sBAAsB,EAAE,QAAQ,IAAI,EAAE,CAAC;QACtE,MAAM,cAAc,GAAG,QAAQ,CAAC,sBAAsB,EAAE,SAAS,IAAI,EAAE,CAAC;QAExE,MAAM,YAAY,GAAG,aAAa;aAC/B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvC,OAAO,WAAW,UAAU,CAAC,IAAI,CAAC,YAAY,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC;QAC1F,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,MAAM,aAAa,GAAG,cAAc;aACjC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxC,OAAO,WAAW,UAAU,CAAC,IAAI,CAAC,YAAY,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC;QAC1F,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC;aAC3D,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,WAAW,UAAU,CAAC,IAAI,CAAC,YAAY,KAAK,YAAY,CAAC;aAChF,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;aAC9D,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;YACtB,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;iBAChC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,WAAW,UAAU,CAAC,KAAK,CAAC,YAAY,KAAK,YAAY,CAAC;iBAClF,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,OAAO;kBACC,UAAU,CAAC,IAAI,CAAC;;;uBAGX,IAAI,IAAI,yCAAyC;;WAE7D,CAAC;QACJ,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,OAAO;gCACmB,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAChD,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC;uCACT,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,6BACzD,QAAQ,CAAC,IAAI,CAAC,MAChB,kCAAkC,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC;;;;;qBAKpD,YAAY,IAAI,6CAA6C;;;;;;qBAM7D,WAAW,IAAI,kCAAkC;;;;;;qBAMjD,YAAY,IAAI,iDAAiD;;;;;;qBAMjE,aAAa,IAAI,kDAAkD;;;;;;qBAMnE,QAAQ,IAAI,6CAA6C;;;YAGlE,eAAe,CAAC,CAAC,CAAC,4BAA4B,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE;;;;mBAI7D,UAAU,CAAC,QAAQ,CAAC,iBAAiB,IAAI,EAAE,CAAC;;;OAGxD,CAAC;IACJ,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAsHO,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;mBAChC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;qBACpC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;qBACxC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;QAErD,OAAO,CAAC,QAAQ,CAAC,UAAU;QACzB,CAAC,CAAC,qBAAqB,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;QAChE,CAAC,CAAC,EACN;;;;;;+DAOE,OAAO,CAAC,OAAO,CAAC,eAClB;0DACoD,OAAO,CAAC,OAAO,CAAC,UAAU;yDAC3B,aAAa,CAC9D,OAAO,CAAC,OAAO,CAAC,SAAS,CAC1B;kEAC2D,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,OAAO,CACxG,CAAC,CACF;gEAEC,OAAO,CAAC,OAAO,CAAC,mBAAmB,KAAK,IAAI;QAC1C,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,KACvD;;;;;;;;;;;;;;;;;;;;;;;YAuBM,YAAY;;;;;;;QAOhB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCZ,CAAC,IAAI,EAAE,CAAC;AACX,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ResultsJson } from '@inspectr/mcplab-core';
2
+ export declare function renderReport(results: ResultsJson): string;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAEzD"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ import { renderHtml } from './html.js';
2
+ export function renderReport(results) {
3
+ return renderHtml(results);
4
+ }
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,UAAU,YAAY,CAAC,OAAoB;IAC/C,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@inspectr/mcplab-reporting",
3
+ "version": "0.1.0",
4
+ "description": "HTML report generation for MCPLab evaluation runs",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/inspectr-hq/mcplab.git"
9
+ },
10
+ "keywords": [
11
+ "mcp",
12
+ "model-context-protocol",
13
+ "llm",
14
+ "evaluation",
15
+ "reporting"
16
+ ],
17
+ "engines": {
18
+ "node": ">=20.19.0"
19
+ },
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "type": "module",
24
+ "main": "dist/index.js",
25
+ "types": "dist/index.d.ts",
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "exports": {
30
+ ".": "./dist/index.js"
31
+ },
32
+ "scripts": {
33
+ "build": "tsc -b"
34
+ },
35
+ "dependencies": {
36
+ "@inspectr/mcplab-core": "0.1.0"
37
+ }
38
+ }