mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-11 21:53:43 +00:00
Agents: infer auth-profile unavailable failover reason
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
clearExpiredCooldowns,
|
||||
isProfileInCooldown,
|
||||
markAuthProfileFailure,
|
||||
resolveProfilesUnavailableReason,
|
||||
resolveProfileUnusableUntil,
|
||||
} from "./usage.js";
|
||||
|
||||
@@ -85,6 +86,101 @@ describe("isProfileInCooldown", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveProfilesUnavailableReason", () => {
|
||||
it("prefers active disabledReason when profiles are disabled", () => {
|
||||
const now = Date.now();
|
||||
const store = makeStore({
|
||||
"anthropic:default": {
|
||||
disabledUntil: now + 60_000,
|
||||
disabledReason: "billing",
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
resolveProfilesUnavailableReason({
|
||||
store,
|
||||
profileIds: ["anthropic:default"],
|
||||
now,
|
||||
}),
|
||||
).toBe("billing");
|
||||
});
|
||||
|
||||
it("uses recorded non-rate-limit failure counts for active cooldown windows", () => {
|
||||
const now = Date.now();
|
||||
const store = makeStore({
|
||||
"anthropic:default": {
|
||||
cooldownUntil: now + 60_000,
|
||||
failureCounts: { auth: 3, rate_limit: 1 },
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
resolveProfilesUnavailableReason({
|
||||
store,
|
||||
profileIds: ["anthropic:default"],
|
||||
now,
|
||||
}),
|
||||
).toBe("auth");
|
||||
});
|
||||
|
||||
it("falls back to rate_limit when active cooldown has no reason history", () => {
|
||||
const now = Date.now();
|
||||
const store = makeStore({
|
||||
"anthropic:default": {
|
||||
cooldownUntil: now + 60_000,
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
resolveProfilesUnavailableReason({
|
||||
store,
|
||||
profileIds: ["anthropic:default"],
|
||||
now,
|
||||
}),
|
||||
).toBe("rate_limit");
|
||||
});
|
||||
|
||||
it("ignores expired windows and returns null when no profile is actively unavailable", () => {
|
||||
const now = Date.now();
|
||||
const store = makeStore({
|
||||
"anthropic:default": {
|
||||
cooldownUntil: now - 1_000,
|
||||
failureCounts: { auth: 5 },
|
||||
},
|
||||
"anthropic:backup": {
|
||||
disabledUntil: now - 500,
|
||||
disabledReason: "billing",
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
resolveProfilesUnavailableReason({
|
||||
store,
|
||||
profileIds: ["anthropic:default", "anthropic:backup"],
|
||||
now,
|
||||
}),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("breaks ties by reason priority for equal active failure counts", () => {
|
||||
const now = Date.now();
|
||||
const store = makeStore({
|
||||
"anthropic:default": {
|
||||
cooldownUntil: now + 60_000,
|
||||
failureCounts: { timeout: 2, auth: 2 },
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
resolveProfilesUnavailableReason({
|
||||
store,
|
||||
profileIds: ["anthropic:default"],
|
||||
now,
|
||||
}),
|
||||
).toBe("auth");
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// clearExpiredCooldowns
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user