MCPcopy Create free account
hub / github.com/adcontextprotocol/adcp / handleReportUsage

Function handleReportUsage

server/src/training-agent/task-handlers.ts:3375–3468  ·  view source on GitHub ↗
(args: ToolArgs, ctx: TrainingContext)

Source from the content-addressed store, hash-verified

3373}
3374
3375export async function handleReportUsage(args: ToolArgs, ctx: TrainingContext) {
3376 const req = args as unknown as ReportUsageArgs;
3377 const session = await getSession(sessionKeyFromArgs(req, ctx.mode, ctx.userId, ctx.moduleId));
3378
3379 if (!req.reporting_period || !req.usage?.length) {
3380 return { errors: [{ code: 'INVALID_USAGE_DATA', message: 'reporting_period and at least one usage record are required.' }] };
3381 }
3382
3383 if (session.usageRecords.length + req.usage.length > MAX_USAGE_RECORDS_PER_SESSION) {
3384 return { errors: [{ code: 'LIMIT_EXCEEDED', message: `Usage record limit (${MAX_USAGE_RECORDS_PER_SESSION}) would be exceeded.` }] };
3385 }
3386
3387 let accepted = 0;
3388 const errors: Array<{ code: string; message: string; field?: string }> = [];
3389
3390 for (let i = 0; i < req.usage.length; i++) {
3391 const record = req.usage[i];
3392
3393 // Validate required fields
3394 if (record.vendor_cost === undefined || record.vendor_cost === null) {
3395 errors.push({ code: 'INVALID_USAGE_DATA', message: 'vendor_cost is required.', field: `usage[${i}].vendor_cost` });
3396 continue;
3397 }
3398 if (record.vendor_cost < 0) {
3399 errors.push({ code: 'INVALID_USAGE_DATA', message: 'vendor_cost must be non-negative.', field: `usage[${i}].vendor_cost` });
3400 continue;
3401 }
3402 if (!record.currency) {
3403 errors.push({ code: 'INVALID_USAGE_DATA', message: 'currency is required.', field: `usage[${i}].currency` });
3404 continue;
3405 }
3406 if (!record.account) {
3407 errors.push({ code: 'INVALID_USAGE_DATA', message: 'account is required.', field: `usage[${i}].account` });
3408 continue;
3409 }
3410 if (record.impressions !== undefined && record.impressions < 0) {
3411 errors.push({ code: 'INVALID_USAGE_DATA', message: 'impressions must be non-negative.', field: `usage[${i}].impressions` });
3412 continue;
3413 }
3414
3415 // Validate creative_id exists if provided
3416 if (record.creative_id) {
3417 const creative = session.creatives.get(record.creative_id) ?? getComplianceCreative(record.creative_id);
3418 if (!creative) {
3419 errors.push({ code: 'NOT_FOUND', message: `Creative "${record.creative_id}" not found in session.`, field: `usage[${i}].creative_id` });
3420 continue;
3421 }
3422
3423 // Validate pricing_option_id matches if provided
3424 if (record.pricing_option_id && creative.pricingOptionId && record.pricing_option_id !== creative.pricingOptionId) {
3425 errors.push({
3426 code: 'INVALID_PRICING_OPTION',
3427 message: `pricing_option_id mismatch: expected ${creative.pricingOptionId}, received ${record.pricing_option_id}`,
3428 field: `usage[${i}].pricing_option_id`,
3429 });
3430 continue;
3431 }
3432 }

Callers

nothing calls this directly

Calls 4

getSessionFunction · 0.85
sessionKeyFromArgsFunction · 0.85
getComplianceCreativeFunction · 0.85
getMethod · 0.45

Tested by

no test coverage detected