agent-shim 9.1.0 → 9.2.1

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/cli.cjs CHANGED
@@ -31107,6 +31107,18 @@ function parseDuration(value2) {
31107
31107
  }
31108
31108
  return Number(count) * multiplier;
31109
31109
  }
31110
+ function windowValues(prefix, windows) {
31111
+ const values = {};
31112
+ for (const name of ["fiveHour", "sevenDay", "extraUsage"]) {
31113
+ const facts = windows?.[name];
31114
+ if (facts !== void 0) {
31115
+ values[`${prefix}.${name}.remaining`] = facts.remaining;
31116
+ values[`${prefix}.${name}.utilization`] = facts.utilization;
31117
+ values[`${prefix}.${name}.hoursUntilReset`] = facts.hoursUntilReset;
31118
+ }
31119
+ }
31120
+ return values;
31121
+ }
31110
31122
  function resolversOf(context) {
31111
31123
  const pool = context.pool;
31112
31124
  const values = {
@@ -31115,8 +31127,7 @@ function resolversOf(context) {
31115
31127
  ...context.fact?.totalSizeBytes === void 0 ? {} : { "entry.totalSizeBytes": context.fact.totalSizeBytes },
31116
31128
  ...context.branch === void 0 ? {} : { "repo.branch": context.branch },
31117
31129
  "repo.detached": context.branchDetached ?? false,
31118
- ...pool?.fiveHour === void 0 ? {} : { "quota.fiveHour.remaining": pool.fiveHour.remaining, "quota.fiveHour.utilization": pool.fiveHour.utilization, "quota.fiveHour.hoursUntilReset": pool.fiveHour.hoursUntilReset },
31119
- ...pool?.sevenDay === void 0 ? {} : { "quota.sevenDay.remaining": pool.sevenDay.remaining, "quota.sevenDay.utilization": pool.sevenDay.utilization, "quota.sevenDay.hoursUntilReset": pool.sevenDay.hoursUntilReset },
31130
+ ...windowValues("quota", pool),
31120
31131
  ...pool?.burnPerHour === void 0 ? {} : { "quota.burnPerHour": pool.burnPerHour },
31121
31132
  ...pool?.resuming === void 0 ? {} : { "session.resuming": pool.resuming },
31122
31133
  ...pool?.lastPickHoursAgo === void 0 ? {} : { "session.lastPickHoursAgo": pool.lastPickHoursAgo },
@@ -31127,12 +31138,7 @@ function resolversOf(context) {
31127
31138
  ...context.request?.maxTokens === void 0 ? {} : { "request.maxTokens": context.request.maxTokens },
31128
31139
  ...context.request?.isCountTokens === void 0 ? {} : { "request.isCountTokens": context.request.isCountTokens },
31129
31140
  ...context.providerQuota === void 0 ? {} : Object.fromEntries(
31130
- Object.entries(context.providerQuota).flatMap(
31131
- ([name, windows]) => [
31132
- ...windows.fiveHour === void 0 ? [] : [["provider." + name + ".fiveHour.remaining", windows.fiveHour.remaining], ["provider." + name + ".fiveHour.utilization", windows.fiveHour.utilization], ["provider." + name + ".fiveHour.hoursUntilReset", windows.fiveHour.hoursUntilReset]],
31133
- ...windows.sevenDay === void 0 ? [] : [["provider." + name + ".sevenDay.remaining", windows.sevenDay.remaining], ["provider." + name + ".sevenDay.utilization", windows.sevenDay.utilization], ["provider." + name + ".sevenDay.hoursUntilReset", windows.sevenDay.hoursUntilReset]]
31134
- ]
31135
- )
31141
+ Object.entries(context.providerQuota).flatMap(([name, windows]) => Object.entries(windowValues("provider." + name, windows)))
31136
31142
  )
31137
31143
  };
31138
31144
  return {
@@ -32529,9 +32535,313 @@ var init_paths = __esm({
32529
32535
  }
32530
32536
  });
32531
32537
 
32538
+ // src/usage/schema.ts
32539
+ function isRateLimitHeader(name) {
32540
+ const lower = name.toLowerCase();
32541
+ return lower === "retry-after" || lower.startsWith("anthropic-ratelimit-") || lower.startsWith("x-ratelimit-") || lower.startsWith("ratelimit") || lower.startsWith("x-codex-");
32542
+ }
32543
+ var USAGE_SCHEMA_VERSION, VersionSchema, InstantSchema, TokenCountSchema, TokenUsageSchema, LIMIT_KINDS, LimitClassificationSchema, UsageRecordSchema, QuotaWindowSchema, UnifiedRateLimitSchema, RateLimitStateSchema, LimitEventSchema, ProviderQuotaWindowSchema, ProviderQuotaSchema, ProviderUsageStateSchema, AccountMetadataSchema, UsageSnapshotSchema;
32544
+ var init_schema2 = __esm({
32545
+ "src/usage/schema.ts"() {
32546
+ "use strict";
32547
+ init_zod();
32548
+ USAGE_SCHEMA_VERSION = 1;
32549
+ VersionSchema = external_exports.literal(USAGE_SCHEMA_VERSION);
32550
+ InstantSchema = external_exports.iso.datetime();
32551
+ TokenCountSchema = external_exports.number().int().nonnegative();
32552
+ TokenUsageSchema = external_exports.strictObject({
32553
+ inputTokens: TokenCountSchema.optional(),
32554
+ outputTokens: TokenCountSchema.optional(),
32555
+ cacheCreationInputTokens: TokenCountSchema.optional(),
32556
+ cacheReadInputTokens: TokenCountSchema.optional()
32557
+ });
32558
+ LIMIT_KINDS = ["rate-limited", "quota-exhausted"];
32559
+ LimitClassificationSchema = external_exports.strictObject({
32560
+ kind: external_exports.enum(LIMIT_KINDS),
32561
+ /** Seconds to wait before retrying, from the response's `retry-after`. */
32562
+ retryAfterSeconds: external_exports.number().nonnegative().optional(),
32563
+ /** When the limiting window resets, from the upstream's own reset header. */
32564
+ resetAt: InstantSchema.optional(),
32565
+ /** The window the upstream named as the binding one (`anthropic-ratelimit-unified-representative-claim`), such as `five_hour` or `seven_day`. */
32566
+ window: external_exports.string().optional(),
32567
+ /** The signals the classification rests on, each `<name>=<value>` from a response header or the error body's `type` or `code`. Never the error message. */
32568
+ evidence: external_exports.array(external_exports.string())
32569
+ });
32570
+ UsageRecordSchema = external_exports.strictObject({
32571
+ schemaVersion: VersionSchema,
32572
+ /** When the front door received the request. */
32573
+ at: InstantSchema,
32574
+ /** The launching identity, when the launch resolved one. */
32575
+ identity: external_exports.string().optional(),
32576
+ /** `anthropic` for an OAuth session's request to Claude Code's own API, otherwise the provider's name. */
32577
+ provider: external_exports.string(),
32578
+ /** The launch's session id, generated per launch. */
32579
+ sessionId: external_exports.string().optional(),
32580
+ /** The project the launch ran in (its git repository root), when the launch sent one: headroom launches do. */
32581
+ project: external_exports.string().optional(),
32582
+ /** The front-door route that served the request. */
32583
+ route: external_exports.string(),
32584
+ method: external_exports.string(),
32585
+ /** The API path as the upstream sees it (`/v1/messages`), without the provider prefix or a query string. */
32586
+ endpoint: external_exports.string(),
32587
+ /** The model the response named. */
32588
+ model: external_exports.string().optional(),
32589
+ status: external_exports.number().int(),
32590
+ /** Milliseconds from the request's arrival to its response head. */
32591
+ latencyMs: external_exports.number().int().nonnegative(),
32592
+ /** Milliseconds from the request's arrival to the end of its response body. */
32593
+ durationMs: external_exports.number().int().nonnegative(),
32594
+ /** Whether the client received the whole body. */
32595
+ outcome: external_exports.enum(["completed", "aborted"]),
32596
+ usage: TokenUsageSchema.optional(),
32597
+ /** The response's quota and rate-limit headers, by name (see `isRateLimitHeader`). */
32598
+ rateLimitHeaders: external_exports.record(external_exports.string(), external_exports.string()).optional(),
32599
+ limit: LimitClassificationSchema.optional(),
32600
+ /** The upstream's request id (`request-id`), for matching a record to the provider's own logs. */
32601
+ requestId: external_exports.string().optional()
32602
+ });
32603
+ QuotaWindowSchema = external_exports.strictObject({
32604
+ /** The fraction of the window used, as the upstream reports it (0 to 1). */
32605
+ utilization: external_exports.number().nonnegative().optional(),
32606
+ resetsAt: InstantSchema.optional(),
32607
+ /** The window's own status (`allowed`, `allowed_warning`, `rejected`). */
32608
+ status: external_exports.string().optional()
32609
+ });
32610
+ UnifiedRateLimitSchema = external_exports.strictObject({
32611
+ /** The overall status: `allowed`, `allowed_warning` or `rejected`. */
32612
+ status: external_exports.string().optional(),
32613
+ fiveHour: QuotaWindowSchema.optional(),
32614
+ sevenDay: QuotaWindowSchema.optional(),
32615
+ /** The window that currently binds. */
32616
+ representativeClaim: external_exports.string().optional(),
32617
+ /** When the binding window resets. */
32618
+ resetAt: InstantSchema.optional(),
32619
+ /** Whether usage beyond the plan (extra usage) is available: `allowed` or `rejected`. */
32620
+ overageStatus: external_exports.string().optional(),
32621
+ /** The fraction of the extra-usage allowance used, as the upstream reports it (0 to 1). An account with no plan windows, such as an Enterprise one, is metered by this alone. */
32622
+ overageUtilization: external_exports.number().nonnegative().optional(),
32623
+ /** When the extra-usage allowance resets. */
32624
+ overageResetsAt: InstantSchema.optional(),
32625
+ /** Why extra usage is unavailable, as the upstream names it (`out_of_credits`, for one). */
32626
+ overageDisabledReason: external_exports.string().optional()
32627
+ });
32628
+ RateLimitStateSchema = external_exports.strictObject({
32629
+ observedAt: InstantSchema,
32630
+ /** Every quota and rate-limit header on that response, by name. */
32631
+ headers: external_exports.record(external_exports.string(), external_exports.string()),
32632
+ unified: UnifiedRateLimitSchema.optional()
32633
+ });
32634
+ LimitEventSchema = LimitClassificationSchema.extend({
32635
+ observedAt: InstantSchema,
32636
+ status: external_exports.number().int()
32637
+ });
32638
+ ProviderQuotaWindowSchema = external_exports.strictObject({
32639
+ /** What the window measures, in the provider's terms (`tokens`, `tool-calls`). */
32640
+ measures: external_exports.string(),
32641
+ /** The window's length in milliseconds, when the provider's unit is one this project knows; absent for an unrecognised unit, with `period` carrying the raw code. */
32642
+ periodMs: external_exports.number().int().positive().optional(),
32643
+ /** The provider's own description of the period when `periodMs` could not be derived, such as `unit 4 x 1`. */
32644
+ period: external_exports.string().optional(),
32645
+ /** The fraction of the window used (0 to 1). */
32646
+ utilization: external_exports.number().nonnegative(),
32647
+ resetsAt: InstantSchema.optional(),
32648
+ /** Absolute counts, when the provider reports them for this window. */
32649
+ limit: external_exports.number().nonnegative().optional(),
32650
+ used: external_exports.number().nonnegative().optional(),
32651
+ remaining: external_exports.number().nonnegative().optional()
32652
+ });
32653
+ ProviderQuotaSchema = external_exports.strictObject({
32654
+ observedAt: InstantSchema,
32655
+ /** Which usage endpoint produced it (`z.ai`). */
32656
+ source: external_exports.string(),
32657
+ /** The subscription level the endpoint reports, when it does. */
32658
+ level: external_exports.string().optional(),
32659
+ windows: external_exports.array(ProviderQuotaWindowSchema)
32660
+ });
32661
+ ProviderUsageStateSchema = external_exports.strictObject({
32662
+ /** When the provider last served a request for the identity through the front door. Absent while the state holds only a rate-limit state fetched from the provider's usage endpoint, for an identity that has made no request. */
32663
+ lastRequestAt: InstantSchema.optional(),
32664
+ lastStatus: external_exports.number().int().optional(),
32665
+ lastModel: external_exports.string().optional(),
32666
+ /** The latest rate-limit state, from the last response that carried any rate-limit header. */
32667
+ rateLimit: RateLimitStateSchema.optional(),
32668
+ /** The latest classified refusal. It stays after later successes, so a reader compares its `resetAt` (or `observedAt` plus `retryAfterSeconds`) with the current time. */
32669
+ lastLimit: LimitEventSchema.optional(),
32670
+ /** The latest quota the provider's usage endpoint reported, for providers whose quota is not visible in response headers. */
32671
+ quota: ProviderQuotaSchema.optional()
32672
+ });
32673
+ AccountMetadataSchema = external_exports.strictObject({
32674
+ accountUuid: external_exports.string().optional(),
32675
+ emailAddress: external_exports.string().optional(),
32676
+ displayName: external_exports.string().optional(),
32677
+ organizationUuid: external_exports.string().optional(),
32678
+ organizationName: external_exports.string().optional(),
32679
+ organizationType: external_exports.string().optional(),
32680
+ organizationRole: external_exports.string().optional(),
32681
+ workspaceRole: external_exports.string().optional(),
32682
+ billingType: external_exports.string().optional(),
32683
+ seatTier: external_exports.string().optional(),
32684
+ organizationRateLimitTier: external_exports.string().optional(),
32685
+ userRateLimitTier: external_exports.string().optional(),
32686
+ hasExtraUsageEnabled: external_exports.boolean().optional(),
32687
+ subscriptionCreatedAt: external_exports.string().optional(),
32688
+ accountCreatedAt: external_exports.string().optional()
32689
+ });
32690
+ UsageSnapshotSchema = external_exports.strictObject({
32691
+ schemaVersion: VersionSchema,
32692
+ identity: external_exports.string(),
32693
+ updatedAt: InstantSchema,
32694
+ /** The identity's account metadata as of `updatedAt`. */
32695
+ account: AccountMetadataSchema.optional(),
32696
+ /** Latest state per provider, keyed by provider name (`anthropic` for OAuth sessions). */
32697
+ providers: external_exports.record(external_exports.string(), ProviderUsageStateSchema)
32698
+ });
32699
+ }
32700
+ });
32701
+
32702
+ // src/usage/rateLimit.ts
32703
+ function rateLimitHeadersOf(headers) {
32704
+ const kept = {};
32705
+ for (const [name, value2] of Object.entries(headers)) {
32706
+ if (isRateLimitHeader(name)) {
32707
+ kept[name.toLowerCase()] = value2;
32708
+ }
32709
+ }
32710
+ return Object.keys(kept).length === 0 ? void 0 : kept;
32711
+ }
32712
+ function epochSecondsToIso(value2) {
32713
+ if (value2 === void 0) {
32714
+ return void 0;
32715
+ }
32716
+ const seconds = Number(value2);
32717
+ return Number.isFinite(seconds) && seconds > 0 ? new Date(seconds * MS_PER_SECOND).toISOString() : void 0;
32718
+ }
32719
+ function nonNegativeNumber(value2) {
32720
+ if (value2 === void 0 || value2.trim() === "") {
32721
+ return void 0;
32722
+ }
32723
+ const parsed = Number(value2);
32724
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : void 0;
32725
+ }
32726
+ function unifiedWindow(headers, window) {
32727
+ const utilization = nonNegativeNumber(headers[`${UNIFIED_PREFIX}${window}-utilization`]);
32728
+ const resetsAt = epochSecondsToIso(headers[`${UNIFIED_PREFIX}${window}-reset`]);
32729
+ const status = headers[`${UNIFIED_PREFIX}${window}-status`];
32730
+ if (utilization === void 0 && resetsAt === void 0 && status === void 0) {
32731
+ return void 0;
32732
+ }
32733
+ return { ...utilization === void 0 ? {} : { utilization }, ...resetsAt === void 0 ? {} : { resetsAt }, ...status === void 0 ? {} : { status } };
32734
+ }
32735
+ function parseUnifiedRateLimit(headers) {
32736
+ if (!Object.keys(headers).some((name) => name.startsWith(UNIFIED_PREFIX))) {
32737
+ return void 0;
32738
+ }
32739
+ const status = headers[`${UNIFIED_PREFIX}status`];
32740
+ const fiveHour = unifiedWindow(headers, "5h");
32741
+ const sevenDay = unifiedWindow(headers, "7d");
32742
+ const representativeClaim = headers[`${UNIFIED_PREFIX}representative-claim`];
32743
+ const resetAt = epochSecondsToIso(headers[`${UNIFIED_PREFIX}reset`]);
32744
+ const overageStatus = headers[`${UNIFIED_PREFIX}overage-status`];
32745
+ const overageUtilization = nonNegativeNumber(headers[`${UNIFIED_PREFIX}overage-utilization`]);
32746
+ const overageResetsAt = epochSecondsToIso(headers[`${UNIFIED_PREFIX}overage-reset`]);
32747
+ const overageDisabledReason = headers[`${UNIFIED_PREFIX}overage-disabled-reason`];
32748
+ return {
32749
+ ...status === void 0 ? {} : { status },
32750
+ ...fiveHour === void 0 ? {} : { fiveHour },
32751
+ ...sevenDay === void 0 ? {} : { sevenDay },
32752
+ ...representativeClaim === void 0 ? {} : { representativeClaim },
32753
+ ...resetAt === void 0 ? {} : { resetAt },
32754
+ ...overageStatus === void 0 ? {} : { overageStatus },
32755
+ ...overageUtilization === void 0 ? {} : { overageUtilization },
32756
+ ...overageResetsAt === void 0 ? {} : { overageResetsAt },
32757
+ ...overageDisabledReason === void 0 ? {} : { overageDisabledReason }
32758
+ };
32759
+ }
32760
+ function overageFactsOf(unified) {
32761
+ const { overageStatus, overageUtilization, overageResetsAt, overageDisabledReason } = unified;
32762
+ return {
32763
+ ...overageStatus === void 0 ? {} : { overageStatus },
32764
+ ...overageUtilization === void 0 ? {} : { overageUtilization },
32765
+ ...overageResetsAt === void 0 ? {} : { overageResetsAt },
32766
+ ...overageDisabledReason === void 0 ? {} : { overageDisabledReason }
32767
+ };
32768
+ }
32769
+ function overageWindowOf(unified) {
32770
+ const { overageUtilization: utilization, overageResetsAt: resetsAt, overageStatus: status } = unified;
32771
+ if (utilization === void 0 && resetsAt === void 0 && status === void 0) {
32772
+ return void 0;
32773
+ }
32774
+ return { ...utilization === void 0 ? {} : { utilization }, ...resetsAt === void 0 ? {} : { resetsAt }, ...status === void 0 ? {} : { status } };
32775
+ }
32776
+ function soleOverageWindow(unified) {
32777
+ return unified.fiveHour === void 0 && unified.sevenDay === void 0 ? overageWindowOf(unified) : void 0;
32778
+ }
32779
+ function retryAfterSeconds(value2, nowMs) {
32780
+ if (value2 === void 0) {
32781
+ return void 0;
32782
+ }
32783
+ const seconds = nonNegativeNumber(value2);
32784
+ if (seconds !== void 0) {
32785
+ return seconds;
32786
+ }
32787
+ const date5 = Date.parse(value2);
32788
+ return Number.isNaN(date5) ? void 0 : Math.max(0, Math.ceil((date5 - nowMs) / MS_PER_SECOND));
32789
+ }
32790
+ function classifyLimit(params) {
32791
+ const { status, headers, error: error62 } = params;
32792
+ if (status !== TOO_MANY_REQUESTS && status !== PAYMENT_REQUIRED) {
32793
+ return void 0;
32794
+ }
32795
+ const evidence = [`status=${String(status)}`];
32796
+ const unified = parseUnifiedRateLimit(headers);
32797
+ const unifiedRejected = unified?.status === "rejected" && (unified.overageStatus === void 0 || unified.overageStatus === "rejected");
32798
+ if (unified?.status !== void 0) {
32799
+ evidence.push(`${UNIFIED_PREFIX}status=${unified.status}`);
32800
+ }
32801
+ if (unified?.overageStatus !== void 0) {
32802
+ evidence.push(`${UNIFIED_PREFIX}overage-status=${unified.overageStatus}`);
32803
+ }
32804
+ for (const [name, value2] of [
32805
+ ["error.type", error62?.type],
32806
+ ["error.code", error62?.code]
32807
+ ]) {
32808
+ if (value2 !== void 0 && EVIDENCE_TOKEN.test(value2)) {
32809
+ evidence.push(`${name}=${value2}`);
32810
+ }
32811
+ }
32812
+ const errorExhausted = [error62?.type, error62?.code].some((value2) => value2 !== void 0 && QUOTA_EXHAUSTED_ERRORS.has(value2));
32813
+ const messageExhausted = error62?.message !== void 0 && QUOTA_EXHAUSTED_MESSAGE.test(error62.message);
32814
+ if (messageExhausted) {
32815
+ evidence.push("error.message=names a usage limit");
32816
+ }
32817
+ const exhausted = status === PAYMENT_REQUIRED || unifiedRejected || errorExhausted || messageExhausted;
32818
+ const retryAfter = retryAfterSeconds(headers["retry-after"], params.nowMs);
32819
+ return {
32820
+ kind: exhausted ? "quota-exhausted" : "rate-limited",
32821
+ ...retryAfter === void 0 ? {} : { retryAfterSeconds: retryAfter },
32822
+ ...unified?.resetAt === void 0 ? {} : { resetAt: unified.resetAt },
32823
+ ...unified?.representativeClaim === void 0 ? {} : { window: unified.representativeClaim },
32824
+ evidence
32825
+ };
32826
+ }
32827
+ var TOO_MANY_REQUESTS, PAYMENT_REQUIRED, MS_PER_SECOND, UNIFIED_PREFIX, QUOTA_EXHAUSTED_ERRORS, QUOTA_EXHAUSTED_MESSAGE, EVIDENCE_TOKEN;
32828
+ var init_rateLimit = __esm({
32829
+ "src/usage/rateLimit.ts"() {
32830
+ "use strict";
32831
+ init_schema2();
32832
+ TOO_MANY_REQUESTS = 429;
32833
+ PAYMENT_REQUIRED = 402;
32834
+ MS_PER_SECOND = 1e3;
32835
+ UNIFIED_PREFIX = "anthropic-ratelimit-unified-";
32836
+ QUOTA_EXHAUSTED_ERRORS = /* @__PURE__ */ new Set(["usage_limit_reached", "insufficient_quota", "1308", "1309", "1310", "1316", "1317", "1318", "1319", "1320", "1321"]);
32837
+ QUOTA_EXHAUSTED_MESSAGE = /usage limit|quota (?:exceeded|exhausted)|limit exhausted|insufficient (?:balance|credits|quota)/i;
32838
+ EVIDENCE_TOKEN = /^[\w.-]{1,64}$/;
32839
+ }
32840
+ });
32841
+
32532
32842
  // src/usage/preflight.ts
32533
32843
  function formatAge(ms2) {
32534
- const minutes = Math.floor(ms2 / (MS_PER_SECOND * SECONDS_PER_MINUTE));
32844
+ const minutes = Math.floor(ms2 / (MS_PER_SECOND2 * SECONDS_PER_MINUTE));
32535
32845
  if (minutes < MINUTES_PER_HOUR) {
32536
32846
  return `${String(Math.max(minutes, 0))}m`;
32537
32847
  }
@@ -32559,7 +32869,8 @@ function quotaWarnings(snapshot, provider, nowMs) {
32559
32869
  const age2 = formatAge(nowMs - Date.parse(rateLimit.observedAt));
32560
32870
  const windows = [
32561
32871
  { name: "five-hour", window: unified.fiveHour },
32562
- { name: "seven-day", window: unified.sevenDay }
32872
+ { name: "seven-day", window: unified.sevenDay },
32873
+ { name: "extra-usage", window: soleOverageWindow(unified) }
32563
32874
  ];
32564
32875
  return windows.flatMap(({ name, window }) => {
32565
32876
  const effective = window === void 0 ? void 0 : effectiveWindow(window, nowMs);
@@ -32571,11 +32882,12 @@ function quotaWarnings(snapshot, provider, nowMs) {
32571
32882
  return [`agent-shim: identity ${snapshot.identity}: the ${name} quota is ${verdict}${reset} (last seen ${age2} ago)`];
32572
32883
  });
32573
32884
  }
32574
- var MS_PER_SECOND, SECONDS_PER_MINUTE, MINUTES_PER_HOUR, HOURS_PER_DAY, WARNING_STATUSES;
32885
+ var MS_PER_SECOND2, SECONDS_PER_MINUTE, MINUTES_PER_HOUR, HOURS_PER_DAY, WARNING_STATUSES;
32575
32886
  var init_preflight = __esm({
32576
32887
  "src/usage/preflight.ts"() {
32577
32888
  "use strict";
32578
- MS_PER_SECOND = 1e3;
32889
+ init_rateLimit();
32890
+ MS_PER_SECOND2 = 1e3;
32579
32891
  SECONDS_PER_MINUTE = 60;
32580
32892
  MINUTES_PER_HOUR = 60;
32581
32893
  HOURS_PER_DAY = 24;
@@ -32879,7 +33191,7 @@ var init_package = __esm({
32879
33191
  "package.json"() {
32880
33192
  package_default = {
32881
33193
  name: "agent-shim",
32882
- version: "9.1.0",
33194
+ version: "9.2.1",
32883
33195
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
32884
33196
  license: "MIT",
32885
33197
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -32981,164 +33293,6 @@ var init_package = __esm({
32981
33293
  }
32982
33294
  });
32983
33295
 
32984
- // src/usage/schema.ts
32985
- function isRateLimitHeader(name) {
32986
- const lower = name.toLowerCase();
32987
- return lower === "retry-after" || lower.startsWith("anthropic-ratelimit-") || lower.startsWith("x-ratelimit-") || lower.startsWith("ratelimit") || lower.startsWith("x-codex-");
32988
- }
32989
- var USAGE_SCHEMA_VERSION, VersionSchema, InstantSchema, TokenCountSchema, TokenUsageSchema, LIMIT_KINDS, LimitClassificationSchema, UsageRecordSchema, QuotaWindowSchema, UnifiedRateLimitSchema, RateLimitStateSchema, LimitEventSchema, ProviderQuotaWindowSchema, ProviderQuotaSchema, ProviderUsageStateSchema, AccountMetadataSchema, UsageSnapshotSchema;
32990
- var init_schema2 = __esm({
32991
- "src/usage/schema.ts"() {
32992
- "use strict";
32993
- init_zod();
32994
- USAGE_SCHEMA_VERSION = 1;
32995
- VersionSchema = external_exports.literal(USAGE_SCHEMA_VERSION);
32996
- InstantSchema = external_exports.iso.datetime();
32997
- TokenCountSchema = external_exports.number().int().nonnegative();
32998
- TokenUsageSchema = external_exports.strictObject({
32999
- inputTokens: TokenCountSchema.optional(),
33000
- outputTokens: TokenCountSchema.optional(),
33001
- cacheCreationInputTokens: TokenCountSchema.optional(),
33002
- cacheReadInputTokens: TokenCountSchema.optional()
33003
- });
33004
- LIMIT_KINDS = ["rate-limited", "quota-exhausted"];
33005
- LimitClassificationSchema = external_exports.strictObject({
33006
- kind: external_exports.enum(LIMIT_KINDS),
33007
- /** Seconds to wait before retrying, from the response's `retry-after`. */
33008
- retryAfterSeconds: external_exports.number().nonnegative().optional(),
33009
- /** When the limiting window resets, from the upstream's own reset header. */
33010
- resetAt: InstantSchema.optional(),
33011
- /** The window the upstream named as the binding one (`anthropic-ratelimit-unified-representative-claim`), such as `five_hour` or `seven_day`. */
33012
- window: external_exports.string().optional(),
33013
- /** The signals the classification rests on, each `<name>=<value>` from a response header or the error body's `type` or `code`. Never the error message. */
33014
- evidence: external_exports.array(external_exports.string())
33015
- });
33016
- UsageRecordSchema = external_exports.strictObject({
33017
- schemaVersion: VersionSchema,
33018
- /** When the front door received the request. */
33019
- at: InstantSchema,
33020
- /** The launching identity, when the launch resolved one. */
33021
- identity: external_exports.string().optional(),
33022
- /** `anthropic` for an OAuth session's request to Claude Code's own API, otherwise the provider's name. */
33023
- provider: external_exports.string(),
33024
- /** The launch's session id, generated per launch. */
33025
- sessionId: external_exports.string().optional(),
33026
- /** The project the launch ran in (its git repository root), when the launch sent one: headroom launches do. */
33027
- project: external_exports.string().optional(),
33028
- /** The front-door route that served the request. */
33029
- route: external_exports.string(),
33030
- method: external_exports.string(),
33031
- /** The API path as the upstream sees it (`/v1/messages`), without the provider prefix or a query string. */
33032
- endpoint: external_exports.string(),
33033
- /** The model the response named. */
33034
- model: external_exports.string().optional(),
33035
- status: external_exports.number().int(),
33036
- /** Milliseconds from the request's arrival to its response head. */
33037
- latencyMs: external_exports.number().int().nonnegative(),
33038
- /** Milliseconds from the request's arrival to the end of its response body. */
33039
- durationMs: external_exports.number().int().nonnegative(),
33040
- /** Whether the client received the whole body. */
33041
- outcome: external_exports.enum(["completed", "aborted"]),
33042
- usage: TokenUsageSchema.optional(),
33043
- /** The response's quota and rate-limit headers, by name (see `isRateLimitHeader`). */
33044
- rateLimitHeaders: external_exports.record(external_exports.string(), external_exports.string()).optional(),
33045
- limit: LimitClassificationSchema.optional(),
33046
- /** The upstream's request id (`request-id`), for matching a record to the provider's own logs. */
33047
- requestId: external_exports.string().optional()
33048
- });
33049
- QuotaWindowSchema = external_exports.strictObject({
33050
- /** The fraction of the window used, as the upstream reports it (0 to 1). */
33051
- utilization: external_exports.number().nonnegative().optional(),
33052
- resetsAt: InstantSchema.optional(),
33053
- /** The window's own status (`allowed`, `allowed_warning`, `rejected`). */
33054
- status: external_exports.string().optional()
33055
- });
33056
- UnifiedRateLimitSchema = external_exports.strictObject({
33057
- /** The overall status: `allowed`, `allowed_warning` or `rejected`. */
33058
- status: external_exports.string().optional(),
33059
- fiveHour: QuotaWindowSchema.optional(),
33060
- sevenDay: QuotaWindowSchema.optional(),
33061
- /** The window that currently binds. */
33062
- representativeClaim: external_exports.string().optional(),
33063
- /** When the binding window resets. */
33064
- resetAt: InstantSchema.optional(),
33065
- /** Whether usage beyond the plan (extra usage) is available: `allowed` or `rejected`. */
33066
- overageStatus: external_exports.string().optional()
33067
- });
33068
- RateLimitStateSchema = external_exports.strictObject({
33069
- observedAt: InstantSchema,
33070
- /** Every quota and rate-limit header on that response, by name. */
33071
- headers: external_exports.record(external_exports.string(), external_exports.string()),
33072
- unified: UnifiedRateLimitSchema.optional()
33073
- });
33074
- LimitEventSchema = LimitClassificationSchema.extend({
33075
- observedAt: InstantSchema,
33076
- status: external_exports.number().int()
33077
- });
33078
- ProviderQuotaWindowSchema = external_exports.strictObject({
33079
- /** What the window measures, in the provider's terms (`tokens`, `tool-calls`). */
33080
- measures: external_exports.string(),
33081
- /** The window's length in milliseconds, when the provider's unit is one this project knows; absent for an unrecognised unit, with `period` carrying the raw code. */
33082
- periodMs: external_exports.number().int().positive().optional(),
33083
- /** The provider's own description of the period when `periodMs` could not be derived, such as `unit 4 x 1`. */
33084
- period: external_exports.string().optional(),
33085
- /** The fraction of the window used (0 to 1). */
33086
- utilization: external_exports.number().nonnegative(),
33087
- resetsAt: InstantSchema.optional(),
33088
- /** Absolute counts, when the provider reports them for this window. */
33089
- limit: external_exports.number().nonnegative().optional(),
33090
- used: external_exports.number().nonnegative().optional(),
33091
- remaining: external_exports.number().nonnegative().optional()
33092
- });
33093
- ProviderQuotaSchema = external_exports.strictObject({
33094
- observedAt: InstantSchema,
33095
- /** Which usage endpoint produced it (`z.ai`). */
33096
- source: external_exports.string(),
33097
- /** The subscription level the endpoint reports, when it does. */
33098
- level: external_exports.string().optional(),
33099
- windows: external_exports.array(ProviderQuotaWindowSchema)
33100
- });
33101
- ProviderUsageStateSchema = external_exports.strictObject({
33102
- /** When the provider last served a request for the identity through the front door. Absent while the state holds only a rate-limit state fetched from the provider's usage endpoint, for an identity that has made no request. */
33103
- lastRequestAt: InstantSchema.optional(),
33104
- lastStatus: external_exports.number().int().optional(),
33105
- lastModel: external_exports.string().optional(),
33106
- /** The latest rate-limit state, from the last response that carried any rate-limit header. */
33107
- rateLimit: RateLimitStateSchema.optional(),
33108
- /** The latest classified refusal. It stays after later successes, so a reader compares its `resetAt` (or `observedAt` plus `retryAfterSeconds`) with the current time. */
33109
- lastLimit: LimitEventSchema.optional(),
33110
- /** The latest quota the provider's usage endpoint reported, for providers whose quota is not visible in response headers. */
33111
- quota: ProviderQuotaSchema.optional()
33112
- });
33113
- AccountMetadataSchema = external_exports.strictObject({
33114
- accountUuid: external_exports.string().optional(),
33115
- emailAddress: external_exports.string().optional(),
33116
- displayName: external_exports.string().optional(),
33117
- organizationUuid: external_exports.string().optional(),
33118
- organizationName: external_exports.string().optional(),
33119
- organizationType: external_exports.string().optional(),
33120
- organizationRole: external_exports.string().optional(),
33121
- workspaceRole: external_exports.string().optional(),
33122
- billingType: external_exports.string().optional(),
33123
- seatTier: external_exports.string().optional(),
33124
- organizationRateLimitTier: external_exports.string().optional(),
33125
- userRateLimitTier: external_exports.string().optional(),
33126
- hasExtraUsageEnabled: external_exports.boolean().optional(),
33127
- subscriptionCreatedAt: external_exports.string().optional(),
33128
- accountCreatedAt: external_exports.string().optional()
33129
- });
33130
- UsageSnapshotSchema = external_exports.strictObject({
33131
- schemaVersion: VersionSchema,
33132
- identity: external_exports.string(),
33133
- updatedAt: InstantSchema,
33134
- /** The identity's account metadata as of `updatedAt`. */
33135
- account: AccountMetadataSchema.optional(),
33136
- /** Latest state per provider, keyed by provider name (`anthropic` for OAuth sessions). */
33137
- providers: external_exports.record(external_exports.string(), ProviderUsageStateSchema)
33138
- });
33139
- }
33140
- });
33141
-
33142
33296
  // src/usage/account.ts
33143
33297
  function isObject2(value2) {
33144
33298
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
@@ -33223,7 +33377,11 @@ var init_account = __esm({
33223
33377
 
33224
33378
  // src/usage/plan.ts
33225
33379
  function planOf(account) {
33226
- const tier = account?.organizationRateLimitTier ?? account?.userRateLimitTier;
33380
+ const userTier = account?.userRateLimitTier;
33381
+ if (userTier !== void 0 && ZERO_TIER.test(userTier)) {
33382
+ return { kind: "pay-per-use", tier: userTier };
33383
+ }
33384
+ const tier = account?.organizationRateLimitTier ?? userTier;
33227
33385
  const tierField = tier === void 0 ? {} : { tier };
33228
33386
  if (tier === void 0) {
33229
33387
  return { kind: "subscription", capacity: 1, recognised: false };
@@ -33344,121 +33502,6 @@ var init_route = __esm({
33344
33502
  }
33345
33503
  });
33346
33504
 
33347
- // src/usage/rateLimit.ts
33348
- function rateLimitHeadersOf(headers) {
33349
- const kept = {};
33350
- for (const [name, value2] of Object.entries(headers)) {
33351
- if (isRateLimitHeader(name)) {
33352
- kept[name.toLowerCase()] = value2;
33353
- }
33354
- }
33355
- return Object.keys(kept).length === 0 ? void 0 : kept;
33356
- }
33357
- function epochSecondsToIso(value2) {
33358
- if (value2 === void 0) {
33359
- return void 0;
33360
- }
33361
- const seconds = Number(value2);
33362
- return Number.isFinite(seconds) && seconds > 0 ? new Date(seconds * MS_PER_SECOND2).toISOString() : void 0;
33363
- }
33364
- function nonNegativeNumber(value2) {
33365
- if (value2 === void 0 || value2.trim() === "") {
33366
- return void 0;
33367
- }
33368
- const parsed = Number(value2);
33369
- return Number.isFinite(parsed) && parsed >= 0 ? parsed : void 0;
33370
- }
33371
- function unifiedWindow(headers, window) {
33372
- const utilization = nonNegativeNumber(headers[`${UNIFIED_PREFIX}${window}-utilization`]);
33373
- const resetsAt = epochSecondsToIso(headers[`${UNIFIED_PREFIX}${window}-reset`]);
33374
- const status = headers[`${UNIFIED_PREFIX}${window}-status`];
33375
- if (utilization === void 0 && resetsAt === void 0 && status === void 0) {
33376
- return void 0;
33377
- }
33378
- return { ...utilization === void 0 ? {} : { utilization }, ...resetsAt === void 0 ? {} : { resetsAt }, ...status === void 0 ? {} : { status } };
33379
- }
33380
- function parseUnifiedRateLimit(headers) {
33381
- if (!Object.keys(headers).some((name) => name.startsWith(UNIFIED_PREFIX))) {
33382
- return void 0;
33383
- }
33384
- const status = headers[`${UNIFIED_PREFIX}status`];
33385
- const fiveHour = unifiedWindow(headers, "5h");
33386
- const sevenDay = unifiedWindow(headers, "7d");
33387
- const representativeClaim = headers[`${UNIFIED_PREFIX}representative-claim`];
33388
- const resetAt = epochSecondsToIso(headers[`${UNIFIED_PREFIX}reset`]);
33389
- const overageStatus = headers[`${UNIFIED_PREFIX}overage-status`];
33390
- return {
33391
- ...status === void 0 ? {} : { status },
33392
- ...fiveHour === void 0 ? {} : { fiveHour },
33393
- ...sevenDay === void 0 ? {} : { sevenDay },
33394
- ...representativeClaim === void 0 ? {} : { representativeClaim },
33395
- ...resetAt === void 0 ? {} : { resetAt },
33396
- ...overageStatus === void 0 ? {} : { overageStatus }
33397
- };
33398
- }
33399
- function retryAfterSeconds(value2, nowMs) {
33400
- if (value2 === void 0) {
33401
- return void 0;
33402
- }
33403
- const seconds = nonNegativeNumber(value2);
33404
- if (seconds !== void 0) {
33405
- return seconds;
33406
- }
33407
- const date5 = Date.parse(value2);
33408
- return Number.isNaN(date5) ? void 0 : Math.max(0, Math.ceil((date5 - nowMs) / MS_PER_SECOND2));
33409
- }
33410
- function classifyLimit(params) {
33411
- const { status, headers, error: error62 } = params;
33412
- if (status !== TOO_MANY_REQUESTS && status !== PAYMENT_REQUIRED) {
33413
- return void 0;
33414
- }
33415
- const evidence = [`status=${String(status)}`];
33416
- const unified = parseUnifiedRateLimit(headers);
33417
- const unifiedRejected = unified?.status === "rejected" && (unified.overageStatus === void 0 || unified.overageStatus === "rejected");
33418
- if (unified?.status !== void 0) {
33419
- evidence.push(`${UNIFIED_PREFIX}status=${unified.status}`);
33420
- }
33421
- if (unified?.overageStatus !== void 0) {
33422
- evidence.push(`${UNIFIED_PREFIX}overage-status=${unified.overageStatus}`);
33423
- }
33424
- for (const [name, value2] of [
33425
- ["error.type", error62?.type],
33426
- ["error.code", error62?.code]
33427
- ]) {
33428
- if (value2 !== void 0 && EVIDENCE_TOKEN.test(value2)) {
33429
- evidence.push(`${name}=${value2}`);
33430
- }
33431
- }
33432
- const errorExhausted = [error62?.type, error62?.code].some((value2) => value2 !== void 0 && QUOTA_EXHAUSTED_ERRORS.has(value2));
33433
- const messageExhausted = error62?.message !== void 0 && QUOTA_EXHAUSTED_MESSAGE.test(error62.message);
33434
- if (messageExhausted) {
33435
- evidence.push("error.message=names a usage limit");
33436
- }
33437
- const exhausted = status === PAYMENT_REQUIRED || unifiedRejected || errorExhausted || messageExhausted;
33438
- const retryAfter = retryAfterSeconds(headers["retry-after"], params.nowMs);
33439
- return {
33440
- kind: exhausted ? "quota-exhausted" : "rate-limited",
33441
- ...retryAfter === void 0 ? {} : { retryAfterSeconds: retryAfter },
33442
- ...unified?.resetAt === void 0 ? {} : { resetAt: unified.resetAt },
33443
- ...unified?.representativeClaim === void 0 ? {} : { window: unified.representativeClaim },
33444
- evidence
33445
- };
33446
- }
33447
- var TOO_MANY_REQUESTS, PAYMENT_REQUIRED, MS_PER_SECOND2, UNIFIED_PREFIX, QUOTA_EXHAUSTED_ERRORS, QUOTA_EXHAUSTED_MESSAGE, EVIDENCE_TOKEN;
33448
- var init_rateLimit = __esm({
33449
- "src/usage/rateLimit.ts"() {
33450
- "use strict";
33451
- init_schema2();
33452
- TOO_MANY_REQUESTS = 429;
33453
- PAYMENT_REQUIRED = 402;
33454
- MS_PER_SECOND2 = 1e3;
33455
- UNIFIED_PREFIX = "anthropic-ratelimit-unified-";
33456
- QUOTA_EXHAUSTED_ERRORS = /* @__PURE__ */ new Set(["usage_limit_reached", "insufficient_quota", "1308", "1309", "1310", "1316", "1317", "1318", "1319", "1320", "1321"]);
33457
- QUOTA_EXHAUSTED_MESSAGE = /usage limit|quota (?:exceeded|exhausted)|limit exhausted|insufficient (?:balance|credits|quota)/i;
33458
- EVIDENCE_TOKEN = /^[\w.-]{1,64}$/;
33459
- }
33460
- });
33461
-
33462
33505
  // src/usage/scan.ts
33463
33506
  function mergeUsage(current, raw) {
33464
33507
  const parsed = AnthropicUsageSchema.safeParse(raw);
@@ -33873,6 +33916,28 @@ var init_middleware = __esm({
33873
33916
  }
33874
33917
  });
33875
33918
 
33919
+ // src/usage/quotaFacts.ts
33920
+ function windowFacts(window, nowMs) {
33921
+ if (window?.utilization === void 0 || window.resetsAt === void 0) {
33922
+ return void 0;
33923
+ }
33924
+ return { remaining: Math.max(0, 1 - window.utilization), utilization: window.utilization, hoursUntilReset: Math.max(0, (Date.parse(window.resetsAt) - nowMs) / MS_PER_HOUR) };
33925
+ }
33926
+ function quotaFactsOf(unified, nowMs) {
33927
+ const fiveHour = windowFacts(unified?.fiveHour, nowMs);
33928
+ const sevenDay = windowFacts(unified?.sevenDay, nowMs);
33929
+ const extraUsage = windowFacts(unified === void 0 ? void 0 : soleOverageWindow(unified), nowMs);
33930
+ return { ...fiveHour === void 0 ? {} : { fiveHour }, ...sevenDay === void 0 ? {} : { sevenDay }, ...extraUsage === void 0 ? {} : { extraUsage } };
33931
+ }
33932
+ var MS_PER_HOUR;
33933
+ var init_quotaFacts = __esm({
33934
+ "src/usage/quotaFacts.ts"() {
33935
+ "use strict";
33936
+ init_rateLimit();
33937
+ MS_PER_HOUR = 36e5;
33938
+ }
33939
+ });
33940
+
33876
33941
  // src/usage/pick.ts
33877
33942
  function unifiedOf(state) {
33878
33943
  return state?.rateLimit?.unified;
@@ -33967,18 +34032,22 @@ function assessIdentity(member, nowMs) {
33967
34032
  ...fiveHourWindow === void 0 || five === void 0 ? [] : [describeWindow("5h", fiveHourWindow, five, nowMs)],
33968
34033
  ...sevenDayWindow === void 0 || seven === void 0 ? [] : [describeWindow("7d", sevenDayWindow, seven, nowMs)]
33969
34034
  ];
34035
+ const overageWindow = soleOverageWindow(unified);
34036
+ const overage = overageWindow === void 0 ? void 0 : effectiveWindow(overageWindow, nowMs);
34037
+ const overageReasons = overageWindow === void 0 || overage === void 0 ? [] : [describeWindow("extra usage", overageWindow, overage, nowMs)];
33970
34038
  const blockedUntil = Math.max(
33971
- windowBlockedUntil([five, seven].flatMap((window) => window === void 0 ? [] : [window])) ?? 0,
34039
+ windowBlockedUntil([five, seven, overage].flatMap((window) => window === void 0 ? [] : [window])) ?? 0,
33972
34040
  limitBlockedUntil(state, nowMs) ?? 0
33973
34041
  );
33974
34042
  if (blockedUntil > nowMs) {
33975
34043
  if (unified.overageStatus === "allowed") {
33976
34044
  return { candidate: { ...base, class: "pay-per-use", reasons: [`plan exhausted until ${new Date(blockedUntil).toISOString()}, continues as extra usage`, ...windowReasons, ...planReasons] } };
33977
34045
  }
33978
- return { candidate: { ...base, class: "ineligible", blockedUntilMs: blockedUntil, reasons: [`refused until ${new Date(blockedUntil).toISOString()} (in ${formatAge(blockedUntil - nowMs)})`, ...windowReasons, ...planReasons] } };
34046
+ return { candidate: { ...base, class: "ineligible", blockedUntilMs: blockedUntil, reasons: [`refused until ${new Date(blockedUntil).toISOString()} (in ${formatAge(blockedUntil - nowMs)})`, ...windowReasons, ...overageReasons, ...planReasons] } };
33979
34047
  }
33980
34048
  if (plan.kind === "pay-per-use" || fiveHourWindow === void 0 && sevenDayWindow === void 0) {
33981
- return { candidate: { ...base, class: "pay-per-use", reasons: [...plan.kind === "pay-per-use" ? planReasons : ["no plan windows reported, so usage bills as extra usage"]] } };
34049
+ const headroom = overage?.utilization === void 0 ? void 0 : Math.max(0, 1 - overage.utilization);
34050
+ return { candidate: { ...base, class: "pay-per-use", ...headroom === void 0 ? {} : { headroom }, reasons: [...plan.kind === "pay-per-use" ? planReasons : ["no plan windows reported, so usage bills as extra usage"], ...overageReasons] } };
33982
34051
  }
33983
34052
  const basis = seven?.utilization !== void 0 ? { window: seven, windowMs: SEVEN_DAY_WINDOW_MS } : five?.utilization !== void 0 ? { window: five, windowMs: FIVE_HOUR_WINDOW_MS } : void 0;
33984
34053
  if (basis?.window.utilization === void 0) {
@@ -33986,7 +34055,7 @@ function assessIdentity(member, nowMs) {
33986
34055
  }
33987
34056
  const remaining = Math.max(0, 1 - basis.window.utilization);
33988
34057
  const untilResetMs = basis.window.resetsAtMs === void 0 ? basis.windowMs : Math.max(basis.window.resetsAtMs - nowMs, MS_PER_SECOND3);
33989
- const score = remaining * plan.capacity / (untilResetMs / MS_PER_HOUR);
34058
+ const score = remaining * plan.capacity / (untilResetMs / MS_PER_HOUR2);
33990
34059
  const fiveRemaining = five?.utilization === void 0 ? void 0 : Math.max(0, 1 - five.utilization);
33991
34060
  const fiveUntil = five?.resetsAtMs === void 0 ? FIVE_HOUR_WINDOW_MS : Math.max(five.resetsAtMs - nowMs, MS_PER_SECOND3);
33992
34061
  const burn = windowBurn(member.records, "fiveHour");
@@ -34002,24 +34071,15 @@ function assessIdentity(member, nowMs) {
34002
34071
  };
34003
34072
  }
34004
34073
  function poolFactsOf(member, nowMs, resuming, sticky) {
34005
- const unified = member.snapshot?.providers[ANTHROPIC_PROVIDER]?.rateLimit?.unified;
34006
- const window = (which) => {
34007
- const raw = unified?.[which];
34008
- if (raw?.utilization === void 0) {
34009
- return void 0;
34010
- }
34011
- if (raw.resetsAt === void 0) {
34012
- return void 0;
34013
- }
34014
- return { remaining: Math.max(0, 1 - raw.utilization), utilization: raw.utilization, hoursUntilReset: Math.max(0, (Date.parse(raw.resetsAt) - nowMs) / MS_PER_HOUR) };
34015
- };
34074
+ const { fiveHour, sevenDay, extraUsage } = quotaFactsOf(member.snapshot?.providers[ANTHROPIC_PROVIDER]?.rateLimit?.unified, nowMs);
34016
34075
  const burn = windowBurn(member.records, "fiveHour");
34017
34076
  return {
34018
- ...window("fiveHour") === void 0 ? {} : { fiveHour: window("fiveHour") },
34019
- ...window("sevenDay") === void 0 ? {} : { sevenDay: window("sevenDay") },
34020
- ...burn === void 0 ? {} : { burnPerHour: burn * MS_PER_HOUR },
34077
+ ...fiveHour === void 0 ? {} : { fiveHour },
34078
+ ...sevenDay === void 0 ? {} : { sevenDay },
34079
+ ...extraUsage === void 0 ? {} : { extraUsage },
34080
+ ...burn === void 0 ? {} : { burnPerHour: burn * MS_PER_HOUR2 },
34021
34081
  resuming,
34022
- ...sticky?.identity === member.identity ? { lastPickHoursAgo: Math.max(0, (nowMs - Date.parse(sticky.at)) / MS_PER_HOUR) } : {}
34082
+ ...sticky?.identity === member.identity ? { lastPickHoursAgo: Math.max(0, (nowMs - Date.parse(sticky.at)) / MS_PER_HOUR2) } : {}
34023
34083
  };
34024
34084
  }
34025
34085
  function rankPool(input2) {
@@ -34068,7 +34128,7 @@ function rankPool(input2) {
34068
34128
  return { ...candidate, feasible: false, reasons: [...drySpots, ...candidate.reasons] };
34069
34129
  });
34070
34130
  const ordered = input2.preference === "listed" ? [...candidates] : [...candidates].sort(
34071
- (left, right) => CLASS_ORDER[left.class] - CLASS_ORDER[right.class] || Number(left.policyDemoted ?? false) - Number(right.policyDemoted ?? false) || Number(right.feasible) - Number(left.feasible) || (right.score ?? 0) - (left.score ?? 0) || left.identity.localeCompare(right.identity)
34131
+ (left, right) => CLASS_ORDER[left.class] - CLASS_ORDER[right.class] || Number(left.policyDemoted ?? false) - Number(right.policyDemoted ?? false) || Number(right.feasible) - Number(left.feasible) || (right.headroom ?? 1) - (left.headroom ?? 1) || (right.score ?? 0) - (left.score ?? 0) || left.identity.localeCompare(right.identity)
34072
34132
  );
34073
34133
  const sticky = input2.sticky;
34074
34134
  const stickyIndex = sticky === void 0 ? -1 : ordered.findIndex((candidate) => candidate.identity === sticky.identity);
@@ -34093,7 +34153,7 @@ function rankPool(input2) {
34093
34153
  ...movedOff === void 0 || pick2 === void 0 ? {} : { movedOff }
34094
34154
  };
34095
34155
  }
34096
- var MS_PER_SECOND3, MS_PER_HOUR, HOURS_PER_DAY2, FIVE_HOURS, PROMPT_CACHE_TTL_HOURS, PERCENT, SEVEN_DAYS, FIVE_HOUR_WINDOW_MS, SEVEN_DAY_WINDOW_MS, PROMPT_CACHE_TTL_MS, CLASS_ORDER;
34156
+ var MS_PER_SECOND3, MS_PER_HOUR2, HOURS_PER_DAY2, FIVE_HOURS, PROMPT_CACHE_TTL_HOURS, PERCENT, SEVEN_DAYS, FIVE_HOUR_WINDOW_MS, SEVEN_DAY_WINDOW_MS, PROMPT_CACHE_TTL_MS, CLASS_ORDER;
34097
34157
  var init_pick = __esm({
34098
34158
  "src/usage/pick.ts"() {
34099
34159
  "use strict";
@@ -34101,17 +34161,18 @@ var init_pick = __esm({
34101
34161
  init_plan2();
34102
34162
  init_middleware();
34103
34163
  init_preflight();
34164
+ init_quotaFacts();
34104
34165
  init_rateLimit();
34105
34166
  MS_PER_SECOND3 = 1e3;
34106
- MS_PER_HOUR = 36e5;
34167
+ MS_PER_HOUR2 = 36e5;
34107
34168
  HOURS_PER_DAY2 = 24;
34108
34169
  FIVE_HOURS = 5;
34109
34170
  PROMPT_CACHE_TTL_HOURS = 1;
34110
34171
  PERCENT = 100;
34111
34172
  SEVEN_DAYS = 7;
34112
- FIVE_HOUR_WINDOW_MS = FIVE_HOURS * MS_PER_HOUR;
34113
- SEVEN_DAY_WINDOW_MS = SEVEN_DAYS * HOURS_PER_DAY2 * MS_PER_HOUR;
34114
- PROMPT_CACHE_TTL_MS = PROMPT_CACHE_TTL_HOURS * MS_PER_HOUR;
34173
+ FIVE_HOUR_WINDOW_MS = FIVE_HOURS * MS_PER_HOUR2;
34174
+ SEVEN_DAY_WINDOW_MS = SEVEN_DAYS * HOURS_PER_DAY2 * MS_PER_HOUR2;
34175
+ PROMPT_CACHE_TTL_MS = PROMPT_CACHE_TTL_HOURS * MS_PER_HOUR2;
34115
34176
  CLASS_ORDER = { scored: 0, unknown: 1, "pay-per-use": 2, ineligible: 3 };
34116
34177
  }
34117
34178
  });
@@ -34381,8 +34442,9 @@ function createUsageStore(deps) {
34381
34442
  recordRateLimit: (identity, provider, rateLimit) => rewriteSnapshot(identity, (current) => {
34382
34443
  const state = current?.providers[provider] ?? {};
34383
34444
  const keep = state.rateLimit !== void 0 && state.rateLimit.observedAt.localeCompare(rateLimit.observedAt) > 0;
34384
- const overageStatus = rateLimit.unified?.overageStatus ?? state.rateLimit?.unified?.overageStatus;
34385
- const merged = overageStatus === void 0 || rateLimit.unified === void 0 ? rateLimit : { ...rateLimit, unified: { ...rateLimit.unified, overageStatus } };
34445
+ const earlier = state.rateLimit?.unified;
34446
+ const carried = rateLimit.unified === void 0 || rateLimit.unified.overageStatus !== void 0 || earlier === void 0 ? void 0 : overageFactsOf(earlier);
34447
+ const merged = carried === void 0 || rateLimit.unified === void 0 ? rateLimit : { ...rateLimit, unified: { ...rateLimit.unified, ...carried } };
34386
34448
  return { ...current?.providers, [provider]: { ...state, rateLimit: keep ? state.rateLimit : merged } };
34387
34449
  })
34388
34450
  };
@@ -60908,7 +60970,8 @@ function unifiedFromReportedLimits(reported) {
60908
60970
  return { ...fiveHour === void 0 ? {} : { fiveHour }, ...sevenDay === void 0 ? {} : { sevenDay } };
60909
60971
  }
60910
60972
  function isAnthropicUsageProbeable(member) {
60911
- return planOf(member.account ?? member.snapshot?.account).kind === "subscription";
60973
+ const unified = member.snapshot?.providers[ANTHROPIC_PROVIDER]?.rateLimit?.unified;
60974
+ return planOf(member.account ?? member.snapshot?.account).kind === "subscription" && (unified === void 0 || soleOverageWindow(unified) === void 0);
60912
60975
  }
60913
60976
  function isAnthropicUsageStale(member, nowMs) {
60914
60977
  const rateLimit = member.snapshot?.providers[ANTHROPIC_PROVIDER]?.rateLimit;
@@ -60994,6 +61057,7 @@ var init_anthropicUsageRefresh = __esm({
60994
61057
  init_middleware();
60995
61058
  init_pick();
60996
61059
  init_plan2();
61060
+ init_rateLimit();
60997
61061
  PERCENT2 = 100;
60998
61062
  ANTHROPIC_USAGE_FRESHNESS_MS = FIVE_HOUR_WINDOW_MS / PERCENT2;
60999
61063
  NO_PLAN_WINDOWS_FRESHNESS_MS = SEVEN_DAY_WINDOW_MS / PERCENT2;
@@ -113105,11 +113169,11 @@ function rcFanoutOnDoorHub(fanout, hub) {
113105
113169
 
113106
113170
  // src/frontdoor/quotaExpiringEvents.ts
113107
113171
  init_schema2();
113108
- var MS_PER_HOUR2 = 36e5;
113172
+ var MS_PER_HOUR3 = 36e5;
113109
113173
  var MS_PER_DAY3 = 864e5;
113110
113174
  var FIVE_HOUR_WINDOW_HOURS = 5;
113111
113175
  var SEVEN_DAY_WINDOW_DAYS = 7;
113112
- var FIVE_HOUR_WINDOW_MS2 = FIVE_HOUR_WINDOW_HOURS * MS_PER_HOUR2;
113176
+ var FIVE_HOUR_WINDOW_MS2 = FIVE_HOUR_WINDOW_HOURS * MS_PER_HOUR3;
113113
113177
  var SEVEN_DAY_WINDOW_MS2 = SEVEN_DAY_WINDOW_DAYS * MS_PER_DAY3;
113114
113178
  var FINAL_SPAN_DENOMINATOR = 30;
113115
113179
  var QUOTA_EXPIRING_WINDOW_FRACTION = 1 / FINAL_SPAN_DENOMINATOR;
@@ -114393,6 +114457,7 @@ function createPassthroughRoute(name, target) {
114393
114457
 
114394
114458
  // src/frontdoor/providerRoute.ts
114395
114459
  init_conditions();
114460
+ init_quotaFacts();
114396
114461
  init_route();
114397
114462
  var import_node_stream3 = require("node:stream");
114398
114463
 
@@ -114475,7 +114540,6 @@ async function scanRequestHead(request7, wholeBody = false) {
114475
114540
  }
114476
114541
 
114477
114542
  // src/frontdoor/providerRoute.ts
114478
- var MS_PER_HOUR3 = 36e5;
114479
114543
  function createProviderRouteResolver(deps) {
114480
114544
  const isRcSelfHostPath = (path47) => path47 === "/v1/code/sessions" || path47.startsWith("/v1/code/sessions/") || path47 === "/v1/sessions" || path47.startsWith("/v1/sessions/");
114481
114545
  const oauthRoute = createPassthroughRoute("anthropic", { baseUrl: `https://${CONNECT_INTERCEPT_HOST}:${String(HTTPS_PORT)}`, stripPrefix: void 0, headroomUpstream: void 0 });
@@ -114575,16 +114639,9 @@ function createProviderRouteResolver(deps) {
114575
114639
  }
114576
114640
  const whole = routes.some((entry) => entry.model !== void 0 || referencesFact(entry.when, "request.hasImage"));
114577
114641
  const snapshot = deps.usageSnapshotOf?.(current.session.identity);
114578
- const windowFacts = (raw) => {
114579
- if (raw?.utilization === void 0 || raw.resetsAt === void 0) {
114580
- return void 0;
114581
- }
114582
- return { remaining: Math.max(0, 1 - raw.utilization), utilization: raw.utilization, hoursUntilReset: Math.max(0, (Date.parse(raw.resetsAt) - Date.now()) / MS_PER_HOUR3) };
114583
- };
114584
114642
  const providerQuota = Object.fromEntries(
114585
114643
  routes.flatMap((entry) => {
114586
- const unified = snapshot?.providers[entry.provider]?.rateLimit?.unified;
114587
- return [[entry.provider, { fiveHour: windowFacts(unified?.fiveHour), sevenDay: windowFacts(unified?.sevenDay) }]];
114644
+ return [[entry.provider, quotaFactsOf(snapshot?.providers[entry.provider]?.rateLimit?.unified, Date.now())]];
114588
114645
  })
114589
114646
  );
114590
114647
  const scan = await scanRequestHead(current, whole);
@@ -119020,6 +119077,7 @@ init_account();
119020
119077
  init_read();
119021
119078
  init_anthropicUsageRefresh();
119022
119079
  init_middleware();
119080
+ init_rateLimit();
119023
119081
  init_realAnthropicUsageProbe();
119024
119082
  init_store2();
119025
119083
  var DAY_MS3 = 864e5;
@@ -119052,13 +119110,19 @@ function formatWindow(label, window) {
119052
119110
  const used = window.utilization === void 0 ? "usage unknown" : `${String(Math.round(window.utilization * PERCENT4))}% used`;
119053
119111
  return `${label} ${used}${window.resetsAt === void 0 ? "" : `, resets ${window.resetsAt}`}${window.status === void 0 ? "" : ` (${window.status})`}`;
119054
119112
  }
119113
+ function extraUsageParts(unified) {
119114
+ const window = overageWindowOf(unified);
119115
+ const measured = window?.utilization !== void 0 || window?.resetsAt !== void 0;
119116
+ const fact = window === void 0 ? void 0 : measured ? formatWindow("extra usage", window) : `extra usage ${window.status ?? "unknown"}`;
119117
+ return [...fact === void 0 ? [] : [fact], ...unified.overageDisabledReason === void 0 ? [] : [`extra usage disabled: ${unified.overageDisabledReason}`]];
119118
+ }
119055
119119
  function formatRateLimit(state) {
119056
119120
  const { unified } = state;
119057
119121
  if (unified === void 0) {
119058
119122
  return `rate-limit headers (as of ${state.observedAt}): ${Object.entries(state.headers).map(([name, value2]) => `${name}=${value2}`).join(", ")}`;
119059
119123
  }
119060
119124
  const parts = [formatWindow("5h", unified.fiveHour), formatWindow("7d", unified.sevenDay)].filter((part) => part !== void 0);
119061
- return `quota (as of ${state.observedAt}): ${[...parts, `status ${unified.status ?? "unknown"}`, ...unified.overageStatus === void 0 ? [] : [`extra usage ${unified.overageStatus}`]].join("; ")}`;
119125
+ return `quota (as of ${state.observedAt}): ${[...parts, `status ${unified.status ?? "unknown"}`, ...extraUsageParts(unified)].join("; ")}`;
119062
119126
  }
119063
119127
  function formatLimit(limit) {
119064
119128
  const wait2 = [