@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.mjs
CHANGED
|
@@ -327,7 +327,8 @@ function collectEvalReport(input, options = {}) {
|
|
|
327
327
|
const cases = workspace.cases.map(collectEvalCase);
|
|
328
328
|
const failures = cases.filter((testCase) => testCase.status === "failed");
|
|
329
329
|
const evalScores = cases.map((testCase) => testCase.eval?.avgScore).filter((score) => isFiniteNumber(score));
|
|
330
|
-
const usage2 =
|
|
330
|
+
const usage2 = sumAppUsage(cases);
|
|
331
|
+
const judgeUsage = sumJudgeUsage(cases);
|
|
331
332
|
const durationMs = workspace.runs[0]?.durationMs;
|
|
332
333
|
return {
|
|
333
334
|
status: input.success && failures.length === 0 ? "passed" : "failed",
|
|
@@ -347,6 +348,7 @@ function collectEvalReport(input, options = {}) {
|
|
|
347
348
|
minimum: Math.min(...evalScores)
|
|
348
349
|
} : void 0,
|
|
349
350
|
usage: usage2,
|
|
351
|
+
judgeUsage,
|
|
350
352
|
cases,
|
|
351
353
|
failures
|
|
352
354
|
};
|
|
@@ -471,24 +473,67 @@ function stringifyReason(value) {
|
|
|
471
473
|
}
|
|
472
474
|
return typeof value === "string" ? value : stringifyValue(value, 4e3);
|
|
473
475
|
}
|
|
474
|
-
function
|
|
475
|
-
|
|
476
|
+
function emptyUsage() {
|
|
477
|
+
return {
|
|
476
478
|
inputTokens: 0,
|
|
477
479
|
outputTokens: 0,
|
|
478
480
|
reasoningTokens: 0,
|
|
479
481
|
totalTokens: 0,
|
|
480
482
|
toolCalls: 0
|
|
481
483
|
};
|
|
484
|
+
}
|
|
485
|
+
function addRunUsage(total, usage2) {
|
|
486
|
+
total.inputTokens += usage2?.inputTokens ?? 0;
|
|
487
|
+
total.outputTokens += usage2?.outputTokens ?? 0;
|
|
488
|
+
total.reasoningTokens += usage2?.reasoningTokens ?? 0;
|
|
489
|
+
total.totalTokens += usage2?.totalTokens ?? (usage2?.inputTokens ?? 0) + (usage2?.outputTokens ?? 0) + (usage2?.reasoningTokens ?? 0);
|
|
490
|
+
if (usage2?.costUsd !== void 0) {
|
|
491
|
+
total.costUsd = (total.costUsd ?? 0) + usage2.costUsd;
|
|
492
|
+
}
|
|
493
|
+
total.toolCalls += usage2?.toolCalls ?? 0;
|
|
494
|
+
}
|
|
495
|
+
function sumAppUsage(cases) {
|
|
496
|
+
const usage2 = emptyUsage();
|
|
497
|
+
const runUsages = cases.map(appUsageForCase).filter((item) => item !== void 0);
|
|
498
|
+
for (const runUsage of runUsages) {
|
|
499
|
+
addRunUsage(usage2, runUsage);
|
|
500
|
+
}
|
|
501
|
+
omitPartialCost(usage2, runUsages);
|
|
502
|
+
return usage2;
|
|
503
|
+
}
|
|
504
|
+
function appUsageForCase(testCase) {
|
|
505
|
+
const usage2 = testCase.harness?.usage;
|
|
506
|
+
const effectiveToolCalls = toolCallCount(testCase);
|
|
507
|
+
if (!usage2 && effectiveToolCalls === 0) {
|
|
508
|
+
return void 0;
|
|
509
|
+
}
|
|
510
|
+
return {
|
|
511
|
+
...usage2,
|
|
512
|
+
...effectiveToolCalls > 0 ? { toolCalls: effectiveToolCalls } : {}
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
function sumJudgeUsage(cases) {
|
|
516
|
+
const usage2 = emptyUsage();
|
|
517
|
+
const runUsages = [];
|
|
482
518
|
for (const testCase of cases) {
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
519
|
+
for (const score of testCase.eval?.scores ?? []) {
|
|
520
|
+
for (const run of score.judgeRuns ?? []) {
|
|
521
|
+
runUsages.push(run.usage);
|
|
522
|
+
addRunUsage(usage2, run.usage);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
489
525
|
}
|
|
526
|
+
omitPartialCost(usage2, runUsages);
|
|
490
527
|
return usage2;
|
|
491
528
|
}
|
|
529
|
+
function omitPartialCost(total, usages) {
|
|
530
|
+
if (usages.some(hasUsageWithoutCost)) {
|
|
531
|
+
total.costUsd = void 0;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
function hasUsageWithoutCost(usage2) {
|
|
535
|
+
return usage2?.costUsd === void 0 && ((usage2?.totalTokens ?? (usage2?.inputTokens ?? 0) + (usage2?.outputTokens ?? 0) + (usage2?.reasoningTokens ?? 0)) > 0 || (usage2?.toolCalls ?? 0) > 0);
|
|
536
|
+
}
|
|
492
537
|
function toolCallCount(testCase) {
|
|
493
538
|
const usageToolCalls = testCase.harness?.usage?.toolCalls;
|
|
494
539
|
if (usageToolCalls !== void 0) {
|
|
@@ -525,8 +570,8 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
525
570
|
status: "failed",
|
|
526
571
|
enforced: true,
|
|
527
572
|
passRate,
|
|
528
|
-
title: "Eval
|
|
529
|
-
message: `${formatNumber(nonEvalFailures)}
|
|
573
|
+
title: "Eval run failed",
|
|
574
|
+
message: `${formatNumber(nonEvalFailures)} test failure${nonEvalFailures === 1 ? "" : "s"} outside eval cases; ${counts}`
|
|
530
575
|
};
|
|
531
576
|
}
|
|
532
577
|
if (report.totals.evalTotal === 0) {
|
|
@@ -535,7 +580,7 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
535
580
|
status: "failed",
|
|
536
581
|
enforced: true,
|
|
537
582
|
passRate: null,
|
|
538
|
-
title: "Eval
|
|
583
|
+
title: "Eval run failed",
|
|
539
584
|
message: "no eval cases were reported"
|
|
540
585
|
};
|
|
541
586
|
}
|
|
@@ -545,8 +590,8 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
545
590
|
status: "failed",
|
|
546
591
|
enforced: true,
|
|
547
592
|
passRate,
|
|
548
|
-
title: "Eval
|
|
549
|
-
message: `
|
|
593
|
+
title: "Eval run failed",
|
|
594
|
+
message: `Vitest failed without reporting a failed test; ${counts}`
|
|
550
595
|
};
|
|
551
596
|
}
|
|
552
597
|
if (minPassRate !== void 0 && (passRate === null || passRate + Number.EPSILON < minPassRate)) {
|
|
@@ -556,7 +601,7 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
556
601
|
enforced: true,
|
|
557
602
|
passRate,
|
|
558
603
|
title: `Eval pass rate ${formatPercent(passRate)} \u2014 required ${formatPercent(minPassRate)}`,
|
|
559
|
-
message: `
|
|
604
|
+
message: `pass rate is below the minimum: ${counts}; minimum ${formatPercent(minPassRate)}`
|
|
560
605
|
};
|
|
561
606
|
}
|
|
562
607
|
if (minScoreAverage !== void 0) {
|
|
@@ -567,8 +612,8 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
567
612
|
status: "failed",
|
|
568
613
|
enforced: true,
|
|
569
614
|
passRate,
|
|
570
|
-
title: "
|
|
571
|
-
message: `no score
|
|
615
|
+
title: "Average score unavailable",
|
|
616
|
+
message: `no average score was reported; minimum ${formatScore(minScoreAverage)}`
|
|
572
617
|
};
|
|
573
618
|
}
|
|
574
619
|
if (average + Number.EPSILON < minScoreAverage) {
|
|
@@ -577,8 +622,8 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
577
622
|
status: "failed",
|
|
578
623
|
enforced: true,
|
|
579
624
|
passRate,
|
|
580
|
-
title: `
|
|
581
|
-
message: `
|
|
625
|
+
title: `Average score ${formatScore(average)} \u2014 required ${formatScore(minScoreAverage)}`,
|
|
626
|
+
message: `average score is below the minimum: ${counts}; minimum ${formatScore(minScoreAverage)}`
|
|
582
627
|
};
|
|
583
628
|
}
|
|
584
629
|
}
|
|
@@ -588,7 +633,7 @@ function evaluateEvalGate(report, policy = {}) {
|
|
|
588
633
|
enforced: true,
|
|
589
634
|
passRate,
|
|
590
635
|
title: enforcedPassTitle(report, passRate, minPassRate, minScoreAverage),
|
|
591
|
-
message: `
|
|
636
|
+
message: `requirements met: ${counts}${formatMinimumSuffix(minPassRate, minScoreAverage)}`
|
|
592
637
|
};
|
|
593
638
|
}
|
|
594
639
|
function computePassRate(report) {
|
|
@@ -621,7 +666,7 @@ function resolveMinPassRate(policy) {
|
|
|
621
666
|
}
|
|
622
667
|
function defaultCheckTitle(report) {
|
|
623
668
|
if (report.failures.length === 0 && report.status === "passed") {
|
|
624
|
-
return "No eval
|
|
669
|
+
return "No eval cases failed";
|
|
625
670
|
}
|
|
626
671
|
if (report.failures.length === 0) {
|
|
627
672
|
return "Vitest run failed";
|
|
@@ -630,10 +675,10 @@ function defaultCheckTitle(report) {
|
|
|
630
675
|
}
|
|
631
676
|
function enforcedPassTitle(report, passRate, minPassRate, minScoreAverage) {
|
|
632
677
|
if (minPassRate !== void 0) {
|
|
633
|
-
return `Eval pass rate ${formatPercent(passRate)} \u2014
|
|
678
|
+
return `Eval pass rate ${formatPercent(passRate)} \u2014 minimum ${formatPercent(minPassRate)}`;
|
|
634
679
|
}
|
|
635
680
|
if (minScoreAverage !== void 0) {
|
|
636
|
-
return `
|
|
681
|
+
return `Average score ${formatScore(report.score?.average)} \u2014 minimum ${formatScore(minScoreAverage)}`;
|
|
637
682
|
}
|
|
638
683
|
return defaultCheckTitle(report);
|
|
639
684
|
}
|
|
@@ -642,15 +687,15 @@ function formatEvalCounts(report, passRate) {
|
|
|
642
687
|
const passRateText = passRate === null ? "n/a" : formatPercent(passRate);
|
|
643
688
|
return `${formatNumber(report.totals.evalPassed)}/${formatNumber(
|
|
644
689
|
report.totals.evalTotal
|
|
645
|
-
)} passed (${passRateText}),
|
|
690
|
+
)} passed (${passRateText}), average score ${scoreText}`;
|
|
646
691
|
}
|
|
647
|
-
function
|
|
692
|
+
function formatMinimumSuffix(minPassRate, minScoreAverage) {
|
|
648
693
|
const parts = [];
|
|
649
694
|
if (minPassRate !== void 0) {
|
|
650
|
-
parts.push(`pass rate
|
|
695
|
+
parts.push(`minimum pass rate ${formatPercent(minPassRate)}`);
|
|
651
696
|
}
|
|
652
697
|
if (minScoreAverage !== void 0) {
|
|
653
|
-
parts.push(`
|
|
698
|
+
parts.push(`minimum average score ${formatScore(minScoreAverage)}`);
|
|
654
699
|
}
|
|
655
700
|
return parts.length === 0 ? "" : `; ${parts.join(", ")}`;
|
|
656
701
|
}
|
|
@@ -685,23 +730,23 @@ function renderJobSummary(report, options = {}) {
|
|
|
685
730
|
""
|
|
686
731
|
];
|
|
687
732
|
if (report.failures.length > 0) {
|
|
688
|
-
const failureHeading = options.gate?.ok === true ? "###
|
|
733
|
+
const failureHeading = options.gate?.ok === true ? "### Cases Below Target" : "### Failures";
|
|
689
734
|
lines.push(failureHeading, "");
|
|
690
735
|
failures.forEach((testCase, index) => {
|
|
691
736
|
lines.push(...renderFailureDetails(testCase, index + 1, options), "");
|
|
692
737
|
});
|
|
693
738
|
if (report.failures.length > failures.length) {
|
|
694
|
-
const omittedLabel = options.gate?.ok === true ? "
|
|
739
|
+
const omittedLabel = options.gate?.ok === true ? "cases below target" : "failures";
|
|
695
740
|
lines.push(
|
|
696
741
|
`${report.failures.length - failures.length} more ${omittedLabel} omitted from this summary.`,
|
|
697
742
|
""
|
|
698
743
|
);
|
|
699
744
|
}
|
|
700
745
|
} else if (report.totals.evalTotal > 0) {
|
|
701
|
-
lines.push("### Failures", "", "No eval
|
|
746
|
+
lines.push("### Failures", "", "No eval cases failed.", "");
|
|
702
747
|
}
|
|
703
748
|
if (report.totals.evalTotal === 0) {
|
|
704
|
-
lines.push("No eval
|
|
749
|
+
lines.push("No eval results were found in the Vitest JSON report.", "");
|
|
705
750
|
}
|
|
706
751
|
return `${lines.join("\n")}
|
|
707
752
|
`;
|
|
@@ -711,9 +756,9 @@ function formatCountLine(passed, failed, total) {
|
|
|
711
756
|
}
|
|
712
757
|
function renderSummaryTable(report, nonEvalFailures, gate) {
|
|
713
758
|
const rows = [
|
|
714
|
-
["Status", gate?.status ?? report.status],
|
|
759
|
+
["Status", capitalize(gate?.status ?? report.status)],
|
|
715
760
|
[
|
|
716
|
-
"
|
|
761
|
+
"Eval cases",
|
|
717
762
|
formatCountLine(
|
|
718
763
|
report.totals.evalPassed,
|
|
719
764
|
report.totals.evalFailed,
|
|
@@ -722,23 +767,31 @@ function renderSummaryTable(report, nonEvalFailures, gate) {
|
|
|
722
767
|
]
|
|
723
768
|
];
|
|
724
769
|
if (gate?.passRate !== void 0 && gate.passRate !== null) {
|
|
725
|
-
rows.push(["Pass
|
|
770
|
+
rows.push(["Pass rate", formatPercent(gate.passRate)]);
|
|
726
771
|
} else if (report.totals.evalTotal > 0) {
|
|
727
772
|
rows.push([
|
|
728
|
-
"Pass
|
|
773
|
+
"Pass rate",
|
|
729
774
|
formatPercent(report.totals.evalPassed / report.totals.evalTotal)
|
|
730
775
|
]);
|
|
731
776
|
}
|
|
732
777
|
if (report.score) {
|
|
733
778
|
rows.push(["Score", formatScoreSummary(report.score)]);
|
|
734
779
|
}
|
|
780
|
+
if (hasUsage(report.usage) || hasUsage(report.judgeUsage)) {
|
|
781
|
+
rows.push(["App usage", formatUsage(report.usage)]);
|
|
782
|
+
rows.push(["Judge usage", formatUsage(report.judgeUsage)]);
|
|
783
|
+
rows.push([
|
|
784
|
+
"Total usage",
|
|
785
|
+
formatUsage(sumUsage(report.usage, report.judgeUsage))
|
|
786
|
+
]);
|
|
787
|
+
}
|
|
735
788
|
if (gate?.enforced) {
|
|
736
|
-
rows.push(["
|
|
789
|
+
rows.push(["Requirements", gate.message]);
|
|
737
790
|
}
|
|
738
791
|
if (nonEvalFailures > 0) {
|
|
739
792
|
rows.push([
|
|
740
|
-
"Other
|
|
741
|
-
`${formatNumber(nonEvalFailures)}
|
|
793
|
+
"Other test failures",
|
|
794
|
+
`${formatNumber(nonEvalFailures)} test failure${nonEvalFailures === 1 ? "" : "s"} outside eval cases`
|
|
742
795
|
]);
|
|
743
796
|
}
|
|
744
797
|
rows.push(["Duration", formatDuration(report.durationMs)]);
|
|
@@ -751,7 +804,53 @@ function renderSummaryTable(report, nonEvalFailures, gate) {
|
|
|
751
804
|
];
|
|
752
805
|
}
|
|
753
806
|
function formatScoreSummary(score) {
|
|
754
|
-
return `
|
|
807
|
+
return `average ${formatScore(score.average)}${score.minimum === void 0 ? "" : `, lowest ${formatScore(score.minimum)}`}`;
|
|
808
|
+
}
|
|
809
|
+
function capitalize(value) {
|
|
810
|
+
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
811
|
+
}
|
|
812
|
+
function hasUsage(usage2) {
|
|
813
|
+
return usage2.totalTokens > 0 || usage2.costUsd !== void 0 || usage2.toolCalls > 0;
|
|
814
|
+
}
|
|
815
|
+
function sumUsage(app, judge) {
|
|
816
|
+
const appCostKnown = !hasUsageWithoutCost2(app);
|
|
817
|
+
const judgeCostKnown = !hasUsageWithoutCost2(judge);
|
|
818
|
+
return {
|
|
819
|
+
inputTokens: app.inputTokens + judge.inputTokens,
|
|
820
|
+
outputTokens: app.outputTokens + judge.outputTokens,
|
|
821
|
+
reasoningTokens: app.reasoningTokens + judge.reasoningTokens,
|
|
822
|
+
totalTokens: app.totalTokens + judge.totalTokens,
|
|
823
|
+
...appCostKnown && judgeCostKnown ? { costUsd: (app.costUsd ?? 0) + (judge.costUsd ?? 0) } : {},
|
|
824
|
+
toolCalls: app.toolCalls + judge.toolCalls
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
function hasUsageWithoutCost2(usage2) {
|
|
828
|
+
return usage2.costUsd === void 0 && (usage2.totalTokens > 0 || usage2.toolCalls > 0);
|
|
829
|
+
}
|
|
830
|
+
function formatUsage(usage2) {
|
|
831
|
+
const parts = [];
|
|
832
|
+
if (usage2.totalTokens > 0) {
|
|
833
|
+
parts.push(`${formatNumber(usage2.totalTokens)} tokens`);
|
|
834
|
+
}
|
|
835
|
+
if (usage2.costUsd !== void 0) {
|
|
836
|
+
parts.push(
|
|
837
|
+
usage2.costUsd.toLocaleString("en-US", {
|
|
838
|
+
style: "currency",
|
|
839
|
+
currency: "USD",
|
|
840
|
+
minimumFractionDigits: 2,
|
|
841
|
+
maximumFractionDigits: 6
|
|
842
|
+
})
|
|
843
|
+
);
|
|
844
|
+
}
|
|
845
|
+
if (hasUsageWithoutCost2(usage2)) {
|
|
846
|
+
parts.push("cost unavailable");
|
|
847
|
+
}
|
|
848
|
+
if (usage2.toolCalls > 0) {
|
|
849
|
+
parts.push(
|
|
850
|
+
`${formatNumber(usage2.toolCalls)} tool call${usage2.toolCalls === 1 ? "" : "s"}`
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
return parts.join(", ") || "none";
|
|
755
854
|
}
|
|
756
855
|
function escapeTableCell(value) {
|
|
757
856
|
return value.replace(/\r?\n/g, " ").replace(/\\/g, "\\\\").replace(/\|/g, "\\|");
|
|
@@ -831,7 +930,7 @@ function renderFailureBlock(testCase, {
|
|
|
831
930
|
["Case", `${number}. ${testCase.displayName}`],
|
|
832
931
|
["Status", testCase.status],
|
|
833
932
|
["Location", formatLocation(testCase.displayFile, testCase.location)],
|
|
834
|
-
["
|
|
933
|
+
["App runner", testCase.harness?.name ?? "n/a"],
|
|
835
934
|
["Score", formatScore(failure?.score ?? testCase.eval?.avgScore)],
|
|
836
935
|
["Judge", failure?.judgeName ?? "n/a"]
|
|
837
936
|
];
|
|
@@ -869,7 +968,7 @@ function renderFailureBlock(testCase, {
|
|
|
869
968
|
if (finalOutput !== void 0) {
|
|
870
969
|
lines.push(
|
|
871
970
|
...renderAsciiSection(
|
|
872
|
-
"
|
|
971
|
+
"Output",
|
|
873
972
|
stringifyValue(finalOutput, maxOutputChars).split(/\r?\n/)
|
|
874
973
|
),
|
|
875
974
|
""
|
|
@@ -897,7 +996,7 @@ function renderFailureBlock(testCase, {
|
|
|
897
996
|
if (testCase.harness?.errors.length) {
|
|
898
997
|
lines.push(
|
|
899
998
|
...renderAsciiSection(
|
|
900
|
-
"
|
|
999
|
+
"App errors",
|
|
901
1000
|
stringifyValue(testCase.harness.errors, maxReasonChars).split(/\r?\n/)
|
|
902
1001
|
),
|
|
903
1002
|
""
|
|
@@ -946,7 +1045,9 @@ function formatCaseUsage(testCase) {
|
|
|
946
1045
|
parts.push(`${formatNumber(totalTokens)} tokens`);
|
|
947
1046
|
}
|
|
948
1047
|
if (toolCalls > 0) {
|
|
949
|
-
parts.push(
|
|
1048
|
+
parts.push(
|
|
1049
|
+
`${formatNumber(toolCalls)} tool call${toolCalls === 1 ? "" : "s"}`
|
|
1050
|
+
);
|
|
950
1051
|
}
|
|
951
1052
|
if (testCase.harness?.timingMs !== void 0) {
|
|
952
1053
|
parts.push(formatDuration(testCase.harness.timingMs));
|
|
@@ -1112,16 +1213,22 @@ function mergeEvalReports(reports) {
|
|
|
1112
1213
|
minimum: Math.min(...scoredCases)
|
|
1113
1214
|
} : void 0,
|
|
1114
1215
|
usage: mergeUsage(reports.map((report) => report.usage)),
|
|
1216
|
+
judgeUsage: mergeUsage(reports.map((report) => report.judgeUsage)),
|
|
1115
1217
|
cases,
|
|
1116
1218
|
failures
|
|
1117
1219
|
};
|
|
1118
1220
|
}
|
|
1119
1221
|
function mergeUsage(usages) {
|
|
1222
|
+
const costs = usages.map((usage2) => usage2.costUsd).filter((cost) => cost !== void 0);
|
|
1223
|
+
const costComplete = !usages.some(
|
|
1224
|
+
(usage2) => usage2.costUsd === void 0 && (usage2.totalTokens > 0 || usage2.toolCalls > 0)
|
|
1225
|
+
);
|
|
1120
1226
|
return {
|
|
1121
1227
|
inputTokens: sum(usages, (usage2) => usage2.inputTokens),
|
|
1122
1228
|
outputTokens: sum(usages, (usage2) => usage2.outputTokens),
|
|
1123
1229
|
reasoningTokens: sum(usages, (usage2) => usage2.reasoningTokens),
|
|
1124
1230
|
totalTokens: sum(usages, (usage2) => usage2.totalTokens),
|
|
1231
|
+
...costComplete && costs.length > 0 ? { costUsd: costs.reduce((total, cost) => total + cost, 0) } : {},
|
|
1125
1232
|
toolCalls: sum(usages, (usage2) => usage2.toolCalls)
|
|
1126
1233
|
};
|
|
1127
1234
|
}
|