fix: update cooldownReason on active-window failures + clear model scope for non-rate-limit
This commit is contained in:
parent
d88de88962
commit
8ea6f5206c
@ -796,4 +796,51 @@ describe("markAuthProfileFailure — per-model cooldown metadata", () => {
|
||||
const stats = store.usageStats?.["github-copilot:github"];
|
||||
expect(stats?.cooldownModel).toBe("claude-sonnet-4.6");
|
||||
});
|
||||
|
||||
it("updates cooldownReason when auth failure occurs during active rate_limit window", async () => {
|
||||
const now = 1_000_000;
|
||||
const store = makeStoreWithCopilot({
|
||||
"github-copilot:github": {
|
||||
cooldownUntil: now + 30_000,
|
||||
cooldownReason: "rate_limit",
|
||||
cooldownModel: "claude-sonnet-4.6",
|
||||
errorCount: 1,
|
||||
lastFailureAt: now - 1000,
|
||||
},
|
||||
});
|
||||
await markAuthProfileFailure({
|
||||
store,
|
||||
profileId: "github-copilot:github",
|
||||
reason: "auth",
|
||||
modelId: "claude-opus-4.6",
|
||||
});
|
||||
const stats = store.usageStats?.["github-copilot:github"];
|
||||
// Reason should update to the new failure type, not stay as rate_limit
|
||||
expect(stats?.cooldownReason).toBe("auth");
|
||||
// Model scope should be cleared — auth failures are profile-wide
|
||||
expect(stats?.cooldownModel).toBeUndefined();
|
||||
});
|
||||
|
||||
it("clears cooldownModel when non-rate_limit failure hits same model during active window", async () => {
|
||||
const now = 1_000_000;
|
||||
const store = makeStoreWithCopilot({
|
||||
"github-copilot:github": {
|
||||
cooldownUntil: now + 30_000,
|
||||
cooldownReason: "rate_limit",
|
||||
cooldownModel: "claude-sonnet-4.6",
|
||||
errorCount: 1,
|
||||
lastFailureAt: now - 1000,
|
||||
},
|
||||
});
|
||||
await markAuthProfileFailure({
|
||||
store,
|
||||
profileId: "github-copilot:github",
|
||||
reason: "auth",
|
||||
modelId: "claude-sonnet-4.6",
|
||||
});
|
||||
const stats = store.usageStats?.["github-copilot:github"];
|
||||
// Even same-model auth failure should clear model scope (auth is profile-wide)
|
||||
expect(stats?.cooldownReason).toBe("auth");
|
||||
expect(stats?.cooldownModel).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@ -479,7 +479,11 @@ function computeNextProfileUsageStats(params: {
|
||||
typeof params.existing.cooldownUntil === "number" &&
|
||||
params.existing.cooldownUntil > params.now;
|
||||
if (existingCooldownActive) {
|
||||
updatedStats.cooldownReason = params.existing.cooldownReason;
|
||||
// Always use the latest failure reason so that downstream consumers
|
||||
// (e.g. isProfileInCooldown model-bypass) see the most recent signal.
|
||||
// A non-rate_limit failure (auth, billing, …) is profile-wide, so
|
||||
// upgrading from rate_limit → auth correctly blocks all models.
|
||||
updatedStats.cooldownReason = params.reason;
|
||||
// If a different model fails during an active window, widen the scope
|
||||
// to all models (undefined) so neither model bypasses the cooldown.
|
||||
if (
|
||||
@ -488,6 +492,10 @@ function computeNextProfileUsageStats(params: {
|
||||
params.existing.cooldownModel !== params.modelId
|
||||
) {
|
||||
updatedStats.cooldownModel = undefined;
|
||||
} else if (params.reason !== "rate_limit") {
|
||||
// Non-rate-limit failures are profile-wide — clear model scope even
|
||||
// when the same model fails, so that no model can bypass.
|
||||
updatedStats.cooldownModel = undefined;
|
||||
} else {
|
||||
updatedStats.cooldownModel = params.existing.cooldownModel;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user