@vitest-evals/github-reporter 0.16.1 → 0.17.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/cli.js +150 -43
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +150 -43
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +150 -43
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +150 -43
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -323,7 +323,8 @@ function collectEvalReport(input, options = {}) {
|
|
|
323
323
|
const cases = workspace.cases.map(collectEvalCase);
|
|
324
324
|
const failures = cases.filter((testCase) => testCase.status === "failed");
|
|
325
325
|
const evalScores = cases.map((testCase) => testCase.eval?.avgScore).filter((score) => isFiniteNumber(score));
|
|
326
|
-
const usage2 =
|
|
326
|
+
const usage2 = sumAppUsage(cases);
|
|
327
|
+
const judgeUsage = sumJudgeUsage(cases);
|
|
327
328
|
const durationMs = workspace.runs[0]?.durationMs;
|
|
328
329
|
return {
|
|
329
330
|
status: input.success && failures.length === 0 ? "passed" : "failed",
|
|
@@ -343,6 +344,7 @@ function collectEvalReport(input, options = {}) {
|
|
|
343
344
|
minimum: Math.min(...evalScores)
|
|
344
345
|
} : void 0,
|
|
345
346
|
usage: usage2,
|
|
347
|
+
judgeUsage,
|
|
346
348
|
cases,
|
|
347
349
|
failures
|
|
348
350
|
};
|
|
@@ -467,24 +469,67 @@ function stringifyReason(value) {
|
|
|
467
469
|
}
|
|
468
470
|
return typeof value === "string" ? value : stringifyValue(value, 4e3);
|
|
469
471
|
}
|
|
470
|
-
function
|
|
471
|
-
|
|
472
|
+
function emptyUsage() {
|
|
473
|
+
return {
|
|
472
474
|
inputTokens: 0,
|
|
473
475
|
outputTokens: 0,
|
|
474
476
|
reasoningTokens: 0,
|
|
475
477
|
totalTokens: 0,
|
|
476
478
|
toolCalls: 0
|
|
477
479
|
};
|
|
480
|
+
}
|
|
481
|
+
function addRunUsage(total, usage2) {
|
|
482
|
+
total.inputTokens += usage2?.inputTokens ?? 0;
|
|
483
|
+
total.outputTokens += usage2?.outputTokens ?? 0;
|
|
484
|
+
total.reasoningTokens += usage2?.reasoningTokens ?? 0;
|
|
485
|
+
total.totalTokens += usage2?.totalTokens ?? (usage2?.inputTokens ?? 0) + (usage2?.outputTokens ?? 0) + (usage2?.reasoningTokens ?? 0);
|
|
486
|
+
if (usage2?.costUsd !== void 0) {
|
|
487
|
+
total.costUsd = (total.costUsd ?? 0) + usage2.costUsd;
|
|
488
|
+
}
|
|
489
|
+
total.toolCalls += usage2?.toolCalls ?? 0;
|
|
490
|
+
}
|
|
491
|
+
function sumAppUsage(cases) {
|
|
492
|
+
const usage2 = emptyUsage();
|
|
493
|
+
const runUsages = cases.map(appUsageForCase).filter((item) => item !== void 0);
|
|
494
|
+
for (const runUsage of runUsages) {
|
|
495
|
+
addRunUsage(usage2, runUsage);
|
|
496
|
+
}
|
|
497
|
+
omitPartialCost(usage2, runUsages);
|
|
498
|
+
return usage2;
|
|
499
|
+
}
|
|
500
|
+
function appUsageForCase(testCase) {
|
|
501
|
+
const usage2 = testCase.harness?.usage;
|
|
502
|
+
const effectiveToolCalls = toolCallCount(testCase);
|
|
503
|
+
if (!usage2 && effectiveToolCalls === 0) {
|
|
504
|
+
return void 0;
|
|
505
|
+
}
|
|
506
|
+
return {
|
|
507
|
+
...usage2,
|
|
508
|
+
...effectiveToolCalls > 0 ? { toolCalls: effectiveToolCalls } : {}
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
function sumJudgeUsage(cases) {
|
|
512
|
+
const usage2 = emptyUsage();
|
|
513
|
+
const runUsages = [];
|
|
478
514
|
for (const testCase of cases) {
|
|
479
|
-
const
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
515
|
+
for (const score of testCase.eval?.scores ?? []) {
|
|
516
|
+
for (const run of score.judgeRuns ?? []) {
|
|
517
|
+
runUsages.push(run.usage);
|
|
518
|
+
addRunUsage(usage2, run.usage);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
485
521
|
}
|
|
522
|
+
omitPartialCost(usage2, runUsages);
|
|
486
523
|
return usage2;
|
|
487
524
|
}
|
|
525
|
+
function omitPartialCost(total, usages) {
|
|
526
|
+
if (usages.some(hasUsageWithoutCost)) {
|
|
527
|
+
total.costUsd = void 0;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
function hasUsageWithoutCost(usage2) {
|
|
531
|
+
return usage2?.costUsd === void 0 && ((usage2?.totalTokens ?? (usage2?.inputTokens ?? 0) + (usage2?.outputTokens ?? 0) + (usage2?.reasoningTokens ?? 0)) > 0 || (usage2?.toolCalls ?? 0) > 0);
|
|
532
|
+
}
|
|
488
533
|
function toolCallCount(testCase) {
|
|
489
534
|
const usageToolCalls = testCase.harness?.usage?.toolCalls;
|
|
490
535
|
if (usageToolCalls !== void 0) {
|
|
@@ -521,8 +566,8 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
521
566
|
status: "failed",
|
|
522
567
|
enforced: true,
|
|
523
568
|
passRate,
|
|
524
|
-
title: "Eval
|
|
525
|
-
message: `${formatNumber(nonEvalFailures)}
|
|
569
|
+
title: "Eval run failed",
|
|
570
|
+
message: `${formatNumber(nonEvalFailures)} test failure${nonEvalFailures === 1 ? "" : "s"} outside eval cases; ${counts}`
|
|
526
571
|
};
|
|
527
572
|
}
|
|
528
573
|
if (report.totals.evalTotal === 0) {
|
|
@@ -531,7 +576,7 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
531
576
|
status: "failed",
|
|
532
577
|
enforced: true,
|
|
533
578
|
passRate: null,
|
|
534
|
-
title: "Eval
|
|
579
|
+
title: "Eval run failed",
|
|
535
580
|
message: "no eval cases were reported"
|
|
536
581
|
};
|
|
537
582
|
}
|
|
@@ -541,8 +586,8 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
541
586
|
status: "failed",
|
|
542
587
|
enforced: true,
|
|
543
588
|
passRate,
|
|
544
|
-
title: "Eval
|
|
545
|
-
message: `
|
|
589
|
+
title: "Eval run failed",
|
|
590
|
+
message: `Vitest failed without reporting a failed test; ${counts}`
|
|
546
591
|
};
|
|
547
592
|
}
|
|
548
593
|
if (minPassRate !== void 0 && (passRate === null || passRate + Number.EPSILON < minPassRate)) {
|
|
@@ -552,7 +597,7 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
552
597
|
enforced: true,
|
|
553
598
|
passRate,
|
|
554
599
|
title: `Eval pass rate ${formatPercent(passRate)} \u2014 required ${formatPercent(minPassRate)}`,
|
|
555
|
-
message: `
|
|
600
|
+
message: `pass rate is below the minimum: ${counts}; minimum ${formatPercent(minPassRate)}`
|
|
556
601
|
};
|
|
557
602
|
}
|
|
558
603
|
if (minScoreAverage !== void 0) {
|
|
@@ -563,8 +608,8 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
563
608
|
status: "failed",
|
|
564
609
|
enforced: true,
|
|
565
610
|
passRate,
|
|
566
|
-
title: "
|
|
567
|
-
message: `no score
|
|
611
|
+
title: "Average score unavailable",
|
|
612
|
+
message: `no average score was reported; minimum ${formatScore(minScoreAverage)}`
|
|
568
613
|
};
|
|
569
614
|
}
|
|
570
615
|
if (average + Number.EPSILON < minScoreAverage) {
|
|
@@ -573,8 +618,8 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
573
618
|
status: "failed",
|
|
574
619
|
enforced: true,
|
|
575
620
|
passRate,
|
|
576
|
-
title: `
|
|
577
|
-
message: `
|
|
621
|
+
title: `Average score ${formatScore(average)} \u2014 required ${formatScore(minScoreAverage)}`,
|
|
622
|
+
message: `average score is below the minimum: ${counts}; minimum ${formatScore(minScoreAverage)}`
|
|
578
623
|
};
|
|
579
624
|
}
|
|
580
625
|
}
|
|
@@ -584,7 +629,7 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
584
629
|
enforced: true,
|
|
585
630
|
passRate,
|
|
586
631
|
title: enforcedPassTitle(report, passRate, minPassRate, minScoreAverage),
|
|
587
|
-
message: `
|
|
632
|
+
message: `requirements met: ${counts}${formatMinimumSuffix(minPassRate, minScoreAverage)}`
|
|
588
633
|
};
|
|
589
634
|
}
|
|
590
635
|
function computePassRate(report) {
|
|
@@ -617,7 +662,7 @@ function resolveMinPassRate(policy) {
|
|
|
617
662
|
}
|
|
618
663
|
function defaultCheckTitle(report) {
|
|
619
664
|
if (report.failures.length === 0 && report.status === "passed") {
|
|
620
|
-
return "No eval
|
|
665
|
+
return "No eval cases failed";
|
|
621
666
|
}
|
|
622
667
|
if (report.failures.length === 0) {
|
|
623
668
|
return "Vitest run failed";
|
|
@@ -626,10 +671,10 @@ function defaultCheckTitle(report) {
|
|
|
626
671
|
}
|
|
627
672
|
function enforcedPassTitle(report, passRate, minPassRate, minScoreAverage) {
|
|
628
673
|
if (minPassRate !== void 0) {
|
|
629
|
-
return `Eval pass rate ${formatPercent(passRate)} \u2014
|
|
674
|
+
return `Eval pass rate ${formatPercent(passRate)} \u2014 minimum ${formatPercent(minPassRate)}`;
|
|
630
675
|
}
|
|
631
676
|
if (minScoreAverage !== void 0) {
|
|
632
|
-
return `
|
|
677
|
+
return `Average score ${formatScore(report.score?.average)} \u2014 minimum ${formatScore(minScoreAverage)}`;
|
|
633
678
|
}
|
|
634
679
|
return defaultCheckTitle(report);
|
|
635
680
|
}
|
|
@@ -638,15 +683,15 @@ function formatEvalCounts(report, passRate) {
|
|
|
638
683
|
const passRateText = passRate === null ? "n/a" : formatPercent(passRate);
|
|
639
684
|
return `${formatNumber(report.totals.evalPassed)}/${formatNumber(
|
|
640
685
|
report.totals.evalTotal
|
|
641
|
-
)} passed (${passRateText}),
|
|
686
|
+
)} passed (${passRateText}), average score ${scoreText}`;
|
|
642
687
|
}
|
|
643
|
-
function
|
|
688
|
+
function formatMinimumSuffix(minPassRate, minScoreAverage) {
|
|
644
689
|
const parts = [];
|
|
645
690
|
if (minPassRate !== void 0) {
|
|
646
|
-
parts.push(`pass rate
|
|
691
|
+
parts.push(`minimum pass rate ${formatPercent(minPassRate)}`);
|
|
647
692
|
}
|
|
648
693
|
if (minScoreAverage !== void 0) {
|
|
649
|
-
parts.push(`
|
|
694
|
+
parts.push(`minimum average score ${formatScore(minScoreAverage)}`);
|
|
650
695
|
}
|
|
651
696
|
return parts.length === 0 ? "" : `; ${parts.join(", ")}`;
|
|
652
697
|
}
|
|
@@ -681,23 +726,23 @@ function renderJobSummary(report, options = {}) {
|
|
|
681
726
|
""
|
|
682
727
|
];
|
|
683
728
|
if (report.failures.length > 0) {
|
|
684
|
-
const failureHeading = options.gate?.ok === true ? "###
|
|
729
|
+
const failureHeading = options.gate?.ok === true ? "### Cases Below Target" : "### Failures";
|
|
685
730
|
lines.push(failureHeading, "");
|
|
686
731
|
failures.forEach((testCase, index) => {
|
|
687
732
|
lines.push(...renderFailureDetails(testCase, index + 1, options), "");
|
|
688
733
|
});
|
|
689
734
|
if (report.failures.length > failures.length) {
|
|
690
|
-
const omittedLabel = options.gate?.ok === true ? "
|
|
735
|
+
const omittedLabel = options.gate?.ok === true ? "cases below target" : "failures";
|
|
691
736
|
lines.push(
|
|
692
737
|
`${report.failures.length - failures.length} more ${omittedLabel} omitted from this summary.`,
|
|
693
738
|
""
|
|
694
739
|
);
|
|
695
740
|
}
|
|
696
741
|
} else if (report.totals.evalTotal > 0) {
|
|
697
|
-
lines.push("### Failures", "", "No eval
|
|
742
|
+
lines.push("### Failures", "", "No eval cases failed.", "");
|
|
698
743
|
}
|
|
699
744
|
if (report.totals.evalTotal === 0) {
|
|
700
|
-
lines.push("No eval
|
|
745
|
+
lines.push("No eval results were found in the Vitest JSON report.", "");
|
|
701
746
|
}
|
|
702
747
|
return `${lines.join("\n")}
|
|
703
748
|
`;
|
|
@@ -707,9 +752,9 @@ function formatCountLine(passed, failed, total) {
|
|
|
707
752
|
}
|
|
708
753
|
function renderSummaryTable(report, nonEvalFailures, gate) {
|
|
709
754
|
const rows = [
|
|
710
|
-
["Status", gate?.status ?? report.status],
|
|
755
|
+
["Status", capitalize(gate?.status ?? report.status)],
|
|
711
756
|
[
|
|
712
|
-
"
|
|
757
|
+
"Eval cases",
|
|
713
758
|
formatCountLine(
|
|
714
759
|
report.totals.evalPassed,
|
|
715
760
|
report.totals.evalFailed,
|
|
@@ -718,23 +763,31 @@ function renderSummaryTable(report, nonEvalFailures, gate) {
|
|
|
718
763
|
]
|
|
719
764
|
];
|
|
720
765
|
if (gate?.passRate !== void 0 && gate.passRate !== null) {
|
|
721
|
-
rows.push(["Pass
|
|
766
|
+
rows.push(["Pass rate", formatPercent(gate.passRate)]);
|
|
722
767
|
} else if (report.totals.evalTotal > 0) {
|
|
723
768
|
rows.push([
|
|
724
|
-
"Pass
|
|
769
|
+
"Pass rate",
|
|
725
770
|
formatPercent(report.totals.evalPassed / report.totals.evalTotal)
|
|
726
771
|
]);
|
|
727
772
|
}
|
|
728
773
|
if (report.score) {
|
|
729
774
|
rows.push(["Score", formatScoreSummary(report.score)]);
|
|
730
775
|
}
|
|
776
|
+
if (hasUsage(report.usage) || hasUsage(report.judgeUsage)) {
|
|
777
|
+
rows.push(["App usage", formatUsage(report.usage)]);
|
|
778
|
+
rows.push(["Judge usage", formatUsage(report.judgeUsage)]);
|
|
779
|
+
rows.push([
|
|
780
|
+
"Total usage",
|
|
781
|
+
formatUsage(sumUsage(report.usage, report.judgeUsage))
|
|
782
|
+
]);
|
|
783
|
+
}
|
|
731
784
|
if (gate?.enforced) {
|
|
732
|
-
rows.push(["
|
|
785
|
+
rows.push(["Requirements", gate.message]);
|
|
733
786
|
}
|
|
734
787
|
if (nonEvalFailures > 0) {
|
|
735
788
|
rows.push([
|
|
736
|
-
"Other
|
|
737
|
-
`${formatNumber(nonEvalFailures)}
|
|
789
|
+
"Other test failures",
|
|
790
|
+
`${formatNumber(nonEvalFailures)} test failure${nonEvalFailures === 1 ? "" : "s"} outside eval cases`
|
|
738
791
|
]);
|
|
739
792
|
}
|
|
740
793
|
rows.push(["Duration", formatDuration(report.durationMs)]);
|
|
@@ -747,7 +800,53 @@ function renderSummaryTable(report, nonEvalFailures, gate) {
|
|
|
747
800
|
];
|
|
748
801
|
}
|
|
749
802
|
function formatScoreSummary(score) {
|
|
750
|
-
return `
|
|
803
|
+
return `average ${formatScore(score.average)}${score.minimum === void 0 ? "" : `, lowest ${formatScore(score.minimum)}`}`;
|
|
804
|
+
}
|
|
805
|
+
function capitalize(value) {
|
|
806
|
+
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
807
|
+
}
|
|
808
|
+
function hasUsage(usage2) {
|
|
809
|
+
return usage2.totalTokens > 0 || usage2.costUsd !== void 0 || usage2.toolCalls > 0;
|
|
810
|
+
}
|
|
811
|
+
function sumUsage(app, judge) {
|
|
812
|
+
const appCostKnown = !hasUsageWithoutCost2(app);
|
|
813
|
+
const judgeCostKnown = !hasUsageWithoutCost2(judge);
|
|
814
|
+
return {
|
|
815
|
+
inputTokens: app.inputTokens + judge.inputTokens,
|
|
816
|
+
outputTokens: app.outputTokens + judge.outputTokens,
|
|
817
|
+
reasoningTokens: app.reasoningTokens + judge.reasoningTokens,
|
|
818
|
+
totalTokens: app.totalTokens + judge.totalTokens,
|
|
819
|
+
...appCostKnown && judgeCostKnown ? { costUsd: (app.costUsd ?? 0) + (judge.costUsd ?? 0) } : {},
|
|
820
|
+
toolCalls: app.toolCalls + judge.toolCalls
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
function hasUsageWithoutCost2(usage2) {
|
|
824
|
+
return usage2.costUsd === void 0 && (usage2.totalTokens > 0 || usage2.toolCalls > 0);
|
|
825
|
+
}
|
|
826
|
+
function formatUsage(usage2) {
|
|
827
|
+
const parts = [];
|
|
828
|
+
if (usage2.totalTokens > 0) {
|
|
829
|
+
parts.push(`${formatNumber(usage2.totalTokens)} tokens`);
|
|
830
|
+
}
|
|
831
|
+
if (usage2.costUsd !== void 0) {
|
|
832
|
+
parts.push(
|
|
833
|
+
usage2.costUsd.toLocaleString("en-US", {
|
|
834
|
+
style: "currency",
|
|
835
|
+
currency: "USD",
|
|
836
|
+
minimumFractionDigits: 2,
|
|
837
|
+
maximumFractionDigits: 6
|
|
838
|
+
})
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
if (hasUsageWithoutCost2(usage2)) {
|
|
842
|
+
parts.push("cost unavailable");
|
|
843
|
+
}
|
|
844
|
+
if (usage2.toolCalls > 0) {
|
|
845
|
+
parts.push(
|
|
846
|
+
`${formatNumber(usage2.toolCalls)} tool call${usage2.toolCalls === 1 ? "" : "s"}`
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
return parts.join(", ") || "none";
|
|
751
850
|
}
|
|
752
851
|
function escapeTableCell(value) {
|
|
753
852
|
return value.replace(/\r?\n/g, " ").replace(/\\/g, "\\\\").replace(/\|/g, "\\|");
|
|
@@ -827,7 +926,7 @@ function renderFailureBlock(testCase, {
|
|
|
827
926
|
["Case", `${number}. ${testCase.displayName}`],
|
|
828
927
|
["Status", testCase.status],
|
|
829
928
|
["Location", formatLocation(testCase.displayFile, testCase.location)],
|
|
830
|
-
["
|
|
929
|
+
["App runner", testCase.harness?.name ?? "n/a"],
|
|
831
930
|
["Score", formatScore(failure?.score ?? testCase.eval?.avgScore)],
|
|
832
931
|
["Judge", failure?.judgeName ?? "n/a"]
|
|
833
932
|
];
|
|
@@ -865,7 +964,7 @@ function renderFailureBlock(testCase, {
|
|
|
865
964
|
if (finalOutput !== void 0) {
|
|
866
965
|
lines.push(
|
|
867
966
|
...renderAsciiSection(
|
|
868
|
-
"
|
|
967
|
+
"Output",
|
|
869
968
|
stringifyValue(finalOutput, maxOutputChars).split(/\r?\n/)
|
|
870
969
|
),
|
|
871
970
|
""
|
|
@@ -893,7 +992,7 @@ function renderFailureBlock(testCase, {
|
|
|
893
992
|
if (testCase.harness?.errors.length) {
|
|
894
993
|
lines.push(
|
|
895
994
|
...renderAsciiSection(
|
|
896
|
-
"
|
|
995
|
+
"App errors",
|
|
897
996
|
stringifyValue(testCase.harness.errors, maxReasonChars).split(/\r?\n/)
|
|
898
997
|
),
|
|
899
998
|
""
|
|
@@ -942,7 +1041,9 @@ function formatCaseUsage(testCase) {
|
|
|
942
1041
|
parts.push(`${formatNumber(totalTokens)} tokens`);
|
|
943
1042
|
}
|
|
944
1043
|
if (toolCalls > 0) {
|
|
945
|
-
parts.push(
|
|
1044
|
+
parts.push(
|
|
1045
|
+
`${formatNumber(toolCalls)} tool call${toolCalls === 1 ? "" : "s"}`
|
|
1046
|
+
);
|
|
946
1047
|
}
|
|
947
1048
|
if (testCase.harness?.timingMs !== void 0) {
|
|
948
1049
|
parts.push(formatDuration(testCase.harness.timingMs));
|
|
@@ -1108,16 +1209,22 @@ function mergeEvalReports(reports) {
|
|
|
1108
1209
|
minimum: Math.min(...scoredCases)
|
|
1109
1210
|
} : void 0,
|
|
1110
1211
|
usage: mergeUsage(reports.map((report) => report.usage)),
|
|
1212
|
+
judgeUsage: mergeUsage(reports.map((report) => report.judgeUsage)),
|
|
1111
1213
|
cases,
|
|
1112
1214
|
failures
|
|
1113
1215
|
};
|
|
1114
1216
|
}
|
|
1115
1217
|
function mergeUsage(usages) {
|
|
1218
|
+
const costs = usages.map((usage2) => usage2.costUsd).filter((cost) => cost !== void 0);
|
|
1219
|
+
const costComplete = !usages.some(
|
|
1220
|
+
(usage2) => usage2.costUsd === void 0 && (usage2.totalTokens > 0 || usage2.toolCalls > 0)
|
|
1221
|
+
);
|
|
1116
1222
|
return {
|
|
1117
1223
|
inputTokens: sum(usages, (usage2) => usage2.inputTokens),
|
|
1118
1224
|
outputTokens: sum(usages, (usage2) => usage2.outputTokens),
|
|
1119
1225
|
reasoningTokens: sum(usages, (usage2) => usage2.reasoningTokens),
|
|
1120
1226
|
totalTokens: sum(usages, (usage2) => usage2.totalTokens),
|
|
1227
|
+
...costComplete && costs.length > 0 ? { costUsd: costs.reduce((total, cost) => total + cost, 0) } : {},
|
|
1121
1228
|
toolCalls: sum(usages, (usage2) => usage2.toolCalls)
|
|
1122
1229
|
};
|
|
1123
1230
|
}
|