From 8b7b7e154fa2ea402bb2fd0bb083a68648e7591b Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 23 Jan 2026 11:36:28 +0000 Subject: [PATCH] chore: speed up tests and update opencode models --- scripts/test-parallel.mjs | 35 +++++++++++++++++++++++--- src/agents/live-model-filter.ts | 4 +++ src/agents/opencode-zen-models.test.ts | 13 ++++------ src/agents/opencode-zen-models.ts | 23 ++++++----------- vitest.extensions.config.ts | 14 +++++++++++ vitest.gateway.config.ts | 19 +++++++------- vitest.unit.config.ts | 19 +++++++------- 7 files changed, 79 insertions(+), 48 deletions(-) create mode 100644 vitest.extensions.config.ts diff --git a/scripts/test-parallel.mjs b/scripts/test-parallel.mjs index 3c8ad0a57..78a996751 100644 --- a/scripts/test-parallel.mjs +++ b/scripts/test-parallel.mjs @@ -1,4 +1,5 @@ import { spawn } from "node:child_process"; +import os from "node:os"; const pnpm = process.platform === "win32" ? "pnpm.cmd" : "pnpm"; @@ -7,17 +8,31 @@ const runs = [ name: "unit", args: ["vitest", "run", "--config", "vitest.unit.config.ts"], }, + { + name: "extensions", + args: ["vitest", "run", "--config", "vitest.extensions.config.ts"], + }, { name: "gateway", args: ["vitest", "run", "--config", "vitest.gateway.config.ts"], }, ]; +const parallelRuns = runs.filter((entry) => entry.name !== "gateway"); +const serialRuns = runs.filter((entry) => entry.name === "gateway"); + const children = new Set(); +const isCI = process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true"; +const overrideWorkers = Number.parseInt(process.env.CLAWDBOT_TEST_WORKERS ?? "", 10); +const resolvedOverride = Number.isFinite(overrideWorkers) && overrideWorkers > 0 ? overrideWorkers : null; +const localWorkers = Math.max(4, Math.min(16, os.cpus().length)); +const perRunWorkers = Math.max(1, Math.floor(localWorkers / parallelRuns.length)); +const maxWorkers = isCI ? null : resolvedOverride ?? perRunWorkers; const run = (entry) => new Promise((resolve) => { - const child = spawn(pnpm, entry.args, { + const args = maxWorkers ? [...entry.args, "--maxWorkers", String(maxWorkers)] : entry.args; + const child = spawn(pnpm, args, { stdio: "inherit", env: { ...process.env, VITEST_GROUP: entry.name }, shell: process.platform === "win32", @@ -38,6 +53,18 @@ const shutdown = (signal) => { process.on("SIGINT", () => shutdown("SIGINT")); process.on("SIGTERM", () => shutdown("SIGTERM")); -const codes = await Promise.all(runs.map(run)); -const failed = codes.find((code) => code !== 0); -process.exit(failed ?? 0); +const parallelCodes = await Promise.all(parallelRuns.map(run)); +const failedParallel = parallelCodes.find((code) => code !== 0); +if (failedParallel !== undefined) { + process.exit(failedParallel); +} + +for (const entry of serialRuns) { + // eslint-disable-next-line no-await-in-loop + const code = await run(entry); + if (code !== 0) { + process.exit(code); + } +} + +process.exit(0); diff --git a/src/agents/live-model-filter.ts b/src/agents/live-model-filter.ts index 155fdd81e..07630dd30 100644 --- a/src/agents/live-model-filter.ts +++ b/src/agents/live-model-filter.ts @@ -66,6 +66,10 @@ export function isModernModelRef(ref: ModelRef): boolean { return matchesPrefix(id, XAI_PREFIXES); } + if (provider === "opencode" && id.endsWith("-free")) { + return false; + } + if (provider === "openrouter" || provider === "opencode") { return matchesAny(id, [ ...ANTHROPIC_PREFIXES, diff --git a/src/agents/opencode-zen-models.test.ts b/src/agents/opencode-zen-models.test.ts index d46b0ac6b..2d540120b 100644 --- a/src/agents/opencode-zen-models.test.ts +++ b/src/agents/opencode-zen-models.test.ts @@ -41,12 +41,11 @@ describe("resolveOpencodeZenAlias", () => { describe("resolveOpencodeZenModelApi", () => { it("maps APIs by model family", () => { expect(resolveOpencodeZenModelApi("claude-opus-4-5")).toBe("anthropic-messages"); - expect(resolveOpencodeZenModelApi("minimax-m2.1-free")).toBe("anthropic-messages"); expect(resolveOpencodeZenModelApi("gemini-3-pro")).toBe("google-generative-ai"); expect(resolveOpencodeZenModelApi("gpt-5.2")).toBe("openai-responses"); expect(resolveOpencodeZenModelApi("alpha-gd4")).toBe("openai-completions"); expect(resolveOpencodeZenModelApi("big-pickle")).toBe("openai-completions"); - expect(resolveOpencodeZenModelApi("glm-4.7-free")).toBe("openai-completions"); + expect(resolveOpencodeZenModelApi("glm-4.7")).toBe("openai-completions"); expect(resolveOpencodeZenModelApi("some-unknown-model")).toBe("openai-completions"); }); }); @@ -55,10 +54,10 @@ describe("getOpencodeZenStaticFallbackModels", () => { it("returns an array of models", () => { const models = getOpencodeZenStaticFallbackModels(); expect(Array.isArray(models)).toBe(true); - expect(models.length).toBe(11); + expect(models.length).toBe(10); }); - it("includes Claude, GPT, Gemini, GLM, and MiniMax models", () => { + it("includes Claude, GPT, Gemini, and GLM models", () => { const models = getOpencodeZenStaticFallbackModels(); const ids = models.map((m) => m.id); @@ -66,8 +65,7 @@ describe("getOpencodeZenStaticFallbackModels", () => { expect(ids).toContain("gpt-5.2"); expect(ids).toContain("gpt-5.1-codex"); expect(ids).toContain("gemini-3-pro"); - expect(ids).toContain("glm-4.7-free"); - expect(ids).toContain("minimax-m2.1-free"); + expect(ids).toContain("glm-4.7"); }); it("returns valid ModelDefinitionConfig objects", () => { @@ -90,8 +88,7 @@ describe("OPENCODE_ZEN_MODEL_ALIASES", () => { expect(OPENCODE_ZEN_MODEL_ALIASES.codex).toBe("gpt-5.1-codex"); expect(OPENCODE_ZEN_MODEL_ALIASES.gpt5).toBe("gpt-5.2"); expect(OPENCODE_ZEN_MODEL_ALIASES.gemini).toBe("gemini-3-pro"); - expect(OPENCODE_ZEN_MODEL_ALIASES.glm).toBe("glm-4.7-free"); - expect(OPENCODE_ZEN_MODEL_ALIASES.minimax).toBe("minimax-m2.1-free"); + expect(OPENCODE_ZEN_MODEL_ALIASES.glm).toBe("glm-4.7"); // Legacy aliases (kept for backward compatibility). expect(OPENCODE_ZEN_MODEL_ALIASES.sonnet).toBe("claude-opus-4-5"); diff --git a/src/agents/opencode-zen-models.ts b/src/agents/opencode-zen-models.ts index bf1734d5e..d91111ffb 100644 --- a/src/agents/opencode-zen-models.ts +++ b/src/agents/opencode-zen-models.ts @@ -68,13 +68,9 @@ export const OPENCODE_ZEN_MODEL_ALIASES: Record = { "gemini-2.5-flash": "gemini-3-flash", // GLM (free + alpha) - glm: "glm-4.7-free", - "glm-free": "glm-4.7-free", + glm: "glm-4.7", + "glm-free": "glm-4.7", "alpha-glm": "alpha-glm-4.7", - - // MiniMax - minimax: "minimax-m2.1-free", - "minimax-free": "minimax-m2.1-free", }; /** @@ -134,7 +130,7 @@ const MODEL_COSTS: Record< cacheWrite: 0, }, "gpt-5.1": { input: 1.07, output: 8.5, cacheRead: 0.107, cacheWrite: 0 }, - "glm-4.7-free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, + "glm-4.7": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, "gemini-3-flash": { input: 0.5, output: 3, cacheRead: 0.05, cacheWrite: 0 }, "gpt-5.1-codex-max": { input: 1.25, @@ -142,7 +138,6 @@ const MODEL_COSTS: Record< cacheRead: 0.125, cacheWrite: 0, }, - "minimax-m2.1-free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, "gpt-5.2": { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 }, }; @@ -155,10 +150,9 @@ const MODEL_CONTEXT_WINDOWS: Record = { "alpha-glm-4.7": 204800, "gpt-5.1-codex-mini": 400000, "gpt-5.1": 400000, - "glm-4.7-free": 204800, + "glm-4.7": 204800, "gemini-3-flash": 1048576, "gpt-5.1-codex-max": 400000, - "minimax-m2.1-free": 204800, "gpt-5.2": 400000, }; @@ -173,10 +167,9 @@ const MODEL_MAX_TOKENS: Record = { "alpha-glm-4.7": 131072, "gpt-5.1-codex-mini": 128000, "gpt-5.1": 128000, - "glm-4.7-free": 131072, + "glm-4.7": 131072, "gemini-3-flash": 65536, "gpt-5.1-codex-max": 128000, - "minimax-m2.1-free": 131072, "gpt-5.2": 128000, }; @@ -211,10 +204,9 @@ const MODEL_NAMES: Record = { "alpha-glm-4.7": "Alpha GLM-4.7", "gpt-5.1-codex-mini": "GPT-5.1 Codex Mini", "gpt-5.1": "GPT-5.1", - "glm-4.7-free": "GLM-4.7", + "glm-4.7": "GLM-4.7", "gemini-3-flash": "Gemini 3 Flash", "gpt-5.1-codex-max": "GPT-5.1 Codex Max", - "minimax-m2.1-free": "MiniMax M2.1", "gpt-5.2": "GPT-5.2", }; @@ -240,10 +232,9 @@ export function getOpencodeZenStaticFallbackModels(): ModelDefinitionConfig[] { "alpha-glm-4.7", "gpt-5.1-codex-mini", "gpt-5.1", - "glm-4.7-free", + "glm-4.7", "gemini-3-flash", "gpt-5.1-codex-max", - "minimax-m2.1-free", "gpt-5.2", ]; diff --git a/vitest.extensions.config.ts b/vitest.extensions.config.ts new file mode 100644 index 000000000..83f9d97d3 --- /dev/null +++ b/vitest.extensions.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from "vitest/config"; +import baseConfig from "./vitest.config.ts"; + +const baseTest = (baseConfig as { test?: { exclude?: string[] } }).test ?? {}; +const exclude = baseTest.exclude ?? []; + +export default defineConfig({ + ...baseConfig, + test: { + ...baseTest, + include: ["extensions/**/*.test.ts"], + exclude, + }, +}); diff --git a/vitest.gateway.config.ts b/vitest.gateway.config.ts index 3440d797f..eb091f265 100644 --- a/vitest.gateway.config.ts +++ b/vitest.gateway.config.ts @@ -1,15 +1,14 @@ -import { defineConfig, mergeConfig } from "vitest/config"; +import { defineConfig } from "vitest/config"; import baseConfig from "./vitest.config.ts"; const baseTest = (baseConfig as { test?: { exclude?: string[] } }).test ?? {}; const exclude = baseTest.exclude ?? []; -export default mergeConfig( - baseConfig, - defineConfig({ - test: { - include: ["src/gateway/**/*.test.ts", "extensions/**/*.test.ts"], - exclude, - }, - }), -); +export default defineConfig({ + ...baseConfig, + test: { + ...baseTest, + include: ["src/gateway/**/*.test.ts"], + exclude, + }, +}); diff --git a/vitest.unit.config.ts b/vitest.unit.config.ts index 697063180..541dd864e 100644 --- a/vitest.unit.config.ts +++ b/vitest.unit.config.ts @@ -1,4 +1,4 @@ -import { defineConfig, mergeConfig } from "vitest/config"; +import { defineConfig } from "vitest/config"; import baseConfig from "./vitest.config.ts"; const baseTest = (baseConfig as { test?: { include?: string[]; exclude?: string[] } }).test ?? {}; @@ -9,12 +9,11 @@ const include = baseTest.include ?? [ ]; const exclude = baseTest.exclude ?? []; -export default mergeConfig( - baseConfig, - defineConfig({ - test: { - include, - exclude: [...exclude, "src/gateway/**", "extensions/**"], - }, - }), -); +export default defineConfig({ + ...baseConfig, + test: { + ...baseTest, + include, + exclude: [...exclude, "src/gateway/**", "extensions/**"], + }, +});