-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpredicate.ts
More file actions
101 lines (85 loc) · 3.57 KB
/
Copy pathpredicate.ts
File metadata and controls
101 lines (85 loc) · 3.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/**
* Pure decision logic for whether omp's failed auto-retry should trigger an
* automatic resume. Reactive-only: the only trustworthy signal is a freshly
* fetched usage report confirming a real block, never a proactive percentage
* poll. See docs/superpowers/specs/2026-07-16-omp-auto-resume-design.md.
*/
export interface UsageLimitLike {
windowId: string;
usedFraction: number | undefined;
resetsAt: number | undefined;
tiered: boolean;
}
export interface UsageReportLike {
provider: string;
limits: UsageLimitLike[];
}
export const EXHAUSTED_MIN_FRACTION = 0.999;
export const MAX_PLAUSIBLE_REMAINING_MS = 7 * 24 * 3_600_000 + 60 * 60_000;
export type BlockDecisionReason =
| "wrong-provider"
| "not-exhausted"
| "no-reset-time"
| "reset-in-past"
| "reset-implausible"
| "already-handled";
export type BlockDecision =
| { act: false; reason: BlockDecisionReason }
| { act: true; windowId: string; resetsAt: number; episodeKey: string };
export interface EvaluateBlockInput {
nowMs: number;
activeProvider: string | undefined;
reports: UsageReportLike[] | undefined;
handledEpisodes: ReadonlySet<string>;
}
interface BindingWindow {
windowId: string;
resetsAt: number | undefined;
tiered: boolean;
}
function selectBindingWindow(reports: UsageReportLike[]): BindingWindow | undefined {
const byWindow = new Map<string, BindingWindow>();
for (const report of reports) {
if (report.provider !== "anthropic") continue;
for (const limit of report.limits) {
if (limit.windowId !== "5h" && limit.windowId !== "7d") continue;
if (typeof limit.usedFraction !== "number" || limit.usedFraction < EXHAUSTED_MIN_FRACTION) continue;
const existing = byWindow.get(limit.windowId);
// Untiered wins over tiered, mirroring the built-in `usage` segment's tie-break.
if (!existing || (existing.tiered && !limit.tiered)) {
byWindow.set(limit.windowId, {
windowId: limit.windowId,
resetsAt: limit.resetsAt,
tiered: limit.tiered,
});
}
}
}
if (byWindow.size === 0) return undefined;
// If ANY exhausted window has an unresolvable reset time, refuse to bind to
// some other exhausted window that does have one — that other window might
// still be blocking after this one's reset passes. Precision over recall:
// better to skip an auto-resume than fire one prematurely.
for (const w of byWindow.values()) {
if (typeof w.resetsAt !== "number") return { ...w, resetsAt: undefined };
}
// Both 5h and 7d can be exhausted at once. The binding constraint is
// whichever resets LATEST — resuming before that would just re-block.
let binding: BindingWindow | undefined;
for (const w of byWindow.values()) {
if (!binding || (w.resetsAt as number) > (binding.resetsAt as number)) binding = w;
}
return binding;
}
export function evaluateBlock(input: EvaluateBlockInput): BlockDecision {
if (input.activeProvider !== "anthropic") return { act: false, reason: "wrong-provider" };
const binding = selectBindingWindow(input.reports ?? []);
if (!binding) return { act: false, reason: "not-exhausted" };
if (typeof binding.resetsAt !== "number") return { act: false, reason: "no-reset-time" };
const remainingMs = binding.resetsAt - input.nowMs;
if (remainingMs <= 0) return { act: false, reason: "reset-in-past" };
if (remainingMs > MAX_PLAUSIBLE_REMAINING_MS) return { act: false, reason: "reset-implausible" };
const episodeKey = `${binding.windowId}:${binding.resetsAt}`;
if (input.handledEpisodes.has(episodeKey)) return { act: false, reason: "already-handled" };
return { act: true, windowId: binding.windowId, resetsAt: binding.resetsAt, episodeKey };
}