@cat-factory/spend 0.10.109 → 0.11.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.
@@ -1,13 +1,13 @@
1
- import type { OpenRouterModelMeta, SpendStatus } from '@cat-factory/contracts';
1
+ import type { BudgetCaps, OpenRouterModelMeta, SpendStatus } from '@cat-factory/contracts';
2
2
  import type { AgentTokenUsage } from '@cat-factory/kernel';
3
3
  import type { Clock, IdGenerator } from '@cat-factory/kernel';
4
- import type { TokenUsageRepository, WorkspaceSettingsRepository } from '@cat-factory/kernel';
4
+ import type { AccountRepository, TokenUsageRepository, UserSettingsRepository, WorkspaceSettingsRepository } from '@cat-factory/kernel';
5
5
  import { type SpendPricing } from './pricing.js';
6
6
  export interface SpendServiceDependencies {
7
7
  tokenUsageRepository: TokenUsageRepository;
8
8
  idGenerator: IdGenerator;
9
9
  clock: Clock;
10
- /** The base (built-in) pricing table + the deployment fallback budget/currency. */
10
+ /** The base (built-in) pricing table + the deployment fallback budget/currency + env caps. */
11
11
  pricing: SpendPricing;
12
12
  /**
13
13
  * Per-workspace budget overrides (currency / monthly limit / per-model prices),
@@ -16,6 +16,18 @@ export interface SpendServiceDependencies {
16
16
  * base table; absent ⇒ every workspace uses the base table (tests/conformance).
17
17
  */
18
18
  workspaceSettingsRepository?: WorkspaceSettingsRepository;
19
+ /**
20
+ * Account tenancy repository, read for the ACCOUNT budget tier (an account's
21
+ * configured `spendMonthlyLimit`). Absent ⇒ the account tier is inert unless the
22
+ * operator env cap alone activates it.
23
+ */
24
+ accountRepository?: AccountRepository;
25
+ /**
26
+ * Per-user settings repository, read for the USER budget tier (a user's configured
27
+ * `spendMonthlyLimit`). Absent ⇒ the user tier is inert unless the operator env cap
28
+ * alone activates it.
29
+ */
30
+ userSettingsRepository?: UserSettingsRepository;
19
31
  /**
20
32
  * Optional resolver for a workspace's dynamic gateway model prices (the enabled
21
33
  * OpenRouter catalog). When wired, a metered `openrouter:<slug>` call is priced at the
@@ -28,12 +40,21 @@ export interface SpendServiceDependencies {
28
40
  /** Details of a single metered LLM call, handed in by the execution engine. */
29
41
  export interface RecordUsageInput {
30
42
  workspaceId: string;
43
+ /** The owning account of `workspaceId` (denormalized for the account rollup). */
44
+ accountId?: string | null;
45
+ /** The user who initiated the run (denormalized for the user rollup). */
46
+ userId?: string | null;
31
47
  executionId: string | null;
32
48
  agentKind: string;
33
49
  /** Model identifier as `provider:model` (as produced by AgentRunResult.model). */
34
50
  model: string;
35
51
  usage: AgentTokenUsage;
36
52
  }
53
+ /** Which budget tiers to check when gating a run (the caller passes what ids it has). */
54
+ export interface BudgetTierScope {
55
+ accountId?: string | null;
56
+ userId?: string | null;
57
+ }
37
58
  /**
38
59
  * The spend safeguard. It meters token usage into a persistent ledger, prices
39
60
  * each call into a single currency, and reports the current billing period's
@@ -41,9 +62,12 @@ export interface RecordUsageInput {
41
62
  * {@link isOverBudget} before every agent step and pauses when the budget is
42
63
  * exhausted; the worker surfaces {@link status} so the frontend can warn.
43
64
  *
44
- * Budgets are per-workspace: each workspace's currency/monthly-limit/price overrides
45
- * (on its settings row) are overlaid onto the built-in base table. Resolution is
46
- * cached briefly so the hot {@link isOverBudget} gate doesn't re-read settings per step.
65
+ * Budgets are tiered — workspace, account, and user. The workspace tier overlays the
66
+ * workspace's currency/monthly-limit overrides onto the built-in base table; the account
67
+ * and user tiers compare their own rollup against a configured limit clamped by the
68
+ * operator env cap. A run is over budget when ANY applicable tier is exhausted.
69
+ * Resolutions are cached briefly so the hot {@link isOverBudget} gate doesn't re-read
70
+ * settings per step.
47
71
  */
48
72
  export declare class SpendService {
49
73
  private readonly tokenUsageRepository;
@@ -51,9 +75,13 @@ export declare class SpendService {
51
75
  private readonly clock;
52
76
  private readonly pricing;
53
77
  private readonly workspaceSettingsRepository?;
78
+ private readonly accountRepository?;
79
+ private readonly userSettingsRepository?;
54
80
  private readonly dynamicPricesFor?;
55
81
  private readonly pricingCache;
56
- constructor({ tokenUsageRepository, idGenerator, clock, pricing, workspaceSettingsRepository, dynamicPricesFor, }: SpendServiceDependencies);
82
+ private readonly accountLimitCache;
83
+ private readonly userLimitCache;
84
+ constructor({ tokenUsageRepository, idGenerator, clock, pricing, workspaceSettingsRepository, accountRepository, userSettingsRepository, dynamicPricesFor, }: SpendServiceDependencies);
57
85
  /** Parse a `provider:model` identifier into a {@link ModelRef}. */
58
86
  private parseModel;
59
87
  /**
@@ -64,11 +92,44 @@ export declare class SpendService {
64
92
  private resolvePricing;
65
93
  /** Invalidate a workspace's cached pricing (called after a budget edit). */
66
94
  invalidatePricing(workspaceId: string): void;
95
+ /** Invalidate a cached account effective limit (called after an account-budget edit). */
96
+ invalidateAccountLimit(accountId: string): void;
97
+ /** Invalidate a cached user effective limit (called after a user-budget edit). */
98
+ invalidateUserLimit(userId: string): void;
99
+ /**
100
+ * The account tier's effective monthly limit: the configured account limit clamped by
101
+ * the operator env cap. `Infinity` when the tier is inactive (neither set). Cached for
102
+ * {@link PRICING_CACHE_TTL_MS}.
103
+ */
104
+ private resolveAccountLimit;
105
+ /** The user tier's effective monthly limit (configured user limit clamped by the env cap). */
106
+ private resolveUserLimit;
67
107
  /** Meter and persist one LLM call; returns its estimated cost. */
68
108
  record(input: RecordUsageInput): Promise<number>;
69
- /** The current billing period's spend against the workspace's budget. */
109
+ /** The current billing period's spend against the WORKSPACE budget. */
70
110
  status(workspaceId: string): Promise<SpendStatus>;
71
- /** Whether this period's spend has reached the workspace's budget (runs should pause). */
72
- isOverBudget(workspaceId: string): Promise<boolean>;
111
+ /**
112
+ * The ACCOUNT tier's status, or null when the tier is inactive (no configured limit
113
+ * and no operator cap). `costLimit` is the effective limit (configured clamped by the
114
+ * env cap); costs are in the base pricing currency.
115
+ */
116
+ accountStatus(accountId: string): Promise<SpendStatus | null>;
117
+ /**
118
+ * The USER tier's status, or null when the tier is inactive (no limit and no cap).
119
+ * `preloaded` lets a caller that already holds the user's settings (e.g. the snapshot
120
+ * assembly, which reads the same row for the editable `userSettings` field) pass the
121
+ * configured limit in, so this doesn't re-read the `user_settings` row.
122
+ */
123
+ userStatus(userId: string, preloaded?: {
124
+ configuredLimit: number | null;
125
+ }): Promise<SpendStatus | null>;
126
+ /** The operator hard ceilings on the account/user tiers, for the SPA budget screens. */
127
+ budgetCaps(): BudgetCaps;
128
+ /**
129
+ * Whether this period's spend has reached ANY applicable budget tier (runs should
130
+ * pause). Always checks the workspace tier; also checks the account/user tiers when
131
+ * the caller supplies those ids (they resolve to inactive tiers cheaply otherwise).
132
+ */
133
+ isOverBudget(workspaceId: string, scope?: BudgetTierScope): Promise<boolean>;
73
134
  }
74
135
  //# sourceMappingURL=SpendService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SpendService.d.ts","sourceRoot":"","sources":["../src/SpendService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAE1D,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAA;AAC5F,OAAO,EACL,KAAK,YAAY,EAKlB,MAAM,cAAc,CAAA;AAErB,MAAM,WAAW,wBAAwB;IACvC,oBAAoB,EAAE,oBAAoB,CAAA;IAC1C,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;IACZ,mFAAmF;IACnF,OAAO,EAAE,YAAY,CAAA;IACrB;;;;;OAKG;IACH,2BAA2B,CAAC,EAAE,2BAA2B,CAAA;IACzD;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAA;CAC3E;AAED,+EAA+E;AAC/E,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,eAAe,CAAA;CACvB;AAKD;;;;;;;;;;GAUG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAsB;IAC3D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAO;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAA6B;IAC1E,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAyD;IAC3F,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgE;IAE7F,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,KAAK,EACL,OAAO,EACP,2BAA2B,EAC3B,gBAAgB,GACjB,EAAE,wBAAwB,EAO1B;IAED,mEAAmE;IACnE,OAAO,CAAC,UAAU;IAMlB;;;;OAIG;YACW,cAAc;IAW5B,4EAA4E;IAC5E,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAE3C;IAED,kEAAkE;IAC5D,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBrD;IAED,yEAAyE;IACnE,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAatD;IAED,0FAA0F;IACpF,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAKxD;CACF"}
1
+ {"version":3,"file":"SpendService.d.ts","sourceRoot":"","sources":["../src/SpendService.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { estimateCost, mergeSpendPricing, startOfMonthUtc, withDynamicPrices, } from './pricing.js';
1
+ import { effectiveTierLimit, estimateCost, mergeSpendPricing, startOfMonthUtc, withDynamicPrices, } from './pricing.js';
2
2
  /** How long a workspace's resolved pricing is cached before reloading (ms). */
3
3
  const PRICING_CACHE_TTL_MS = 30_000;
4
4
  /**
@@ -8,9 +8,12 @@ const PRICING_CACHE_TTL_MS = 30_000;
8
8
  * {@link isOverBudget} before every agent step and pauses when the budget is
9
9
  * exhausted; the worker surfaces {@link status} so the frontend can warn.
10
10
  *
11
- * Budgets are per-workspace: each workspace's currency/monthly-limit/price overrides
12
- * (on its settings row) are overlaid onto the built-in base table. Resolution is
13
- * cached briefly so the hot {@link isOverBudget} gate doesn't re-read settings per step.
11
+ * Budgets are tiered — workspace, account, and user. The workspace tier overlays the
12
+ * workspace's currency/monthly-limit overrides onto the built-in base table; the account
13
+ * and user tiers compare their own rollup against a configured limit clamped by the
14
+ * operator env cap. A run is over budget when ANY applicable tier is exhausted.
15
+ * Resolutions are cached briefly so the hot {@link isOverBudget} gate doesn't re-read
16
+ * settings per step.
14
17
  */
15
18
  export class SpendService {
16
19
  tokenUsageRepository;
@@ -18,14 +21,20 @@ export class SpendService {
18
21
  clock;
19
22
  pricing;
20
23
  workspaceSettingsRepository;
24
+ accountRepository;
25
+ userSettingsRepository;
21
26
  dynamicPricesFor;
22
27
  pricingCache = new Map();
23
- constructor({ tokenUsageRepository, idGenerator, clock, pricing, workspaceSettingsRepository, dynamicPricesFor, }) {
28
+ accountLimitCache = new Map();
29
+ userLimitCache = new Map();
30
+ constructor({ tokenUsageRepository, idGenerator, clock, pricing, workspaceSettingsRepository, accountRepository, userSettingsRepository, dynamicPricesFor, }) {
24
31
  this.tokenUsageRepository = tokenUsageRepository;
25
32
  this.idGenerator = idGenerator;
26
33
  this.clock = clock;
27
34
  this.pricing = pricing;
28
35
  this.workspaceSettingsRepository = workspaceSettingsRepository;
36
+ this.accountRepository = accountRepository;
37
+ this.userSettingsRepository = userSettingsRepository;
29
38
  this.dynamicPricesFor = dynamicPricesFor;
30
39
  }
31
40
  /** Parse a `provider:model` identifier into a {@link ModelRef}. */
@@ -56,6 +65,57 @@ export class SpendService {
56
65
  invalidatePricing(workspaceId) {
57
66
  this.pricingCache.delete(workspaceId);
58
67
  }
68
+ /** Invalidate a cached account effective limit (called after an account-budget edit). */
69
+ invalidateAccountLimit(accountId) {
70
+ this.accountLimitCache.delete(accountId);
71
+ }
72
+ /** Invalidate a cached user effective limit (called after a user-budget edit). */
73
+ invalidateUserLimit(userId) {
74
+ this.userLimitCache.delete(userId);
75
+ }
76
+ /**
77
+ * The account tier's effective monthly limit: the configured account limit clamped by
78
+ * the operator env cap. `Infinity` when the tier is inactive (neither set). Cached for
79
+ * {@link PRICING_CACHE_TTL_MS}.
80
+ */
81
+ async resolveAccountLimit(accountId) {
82
+ const cap = this.pricing.accountMonthlyLimitCap;
83
+ if (!this.accountRepository)
84
+ return effectiveTierLimit(null, cap);
85
+ const now = this.clock.now();
86
+ const cached = this.accountLimitCache.get(accountId);
87
+ let configured;
88
+ if (cached && cached.expiresAt > now) {
89
+ configured = cached.value;
90
+ }
91
+ else {
92
+ const account = await this.accountRepository.get(accountId);
93
+ configured = account?.spendMonthlyLimit ?? null;
94
+ this.accountLimitCache.set(accountId, {
95
+ value: configured,
96
+ expiresAt: now + PRICING_CACHE_TTL_MS,
97
+ });
98
+ }
99
+ return effectiveTierLimit(configured, cap);
100
+ }
101
+ /** The user tier's effective monthly limit (configured user limit clamped by the env cap). */
102
+ async resolveUserLimit(userId) {
103
+ const cap = this.pricing.userMonthlyLimitCap;
104
+ if (!this.userSettingsRepository)
105
+ return effectiveTierLimit(null, cap);
106
+ const now = this.clock.now();
107
+ const cached = this.userLimitCache.get(userId);
108
+ let configured;
109
+ if (cached && cached.expiresAt > now) {
110
+ configured = cached.value;
111
+ }
112
+ else {
113
+ const settings = await this.userSettingsRepository.get(userId);
114
+ configured = settings?.spendMonthlyLimit ?? null;
115
+ this.userLimitCache.set(userId, { value: configured, expiresAt: now + PRICING_CACHE_TTL_MS });
116
+ }
117
+ return effectiveTierLimit(configured, cap);
118
+ }
59
119
  /** Meter and persist one LLM call; returns its estimated cost. */
60
120
  async record(input) {
61
121
  const ref = this.parseModel(input.model);
@@ -69,6 +129,8 @@ export class SpendService {
69
129
  await this.tokenUsageRepository.record({
70
130
  id: this.idGenerator.next('tok'),
71
131
  workspaceId: input.workspaceId,
132
+ accountId: input.accountId ?? null,
133
+ userId: input.userId ?? null,
72
134
  executionId: input.executionId,
73
135
  agentKind: input.agentKind,
74
136
  provider: ref.provider,
@@ -80,7 +142,7 @@ export class SpendService {
80
142
  });
81
143
  return costEstimate;
82
144
  }
83
- /** The current billing period's spend against the workspace's budget. */
145
+ /** The current billing period's spend against the WORKSPACE budget. */
84
146
  async status(workspaceId) {
85
147
  const pricing = await this.resolvePricing(workspaceId);
86
148
  const periodStart = startOfMonthUtc(this.clock.now());
@@ -95,12 +157,87 @@ export class SpendService {
95
157
  exceeded: totals.costEstimate >= pricing.monthlyLimit,
96
158
  };
97
159
  }
98
- /** Whether this period's spend has reached the workspace's budget (runs should pause). */
99
- async isOverBudget(workspaceId) {
100
- const pricing = await this.resolvePricing(workspaceId);
160
+ /**
161
+ * The ACCOUNT tier's status, or null when the tier is inactive (no configured limit
162
+ * and no operator cap). `costLimit` is the effective limit (configured clamped by the
163
+ * env cap); costs are in the base pricing currency.
164
+ */
165
+ async accountStatus(accountId) {
166
+ const limit = await this.resolveAccountLimit(accountId);
167
+ if (!Number.isFinite(limit))
168
+ return null;
101
169
  const periodStart = startOfMonthUtc(this.clock.now());
102
- const totals = await this.tokenUsageRepository.totalsSinceForWorkspace(workspaceId, periodStart);
103
- return totals.costEstimate >= pricing.monthlyLimit;
170
+ const totals = await this.tokenUsageRepository.totalsSinceForAccount(accountId, periodStart);
171
+ return {
172
+ periodStart,
173
+ inputTokens: totals.inputTokens,
174
+ outputTokens: totals.outputTokens,
175
+ costSpent: totals.costEstimate,
176
+ costLimit: limit,
177
+ currency: this.pricing.currency,
178
+ exceeded: totals.costEstimate >= limit,
179
+ };
180
+ }
181
+ /**
182
+ * The USER tier's status, or null when the tier is inactive (no limit and no cap).
183
+ * `preloaded` lets a caller that already holds the user's settings (e.g. the snapshot
184
+ * assembly, which reads the same row for the editable `userSettings` field) pass the
185
+ * configured limit in, so this doesn't re-read the `user_settings` row.
186
+ */
187
+ async userStatus(userId, preloaded) {
188
+ const limit = preloaded
189
+ ? effectiveTierLimit(preloaded.configuredLimit, this.pricing.userMonthlyLimitCap)
190
+ : await this.resolveUserLimit(userId);
191
+ if (!Number.isFinite(limit))
192
+ return null;
193
+ const periodStart = startOfMonthUtc(this.clock.now());
194
+ const totals = await this.tokenUsageRepository.totalsSinceForUser(userId, periodStart);
195
+ return {
196
+ periodStart,
197
+ inputTokens: totals.inputTokens,
198
+ outputTokens: totals.outputTokens,
199
+ costSpent: totals.costEstimate,
200
+ costLimit: limit,
201
+ currency: this.pricing.currency,
202
+ exceeded: totals.costEstimate >= limit,
203
+ };
204
+ }
205
+ /** The operator hard ceilings on the account/user tiers, for the SPA budget screens. */
206
+ budgetCaps() {
207
+ return {
208
+ accountMonthlyLimitMax: this.pricing.accountMonthlyLimitCap ?? null,
209
+ userMonthlyLimitMax: this.pricing.userMonthlyLimitCap ?? null,
210
+ currency: this.pricing.currency,
211
+ };
212
+ }
213
+ /**
214
+ * Whether this period's spend has reached ANY applicable budget tier (runs should
215
+ * pause). Always checks the workspace tier; also checks the account/user tiers when
216
+ * the caller supplies those ids (they resolve to inactive tiers cheaply otherwise).
217
+ */
218
+ async isOverBudget(workspaceId, scope = {}) {
219
+ const periodStart = startOfMonthUtc(this.clock.now());
220
+ const pricing = await this.resolvePricing(workspaceId);
221
+ const workspaceTotals = await this.tokenUsageRepository.totalsSinceForWorkspace(workspaceId, periodStart);
222
+ if (workspaceTotals.costEstimate >= pricing.monthlyLimit)
223
+ return true;
224
+ if (scope.accountId) {
225
+ const limit = await this.resolveAccountLimit(scope.accountId);
226
+ if (Number.isFinite(limit)) {
227
+ const totals = await this.tokenUsageRepository.totalsSinceForAccount(scope.accountId, periodStart);
228
+ if (totals.costEstimate >= limit)
229
+ return true;
230
+ }
231
+ }
232
+ if (scope.userId) {
233
+ const limit = await this.resolveUserLimit(scope.userId);
234
+ if (Number.isFinite(limit)) {
235
+ const totals = await this.tokenUsageRepository.totalsSinceForUser(scope.userId, periodStart);
236
+ if (totals.costEstimate >= limit)
237
+ return true;
238
+ }
239
+ }
240
+ return false;
104
241
  }
105
242
  }
106
243
  //# sourceMappingURL=SpendService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SpendService.js","sourceRoot":"","sources":["../src/SpendService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SpendService.js","sourceRoot":"","sources":["../src/SpendService.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { SpendService, type SpendServiceDependencies, type RecordUsageInput, } from './SpendService.js';
2
- export { type ModelPrice, type SpendPricing, DEFAULT_MODEL_PRICES, DEFAULT_MONTHLY_LIMIT_EUR, DEFAULT_SPEND_PRICING, priceFor, modelCostResolver, estimateCost, withDynamicPrices, startOfMonthUtc, } from './pricing.js';
1
+ export { SpendService, type SpendServiceDependencies, type RecordUsageInput, type BudgetTierScope, } from './SpendService.js';
2
+ export { type ModelPrice, type SpendPricing, DEFAULT_MODEL_PRICES, DEFAULT_MONTHLY_LIMIT_EUR, DEFAULT_SPEND_PRICING, budgetCapsOverlay, effectiveTierLimit, priceFor, modelCostResolver, estimateCost, withDynamicPrices, startOfMonthUtc, } from './pricing.js';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,QAAQ,EACR,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,eAAe,GAChB,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,eAAe,GAChB,MAAM,cAAc,CAAA"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // Pricing tables and spend metering/gating for @cat-factory.
2
2
  export { SpendService, } from './SpendService.js';
3
- export { DEFAULT_MODEL_PRICES, DEFAULT_MONTHLY_LIMIT_EUR, DEFAULT_SPEND_PRICING, priceFor, modelCostResolver, estimateCost, withDynamicPrices, startOfMonthUtc, } from './pricing.js';
3
+ export { DEFAULT_MODEL_PRICES, DEFAULT_MONTHLY_LIMIT_EUR, DEFAULT_SPEND_PRICING, budgetCapsOverlay, effectiveTierLimit, priceFor, modelCostResolver, estimateCost, withDynamicPrices, startOfMonthUtc, } from './pricing.js';
4
4
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D,OAAO,EACL,YAAY,GAGb,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAGL,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,QAAQ,EACR,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,eAAe,GAChB,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D,OAAO,EACL,YAAY,GAIb,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAGL,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,eAAe,GAChB,MAAM,cAAc,CAAA"}
package/dist/pricing.d.ts CHANGED
@@ -15,7 +15,27 @@ export interface SpendPricing {
15
15
  prices: Record<string, ModelPrice>;
16
16
  /** Fallback price for any model without a specific or provider-level entry. */
17
17
  defaultPrice: ModelPrice;
18
+ /**
19
+ * Operator hard ceiling on the ACCOUNT-tier monthly budget, from the deployment env
20
+ * var `BUDGET_MAX_MONTHLY_PER_ACCOUNT`. Undefined ⇒ no operator ceiling. When set it
21
+ * caps whatever value the UI submits AND acts as the effective account budget when no
22
+ * account limit is configured. See the tiered-budgets initiative.
23
+ */
24
+ accountMonthlyLimitCap?: number;
25
+ /**
26
+ * Operator hard ceiling on the USER-tier monthly budget, from the deployment env var
27
+ * `BUDGET_MAX_MONTHLY_PER_USER`. Undefined ⇒ no operator ceiling. Same double duty as
28
+ * {@link accountMonthlyLimitCap}.
29
+ */
30
+ userMonthlyLimitCap?: number;
18
31
  }
32
+ /**
33
+ * The effective monthly limit for a budget tier: the smaller of the tier's configured
34
+ * limit and the operator env cap, treating an absent value as "no constraint". Returns
35
+ * `Infinity` when neither is set — the tier is inactive and never gates. `0` is a real
36
+ * limit ("no paid spend"), not "absent", so it is respected.
37
+ */
38
+ export declare function effectiveTierLimit(configured: number | null | undefined, cap: number | null | undefined): number;
19
39
  /**
20
40
  * Built-in approximate EUR prices per 1M tokens. Keys are matched most-specific
21
41
  * first: exact `provider:model`, then the bare `provider`, then `defaultPrice`.
@@ -58,6 +78,13 @@ export declare function modelCostResolver(pricing: SpendPricing): (ref: ModelRef
58
78
  };
59
79
  /** Cost of a single call's token usage, in the pricing currency. */
60
80
  export declare function estimateCost(pricing: SpendPricing, ref: ModelRef, usage: AgentTokenUsage): number;
81
+ /**
82
+ * Build the env-driven operator budget-cap overlay for a {@link SpendPricing}. Each cap
83
+ * is applied only when it is a non-negative number; a missing/invalid value leaves that
84
+ * tier uncapped. Shared by the Node and Cloudflare config loaders so both runtimes read
85
+ * `BUDGET_MAX_MONTHLY_PER_ACCOUNT` / `BUDGET_MAX_MONTHLY_PER_USER` identically.
86
+ */
87
+ export declare function budgetCapsOverlay(accountCap: number | undefined, userCap: number | undefined): Partial<Pick<SpendPricing, 'accountMonthlyLimitCap' | 'userMonthlyLimitCap'>>;
61
88
  /** Start of the calendar month containing `epochMs`, in UTC (epoch ms). */
62
89
  export declare function startOfMonthUtc(epochMs: number): number;
63
90
  //# sourceMappingURL=pricing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAWpF,sDAAsD;AACtD,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAA;IAChB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAA;IACpB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IAClC,+EAA+E;IAC/E,YAAY,EAAE,UAAU,CAAA;CACzB;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAoD3D,CAAA;AAED,oEAAoE;AACpE,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C,eAAO,MAAM,qBAAqB,EAAE,YAKnC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,mBAAmB,EAAE,GAC5B,YAAY,CAWd;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,GAAG,mBAAmB,CAAC,GAAG,IAAI,GAC/E,YAAY,CAQd;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,GAAG,UAAU,CAMzE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,YAAY,GACpB,CAAC,GAAG,EAAE,QAAQ,KAAK;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAS5F;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,GAAG,MAAM,CAMjG;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGvD"}
1
+ {"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAWpF,sDAAsD;AACtD,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAA;IAChB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAA;IACpB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IAClC,+EAA+E;IAC/E,YAAY,EAAE,UAAU,CAAA;IACxB;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACrC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC7B,MAAM,CAKR;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAoD3D,CAAA;AAED,oEAAoE;AACpE,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C,eAAO,MAAM,qBAAqB,EAAE,YAKnC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,mBAAmB,EAAE,GAC5B,YAAY,CAWd;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,GAAG,mBAAmB,CAAC,GAAG,IAAI,GAC/E,YAAY,CASd;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,GAAG,UAAU,CAMzE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,YAAY,GACpB,CAAC,GAAG,EAAE,QAAQ,KAAK;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAS5F;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,GAAG,MAAM,CAMjG;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,wBAAwB,GAAG,qBAAqB,CAAC,CAAC,CAS/E;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGvD"}
package/dist/pricing.js CHANGED
@@ -1,3 +1,17 @@
1
+ /**
2
+ * The effective monthly limit for a budget tier: the smaller of the tier's configured
3
+ * limit and the operator env cap, treating an absent value as "no constraint". Returns
4
+ * `Infinity` when neither is set — the tier is inactive and never gates. `0` is a real
5
+ * limit ("no paid spend"), not "absent", so it is respected.
6
+ */
7
+ export function effectiveTierLimit(configured, cap) {
8
+ const values = [];
9
+ if (configured != null)
10
+ values.push(configured);
11
+ if (cap != null)
12
+ values.push(cap);
13
+ return values.length > 0 ? Math.min(...values) : Number.POSITIVE_INFINITY;
14
+ }
1
15
  /**
2
16
  * Built-in approximate EUR prices per 1M tokens. Keys are matched most-specific
3
17
  * first: exact `provider:model`, then the bare `provider`, then `defaultPrice`.
@@ -100,6 +114,7 @@ export function mergeSpendPricing(base, overrides) {
100
114
  if (!overrides)
101
115
  return base;
102
116
  return {
117
+ ...base,
103
118
  currency: overrides.spendCurrency ?? base.currency,
104
119
  monthlyLimit: overrides.spendMonthlyLimit ?? base.monthlyLimit,
105
120
  prices: base.prices,
@@ -132,6 +147,22 @@ export function estimateCost(pricing, ref, usage) {
132
147
  return ((usage.inputTokens / 1_000_000) * price.inputPerMillion +
133
148
  (usage.outputTokens / 1_000_000) * price.outputPerMillion);
134
149
  }
150
+ /**
151
+ * Build the env-driven operator budget-cap overlay for a {@link SpendPricing}. Each cap
152
+ * is applied only when it is a non-negative number; a missing/invalid value leaves that
153
+ * tier uncapped. Shared by the Node and Cloudflare config loaders so both runtimes read
154
+ * `BUDGET_MAX_MONTHLY_PER_ACCOUNT` / `BUDGET_MAX_MONTHLY_PER_USER` identically.
155
+ */
156
+ export function budgetCapsOverlay(accountCap, userCap) {
157
+ const overlay = {};
158
+ if (accountCap != null && Number.isFinite(accountCap) && accountCap >= 0) {
159
+ overlay.accountMonthlyLimitCap = accountCap;
160
+ }
161
+ if (userCap != null && Number.isFinite(userCap) && userCap >= 0) {
162
+ overlay.userMonthlyLimitCap = userCap;
163
+ }
164
+ return overlay;
165
+ }
135
166
  /** Start of the calendar month containing `epochMs`, in UTC (epoch ms). */
136
167
  export function startOfMonthUtc(epochMs) {
137
168
  const d = new Date(epochMs);
@@ -1 +1 @@
1
- {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"AA8BA;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAA+B;IAC9D,wEAAwE;IACxE,2BAA2B,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,gBAAgB,EAAE,EAAE,EAAE;IAC3E,6BAA6B,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE;IAChF,4BAA4B,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE;IAC9E,SAAS,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE;IAC5D,mDAAmD;IACnD,eAAe,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE;IAChE,oBAAoB,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE;IACvE,gFAAgF;IAChF,sBAAsB,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE;IACxE,sBAAsB,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE;IACxE,MAAM,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE;IACzD,0EAA0E;IAC1E,YAAY,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE;IAC7D,+EAA+E;IAC/E,iFAAiF;IACjF,8CAA8C;IAC9C,qCAAqC,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC,EAAE;IACpF,yFAAyF;IACzF,sFAAsF;IACtF,sFAAsF;IACtF,yFAAyF;IACzF,oFAAoF;IACpF,wFAAwF;IACxF,8EAA8E;IAC9E,+BAA+B;IAC/B,qCAAqC,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE;IACxF,qCAAqC,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE;IACxF,0CAA0C,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE;IAC7F,2EAA2E;IAC3E,wBAAwB,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE;IAC3E,QAAQ,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE;IAC3D,wEAAwE;IACxE,gBAAgB,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE;IACjE,IAAI,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE;IACrD,yEAAyE;IACzE,oBAAoB,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE;IACtE,QAAQ,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE;IAC1D,mFAAmF;IACnF,oFAAoF;IACpF,sFAAsF;IACtF,2DAA2D;IAC3D,sCAAsC,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,gBAAgB,EAAE,EAAE,EAAE;IACtF,gCAAgC,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE;IACpF,2BAA2B,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE;IAC/E,mCAAmC,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE;IACtF,sCAAsC,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE;IACxF,UAAU,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE;IAC9D,uFAAuF;IACvF,sFAAsF;IACtF,OAAO,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE;CAC3D,CAAA;AAED,oEAAoE;AACpE,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAA;AAE5C,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,yBAAyB;IACvC,MAAM,EAAE,oBAAoB;IAC5B,YAAY,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE;CAChE,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAqB,EACrB,MAA6B;IAE7B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAA;IACvC,MAAM,MAAM,GAA+B,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAA;IAChE,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,CAAC,gBAAgB,IAAI,CAAC;YAAE,SAAQ;QAC/D,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG;YAC7B,eAAe,EAAE,CAAC,CAAC,eAAe;YAClC,gBAAgB,EAAE,CAAC,CAAC,gBAAgB;SACrC,CAAA;IACH,CAAC;IACD,OAAO,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAA;AAC/B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAkB,EAClB,SAAgF;IAEhF,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAA;IAC3B,OAAO;QACL,QAAQ,EAAE,SAAS,CAAC,aAAa,IAAI,IAAI,CAAC,QAAQ;QAClD,YAAY,EAAE,SAAS,CAAC,iBAAiB,IAAI,IAAI,CAAC,YAAY;QAC9D,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,YAAY,EAAE,IAAI,CAAC,YAAY;KAChC,CAAA;AACH,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,QAAQ,CAAC,OAAqB,EAAE,GAAa;IAC3D,OAAO,CACL,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QAC9C,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC5B,OAAO,CAAC,YAAY,CACrB,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAqB;IAErB,OAAO,CAAC,GAAG,EAAE,EAAE;QACb,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;QACpC,OAAO;YACL,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;YACxC,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAA;IACH,CAAC,CAAA;AACH,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,OAAqB,EAAE,GAAa,EAAE,KAAsB;IACvF,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;IACpC,OAAO,CACL,CAAC,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,eAAe;QACvD,CAAC,KAAK,CAAC,YAAY,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAC1D,CAAA;AACH,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAA;IAC3B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAA;AACzD,CAAC"}
1
+ {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/spend",
3
- "version": "0.10.109",
3
+ "version": "0.11.1",
4
4
  "description": "Pricing tables and spend metering for the Agent Architecture Board.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,8 +24,8 @@
24
24
  "access": "public"
25
25
  },
26
26
  "dependencies": {
27
- "@cat-factory/contracts": "0.108.1",
28
- "@cat-factory/kernel": "0.99.1"
27
+ "@cat-factory/contracts": "0.110.0",
28
+ "@cat-factory/kernel": "0.101.0"
29
29
  },
30
30
  "devDependencies": {
31
31
  "typescript": "7.0.1-rc"