monora-ai 2.1.0 → 2.1.4
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 +339 -158
- package/dist/aims_governance.d.ts +238 -0
- package/dist/aims_governance.d.ts.map +1 -0
- package/dist/aims_governance.js +922 -0
- package/dist/alerts.d.ts +16 -0
- package/dist/alerts.d.ts.map +1 -1
- package/dist/alerts.js +16 -0
- package/dist/api.d.ts +6 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +6 -0
- package/dist/assessment.d.ts +85 -0
- package/dist/assessment.d.ts.map +1 -1
- package/dist/assessment.js +525 -13
- package/dist/attribution.d.ts +44 -3
- package/dist/attribution.d.ts.map +1 -1
- package/dist/attribution.js +197 -10
- package/dist/autodetect.d.ts +68 -0
- package/dist/autodetect.d.ts.map +1 -1
- package/dist/autodetect.js +639 -0
- package/dist/bias.d.ts +130 -0
- package/dist/bias.d.ts.map +1 -0
- package/dist/bias.js +223 -0
- package/dist/cli/diagnostics.d.ts +5 -1
- package/dist/cli/diagnostics.d.ts.map +1 -1
- package/dist/cli/diagnostics.js +23 -6
- package/dist/cli/doctor.d.ts +25 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +381 -0
- package/dist/cli/fix.d.ts +16 -0
- package/dist/cli/fix.d.ts.map +1 -0
- package/dist/cli/fix.js +284 -0
- package/dist/cli/init.d.ts +57 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +205 -0
- package/dist/cli.js +1564 -177
- package/dist/complianceConsolidation.d.ts +17 -0
- package/dist/complianceConsolidation.d.ts.map +1 -0
- package/dist/complianceConsolidation.js +68 -0
- package/dist/complianceTargets.d.ts +111 -0
- package/dist/complianceTargets.d.ts.map +1 -0
- package/dist/complianceTargets.js +521 -0
- package/dist/config.d.ts +261 -16
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +381 -32
- package/dist/config_migrations.d.ts.map +1 -1
- package/dist/config_migrations.js +38 -1
- package/dist/config_schema.d.ts +2490 -1035
- package/dist/config_schema.d.ts.map +1 -1
- package/dist/config_schema.js +233 -64
- package/dist/context.d.ts +34 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +118 -7
- package/dist/control_backbone.d.ts +128 -0
- package/dist/control_backbone.d.ts.map +1 -0
- package/dist/control_backbone.js +826 -0
- package/dist/data-governance.d.ts +187 -0
- package/dist/data-governance.d.ts.map +1 -0
- package/dist/data-governance.js +424 -0
- package/dist/dataResidency.d.ts +44 -0
- package/dist/dataResidency.d.ts.map +1 -0
- package/dist/dataResidency.js +203 -0
- package/dist/dispatcher.d.ts.map +1 -1
- package/dist/dispatcher.js +17 -5
- package/dist/evidence_store.d.ts +103 -0
- package/dist/evidence_store.d.ts.map +1 -0
- package/dist/evidence_store.js +459 -0
- package/dist/executiveSummary.d.ts +15 -0
- package/dist/executiveSummary.d.ts.map +1 -1
- package/dist/executiveSummary.js +135 -22
- package/dist/identity.d.ts +143 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +231 -0
- package/dist/impact-assessment.d.ts +350 -0
- package/dist/impact-assessment.d.ts.map +1 -0
- package/dist/impact-assessment.js +580 -0
- package/dist/index.d.ts +21 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +254 -5
- package/dist/instrumentation.d.ts +1 -1
- package/dist/instrumentation.d.ts.map +1 -1
- package/dist/instrumentation.js +123 -22
- package/dist/integrations/anthropic.d.ts +3 -0
- package/dist/integrations/anthropic.d.ts.map +1 -1
- package/dist/integrations/anthropic.js +282 -80
- package/dist/integrations/governance.d.ts +33 -0
- package/dist/integrations/governance.d.ts.map +1 -0
- package/dist/integrations/governance.js +208 -0
- package/dist/integrations/langchain.d.ts +4 -0
- package/dist/integrations/langchain.d.ts.map +1 -1
- package/dist/integrations/langchain.js +362 -142
- package/dist/integrations/openai.d.ts +9 -0
- package/dist/integrations/openai.d.ts.map +1 -1
- package/dist/integrations/openai.js +673 -73
- package/dist/iso42001_consolidation.d.ts +16 -0
- package/dist/iso42001_consolidation.d.ts.map +1 -0
- package/dist/iso42001_consolidation.js +413 -0
- package/dist/iso42001_workflows.d.ts +263 -0
- package/dist/iso42001_workflows.d.ts.map +1 -0
- package/dist/iso42001_workflows.js +781 -0
- package/dist/lifecycle.d.ts +299 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +624 -0
- package/dist/lineage.d.ts +2 -2
- package/dist/lineage.d.ts.map +1 -1
- package/dist/lineage.js +9 -16
- package/dist/middleware/express.d.ts.map +1 -1
- package/dist/middleware/express.js +18 -3
- package/dist/middleware/nextjs.js +2 -2
- package/dist/model.d.ts +143 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +371 -0
- package/dist/onboarding.d.ts +42 -0
- package/dist/onboarding.d.ts.map +1 -0
- package/dist/onboarding.js +1075 -0
- package/dist/oversight.d.ts +264 -0
- package/dist/oversight.d.ts.map +1 -0
- package/dist/oversight.js +497 -0
- package/dist/presets.js +7 -7
- package/dist/quotas.d.ts +171 -0
- package/dist/quotas.d.ts.map +1 -0
- package/dist/quotas.js +259 -0
- package/dist/register.d.ts +13 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +99 -0
- package/dist/registry.d.ts +1 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +7 -0
- package/dist/registryData.json +43 -6
- package/dist/report.d.ts +2 -1
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +189 -2
- package/dist/reporting.d.ts +125 -0
- package/dist/reporting.d.ts.map +1 -1
- package/dist/reporting.js +192 -2
- package/dist/resources.d.ts +285 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +643 -0
- package/dist/risk.d.ts +120 -0
- package/dist/risk.d.ts.map +1 -0
- package/dist/risk.js +220 -0
- package/dist/runtime.d.ts +74 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +416 -18
- package/dist/schemaInference.d.ts +92 -0
- package/dist/schemaInference.d.ts.map +1 -0
- package/dist/schemaInference.js +466 -0
- package/dist/schema_validation.js +2 -2
- package/dist/schemas/config.schema.json +118 -4
- package/dist/security_report.js +4 -4
- package/dist/signing.d.ts +1 -1
- package/dist/signing.d.ts.map +1 -1
- package/dist/signing.js +4 -0
- package/dist/sinks/file.d.ts +19 -1
- package/dist/sinks/file.d.ts.map +1 -1
- package/dist/sinks/file.js +82 -13
- package/dist/sinks/https.d.ts +10 -0
- package/dist/sinks/https.d.ts.map +1 -1
- package/dist/sinks/https.js +76 -16
- package/dist/sinks/stdout.d.ts +1 -0
- package/dist/sinks/stdout.d.ts.map +1 -1
- package/dist/sinks/stdout.js +12 -1
- package/dist/spec.d.ts +159 -0
- package/dist/spec.d.ts.map +1 -0
- package/dist/spec.js +391 -0
- package/dist/stakeholders.d.ts +199 -0
- package/dist/stakeholders.d.ts.map +1 -0
- package/dist/stakeholders.js +398 -0
- package/dist/standards.d.ts.map +1 -1
- package/dist/standards.js +160 -2
- package/dist/standards_ingest.d.ts.map +1 -1
- package/dist/standards_ingest.js +1 -4
- package/dist/telemetry.d.ts +16 -2
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +77 -14
- package/dist/templates/controls/gdpr_control_catalog.json +261 -0
- package/dist/templates/controls/iso42001_control_catalog.json +1443 -0
- package/dist/templates/controls/soc2_control_catalog.json +163 -0
- package/dist/templates/standards/iso42001_claims.json +72 -0
- package/dist/traced_emitter.d.ts.map +1 -1
- package/dist/traced_emitter.js +19 -9
- package/dist/trust_package.d.ts +20 -1
- package/dist/trust_package.d.ts.map +1 -1
- package/dist/trust_package.js +90 -2
- package/dist/verify.d.ts.map +1 -1
- package/dist/verify.js +9 -2
- package/dist/wal.d.ts.map +1 -1
- package/dist/wal.js +2 -1
- package/package.json +14 -1
- package/scripts/postinstall.js +105 -210
- package/templates/controls/gdpr_control_catalog.json +261 -0
- package/templates/controls/iso42001_control_catalog.json +1443 -0
- package/templates/controls/soc2_control_catalog.json +163 -0
- package/templates/standards/iso42001_claims.json +72 -0
package/dist/report.d.ts
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* CLI report generation utilities.
|
|
3
3
|
*/
|
|
4
4
|
import { MonoraConfig } from './config';
|
|
5
|
+
import { ModelRegistryConfig } from './registry';
|
|
5
6
|
export declare function loadJsonl(path: string): Array<Record<string, any>>;
|
|
6
|
-
export declare function buildReport(events: Array<Record<string, any>>, policies?: MonoraConfig['policies']): Record<string, any>;
|
|
7
|
+
export declare function buildReport(events: Array<Record<string, any>>, policies?: MonoraConfig['policies'], registryConfig?: ModelRegistryConfig): Record<string, any>;
|
|
7
8
|
export declare function buildUsageSummary(events: Array<Record<string, any>>): Record<string, any>;
|
|
8
9
|
export declare function writeJson(path: string, report: Record<string, any>): void;
|
|
9
10
|
export declare function writeMarkdown(path: string, report: Record<string, any>): void;
|
package/dist/report.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAiB,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAKhE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAelE;AAmPD,wBAAgB,WAAW,CACzB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EAClC,QAAQ,CAAC,EAAE,YAAY,CAAC,UAAU,CAAC,EACnC,cAAc,CAAC,EAAE,mBAAmB,GACnC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA8RrB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA2GzF;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAEzE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CA6E7E;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAmFnF"}
|
package/dist/report.js
CHANGED
|
@@ -43,6 +43,7 @@ exports.writeJson = writeJson;
|
|
|
43
43
|
exports.writeMarkdown = writeMarkdown;
|
|
44
44
|
exports.writeUsageMarkdown = writeUsageMarkdown;
|
|
45
45
|
const fs = __importStar(require("fs"));
|
|
46
|
+
const registry_1 = require("./registry");
|
|
46
47
|
const logger_1 = require("./logger");
|
|
47
48
|
function loadJsonl(path) {
|
|
48
49
|
const events = [];
|
|
@@ -164,6 +165,83 @@ function extractUsage(body) {
|
|
|
164
165
|
}
|
|
165
166
|
return null;
|
|
166
167
|
}
|
|
168
|
+
function coerceCost(value) {
|
|
169
|
+
if (value === null || value === undefined) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
const numberValue = Number(value);
|
|
173
|
+
return Number.isFinite(numberValue) ? numberValue : null;
|
|
174
|
+
}
|
|
175
|
+
function extractUsagePayload(body) {
|
|
176
|
+
const response = body.response;
|
|
177
|
+
if (response && typeof response === 'object' && response.usage && typeof response.usage === 'object') {
|
|
178
|
+
return response.usage;
|
|
179
|
+
}
|
|
180
|
+
if (body.usage && typeof body.usage === 'object') {
|
|
181
|
+
return body.usage;
|
|
182
|
+
}
|
|
183
|
+
if (body.token_usage && typeof body.token_usage === 'object') {
|
|
184
|
+
return body.token_usage;
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
function estimateCostFromPricing(pricing, usage) {
|
|
189
|
+
if (!pricing || typeof pricing !== 'object' || !usage) {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
const unit = String(pricing.unit || '1k_tokens').toLowerCase();
|
|
193
|
+
let scale = 1000;
|
|
194
|
+
if (unit === '1m_tokens' || unit === '1m' || unit === 'per_1m') {
|
|
195
|
+
scale = 1000000;
|
|
196
|
+
}
|
|
197
|
+
else if (unit === 'token' || unit === 'per_token') {
|
|
198
|
+
scale = 1;
|
|
199
|
+
}
|
|
200
|
+
const totalRate = coerceCost(pricing.cost_per_1k_tokens ||
|
|
201
|
+
pricing.total_cost_per_1k ||
|
|
202
|
+
pricing.cost_per_1m_tokens ||
|
|
203
|
+
pricing.total_cost_per_1m);
|
|
204
|
+
const promptRate = coerceCost(pricing.prompt_cost_per_1k ||
|
|
205
|
+
pricing.input_cost_per_1k ||
|
|
206
|
+
pricing.prompt_cost_per_1m ||
|
|
207
|
+
pricing.input_cost_per_1m);
|
|
208
|
+
const completionRate = coerceCost(pricing.completion_cost_per_1k ||
|
|
209
|
+
pricing.output_cost_per_1k ||
|
|
210
|
+
pricing.completion_cost_per_1m ||
|
|
211
|
+
pricing.output_cost_per_1m);
|
|
212
|
+
if (totalRate !== null) {
|
|
213
|
+
return (usage.total / scale) * totalRate;
|
|
214
|
+
}
|
|
215
|
+
if (promptRate === null && completionRate === null) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
let cost = 0;
|
|
219
|
+
if (promptRate !== null) {
|
|
220
|
+
cost += (usage.prompt / scale) * promptRate;
|
|
221
|
+
}
|
|
222
|
+
if (completionRate !== null) {
|
|
223
|
+
cost += (usage.completion / scale) * completionRate;
|
|
224
|
+
}
|
|
225
|
+
return cost;
|
|
226
|
+
}
|
|
227
|
+
function estimateCost(body, model, usage, registry) {
|
|
228
|
+
const usagePayload = extractUsagePayload(body);
|
|
229
|
+
if (usagePayload) {
|
|
230
|
+
for (const key of ['total_cost', 'cost', 'estimated_cost', 'total_cost_usd', 'cost_usd']) {
|
|
231
|
+
const value = usagePayload[key];
|
|
232
|
+
const cost = coerceCost(value);
|
|
233
|
+
if (cost !== null) {
|
|
234
|
+
return cost;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (!registry || !model) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
const metadata = registry.getModelMetadata(model);
|
|
242
|
+
const pricing = metadata && typeof metadata === 'object' ? metadata.pricing : null;
|
|
243
|
+
return estimateCostFromPricing(pricing, usage);
|
|
244
|
+
}
|
|
167
245
|
function classifyPolicyViolation(policyName) {
|
|
168
246
|
const lowered = policyName.toLowerCase();
|
|
169
247
|
if (lowered.includes('unknown_model')) {
|
|
@@ -194,8 +272,9 @@ function matchesAny(patterns, model, used) {
|
|
|
194
272
|
}
|
|
195
273
|
return false;
|
|
196
274
|
}
|
|
197
|
-
function buildReport(events, policies) {
|
|
275
|
+
function buildReport(events, policies, registryConfig) {
|
|
198
276
|
const filteredEvents = events.filter((event) => event.event_type !== 'trust_summary');
|
|
277
|
+
const registry = new registry_1.ModelRegistry(registryConfig || {});
|
|
199
278
|
const traceIds = new Set();
|
|
200
279
|
const timestamps = [];
|
|
201
280
|
const byEventType = {};
|
|
@@ -210,6 +289,12 @@ function buildReport(events, policies) {
|
|
|
210
289
|
missing_usage_events: 0,
|
|
211
290
|
missing_usage_models: [],
|
|
212
291
|
};
|
|
292
|
+
const costUsage = {
|
|
293
|
+
total_cost_usd: 0,
|
|
294
|
+
by_model: {},
|
|
295
|
+
missing_cost_events: 0,
|
|
296
|
+
missing_cost_models: [],
|
|
297
|
+
};
|
|
213
298
|
const violations = [];
|
|
214
299
|
const errors = [];
|
|
215
300
|
const modelsUsed = new Set();
|
|
@@ -218,9 +303,12 @@ function buildReport(events, policies) {
|
|
|
218
303
|
const allowedModelsUsed = new Set();
|
|
219
304
|
const usedAllowlistPatterns = new Set();
|
|
220
305
|
const missingUsageModels = new Set();
|
|
306
|
+
const missingCostModels = new Set();
|
|
221
307
|
let missingUsageEvents = 0;
|
|
308
|
+
let missingCostEvents = 0;
|
|
222
309
|
const modelEventIds = {};
|
|
223
310
|
const missingUsageEventIds = [];
|
|
311
|
+
const missingCostEventIds = [];
|
|
224
312
|
const unknownViolationEventIds = {};
|
|
225
313
|
const forbiddenViolationEventIds = {};
|
|
226
314
|
for (const event of filteredEvents) {
|
|
@@ -292,8 +380,9 @@ function buildReport(events, policies) {
|
|
|
292
380
|
}
|
|
293
381
|
modelEventIds[model].push(event.event_id);
|
|
294
382
|
}
|
|
383
|
+
let usage = null;
|
|
295
384
|
if (!isBlocked) {
|
|
296
|
-
|
|
385
|
+
usage = extractUsage(body);
|
|
297
386
|
if (!usage) {
|
|
298
387
|
missingUsageEvents += 1;
|
|
299
388
|
if (model) {
|
|
@@ -315,6 +404,25 @@ function buildReport(events, policies) {
|
|
|
315
404
|
}
|
|
316
405
|
}
|
|
317
406
|
}
|
|
407
|
+
if (!isBlocked) {
|
|
408
|
+
const cost = estimateCost(body, model, usage, registry);
|
|
409
|
+
if (cost === null) {
|
|
410
|
+
missingCostEvents += 1;
|
|
411
|
+
missingCostEventIds.push(event.event_id);
|
|
412
|
+
if (model) {
|
|
413
|
+
missingCostModels.add(model);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
costUsage.total_cost_usd += cost;
|
|
418
|
+
if (model) {
|
|
419
|
+
if (!costUsage.by_model[model]) {
|
|
420
|
+
costUsage.by_model[model] = { estimated_cost_usd: 0 };
|
|
421
|
+
}
|
|
422
|
+
costUsage.by_model[model].estimated_cost_usd += cost;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
318
426
|
}
|
|
319
427
|
if (body.error) {
|
|
320
428
|
errors.push({
|
|
@@ -368,6 +476,8 @@ function buildReport(events, policies) {
|
|
|
368
476
|
}
|
|
369
477
|
tokenUsage.missing_usage_events = missingUsageEvents;
|
|
370
478
|
tokenUsage.missing_usage_models = Array.from(missingUsageModels).sort();
|
|
479
|
+
costUsage.missing_cost_events = missingCostEvents;
|
|
480
|
+
costUsage.missing_cost_models = Array.from(missingCostModels).sort();
|
|
371
481
|
const unusedAllowlistPatterns = allowlistPatterns.length > 0
|
|
372
482
|
? allowlistPatterns
|
|
373
483
|
.map(([raw]) => raw)
|
|
@@ -413,6 +523,7 @@ function buildReport(events, policies) {
|
|
|
413
523
|
violations,
|
|
414
524
|
errors,
|
|
415
525
|
token_usage: tokenUsage,
|
|
526
|
+
cost_usage: costUsage,
|
|
416
527
|
model_compliance: {
|
|
417
528
|
allowed_models_used: Array.from(allowedModelsUsed).sort(),
|
|
418
529
|
forbidden_models_blocked: Array.from(forbiddenModelsBlocked).sort(),
|
|
@@ -427,17 +538,23 @@ function buildReport(events, policies) {
|
|
|
427
538
|
forbidden_models: forbiddenModelsEvidence,
|
|
428
539
|
errors,
|
|
429
540
|
missing_usage_events: dedupe(missingUsageEventIds),
|
|
541
|
+
missing_cost_events: dedupe(missingCostEventIds),
|
|
430
542
|
},
|
|
431
543
|
};
|
|
432
544
|
}
|
|
433
545
|
function buildUsageSummary(events) {
|
|
434
546
|
const filteredEvents = events.filter((event) => event.event_type !== 'trust_summary');
|
|
547
|
+
const registry = new registry_1.ModelRegistry({});
|
|
435
548
|
const traceIds = new Set();
|
|
436
549
|
const timestamps = [];
|
|
437
550
|
const dailyCounts = {};
|
|
438
551
|
const apiByType = {};
|
|
439
552
|
const apiStatusCounts = {};
|
|
440
553
|
const modelCounts = {};
|
|
554
|
+
const costByModel = {};
|
|
555
|
+
let totalCostUsd = 0;
|
|
556
|
+
let missingCostEvents = 0;
|
|
557
|
+
const missingCostModels = new Set();
|
|
441
558
|
let sdkInits = 0;
|
|
442
559
|
for (const event of filteredEvents) {
|
|
443
560
|
if (event.trace_id) {
|
|
@@ -465,6 +582,22 @@ function buildUsageSummary(events) {
|
|
|
465
582
|
if (model) {
|
|
466
583
|
modelCounts[model] = (modelCounts[model] || 0) + 1;
|
|
467
584
|
}
|
|
585
|
+
if (status !== 'policy_violation') {
|
|
586
|
+
const usage = extractUsage(body);
|
|
587
|
+
const cost = estimateCost(body, model, usage, registry);
|
|
588
|
+
if (cost === null) {
|
|
589
|
+
missingCostEvents += 1;
|
|
590
|
+
if (model) {
|
|
591
|
+
missingCostModels.add(model);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
else {
|
|
595
|
+
totalCostUsd += cost;
|
|
596
|
+
if (model) {
|
|
597
|
+
costByModel[model] = (costByModel[model] || 0) + cost;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
468
601
|
}
|
|
469
602
|
}
|
|
470
603
|
}
|
|
@@ -484,6 +617,10 @@ function buildUsageSummary(events) {
|
|
|
484
617
|
.sort(([, a], [, b]) => b - a)
|
|
485
618
|
.slice(0, 5)
|
|
486
619
|
.map(([model, count]) => ({ model, count }));
|
|
620
|
+
const topCostModels = Object.entries(costByModel)
|
|
621
|
+
.sort(([, a], [, b]) => b - a)
|
|
622
|
+
.slice(0, 5)
|
|
623
|
+
.map(([model, cost]) => ({ model, estimated_cost_usd: cost }));
|
|
487
624
|
return {
|
|
488
625
|
period: { start, end },
|
|
489
626
|
total_events: filteredEvents.length,
|
|
@@ -498,6 +635,13 @@ function buildUsageSummary(events) {
|
|
|
498
635
|
active_days: Object.keys(dailyCounts).length,
|
|
499
636
|
daily_activity: dailyActivity,
|
|
500
637
|
top_models: topModels,
|
|
638
|
+
cost_usage: {
|
|
639
|
+
total_cost_usd: totalCostUsd,
|
|
640
|
+
by_model: costByModel,
|
|
641
|
+
missing_cost_events: missingCostEvents,
|
|
642
|
+
missing_cost_models: Array.from(missingCostModels).sort(),
|
|
643
|
+
},
|
|
644
|
+
top_cost_models: topCostModels,
|
|
501
645
|
};
|
|
502
646
|
}
|
|
503
647
|
function writeJson(path, report) {
|
|
@@ -522,6 +666,29 @@ function writeMarkdown(path, report) {
|
|
|
522
666
|
for (const [model, count] of Object.entries(report.by_model || {})) {
|
|
523
667
|
lines.push(`- ${model}: ${count} calls`);
|
|
524
668
|
}
|
|
669
|
+
const costUsage = report.cost_usage || {};
|
|
670
|
+
if (Object.keys(costUsage).length > 0) {
|
|
671
|
+
const totalCost = typeof costUsage.total_cost_usd === 'number'
|
|
672
|
+
? costUsage.total_cost_usd.toFixed(6)
|
|
673
|
+
: 'N/A';
|
|
674
|
+
lines.push('');
|
|
675
|
+
lines.push('## Cost Usage');
|
|
676
|
+
lines.push(`- Total estimated cost (USD): ${totalCost}`);
|
|
677
|
+
const byModelCost = costUsage.by_model || {};
|
|
678
|
+
const sortedModels = Object.entries(byModelCost)
|
|
679
|
+
.sort(([, a], [, b]) => (b.estimated_cost_usd || 0) - (a.estimated_cost_usd || 0))
|
|
680
|
+
.slice(0, 5);
|
|
681
|
+
if (sortedModels.length > 0) {
|
|
682
|
+
lines.push('- By model:');
|
|
683
|
+
for (const [model, data] of sortedModels) {
|
|
684
|
+
const costData = data;
|
|
685
|
+
const costValue = costData && typeof costData.estimated_cost_usd === 'number'
|
|
686
|
+
? costData.estimated_cost_usd.toFixed(6)
|
|
687
|
+
: '0.000000';
|
|
688
|
+
lines.push(` - ${model}: ${costValue}`);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
525
692
|
const violations = report.violations || [];
|
|
526
693
|
lines.push('');
|
|
527
694
|
lines.push(`## Policy Violations (${violations.length})`);
|
|
@@ -584,6 +751,26 @@ function writeUsageMarkdown(path, summary) {
|
|
|
584
751
|
lines.push(` - ${status}: ${count}`);
|
|
585
752
|
}
|
|
586
753
|
}
|
|
754
|
+
const costUsage = summary.cost_usage || {};
|
|
755
|
+
if (Object.keys(costUsage).length > 0) {
|
|
756
|
+
const totalCost = typeof costUsage.total_cost_usd === 'number'
|
|
757
|
+
? costUsage.total_cost_usd.toFixed(6)
|
|
758
|
+
: 'N/A';
|
|
759
|
+
lines.push('');
|
|
760
|
+
lines.push('## Cost Usage');
|
|
761
|
+
lines.push(`- Total estimated cost (USD): ${totalCost}`);
|
|
762
|
+
const topCostModels = summary.top_cost_models || [];
|
|
763
|
+
if (topCostModels.length > 0) {
|
|
764
|
+
lines.push('- Top models by cost:');
|
|
765
|
+
for (const entry of topCostModels) {
|
|
766
|
+
const model = entry.model;
|
|
767
|
+
const costValue = typeof entry.estimated_cost_usd === 'number'
|
|
768
|
+
? entry.estimated_cost_usd.toFixed(6)
|
|
769
|
+
: '0.000000';
|
|
770
|
+
lines.push(` - ${model}: ${costValue}`);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
587
774
|
lines.push('');
|
|
588
775
|
lines.push('## Daily Activity');
|
|
589
776
|
const dailyActivity = summary.daily_activity || [];
|
package/dist/reporting.d.ts
CHANGED
|
@@ -3,6 +3,131 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { MonoraConfig } from './config';
|
|
5
5
|
export declare const TRUST_SUMMARY_EVENT_TYPE = "trust_summary";
|
|
6
|
+
export declare const COMPLIANCE_DRIFT_EVENT_TYPE = "compliance_drift";
|
|
7
|
+
/**
|
|
8
|
+
* Compliance score snapshot for monitoring.
|
|
9
|
+
*/
|
|
10
|
+
export interface ComplianceScoreSnapshot {
|
|
11
|
+
traceId: string;
|
|
12
|
+
score: number;
|
|
13
|
+
grade: string;
|
|
14
|
+
timestamp: string;
|
|
15
|
+
framework?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Compliance drift event data.
|
|
19
|
+
*/
|
|
20
|
+
export interface ComplianceDriftEvent {
|
|
21
|
+
eventType: typeof COMPLIANCE_DRIFT_EVENT_TYPE;
|
|
22
|
+
previousScore: number;
|
|
23
|
+
currentScore: number;
|
|
24
|
+
scoreDelta: number;
|
|
25
|
+
previousGrade: string;
|
|
26
|
+
currentGrade: string;
|
|
27
|
+
traceId: string;
|
|
28
|
+
previousTraceId: string;
|
|
29
|
+
timestamp: string;
|
|
30
|
+
driftDirection: 'improved' | 'degraded' | 'stable';
|
|
31
|
+
threshold: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Callback for compliance drift events.
|
|
35
|
+
*/
|
|
36
|
+
export type ComplianceDriftCallback = (event: ComplianceDriftEvent) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Options for compliance monitoring.
|
|
39
|
+
*/
|
|
40
|
+
export interface ComplianceMonitorOptions {
|
|
41
|
+
/** Score change threshold to trigger drift event (default: 5) */
|
|
42
|
+
driftThreshold?: number;
|
|
43
|
+
/** Maximum number of snapshots to retain (default: 100) */
|
|
44
|
+
maxSnapshots?: number;
|
|
45
|
+
/** Framework to monitor (optional, monitors all if not set) */
|
|
46
|
+
framework?: string;
|
|
47
|
+
/** Callback for drift events */
|
|
48
|
+
onDrift?: ComplianceDriftCallback;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Continuous compliance monitoring for tracking score changes.
|
|
52
|
+
*
|
|
53
|
+
* Monitors compliance scores across traces and emits drift events
|
|
54
|
+
* when scores change significantly.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const monitor = new ComplianceMonitor({
|
|
59
|
+
* driftThreshold: 5,
|
|
60
|
+
* onDrift: (event) => {
|
|
61
|
+
* if (event.driftDirection === 'degraded') {
|
|
62
|
+
* console.warn(`Compliance degraded: ${event.scoreDelta} points`);
|
|
63
|
+
* }
|
|
64
|
+
* },
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* // Record score after each trace
|
|
68
|
+
* monitor.recordScore('trace_1', 85, 'B');
|
|
69
|
+
* monitor.recordScore('trace_2', 78, 'C'); // Triggers drift event
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export declare class ComplianceMonitor {
|
|
73
|
+
private snapshots;
|
|
74
|
+
private driftThreshold;
|
|
75
|
+
private maxSnapshots;
|
|
76
|
+
private framework?;
|
|
77
|
+
private onDrift?;
|
|
78
|
+
private driftCallbacks;
|
|
79
|
+
constructor(options?: ComplianceMonitorOptions);
|
|
80
|
+
/**
|
|
81
|
+
* Record a compliance score snapshot.
|
|
82
|
+
*
|
|
83
|
+
* @param traceId - Trace identifier
|
|
84
|
+
* @param score - Compliance score (0-100)
|
|
85
|
+
* @param grade - Grade letter (A-F)
|
|
86
|
+
* @param framework - Optional framework name
|
|
87
|
+
* @returns Drift event if threshold exceeded, null otherwise
|
|
88
|
+
*/
|
|
89
|
+
recordScore(traceId: string, score: number, grade: string, framework?: string): ComplianceDriftEvent | null;
|
|
90
|
+
/**
|
|
91
|
+
* Get the latest score snapshot.
|
|
92
|
+
*/
|
|
93
|
+
getLatestSnapshot(): ComplianceScoreSnapshot | null;
|
|
94
|
+
/**
|
|
95
|
+
* Get all score snapshots.
|
|
96
|
+
*/
|
|
97
|
+
getSnapshots(): ComplianceScoreSnapshot[];
|
|
98
|
+
/**
|
|
99
|
+
* Get score trend (average change over recent snapshots).
|
|
100
|
+
*
|
|
101
|
+
* @param windowSize - Number of recent snapshots to consider (default: 5)
|
|
102
|
+
*/
|
|
103
|
+
getScoreTrend(windowSize?: number): {
|
|
104
|
+
trend: 'improving' | 'degrading' | 'stable';
|
|
105
|
+
avgChange: number;
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Get compliance statistics.
|
|
109
|
+
*/
|
|
110
|
+
getStatistics(): {
|
|
111
|
+
currentScore: number | null;
|
|
112
|
+
averageScore: number;
|
|
113
|
+
minScore: number;
|
|
114
|
+
maxScore: number;
|
|
115
|
+
snapshotCount: number;
|
|
116
|
+
trend: 'improving' | 'degrading' | 'stable';
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Register a callback for drift events.
|
|
120
|
+
*
|
|
121
|
+
* @param callback - Function to call on drift
|
|
122
|
+
* @returns Unsubscribe function
|
|
123
|
+
*/
|
|
124
|
+
onDriftEvent(callback: ComplianceDriftCallback): () => void;
|
|
125
|
+
/**
|
|
126
|
+
* Clear all snapshots.
|
|
127
|
+
*/
|
|
128
|
+
reset(): void;
|
|
129
|
+
private notifyDrift;
|
|
130
|
+
}
|
|
6
131
|
interface RegistryMetadata {
|
|
7
132
|
version?: string;
|
|
8
133
|
hash?: string;
|
package/dist/reporting.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporting.d.ts","sourceRoot":"","sources":["../src/reporting.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAWxC,eAAO,MAAM,wBAAwB,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"reporting.d.ts","sourceRoot":"","sources":["../src/reporting.ts"],"names":[],"mappings":"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"}
|
package/dist/reporting.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.TraceReportManager = exports.TRUST_SUMMARY_EVENT_TYPE = void 0;
|
|
39
|
+
exports.TraceReportManager = exports.ComplianceMonitor = exports.COMPLIANCE_DRIFT_EVENT_TYPE = exports.TRUST_SUMMARY_EVENT_TYPE = void 0;
|
|
40
40
|
const crypto = __importStar(require("crypto"));
|
|
41
41
|
const fs = __importStar(require("fs"));
|
|
42
42
|
const path = __importStar(require("path"));
|
|
@@ -47,6 +47,196 @@ const report_1 = require("./report");
|
|
|
47
47
|
const security_report_1 = require("./security_report");
|
|
48
48
|
const verify_1 = require("./verify");
|
|
49
49
|
exports.TRUST_SUMMARY_EVENT_TYPE = 'trust_summary';
|
|
50
|
+
exports.COMPLIANCE_DRIFT_EVENT_TYPE = 'compliance_drift';
|
|
51
|
+
/**
|
|
52
|
+
* Continuous compliance monitoring for tracking score changes.
|
|
53
|
+
*
|
|
54
|
+
* Monitors compliance scores across traces and emits drift events
|
|
55
|
+
* when scores change significantly.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const monitor = new ComplianceMonitor({
|
|
60
|
+
* driftThreshold: 5,
|
|
61
|
+
* onDrift: (event) => {
|
|
62
|
+
* if (event.driftDirection === 'degraded') {
|
|
63
|
+
* console.warn(`Compliance degraded: ${event.scoreDelta} points`);
|
|
64
|
+
* }
|
|
65
|
+
* },
|
|
66
|
+
* });
|
|
67
|
+
*
|
|
68
|
+
* // Record score after each trace
|
|
69
|
+
* monitor.recordScore('trace_1', 85, 'B');
|
|
70
|
+
* monitor.recordScore('trace_2', 78, 'C'); // Triggers drift event
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
class ComplianceMonitor {
|
|
74
|
+
constructor(options = {}) {
|
|
75
|
+
this.snapshots = [];
|
|
76
|
+
this.driftCallbacks = [];
|
|
77
|
+
this.driftThreshold = options.driftThreshold ?? 5;
|
|
78
|
+
this.maxSnapshots = options.maxSnapshots ?? 100;
|
|
79
|
+
this.framework = options.framework;
|
|
80
|
+
this.onDrift = options.onDrift;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Record a compliance score snapshot.
|
|
84
|
+
*
|
|
85
|
+
* @param traceId - Trace identifier
|
|
86
|
+
* @param score - Compliance score (0-100)
|
|
87
|
+
* @param grade - Grade letter (A-F)
|
|
88
|
+
* @param framework - Optional framework name
|
|
89
|
+
* @returns Drift event if threshold exceeded, null otherwise
|
|
90
|
+
*/
|
|
91
|
+
recordScore(traceId, score, grade, framework) {
|
|
92
|
+
const snapshot = {
|
|
93
|
+
traceId,
|
|
94
|
+
score,
|
|
95
|
+
grade,
|
|
96
|
+
timestamp: new Date().toISOString(),
|
|
97
|
+
framework,
|
|
98
|
+
};
|
|
99
|
+
const previousSnapshot = this.getLatestSnapshot();
|
|
100
|
+
this.snapshots.push(snapshot);
|
|
101
|
+
// Trim old snapshots
|
|
102
|
+
if (this.snapshots.length > this.maxSnapshots) {
|
|
103
|
+
this.snapshots = this.snapshots.slice(-this.maxSnapshots);
|
|
104
|
+
}
|
|
105
|
+
// Check for drift
|
|
106
|
+
if (previousSnapshot) {
|
|
107
|
+
const scoreDelta = score - previousSnapshot.score;
|
|
108
|
+
const absDelta = Math.abs(scoreDelta);
|
|
109
|
+
if (absDelta >= this.driftThreshold) {
|
|
110
|
+
const driftEvent = {
|
|
111
|
+
eventType: exports.COMPLIANCE_DRIFT_EVENT_TYPE,
|
|
112
|
+
previousScore: previousSnapshot.score,
|
|
113
|
+
currentScore: score,
|
|
114
|
+
scoreDelta,
|
|
115
|
+
previousGrade: previousSnapshot.grade,
|
|
116
|
+
currentGrade: grade,
|
|
117
|
+
traceId,
|
|
118
|
+
previousTraceId: previousSnapshot.traceId,
|
|
119
|
+
timestamp: snapshot.timestamp,
|
|
120
|
+
driftDirection: scoreDelta > 0 ? 'improved' : scoreDelta < 0 ? 'degraded' : 'stable',
|
|
121
|
+
threshold: this.driftThreshold,
|
|
122
|
+
};
|
|
123
|
+
// Notify callbacks
|
|
124
|
+
this.notifyDrift(driftEvent);
|
|
125
|
+
return driftEvent;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Get the latest score snapshot.
|
|
132
|
+
*/
|
|
133
|
+
getLatestSnapshot() {
|
|
134
|
+
return this.snapshots.length > 0 ? this.snapshots[this.snapshots.length - 1] : null;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get all score snapshots.
|
|
138
|
+
*/
|
|
139
|
+
getSnapshots() {
|
|
140
|
+
return [...this.snapshots];
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get score trend (average change over recent snapshots).
|
|
144
|
+
*
|
|
145
|
+
* @param windowSize - Number of recent snapshots to consider (default: 5)
|
|
146
|
+
*/
|
|
147
|
+
getScoreTrend(windowSize = 5) {
|
|
148
|
+
if (this.snapshots.length < 2) {
|
|
149
|
+
return { trend: 'stable', avgChange: 0 };
|
|
150
|
+
}
|
|
151
|
+
const recentSnapshots = this.snapshots.slice(-windowSize);
|
|
152
|
+
if (recentSnapshots.length < 2) {
|
|
153
|
+
return { trend: 'stable', avgChange: 0 };
|
|
154
|
+
}
|
|
155
|
+
let totalChange = 0;
|
|
156
|
+
for (let i = 1; i < recentSnapshots.length; i++) {
|
|
157
|
+
totalChange += recentSnapshots[i].score - recentSnapshots[i - 1].score;
|
|
158
|
+
}
|
|
159
|
+
const avgChange = totalChange / (recentSnapshots.length - 1);
|
|
160
|
+
let trend;
|
|
161
|
+
if (avgChange > 1) {
|
|
162
|
+
trend = 'improving';
|
|
163
|
+
}
|
|
164
|
+
else if (avgChange < -1) {
|
|
165
|
+
trend = 'degrading';
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
trend = 'stable';
|
|
169
|
+
}
|
|
170
|
+
return { trend, avgChange: Number(avgChange.toFixed(2)) };
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get compliance statistics.
|
|
174
|
+
*/
|
|
175
|
+
getStatistics() {
|
|
176
|
+
if (this.snapshots.length === 0) {
|
|
177
|
+
return {
|
|
178
|
+
currentScore: null,
|
|
179
|
+
averageScore: 0,
|
|
180
|
+
minScore: 0,
|
|
181
|
+
maxScore: 0,
|
|
182
|
+
snapshotCount: 0,
|
|
183
|
+
trend: 'stable',
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
const scores = this.snapshots.map((s) => s.score);
|
|
187
|
+
const sum = scores.reduce((a, b) => a + b, 0);
|
|
188
|
+
return {
|
|
189
|
+
currentScore: scores[scores.length - 1],
|
|
190
|
+
averageScore: Number((sum / scores.length).toFixed(2)),
|
|
191
|
+
minScore: Math.min(...scores),
|
|
192
|
+
maxScore: Math.max(...scores),
|
|
193
|
+
snapshotCount: this.snapshots.length,
|
|
194
|
+
trend: this.getScoreTrend().trend,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Register a callback for drift events.
|
|
199
|
+
*
|
|
200
|
+
* @param callback - Function to call on drift
|
|
201
|
+
* @returns Unsubscribe function
|
|
202
|
+
*/
|
|
203
|
+
onDriftEvent(callback) {
|
|
204
|
+
this.driftCallbacks.push(callback);
|
|
205
|
+
return () => {
|
|
206
|
+
const index = this.driftCallbacks.indexOf(callback);
|
|
207
|
+
if (index !== -1) {
|
|
208
|
+
this.driftCallbacks.splice(index, 1);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Clear all snapshots.
|
|
214
|
+
*/
|
|
215
|
+
reset() {
|
|
216
|
+
this.snapshots = [];
|
|
217
|
+
}
|
|
218
|
+
notifyDrift(event) {
|
|
219
|
+
// Call constructor callback
|
|
220
|
+
if (this.onDrift) {
|
|
221
|
+
try {
|
|
222
|
+
this.onDrift(event);
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// Ignore callback errors
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// Call registered callbacks
|
|
229
|
+
for (const callback of this.driftCallbacks) {
|
|
230
|
+
try {
|
|
231
|
+
callback(event);
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
// Ignore callback errors
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
exports.ComplianceMonitor = ComplianceMonitor;
|
|
50
240
|
class TraceReportManager {
|
|
51
241
|
constructor(config) {
|
|
52
242
|
this.eventsByTrace = new Map();
|
|
@@ -113,7 +303,7 @@ class TraceReportManager {
|
|
|
113
303
|
this.eventsByTrace.delete(traceId);
|
|
114
304
|
const dropped = this.droppedByTrace.get(traceId) || 0;
|
|
115
305
|
this.droppedByTrace.delete(traceId);
|
|
116
|
-
const report = (0, report_1.buildReport)(events, this.config.policies || {});
|
|
306
|
+
const report = (0, report_1.buildReport)(events, this.config.policies || {}, this.config.registry);
|
|
117
307
|
const artifacts = [];
|
|
118
308
|
const reportPaths = {};
|
|
119
309
|
let reportDir = resolveReportDir(this.outputDir, traceId);
|