@bymax-one/nest-ai-tokens 1.1.1 → 1.1.2
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/CHANGELOG.md +32 -2
- package/dist/server/index.cjs +6 -6
- package/dist/server/index.d.cts +6 -6
- package/dist/server/index.d.ts +6 -6
- package/dist/server/index.mjs +6 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,35 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [Unreleased]
|
|
10
|
+
|
|
11
|
+
## [1.1.2] - 2026-10-30
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **`PricingService.resolveRate` no longer serves one request's price to another.** The
|
|
16
|
+
resolution cache key joined provider, model, baseModel, operation, tier and time bucket
|
|
17
|
+
with `|`, which can also appear inside a model id. Two different requests could spell the
|
|
18
|
+
same key — `model: 'b|c'` with no `baseModel` against `model: 'b'` with `baseModel: 'c|'` —
|
|
19
|
+
and the second received the first's rate from the cache. The key is now a JSON array of
|
|
20
|
+
the fields, so no value can move the boundary between them. (#117)
|
|
21
|
+
|
|
22
|
+
**Apply:** no action required. Requests whose model names contain `|` now resolve their
|
|
23
|
+
own price instead of a colliding entry's.
|
|
24
|
+
|
|
25
|
+
### Security
|
|
26
|
+
|
|
27
|
+
- Advisories on transitive **dev** packages are cleared through `pnpm-workspace.yaml`
|
|
28
|
+
overrides: body-parser, multer, qs and zod (#115). deepmerge GHSA-gcqx-w48m-w2h4 has no
|
|
29
|
+
patched release and is reached only through `jest-config`, so it is ignored in
|
|
30
|
+
`osv-scanner.toml` until 2027-01-27. None of these reach a consumer install: the package
|
|
31
|
+
has no runtime dependencies.
|
|
32
|
+
|
|
33
|
+
### Documentation
|
|
34
|
+
|
|
35
|
+
- `SECURITY.md`: only the latest minor line (1.1.x) receives security fixes; 1.0.x is
|
|
36
|
+
unsupported and consumers should upgrade.
|
|
37
|
+
|
|
9
38
|
## [1.1.1] - 2026-10-23
|
|
10
39
|
|
|
11
40
|
### Fixed
|
|
@@ -62,7 +91,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and
|
|
|
62
91
|
|
|
63
92
|
## [1.0.4] - 2026-08-10
|
|
64
93
|
|
|
65
|
-
Remediation of a local audit's settlement findings (merged in #65). No API
|
|
94
|
+
Remediation of a local audit's settlement findings (merged in #65). No API changes.
|
|
66
95
|
|
|
67
96
|
### Fixed
|
|
68
97
|
|
|
@@ -267,7 +296,8 @@ have regressed from. They are kept because the reasoning is worth having.
|
|
|
267
296
|
[1.0.1]: https://github.com/bymaxone/nest-ai-tokens/compare/v1.0.0...v1.0.1
|
|
268
297
|
[1.0.2]: https://github.com/bymaxone/nest-ai-tokens/compare/v1.0.1...v1.0.2
|
|
269
298
|
[1.1.0]: https://github.com/bymaxone/nest-ai-tokens/compare/v1.0.4...v1.1.0
|
|
299
|
+
[1.1.2]: https://github.com/bymaxone/nest-ai-tokens/compare/v1.1.1...v1.1.2
|
|
270
300
|
[1.1.1]: https://github.com/bymaxone/nest-ai-tokens/compare/v1.1.0...v1.1.1
|
|
271
301
|
[1.0.4]: https://github.com/bymaxone/nest-ai-tokens/compare/v1.0.3...v1.0.4
|
|
272
302
|
[1.0.3]: https://github.com/bymaxone/nest-ai-tokens/compare/v1.0.2...v1.0.3
|
|
273
|
-
[Unreleased]: https://github.com/bymaxone/nest-ai-tokens/compare/v1.1.
|
|
303
|
+
[Unreleased]: https://github.com/bymaxone/nest-ai-tokens/compare/v1.1.2...HEAD
|
package/dist/server/index.cjs
CHANGED
|
@@ -1224,7 +1224,7 @@ exports.PricingService = class PricingService {
|
|
|
1224
1224
|
const serviceTier = input.serviceTier ?? "standard";
|
|
1225
1225
|
const operation = input.operation === "responses" ? "chat" : input.operation;
|
|
1226
1226
|
const bucket = Math.floor(input.at.getTime() / this.options.pricing.cacheTtlMs);
|
|
1227
|
-
const cacheKey =
|
|
1227
|
+
const cacheKey = JSON.stringify([input.provider, input.model, input.baseModel, operation, serviceTier, bucket]);
|
|
1228
1228
|
let resolved;
|
|
1229
1229
|
const cached = this.cache.get(cacheKey);
|
|
1230
1230
|
if (cached !== void 0 && this.now() < cached.expiresAt) {
|
|
@@ -2775,10 +2775,10 @@ exports.WalletService = class WalletService {
|
|
|
2775
2775
|
options;
|
|
2776
2776
|
events;
|
|
2777
2777
|
/**
|
|
2778
|
-
* The current balance
|
|
2779
|
-
*
|
|
2780
|
-
*
|
|
2781
|
-
*
|
|
2778
|
+
* The current balance (§9.2). Reads the materialized balance; expiry is applied
|
|
2779
|
+
* lazily on debit, so a grant that lapses purely with the passage of time is still
|
|
2780
|
+
* counted until the next debit or `reconcile` (the documented §9.3
|
|
2781
|
+
* lazy-materialization trade-off).
|
|
2782
2782
|
*
|
|
2783
2783
|
* @param ref The wallet owner (a `'tenant' | 'team' | 'user'`, never `'key'`).
|
|
2784
2784
|
* @returns The nano-USD balance and its presentation credits.
|
|
@@ -2965,7 +2965,7 @@ exports.WalletService = class WalletService {
|
|
|
2965
2965
|
* `ai_tokens.audit`.
|
|
2966
2966
|
*
|
|
2967
2967
|
* @param ref The wallet owner.
|
|
2968
|
-
* @returns The reconciled
|
|
2968
|
+
* @returns The reconciled nano-USD balance and its presentation credits.
|
|
2969
2969
|
*/
|
|
2970
2970
|
async reconcile(ref) {
|
|
2971
2971
|
this.assertOwner(ref);
|
package/dist/server/index.d.cts
CHANGED
|
@@ -2224,10 +2224,10 @@ declare class WalletService {
|
|
|
2224
2224
|
*/
|
|
2225
2225
|
constructor(store: IWalletStore, options: WalletServiceOptions, events?: WalletEventHooks);
|
|
2226
2226
|
/**
|
|
2227
|
-
* The current balance
|
|
2228
|
-
*
|
|
2229
|
-
*
|
|
2230
|
-
*
|
|
2227
|
+
* The current balance (§9.2). Reads the materialized balance; expiry is applied
|
|
2228
|
+
* lazily on debit, so a grant that lapses purely with the passage of time is still
|
|
2229
|
+
* counted until the next debit or `reconcile` (the documented §9.3
|
|
2230
|
+
* lazy-materialization trade-off).
|
|
2231
2231
|
*
|
|
2232
2232
|
* @param ref The wallet owner (a `'tenant' | 'team' | 'user'`, never `'key'`).
|
|
2233
2233
|
* @returns The nano-USD balance and its presentation credits.
|
|
@@ -2306,7 +2306,7 @@ declare class WalletService {
|
|
|
2306
2306
|
* `ai_tokens.audit`.
|
|
2307
2307
|
*
|
|
2308
2308
|
* @param ref The wallet owner.
|
|
2309
|
-
* @returns The reconciled
|
|
2309
|
+
* @returns The reconciled nano-USD balance and its presentation credits.
|
|
2310
2310
|
*/
|
|
2311
2311
|
reconcile(ref: WalletRef): Promise<WalletBalance>;
|
|
2312
2312
|
/** Append a non-debit entry, mapping a store idempotency/missing-wallet signal to the catalog. */
|
|
@@ -3119,7 +3119,7 @@ declare class MeteringInterceptor implements NestInterceptor {
|
|
|
3119
3119
|
* @fileoverview The controller-level metering/enforcement decorators (spec §11.4).
|
|
3120
3120
|
* `@Meter` marks a handler for the `MeteringInterceptor` and is metadata-only
|
|
3121
3121
|
* here; `@RequireBudget` marks it for the `BudgetGuard`; `@AiFeature`
|
|
3122
|
-
* is a lightweight feature tag. Each stores its config under an exported
|
|
3122
|
+
* is a lightweight feature tag. Each stores its config under an exported string key
|
|
3123
3123
|
* that the guard/interceptor read via the NestJS `Reflector`. Feature precedence is
|
|
3124
3124
|
* `@RequireBudget.feature` > `@Meter.feature` > `@AiFeature` (§11.4). These are pure
|
|
3125
3125
|
* metadata; they never touch a wallet, budget, or the request.
|
package/dist/server/index.d.ts
CHANGED
|
@@ -2224,10 +2224,10 @@ declare class WalletService {
|
|
|
2224
2224
|
*/
|
|
2225
2225
|
constructor(store: IWalletStore, options: WalletServiceOptions, events?: WalletEventHooks);
|
|
2226
2226
|
/**
|
|
2227
|
-
* The current balance
|
|
2228
|
-
*
|
|
2229
|
-
*
|
|
2230
|
-
*
|
|
2227
|
+
* The current balance (§9.2). Reads the materialized balance; expiry is applied
|
|
2228
|
+
* lazily on debit, so a grant that lapses purely with the passage of time is still
|
|
2229
|
+
* counted until the next debit or `reconcile` (the documented §9.3
|
|
2230
|
+
* lazy-materialization trade-off).
|
|
2231
2231
|
*
|
|
2232
2232
|
* @param ref The wallet owner (a `'tenant' | 'team' | 'user'`, never `'key'`).
|
|
2233
2233
|
* @returns The nano-USD balance and its presentation credits.
|
|
@@ -2306,7 +2306,7 @@ declare class WalletService {
|
|
|
2306
2306
|
* `ai_tokens.audit`.
|
|
2307
2307
|
*
|
|
2308
2308
|
* @param ref The wallet owner.
|
|
2309
|
-
* @returns The reconciled
|
|
2309
|
+
* @returns The reconciled nano-USD balance and its presentation credits.
|
|
2310
2310
|
*/
|
|
2311
2311
|
reconcile(ref: WalletRef): Promise<WalletBalance>;
|
|
2312
2312
|
/** Append a non-debit entry, mapping a store idempotency/missing-wallet signal to the catalog. */
|
|
@@ -3119,7 +3119,7 @@ declare class MeteringInterceptor implements NestInterceptor {
|
|
|
3119
3119
|
* @fileoverview The controller-level metering/enforcement decorators (spec §11.4).
|
|
3120
3120
|
* `@Meter` marks a handler for the `MeteringInterceptor` and is metadata-only
|
|
3121
3121
|
* here; `@RequireBudget` marks it for the `BudgetGuard`; `@AiFeature`
|
|
3122
|
-
* is a lightweight feature tag. Each stores its config under an exported
|
|
3122
|
+
* is a lightweight feature tag. Each stores its config under an exported string key
|
|
3123
3123
|
* that the guard/interceptor read via the NestJS `Reflector`. Feature precedence is
|
|
3124
3124
|
* `@RequireBudget.feature` > `@Meter.feature` > `@AiFeature` (§11.4). These are pure
|
|
3125
3125
|
* metadata; they never touch a wallet, budget, or the request.
|
package/dist/server/index.mjs
CHANGED
|
@@ -1222,7 +1222,7 @@ var PricingService = class {
|
|
|
1222
1222
|
const serviceTier = input.serviceTier ?? "standard";
|
|
1223
1223
|
const operation = input.operation === "responses" ? "chat" : input.operation;
|
|
1224
1224
|
const bucket = Math.floor(input.at.getTime() / this.options.pricing.cacheTtlMs);
|
|
1225
|
-
const cacheKey =
|
|
1225
|
+
const cacheKey = JSON.stringify([input.provider, input.model, input.baseModel, operation, serviceTier, bucket]);
|
|
1226
1226
|
let resolved;
|
|
1227
1227
|
const cached = this.cache.get(cacheKey);
|
|
1228
1228
|
if (cached !== void 0 && this.now() < cached.expiresAt) {
|
|
@@ -2773,10 +2773,10 @@ var WalletService = class {
|
|
|
2773
2773
|
options;
|
|
2774
2774
|
events;
|
|
2775
2775
|
/**
|
|
2776
|
-
* The current balance
|
|
2777
|
-
*
|
|
2778
|
-
*
|
|
2779
|
-
*
|
|
2776
|
+
* The current balance (§9.2). Reads the materialized balance; expiry is applied
|
|
2777
|
+
* lazily on debit, so a grant that lapses purely with the passage of time is still
|
|
2778
|
+
* counted until the next debit or `reconcile` (the documented §9.3
|
|
2779
|
+
* lazy-materialization trade-off).
|
|
2780
2780
|
*
|
|
2781
2781
|
* @param ref The wallet owner (a `'tenant' | 'team' | 'user'`, never `'key'`).
|
|
2782
2782
|
* @returns The nano-USD balance and its presentation credits.
|
|
@@ -2963,7 +2963,7 @@ var WalletService = class {
|
|
|
2963
2963
|
* `ai_tokens.audit`.
|
|
2964
2964
|
*
|
|
2965
2965
|
* @param ref The wallet owner.
|
|
2966
|
-
* @returns The reconciled
|
|
2966
|
+
* @returns The reconciled nano-USD balance and its presentation credits.
|
|
2967
2967
|
*/
|
|
2968
2968
|
async reconcile(ref) {
|
|
2969
2969
|
this.assertOwner(ref);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bymax-one/nest-ai-tokens",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "AI token metering & usage-based billing for NestJS 11: provider usage normalizer (×9), versioned effective-dated pricing, immutable append-only ledger, prepaid wallets, multi-dimension budgets, and markup/margin. Zero runtime dependencies.",
|
|
5
5
|
"author": "Bymax One <support@bymax.one>",
|
|
6
6
|
"license": "MIT",
|