78 lines
5.5 KiB
TypeScript
78 lines
5.5 KiB
TypeScript
import { defaultCodexTempUnschedulablePolicy, renderSub2ApiTempUnschedulableCredentials } from "./src/platform-infra-sub2api-codex";
|
|
|
|
function assertCondition(condition: unknown, message: string, detail: unknown = {}): void {
|
|
if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`);
|
|
}
|
|
|
|
const policy = defaultCodexTempUnschedulablePolicy();
|
|
const credentials = renderSub2ApiTempUnschedulableCredentials(policy) as {
|
|
temp_unschedulable_enabled?: boolean;
|
|
temp_unschedulable_rules?: Array<{
|
|
error_code?: number;
|
|
keywords?: string[];
|
|
duration_minutes?: number;
|
|
description?: string;
|
|
}>;
|
|
pool_mode?: unknown;
|
|
};
|
|
|
|
const rules = credentials.temp_unschedulable_rules ?? [];
|
|
|
|
assertCondition(credentials.temp_unschedulable_enabled === true, "default policy must enable Sub2API temporary unschedulable mode", credentials);
|
|
assertCondition(Array.isArray(credentials.temp_unschedulable_rules), "Sub2API rules must be rendered as an array", credentials);
|
|
assertCondition(rules.length === policy.rules.length, "rendered rule count must match the UniDesk policy", { policy, credentials });
|
|
assertCondition(rules.every((rule, index) => rule.error_code === policy.rules[index]?.statusCode), "rules must map statusCode to Sub2API error_code", { policy, credentials });
|
|
assertCondition(rules.every((rule, index) => rule.duration_minutes === policy.rules[index]?.durationMinutes), "rules must map durationMinutes to Sub2API duration_minutes", { policy, credentials });
|
|
assertCondition(rules.every((rule, index) => JSON.stringify(rule.keywords ?? []) === JSON.stringify(policy.rules[index]?.keywords ?? [])), "rules must preserve policy keywords", { policy, credentials });
|
|
assertCondition(rules.every((rule, index) => rule.description === policy.rules[index]?.description), "rules must preserve policy descriptions", { policy, credentials });
|
|
assertCondition(!("pool_mode" in credentials), "pool_mode must not be enabled because it retries the same account instead of cooling it down", credentials);
|
|
assertCondition(!("api_key" in credentials) && !("base_url" in credentials), "temporary-unschedulable rendering must not include secrets or endpoints", credentials);
|
|
const accountState403Rule = rules.find((rule) => rule.error_code === 403);
|
|
const quota429Rule = rules.find((rule) => rule.error_code === 429);
|
|
const gateway502Rule = rules.find((rule) => rule.error_code === 502);
|
|
const serviceUnavailable503Rule = rules.find((rule) => rule.error_code === 503);
|
|
const gatewayTimeout504Rule = rules.find((rule) => rule.error_code === 504);
|
|
const largeContext413Rule = rules.find((rule) => rule.error_code === 413);
|
|
const cloudflare524Rule = rules.find((rule) => rule.error_code === 524);
|
|
for (const keyword of ["weekly limit", "less than 10% of your weekly limit left", "run /status for a breakdown"]) {
|
|
assertCondition(accountState403Rule?.keywords?.includes(keyword), "403 rendered rule must preserve Codex weekly-limit account-state keyword", { keyword, accountState403Rule });
|
|
assertCondition(quota429Rule?.keywords?.includes(keyword), "429 rendered rule must preserve Codex weekly-limit quota keyword", { keyword, quota429Rule });
|
|
}
|
|
for (const keyword of ["model_not_found", "no available channel for model"]) {
|
|
assertCondition(serviceUnavailable503Rule?.keywords?.includes(keyword), "503 rendered rule must catch upstream model-routing failures", { keyword, serviceUnavailable503Rule });
|
|
}
|
|
for (const keyword of ["openai_error", "context length", "maximum context"]) {
|
|
assertCondition(largeContext413Rule?.keywords?.includes(keyword), "413 rendered rule must catch large-context upstream failures", { keyword, largeContext413Rule });
|
|
}
|
|
for (const keyword of ["unknown error", "upstream request failed", "context canceled"]) {
|
|
assertCondition(gateway502Rule?.keywords?.includes(keyword), "502 rendered rule must catch compact gateway wrappers", { keyword, gateway502Rule });
|
|
}
|
|
for (const keyword of ["gateway timeout", "unknown error", "context deadline exceeded"]) {
|
|
assertCondition(gatewayTimeout504Rule?.keywords?.includes(keyword), "504 rendered rule must preserve gateway-timeout cooldown keyword", { keyword, gatewayTimeout504Rule });
|
|
}
|
|
for (const keyword of ["timeout", "a timeout occurred", "cloudflare", "unknown error", "upstream request failed", "context canceled"]) {
|
|
assertCondition(cloudflare524Rule?.keywords?.includes(keyword), "524 rendered rule must catch Cloudflare timeout wrappers", { keyword, cloudflare524Rule });
|
|
}
|
|
|
|
const disabled = renderSub2ApiTempUnschedulableCredentials({ enabled: false, rules: policy.rules }) as {
|
|
temp_unschedulable_enabled?: boolean;
|
|
temp_unschedulable_rules?: unknown[];
|
|
};
|
|
|
|
assertCondition(disabled.temp_unschedulable_enabled === false, "disabled policy must explicitly disable Sub2API temporary unschedulable mode", disabled);
|
|
assertCondition(Array.isArray(disabled.temp_unschedulable_rules) && disabled.temp_unschedulable_rules.length === 0, "disabled policy must not leave stale rules active", disabled);
|
|
|
|
console.log(JSON.stringify({
|
|
ok: true,
|
|
checks: [
|
|
"temporary unschedulable policy renders to Sub2API credential field names",
|
|
"temporary unschedulable rendering follows the input policy without hard-coded policy gates",
|
|
"Codex weekly-limit prompt keywords render into 403 and 429 cooldown rules",
|
|
"large-context upstream failures render into the 413 cooldown rule",
|
|
"upstream model-routing failures render into the 503 cooldown rule",
|
|
"gateway timeout wrappers render into the 504 cooldown rule",
|
|
"Cloudflare timeout wrappers render into the 524 cooldown rule",
|
|
"disabled policies clear runtime rules",
|
|
],
|
|
}));
|