From ca487fc9f6a032cb89c7ed8d7a12ed2375678b65 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 24 Sep 2026 11:15:59 -0500 Subject: [PATCH 1/5] fix(stats): show missing radar scores as gaps --- .../stats/app/src/routes/compare-radar.tsx | 42 ++++++++++++++++--- .../stats/app/src/routes/model-catalog.ts | 25 ++++++++++- packages/stats/app/test/compare-radar.test.ts | 17 ++++++++ 3 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 packages/stats/app/test/compare-radar.test.ts diff --git a/packages/stats/app/src/routes/compare-radar.tsx b/packages/stats/app/src/routes/compare-radar.tsx index 35ada12885f1..ad1a301e9b48 100644 --- a/packages/stats/app/src/routes/compare-radar.tsx +++ b/packages/stats/app/src/routes/compare-radar.tsx @@ -62,6 +62,13 @@ export function ComparisonRadar(props: ComparisonRadarProps) { {model.name} {(name) => {name()}} + score === undefined)}> + + {model.scores.every((score) => score === undefined) + ? "No data available" + : `${model.scores.filter((score) => score !== undefined).length} of ${axes().length} metrics available · gaps mean no data`} + + )} @@ -86,10 +93,16 @@ export function ComparisonRadar(props: ComparisonRadarProps) { {(model) => ( - + score !== undefined)} + fallback={} + > + + {(score, index) => { - const point = () => radarPoint(index(), axes().length, score ?? 0) + if (score === undefined) return null + const point = () => radarPoint(index(), axes().length, score) return ( <> @@ -138,6 +151,13 @@ export function ComparisonRadar(props: ComparisonRadarProps) { > {axes()[activeAxis() ?? 0]?.label} {axes()[activeAxis() ?? 0]?.description} + + {(model) => ( + + {model.name}: {formatRadarScore(model.scores[activeAxis() ?? 0])} + + )} + @@ -181,8 +201,7 @@ function buildRadarAxes(catalogModels: readonly ModelCatalogEntry[]): RadarAxis[ { label: "Reasoning", description: "Ability to solve complex, multi-step problems. Based on reasoning benchmarks when available.", - score: (model) => - benchmarkPercentile(model, benchmarks, reasoningBenchmarkPattern) ?? (model.reasoning ? 100 : 0), + score: (model) => benchmarkPercentile(model, benchmarks, reasoningBenchmarkPattern), }, { label: "Coding", @@ -326,11 +345,24 @@ function radarPolygonPoints(count: number, score: number) { function radarSeriesPolygon(scores: (number | undefined)[]) { return scores - .map((score, index) => radarPoint(index, scores.length, score ?? 0)) + .flatMap((score, index) => (score === undefined ? [] : [radarPoint(index, scores.length, score)])) .map((point) => `${point.x},${point.y}`) .join(" ") } +// Only connect neighboring measured axes; missing values have no position on the chart. +export function radarSeriesPath(scores: readonly (number | undefined)[]) { + return scores + .flatMap((score, index) => { + const next = scores[(index + 1) % scores.length] + if (score === undefined || next === undefined) return [] + const start = radarPoint(index, scores.length, score) + const end = radarPoint((index + 1) % scores.length, scores.length, next) + return [`M ${start.x},${start.y} L ${end.x},${end.y}`] + }) + .join(" ") +} + function radarAxisStyle(index: number, count: number) { const angle = -Math.PI / 2 + (index * Math.PI * 2) / count const horizontal = Math.cos(angle) diff --git a/packages/stats/app/src/routes/model-catalog.ts b/packages/stats/app/src/routes/model-catalog.ts index c55af8594ce8..542d95a61eed 100644 --- a/packages/stats/app/src/routes/model-catalog.ts +++ b/packages/stats/app/src/routes/model-catalog.ts @@ -54,6 +54,7 @@ export type ModelCatalogLab = { export type ModelCatalog = { models: ModelCatalogEntry[] + aliases?: ModelCatalogEntry[] labs: ModelCatalogLab[] } @@ -80,7 +81,8 @@ export function findModelCatalogEntry(catalog: ModelCatalog, model: string, lab? return ( catalog.models.find((entry) => entry.id.toLowerCase() === normalizedId) ?? catalog.models.find((entry) => (lab ? entry.lab === catalogLabSlug(lab) : true) && entry.slug === leaf) ?? - catalog.models.find((entry) => entry.slug === leaf) + catalog.models.find((entry) => entry.slug === leaf) ?? + catalog.aliases?.find((entry) => (lab ? entry.lab === catalogLabSlug(lab) : true) && entry.slug === leaf) ) } @@ -133,7 +135,7 @@ export function catalogSlug(value: string) { .replace(/-{2,}/g, "-") } -function buildModelCatalog(payload: unknown, pricingPayload?: unknown, labPayload?: unknown): ModelCatalog { +export function buildModelCatalog(payload: unknown, pricingPayload?: unknown, labPayload?: unknown): ModelCatalog { const costs = readCatalogCosts(pricingPayload) const labDescriptions = readCatalogLabDescriptions(payload, pricingPayload, labPayload) const models = readCatalogModels(payload) @@ -149,6 +151,25 @@ function buildModelCatalog(payload: unknown, pricingPayload?: unknown, labPayloa .toSorted((a, b) => a.lab.localeCompare(b.lab) || displayDateTime(b.releaseDate) - displayDateTime(a.releaseDate)) return { models, + // Contributor is a serving tier of these Muse models, with its own pricing. + // Keep aliases out of the model population used to normalize benchmark scores. + aliases: ["meta/muse-spark-1.2", "meta/muse-spark-1.3"].flatMap((id) => { + const model = models.find((entry) => entry.id === id) + if (!model) return [] + const alias = `${id}-contributor` + return [ + { + ...model, + id: alias, + slug: `${model.slug}-contributor`, + name: `${model.name} Contributor`, + cost: + costs.get(catalogIdKey(alias)) ?? + costs.get(`${model.lab}/${model.slug}-contributor`) ?? + costs.get(`${model.slug}-contributor`), + }, + ] + }), labs: Object.values( models.reduce>((result, model) => { result[model.lab] = { diff --git a/packages/stats/app/test/compare-radar.test.ts b/packages/stats/app/test/compare-radar.test.ts new file mode 100644 index 000000000000..5408c3899a1e --- /dev/null +++ b/packages/stats/app/test/compare-radar.test.ts @@ -0,0 +1,17 @@ +import { describe, expect, test } from "bun:test" +import { radarSeriesPath } from "../src/routes/compare-radar" + +describe("radar missing data", () => { + test("unknown scores do not create points or segments at zero", () => { + expect(radarSeriesPath([undefined, undefined, undefined, undefined])).toBe("") + expect(radarSeriesPath([80, undefined, 60, undefined])).toBe("") + }) + + test("segments stop at gaps and retain the wraparound edge", () => { + expect(radarSeriesPath([100, undefined, 50, 100])).toBe("M 50,75 L 0,50 M 0,50 L 50,0") + }) + + test("a measured zero still connects to measured neighbors", () => { + expect(radarSeriesPath([0, 100, undefined, undefined])).toBe("M 50,50 L 100,50") + }) +}) From ece607374d7aeffe176ed30b83a6b0156204f3ad Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 24 Sep 2026 11:30:14 -0500 Subject: [PATCH 2/5] fix(stats): add radar capability fallbacks --- .../stats/app/src/routes/compare-radar.tsx | 75 ++++++++++--------- packages/stats/app/src/routes/index.css | 11 ++- .../stats/app/src/routes/model-catalog.ts | 8 +- packages/stats/app/test/compare-radar.test.ts | 75 ++++++++++++++++--- 4 files changed, 114 insertions(+), 55 deletions(-) diff --git a/packages/stats/app/src/routes/compare-radar.tsx b/packages/stats/app/src/routes/compare-radar.tsx index ad1a301e9b48..3ed23586b949 100644 --- a/packages/stats/app/src/routes/compare-radar.tsx +++ b/packages/stats/app/src/routes/compare-radar.tsx @@ -22,6 +22,12 @@ type RadarAxis = { label: string description: string score: (model: ModelCatalogEntry) => number | undefined + capability?: "reasoning" | "toolCall" +} + +type RadarScore = { + value: number + fallback?: string } type RadarPoint = { @@ -37,7 +43,7 @@ export function ComparisonRadar(props: ComparisonRadarProps) { name: model.name, labName: model.labName, color: radarColors[index % radarColors.length], - scores: axes().map((axis) => (model.catalog ? axis.score(model.catalog) : undefined)), + scores: axes().map((axis) => resolveRadarScore(axis, model.catalog)), })), ) const accessibleDescription = createMemo(() => @@ -62,12 +68,8 @@ export function ComparisonRadar(props: ComparisonRadarProps) { {model.name} {(name) => {name()}} - score === undefined)}> - - {model.scores.every((score) => score === undefined) - ? "No data available" - : `${model.scores.filter((score) => score !== undefined).length} of ${axes().length} metrics available · gaps mean no data`} - + score.fallback)}> + Hollow points use fallbacks · hover for details @@ -93,19 +95,19 @@ export function ComparisonRadar(props: ComparisonRadarProps) { {(model) => ( - score !== undefined)} - fallback={} - > - - + {(score, index) => { - if (score === undefined) return null - const point = () => radarPoint(index(), axes().length, score) + const point = () => radarPoint(index(), axes().length, score.value) return ( <> - + { @@ -200,7 +202,9 @@ function buildRadarAxes(catalogModels: readonly ModelCatalogEntry[]): RadarAxis[ return [ { label: "Reasoning", - description: "Ability to solve complex, multi-step problems. Based on reasoning benchmarks when available.", + capability: "reasoning", + description: + "Ability to solve complex, multi-step problems. Benchmarks take priority; reasoning support defaults to 50/100.", score: (model) => benchmarkPercentile(model, benchmarks, reasoningBenchmarkPattern), }, { @@ -237,7 +241,8 @@ function buildRadarAxes(catalogModels: readonly ModelCatalogEntry[]): RadarAxis[ }, { label: "Tool use", - description: "Performance on agent benchmarks including Terminal-Bench, Tau3, and Claw-Eval.", + capability: "toolCall", + description: "Agent benchmark performance. Benchmarks take priority; tool calling support defaults to 50/100.", score: (model) => benchmarkPercentile(model, toolUseBenchmarks, toolUseBenchmarkPattern, { aggregate: "average", @@ -343,26 +348,13 @@ function radarPolygonPoints(count: number, score: number) { .join(" ") } -function radarSeriesPolygon(scores: (number | undefined)[]) { +function radarSeriesPolygon(scores: RadarScore[]) { return scores - .flatMap((score, index) => (score === undefined ? [] : [radarPoint(index, scores.length, score)])) + .map((score, index) => radarPoint(index, scores.length, score.value)) .map((point) => `${point.x},${point.y}`) .join(" ") } -// Only connect neighboring measured axes; missing values have no position on the chart. -export function radarSeriesPath(scores: readonly (number | undefined)[]) { - return scores - .flatMap((score, index) => { - const next = scores[(index + 1) % scores.length] - if (score === undefined || next === undefined) return [] - const start = radarPoint(index, scores.length, score) - const end = radarPoint((index + 1) % scores.length, scores.length, next) - return [`M ${start.x},${start.y} L ${end.x},${end.y}`] - }) - .join(" ") -} - function radarAxisStyle(index: number, count: number) { const angle = -Math.PI / 2 + (index * Math.PI * 2) / count const horizontal = Math.cos(angle) @@ -387,6 +379,17 @@ function roundRadarCoordinate(value: number) { return Math.round(value * 1000) / 1000 } -function formatRadarScore(score: number | undefined) { - return score === undefined ? "No data" : `${Math.round(score)}/100` +function formatRadarScore(score: RadarScore) { + return `${Math.round(score.value)}/100${score.fallback ? ` — ${score.fallback}` : ""}` +} + +export function resolveRadarScore(axis: RadarAxis, model: ModelCatalogEntry | null): RadarScore { + const score = model ? axis.score(model) : undefined + if (score !== undefined) return { value: score } + const supported = axis.capability ? model?.[axis.capability] : undefined + if (supported === undefined) return { value: 50, fallback: "No data; neutral placeholder" } + const capability = axis.capability === "toolCall" ? "Tool calling" : "Reasoning" + return supported + ? { value: 50, fallback: `${capability} supported; no comparable benchmark` } + : { value: 0, fallback: `${capability} not supported` } } diff --git a/packages/stats/app/src/routes/index.css b/packages/stats/app/src/routes/index.css index e3e2de48e08a..9cc3bfe13b82 100644 --- a/packages/stats/app/src/routes/index.css +++ b/packages/stats/app/src/routes/index.css @@ -6291,8 +6291,7 @@ body { vector-effect: non-scaling-stroke; } -[data-page="stats"] [data-slot="compare-radar-area"], -[data-page="stats"] [data-slot="compare-radar-line"] { +[data-page="stats"] [data-slot="compare-radar-area"] { stroke: currentColor; stroke-width: 1.5px; stroke-linejoin: round; @@ -6304,10 +6303,6 @@ body { fill-opacity: 0.09; } -[data-page="stats"] [data-slot="compare-radar-line"] { - fill: none; -} - [data-page="stats"] [data-slot="compare-radar-point"] { fill: currentColor; stroke: currentColor; @@ -6315,6 +6310,10 @@ body { vector-effect: non-scaling-stroke; } +[data-page="stats"] [data-slot="compare-radar-point"][data-fallback="true"] { + fill: var(--stats-bg); +} + [data-page="stats"] [data-slot="compare-radar-point-hit"] { fill: transparent; cursor: pointer; diff --git a/packages/stats/app/src/routes/model-catalog.ts b/packages/stats/app/src/routes/model-catalog.ts index 542d95a61eed..ae55eb55a851 100644 --- a/packages/stats/app/src/routes/model-catalog.ts +++ b/packages/stats/app/src/routes/model-catalog.ts @@ -25,8 +25,8 @@ export type ModelCatalogEntry = { limit?: { context?: number; output?: number } modalities: { input: string[]; output: string[] } openWeights: boolean - reasoning: boolean - toolCall: boolean + reasoning?: boolean + toolCall?: boolean attachment: boolean temperature: boolean cost?: ModelCatalogCost @@ -205,8 +205,8 @@ function readModelCatalogEntry(value: unknown): ModelCatalogEntry[] { limit: readCatalogLimit(value.limit), modalities: readCatalogModalities(value.modalities), openWeights: booleanValue(value.open_weights), - reasoning: booleanValue(value.reasoning), - toolCall: booleanValue(value.tool_call), + reasoning: typeof value.reasoning === "boolean" ? value.reasoning : undefined, + toolCall: typeof value.tool_call === "boolean" ? value.tool_call : undefined, attachment: booleanValue(value.attachment), temperature: booleanValue(value.temperature), cost: readCatalogCost(value.cost), diff --git a/packages/stats/app/test/compare-radar.test.ts b/packages/stats/app/test/compare-radar.test.ts index 5408c3899a1e..59f855c69214 100644 --- a/packages/stats/app/test/compare-radar.test.ts +++ b/packages/stats/app/test/compare-radar.test.ts @@ -1,17 +1,74 @@ import { describe, expect, test } from "bun:test" -import { radarSeriesPath } from "../src/routes/compare-radar" +import { buildRadarAxes, resolveRadarScore } from "../src/routes/compare-radar" +import type { ModelCatalogEntry } from "../src/routes/model-catalog" -describe("radar missing data", () => { - test("unknown scores do not create points or segments at zero", () => { - expect(radarSeriesPath([undefined, undefined, undefined, undefined])).toBe("") - expect(radarSeriesPath([80, undefined, 60, undefined])).toBe("") +const model: ModelCatalogEntry = { + id: "meta/muse-spark-1.3", + lab: "meta", + slug: "muse-spark-1-3", + name: "Muse Spark 1.3", + modalities: { input: ["text", "image"], output: ["text"] }, + reasoning: true, + toolCall: true, + openWeights: false, + attachment: true, + temperature: true, + weights: [], + benchmarks: [], +} + +function scores(entry: ModelCatalogEntry | null, catalog = [model]) { + return Object.fromEntries(buildRadarAxes(catalog).map((axis) => [axis.label, resolveRadarScore(axis, entry)])) +} + +describe("radar capability fallbacks", () => { + test("supported capabilities have visible baselines without benchmarks", () => { + const result = scores(model) + expect(result["Tool use"]).toEqual({ value: 50, fallback: "Tool calling supported; no comparable benchmark" }) + expect(result.Reasoning).toEqual({ value: 50, fallback: "Reasoning supported; no comparable benchmark" }) + expect(result.Coding).toEqual({ value: 50, fallback: "No data; neutral placeholder" }) + }) + + test("explicitly unsupported capabilities remain zero", () => { + const result = scores({ ...model, reasoning: false, toolCall: false }) + expect(result["Tool use"]).toEqual({ value: 0, fallback: "Tool calling not supported" }) + expect(result.Reasoning).toEqual({ value: 0, fallback: "Reasoning not supported" }) + }) + + test("unknown capabilities and unmatched models use neutral placeholders", () => { + const result = scores({ ...model, reasoning: undefined, toolCall: undefined }) + expect(result["Tool use"]).toEqual({ value: 50, fallback: "No data; neutral placeholder" }) + expect(result.Reasoning).toEqual({ value: 50, fallback: "No data; neutral placeholder" }) + expect(Object.values(scores(null))).toEqual(Array(6).fill({ value: 50, fallback: "No data; neutral placeholder" })) }) - test("segments stop at gaps and retain the wraparound edge", () => { - expect(radarSeriesPath([100, undefined, 50, 100])).toBe("M 50,75 L 0,50 M 0,50 L 50,0") + test("measured benchmark percentiles override fallbacks, including zero", () => { + const low = { + ...model, + benchmarks: [ + { name: "Tau3", score: 20 }, + { name: "GPQA", score: 40 }, + ], + } + const high = { + ...model, + id: "other/model", + benchmarks: [ + { name: "Tau3", score: 80 }, + { name: "GPQA", score: 90 }, + ], + } + expect(scores(low, [low, high])["Tool use"]).toEqual({ value: 0 }) + expect(scores(low, [low, high]).Reasoning).toEqual({ value: 0 }) + expect(scores(high, [low, high])["Tool use"]).toEqual({ value: 100 }) + expect(scores(high, [low, high]).Reasoning).toEqual({ value: 100 }) }) - test("a measured zero still connects to measured neighbors", () => { - expect(radarSeriesPath([0, 100, undefined, undefined])).toBe("M 50,50 L 100,50") + test("a benchmark without comparison peers retains the capability baseline", () => { + const entry = { ...model, benchmarks: [{ name: "Tau3", score: 90 }] } + expect(scores(entry, [entry])["Tool use"]).toEqual({ + value: 50, + fallback: "Tool calling supported; no comparable benchmark", + }) }) }) From d43f9c604c0631aaa70c0000f459d4cc61aa5cd2 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 24 Sep 2026 13:37:03 -0500 Subject: [PATCH 3/5] fix(ci): clear restored windows patch caches --- .github/actions/setup-bun/action.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.github/actions/setup-bun/action.yml b/.github/actions/setup-bun/action.yml index 9d29724d86a4..40cd60eb2265 100644 --- a/.github/actions/setup-bun/action.yml +++ b/.github/actions/setup-bun/action.yml @@ -49,6 +49,32 @@ runs: restore-keys: | ${{ runner.os }}-bun- + # Bun can reapply patches after a cache restore; Windows cannot rename over + # an existing patched directory (ENOTEMPTY). Keep unpatched downloads cached. + - name: Clear restored patched packages on Windows + if: runner.os == 'Windows' + env: + BUN_CACHE_DIR: ${{ steps.cache.outputs.dir }} + shell: bash + run: | + node --input-type=module <<'JS' + import { existsSync, readdirSync, rmSync } from "node:fs" + import { join } from "node:path" + + const cache = process.env.BUN_CACHE_DIR + if (existsSync(cache)) { + const scopes = readdirSync(cache, { withFileTypes: true }) + .filter((entry) => entry.isDirectory() && entry.name.startsWith("@")) + .map((entry) => join(cache, entry.name)) + for (const directory of [cache, ...scopes]) { + for (const entry of readdirSync(directory, { withFileTypes: true })) { + if (!entry.isDirectory() || !entry.name.includes("_patch_hash=")) continue + rmSync(join(directory, entry.name), { recursive: true, force: true }) + } + } + } + JS + - name: Install setuptools for distutils compatibility run: python3 -m pip install setuptools || pip install setuptools || true shell: bash From 2a806284931847d90ed555d7981446210ac69907 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 24 Sep 2026 13:40:03 -0500 Subject: [PATCH 4/5] fix(ci): distinguish github cache entries from scopes --- .github/actions/setup-bun/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-bun/action.yml b/.github/actions/setup-bun/action.yml index 40cd60eb2265..ff7bfc2b09da 100644 --- a/.github/actions/setup-bun/action.yml +++ b/.github/actions/setup-bun/action.yml @@ -64,7 +64,7 @@ runs: const cache = process.env.BUN_CACHE_DIR if (existsSync(cache)) { const scopes = readdirSync(cache, { withFileTypes: true }) - .filter((entry) => entry.isDirectory() && entry.name.startsWith("@")) + .filter((entry) => entry.isDirectory() && /^@[^@]+$/.test(entry.name)) .map((entry) => join(cache, entry.name)) for (const directory of [cache, ...scopes]) { for (const entry of readdirSync(directory, { withFileTypes: true })) { From acddade450b97d630056c131c2178f7517ae6c5d Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 24 Sep 2026 13:47:07 -0500 Subject: [PATCH 5/5] fix(ci): use patched bun installer on windows --- .github/actions/setup-bun/action.yml | 52 ++++++---------------------- 1 file changed, 11 insertions(+), 41 deletions(-) diff --git a/.github/actions/setup-bun/action.yml b/.github/actions/setup-bun/action.yml index ff7bfc2b09da..92bddf7f531a 100644 --- a/.github/actions/setup-bun/action.yml +++ b/.github/actions/setup-bun/action.yml @@ -15,12 +15,15 @@ runs: with: node-version: "24" - - name: Get baseline download URL + - name: Get Bun version and baseline download URL id: bun-url shell: bash run: | + V=$(node -p "require('./package.json').packageManager.split('@')[1]") + # Bun 1.4.2 includes the patched peer-variant fix in oven-sh/bun#33646. + if [ "$RUNNER_OS" = "Windows" ]; then V=1.4.2; fi + echo "version=$V" >> "$GITHUB_OUTPUT" if [ "$RUNNER_ARCH" = "X64" ]; then - V=$(node -p "require('./package.json').packageManager.split('@')[1]") case "$RUNNER_OS" in macOS) OS=darwin ;; Linux) OS=linux ;; @@ -30,9 +33,10 @@ runs: fi - name: Setup Bun + id: setup-bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: - bun-version-file: ${{ !steps.bun-url.outputs.url && 'package.json' || '' }} + bun-version: ${{ !steps.bun-url.outputs.url && steps.bun-url.outputs.version || '' }} bun-download-url: ${{ steps.bun-url.outputs.url }} - name: Get cache directory @@ -45,50 +49,16 @@ runs: uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ${{ steps.cache.outputs.dir }} - key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} + key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-version }}-${{ hashFiles('**/bun.lock') }} restore-keys: | - ${{ runner.os }}-bun- - - # Bun can reapply patches after a cache restore; Windows cannot rename over - # an existing patched directory (ENOTEMPTY). Keep unpatched downloads cached. - - name: Clear restored patched packages on Windows - if: runner.os == 'Windows' - env: - BUN_CACHE_DIR: ${{ steps.cache.outputs.dir }} - shell: bash - run: | - node --input-type=module <<'JS' - import { existsSync, readdirSync, rmSync } from "node:fs" - import { join } from "node:path" - - const cache = process.env.BUN_CACHE_DIR - if (existsSync(cache)) { - const scopes = readdirSync(cache, { withFileTypes: true }) - .filter((entry) => entry.isDirectory() && /^@[^@]+$/.test(entry.name)) - .map((entry) => join(cache, entry.name)) - for (const directory of [cache, ...scopes]) { - for (const entry of readdirSync(directory, { withFileTypes: true })) { - if (!entry.isDirectory() || !entry.name.includes("_patch_hash=")) continue - rmSync(join(directory, entry.name), { recursive: true, force: true }) - } - } - } - JS + ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-version }}- - name: Install setuptools for distutils compatibility run: python3 -m pip install setuptools || pip install setuptools || true shell: bash - name: Install dependencies - run: | - # Workaround for patched peer variants - # e.g. ./patches/ for standard-openapi - # https://github.com/oven-sh/bun/issues/28147 - if [ "$RUNNER_OS" = "Windows" ]; then - bun install --linker hoisted ${{ inputs.install-flags }} - else - bun install ${{ inputs.install-flags }} - fi + run: bun install ${{ inputs.install-flags }} shell: bash - name: Save Bun dependencies @@ -96,4 +66,4 @@ runs: uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ${{ steps.cache.outputs.dir }} - key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} + key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-version }}-${{ hashFiles('**/bun.lock') }}
{axes()[activeAxis() ?? 0]?.description}
+ {model.name}: {formatRadarScore(model.scores[activeAxis() ?? 0])} +