mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-06 15:22:12 +03:00
fix(test): revive orphaned open-sse vitest tests (#8772)
Validated in local merge-train T6 (ungrouped batch 1)
This commit is contained in:
@@ -273,9 +273,15 @@ describe("claudeTlsClient", () => {
|
||||
|
||||
await tlsFetchClaude("https://claude.ai/test", {});
|
||||
|
||||
// The proxyUrl should reflect environment resolution
|
||||
// The testOverride is called with the raw options object BEFORE proxy
|
||||
// resolution occurs (see claudeTlsClient.ts line 258:
|
||||
// `if (testOverride) return testOverride(url, options)`).
|
||||
// Proxy resolution (env var → proxyUrl) only runs inside the real
|
||||
// tls-client path, which is bypassed when an override is active.
|
||||
// So callOptions here is exactly the {} we passed — no proxyUrl injected.
|
||||
expect(mockFn).toHaveBeenCalledOnce();
|
||||
const callOptions = mockFn.mock.calls[0][1];
|
||||
expect(callOptions).toHaveProperty("proxyUrl");
|
||||
expect(callOptions.proxyUrl).toBeUndefined();
|
||||
|
||||
__setTlsFetchOverrideForTesting(null);
|
||||
delete process.env.HTTPS_PROXY;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { describe, it } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import {
|
||||
generateRoutingHints,
|
||||
compareByCostEffectiveness,
|
||||
@@ -27,8 +26,8 @@ describe("ManifestAdapter", () => {
|
||||
const hints = generateRoutingHints([], {
|
||||
messages: [{ content: "Hello" }],
|
||||
});
|
||||
assert.equal(hints.strategyModifier, "prefer-free");
|
||||
assert.equal(hints.specificityLevel, "trivial");
|
||||
expect(hints.strategyModifier).toBe("prefer-free");
|
||||
expect(hints.specificityLevel).toBe("trivial");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,7 +42,7 @@ describe("ManifestAdapter", () => {
|
||||
],
|
||||
});
|
||||
const validModifiers = ["prefer-free", "prefer-cheap", "require-premium", "default"];
|
||||
assert.ok(validModifiers.includes(hints.strategyModifier));
|
||||
expect(validModifiers.includes(hints.strategyModifier)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -53,15 +52,15 @@ describe("ManifestAdapter", () => {
|
||||
const hints = generateRoutingHints(targets, {
|
||||
messages: [{ content: "Hi" }],
|
||||
});
|
||||
assert.ok(hints.eligibleTargets.length >= 0);
|
||||
expect(hints.eligibleTargets.length).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
|
||||
it("handles empty targets array gracefully", () => {
|
||||
const hints = generateRoutingHints([], {
|
||||
messages: [{ content: "Hello" }],
|
||||
});
|
||||
assert.equal(hints.eligibleTargets.length, 0);
|
||||
assert.equal(hints.underqualifiedTargets.length, 0);
|
||||
expect(hints.eligibleTargets.length).toBe(0);
|
||||
expect(hints.underqualifiedTargets.length).toBe(0);
|
||||
});
|
||||
|
||||
it("classifies mixed targets for simple query", () => {
|
||||
@@ -69,7 +68,7 @@ describe("ManifestAdapter", () => {
|
||||
const hints = generateRoutingHints(targets, {
|
||||
messages: [{ content: "Hello" }],
|
||||
});
|
||||
assert.ok(hints.eligibleTargets.length >= 0);
|
||||
expect(hints.eligibleTargets.length).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -81,7 +80,7 @@ describe("ManifestAdapter", () => {
|
||||
messages: [{ content: "Test" }],
|
||||
});
|
||||
const result = compareByCostEffectiveness(a, b, hints);
|
||||
assert.equal(typeof result, "number");
|
||||
expect(typeof result).toBe("number");
|
||||
});
|
||||
|
||||
it("returns negative when a is cheaper than b", () => {
|
||||
@@ -91,7 +90,7 @@ describe("ManifestAdapter", () => {
|
||||
messages: [{ content: "Test" }],
|
||||
});
|
||||
const result = compareByCostEffectiveness(a, b, hints);
|
||||
assert.ok(result < 0, "deepseek should be cheaper than openai");
|
||||
expect(result, "deepseek should be cheaper than openai").toBeLessThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -99,19 +98,19 @@ describe("ManifestAdapter", () => {
|
||||
it("returns 0 for free providers", () => {
|
||||
const target = makeTarget("kiro", "claude-sonnet-4.5");
|
||||
const cost = estimateRequestCost(target, 1000, 500);
|
||||
assert.equal(cost, 0);
|
||||
expect(cost).toBe(0);
|
||||
});
|
||||
|
||||
it("returns non-zero for premium provider", () => {
|
||||
const target = makeTarget("openai", "gpt-4o");
|
||||
const cost = estimateRequestCost(target, 1000000, 500000);
|
||||
assert.ok(cost > 0, "gpt-4o should have non-zero cost");
|
||||
expect(cost, "gpt-4o should have non-zero cost").toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("handles zero tokens", () => {
|
||||
const target = makeTarget("openai", "gpt-4o");
|
||||
const cost = estimateRequestCost(target, 0, 0);
|
||||
assert.equal(cost, 0);
|
||||
expect(cost).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -120,17 +119,17 @@ describe("ManifestAdapter", () => {
|
||||
const hints = generateRoutingHints([], {
|
||||
messages: [{ content: "Hello" }],
|
||||
});
|
||||
assert.equal(hints.eligibleTargets.length, 0);
|
||||
assert.equal(hints.underqualifiedTargets.length, 0);
|
||||
expect(hints.eligibleTargets.length).toBe(0);
|
||||
expect(hints.underqualifiedTargets.length).toBe(0);
|
||||
});
|
||||
|
||||
it("returns valid hints structure with no targets", () => {
|
||||
const hints = generateRoutingHints([], {
|
||||
messages: [{ content: "Test" }],
|
||||
});
|
||||
assert.ok("specificityLevel" in hints);
|
||||
assert.ok("strategyModifier" in hints);
|
||||
assert.ok("recommendedMinTier" in hints);
|
||||
expect("specificityLevel" in hints).toBe(true);
|
||||
expect("strategyModifier" in hints).toBe(true);
|
||||
expect("recommendedMinTier" in hints).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { describe, it } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import {
|
||||
analyzeSpecificity,
|
||||
getSpecificityLevel,
|
||||
@@ -12,13 +11,13 @@ describe("SpecificityDetector", () => {
|
||||
describe("analyzeSpecificity - trivial query", () => {
|
||||
it("returns score <= 5 for greeting", () => {
|
||||
const result = analyzeSpecificity({ messages: [{ content: "Hello, how are you?" }] });
|
||||
assert.ok(result.score <= 5);
|
||||
expect(result.score).toBeLessThanOrEqual(5);
|
||||
});
|
||||
|
||||
it("level is 'trivial' for greeting", () => {
|
||||
const result = analyzeSpecificity({ messages: [{ content: "Hi there!" }] });
|
||||
const level = getSpecificityLevel(result.score);
|
||||
assert.equal(level, "trivial");
|
||||
expect(level).toBe("trivial");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -27,8 +26,8 @@ describe("SpecificityDetector", () => {
|
||||
const result = analyzeSpecificity({
|
||||
messages: [{ content: "What is the capital of France?" }],
|
||||
});
|
||||
assert.ok(result.score >= 0);
|
||||
assert.ok(result.score <= 20);
|
||||
expect(result.score).toBeGreaterThanOrEqual(0);
|
||||
expect(result.score).toBeLessThanOrEqual(20);
|
||||
});
|
||||
|
||||
it("returns 'simple' or lower for factual question", () => {
|
||||
@@ -36,7 +35,7 @@ describe("SpecificityDetector", () => {
|
||||
messages: [{ content: "Who invented Python?" }],
|
||||
});
|
||||
const level = getSpecificityLevel(result.score);
|
||||
assert.ok(["trivial", "simple"].includes(level));
|
||||
expect(["trivial", "simple"].includes(level)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -45,14 +44,14 @@ describe("SpecificityDetector", () => {
|
||||
const result = analyzeSpecificity({
|
||||
messages: [{ content: "```ts\nfunction foo(){}\n```" }],
|
||||
});
|
||||
assert.ok(result.score >= 5, `Expected >= 5, got ${result.score}`);
|
||||
expect(result.score, `Expected >= 5, got ${result.score}`).toBeGreaterThanOrEqual(5);
|
||||
});
|
||||
|
||||
it("code complexity is detected in code blocks", () => {
|
||||
const result = analyzeSpecificity({
|
||||
messages: [{ content: "```ts\nfunction foo(){}\n```" }],
|
||||
});
|
||||
assert.ok(result.breakdown.codeComplexity > 0);
|
||||
expect(result.breakdown.codeComplexity).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("returns higher score for code + reasoning", () => {
|
||||
@@ -66,7 +65,7 @@ describe("SpecificityDetector", () => {
|
||||
{ content: "```typescript\nclass BST<T> { insert(val: T): void {} }\n```" },
|
||||
],
|
||||
});
|
||||
assert.ok(result.score >= 10, `Expected >= 10, got ${result.score}`);
|
||||
expect(result.score, `Expected >= 10, got ${result.score}`).toBeGreaterThanOrEqual(10);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -80,82 +79,82 @@ describe("SpecificityDetector", () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
assert.ok(result.breakdown.reasoningDepth > 0);
|
||||
expect(result.breakdown.reasoningDepth).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getSpecificityLevel", () => {
|
||||
it("returns 'trivial' for score 0-5", () => {
|
||||
assert.equal(getSpecificityLevel(0), "trivial");
|
||||
assert.equal(getSpecificityLevel(3), "trivial");
|
||||
assert.equal(getSpecificityLevel(5), "trivial");
|
||||
expect(getSpecificityLevel(0)).toBe("trivial");
|
||||
expect(getSpecificityLevel(3)).toBe("trivial");
|
||||
expect(getSpecificityLevel(5)).toBe("trivial");
|
||||
});
|
||||
|
||||
it("returns 'simple' for score 6-20", () => {
|
||||
assert.equal(getSpecificityLevel(6), "simple");
|
||||
assert.equal(getSpecificityLevel(10), "simple");
|
||||
assert.equal(getSpecificityLevel(20), "simple");
|
||||
expect(getSpecificityLevel(6)).toBe("simple");
|
||||
expect(getSpecificityLevel(10)).toBe("simple");
|
||||
expect(getSpecificityLevel(20)).toBe("simple");
|
||||
});
|
||||
|
||||
it("returns 'moderate' for score 6-40", () => {
|
||||
assert.equal(getSpecificityLevel(21), "moderate");
|
||||
assert.equal(getSpecificityLevel(30), "moderate");
|
||||
assert.equal(getSpecificityLevel(40), "moderate");
|
||||
expect(getSpecificityLevel(21)).toBe("moderate");
|
||||
expect(getSpecificityLevel(30)).toBe("moderate");
|
||||
expect(getSpecificityLevel(40)).toBe("moderate");
|
||||
});
|
||||
|
||||
it("returns 'complex' for score 41+", () => {
|
||||
assert.equal(getSpecificityLevel(41), "complex");
|
||||
assert.equal(getSpecificityLevel(46), "complex");
|
||||
assert.equal(getSpecificityLevel(65), "complex");
|
||||
expect(getSpecificityLevel(41)).toBe("complex");
|
||||
expect(getSpecificityLevel(46)).toBe("complex");
|
||||
expect(getSpecificityLevel(65)).toBe("complex");
|
||||
});
|
||||
|
||||
it("returns 'expert' for score 66+", () => {
|
||||
assert.equal(getSpecificityLevel(66), "expert");
|
||||
assert.equal(getSpecificityLevel(80), "expert");
|
||||
assert.equal(getSpecificityLevel(100), "expert");
|
||||
expect(getSpecificityLevel(66)).toBe("expert");
|
||||
expect(getSpecificityLevel(80)).toBe("expert");
|
||||
expect(getSpecificityLevel(100)).toBe("expert");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getRecommendedMinTier", () => {
|
||||
it("returns 'free' for 'trivial'", () => {
|
||||
assert.equal(getRecommendedMinTier("trivial"), "free");
|
||||
expect(getRecommendedMinTier("trivial")).toBe("free");
|
||||
});
|
||||
|
||||
it("returns 'free' for 'simple'", () => {
|
||||
assert.equal(getRecommendedMinTier("simple"), "free");
|
||||
expect(getRecommendedMinTier("simple")).toBe("free");
|
||||
});
|
||||
|
||||
it("returns 'cheap' for 'moderate'", () => {
|
||||
assert.equal(getRecommendedMinTier("moderate"), "cheap");
|
||||
expect(getRecommendedMinTier("moderate")).toBe("cheap");
|
||||
});
|
||||
|
||||
it("returns 'premium' for 'complex'", () => {
|
||||
assert.equal(getRecommendedMinTier("complex"), "cheap");
|
||||
expect(getRecommendedMinTier("complex")).toBe("cheap");
|
||||
});
|
||||
|
||||
it("returns 'premium' for 'expert'", () => {
|
||||
assert.equal(getRecommendedMinTier("expert"), "premium");
|
||||
expect(getRecommendedMinTier("expert")).toBe("premium");
|
||||
});
|
||||
});
|
||||
|
||||
describe("isHighSpecificity", () => {
|
||||
it("returns false for trivial query", () => {
|
||||
const result = analyzeSpecificity({ messages: [{ content: "Hi" }] });
|
||||
assert.equal(isHighSpecificity(result), false);
|
||||
expect(isHighSpecificity(result)).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false for simple query", () => {
|
||||
const result = analyzeSpecificity({
|
||||
messages: [{ content: "What is Python?" }],
|
||||
});
|
||||
assert.equal(isHighSpecificity(result), false);
|
||||
expect(isHighSpecificity(result)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isLowSpecificity", () => {
|
||||
it("returns true for trivial query", () => {
|
||||
const result = analyzeSpecificity({ messages: [{ content: "Hi" }] });
|
||||
assert.equal(isLowSpecificity(result), true);
|
||||
expect(isLowSpecificity(result)).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false for complex query", () => {
|
||||
@@ -172,45 +171,45 @@ describe("SpecificityDetector", () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
assert.equal(isLowSpecificity(result), false);
|
||||
expect(isLowSpecificity(result)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("analyzeSpecificity returns complete result", () => {
|
||||
it("returns score, breakdown, rulesTriggered, inputTokens, confidence", () => {
|
||||
const result = analyzeSpecificity({ messages: [{ content: "Test" }] });
|
||||
assert.ok("score" in result);
|
||||
assert.ok("breakdown" in result);
|
||||
assert.ok("rulesTriggered" in result);
|
||||
assert.ok("inputTokens" in result);
|
||||
assert.ok("confidence" in result);
|
||||
expect("score" in result).toBe(true);
|
||||
expect("breakdown" in result).toBe(true);
|
||||
expect("rulesTriggered" in result).toBe(true);
|
||||
expect("inputTokens" in result).toBe(true);
|
||||
expect("confidence" in result).toBe(true);
|
||||
});
|
||||
|
||||
it("returns all 6 breakdown categories", () => {
|
||||
const result = analyzeSpecificity({ messages: [{ content: "Test" }] });
|
||||
assert.ok("codeComplexity" in result.breakdown);
|
||||
assert.ok("mathComplexity" in result.breakdown);
|
||||
assert.ok("reasoningDepth" in result.breakdown);
|
||||
assert.ok("contextSize" in result.breakdown);
|
||||
assert.ok("toolCalling" in result.breakdown);
|
||||
assert.ok("domainSpecificity" in result.breakdown);
|
||||
expect("codeComplexity" in result.breakdown).toBe(true);
|
||||
expect("mathComplexity" in result.breakdown).toBe(true);
|
||||
expect("reasoningDepth" in result.breakdown).toBe(true);
|
||||
expect("contextSize" in result.breakdown).toBe(true);
|
||||
expect("toolCalling" in result.breakdown).toBe(true);
|
||||
expect("domainSpecificity" in result.breakdown).toBe(true);
|
||||
});
|
||||
|
||||
it("returns non-negative scores for all categories", () => {
|
||||
const result = analyzeSpecificity({ messages: [{ content: "Hello" }] });
|
||||
assert.ok(result.breakdown.codeComplexity >= 0);
|
||||
assert.ok(result.breakdown.mathComplexity >= 0);
|
||||
assert.ok(result.breakdown.reasoningDepth >= 0);
|
||||
assert.ok(result.breakdown.contextSize >= 0);
|
||||
assert.ok(result.breakdown.toolCalling >= 0);
|
||||
assert.ok(result.breakdown.domainSpecificity >= 0);
|
||||
expect(result.breakdown.codeComplexity).toBeGreaterThanOrEqual(0);
|
||||
expect(result.breakdown.mathComplexity).toBeGreaterThanOrEqual(0);
|
||||
expect(result.breakdown.reasoningDepth).toBeGreaterThanOrEqual(0);
|
||||
expect(result.breakdown.contextSize).toBeGreaterThanOrEqual(0);
|
||||
expect(result.breakdown.toolCalling).toBeGreaterThanOrEqual(0);
|
||||
expect(result.breakdown.domainSpecificity).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("tool calling detection", () => {
|
||||
it("returns 0 when no tools defined", () => {
|
||||
const result = analyzeSpecificity({ messages: [{ content: "Hello" }] });
|
||||
assert.equal(result.breakdown.toolCalling, 0);
|
||||
expect(result.breakdown.toolCalling).toBe(0);
|
||||
});
|
||||
|
||||
it("returns positive score when tools present", () => {
|
||||
@@ -221,7 +220,7 @@ describe("SpecificityDetector", () => {
|
||||
{ type: "function", function: { name: "weather", description: "get weather" } },
|
||||
],
|
||||
});
|
||||
assert.ok(result.breakdown.toolCalling > 0);
|
||||
expect(result.breakdown.toolCalling).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -234,7 +233,7 @@ describe("SpecificityDetector", () => {
|
||||
const t0 = performance.now();
|
||||
analyzeSpecificity({ messages: msgs });
|
||||
const elapsed = performance.now() - t0;
|
||||
assert.ok(elapsed < 5, `Expected < 5ms, got ${elapsed.toFixed(2)}ms`);
|
||||
expect(elapsed, `Expected < 5ms, got ${elapsed.toFixed(2)}ms`).toBeLessThan(5);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
* Tests: classifyTier, setTierConfig, clearTierCache, getTierStats, classifyTiers
|
||||
*/
|
||||
|
||||
import { describe, it, beforeEach } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it, expect, beforeEach } from "vitest";
|
||||
import {
|
||||
classifyTier,
|
||||
setTierConfig,
|
||||
@@ -27,94 +26,94 @@ describe("TierResolver", () => {
|
||||
describe("classifyTier - free providers", () => {
|
||||
it("classifies Kiro as free", () => {
|
||||
const result = classifyTier("kiro", "claude-sonnet-4.5");
|
||||
assert.equal(result.tier, PROVIDER_TIER.FREE);
|
||||
assert.equal(result.hasFreeTier, true);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.FREE);
|
||||
expect(result.hasFreeTier).toBe(true);
|
||||
});
|
||||
|
||||
it("classifies Qoder as free", () => {
|
||||
const result = classifyTier("qoder", "kimi-k2-thinking");
|
||||
assert.equal(result.tier, PROVIDER_TIER.FREE);
|
||||
assert.equal(result.hasFreeTier, true);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.FREE);
|
||||
expect(result.hasFreeTier).toBe(true);
|
||||
});
|
||||
|
||||
it("classifies Pollinations as free", () => {
|
||||
const result = classifyTier("pollinations", "gpt-5");
|
||||
assert.equal(result.tier, PROVIDER_TIER.FREE);
|
||||
assert.equal(result.hasFreeTier, true);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.FREE);
|
||||
expect(result.hasFreeTier).toBe(true);
|
||||
});
|
||||
|
||||
it("classifies LongCat as free", () => {
|
||||
const result = classifyTier("longcat", "LongCat-2.0");
|
||||
assert.equal(result.tier, PROVIDER_TIER.FREE);
|
||||
assert.equal(result.hasFreeTier, true);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.FREE);
|
||||
expect(result.hasFreeTier).toBe(true);
|
||||
});
|
||||
|
||||
it("classifies Cloudflare AI as free", () => {
|
||||
const result = classifyTier("cloudflare-ai", "llama-3.3-70b");
|
||||
assert.equal(result.tier, PROVIDER_TIER.FREE);
|
||||
assert.equal(result.hasFreeTier, true);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.FREE);
|
||||
expect(result.hasFreeTier).toBe(true);
|
||||
});
|
||||
|
||||
it("classifies NVIDIA NIM as free", () => {
|
||||
const result = classifyTier("nvidia-nim", "llama-3.1-8b");
|
||||
assert.equal(result.tier, PROVIDER_TIER.FREE);
|
||||
assert.equal(result.hasFreeTier, true);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.FREE);
|
||||
expect(result.hasFreeTier).toBe(true);
|
||||
});
|
||||
|
||||
it("classifies Cerebras as free", () => {
|
||||
const result = classifyTier("cerebras", "llama-3.1-70b");
|
||||
assert.equal(result.tier, PROVIDER_TIER.FREE);
|
||||
assert.equal(result.hasFreeTier, true);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.FREE);
|
||||
expect(result.hasFreeTier).toBe(true);
|
||||
});
|
||||
|
||||
it("classifies Groq as free", () => {
|
||||
const result = classifyTier("groq", "llama-3.3-70b");
|
||||
assert.equal(result.tier, PROVIDER_TIER.FREE);
|
||||
assert.equal(result.hasFreeTier, true);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.FREE);
|
||||
expect(result.hasFreeTier).toBe(true);
|
||||
});
|
||||
|
||||
it("sets costPer1MInput to 0 for free providers", () => {
|
||||
const result = classifyTier("kiro", "claude-sonnet-4.5");
|
||||
assert.equal(result.costPer1MInput, 0);
|
||||
assert.equal(result.costPer1MOutput, 0);
|
||||
expect(result.costPer1MInput).toBe(0);
|
||||
expect(result.costPer1MOutput).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("classifyTier - cost-based classification", () => {
|
||||
it("classifies DeepSeek as cheap ($0.27/M < $1.00/M)", () => {
|
||||
const result = classifyTier("deepseek", "deepseek-chat");
|
||||
assert.equal(result.tier, PROVIDER_TIER.CHEAP);
|
||||
assert.ok(result.costPer1MInput <= 1.0);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.CHEAP);
|
||||
expect(result.costPer1MInput).toBeLessThanOrEqual(1.0);
|
||||
});
|
||||
|
||||
it("classifies GLM as cheap ($0.60/M < $1.00/M)", () => {
|
||||
const result = classifyTier("glm", "glm-4.7");
|
||||
assert.equal(result.tier, PROVIDER_TIER.CHEAP);
|
||||
assert.ok(result.costPer1MInput <= 1.0);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.CHEAP);
|
||||
expect(result.costPer1MInput).toBeLessThanOrEqual(1.0);
|
||||
});
|
||||
|
||||
it("classifies MiniMax as cheap ($0.20/M < $1.00/M)", () => {
|
||||
const result = classifyTier("minimax", "minimax-m2.1");
|
||||
assert.equal(result.tier, PROVIDER_TIER.CHEAP);
|
||||
assert.ok(result.costPer1MInput <= 1.0);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.CHEAP);
|
||||
expect(result.costPer1MInput).toBeLessThanOrEqual(1.0);
|
||||
});
|
||||
|
||||
it("classifies GPT-4o as premium ($2.50/M > $1.00/M)", () => {
|
||||
const result = classifyTier("openai", "gpt-4o");
|
||||
assert.equal(result.tier, PROVIDER_TIER.PREMIUM);
|
||||
assert.ok(result.costPer1MInput > 1.0);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.PREMIUM);
|
||||
expect(result.costPer1MInput).toBeGreaterThan(1.0);
|
||||
});
|
||||
|
||||
it("classifies Claude Opus as premium ($15.00/M > $1.00/M)", () => {
|
||||
const result = classifyTier("anthropic", "claude-opus-4-7");
|
||||
assert.equal(result.tier, PROVIDER_TIER.PREMIUM);
|
||||
assert.ok(result.costPer1MInput > 1.0);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.PREMIUM);
|
||||
expect(result.costPer1MInput).toBeGreaterThan(1.0);
|
||||
});
|
||||
|
||||
it("defaults unknown providers to premium", () => {
|
||||
const result = classifyTier("unknown-provider", "unknown-model");
|
||||
assert.equal(result.tier, PROVIDER_TIER.PREMIUM);
|
||||
assert.equal(result.costPer1MInput, 5.0); // default premium pricing
|
||||
expect(result.tier).toBe(PROVIDER_TIER.PREMIUM);
|
||||
expect(result.costPer1MInput).toBe(5.0); // default premium pricing
|
||||
});
|
||||
});
|
||||
|
||||
@@ -122,8 +121,8 @@ describe("TierResolver", () => {
|
||||
it("respects provider-level tier override", () => {
|
||||
setTierConfig({ providerOverrides: [{ provider: "openai", tier: "cheap" }] });
|
||||
const result = classifyTier("openai", "gpt-4o");
|
||||
assert.equal(result.tier, PROVIDER_TIER.CHEAP);
|
||||
assert.ok(result.reason.includes("override"));
|
||||
expect(result.tier).toBe(PROVIDER_TIER.CHEAP);
|
||||
expect(result.reason.includes("override")).toBe(true);
|
||||
});
|
||||
|
||||
it("respects model-level glob pattern override", () => {
|
||||
@@ -131,7 +130,7 @@ describe("TierResolver", () => {
|
||||
modelOverrides: [{ provider: "openai", modelPattern: "gpt-4o-mini*", tier: "cheap" }],
|
||||
});
|
||||
const result = classifyTier("openai", "gpt-4o-mini-2024-07-18");
|
||||
assert.equal(result.tier, PROVIDER_TIER.CHEAP);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.CHEAP);
|
||||
});
|
||||
|
||||
it("glob pattern gpt-4o-mini* matches gpt-4o-mini-2024-07-18", () => {
|
||||
@@ -139,15 +138,15 @@ describe("TierResolver", () => {
|
||||
modelOverrides: [{ provider: "openai", modelPattern: "gpt-4o-mini*", tier: "cheap" }],
|
||||
});
|
||||
const result = classifyTier("openai", "gpt-4o-mini-2024-07-18");
|
||||
assert.equal(result.tier, PROVIDER_TIER.CHEAP);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.CHEAP);
|
||||
});
|
||||
|
||||
it("config change invalidates cache", () => {
|
||||
const before = classifyTier("openai", "gpt-4o");
|
||||
assert.equal(before.tier, PROVIDER_TIER.PREMIUM);
|
||||
expect(before.tier).toBe(PROVIDER_TIER.PREMIUM);
|
||||
setTierConfig({ providerOverrides: [{ provider: "openai", tier: "free" }] });
|
||||
const after = classifyTier("openai", "gpt-4o");
|
||||
assert.equal(after.tier, PROVIDER_TIER.FREE);
|
||||
expect(after.tier).toBe(PROVIDER_TIER.FREE);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -157,15 +156,15 @@ describe("TierResolver", () => {
|
||||
const t0 = performance.now();
|
||||
classifyTier("openai", "gpt-4o");
|
||||
const elapsed = performance.now() - t0;
|
||||
assert.ok(elapsed < 0.1, "cache hit should be <0.1ms");
|
||||
expect(elapsed, "cache hit should be <0.1ms").toBeLessThan(0.1);
|
||||
});
|
||||
|
||||
it("clearTierCache() forces re-classification", () => {
|
||||
const first = classifyTier("openai", "gpt-4o");
|
||||
clearTierCache();
|
||||
const second = classifyTier("openai", "gpt-4o");
|
||||
assert.equal(first.tier, second.tier);
|
||||
assert.ok(second.costPer1MInput > 0);
|
||||
expect(first.tier).toBe(second.tier);
|
||||
expect(second.costPer1MInput).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -185,11 +184,11 @@ describe("TierResolver", () => {
|
||||
{ provider: "unknown", model: "unknown-model" },
|
||||
];
|
||||
const results = classifyTiers(targets);
|
||||
assert.equal(results.length, 9);
|
||||
assert.equal(results[0].tier, PROVIDER_TIER.FREE); // kiro
|
||||
assert.equal(results[1].tier, PROVIDER_TIER.PREMIUM); // openai gpt-4o ($2.50/M)
|
||||
assert.equal(results[2].tier, PROVIDER_TIER.CHEAP); // deepseek
|
||||
assert.equal(results[8].tier, PROVIDER_TIER.PREMIUM); // unknown
|
||||
expect(results.length).toBe(9);
|
||||
expect(results[0].tier).toBe(PROVIDER_TIER.FREE); // kiro
|
||||
expect(results[1].tier).toBe(PROVIDER_TIER.PREMIUM); // openai gpt-4o ($2.50/M)
|
||||
expect(results[2].tier).toBe(PROVIDER_TIER.CHEAP); // deepseek
|
||||
expect(results[8].tier).toBe(PROVIDER_TIER.PREMIUM); // unknown
|
||||
});
|
||||
|
||||
it("uses cache for repeated models", () => {
|
||||
@@ -198,7 +197,7 @@ describe("TierResolver", () => {
|
||||
{ provider: "openai", model: "gpt-4o" },
|
||||
]);
|
||||
// If cache works, second call should be instant; test passes if no error
|
||||
assert.ok(true);
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -208,8 +207,8 @@ describe("TierResolver", () => {
|
||||
classifyTier("kiro", "claude-sonnet-4.5");
|
||||
classifyTier("deepseek", "deepseek-chat");
|
||||
const stats = getTierStats();
|
||||
assert.ok(stats[PROVIDER_TIER.FREE] >= 1);
|
||||
assert.ok(stats[PROVIDER_TIER.CHEAP] >= 1);
|
||||
expect(stats[PROVIDER_TIER.FREE]).toBeGreaterThanOrEqual(1);
|
||||
expect(stats[PROVIDER_TIER.CHEAP]).toBeGreaterThanOrEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -227,58 +226,64 @@ describe("TierResolver", () => {
|
||||
"cerebras",
|
||||
"groq",
|
||||
]) {
|
||||
assert.ok(LEGACY_FREE_PROVIDERS.includes(id), `expected ${id} in LEGACY_FREE_PROVIDERS`);
|
||||
expect(LEGACY_FREE_PROVIDERS.includes(id), `expected ${id} in LEGACY_FREE_PROVIDERS`).toBe(
|
||||
true
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("deriveNoAuthFreeProviders includes all chat-tier noAuth providers", () => {
|
||||
const derived = deriveNoAuthFreeProviders();
|
||||
// opencode + mimocode are the ones the bug report called out
|
||||
assert.ok(derived.includes("opencode"), "opencode should be in derived noAuth-free list");
|
||||
assert.ok(derived.includes("mimocode"), "mimocode should be in derived noAuth-free list");
|
||||
assert.ok(derived.includes("duckduckgo-web"));
|
||||
expect(derived.includes("opencode"), "opencode should be in derived noAuth-free list").toBe(
|
||||
true
|
||||
);
|
||||
expect(derived.includes("mimocode"), "mimocode should be in derived noAuth-free list").toBe(
|
||||
true
|
||||
);
|
||||
expect(derived.includes("duckduckgo-web")).toBe(true);
|
||||
});
|
||||
|
||||
it("deriveNoAuthFreeProviders excludes non-LLM noAuth providers", () => {
|
||||
const derived = deriveNoAuthFreeProviders();
|
||||
assert.ok(
|
||||
!derived.includes("veoaifree-web"),
|
||||
expect(
|
||||
derived.includes("veoaifree-web"),
|
||||
"veoaifree-web (serviceKinds: video) must not be classified as chat-free"
|
||||
);
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("DEFAULT_TIER_CONFIG.freeProviders contains the union of legacy + noAuth-derived", () => {
|
||||
const expected = new Set([...LEGACY_FREE_PROVIDERS, ...deriveNoAuthFreeProviders()]);
|
||||
const actual = new Set(DEFAULT_TIER_CONFIG.freeProviders);
|
||||
assert.deepEqual(actual, expected, "freeProviders must be the union, deduplicated");
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it("classifyTier classifies opencode/big-pickle as free via noAuth derivation", () => {
|
||||
// No provider override, no cost-based match (big-pickle has no KNOWN_MODEL_PRICING row).
|
||||
// The fix is that 'opencode' is now in freeProviders.
|
||||
const result = classifyTier("opencode", "big-pickle");
|
||||
assert.equal(result.tier, PROVIDER_TIER.FREE);
|
||||
assert.equal(result.hasFreeTier, true);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.FREE);
|
||||
expect(result.hasFreeTier).toBe(true);
|
||||
});
|
||||
|
||||
it("classifyTier classifies mimocode/mimo-auto as free via noAuth derivation", () => {
|
||||
const result = classifyTier("mimocode", "mimo-auto");
|
||||
assert.equal(result.tier, PROVIDER_TIER.FREE);
|
||||
assert.equal(result.hasFreeTier, true);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.FREE);
|
||||
expect(result.hasFreeTier).toBe(true);
|
||||
});
|
||||
|
||||
it("classifyTier still returns cheap for paid glm-5.1 (no regression)", () => {
|
||||
// glm-5.1 is not in freeProviders, costs $0.50/M → cheap tier.
|
||||
// Make sure the new noAuth derivation didn't accidentally pull it into free.
|
||||
const result = classifyTier("opencode-go", "glm-5.1");
|
||||
assert.equal(result.tier, PROVIDER_TIER.CHEAP);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.CHEAP);
|
||||
});
|
||||
|
||||
it("userConfig.freeProviders is merged on top of the noAuth-derived list", () => {
|
||||
// Re-merge with a new free provider (e.g. local-llama) and confirm it's added.
|
||||
setTierConfig({ freeProviders: ["local-llama"] });
|
||||
const result = classifyTier("local-llama", "anything");
|
||||
assert.equal(result.tier, PROVIDER_TIER.FREE);
|
||||
expect(result.tier).toBe(PROVIDER_TIER.FREE);
|
||||
clearTierCache();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { describe, it } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
|
||||
// Mock the DB so recommendStrategyOverride sees adaptiveVolumeRouting = true.
|
||||
// Without this the real getSettings() throws (no SQLite in test env), the
|
||||
// catch block fires, and the function returns noOverride before any rule runs.
|
||||
vi.mock("@/lib/localDb", () => ({
|
||||
getSettings: vi.fn().mockResolvedValue({ adaptiveVolumeRouting: true }),
|
||||
}));
|
||||
|
||||
import { detectVolumeSignals, recommendStrategyOverride } from "../volumeDetector";
|
||||
|
||||
describe("volumeDetector", async () => {
|
||||
@@ -9,11 +16,11 @@ describe("volumeDetector", async () => {
|
||||
messages: [{ role: "user", content: "Hello" }],
|
||||
};
|
||||
const signals = detectVolumeSignals(body);
|
||||
assert.equal(signals.batchSize, 1);
|
||||
assert.ok(signals.estimatedTokens < 100);
|
||||
assert.equal(signals.toolCount, 0);
|
||||
assert.equal(signals.hasBrowser, false);
|
||||
assert.equal(signals.complexity, "trivial");
|
||||
expect(signals.batchSize).toBe(1);
|
||||
expect(signals.estimatedTokens).toBeLessThan(100);
|
||||
expect(signals.toolCount).toBe(0);
|
||||
expect(signals.hasBrowser).toBe(false);
|
||||
expect(signals.complexity).toBe("trivial");
|
||||
});
|
||||
|
||||
it("detects tool-heavy request as high complexity", async () => {
|
||||
@@ -27,8 +34,8 @@ describe("volumeDetector", async () => {
|
||||
],
|
||||
};
|
||||
const signals = detectVolumeSignals(body);
|
||||
assert.equal(signals.toolCount, 4);
|
||||
assert.equal(signals.complexity, "critical");
|
||||
expect(signals.toolCount).toBe(4);
|
||||
expect(signals.complexity).toBe("critical");
|
||||
});
|
||||
|
||||
it("detects browser keywords", async () => {
|
||||
@@ -36,7 +43,7 @@ describe("volumeDetector", async () => {
|
||||
messages: [{ role: "user", content: "Navigate to the page and take a screenshot" }],
|
||||
};
|
||||
const signals = detectVolumeSignals(body);
|
||||
assert.equal(signals.hasBrowser, true);
|
||||
expect(signals.hasBrowser).toBe(true);
|
||||
});
|
||||
|
||||
it("detects batch from multi-part content", async () => {
|
||||
@@ -48,7 +55,7 @@ describe("volumeDetector", async () => {
|
||||
messages: [{ role: "user", content: parts }],
|
||||
};
|
||||
const signals = detectVolumeSignals(body);
|
||||
assert.equal(signals.batchSize, 20);
|
||||
expect(signals.batchSize).toBe(20);
|
||||
});
|
||||
|
||||
it("detects security keywords as high complexity", async () => {
|
||||
@@ -56,10 +63,10 @@ describe("volumeDetector", async () => {
|
||||
messages: [{ role: "user", content: "Refactor the authentication module for production" }],
|
||||
};
|
||||
const signals = detectVolumeSignals(body);
|
||||
assert.ok(
|
||||
expect(
|
||||
signals.complexity === "critical" || signals.complexity === "high",
|
||||
`expected critical or high, got ${signals.complexity}`
|
||||
);
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -67,9 +74,9 @@ describe("volumeDetector", async () => {
|
||||
it("recommends round-robin for large batches", async () => {
|
||||
const signals = detectVolumeSignals({ input: Array(60).fill("item") });
|
||||
const override = await recommendStrategyOverride(signals, "priority");
|
||||
assert.equal(override.shouldOverride, true);
|
||||
assert.equal(override.strategy, "round-robin");
|
||||
assert.equal(override.preferEconomy, true);
|
||||
expect(override.shouldOverride).toBe(true);
|
||||
expect(override.strategy).toBe("round-robin");
|
||||
expect(override.preferEconomy).toBe(true);
|
||||
});
|
||||
|
||||
it("recommends premium-first for browser tasks", async () => {
|
||||
@@ -82,9 +89,9 @@ describe("volumeDetector", async () => {
|
||||
complexity: "high" as const,
|
||||
};
|
||||
const override = await recommendStrategyOverride(signals, "round-robin");
|
||||
assert.equal(override.shouldOverride, true);
|
||||
assert.equal(override.strategy, "priority");
|
||||
assert.equal(override.forcePremium, true);
|
||||
expect(override.shouldOverride).toBe(true);
|
||||
expect(override.strategy).toBe("priority");
|
||||
expect(override.forcePremium).toBe(true);
|
||||
});
|
||||
|
||||
it("flags economy for tiny requests without changing strategy", async () => {
|
||||
@@ -97,8 +104,8 @@ describe("volumeDetector", async () => {
|
||||
complexity: "trivial" as const,
|
||||
};
|
||||
const override = await recommendStrategyOverride(signals, "priority");
|
||||
assert.equal(override.shouldOverride, false);
|
||||
assert.equal(override.preferEconomy, true);
|
||||
expect(override.shouldOverride).toBe(false);
|
||||
expect(override.preferEconomy).toBe(true);
|
||||
});
|
||||
|
||||
it("no override for normal medium requests", async () => {
|
||||
@@ -111,8 +118,8 @@ describe("volumeDetector", async () => {
|
||||
complexity: "low" as const,
|
||||
};
|
||||
const override = await recommendStrategyOverride(signals, "priority");
|
||||
assert.equal(override.shouldOverride, false);
|
||||
assert.equal(override.preferEconomy, false);
|
||||
expect(override.shouldOverride).toBe(false);
|
||||
expect(override.preferEconomy).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user