import * as Schema from "effect/Schema";
import {
ForwardCompatibleArray,
IsoDateTime,
NonNegativeInt,
TrimmedNonEmptyString,
} from "./baseSchemas.ts";
import { ProviderDriverKind, ProviderInstanceId } from "./providerInstance.ts";
import { UsageLimitSourceId } from "./usageLimitSourceId.ts";
/**
* One rolling quota window a subscription provider reports for the signed-in
* account, e.g. Claude's five-hour session or Codex's weekly allowance.
*
* `id` is stable per provider (`five_hour`, `seven_day_opus`, `primary`) so a
* sparse turn-driven update lands on the same row a full probe produced.
* `kind` only orders and labels the bar.
*/
export const ServerProviderUsageWindow = Schema.Struct({
id: TrimmedNonEmptyString,
kind: Schema.Literals(["session", "weekly", "monthly", "other"]),
label: TrimmedNonEmptyString,
usedPercent: Schema.Number.check(Schema.isBetween({ minimum: 0, maximum: 100 })),
resetsAt: Schema.optional(IsoDateTime),
windowDurationMins: Schema.optional(NonNegativeInt),
});
export type ServerProviderUsageWindow = typeof ServerProviderUsageWindow.Type;
/**
* Reset credits a provider banks on the account. Codex grants these when it
* has rate-limited the user unfairly; redeeming one clears the current
* windows. Only present when the provider reports them at all.
*/
export const ServerProviderResetCredits = Schema.Struct({
availableCount: NonNegativeInt,
nextExpiresAt: Schema.optional(IsoDateTime),
});
export type ServerProviderResetCredits = typeof ServerProviderResetCredits.Type;
/**
* Subscription usage the provider knows about the signed-in account.
*
* `unavailable` distinguishes an account that can never report windows (API
* key, Bedrock) from a probe that failed this time, so clients can keep the
* last good bars for the latter and clear them for the former.
*/
export const ServerProviderUsageLimits = Schema.Struct({
checkedAt: IsoDateTime,
windows: ForwardCompatibleArray(ServerProviderUsageWindow),
resetCredits: Schema.optional(ServerProviderResetCredits),
unavailable: Schema.optional(
Schema.Struct({
reason: Schema.Literals(["unsupported", "probeFailed"]),
message: Schema.optional(TrimmedNonEmptyString),
}),
),
});
export type ServerProviderUsageLimits = typeof ServerProviderUsageLimits.Type;
/**
* What an adapter reports when its runtime pushes a rate-limit update during
* a turn. Sparse by contract: Claude's `rate_limit_event` names one window at
* a time and Codex documents its notification as a partial. Windows merge by
* `id` onto the instance's published snapshot; omitted windows are unchanged.
*/
export const ProviderUsageLimitsUpdate = Schema.Struct({
windows: Schema.Array(ServerProviderUsageWindow),
});
export type ProviderUsageLimitsUpdate = typeof ProviderUsageLimitsUpdate.Type;
/**
* One account a usage-limit source reports on. `driver` is the provider the
* account belongs to, for the icon and colour clients already have; the
* account itself is not something this environment can run turns on.
*/
export const UsageLimitSourceAccount = Schema.Struct({
id: TrimmedNonEmptyString,
driver: ProviderDriverKind,
/** The signed-in address, when the source names one; clients blur it like provider auth. */
email: Schema.optional(TrimmedNonEmptyString),
/** Plan as the matching provider would label it (`ChatGPT Pro 20x Subscription`). */
plan: Schema.optional(TrimmedNonEmptyString),
usageLimits: ServerProviderUsageLimits,
});
export type UsageLimitSourceAccount = typeof UsageLimitSourceAccount.Type;
/**
* The published state of one configured `usageLimitSources` entry. A source
* that could not be read keeps `error` beside an empty account list rather
* than vanishing, so the user can see it is configured but failing.
*/
export const UsageLimitSourceSnapshot = Schema.Struct({
id: UsageLimitSourceId,
kind: Schema.Literal("cliproxy"),
label: TrimmedNonEmptyString,
checkedAt: IsoDateTime,
accounts: ForwardCompatibleArray(UsageLimitSourceAccount),
error: Schema.optional(TrimmedNonEmptyString),
});
export type UsageLimitSourceSnapshot = typeof UsageLimitSourceSnapshot.Type;
export const UsageLimitSourceSnapshots = ForwardCompatibleArray(UsageLimitSourceSnapshot);
export type UsageLimitSourceSnapshots = typeof UsageLimitSourceSnapshots.Type;
export const ProviderConsumeResetCreditInput = Schema.Struct({
instanceId: ProviderInstanceId,
});
export type ProviderConsumeResetCreditInput = typeof ProviderConsumeResetCreditInput.Type;
/** Mirrors Codex's own outcome set; other providers map onto it. */
export const ProviderConsumeResetCreditOutcome = Schema.Literals([
"reset",
"nothingToReset",
"noCredit",
"alreadyRedeemed",
]);
export type ProviderConsumeResetCreditOutcome = typeof ProviderConsumeResetCreditOutcome.Type;
export const ProviderConsumeResetCreditResult = Schema.Struct({
outcome: ProviderConsumeResetCreditOutcome,
});
export type ProviderConsumeResetCreditResult = typeof ProviderConsumeResetCreditResult.Type;