@kill-switch/agent-guard 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/estimate.d.ts +27 -21
- package/dist/estimate.js +30 -30
- package/package.json +1 -1
package/dist/estimate.d.ts
CHANGED
|
@@ -4,40 +4,46 @@
|
|
|
4
4
|
* Ground truth for plan limits lives in the `anthropic-ratelimit-unified-*`
|
|
5
5
|
* response headers, which only the proxy sees. A user running just the Claude
|
|
6
6
|
* Code hook (the common, zero-config setup) never sees those headers — so when
|
|
7
|
-
* they've told us their plan tier, we *estimate* where they stand
|
|
8
|
-
* tokens the ledger recorded inside each rolling window and dividing by a
|
|
9
|
-
* per-tier token budget.
|
|
7
|
+
* they've told us their plan tier, we *estimate* where they stand.
|
|
10
8
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
9
|
+
* We estimate from the ledger's **cost** (`costUSD`), not its token counts. That
|
|
10
|
+
* matters: a coding agent's volume is dominated by cache reads/writes, and the
|
|
11
|
+
* ledger only stores non-cache input/output token counts — so a token-based
|
|
12
|
+
* estimate undercounts real throughput (and thus rate-limit consumption) by a
|
|
13
|
+
* large factor. `costUSD` is priced from the *full* usage including cache, so it
|
|
14
|
+
* tracks actual consumption far better. We compare it against a rough per-tier
|
|
15
|
+
* **API-equivalent** dollar ceiling for each window.
|
|
17
16
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* This is still deliberately approximate and always labelled as such:
|
|
18
|
+
* - Anthropic meters opaque "prompts" / "active hours", and the dollar ceilings
|
|
19
|
+
* below are rough API-equivalent calibrations, not contractual.
|
|
20
|
+
* - The ledger stores a session's cumulative cost against a single `lastAt`,
|
|
21
|
+
* not a time series, so a long session is counted wholesale into whichever
|
|
22
|
+
* window its last activity falls in.
|
|
23
|
+
*
|
|
24
|
+
* It exists to give hook-only users *a* directional signal and to nudge them
|
|
25
|
+
* toward `ks guard proxy` for exact numbers — never to block (subscription mode
|
|
26
|
+
* is alert-only).
|
|
21
27
|
*/
|
|
22
28
|
import { type LimitSnapshot } from "./limits.js";
|
|
23
29
|
import type { Ledger } from "./ledger.js";
|
|
24
30
|
export type PlanTier = "pro" | "max5" | "max20";
|
|
25
31
|
/**
|
|
26
|
-
* Rough per-tier
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
32
|
+
* Rough per-tier **API-equivalent USD** ceilings per window — what the plan's
|
|
33
|
+
* rate limit lets you consume before lock-out, expressed in the same list-price
|
|
34
|
+
* dollars the ledger meters. Scaled by plan: Pro is the baseline, Max 5x/20x lift
|
|
35
|
+
* the burst (5h) roughly with the multiplier and the weekly cap more
|
|
36
|
+
* conservatively. These are estimates; the proxy's real headers override them.
|
|
30
37
|
*/
|
|
31
38
|
export interface TierBudget {
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
fiveHourUSD: number;
|
|
40
|
+
weeklyUSD: number;
|
|
34
41
|
}
|
|
35
42
|
export declare const TIER_BUDGETS: Record<PlanTier, TierBudget>;
|
|
36
43
|
/**
|
|
37
44
|
* Build an estimated {@link LimitSnapshot} from the ledger for a known tier.
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* `now` as a conservative upper bound on time remaining).
|
|
45
|
+
* `resetAt` is null (the true rolling reset is unknowable without a per-event
|
|
46
|
+
* time series), so pacing reports utilization only — no fabricated reset/lockout.
|
|
41
47
|
*/
|
|
42
48
|
export declare function estimateSnapshot(ledger: Ledger, tier: PlanTier, now: number, budgets?: Record<PlanTier, TierBudget>): LimitSnapshot;
|
|
43
49
|
/** True when a snapshot came from {@link estimateSnapshot} rather than real headers. */
|
package/dist/estimate.js
CHANGED
|
@@ -4,57 +4,57 @@
|
|
|
4
4
|
* Ground truth for plan limits lives in the `anthropic-ratelimit-unified-*`
|
|
5
5
|
* response headers, which only the proxy sees. A user running just the Claude
|
|
6
6
|
* Code hook (the common, zero-config setup) never sees those headers — so when
|
|
7
|
-
* they've told us their plan tier, we *estimate* where they stand
|
|
8
|
-
* tokens the ledger recorded inside each rolling window and dividing by a
|
|
9
|
-
* per-tier token budget.
|
|
7
|
+
* they've told us their plan tier, we *estimate* where they stand.
|
|
10
8
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
9
|
+
* We estimate from the ledger's **cost** (`costUSD`), not its token counts. That
|
|
10
|
+
* matters: a coding agent's volume is dominated by cache reads/writes, and the
|
|
11
|
+
* ledger only stores non-cache input/output token counts — so a token-based
|
|
12
|
+
* estimate undercounts real throughput (and thus rate-limit consumption) by a
|
|
13
|
+
* large factor. `costUSD` is priced from the *full* usage including cache, so it
|
|
14
|
+
* tracks actual consumption far better. We compare it against a rough per-tier
|
|
15
|
+
* **API-equivalent** dollar ceiling for each window.
|
|
17
16
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* This is still deliberately approximate and always labelled as such:
|
|
18
|
+
* - Anthropic meters opaque "prompts" / "active hours", and the dollar ceilings
|
|
19
|
+
* below are rough API-equivalent calibrations, not contractual.
|
|
20
|
+
* - The ledger stores a session's cumulative cost against a single `lastAt`,
|
|
21
|
+
* not a time series, so a long session is counted wholesale into whichever
|
|
22
|
+
* window its last activity falls in.
|
|
23
|
+
*
|
|
24
|
+
* It exists to give hook-only users *a* directional signal and to nudge them
|
|
25
|
+
* toward `ks guard proxy` for exact numbers — never to block (subscription mode
|
|
26
|
+
* is alert-only).
|
|
21
27
|
*/
|
|
22
28
|
import { WINDOW_MS } from "./limits.js";
|
|
23
29
|
export const TIER_BUDGETS = {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
max20: { fiveHourTokens: 160_000_000, weeklyTokens: 1_400_000_000 },
|
|
30
|
+
pro: { fiveHourUSD: 16, weeklyUSD: 100 },
|
|
31
|
+
max5: { fiveHourUSD: 80, weeklyUSD: 500 },
|
|
32
|
+
max20: { fiveHourUSD: 300, weeklyUSD: 2000 },
|
|
28
33
|
};
|
|
29
34
|
const FIVE_HOUR_MS = WINDOW_MS["5h"];
|
|
30
35
|
const WEEK_MS = WINDOW_MS.weekly;
|
|
31
|
-
/** Sum
|
|
32
|
-
function
|
|
36
|
+
/** Sum metered cost across sessions whose last activity is within `windowMs`. */
|
|
37
|
+
function costInWindow(ledger, now, windowMs) {
|
|
33
38
|
let total = 0;
|
|
34
39
|
for (const s of Object.values(ledger.sessions)) {
|
|
35
40
|
if (now - s.lastAt < windowMs)
|
|
36
|
-
total +=
|
|
41
|
+
total += s.costUSD || 0;
|
|
37
42
|
}
|
|
38
43
|
return total;
|
|
39
44
|
}
|
|
40
45
|
/**
|
|
41
46
|
* Build an estimated {@link LimitSnapshot} from the ledger for a known tier.
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* `now` as a conservative upper bound on time remaining).
|
|
47
|
+
* `resetAt` is null (the true rolling reset is unknowable without a per-event
|
|
48
|
+
* time series), so pacing reports utilization only — no fabricated reset/lockout.
|
|
45
49
|
*/
|
|
46
50
|
export function estimateSnapshot(ledger, tier, now, budgets = TIER_BUDGETS) {
|
|
47
51
|
const b = budgets[tier];
|
|
48
|
-
const
|
|
49
|
-
const
|
|
52
|
+
const fiveUSD = costInWindow(ledger, now, FIVE_HOUR_MS);
|
|
53
|
+
const weekUSD = costInWindow(ledger, now, WEEK_MS);
|
|
50
54
|
const clamp = (n) => Math.max(0, Math.min(1, n));
|
|
51
|
-
// resetAt is null, not fabricated: we have no per-event time series, so the
|
|
52
|
-
// true rolling reset is unknowable. A null reset means pacing reports
|
|
53
|
-
// utilization only (no burn-rate, no lockout projection, no bogus reset time) —
|
|
54
|
-
// the honest behaviour for an estimate.
|
|
55
55
|
return {
|
|
56
|
-
fiveHour: { utilization: clamp(
|
|
57
|
-
weekly: { utilization: clamp(
|
|
56
|
+
fiveHour: { utilization: clamp(fiveUSD / b.fiveHourUSD), resetAt: null, status: "estimated" },
|
|
57
|
+
weekly: { utilization: clamp(weekUSD / b.weeklyUSD), resetAt: null, status: "estimated" },
|
|
58
58
|
status: "estimated",
|
|
59
59
|
observedAt: now,
|
|
60
60
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kill-switch/agent-guard",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Kill Switch for coding agents — stop runaway Claude Code / Cursor / Aider sessions from racking up an LLM bill. Native hook + token-metering proxy with per-session and daily-rolling budgets.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|