Files
2026-07-13 13:39:12 +08:00

77 lines
2.6 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
const {
classifyModelScope429,
getModelScopeRetryDelayMs,
isModelScopeProvider,
parseModelScopeRateLimitHeaders,
} = await import("../../open-sse/services/modelscopePolicy.ts");
const { normalizeHeaders } = await import("../../open-sse/utils/headers.ts");
test("ModelScope policy detects provider ids and ModelScope host markers", () => {
assert.equal(isModelScopeProvider("modelscope"), true);
assert.equal(
isModelScopeProvider("openai-compatible-custom", {
baseUrl: "https://api-inference.modelscope.cn/v1",
}),
true
);
assert.equal(isModelScopeProvider("openai", { baseUrl: "https://api.openai.com/v1" }), false);
});
test("ModelScope policy parses per-model and total rate-limit headers", () => {
const snapshot = parseModelScopeRateLimitHeaders({
"modelscope-ratelimit-model-requests-remaining": "0",
"modelscope-ratelimit-model-requests-limit": "10",
"modelscope-ratelimit-requests-remaining": "17",
"modelscope-ratelimit-requests-limit": "20",
});
assert.deepEqual(snapshot, {
modelRemaining: 0,
modelLimit: 10,
totalRemaining: 17,
totalLimit: 20,
});
});
test("ModelScope policy keeps temporary 429 headers retryable", () => {
const decision = classifyModelScope429(
"Throttling: current batch requests reached the limit",
{
"modelscope-ratelimit-model-requests-remaining": "0",
"modelscope-ratelimit-model-requests-limit": "10",
}
);
assert.equal(decision.kind, "rate_limited");
assert.equal(decision.retryable, true);
assert.equal(decision.snapshot.modelRemaining, 0);
});
test("ModelScope policy treats explicit free quota exhaustion as terminal", () => {
const decision = classifyModelScope429("Free allocated quota exceeded", {});
assert.equal(decision.kind, "quota_exhausted");
assert.equal(decision.retryable, false);
});
test("ModelScope retry delay respects Retry-After seconds before backoff fallback", () => {
assert.equal(getModelScopeRetryDelayMs({ "retry-after": "2.5" }, 0), 2500);
assert.equal(getModelScopeRetryDelayMs({}, 1), 6000);
});
test("ModelScope policy accepts headers normalized via normalizeHeaders (Node 24 undici interop)", () => {
// Simulate a Headers object from a different undici instance via the helper.
const upstreamHeaders = new Headers({
"modelscope-ratelimit-model-requests-remaining": "3",
"retry-after": "1.5",
});
const normalized = normalizeHeaders(upstreamHeaders);
const snapshot = parseModelScopeRateLimitHeaders(normalized);
assert.equal(snapshot.modelRemaining, 3);
assert.equal(getModelScopeRetryDelayMs(normalized, 0), 1500);
});