Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions actions/setup/js/effective_tokens.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -186,18 +186,26 @@ function computeEffectiveTokens(model, inputTokens, outputTokens, cacheReadToken
/**
* Formats an ET number in a compact, human-readable form.
*
* Effective tokens are estimates, so sub-1000 values are rounded to the nearest 10.
*
* Ranges:
* < 1,000 → exact integer (e.g. "900")
* < 10 → exact integer (e.g. "7")
* 10–999 → rounded to nearest 10 (e.g. "40", "120", "900")
* 1,000–999,999 → Xk with one decimal when non-zero (e.g. "1.2K", "450K")
* >= 1,000,000 → Xm with one decimal when non-zero (e.g. "1.2M", "3M")
* >= 1,000,000 → rounded to nearest whole M (e.g. "1M", "12M")
*
* @param {number} n - Non-negative ET value (should be rounded before passing)
* @returns {string} Compact string representation
*/
function formatET(n) {
// Round to nearest 10 for values in [10, 1000) — effective tokens are estimates
if (n >= 10 && n < 1000) {
n = Math.round(n / 10) * 10;
}
if (n < 1000) return String(n);
if (n < 1_000_000) return `${(n / 1000).toFixed(1).replace(/\.0$/, "")}K`;
return `${(n / 1_000_000).toFixed(1).replace(/\.0$/, "")}M`;
// Round to nearest whole M — effective tokens are estimates
return `${Math.round(n / 1_000_000)}M`;
}

/**
Expand Down
26 changes: 20 additions & 6 deletions actions/setup/js/effective_tokens.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,24 @@ describe("effective_tokens", () => {
});

describe("formatET", () => {
test("returns exact string for values under 1000", () => {
test("returns exact string for values under 10", () => {
expect(formatET(0)).toBe("0");
expect(formatET(1)).toBe("1");
expect(formatET(9)).toBe("9");
});

test("rounds values in [10, 1000) to nearest 10", () => {
expect(formatET(10)).toBe("10");
expect(formatET(14)).toBe("10");
expect(formatET(15)).toBe("20");
expect(formatET(42)).toBe("40");
expect(formatET(123)).toBe("120");
expect(formatET(900)).toBe("900");
expect(formatET(999)).toBe("999");
});

test("rounds values near 1000 up to 1K", () => {
expect(formatET(995)).toBe("1K");
expect(formatET(999)).toBe("1K");
});

test("formats values in the thousands as K", () => {
Expand All @@ -317,13 +330,14 @@ describe("effective_tokens", () => {
expect(formatET(999999)).toBe("1000K");
});

test("formats values in the millions as M", () => {
test("formats values in the millions as M (rounded to nearest whole M)", () => {
expect(formatET(1_000_000)).toBe("1M");
expect(formatET(1_200_000)).toBe("1.2M");
expect(formatET(12_345_678)).toBe("12.3M");
expect(formatET(1_200_000)).toBe("1M");
expect(formatET(1_500_000)).toBe("2M");
expect(formatET(12_345_678)).toBe("12M");
});

test("omits trailing .0 in K/M format", () => {
test("omits trailing .0 in K format", () => {
expect(formatET(2000)).toBe("2K");
expect(formatET(5_000_000)).toBe("5M");
});
Expand Down
16 changes: 13 additions & 3 deletions pkg/cli/health_metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,18 +235,28 @@ func GroupRunsByWorkflow(runs []WorkflowRun) map[string][]WorkflowRun {
return grouped
}

// formatTokens formats token count in a human-readable format
// formatTokens formats token count in a human-readable format.
// Values in [10, 1000) are rounded to the nearest 10 — token counts are estimates.
func formatTokens(tokens int) string {
if tokens == 0 {
return "-"
}
if tokens < 1000 {
if tokens < 10 {
return strconv.Itoa(tokens)
}
if tokens < 1000 {
// Round to nearest 10 — token counts are estimates
rounded := (tokens + 5) / 10 * 10
if rounded >= 1000 {
return "1K"
}
return strconv.Itoa(rounded)
}
if tokens < 1000000 {
return fmt.Sprintf("%.1fK", float64(tokens)/1000)
}
return fmt.Sprintf("%.1fM", float64(tokens)/1000000)
// Round to nearest whole M — token counts are estimates
return fmt.Sprintf("%dM", (tokens+500000)/1000000)
}

// formatCost formats cost in a human-readable format
Expand Down
29 changes: 27 additions & 2 deletions pkg/cli/health_metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,30 @@ func TestFormatTokens(t *testing.T) {
expected: "-",
},
{
name: "small tokens",
name: "single digit kept exact",
tokens: 7,
expected: "7",
},
{
name: "rounds to nearest 10",
tokens: 42,
expected: "40",
},
{
name: "rounds up to nearest 10",
tokens: 45,
expected: "50",
},
{
name: "multiple of 10 unchanged",
tokens: 500,
expected: "500",
},
{
name: "rounds near 1000 to 1K",
tokens: 999,
expected: "1K",
},
{
name: "thousands",
tokens: 5000,
Expand All @@ -245,7 +265,12 @@ func TestFormatTokens(t *testing.T) {
{
name: "millions",
tokens: 2500000,
expected: "2.5M",
expected: "3M",
},
{
name: "millions rounded down",
tokens: 2400000,
expected: "2M",
},
}

Expand Down