@agentproto/model-intel 0.1.0 → 0.2.0

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/index.d.ts CHANGED
@@ -118,6 +118,47 @@ interface AnthropicHeadersInput {
118
118
  */
119
119
  declare function quotaFromAnthropicHeaders(input: AnthropicHeadersInput): QuotaStatus | undefined;
120
120
 
121
+ /** One side of a Codex `rate_limits` payload. */
122
+ interface CodexRateLimitWindow {
123
+ used_percent: number;
124
+ window_minutes?: number;
125
+ /** Epoch seconds. */
126
+ reset_at?: number;
127
+ }
128
+ interface CodexRateLimits {
129
+ primary?: CodexRateLimitWindow;
130
+ secondary?: CodexRateLimitWindow;
131
+ }
132
+ interface CodexCredits {
133
+ has_credits?: boolean;
134
+ unlimited?: boolean;
135
+ balance?: number;
136
+ }
137
+ interface CodexRateLimitsInput {
138
+ profileRef: string;
139
+ rateLimits: CodexRateLimits;
140
+ credits?: CodexCredits;
141
+ now?: () => Date;
142
+ }
143
+ /**
144
+ * Pure parser for a Codex `rate_limits` payload: each present side becomes one
145
+ * window and optional credits become a credits block. Never throws; a missing
146
+ * or non-numeric field is dropped, a valid value (0 included) is kept.
147
+ */
148
+ declare function quotaFromCodexRateLimits(input: CodexRateLimitsInput): QuotaStatus | undefined;
149
+
150
+ interface MoonshotQuotaReaderOptions {
151
+ baseUrl?: string;
152
+ timeoutMs?: number;
153
+ }
154
+ /**
155
+ * Moonshot balance reader: `GET /v1/users/me/balance` exposes the account's
156
+ * available USD balance, but no cap, so it is reported as credits-only (no
157
+ * window). The whole read never throws; a balance of 0 or below is real data
158
+ * and is kept as is.
159
+ */
160
+ declare function createMoonshotQuotaReader(opts?: MoonshotQuotaReaderOptions): QuotaReader;
161
+
121
162
  interface OpenRouterQuotaReaderOptions {
122
163
  baseUrl?: string;
123
164
  timeoutMs?: number;
@@ -141,4 +182,4 @@ declare function createOpenRouterQuotaReader(opts?: OpenRouterQuotaReaderOptions
141
182
  declare const SPEC_NAME: "quota/v1";
142
183
  declare const SPEC_VERSION: "1.0.0-alpha";
143
184
 
144
- export { type BuildQuotaStatusInput, QUOTA_BASES, type QuotaBasis, type QuotaCredits, type QuotaProfile, type QuotaReadContext, type QuotaReader, QuotaReaderRegistry, type QuotaStatus, type QuotaWindow, SPEC_NAME, SPEC_VERSION, buildQuotaStatus, createOpenRouterQuotaReader, defineQuotaReader, quotaCreditsSchema, quotaFromAnthropicHeaders, quotaStatusSchema, quotaWindowSchema, remainingPctFromCounts, remainingPctFromUsed };
185
+ export { type BuildQuotaStatusInput, type CodexCredits, type CodexRateLimitWindow, type CodexRateLimits, type CodexRateLimitsInput, QUOTA_BASES, type QuotaBasis, type QuotaCredits, type QuotaProfile, type QuotaReadContext, type QuotaReader, QuotaReaderRegistry, type QuotaStatus, type QuotaWindow, SPEC_NAME, SPEC_VERSION, buildQuotaStatus, createMoonshotQuotaReader, createOpenRouterQuotaReader, defineQuotaReader, quotaCreditsSchema, quotaFromAnthropicHeaders, quotaFromCodexRateLimits, quotaStatusSchema, quotaWindowSchema, remainingPctFromCounts, remainingPctFromUsed };
package/dist/index.mjs CHANGED
@@ -145,12 +145,12 @@ function quotaFromAnthropicHeaders(input) {
145
145
  const limit = parseCount(headerGet(input.headers, `${prefix}-limit`));
146
146
  const remaining = parseCount(headerGet(input.headers, `${prefix}-remaining`));
147
147
  if (limit === void 0 || remaining === void 0) continue;
148
- const remainingPct = remainingPctFromCounts(remaining, limit);
149
- if (remainingPct === void 0) continue;
148
+ const remainingPct2 = remainingPctFromCounts(remaining, limit);
149
+ if (remainingPct2 === void 0) continue;
150
150
  const resetsAt = parseReset(headerGet(input.headers, `${prefix}-reset`));
151
151
  windows.push({
152
152
  id: dimension.id,
153
- remainingPct,
153
+ remainingPct: remainingPct2,
154
154
  limit,
155
155
  remaining,
156
156
  unit: dimension.unit,
@@ -165,8 +165,112 @@ function quotaFromAnthropicHeaders(input) {
165
165
  windows
166
166
  });
167
167
  }
168
- var DEFAULT_BASE_URL = "https://openrouter.ai/api/v1";
168
+
169
+ // src/readers/codex.ts
170
+ function remainingPct(used) {
171
+ return Math.max(0, Math.min(100, 100 - used));
172
+ }
173
+ function windowFromSide(id, side) {
174
+ if (!side || typeof side.used_percent !== "number" || !Number.isFinite(side.used_percent)) {
175
+ return void 0;
176
+ }
177
+ const window = { id, remainingPct: remainingPct(side.used_percent) };
178
+ if (typeof side.reset_at === "number" && Number.isFinite(side.reset_at)) {
179
+ const date = new Date(side.reset_at * 1e3);
180
+ if (!Number.isNaN(date.getTime())) window.resetsAt = date.toISOString();
181
+ }
182
+ return window;
183
+ }
184
+ function quotaFromCodexRateLimits(input) {
185
+ try {
186
+ const windows = [];
187
+ const primary = windowFromSide("primary", input.rateLimits?.primary);
188
+ if (primary) windows.push(primary);
189
+ const secondary = windowFromSide("secondary", input.rateLimits?.secondary);
190
+ if (secondary) windows.push(secondary);
191
+ let credits;
192
+ const raw = input.credits;
193
+ if (raw) {
194
+ const hasBalance = typeof raw.balance === "number" && Number.isFinite(raw.balance);
195
+ if (raw.unlimited === true || hasBalance) {
196
+ credits = { currency: "USD" };
197
+ if (raw.unlimited === true) credits.unlimited = true;
198
+ if (hasBalance) credits.balanceUsd = raw.balance;
199
+ }
200
+ }
201
+ return buildQuotaStatus({
202
+ profileRef: input.profileRef,
203
+ basis: "provider",
204
+ source: "codex:rate_limits",
205
+ now: input.now,
206
+ windows,
207
+ ...credits !== void 0 ? { credits } : {}
208
+ });
209
+ } catch {
210
+ return void 0;
211
+ }
212
+ }
213
+ var DEFAULT_BASE_URL = "https://api.moonshot.ai";
169
214
  var DEFAULT_TIMEOUT_MS = 4e3;
215
+ var MOONSHOT_BALANCE_SCHEMA = z.object({
216
+ data: z.object({
217
+ available_balance: z.number()
218
+ }).passthrough()
219
+ }).passthrough();
220
+ async function getBalanceJson(baseUrl, secret, ctx, timeoutMs) {
221
+ const controller = new AbortController();
222
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
223
+ const onAbort = () => controller.abort();
224
+ ctx.signal?.addEventListener("abort", onAbort);
225
+ try {
226
+ const res = await (ctx.fetchImpl ?? fetch)(`${baseUrl}/v1/users/me/balance`, {
227
+ method: "GET",
228
+ headers: { authorization: `Bearer ${secret}` },
229
+ signal: controller.signal
230
+ });
231
+ if (!res.ok) return void 0;
232
+ return await res.json();
233
+ } catch {
234
+ return void 0;
235
+ } finally {
236
+ clearTimeout(timer);
237
+ ctx.signal?.removeEventListener("abort", onAbort);
238
+ }
239
+ }
240
+ function createMoonshotQuotaReader(opts) {
241
+ const baseUrl = opts?.baseUrl ?? DEFAULT_BASE_URL;
242
+ const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
243
+ return defineQuotaReader({
244
+ id: "moonshot-balance",
245
+ supports: (profile) => profile.endpoint === "moonshot" && profile.method === "api-key",
246
+ read: async (profile, ctx) => {
247
+ try {
248
+ if (!profile.credentialRef) return void 0;
249
+ if (!ctx.resolveCredential) return void 0;
250
+ const secret = await ctx.resolveCredential(profile.credentialRef).catch(() => void 0);
251
+ if (!secret) return void 0;
252
+ const body = await getBalanceJson(baseUrl, secret, ctx, timeoutMs);
253
+ if (body === void 0) return void 0;
254
+ const parsed = MOONSHOT_BALANCE_SCHEMA.safeParse(body);
255
+ if (!parsed.success) return void 0;
256
+ const balance = parsed.data.data.available_balance;
257
+ if (!Number.isFinite(balance)) return void 0;
258
+ return buildQuotaStatus({
259
+ profileRef: profile.profileRef,
260
+ basis: "provider",
261
+ source: "moonshot:/users/me/balance",
262
+ now: ctx.now,
263
+ windows: [],
264
+ credits: { balanceUsd: balance, currency: "USD" }
265
+ });
266
+ } catch {
267
+ return void 0;
268
+ }
269
+ }
270
+ });
271
+ }
272
+ var DEFAULT_BASE_URL2 = "https://openrouter.ai/api/v1";
273
+ var DEFAULT_TIMEOUT_MS2 = 4e3;
170
274
  var OPENROUTER_KEY_SCHEMA = z.object({
171
275
  data: z.object({
172
276
  limit: z.number().nullable().optional(),
@@ -194,8 +298,8 @@ async function getKeyJson(baseUrl, secret, ctx, timeoutMs) {
194
298
  }
195
299
  }
196
300
  function createOpenRouterQuotaReader(opts) {
197
- const baseUrl = opts?.baseUrl ?? DEFAULT_BASE_URL;
198
- const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
301
+ const baseUrl = opts?.baseUrl ?? DEFAULT_BASE_URL2;
302
+ const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
199
303
  return defineQuotaReader({
200
304
  id: "openrouter-key",
201
305
  supports: (profile) => profile.endpoint === "openrouter" && profile.method === "api-key",
@@ -212,11 +316,11 @@ function createOpenRouterQuotaReader(opts) {
212
316
  const { limit, limit_remaining } = parsed.data.data;
213
317
  const windows = [];
214
318
  if (typeof limit === "number" && Number.isFinite(limit) && typeof limit_remaining === "number" && Number.isFinite(limit_remaining)) {
215
- const remainingPct = remainingPctFromCounts(limit_remaining, limit);
216
- if (remainingPct !== void 0) {
319
+ const remainingPct2 = remainingPctFromCounts(limit_remaining, limit);
320
+ if (remainingPct2 !== void 0) {
217
321
  windows.push({
218
322
  id: "key_limit",
219
- remainingPct,
323
+ remainingPct: remainingPct2,
220
324
  remaining: limit_remaining,
221
325
  limit,
222
326
  unit: "USD"
@@ -246,6 +350,6 @@ function createOpenRouterQuotaReader(opts) {
246
350
  var SPEC_NAME = "quota/v1";
247
351
  var SPEC_VERSION = "1.0.0-alpha";
248
352
 
249
- export { QUOTA_BASES, QuotaReaderRegistry, SPEC_NAME, SPEC_VERSION, buildQuotaStatus, createOpenRouterQuotaReader, defineQuotaReader, quotaCreditsSchema, quotaFromAnthropicHeaders, quotaStatusSchema, quotaWindowSchema, remainingPctFromCounts, remainingPctFromUsed };
353
+ export { QUOTA_BASES, QuotaReaderRegistry, SPEC_NAME, SPEC_VERSION, buildQuotaStatus, createMoonshotQuotaReader, createOpenRouterQuotaReader, defineQuotaReader, quotaCreditsSchema, quotaFromAnthropicHeaders, quotaFromCodexRateLimits, quotaStatusSchema, quotaWindowSchema, remainingPctFromCounts, remainingPctFromUsed };
250
354
  //# sourceMappingURL=index.mjs.map
251
355
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/build.ts","../src/registry.ts","../src/readers/anthropic.ts","../src/readers/openrouter.ts","../src/index.ts"],"names":["z"],"mappings":"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","file":"index.mjs","sourcesContent":["import { z } from \"zod\"\n\n/**\n * Where a quota figure came from. `provider` is a documented provider\n * surface; `observed` is derived from this host's own traffic; `estimated`\n * is a local computation; `probe` is an undocumented surface reached through\n * a connector and MUST NOT be emitted by core readers.\n */\nexport const QUOTA_BASES = [\"provider\", \"probe\", \"observed\", \"estimated\"] as const\nexport type QuotaBasis = (typeof QUOTA_BASES)[number]\n\nconst isoTimestamp = z.string().refine((s) => !Number.isNaN(Date.parse(s)), {\n message: \"expected an ISO-8601 timestamp\",\n})\n\nexport const quotaWindowSchema = z.object({\n /** Open string: \"5h\", \"7d\", \"month\", \"minute\", \"day\", \"primary\", \"key_limit\", ... */\n id: z.string().min(1),\n /** 0-100. Required: a window that cannot state it is not emitted. */\n remainingPct: z.number().min(0).max(100),\n used: z.number().optional(),\n limit: z.number().optional(),\n remaining: z.number().optional(),\n unit: z.string().optional(),\n resetsAt: isoTimestamp.optional(),\n})\nexport type QuotaWindow = z.infer<typeof quotaWindowSchema>\n\nexport const quotaCreditsSchema = z.object({\n balanceUsd: z.number().optional(),\n unlimited: z.boolean().optional(),\n currency: z.string().min(1),\n})\nexport type QuotaCredits = z.infer<typeof quotaCreditsSchema>\n\nexport const quotaStatusSchema = z.object({\n profileRef: z.string().min(1),\n asOf: isoTimestamp,\n basis: z.enum(QUOTA_BASES),\n source: z.string().optional(),\n windows: z.array(quotaWindowSchema),\n credits: quotaCreditsSchema.optional(),\n})\nexport type QuotaStatus = z.infer<typeof quotaStatusSchema>\n\n/** The minimal auth-profile projection a reader needs. */\nexport interface QuotaProfile {\n profileRef: string\n endpoint: string\n method: \"oauth-bearer\" | \"api-key\"\n credentialRef?: string\n}\n\nexport interface QuotaReadContext {\n signal?: AbortSignal\n /** Resolve a profile's opaque credentialRef to a bearer secret. */\n resolveCredential?(ref: string): Promise<string | undefined>\n fetchImpl?: typeof fetch\n now?: () => Date\n}\n\n/**\n * Reads quota for a profile. MUST NOT throw: any failure or unknown value\n * resolves to `undefined`. Never fabricates a figure.\n */\nexport interface QuotaReader {\n readonly id: string\n supports(profile: QuotaProfile): boolean\n read(profile: QuotaProfile, ctx: QuotaReadContext): Promise<QuotaStatus | undefined>\n}\n","import type { QuotaBasis, QuotaCredits, QuotaStatus, QuotaWindow } from \"./types.js\"\nimport { quotaWindowSchema } from \"./types.js\"\n\n/** remainingPct from a used percentage, or undefined when it is not a finite 0-100 number. */\nexport function remainingPctFromUsed(usedPct: number | null | undefined): number | undefined {\n if (usedPct === null || usedPct === undefined || !Number.isFinite(usedPct)) return undefined\n if (usedPct < 0 || usedPct > 100) return undefined\n return 100 - usedPct\n}\n\n/** remainingPct from remaining/limit counts, or undefined when limit is not a positive finite number. */\nexport function remainingPctFromCounts(\n remaining: number | null | undefined,\n limit: number | null | undefined,\n): number | undefined {\n if (remaining === null || remaining === undefined || limit === null || limit === undefined) {\n return undefined\n }\n if (!Number.isFinite(remaining) || !Number.isFinite(limit) || limit <= 0) return undefined\n if (remaining < 0 || remaining > limit) return undefined\n return (remaining / limit) * 100\n}\n\nexport interface BuildQuotaStatusInput {\n profileRef: string\n basis: QuotaBasis\n source?: string\n now?: () => Date\n /** Candidate windows; any that fail validation are dropped, never repaired. */\n windows?: readonly unknown[]\n credits?: QuotaCredits\n}\n\n/**\n * Assemble a QuotaStatus. Invalid windows are omitted. Returns `undefined`\n * when there is nothing to report (no valid window and no credits).\n */\nexport function buildQuotaStatus(input: BuildQuotaStatusInput): QuotaStatus | undefined {\n const windows: QuotaWindow[] = []\n for (const candidate of input.windows ?? []) {\n const parsed = quotaWindowSchema.safeParse(candidate)\n if (parsed.success) windows.push(parsed.data)\n }\n if (windows.length === 0 && input.credits === undefined) return undefined\n return {\n profileRef: input.profileRef,\n asOf: (input.now ?? (() => new Date()))().toISOString(),\n basis: input.basis,\n ...(input.source !== undefined ? { source: input.source } : {}),\n windows,\n ...(input.credits !== undefined ? { credits: input.credits } : {}),\n }\n}\n","import type { QuotaProfile, QuotaReadContext, QuotaReader, QuotaStatus } from \"./types.js\"\n\n/** Identity helper that fixes the QuotaReader contract at definition time (AIP-43 handle). */\nexport function defineQuotaReader(reader: QuotaReader): QuotaReader {\n return reader\n}\n\nexport class QuotaReaderRegistry {\n private readonly readers = new Map<string, QuotaReader>()\n\n register(reader: QuotaReader): this {\n if (this.readers.has(reader.id)) {\n throw new Error(`quota reader already registered: ${reader.id}`)\n }\n this.readers.set(reader.id, reader)\n return this\n }\n\n list(): QuotaReader[] {\n return [...this.readers.values()]\n }\n\n /** First registered reader that supports the profile, in registration order. */\n find(profile: QuotaProfile): QuotaReader | undefined {\n for (const reader of this.readers.values()) {\n if (safeSupports(reader, profile)) return reader\n }\n return undefined\n }\n\n /** Read through the first supporting reader. Never throws; unknown -> undefined. */\n async read(profile: QuotaProfile, ctx: QuotaReadContext = {}): Promise<QuotaStatus | undefined> {\n const reader = this.find(profile)\n if (!reader) return undefined\n try {\n return await reader.read(profile, ctx)\n } catch {\n return undefined\n }\n }\n}\n\nfunction safeSupports(reader: QuotaReader, profile: QuotaProfile): boolean {\n try {\n return reader.supports(profile)\n } catch {\n return false\n }\n}\n","import { buildQuotaStatus, remainingPctFromCounts } from \"../build.js\"\nimport type { QuotaStatus } from \"../types.js\"\n\nexport interface AnthropicHeadersInput {\n profileRef: string\n headers: Headers | Record<string, string | undefined>\n now?: () => Date\n}\n\ninterface Dimension {\n id: string\n header: string\n unit: string\n}\n\nconst DIMENSIONS: readonly Dimension[] = [\n { id: \"requests-1m\", header: \"requests\", unit: \"requests\" },\n { id: \"tokens-1m\", header: \"tokens\", unit: \"tokens\" },\n { id: \"input-tokens-1m\", header: \"input-tokens\", unit: \"tokens\" },\n { id: \"output-tokens-1m\", header: \"output-tokens\", unit: \"tokens\" },\n]\n\n/** Read a header case-insensitively from a `Headers` or a plain record. */\nfunction headerGet(\n headers: Headers | Record<string, string | undefined>,\n name: string,\n): string | undefined {\n if (headers instanceof Headers) {\n return headers.get(name) ?? undefined\n }\n const lower = name.toLowerCase()\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === lower) return value\n }\n return undefined\n}\n\n/** Parse a numeric rate-limit header; empty/garbage → undefined. */\nfunction parseCount(raw: string | undefined): number | undefined {\n if (raw === undefined) return undefined\n const trimmed = raw.trim()\n if (!trimmed) return undefined\n const n = Number(trimmed)\n return Number.isFinite(n) ? n : undefined\n}\n\n/** Normalize an RFC 3339 reset header to an ISO string; unparseable → undefined. */\nfunction parseReset(raw: string | undefined): string | undefined {\n if (raw === undefined) return undefined\n const trimmed = raw.trim()\n if (!trimmed) return undefined\n const date = new Date(trimmed)\n return Number.isNaN(date.getTime()) ? undefined : date.toISOString()\n}\n\n/**\n * PURE: build a QuotaStatus from Anthropic's DOCUMENTED rate-limit headers\n * `anthropic-ratelimit-{requests,tokens,input-tokens,output-tokens}-{limit,remaining,reset}`.\n * The undocumented `anthropic-ratelimit-unified-*` family is never read.\n * A dimension with a missing/non-numeric limit or remaining is skipped.\n */\nexport function quotaFromAnthropicHeaders(input: AnthropicHeadersInput): QuotaStatus | undefined {\n const windows: Record<string, unknown>[] = []\n for (const dimension of DIMENSIONS) {\n const prefix = `anthropic-ratelimit-${dimension.header}`\n const limit = parseCount(headerGet(input.headers, `${prefix}-limit`))\n const remaining = parseCount(headerGet(input.headers, `${prefix}-remaining`))\n if (limit === undefined || remaining === undefined) continue\n const remainingPct = remainingPctFromCounts(remaining, limit)\n if (remainingPct === undefined) continue\n const resetsAt = parseReset(headerGet(input.headers, `${prefix}-reset`))\n windows.push({\n id: dimension.id,\n remainingPct,\n limit,\n remaining,\n unit: dimension.unit,\n ...(resetsAt !== undefined ? { resetsAt } : {}),\n })\n }\n return buildQuotaStatus({\n profileRef: input.profileRef,\n basis: \"provider\",\n source: \"anthropic:ratelimit-headers\",\n now: input.now,\n windows,\n })\n}\n","import { z } from \"zod\"\nimport { buildQuotaStatus, remainingPctFromCounts } from \"../build.js\"\nimport { defineQuotaReader } from \"../registry.js\"\nimport type { QuotaCredits, QuotaProfile, QuotaReadContext, QuotaReader, QuotaStatus, QuotaWindow } from \"../types.js\"\n\nconst DEFAULT_BASE_URL = \"https://openrouter.ai/api/v1\"\nconst DEFAULT_TIMEOUT_MS = 4000\n\nconst OPENROUTER_KEY_SCHEMA = z\n .object({\n data: z\n .object({\n limit: z.number().nullable().optional(),\n limit_remaining: z.number().nullable().optional(),\n })\n .passthrough(),\n })\n .passthrough()\n\nexport interface OpenRouterQuotaReaderOptions {\n baseUrl?: string\n timeoutMs?: number\n}\n\n/** GET `${baseUrl}/key` and parse the body, never throwing. */\nasync function getKeyJson(\n baseUrl: string,\n secret: string,\n ctx: QuotaReadContext,\n timeoutMs: number,\n): Promise<unknown | undefined> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n const onAbort = () => controller.abort()\n ctx.signal?.addEventListener(\"abort\", onAbort)\n try {\n const res = await (ctx.fetchImpl ?? fetch)(`${baseUrl}/key`, {\n method: \"GET\",\n headers: { authorization: `Bearer ${secret}` },\n signal: controller.signal,\n })\n if (!res.ok) return undefined\n return await res.json()\n } catch {\n return undefined\n } finally {\n clearTimeout(timer)\n ctx.signal?.removeEventListener(\"abort\", onAbort)\n }\n}\n\n/**\n * OpenRouter quota reader: `GET /key` exposes the key's USD cap and remaining\n * headroom. The whole read is wrapped so it never throws; an uncapped key\n * (`limit_remaining` null/absent) yields no window and no credits.\n */\nexport function createOpenRouterQuotaReader(opts?: OpenRouterQuotaReaderOptions): QuotaReader {\n const baseUrl = opts?.baseUrl ?? DEFAULT_BASE_URL\n const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS\n\n return defineQuotaReader({\n id: \"openrouter-key\",\n supports: (profile: QuotaProfile): boolean =>\n profile.endpoint === \"openrouter\" && profile.method === \"api-key\",\n read: async (\n profile: QuotaProfile,\n ctx: QuotaReadContext,\n ): Promise<QuotaStatus | undefined> => {\n try {\n if (!profile.credentialRef) return undefined\n if (!ctx.resolveCredential) return undefined\n const secret = await ctx.resolveCredential(profile.credentialRef).catch(() => undefined)\n if (!secret) return undefined\n\n const body = await getKeyJson(baseUrl, secret, ctx, timeoutMs)\n if (body === undefined) return undefined\n const parsed = OPENROUTER_KEY_SCHEMA.safeParse(body)\n if (!parsed.success) return undefined\n\n const { limit, limit_remaining } = parsed.data.data\n const windows: QuotaWindow[] = []\n if (\n typeof limit === \"number\" &&\n Number.isFinite(limit) &&\n typeof limit_remaining === \"number\" &&\n Number.isFinite(limit_remaining)\n ) {\n const remainingPct = remainingPctFromCounts(limit_remaining, limit)\n if (remainingPct !== undefined) {\n windows.push({\n id: \"key_limit\",\n remainingPct,\n remaining: limit_remaining,\n limit,\n unit: \"USD\",\n })\n }\n }\n let credits: QuotaCredits | undefined\n if (typeof limit_remaining === \"number\" && Number.isFinite(limit_remaining)) {\n credits = { balanceUsd: limit_remaining, currency: \"USD\" }\n }\n\n return buildQuotaStatus({\n profileRef: profile.profileRef,\n basis: \"provider\",\n source: \"openrouter:/key\",\n now: ctx.now,\n windows,\n ...(credits !== undefined ? { credits } : {}),\n })\n } catch {\n return undefined\n }\n },\n })\n}\n","/**\n * @agentproto/model-intel — model intelligence primitives.\n *\n * Unified, provider-neutral quota status (AIP-67): one QuotaStatus shape with a\n * mandatory `basis`, a never-throw QuotaReader contract, and a reader registry.\n * Unknown is omitted, never fabricated.\n *\n * @see https://agentproto.sh/docs/aip-67\n */\n\nexport const SPEC_NAME = \"quota/v1\" as const\nexport const SPEC_VERSION = \"1.0.0-alpha\" as const\n\nexport {\n QUOTA_BASES,\n quotaCreditsSchema,\n quotaStatusSchema,\n quotaWindowSchema,\n} from \"./types.js\"\nexport type {\n QuotaBasis,\n QuotaCredits,\n QuotaProfile,\n QuotaReadContext,\n QuotaReader,\n QuotaStatus,\n QuotaWindow,\n} from \"./types.js\"\nexport {\n buildQuotaStatus,\n remainingPctFromCounts,\n remainingPctFromUsed,\n} from \"./build.js\"\nexport type { BuildQuotaStatusInput } from \"./build.js\"\nexport { QuotaReaderRegistry, defineQuotaReader } from \"./registry.js\"\nexport { quotaFromAnthropicHeaders } from \"./readers/anthropic.js\"\nexport { createOpenRouterQuotaReader } from \"./readers/openrouter.js\"\n"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/build.ts","../src/registry.ts","../src/readers/anthropic.ts","../src/readers/codex.ts","../src/readers/moonshot.ts","../src/readers/openrouter.ts","../src/index.ts"],"names":["remainingPct","z","DEFAULT_BASE_URL","DEFAULT_TIMEOUT_MS"],"mappings":"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","file":"index.mjs","sourcesContent":["import { z } from \"zod\"\n\n/**\n * Where a quota figure came from. `provider` is a documented provider\n * surface; `observed` is derived from this host's own traffic; `estimated`\n * is a local computation; `probe` is an undocumented surface reached through\n * a connector and MUST NOT be emitted by core readers.\n */\nexport const QUOTA_BASES = [\"provider\", \"probe\", \"observed\", \"estimated\"] as const\nexport type QuotaBasis = (typeof QUOTA_BASES)[number]\n\nconst isoTimestamp = z.string().refine((s) => !Number.isNaN(Date.parse(s)), {\n message: \"expected an ISO-8601 timestamp\",\n})\n\nexport const quotaWindowSchema = z.object({\n /** Open string: \"5h\", \"7d\", \"month\", \"minute\", \"day\", \"primary\", \"key_limit\", ... */\n id: z.string().min(1),\n /** 0-100. Required: a window that cannot state it is not emitted. */\n remainingPct: z.number().min(0).max(100),\n used: z.number().optional(),\n limit: z.number().optional(),\n remaining: z.number().optional(),\n unit: z.string().optional(),\n resetsAt: isoTimestamp.optional(),\n})\nexport type QuotaWindow = z.infer<typeof quotaWindowSchema>\n\nexport const quotaCreditsSchema = z.object({\n balanceUsd: z.number().optional(),\n unlimited: z.boolean().optional(),\n currency: z.string().min(1),\n})\nexport type QuotaCredits = z.infer<typeof quotaCreditsSchema>\n\nexport const quotaStatusSchema = z.object({\n profileRef: z.string().min(1),\n asOf: isoTimestamp,\n basis: z.enum(QUOTA_BASES),\n source: z.string().optional(),\n windows: z.array(quotaWindowSchema),\n credits: quotaCreditsSchema.optional(),\n})\nexport type QuotaStatus = z.infer<typeof quotaStatusSchema>\n\n/** The minimal auth-profile projection a reader needs. */\nexport interface QuotaProfile {\n profileRef: string\n endpoint: string\n method: \"oauth-bearer\" | \"api-key\"\n credentialRef?: string\n}\n\nexport interface QuotaReadContext {\n signal?: AbortSignal\n /** Resolve a profile's opaque credentialRef to a bearer secret. */\n resolveCredential?(ref: string): Promise<string | undefined>\n fetchImpl?: typeof fetch\n now?: () => Date\n}\n\n/**\n * Reads quota for a profile. MUST NOT throw: any failure or unknown value\n * resolves to `undefined`. Never fabricates a figure.\n */\nexport interface QuotaReader {\n readonly id: string\n supports(profile: QuotaProfile): boolean\n read(profile: QuotaProfile, ctx: QuotaReadContext): Promise<QuotaStatus | undefined>\n}\n","import type { QuotaBasis, QuotaCredits, QuotaStatus, QuotaWindow } from \"./types.js\"\nimport { quotaWindowSchema } from \"./types.js\"\n\n/** remainingPct from a used percentage, or undefined when it is not a finite 0-100 number. */\nexport function remainingPctFromUsed(usedPct: number | null | undefined): number | undefined {\n if (usedPct === null || usedPct === undefined || !Number.isFinite(usedPct)) return undefined\n if (usedPct < 0 || usedPct > 100) return undefined\n return 100 - usedPct\n}\n\n/** remainingPct from remaining/limit counts, or undefined when limit is not a positive finite number. */\nexport function remainingPctFromCounts(\n remaining: number | null | undefined,\n limit: number | null | undefined,\n): number | undefined {\n if (remaining === null || remaining === undefined || limit === null || limit === undefined) {\n return undefined\n }\n if (!Number.isFinite(remaining) || !Number.isFinite(limit) || limit <= 0) return undefined\n if (remaining < 0 || remaining > limit) return undefined\n return (remaining / limit) * 100\n}\n\nexport interface BuildQuotaStatusInput {\n profileRef: string\n basis: QuotaBasis\n source?: string\n now?: () => Date\n /** Candidate windows; any that fail validation are dropped, never repaired. */\n windows?: readonly unknown[]\n credits?: QuotaCredits\n}\n\n/**\n * Assemble a QuotaStatus. Invalid windows are omitted. Returns `undefined`\n * when there is nothing to report (no valid window and no credits).\n */\nexport function buildQuotaStatus(input: BuildQuotaStatusInput): QuotaStatus | undefined {\n const windows: QuotaWindow[] = []\n for (const candidate of input.windows ?? []) {\n const parsed = quotaWindowSchema.safeParse(candidate)\n if (parsed.success) windows.push(parsed.data)\n }\n if (windows.length === 0 && input.credits === undefined) return undefined\n return {\n profileRef: input.profileRef,\n asOf: (input.now ?? (() => new Date()))().toISOString(),\n basis: input.basis,\n ...(input.source !== undefined ? { source: input.source } : {}),\n windows,\n ...(input.credits !== undefined ? { credits: input.credits } : {}),\n }\n}\n","import type { QuotaProfile, QuotaReadContext, QuotaReader, QuotaStatus } from \"./types.js\"\n\n/** Identity helper that fixes the QuotaReader contract at definition time (AIP-43 handle). */\nexport function defineQuotaReader(reader: QuotaReader): QuotaReader {\n return reader\n}\n\nexport class QuotaReaderRegistry {\n private readonly readers = new Map<string, QuotaReader>()\n\n register(reader: QuotaReader): this {\n if (this.readers.has(reader.id)) {\n throw new Error(`quota reader already registered: ${reader.id}`)\n }\n this.readers.set(reader.id, reader)\n return this\n }\n\n list(): QuotaReader[] {\n return [...this.readers.values()]\n }\n\n /** First registered reader that supports the profile, in registration order. */\n find(profile: QuotaProfile): QuotaReader | undefined {\n for (const reader of this.readers.values()) {\n if (safeSupports(reader, profile)) return reader\n }\n return undefined\n }\n\n /** Read through the first supporting reader. Never throws; unknown -> undefined. */\n async read(profile: QuotaProfile, ctx: QuotaReadContext = {}): Promise<QuotaStatus | undefined> {\n const reader = this.find(profile)\n if (!reader) return undefined\n try {\n return await reader.read(profile, ctx)\n } catch {\n return undefined\n }\n }\n}\n\nfunction safeSupports(reader: QuotaReader, profile: QuotaProfile): boolean {\n try {\n return reader.supports(profile)\n } catch {\n return false\n }\n}\n","import { buildQuotaStatus, remainingPctFromCounts } from \"../build.js\"\nimport type { QuotaStatus } from \"../types.js\"\n\nexport interface AnthropicHeadersInput {\n profileRef: string\n headers: Headers | Record<string, string | undefined>\n now?: () => Date\n}\n\ninterface Dimension {\n id: string\n header: string\n unit: string\n}\n\nconst DIMENSIONS: readonly Dimension[] = [\n { id: \"requests-1m\", header: \"requests\", unit: \"requests\" },\n { id: \"tokens-1m\", header: \"tokens\", unit: \"tokens\" },\n { id: \"input-tokens-1m\", header: \"input-tokens\", unit: \"tokens\" },\n { id: \"output-tokens-1m\", header: \"output-tokens\", unit: \"tokens\" },\n]\n\n/** Read a header case-insensitively from a `Headers` or a plain record. */\nfunction headerGet(\n headers: Headers | Record<string, string | undefined>,\n name: string,\n): string | undefined {\n if (headers instanceof Headers) {\n return headers.get(name) ?? undefined\n }\n const lower = name.toLowerCase()\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === lower) return value\n }\n return undefined\n}\n\n/** Parse a numeric rate-limit header; empty/garbage → undefined. */\nfunction parseCount(raw: string | undefined): number | undefined {\n if (raw === undefined) return undefined\n const trimmed = raw.trim()\n if (!trimmed) return undefined\n const n = Number(trimmed)\n return Number.isFinite(n) ? n : undefined\n}\n\n/** Normalize an RFC 3339 reset header to an ISO string; unparseable → undefined. */\nfunction parseReset(raw: string | undefined): string | undefined {\n if (raw === undefined) return undefined\n const trimmed = raw.trim()\n if (!trimmed) return undefined\n const date = new Date(trimmed)\n return Number.isNaN(date.getTime()) ? undefined : date.toISOString()\n}\n\n/**\n * PURE: build a QuotaStatus from Anthropic's DOCUMENTED rate-limit headers\n * `anthropic-ratelimit-{requests,tokens,input-tokens,output-tokens}-{limit,remaining,reset}`.\n * The undocumented `anthropic-ratelimit-unified-*` family is never read.\n * A dimension with a missing/non-numeric limit or remaining is skipped.\n */\nexport function quotaFromAnthropicHeaders(input: AnthropicHeadersInput): QuotaStatus | undefined {\n const windows: Record<string, unknown>[] = []\n for (const dimension of DIMENSIONS) {\n const prefix = `anthropic-ratelimit-${dimension.header}`\n const limit = parseCount(headerGet(input.headers, `${prefix}-limit`))\n const remaining = parseCount(headerGet(input.headers, `${prefix}-remaining`))\n if (limit === undefined || remaining === undefined) continue\n const remainingPct = remainingPctFromCounts(remaining, limit)\n if (remainingPct === undefined) continue\n const resetsAt = parseReset(headerGet(input.headers, `${prefix}-reset`))\n windows.push({\n id: dimension.id,\n remainingPct,\n limit,\n remaining,\n unit: dimension.unit,\n ...(resetsAt !== undefined ? { resetsAt } : {}),\n })\n }\n return buildQuotaStatus({\n profileRef: input.profileRef,\n basis: \"provider\",\n source: \"anthropic:ratelimit-headers\",\n now: input.now,\n windows,\n })\n}\n","import { buildQuotaStatus } from \"../build.js\"\nimport type { QuotaCredits, QuotaStatus, QuotaWindow } from \"../types.js\"\n\n/** One side of a Codex `rate_limits` payload. */\nexport interface CodexRateLimitWindow {\n used_percent: number\n window_minutes?: number\n /** Epoch seconds. */\n reset_at?: number\n}\n\nexport interface CodexRateLimits {\n primary?: CodexRateLimitWindow\n secondary?: CodexRateLimitWindow\n}\n\nexport interface CodexCredits {\n has_credits?: boolean\n unlimited?: boolean\n balance?: number\n}\n\nexport interface CodexRateLimitsInput {\n profileRef: string\n rateLimits: CodexRateLimits\n credits?: CodexCredits\n now?: () => Date\n}\n\n/** remainingPct clamped to 0..100; a used percentage >100 maps to 0, kept. */\nfunction remainingPct(used: number): number {\n return Math.max(0, Math.min(100, 100 - used))\n}\n\nfunction windowFromSide(id: string, side: CodexRateLimitWindow | undefined): QuotaWindow | undefined {\n if (!side || typeof side.used_percent !== \"number\" || !Number.isFinite(side.used_percent)) {\n return undefined\n }\n const window: QuotaWindow = { id, remainingPct: remainingPct(side.used_percent) }\n if (typeof side.reset_at === \"number\" && Number.isFinite(side.reset_at)) {\n const date = new Date(side.reset_at * 1000)\n if (!Number.isNaN(date.getTime())) window.resetsAt = date.toISOString()\n }\n return window\n}\n\n/**\n * Pure parser for a Codex `rate_limits` payload: each present side becomes one\n * window and optional credits become a credits block. Never throws; a missing\n * or non-numeric field is dropped, a valid value (0 included) is kept.\n */\nexport function quotaFromCodexRateLimits(\n input: CodexRateLimitsInput,\n): QuotaStatus | undefined {\n try {\n const windows: QuotaWindow[] = []\n const primary = windowFromSide(\"primary\", input.rateLimits?.primary)\n if (primary) windows.push(primary)\n const secondary = windowFromSide(\"secondary\", input.rateLimits?.secondary)\n if (secondary) windows.push(secondary)\n\n let credits: QuotaCredits | undefined\n const raw = input.credits\n if (raw) {\n const hasBalance = typeof raw.balance === \"number\" && Number.isFinite(raw.balance)\n if (raw.unlimited === true || hasBalance) {\n credits = { currency: \"USD\" }\n if (raw.unlimited === true) credits.unlimited = true\n if (hasBalance) credits.balanceUsd = raw.balance\n }\n }\n\n return buildQuotaStatus({\n profileRef: input.profileRef,\n basis: \"provider\",\n source: \"codex:rate_limits\",\n now: input.now,\n windows,\n ...(credits !== undefined ? { credits } : {}),\n })\n } catch {\n return undefined\n }\n}\n","import { z } from \"zod\"\nimport { buildQuotaStatus } from \"../build.js\"\nimport { defineQuotaReader } from \"../registry.js\"\nimport type { QuotaProfile, QuotaReadContext, QuotaReader, QuotaStatus } from \"../types.js\"\n\nconst DEFAULT_BASE_URL = \"https://api.moonshot.ai\"\nconst DEFAULT_TIMEOUT_MS = 4000\n\nconst MOONSHOT_BALANCE_SCHEMA = z\n .object({\n data: z\n .object({\n available_balance: z.number(),\n })\n .passthrough(),\n })\n .passthrough()\n\nexport interface MoonshotQuotaReaderOptions {\n baseUrl?: string\n timeoutMs?: number\n}\n\n/** GET `${baseUrl}/v1/users/me/balance` and parse the body, never throwing. */\nasync function getBalanceJson(\n baseUrl: string,\n secret: string,\n ctx: QuotaReadContext,\n timeoutMs: number,\n): Promise<unknown | undefined> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n const onAbort = () => controller.abort()\n ctx.signal?.addEventListener(\"abort\", onAbort)\n try {\n const res = await (ctx.fetchImpl ?? fetch)(`${baseUrl}/v1/users/me/balance`, {\n method: \"GET\",\n headers: { authorization: `Bearer ${secret}` },\n signal: controller.signal,\n })\n if (!res.ok) return undefined\n return await res.json()\n } catch {\n return undefined\n } finally {\n clearTimeout(timer)\n ctx.signal?.removeEventListener(\"abort\", onAbort)\n }\n}\n\n/**\n * Moonshot balance reader: `GET /v1/users/me/balance` exposes the account's\n * available USD balance, but no cap, so it is reported as credits-only (no\n * window). The whole read never throws; a balance of 0 or below is real data\n * and is kept as is.\n */\nexport function createMoonshotQuotaReader(opts?: MoonshotQuotaReaderOptions): QuotaReader {\n const baseUrl = opts?.baseUrl ?? DEFAULT_BASE_URL\n const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS\n\n return defineQuotaReader({\n id: \"moonshot-balance\",\n supports: (profile: QuotaProfile): boolean =>\n profile.endpoint === \"moonshot\" && profile.method === \"api-key\",\n read: async (\n profile: QuotaProfile,\n ctx: QuotaReadContext,\n ): Promise<QuotaStatus | undefined> => {\n try {\n if (!profile.credentialRef) return undefined\n if (!ctx.resolveCredential) return undefined\n const secret = await ctx.resolveCredential(profile.credentialRef).catch(() => undefined)\n if (!secret) return undefined\n\n const body = await getBalanceJson(baseUrl, secret, ctx, timeoutMs)\n if (body === undefined) return undefined\n const parsed = MOONSHOT_BALANCE_SCHEMA.safeParse(body)\n if (!parsed.success) return undefined\n\n const balance = parsed.data.data.available_balance\n if (!Number.isFinite(balance)) return undefined\n\n return buildQuotaStatus({\n profileRef: profile.profileRef,\n basis: \"provider\",\n source: \"moonshot:/users/me/balance\",\n now: ctx.now,\n windows: [],\n credits: { balanceUsd: balance, currency: \"USD\" },\n })\n } catch {\n return undefined\n }\n },\n })\n}\n","import { z } from \"zod\"\nimport { buildQuotaStatus, remainingPctFromCounts } from \"../build.js\"\nimport { defineQuotaReader } from \"../registry.js\"\nimport type { QuotaCredits, QuotaProfile, QuotaReadContext, QuotaReader, QuotaStatus, QuotaWindow } from \"../types.js\"\n\nconst DEFAULT_BASE_URL = \"https://openrouter.ai/api/v1\"\nconst DEFAULT_TIMEOUT_MS = 4000\n\nconst OPENROUTER_KEY_SCHEMA = z\n .object({\n data: z\n .object({\n limit: z.number().nullable().optional(),\n limit_remaining: z.number().nullable().optional(),\n })\n .passthrough(),\n })\n .passthrough()\n\nexport interface OpenRouterQuotaReaderOptions {\n baseUrl?: string\n timeoutMs?: number\n}\n\n/** GET `${baseUrl}/key` and parse the body, never throwing. */\nasync function getKeyJson(\n baseUrl: string,\n secret: string,\n ctx: QuotaReadContext,\n timeoutMs: number,\n): Promise<unknown | undefined> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n const onAbort = () => controller.abort()\n ctx.signal?.addEventListener(\"abort\", onAbort)\n try {\n const res = await (ctx.fetchImpl ?? fetch)(`${baseUrl}/key`, {\n method: \"GET\",\n headers: { authorization: `Bearer ${secret}` },\n signal: controller.signal,\n })\n if (!res.ok) return undefined\n return await res.json()\n } catch {\n return undefined\n } finally {\n clearTimeout(timer)\n ctx.signal?.removeEventListener(\"abort\", onAbort)\n }\n}\n\n/**\n * OpenRouter quota reader: `GET /key` exposes the key's USD cap and remaining\n * headroom. The whole read is wrapped so it never throws; an uncapped key\n * (`limit_remaining` null/absent) yields no window and no credits.\n */\nexport function createOpenRouterQuotaReader(opts?: OpenRouterQuotaReaderOptions): QuotaReader {\n const baseUrl = opts?.baseUrl ?? DEFAULT_BASE_URL\n const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS\n\n return defineQuotaReader({\n id: \"openrouter-key\",\n supports: (profile: QuotaProfile): boolean =>\n profile.endpoint === \"openrouter\" && profile.method === \"api-key\",\n read: async (\n profile: QuotaProfile,\n ctx: QuotaReadContext,\n ): Promise<QuotaStatus | undefined> => {\n try {\n if (!profile.credentialRef) return undefined\n if (!ctx.resolveCredential) return undefined\n const secret = await ctx.resolveCredential(profile.credentialRef).catch(() => undefined)\n if (!secret) return undefined\n\n const body = await getKeyJson(baseUrl, secret, ctx, timeoutMs)\n if (body === undefined) return undefined\n const parsed = OPENROUTER_KEY_SCHEMA.safeParse(body)\n if (!parsed.success) return undefined\n\n const { limit, limit_remaining } = parsed.data.data\n const windows: QuotaWindow[] = []\n if (\n typeof limit === \"number\" &&\n Number.isFinite(limit) &&\n typeof limit_remaining === \"number\" &&\n Number.isFinite(limit_remaining)\n ) {\n const remainingPct = remainingPctFromCounts(limit_remaining, limit)\n if (remainingPct !== undefined) {\n windows.push({\n id: \"key_limit\",\n remainingPct,\n remaining: limit_remaining,\n limit,\n unit: \"USD\",\n })\n }\n }\n let credits: QuotaCredits | undefined\n if (typeof limit_remaining === \"number\" && Number.isFinite(limit_remaining)) {\n credits = { balanceUsd: limit_remaining, currency: \"USD\" }\n }\n\n return buildQuotaStatus({\n profileRef: profile.profileRef,\n basis: \"provider\",\n source: \"openrouter:/key\",\n now: ctx.now,\n windows,\n ...(credits !== undefined ? { credits } : {}),\n })\n } catch {\n return undefined\n }\n },\n })\n}\n","/**\n * @agentproto/model-intel — model intelligence primitives.\n *\n * Unified, provider-neutral quota status (AIP-67): one QuotaStatus shape with a\n * mandatory `basis`, a never-throw QuotaReader contract, and a reader registry.\n * Unknown is omitted, never fabricated.\n *\n * @see https://agentproto.sh/docs/aip-67\n */\n\nexport const SPEC_NAME = \"quota/v1\" as const\nexport const SPEC_VERSION = \"1.0.0-alpha\" as const\n\nexport {\n QUOTA_BASES,\n quotaCreditsSchema,\n quotaStatusSchema,\n quotaWindowSchema,\n} from \"./types.js\"\nexport type {\n QuotaBasis,\n QuotaCredits,\n QuotaProfile,\n QuotaReadContext,\n QuotaReader,\n QuotaStatus,\n QuotaWindow,\n} from \"./types.js\"\nexport {\n buildQuotaStatus,\n remainingPctFromCounts,\n remainingPctFromUsed,\n} from \"./build.js\"\nexport type { BuildQuotaStatusInput } from \"./build.js\"\nexport { QuotaReaderRegistry, defineQuotaReader } from \"./registry.js\"\nexport { quotaFromAnthropicHeaders } from \"./readers/anthropic.js\"\nexport { quotaFromCodexRateLimits } from \"./readers/codex.js\"\nexport type {\n CodexCredits,\n CodexRateLimits,\n CodexRateLimitsInput,\n CodexRateLimitWindow,\n} from \"./readers/codex.js\"\nexport { createMoonshotQuotaReader } from \"./readers/moonshot.js\"\nexport { createOpenRouterQuotaReader } from \"./readers/openrouter.js\"\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentproto/model-intel",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "@agentproto/model-intel — model intelligence primitives. Unified, provider-neutral quota status (AIP-67): a QuotaStatus shape with a mandatory basis, a never-throw QuotaReader contract, and a reader registry. Unknown is omitted, never fabricated.",
5
5
  "keywords": [
6
6
  "agentproto",