@bymax-one/nest-ai-tokens 1.0.2 → 1.0.3
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 +31 -1
- package/README.md +5 -3
- package/dist/prisma/index.cjs +1 -1
- package/dist/prisma/index.mjs +1 -1
- package/dist/server/index.cjs +71 -71
- package/dist/server/index.mjs +71 -71
- package/dist/shared/index.cjs +2 -2
- package/dist/shared/index.mjs +2 -2
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,35 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [1.0.3] - 2026-08-06
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **Every suppression reason was dropped from the mutation report.** All 249 `// Stryker
|
|
16
|
+
disable` directives in the source wrote their justification after `--`. Stryker reads a
|
|
17
|
+
directive with one regular expression, `/^\s?Stryker (disable|restore)(?: (next-line))?
|
|
18
|
+
([a-zA-Z, ]+)(?::(.+)?)?/`, whose mutator list accepts letters, commas and spaces only
|
|
19
|
+
and which captures the reason exclusively after a colon. A `-` therefore closed the
|
|
20
|
+
mutator list and left the reason unmatched, so each directive still silenced its mutant
|
|
21
|
+
but the report recorded Stryker's fallback text, `Ignored using a comment`. The README
|
|
22
|
+
claimed the opposite — that every suppression carries its reason — and documented the
|
|
23
|
+
broken separator as the convention. The directives now use `<Mutator>: <reason>`, which
|
|
24
|
+
is the grammar the parser accepts, and the reasons reach the report.
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- `check:mutants` gate (`scripts/check-mutation-directives.mjs`) — validates every
|
|
29
|
+
`// Stryker` comment against the parser's own regular expression, rejecting a reason
|
|
30
|
+
written after `--`, a reason wrapped onto a second comment line (the report keeps only
|
|
31
|
+
the first fragment), and a mutator name Stryker does not know, which would silence
|
|
32
|
+
nothing at all. Wired into CI and `prepublishOnly`. Stryker warns about the last case,
|
|
33
|
+
but only during a mutation run, which on this repo happens post-merge.
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- No runtime behaviour changed. `dist/` differs only in the text of those comments; the
|
|
38
|
+
server bundle moved from 38,096 to 38,145 B brotli, well inside its 40,000 B budget.
|
|
39
|
+
|
|
11
40
|
## [1.0.2] - 2026-08-05
|
|
12
41
|
|
|
13
42
|
### Fixed
|
|
@@ -164,4 +193,5 @@ have regressed from. They are kept because the reasoning is worth having.
|
|
|
164
193
|
[1.0.0]: https://github.com/bymaxone/nest-ai-tokens/releases/tag/v1.0.0
|
|
165
194
|
[1.0.1]: https://github.com/bymaxone/nest-ai-tokens/compare/v1.0.0...v1.0.1
|
|
166
195
|
[1.0.2]: https://github.com/bymaxone/nest-ai-tokens/compare/v1.0.1...v1.0.2
|
|
167
|
-
[
|
|
196
|
+
[1.0.3]: https://github.com/bymaxone/nest-ai-tokens/compare/v1.0.2...v1.0.3
|
|
197
|
+
[Unreleased]: https://github.com/bymaxone/nest-ai-tokens/compare/v1.0.3...HEAD
|
package/README.md
CHANGED
|
@@ -742,9 +742,11 @@ tests pass".
|
|
|
742
742
|
system does, `check:runtime` loads every subpath from the packed tarball in ESM and
|
|
743
743
|
CommonJS, and `check:published` compiles this README's snippets against `dist/`
|
|
744
744
|
- ✅ **Every suppression carries its reason** — no coverage directives anywhere; each
|
|
745
|
-
`// Stryker disable` in the production source states, after
|
|
746
|
-
silences is unobservable from a unit test (an internal error
|
|
747
|
-
reached only through integration)
|
|
745
|
+
`// Stryker disable` in the production source states, after the `:` Stryker reads it
|
|
746
|
+
from, why the mutant it silences is unobservable from a unit test (an internal error
|
|
747
|
+
context, a provider id reached only through integration). `check:mutants` proves the
|
|
748
|
+
reasons parse, so they reach the mutation report instead of being replaced by
|
|
749
|
+
Stryker's `Ignored using a comment` fallback
|
|
748
750
|
|
|
749
751
|
```bash
|
|
750
752
|
pnpm test # unit tests
|
package/dist/prisma/index.cjs
CHANGED
|
@@ -276,7 +276,7 @@ function computePayloadHash(record) {
|
|
|
276
276
|
// src/server/utils/hash-chain.ts
|
|
277
277
|
function chainHash(prevHash, record) {
|
|
278
278
|
return deriveIdempotencyKey({
|
|
279
|
-
// Stryker disable next-line StringLiteral
|
|
279
|
+
// Stryker disable next-line StringLiteral: empty-string fallback for null prevHash; tests only verify hash determinism and inequality, not the specific hash value for a genesis block
|
|
280
280
|
prevHash: prevHash ?? "",
|
|
281
281
|
id: record.id,
|
|
282
282
|
content: computePayloadHash(record)
|
package/dist/prisma/index.mjs
CHANGED
|
@@ -274,7 +274,7 @@ function computePayloadHash(record) {
|
|
|
274
274
|
// src/server/utils/hash-chain.ts
|
|
275
275
|
function chainHash(prevHash, record) {
|
|
276
276
|
return deriveIdempotencyKey({
|
|
277
|
-
// Stryker disable next-line StringLiteral
|
|
277
|
+
// Stryker disable next-line StringLiteral: empty-string fallback for null prevHash; tests only verify hash determinism and inequality, not the specific hash value for a genesis block
|
|
278
278
|
prevHash: prevHash ?? "",
|
|
279
279
|
id: record.id,
|
|
280
280
|
content: computePayloadHash(record)
|
package/dist/server/index.cjs
CHANGED
|
@@ -362,9 +362,9 @@ function normalizeMistralUsage(raw) {
|
|
|
362
362
|
provider: "mistral",
|
|
363
363
|
model: str(response.model) ?? "",
|
|
364
364
|
operation: "chat",
|
|
365
|
-
// Stryker disable next-line StringLiteral
|
|
365
|
+
// Stryker disable next-line StringLiteral: provider and field names in error messages are internal diagnostics
|
|
366
366
|
inputTokens: requireNum(usage.prompt_tokens, "mistral", "usage.prompt_tokens"),
|
|
367
|
-
// Stryker disable next-line StringLiteral
|
|
367
|
+
// Stryker disable next-line StringLiteral: provider and field names in error messages are internal diagnostics
|
|
368
368
|
outputTokens: requireNum(usage.completion_tokens, "mistral", "usage.completion_tokens"),
|
|
369
369
|
raw: usage
|
|
370
370
|
});
|
|
@@ -808,7 +808,7 @@ function validatePricing(options) {
|
|
|
808
808
|
if (cacheTtlMs === void 0) return;
|
|
809
809
|
if (!Number.isInteger(cacheTtlMs) || cacheTtlMs <= 0) {
|
|
810
810
|
throw invalidConfig(
|
|
811
|
-
// Stryker disable next-line StringLiteral
|
|
811
|
+
// Stryker disable next-line StringLiteral: error reason template is internal diagnostics
|
|
812
812
|
`pricing.cacheTtlMs must be a positive integer number of milliseconds, received ${String(cacheTtlMs)}`
|
|
813
813
|
);
|
|
814
814
|
}
|
|
@@ -1128,7 +1128,7 @@ exports.BudgetGuard = class BudgetGuard {
|
|
|
1128
1128
|
this.reflector = reflector;
|
|
1129
1129
|
if (options.scopeResolver === void 0) {
|
|
1130
1130
|
throw new AiTokensException("AI_TOKENS_INVALID_CONFIG", void 0, {
|
|
1131
|
-
// Stryker disable next-line StringLiteral
|
|
1131
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
1132
1132
|
reason: "BudgetGuard requires options.scopeResolver to resolve the caller scope"
|
|
1133
1133
|
});
|
|
1134
1134
|
}
|
|
@@ -1359,7 +1359,7 @@ function computePayloadHash(record) {
|
|
|
1359
1359
|
// src/server/utils/hash-chain.ts
|
|
1360
1360
|
function chainHash(prevHash, record) {
|
|
1361
1361
|
return deriveIdempotencyKey({
|
|
1362
|
-
// Stryker disable next-line StringLiteral
|
|
1362
|
+
// Stryker disable next-line StringLiteral: empty-string fallback for null prevHash; tests only verify hash determinism and inequality, not the specific hash value for a genesis block
|
|
1363
1363
|
prevHash: prevHash ?? "",
|
|
1364
1364
|
id: record.id,
|
|
1365
1365
|
content: computePayloadHash(record)
|
|
@@ -1560,7 +1560,7 @@ exports.LedgerService = class LedgerService {
|
|
|
1560
1560
|
const original = await this.store.findById(recordId);
|
|
1561
1561
|
if (original?.status !== "posted") {
|
|
1562
1562
|
throw new AiTokensException("AI_TOKENS_IDEMPOTENCY_CONFLICT", void 0, {
|
|
1563
|
-
// Stryker disable next-line StringLiteral
|
|
1563
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
1564
1564
|
reason: original === null ? "record not found" : `cannot reverse a ${original.status} record`,
|
|
1565
1565
|
recordId,
|
|
1566
1566
|
requestedReason: reason
|
|
@@ -1581,7 +1581,7 @@ exports.LedgerService = class LedgerService {
|
|
|
1581
1581
|
assertLegalTransition(from2, to, patch) {
|
|
1582
1582
|
if (!isLegalLedgerTransition(from2, to)) {
|
|
1583
1583
|
throw new AiTokensException("AI_TOKENS_IDEMPOTENCY_CONFLICT", void 0, {
|
|
1584
|
-
// Stryker disable next-line StringLiteral
|
|
1584
|
+
// Stryker disable next-line StringLiteral: error reason template is internal diagnostics
|
|
1585
1585
|
reason: `illegal transition ${from2} \u2192 ${to}`
|
|
1586
1586
|
});
|
|
1587
1587
|
}
|
|
@@ -1589,7 +1589,7 @@ exports.LedgerService = class LedgerService {
|
|
|
1589
1589
|
for (const key of Object.keys(patch)) {
|
|
1590
1590
|
if (!isLegalTransitionPatchKey(from2, to, key)) {
|
|
1591
1591
|
throw new AiTokensException("AI_TOKENS_IDEMPOTENCY_CONFLICT", void 0, {
|
|
1592
|
-
// Stryker disable next-line StringLiteral
|
|
1592
|
+
// Stryker disable next-line StringLiteral: error reason template is internal diagnostics
|
|
1593
1593
|
reason: `${from2} \u2192 ${to} may not patch "${key}"`
|
|
1594
1594
|
});
|
|
1595
1595
|
}
|
|
@@ -1608,13 +1608,13 @@ function buildCompensatingRecord(original) {
|
|
|
1608
1608
|
return {
|
|
1609
1609
|
tenantId: original.tenantId,
|
|
1610
1610
|
scope: original.scope,
|
|
1611
|
-
// Stryker disable next-line ConditionalExpression
|
|
1611
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { beneficiary: undefined } is equivalent to {} because downstream consumers check !== undefined
|
|
1612
1612
|
...original.beneficiary !== void 0 ? { beneficiary: original.beneficiary } : {},
|
|
1613
|
-
// Stryker disable next-line ConditionalExpression
|
|
1613
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { requestedBy: undefined } is equivalent to {}
|
|
1614
1614
|
...original.requestedBy !== void 0 ? { requestedBy: original.requestedBy } : {},
|
|
1615
1615
|
provider: original.provider,
|
|
1616
1616
|
model: original.model,
|
|
1617
|
-
// Stryker disable next-line ConditionalExpression
|
|
1617
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { requestedModel: undefined } is equivalent to {}
|
|
1618
1618
|
...original.requestedModel !== void 0 ? { requestedModel: original.requestedModel } : {},
|
|
1619
1619
|
operation: original.operation,
|
|
1620
1620
|
serviceTier: original.serviceTier,
|
|
@@ -1630,7 +1630,7 @@ function buildCompensatingRecord(original) {
|
|
|
1630
1630
|
audioOutTokens: -original.audioOutTokens,
|
|
1631
1631
|
imageInTokens: -original.imageInTokens,
|
|
1632
1632
|
imageOutTokens: -original.imageOutTokens,
|
|
1633
|
-
// Stryker disable next-line ConditionalExpression
|
|
1633
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { extraUnits: undefined } is equivalent to {} because consumers check !== undefined
|
|
1634
1634
|
...original.extraUnits !== void 0 ? { extraUnits: negateUnits(original.extraUnits) } : {},
|
|
1635
1635
|
priceVersionId: original.priceVersionId,
|
|
1636
1636
|
rawCostNanoUsd: -original.rawCostNanoUsd,
|
|
@@ -1641,12 +1641,12 @@ function buildCompensatingRecord(original) {
|
|
|
1641
1641
|
priceMissing: original.priceMissing,
|
|
1642
1642
|
status: "posted",
|
|
1643
1643
|
reversesRecordId: original.id,
|
|
1644
|
-
// Stryker disable next-line ConditionalExpression
|
|
1644
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { correlationId: undefined } is equivalent to {}
|
|
1645
1645
|
...original.correlationId !== void 0 ? { correlationId: original.correlationId } : {},
|
|
1646
|
-
// Stryker disable next-line ConditionalExpression
|
|
1646
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { requestId: undefined } is equivalent to {}
|
|
1647
1647
|
...original.requestId !== void 0 ? { requestId: original.requestId } : {},
|
|
1648
1648
|
isSystemCost: original.isSystemCost,
|
|
1649
|
-
// Stryker disable next-line ConditionalExpression
|
|
1649
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { systemCostCategory: undefined } is equivalent to {}
|
|
1650
1650
|
...original.systemCostCategory !== void 0 ? { systemCostCategory: original.systemCostCategory } : {},
|
|
1651
1651
|
enforced: original.enforced,
|
|
1652
1652
|
occurredAt: original.occurredAt
|
|
@@ -1683,7 +1683,7 @@ var MarkupResolver = class {
|
|
|
1683
1683
|
return await policy.resolve(context);
|
|
1684
1684
|
} catch {
|
|
1685
1685
|
throw new AiTokensException("AI_TOKENS_INVALID_CONFIG", void 0, {
|
|
1686
|
-
// Stryker disable next-line StringLiteral
|
|
1686
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
1687
1687
|
reason: "markup policy failed to resolve a multiplier"
|
|
1688
1688
|
});
|
|
1689
1689
|
}
|
|
@@ -1694,7 +1694,7 @@ var MarkupResolver = class {
|
|
|
1694
1694
|
return resolveMultiplier4dp(raw);
|
|
1695
1695
|
} catch {
|
|
1696
1696
|
throw new AiTokensException("AI_TOKENS_INVALID_CONFIG", void 0, {
|
|
1697
|
-
// Stryker disable next-line StringLiteral
|
|
1697
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
1698
1698
|
reason: "markup policy returned an invalid multiplier",
|
|
1699
1699
|
value: raw
|
|
1700
1700
|
});
|
|
@@ -2163,7 +2163,7 @@ async function resolveHoldEstimate(pricing, context, estimate, at) {
|
|
|
2163
2163
|
operation: estimate.operation,
|
|
2164
2164
|
serviceTier: tier,
|
|
2165
2165
|
at,
|
|
2166
|
-
// Stryker disable next-line ConditionalExpression
|
|
2166
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { baseModel: undefined } is equivalent to {} because resolveRate reads input.baseModel (undefined either way) — same cache key and same `baseModel !== undefined` resolution branch
|
|
2167
2167
|
...context.baseModel !== void 0 ? { baseModel: context.baseModel } : {}
|
|
2168
2168
|
});
|
|
2169
2169
|
const rawEstimateNanoUsd = rate === null ? 0n : computeCostNanoUsd(usage, rate).totalNanoUsd;
|
|
@@ -2187,7 +2187,7 @@ async function resolveHoldEstimate(pricing, context, estimate, at) {
|
|
|
2187
2187
|
async function resolveTokenEstimate(pricing, context, tokens, serviceTier, at) {
|
|
2188
2188
|
if (context.preset === void 0) {
|
|
2189
2189
|
throw new AiTokensException("AI_TOKENS_INVALID_CONFIG", void 0, {
|
|
2190
|
-
// Stryker disable next-line StringLiteral
|
|
2190
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
2191
2191
|
reason: "a { tokens } hold estimate requires context.preset to identify the provider"
|
|
2192
2192
|
});
|
|
2193
2193
|
}
|
|
@@ -2212,7 +2212,7 @@ function normalizeCaptureUsage(usage, normalizer) {
|
|
|
2212
2212
|
}
|
|
2213
2213
|
}
|
|
2214
2214
|
throw new AiTokensException("AI_TOKENS_USAGE_MALFORMED", void 0, {
|
|
2215
|
-
// Stryker disable next-line StringLiteral
|
|
2215
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
2216
2216
|
reason: "capture requires an already-normalized usage or a preset normalizer"
|
|
2217
2217
|
});
|
|
2218
2218
|
}
|
|
@@ -2241,7 +2241,7 @@ function buildAppendInput(args) {
|
|
|
2241
2241
|
audioOutTokens: normalized.audioOutTokens,
|
|
2242
2242
|
imageInTokens: normalized.imageInTokens,
|
|
2243
2243
|
imageOutTokens: normalized.imageOutTokens,
|
|
2244
|
-
// Stryker disable next-line ConditionalExpression,EqualityOperator
|
|
2244
|
+
// Stryker disable next-line ConditionalExpression,EqualityOperator: CE/EQ: when ratedUnits is empty, spreading { extraUnits: {} } vs omitting the key; downstream consumers check record.extraUnits !== undefined (absent vs present {}); unit tests don't use server tool use, so ratedUnits={} always → no observable difference
|
|
2245
2245
|
...Object.keys(ratedUnits).length > 0 ? { extraUnits: ratedUnits } : {},
|
|
2246
2246
|
priceVersionId: rating.priceVersionId,
|
|
2247
2247
|
rawCostNanoUsd: rating.rawCostNanoUsd,
|
|
@@ -2252,7 +2252,7 @@ function buildAppendInput(args) {
|
|
|
2252
2252
|
priceMissing: rating.priceMissing,
|
|
2253
2253
|
status: "posted",
|
|
2254
2254
|
isSystemCost: context.isSystemCost ?? false,
|
|
2255
|
-
// Stryker disable next-line ConditionalExpression
|
|
2255
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { systemCostCategory: undefined } is equivalent to {} because JS property access treats absent and undefined the same
|
|
2256
2256
|
...context.systemCostCategory !== void 0 ? { systemCostCategory: context.systemCostCategory } : {},
|
|
2257
2257
|
enforced,
|
|
2258
2258
|
occurredAt
|
|
@@ -2262,19 +2262,19 @@ function baseColumns(usage, context, serviceTier) {
|
|
|
2262
2262
|
return {
|
|
2263
2263
|
tenantId: context.tenantId,
|
|
2264
2264
|
scope: context.scope,
|
|
2265
|
-
// Stryker disable next-line ConditionalExpression
|
|
2265
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { beneficiary: undefined } is equivalent to {} for property access and truthiness-based filters
|
|
2266
2266
|
...context.beneficiary !== void 0 ? { beneficiary: context.beneficiary } : {},
|
|
2267
|
-
// Stryker disable next-line ConditionalExpression
|
|
2267
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { requestedBy: undefined } is equivalent to {}
|
|
2268
2268
|
...context.requestedBy !== void 0 ? { requestedBy: context.requestedBy } : {},
|
|
2269
2269
|
provider: usage.provider,
|
|
2270
2270
|
model: usage.model,
|
|
2271
|
-
// Stryker disable next-line ConditionalExpression
|
|
2271
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { requestedModel: undefined } is equivalent to {} for downstream consumers
|
|
2272
2272
|
...context.baseModel !== void 0 ? { requestedModel: context.baseModel } : {},
|
|
2273
2273
|
operation: usage.operation,
|
|
2274
2274
|
serviceTier,
|
|
2275
2275
|
feature: context.feature,
|
|
2276
2276
|
tags: context.tags ?? [],
|
|
2277
|
-
// Stryker disable next-line ConditionalExpression
|
|
2277
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { correlationId: undefined } is equivalent to {} because it's only read via record.correlationId
|
|
2278
2278
|
...context.correlationId !== void 0 ? { correlationId: context.correlationId } : {}
|
|
2279
2279
|
};
|
|
2280
2280
|
}
|
|
@@ -2336,7 +2336,7 @@ exports.MeteringService = class MeteringService {
|
|
|
2336
2336
|
const enforcing = context.enforce === true;
|
|
2337
2337
|
if (enforcing && this.wallets === void 0 && this.budgets === void 0) {
|
|
2338
2338
|
throw new AiTokensException("AI_TOKENS_INVALID_CONFIG", void 0, {
|
|
2339
|
-
// Stryker disable next-line StringLiteral
|
|
2339
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
2340
2340
|
reason: "enforce requires the wallets or budgets feature to be enabled"
|
|
2341
2341
|
});
|
|
2342
2342
|
}
|
|
@@ -2391,7 +2391,7 @@ exports.MeteringService = class MeteringService {
|
|
|
2391
2391
|
model: input.model,
|
|
2392
2392
|
operation: input.operation,
|
|
2393
2393
|
serviceTier,
|
|
2394
|
-
// Stryker disable next-line ConditionalExpression
|
|
2394
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { feature: undefined } is equivalent to {} because markup.resolve treats absent and undefined feature the same
|
|
2395
2395
|
...input.feature !== void 0 ? { feature: input.feature } : {}
|
|
2396
2396
|
});
|
|
2397
2397
|
return { rawCostNanoUsd, billedCostNanoUsd: markup.apply(rawCostNanoUsd) };
|
|
@@ -2593,7 +2593,7 @@ exports.MeteringService = class MeteringService {
|
|
|
2593
2593
|
priceMissing: false,
|
|
2594
2594
|
status: "pending",
|
|
2595
2595
|
isSystemCost,
|
|
2596
|
-
// Stryker disable next-line ConditionalExpression
|
|
2596
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { systemCostCategory: undefined } is equivalent to {}
|
|
2597
2597
|
...context.systemCostCategory !== void 0 ? { systemCostCategory: context.systemCostCategory } : {},
|
|
2598
2598
|
enforced: !isSystemCost,
|
|
2599
2599
|
occurredAt
|
|
@@ -2691,7 +2691,7 @@ exports.MeteringService = class MeteringService {
|
|
|
2691
2691
|
if (normalizer !== void 0) return this.normalize(normalizer, input.usage);
|
|
2692
2692
|
if (isNormalizedUsage(input.usage)) return input.usage;
|
|
2693
2693
|
throw new AiTokensException("AI_TOKENS_UNKNOWN_PROVIDER", void 0, {
|
|
2694
|
-
// Stryker disable next-line StringLiteral
|
|
2694
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
2695
2695
|
reason: "raw usage requires a preset or normalizer, or an already-normalized usage"
|
|
2696
2696
|
});
|
|
2697
2697
|
}
|
|
@@ -2794,7 +2794,7 @@ exports.WalletService = class WalletService {
|
|
|
2794
2794
|
amountNanoUsd: input.amountNanoUsd,
|
|
2795
2795
|
priority: input.priority ?? 0,
|
|
2796
2796
|
effectiveAt: input.effectiveAt ?? /* @__PURE__ */ new Date(),
|
|
2797
|
-
// Stryker disable next-line ConditionalExpression
|
|
2797
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { expiresAt: undefined } is equivalent to {} because InMemoryWalletStore and consumers check expiresAt !== undefined
|
|
2798
2798
|
...input.expiresAt !== void 0 ? { expiresAt: input.expiresAt } : {},
|
|
2799
2799
|
idempotencyKey: input.idempotencyKey,
|
|
2800
2800
|
reason: input.reason
|
|
@@ -2803,7 +2803,7 @@ exports.WalletService = class WalletService {
|
|
|
2803
2803
|
walletId: entry.walletId,
|
|
2804
2804
|
entryId: entry.id,
|
|
2805
2805
|
amountNanoUsd: entry.amountNanoUsd,
|
|
2806
|
-
// Stryker disable next-line ConditionalExpression
|
|
2806
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { expiresAt: undefined } is equivalent to {} because event consumers check expiresAt !== undefined
|
|
2807
2807
|
...entry.expiresAt !== void 0 ? { expiresAt: entry.expiresAt } : {}
|
|
2808
2808
|
};
|
|
2809
2809
|
await this.events.granted(ref, granted);
|
|
@@ -2834,16 +2834,16 @@ exports.WalletService = class WalletService {
|
|
|
2834
2834
|
throw this.invalid("a debit without a usageRecordId must carry a reason");
|
|
2835
2835
|
}
|
|
2836
2836
|
const entry = {
|
|
2837
|
-
// Stryker disable next-line StringLiteral
|
|
2837
|
+
// Stryker disable next-line StringLiteral: placeholder walletId; the store's insert always assigns the real wallet id and never reads this sentinel, so any string here is equivalent
|
|
2838
2838
|
walletId: "",
|
|
2839
2839
|
type: "debit",
|
|
2840
2840
|
amountNanoUsd: -input.amountNanoUsd,
|
|
2841
2841
|
priority: 0,
|
|
2842
2842
|
effectiveAt: /* @__PURE__ */ new Date(),
|
|
2843
|
-
// Stryker disable next-line ConditionalExpression
|
|
2843
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { usageRecordId: undefined } is equivalent to {} because store and consumers check usageRecordId !== undefined
|
|
2844
2844
|
...input.usageRecordId !== void 0 ? { usageRecordId: input.usageRecordId } : {},
|
|
2845
2845
|
idempotencyKey: input.idempotencyKey,
|
|
2846
|
-
// Stryker disable next-line ConditionalExpression
|
|
2846
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { reason: undefined } is equivalent to {} because store and consumers check reason !== undefined
|
|
2847
2847
|
...input.reason !== void 0 ? { reason: input.reason } : {}
|
|
2848
2848
|
};
|
|
2849
2849
|
const debited = await this.conditionalDebit(ref, entry, input.amountNanoUsd);
|
|
@@ -2870,7 +2870,7 @@ exports.WalletService = class WalletService {
|
|
|
2870
2870
|
amountNanoUsd: input.amountNanoUsd,
|
|
2871
2871
|
priority: 0,
|
|
2872
2872
|
effectiveAt: /* @__PURE__ */ new Date(),
|
|
2873
|
-
// Stryker disable next-line ConditionalExpression,ObjectLiteral
|
|
2873
|
+
// Stryker disable next-line ConditionalExpression,ObjectLiteral: CE true / OL {}: spreading { usageRecordId: undefined } is equivalent to {} because store and consumers check usageRecordId !== undefined
|
|
2874
2874
|
...input.usageRecordId !== void 0 ? { usageRecordId: input.usageRecordId } : {},
|
|
2875
2875
|
idempotencyKey: input.idempotencyKey,
|
|
2876
2876
|
reason: input.reason
|
|
@@ -2927,8 +2927,8 @@ exports.WalletService = class WalletService {
|
|
|
2927
2927
|
amountNanoUsd: input.amountNanoUsd,
|
|
2928
2928
|
priority: 0,
|
|
2929
2929
|
effectiveAt: /* @__PURE__ */ new Date(),
|
|
2930
|
-
// Stryker disable next-line ConditionalExpression
|
|
2931
|
-
// Stryker disable next-line ConditionalExpression
|
|
2930
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { usageRecordId: undefined } is equivalent to {} because store and consumers check usageRecordId !== undefined
|
|
2931
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { usageRecordId: undefined } is equivalent to {} because store and consumers check usageRecordId !== undefined
|
|
2932
2932
|
...input.usageRecordId !== void 0 ? { usageRecordId: input.usageRecordId } : {},
|
|
2933
2933
|
idempotencyKey: input.idempotencyKey,
|
|
2934
2934
|
reason: input.reason
|
|
@@ -3560,11 +3560,11 @@ function featureMatches3(features, feature) {
|
|
|
3560
3560
|
}
|
|
3561
3561
|
function limitsOf(budget) {
|
|
3562
3562
|
return {
|
|
3563
|
-
// Stryker disable next-line ConditionalExpression
|
|
3563
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { nanoUsd: undefined } is equivalent to {} because all consumers check limits.nanoUsd !== undefined
|
|
3564
3564
|
...budget.limitNanoUsd !== void 0 ? { nanoUsd: budget.limitNanoUsd } : {},
|
|
3565
|
-
// Stryker disable next-line ConditionalExpression
|
|
3565
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { tokens: undefined } is equivalent to {} because all consumers check limits.tokens !== undefined
|
|
3566
3566
|
...budget.limitTokens !== void 0 ? { tokens: budget.limitTokens } : {},
|
|
3567
|
-
// Stryker disable next-line ConditionalExpression
|
|
3567
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { count: undefined } is equivalent to {} because all consumers check limits.count !== undefined
|
|
3568
3568
|
...budget.limitCount !== void 0 ? { count: budget.limitCount } : {}
|
|
3569
3569
|
};
|
|
3570
3570
|
}
|
|
@@ -3604,11 +3604,11 @@ function ratio(spent, limit) {
|
|
|
3604
3604
|
}
|
|
3605
3605
|
function limitSnapshot(limits) {
|
|
3606
3606
|
return {
|
|
3607
|
-
// Stryker disable next-line ConditionalExpression
|
|
3607
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { nanoUsd: undefined } is equivalent to {} for event consumers who check field !== undefined
|
|
3608
3608
|
...limits.nanoUsd !== void 0 ? { nanoUsd: limits.nanoUsd } : {},
|
|
3609
|
-
// Stryker disable next-line ConditionalExpression
|
|
3609
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { tokens: undefined } is equivalent to {} for event consumers who check field !== undefined
|
|
3610
3610
|
...limits.tokens !== void 0 ? { tokens: limits.tokens } : {},
|
|
3611
|
-
// Stryker disable next-line ConditionalExpression
|
|
3611
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { count: undefined } is equivalent to {} for event consumers who check field !== undefined
|
|
3612
3612
|
...limits.count !== void 0 ? { count: limits.count } : {}
|
|
3613
3613
|
};
|
|
3614
3614
|
}
|
|
@@ -3617,11 +3617,11 @@ function spendSnapshot(spend) {
|
|
|
3617
3617
|
}
|
|
3618
3618
|
function remainingSnapshot(limits, spend) {
|
|
3619
3619
|
return {
|
|
3620
|
-
// Stryker disable next-line ConditionalExpression
|
|
3620
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { nanoUsd: undefined } is equivalent to {} for event consumers who check field !== undefined
|
|
3621
3621
|
...limits.nanoUsd !== void 0 ? { nanoUsd: max0(limits.nanoUsd - spend.spentNanoUsd) } : {},
|
|
3622
|
-
// Stryker disable next-line ConditionalExpression
|
|
3622
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { tokens: undefined } is equivalent to {} for event consumers who check field !== undefined
|
|
3623
3623
|
...limits.tokens !== void 0 ? { tokens: Math.max(0, limits.tokens - spend.spentTokens) } : {},
|
|
3624
|
-
// Stryker disable next-line ConditionalExpression
|
|
3624
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { count: undefined } is equivalent to {} for event consumers who check field !== undefined
|
|
3625
3625
|
...limits.count !== void 0 ? { count: Math.max(0, limits.count - spend.spentCount) } : {}
|
|
3626
3626
|
};
|
|
3627
3627
|
}
|
|
@@ -3629,7 +3629,7 @@ function buildStatus(budget, windowStart, resetsAt, spend) {
|
|
|
3629
3629
|
const limits = limitsOf(budget);
|
|
3630
3630
|
return {
|
|
3631
3631
|
budgetId: budget.id,
|
|
3632
|
-
// Stryker disable next-line ConditionalExpression
|
|
3632
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { features: undefined } is equivalent to {} because status consumers check features !== undefined
|
|
3633
3633
|
...budget.features !== void 0 ? { features: budget.features } : {},
|
|
3634
3634
|
window: budget.window,
|
|
3635
3635
|
windowStart,
|
|
@@ -3796,29 +3796,29 @@ exports.UsageReportService = __decorateClass([
|
|
|
3796
3796
|
function toLedgerFilter(filter, limit) {
|
|
3797
3797
|
return {
|
|
3798
3798
|
tenantId: filter.tenantId,
|
|
3799
|
-
// Stryker disable next-line ConditionalExpression
|
|
3799
|
+
// Stryker disable next-line ConditionalExpression: spreading { scope: undefined } is equivalent to {} because InMemoryLedgerStore uses truthiness; the 'false' variant is covered by the scope isolation test
|
|
3800
3800
|
...filter.scope !== void 0 ? { scope: filter.scope } : {},
|
|
3801
|
-
// Stryker disable next-line ConditionalExpression
|
|
3801
|
+
// Stryker disable next-line ConditionalExpression: spreading { beneficiary: undefined } is equivalent to {} for the same reason
|
|
3802
3802
|
...filter.beneficiary !== void 0 ? { beneficiary: filter.beneficiary } : {},
|
|
3803
|
-
// Stryker disable next-line ConditionalExpression
|
|
3803
|
+
// Stryker disable next-line ConditionalExpression: spreading { feature: undefined } does not change the !== undefined check in matches()
|
|
3804
3804
|
...filter.feature !== void 0 ? { feature: filter.feature } : {},
|
|
3805
|
-
// Stryker disable next-line ConditionalExpression
|
|
3805
|
+
// Stryker disable next-line ConditionalExpression: spreading { features: undefined } does not change the truthiness check in matches()
|
|
3806
3806
|
...filter.features !== void 0 ? { features: filter.features } : {},
|
|
3807
|
-
// Stryker disable next-line ConditionalExpression
|
|
3807
|
+
// Stryker disable next-line ConditionalExpression: spreading { provider: undefined } does not change the !== undefined check in matches()
|
|
3808
3808
|
...filter.provider !== void 0 ? { provider: filter.provider } : {},
|
|
3809
|
-
// Stryker disable next-line ConditionalExpression
|
|
3809
|
+
// Stryker disable next-line ConditionalExpression: spreading { model: undefined } does not change the !== undefined check in matches()
|
|
3810
3810
|
...filter.model !== void 0 ? { model: filter.model } : {},
|
|
3811
|
-
// Stryker disable next-line ConditionalExpression
|
|
3811
|
+
// Stryker disable next-line ConditionalExpression: spreading { operation: undefined } does not change the !== undefined check in matches()
|
|
3812
3812
|
...filter.operation !== void 0 ? { operation: filter.operation } : {},
|
|
3813
|
-
// Stryker disable next-line ConditionalExpression
|
|
3813
|
+
// Stryker disable next-line ConditionalExpression: spreading { serviceTier: undefined } does not change the !== undefined check in matches()
|
|
3814
3814
|
...filter.serviceTier !== void 0 ? { serviceTier: filter.serviceTier } : {},
|
|
3815
|
-
// Stryker disable next-line ConditionalExpression
|
|
3815
|
+
// Stryker disable next-line ConditionalExpression: spreading { tags: undefined } does not change the truthiness check in matches()
|
|
3816
3816
|
...filter.tags !== void 0 ? { tags: filter.tags } : {},
|
|
3817
|
-
// Stryker disable next-line ConditionalExpression
|
|
3817
|
+
// Stryker disable next-line ConditionalExpression: spreading { isSystemCost: undefined } does not change the !== undefined check in matches()
|
|
3818
3818
|
...filter.isSystemCost !== void 0 ? { isSystemCost: filter.isSystemCost } : {},
|
|
3819
|
-
// Stryker disable next-line ConditionalExpression
|
|
3819
|
+
// Stryker disable next-line ConditionalExpression: spreading { systemCostCategory: undefined } does not change the !== undefined check in matches()
|
|
3820
3820
|
...filter.systemCostCategory !== void 0 ? { systemCostCategory: filter.systemCostCategory } : {},
|
|
3821
|
-
// Stryker disable next-line ConditionalExpression
|
|
3821
|
+
// Stryker disable next-line ConditionalExpression: spreading { enforcedOnly: undefined } does not change the === true check in matches()
|
|
3822
3822
|
...filter.enforcedOnly !== void 0 ? { enforcedOnly: filter.enforcedOnly } : {},
|
|
3823
3823
|
status: filter.status ?? [...BALANCE_STATUSES2],
|
|
3824
3824
|
from: filter.from,
|
|
@@ -4004,9 +4004,9 @@ exports.MeteringInterceptor = class MeteringInterceptor {
|
|
|
4004
4004
|
const context = await this.resolveContext(executionContext, config, enrichment);
|
|
4005
4005
|
return this.metering.record({
|
|
4006
4006
|
usage,
|
|
4007
|
-
// Stryker disable next-line ConditionalExpression
|
|
4007
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { preset: undefined } is equivalent to {} because MeteringService checks preset !== undefined
|
|
4008
4008
|
...config.preset !== void 0 ? { preset: config.preset } : {},
|
|
4009
|
-
// Stryker disable next-line ConditionalExpression
|
|
4009
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { tags: undefined } is equivalent to {} because MeteringService checks tags !== undefined
|
|
4010
4010
|
context: { ...context, enforce: true, isSystemCost: config.isSystemCost ?? false, ...config.tags !== void 0 ? { tags: config.tags } : {} }
|
|
4011
4011
|
});
|
|
4012
4012
|
}
|
|
@@ -4334,24 +4334,24 @@ function preset(provider, normalizer, ratingMode) {
|
|
|
4334
4334
|
return { provider, normalizer, ratingMode };
|
|
4335
4335
|
}
|
|
4336
4336
|
var providerPresets = {
|
|
4337
|
-
// Stryker disable next-line StringLiteral
|
|
4337
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests that exercise the full preset→MeteringService→UsageRecord path
|
|
4338
4338
|
openaiChat: preset("openai", normalizeOpenAiChatUsage, "rate-table"),
|
|
4339
|
-
// Stryker disable next-line StringLiteral
|
|
4339
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4340
4340
|
openaiResponses: preset("openai", normalizeOpenAiResponsesUsage, "rate-table"),
|
|
4341
|
-
// Stryker disable next-line StringLiteral
|
|
4341
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4342
4342
|
azureOpenai: preset("azure-openai", normalizeOpenAiChatUsage, "rate-table"),
|
|
4343
|
-
// Stryker disable next-line StringLiteral
|
|
4343
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4344
4344
|
anthropic: preset("anthropic", normalizeAnthropicUsage, "rate-table"),
|
|
4345
|
-
// Stryker disable next-line StringLiteral
|
|
4345
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4346
4346
|
gemini: preset("gemini", normalizeGeminiUsage, "rate-table"),
|
|
4347
|
-
// Stryker disable next-line StringLiteral
|
|
4347
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4348
4348
|
vertex: preset("vertex", normalizeGeminiUsage, "rate-table"),
|
|
4349
|
-
// Stryker disable next-line StringLiteral
|
|
4349
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4350
4350
|
bedrock: preset("bedrock", normalizeBedrockConverseUsage, "rate-table"),
|
|
4351
|
-
// Stryker disable next-line StringLiteral
|
|
4351
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4352
4352
|
mistral: preset("mistral", normalizeMistralUsage, "rate-table"),
|
|
4353
4353
|
vercelAiSdk: preset("openai", normalizeVercelAiSdkUsage, "rate-table"),
|
|
4354
|
-
// Stryker disable next-line StringLiteral
|
|
4354
|
+
// Stryker disable next-line StringLiteral: provider ID and rating mode; only observable via integration tests
|
|
4355
4355
|
openrouter: preset("openrouter", normalizeOpenRouterUsage, "provider-reported"),
|
|
4356
4356
|
/** A custom OpenAI-compatible provider (DeepSeek, xAI, Groq, …). */
|
|
4357
4357
|
openaiCompatible: (id) => preset(id, normalizeOpenAiCompatibleUsage, "rate-table")
|
package/dist/server/index.mjs
CHANGED
|
@@ -360,9 +360,9 @@ function normalizeMistralUsage(raw) {
|
|
|
360
360
|
provider: "mistral",
|
|
361
361
|
model: str(response.model) ?? "",
|
|
362
362
|
operation: "chat",
|
|
363
|
-
// Stryker disable next-line StringLiteral
|
|
363
|
+
// Stryker disable next-line StringLiteral: provider and field names in error messages are internal diagnostics
|
|
364
364
|
inputTokens: requireNum(usage.prompt_tokens, "mistral", "usage.prompt_tokens"),
|
|
365
|
-
// Stryker disable next-line StringLiteral
|
|
365
|
+
// Stryker disable next-line StringLiteral: provider and field names in error messages are internal diagnostics
|
|
366
366
|
outputTokens: requireNum(usage.completion_tokens, "mistral", "usage.completion_tokens"),
|
|
367
367
|
raw: usage
|
|
368
368
|
});
|
|
@@ -806,7 +806,7 @@ function validatePricing(options) {
|
|
|
806
806
|
if (cacheTtlMs === void 0) return;
|
|
807
807
|
if (!Number.isInteger(cacheTtlMs) || cacheTtlMs <= 0) {
|
|
808
808
|
throw invalidConfig(
|
|
809
|
-
// Stryker disable next-line StringLiteral
|
|
809
|
+
// Stryker disable next-line StringLiteral: error reason template is internal diagnostics
|
|
810
810
|
`pricing.cacheTtlMs must be a positive integer number of milliseconds, received ${String(cacheTtlMs)}`
|
|
811
811
|
);
|
|
812
812
|
}
|
|
@@ -1126,7 +1126,7 @@ var BudgetGuard = class {
|
|
|
1126
1126
|
this.reflector = reflector;
|
|
1127
1127
|
if (options.scopeResolver === void 0) {
|
|
1128
1128
|
throw new AiTokensException("AI_TOKENS_INVALID_CONFIG", void 0, {
|
|
1129
|
-
// Stryker disable next-line StringLiteral
|
|
1129
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
1130
1130
|
reason: "BudgetGuard requires options.scopeResolver to resolve the caller scope"
|
|
1131
1131
|
});
|
|
1132
1132
|
}
|
|
@@ -1357,7 +1357,7 @@ function computePayloadHash(record) {
|
|
|
1357
1357
|
// src/server/utils/hash-chain.ts
|
|
1358
1358
|
function chainHash(prevHash, record) {
|
|
1359
1359
|
return deriveIdempotencyKey({
|
|
1360
|
-
// Stryker disable next-line StringLiteral
|
|
1360
|
+
// Stryker disable next-line StringLiteral: empty-string fallback for null prevHash; tests only verify hash determinism and inequality, not the specific hash value for a genesis block
|
|
1361
1361
|
prevHash: prevHash ?? "",
|
|
1362
1362
|
id: record.id,
|
|
1363
1363
|
content: computePayloadHash(record)
|
|
@@ -1558,7 +1558,7 @@ var LedgerService = class {
|
|
|
1558
1558
|
const original = await this.store.findById(recordId);
|
|
1559
1559
|
if (original?.status !== "posted") {
|
|
1560
1560
|
throw new AiTokensException("AI_TOKENS_IDEMPOTENCY_CONFLICT", void 0, {
|
|
1561
|
-
// Stryker disable next-line StringLiteral
|
|
1561
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
1562
1562
|
reason: original === null ? "record not found" : `cannot reverse a ${original.status} record`,
|
|
1563
1563
|
recordId,
|
|
1564
1564
|
requestedReason: reason
|
|
@@ -1579,7 +1579,7 @@ var LedgerService = class {
|
|
|
1579
1579
|
assertLegalTransition(from2, to, patch) {
|
|
1580
1580
|
if (!isLegalLedgerTransition(from2, to)) {
|
|
1581
1581
|
throw new AiTokensException("AI_TOKENS_IDEMPOTENCY_CONFLICT", void 0, {
|
|
1582
|
-
// Stryker disable next-line StringLiteral
|
|
1582
|
+
// Stryker disable next-line StringLiteral: error reason template is internal diagnostics
|
|
1583
1583
|
reason: `illegal transition ${from2} \u2192 ${to}`
|
|
1584
1584
|
});
|
|
1585
1585
|
}
|
|
@@ -1587,7 +1587,7 @@ var LedgerService = class {
|
|
|
1587
1587
|
for (const key of Object.keys(patch)) {
|
|
1588
1588
|
if (!isLegalTransitionPatchKey(from2, to, key)) {
|
|
1589
1589
|
throw new AiTokensException("AI_TOKENS_IDEMPOTENCY_CONFLICT", void 0, {
|
|
1590
|
-
// Stryker disable next-line StringLiteral
|
|
1590
|
+
// Stryker disable next-line StringLiteral: error reason template is internal diagnostics
|
|
1591
1591
|
reason: `${from2} \u2192 ${to} may not patch "${key}"`
|
|
1592
1592
|
});
|
|
1593
1593
|
}
|
|
@@ -1606,13 +1606,13 @@ function buildCompensatingRecord(original) {
|
|
|
1606
1606
|
return {
|
|
1607
1607
|
tenantId: original.tenantId,
|
|
1608
1608
|
scope: original.scope,
|
|
1609
|
-
// Stryker disable next-line ConditionalExpression
|
|
1609
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { beneficiary: undefined } is equivalent to {} because downstream consumers check !== undefined
|
|
1610
1610
|
...original.beneficiary !== void 0 ? { beneficiary: original.beneficiary } : {},
|
|
1611
|
-
// Stryker disable next-line ConditionalExpression
|
|
1611
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { requestedBy: undefined } is equivalent to {}
|
|
1612
1612
|
...original.requestedBy !== void 0 ? { requestedBy: original.requestedBy } : {},
|
|
1613
1613
|
provider: original.provider,
|
|
1614
1614
|
model: original.model,
|
|
1615
|
-
// Stryker disable next-line ConditionalExpression
|
|
1615
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { requestedModel: undefined } is equivalent to {}
|
|
1616
1616
|
...original.requestedModel !== void 0 ? { requestedModel: original.requestedModel } : {},
|
|
1617
1617
|
operation: original.operation,
|
|
1618
1618
|
serviceTier: original.serviceTier,
|
|
@@ -1628,7 +1628,7 @@ function buildCompensatingRecord(original) {
|
|
|
1628
1628
|
audioOutTokens: -original.audioOutTokens,
|
|
1629
1629
|
imageInTokens: -original.imageInTokens,
|
|
1630
1630
|
imageOutTokens: -original.imageOutTokens,
|
|
1631
|
-
// Stryker disable next-line ConditionalExpression
|
|
1631
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { extraUnits: undefined } is equivalent to {} because consumers check !== undefined
|
|
1632
1632
|
...original.extraUnits !== void 0 ? { extraUnits: negateUnits(original.extraUnits) } : {},
|
|
1633
1633
|
priceVersionId: original.priceVersionId,
|
|
1634
1634
|
rawCostNanoUsd: -original.rawCostNanoUsd,
|
|
@@ -1639,12 +1639,12 @@ function buildCompensatingRecord(original) {
|
|
|
1639
1639
|
priceMissing: original.priceMissing,
|
|
1640
1640
|
status: "posted",
|
|
1641
1641
|
reversesRecordId: original.id,
|
|
1642
|
-
// Stryker disable next-line ConditionalExpression
|
|
1642
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { correlationId: undefined } is equivalent to {}
|
|
1643
1643
|
...original.correlationId !== void 0 ? { correlationId: original.correlationId } : {},
|
|
1644
|
-
// Stryker disable next-line ConditionalExpression
|
|
1644
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { requestId: undefined } is equivalent to {}
|
|
1645
1645
|
...original.requestId !== void 0 ? { requestId: original.requestId } : {},
|
|
1646
1646
|
isSystemCost: original.isSystemCost,
|
|
1647
|
-
// Stryker disable next-line ConditionalExpression
|
|
1647
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { systemCostCategory: undefined } is equivalent to {}
|
|
1648
1648
|
...original.systemCostCategory !== void 0 ? { systemCostCategory: original.systemCostCategory } : {},
|
|
1649
1649
|
enforced: original.enforced,
|
|
1650
1650
|
occurredAt: original.occurredAt
|
|
@@ -1681,7 +1681,7 @@ var MarkupResolver = class {
|
|
|
1681
1681
|
return await policy.resolve(context);
|
|
1682
1682
|
} catch {
|
|
1683
1683
|
throw new AiTokensException("AI_TOKENS_INVALID_CONFIG", void 0, {
|
|
1684
|
-
// Stryker disable next-line StringLiteral
|
|
1684
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
1685
1685
|
reason: "markup policy failed to resolve a multiplier"
|
|
1686
1686
|
});
|
|
1687
1687
|
}
|
|
@@ -1692,7 +1692,7 @@ var MarkupResolver = class {
|
|
|
1692
1692
|
return resolveMultiplier4dp(raw);
|
|
1693
1693
|
} catch {
|
|
1694
1694
|
throw new AiTokensException("AI_TOKENS_INVALID_CONFIG", void 0, {
|
|
1695
|
-
// Stryker disable next-line StringLiteral
|
|
1695
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
1696
1696
|
reason: "markup policy returned an invalid multiplier",
|
|
1697
1697
|
value: raw
|
|
1698
1698
|
});
|
|
@@ -2161,7 +2161,7 @@ async function resolveHoldEstimate(pricing, context, estimate, at) {
|
|
|
2161
2161
|
operation: estimate.operation,
|
|
2162
2162
|
serviceTier: tier,
|
|
2163
2163
|
at,
|
|
2164
|
-
// Stryker disable next-line ConditionalExpression
|
|
2164
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { baseModel: undefined } is equivalent to {} because resolveRate reads input.baseModel (undefined either way) — same cache key and same `baseModel !== undefined` resolution branch
|
|
2165
2165
|
...context.baseModel !== void 0 ? { baseModel: context.baseModel } : {}
|
|
2166
2166
|
});
|
|
2167
2167
|
const rawEstimateNanoUsd = rate === null ? 0n : computeCostNanoUsd(usage, rate).totalNanoUsd;
|
|
@@ -2185,7 +2185,7 @@ async function resolveHoldEstimate(pricing, context, estimate, at) {
|
|
|
2185
2185
|
async function resolveTokenEstimate(pricing, context, tokens, serviceTier, at) {
|
|
2186
2186
|
if (context.preset === void 0) {
|
|
2187
2187
|
throw new AiTokensException("AI_TOKENS_INVALID_CONFIG", void 0, {
|
|
2188
|
-
// Stryker disable next-line StringLiteral
|
|
2188
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
2189
2189
|
reason: "a { tokens } hold estimate requires context.preset to identify the provider"
|
|
2190
2190
|
});
|
|
2191
2191
|
}
|
|
@@ -2210,7 +2210,7 @@ function normalizeCaptureUsage(usage, normalizer) {
|
|
|
2210
2210
|
}
|
|
2211
2211
|
}
|
|
2212
2212
|
throw new AiTokensException("AI_TOKENS_USAGE_MALFORMED", void 0, {
|
|
2213
|
-
// Stryker disable next-line StringLiteral
|
|
2213
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
2214
2214
|
reason: "capture requires an already-normalized usage or a preset normalizer"
|
|
2215
2215
|
});
|
|
2216
2216
|
}
|
|
@@ -2239,7 +2239,7 @@ function buildAppendInput(args) {
|
|
|
2239
2239
|
audioOutTokens: normalized.audioOutTokens,
|
|
2240
2240
|
imageInTokens: normalized.imageInTokens,
|
|
2241
2241
|
imageOutTokens: normalized.imageOutTokens,
|
|
2242
|
-
// Stryker disable next-line ConditionalExpression,EqualityOperator
|
|
2242
|
+
// Stryker disable next-line ConditionalExpression,EqualityOperator: CE/EQ: when ratedUnits is empty, spreading { extraUnits: {} } vs omitting the key; downstream consumers check record.extraUnits !== undefined (absent vs present {}); unit tests don't use server tool use, so ratedUnits={} always → no observable difference
|
|
2243
2243
|
...Object.keys(ratedUnits).length > 0 ? { extraUnits: ratedUnits } : {},
|
|
2244
2244
|
priceVersionId: rating.priceVersionId,
|
|
2245
2245
|
rawCostNanoUsd: rating.rawCostNanoUsd,
|
|
@@ -2250,7 +2250,7 @@ function buildAppendInput(args) {
|
|
|
2250
2250
|
priceMissing: rating.priceMissing,
|
|
2251
2251
|
status: "posted",
|
|
2252
2252
|
isSystemCost: context.isSystemCost ?? false,
|
|
2253
|
-
// Stryker disable next-line ConditionalExpression
|
|
2253
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { systemCostCategory: undefined } is equivalent to {} because JS property access treats absent and undefined the same
|
|
2254
2254
|
...context.systemCostCategory !== void 0 ? { systemCostCategory: context.systemCostCategory } : {},
|
|
2255
2255
|
enforced,
|
|
2256
2256
|
occurredAt
|
|
@@ -2260,19 +2260,19 @@ function baseColumns(usage, context, serviceTier) {
|
|
|
2260
2260
|
return {
|
|
2261
2261
|
tenantId: context.tenantId,
|
|
2262
2262
|
scope: context.scope,
|
|
2263
|
-
// Stryker disable next-line ConditionalExpression
|
|
2263
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { beneficiary: undefined } is equivalent to {} for property access and truthiness-based filters
|
|
2264
2264
|
...context.beneficiary !== void 0 ? { beneficiary: context.beneficiary } : {},
|
|
2265
|
-
// Stryker disable next-line ConditionalExpression
|
|
2265
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { requestedBy: undefined } is equivalent to {}
|
|
2266
2266
|
...context.requestedBy !== void 0 ? { requestedBy: context.requestedBy } : {},
|
|
2267
2267
|
provider: usage.provider,
|
|
2268
2268
|
model: usage.model,
|
|
2269
|
-
// Stryker disable next-line ConditionalExpression
|
|
2269
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { requestedModel: undefined } is equivalent to {} for downstream consumers
|
|
2270
2270
|
...context.baseModel !== void 0 ? { requestedModel: context.baseModel } : {},
|
|
2271
2271
|
operation: usage.operation,
|
|
2272
2272
|
serviceTier,
|
|
2273
2273
|
feature: context.feature,
|
|
2274
2274
|
tags: context.tags ?? [],
|
|
2275
|
-
// Stryker disable next-line ConditionalExpression
|
|
2275
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { correlationId: undefined } is equivalent to {} because it's only read via record.correlationId
|
|
2276
2276
|
...context.correlationId !== void 0 ? { correlationId: context.correlationId } : {}
|
|
2277
2277
|
};
|
|
2278
2278
|
}
|
|
@@ -2334,7 +2334,7 @@ var MeteringService = class {
|
|
|
2334
2334
|
const enforcing = context.enforce === true;
|
|
2335
2335
|
if (enforcing && this.wallets === void 0 && this.budgets === void 0) {
|
|
2336
2336
|
throw new AiTokensException("AI_TOKENS_INVALID_CONFIG", void 0, {
|
|
2337
|
-
// Stryker disable next-line StringLiteral
|
|
2337
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
2338
2338
|
reason: "enforce requires the wallets or budgets feature to be enabled"
|
|
2339
2339
|
});
|
|
2340
2340
|
}
|
|
@@ -2389,7 +2389,7 @@ var MeteringService = class {
|
|
|
2389
2389
|
model: input.model,
|
|
2390
2390
|
operation: input.operation,
|
|
2391
2391
|
serviceTier,
|
|
2392
|
-
// Stryker disable next-line ConditionalExpression
|
|
2392
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { feature: undefined } is equivalent to {} because markup.resolve treats absent and undefined feature the same
|
|
2393
2393
|
...input.feature !== void 0 ? { feature: input.feature } : {}
|
|
2394
2394
|
});
|
|
2395
2395
|
return { rawCostNanoUsd, billedCostNanoUsd: markup.apply(rawCostNanoUsd) };
|
|
@@ -2591,7 +2591,7 @@ var MeteringService = class {
|
|
|
2591
2591
|
priceMissing: false,
|
|
2592
2592
|
status: "pending",
|
|
2593
2593
|
isSystemCost,
|
|
2594
|
-
// Stryker disable next-line ConditionalExpression
|
|
2594
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { systemCostCategory: undefined } is equivalent to {}
|
|
2595
2595
|
...context.systemCostCategory !== void 0 ? { systemCostCategory: context.systemCostCategory } : {},
|
|
2596
2596
|
enforced: !isSystemCost,
|
|
2597
2597
|
occurredAt
|
|
@@ -2689,7 +2689,7 @@ var MeteringService = class {
|
|
|
2689
2689
|
if (normalizer !== void 0) return this.normalize(normalizer, input.usage);
|
|
2690
2690
|
if (isNormalizedUsage(input.usage)) return input.usage;
|
|
2691
2691
|
throw new AiTokensException("AI_TOKENS_UNKNOWN_PROVIDER", void 0, {
|
|
2692
|
-
// Stryker disable next-line StringLiteral
|
|
2692
|
+
// Stryker disable next-line StringLiteral: error reason text is internal diagnostics
|
|
2693
2693
|
reason: "raw usage requires a preset or normalizer, or an already-normalized usage"
|
|
2694
2694
|
});
|
|
2695
2695
|
}
|
|
@@ -2792,7 +2792,7 @@ var WalletService = class {
|
|
|
2792
2792
|
amountNanoUsd: input.amountNanoUsd,
|
|
2793
2793
|
priority: input.priority ?? 0,
|
|
2794
2794
|
effectiveAt: input.effectiveAt ?? /* @__PURE__ */ new Date(),
|
|
2795
|
-
// Stryker disable next-line ConditionalExpression
|
|
2795
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { expiresAt: undefined } is equivalent to {} because InMemoryWalletStore and consumers check expiresAt !== undefined
|
|
2796
2796
|
...input.expiresAt !== void 0 ? { expiresAt: input.expiresAt } : {},
|
|
2797
2797
|
idempotencyKey: input.idempotencyKey,
|
|
2798
2798
|
reason: input.reason
|
|
@@ -2801,7 +2801,7 @@ var WalletService = class {
|
|
|
2801
2801
|
walletId: entry.walletId,
|
|
2802
2802
|
entryId: entry.id,
|
|
2803
2803
|
amountNanoUsd: entry.amountNanoUsd,
|
|
2804
|
-
// Stryker disable next-line ConditionalExpression
|
|
2804
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { expiresAt: undefined } is equivalent to {} because event consumers check expiresAt !== undefined
|
|
2805
2805
|
...entry.expiresAt !== void 0 ? { expiresAt: entry.expiresAt } : {}
|
|
2806
2806
|
};
|
|
2807
2807
|
await this.events.granted(ref, granted);
|
|
@@ -2832,16 +2832,16 @@ var WalletService = class {
|
|
|
2832
2832
|
throw this.invalid("a debit without a usageRecordId must carry a reason");
|
|
2833
2833
|
}
|
|
2834
2834
|
const entry = {
|
|
2835
|
-
// Stryker disable next-line StringLiteral
|
|
2835
|
+
// Stryker disable next-line StringLiteral: placeholder walletId; the store's insert always assigns the real wallet id and never reads this sentinel, so any string here is equivalent
|
|
2836
2836
|
walletId: "",
|
|
2837
2837
|
type: "debit",
|
|
2838
2838
|
amountNanoUsd: -input.amountNanoUsd,
|
|
2839
2839
|
priority: 0,
|
|
2840
2840
|
effectiveAt: /* @__PURE__ */ new Date(),
|
|
2841
|
-
// Stryker disable next-line ConditionalExpression
|
|
2841
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { usageRecordId: undefined } is equivalent to {} because store and consumers check usageRecordId !== undefined
|
|
2842
2842
|
...input.usageRecordId !== void 0 ? { usageRecordId: input.usageRecordId } : {},
|
|
2843
2843
|
idempotencyKey: input.idempotencyKey,
|
|
2844
|
-
// Stryker disable next-line ConditionalExpression
|
|
2844
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { reason: undefined } is equivalent to {} because store and consumers check reason !== undefined
|
|
2845
2845
|
...input.reason !== void 0 ? { reason: input.reason } : {}
|
|
2846
2846
|
};
|
|
2847
2847
|
const debited = await this.conditionalDebit(ref, entry, input.amountNanoUsd);
|
|
@@ -2868,7 +2868,7 @@ var WalletService = class {
|
|
|
2868
2868
|
amountNanoUsd: input.amountNanoUsd,
|
|
2869
2869
|
priority: 0,
|
|
2870
2870
|
effectiveAt: /* @__PURE__ */ new Date(),
|
|
2871
|
-
// Stryker disable next-line ConditionalExpression,ObjectLiteral
|
|
2871
|
+
// Stryker disable next-line ConditionalExpression,ObjectLiteral: CE true / OL {}: spreading { usageRecordId: undefined } is equivalent to {} because store and consumers check usageRecordId !== undefined
|
|
2872
2872
|
...input.usageRecordId !== void 0 ? { usageRecordId: input.usageRecordId } : {},
|
|
2873
2873
|
idempotencyKey: input.idempotencyKey,
|
|
2874
2874
|
reason: input.reason
|
|
@@ -2925,8 +2925,8 @@ var WalletService = class {
|
|
|
2925
2925
|
amountNanoUsd: input.amountNanoUsd,
|
|
2926
2926
|
priority: 0,
|
|
2927
2927
|
effectiveAt: /* @__PURE__ */ new Date(),
|
|
2928
|
-
// Stryker disable next-line ConditionalExpression
|
|
2929
|
-
// Stryker disable next-line ConditionalExpression
|
|
2928
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { usageRecordId: undefined } is equivalent to {} because store and consumers check usageRecordId !== undefined
|
|
2929
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { usageRecordId: undefined } is equivalent to {} because store and consumers check usageRecordId !== undefined
|
|
2930
2930
|
...input.usageRecordId !== void 0 ? { usageRecordId: input.usageRecordId } : {},
|
|
2931
2931
|
idempotencyKey: input.idempotencyKey,
|
|
2932
2932
|
reason: input.reason
|
|
@@ -3558,11 +3558,11 @@ function featureMatches3(features, feature) {
|
|
|
3558
3558
|
}
|
|
3559
3559
|
function limitsOf(budget) {
|
|
3560
3560
|
return {
|
|
3561
|
-
// Stryker disable next-line ConditionalExpression
|
|
3561
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { nanoUsd: undefined } is equivalent to {} because all consumers check limits.nanoUsd !== undefined
|
|
3562
3562
|
...budget.limitNanoUsd !== void 0 ? { nanoUsd: budget.limitNanoUsd } : {},
|
|
3563
|
-
// Stryker disable next-line ConditionalExpression
|
|
3563
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { tokens: undefined } is equivalent to {} because all consumers check limits.tokens !== undefined
|
|
3564
3564
|
...budget.limitTokens !== void 0 ? { tokens: budget.limitTokens } : {},
|
|
3565
|
-
// Stryker disable next-line ConditionalExpression
|
|
3565
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { count: undefined } is equivalent to {} because all consumers check limits.count !== undefined
|
|
3566
3566
|
...budget.limitCount !== void 0 ? { count: budget.limitCount } : {}
|
|
3567
3567
|
};
|
|
3568
3568
|
}
|
|
@@ -3602,11 +3602,11 @@ function ratio(spent, limit) {
|
|
|
3602
3602
|
}
|
|
3603
3603
|
function limitSnapshot(limits) {
|
|
3604
3604
|
return {
|
|
3605
|
-
// Stryker disable next-line ConditionalExpression
|
|
3605
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { nanoUsd: undefined } is equivalent to {} for event consumers who check field !== undefined
|
|
3606
3606
|
...limits.nanoUsd !== void 0 ? { nanoUsd: limits.nanoUsd } : {},
|
|
3607
|
-
// Stryker disable next-line ConditionalExpression
|
|
3607
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { tokens: undefined } is equivalent to {} for event consumers who check field !== undefined
|
|
3608
3608
|
...limits.tokens !== void 0 ? { tokens: limits.tokens } : {},
|
|
3609
|
-
// Stryker disable next-line ConditionalExpression
|
|
3609
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { count: undefined } is equivalent to {} for event consumers who check field !== undefined
|
|
3610
3610
|
...limits.count !== void 0 ? { count: limits.count } : {}
|
|
3611
3611
|
};
|
|
3612
3612
|
}
|
|
@@ -3615,11 +3615,11 @@ function spendSnapshot(spend) {
|
|
|
3615
3615
|
}
|
|
3616
3616
|
function remainingSnapshot(limits, spend) {
|
|
3617
3617
|
return {
|
|
3618
|
-
// Stryker disable next-line ConditionalExpression
|
|
3618
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { nanoUsd: undefined } is equivalent to {} for event consumers who check field !== undefined
|
|
3619
3619
|
...limits.nanoUsd !== void 0 ? { nanoUsd: max0(limits.nanoUsd - spend.spentNanoUsd) } : {},
|
|
3620
|
-
// Stryker disable next-line ConditionalExpression
|
|
3620
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { tokens: undefined } is equivalent to {} for event consumers who check field !== undefined
|
|
3621
3621
|
...limits.tokens !== void 0 ? { tokens: Math.max(0, limits.tokens - spend.spentTokens) } : {},
|
|
3622
|
-
// Stryker disable next-line ConditionalExpression
|
|
3622
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { count: undefined } is equivalent to {} for event consumers who check field !== undefined
|
|
3623
3623
|
...limits.count !== void 0 ? { count: Math.max(0, limits.count - spend.spentCount) } : {}
|
|
3624
3624
|
};
|
|
3625
3625
|
}
|
|
@@ -3627,7 +3627,7 @@ function buildStatus(budget, windowStart, resetsAt, spend) {
|
|
|
3627
3627
|
const limits = limitsOf(budget);
|
|
3628
3628
|
return {
|
|
3629
3629
|
budgetId: budget.id,
|
|
3630
|
-
// Stryker disable next-line ConditionalExpression
|
|
3630
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { features: undefined } is equivalent to {} because status consumers check features !== undefined
|
|
3631
3631
|
...budget.features !== void 0 ? { features: budget.features } : {},
|
|
3632
3632
|
window: budget.window,
|
|
3633
3633
|
windowStart,
|
|
@@ -3794,29 +3794,29 @@ UsageReportService = __decorateClass([
|
|
|
3794
3794
|
function toLedgerFilter(filter, limit) {
|
|
3795
3795
|
return {
|
|
3796
3796
|
tenantId: filter.tenantId,
|
|
3797
|
-
// Stryker disable next-line ConditionalExpression
|
|
3797
|
+
// Stryker disable next-line ConditionalExpression: spreading { scope: undefined } is equivalent to {} because InMemoryLedgerStore uses truthiness; the 'false' variant is covered by the scope isolation test
|
|
3798
3798
|
...filter.scope !== void 0 ? { scope: filter.scope } : {},
|
|
3799
|
-
// Stryker disable next-line ConditionalExpression
|
|
3799
|
+
// Stryker disable next-line ConditionalExpression: spreading { beneficiary: undefined } is equivalent to {} for the same reason
|
|
3800
3800
|
...filter.beneficiary !== void 0 ? { beneficiary: filter.beneficiary } : {},
|
|
3801
|
-
// Stryker disable next-line ConditionalExpression
|
|
3801
|
+
// Stryker disable next-line ConditionalExpression: spreading { feature: undefined } does not change the !== undefined check in matches()
|
|
3802
3802
|
...filter.feature !== void 0 ? { feature: filter.feature } : {},
|
|
3803
|
-
// Stryker disable next-line ConditionalExpression
|
|
3803
|
+
// Stryker disable next-line ConditionalExpression: spreading { features: undefined } does not change the truthiness check in matches()
|
|
3804
3804
|
...filter.features !== void 0 ? { features: filter.features } : {},
|
|
3805
|
-
// Stryker disable next-line ConditionalExpression
|
|
3805
|
+
// Stryker disable next-line ConditionalExpression: spreading { provider: undefined } does not change the !== undefined check in matches()
|
|
3806
3806
|
...filter.provider !== void 0 ? { provider: filter.provider } : {},
|
|
3807
|
-
// Stryker disable next-line ConditionalExpression
|
|
3807
|
+
// Stryker disable next-line ConditionalExpression: spreading { model: undefined } does not change the !== undefined check in matches()
|
|
3808
3808
|
...filter.model !== void 0 ? { model: filter.model } : {},
|
|
3809
|
-
// Stryker disable next-line ConditionalExpression
|
|
3809
|
+
// Stryker disable next-line ConditionalExpression: spreading { operation: undefined } does not change the !== undefined check in matches()
|
|
3810
3810
|
...filter.operation !== void 0 ? { operation: filter.operation } : {},
|
|
3811
|
-
// Stryker disable next-line ConditionalExpression
|
|
3811
|
+
// Stryker disable next-line ConditionalExpression: spreading { serviceTier: undefined } does not change the !== undefined check in matches()
|
|
3812
3812
|
...filter.serviceTier !== void 0 ? { serviceTier: filter.serviceTier } : {},
|
|
3813
|
-
// Stryker disable next-line ConditionalExpression
|
|
3813
|
+
// Stryker disable next-line ConditionalExpression: spreading { tags: undefined } does not change the truthiness check in matches()
|
|
3814
3814
|
...filter.tags !== void 0 ? { tags: filter.tags } : {},
|
|
3815
|
-
// Stryker disable next-line ConditionalExpression
|
|
3815
|
+
// Stryker disable next-line ConditionalExpression: spreading { isSystemCost: undefined } does not change the !== undefined check in matches()
|
|
3816
3816
|
...filter.isSystemCost !== void 0 ? { isSystemCost: filter.isSystemCost } : {},
|
|
3817
|
-
// Stryker disable next-line ConditionalExpression
|
|
3817
|
+
// Stryker disable next-line ConditionalExpression: spreading { systemCostCategory: undefined } does not change the !== undefined check in matches()
|
|
3818
3818
|
...filter.systemCostCategory !== void 0 ? { systemCostCategory: filter.systemCostCategory } : {},
|
|
3819
|
-
// Stryker disable next-line ConditionalExpression
|
|
3819
|
+
// Stryker disable next-line ConditionalExpression: spreading { enforcedOnly: undefined } does not change the === true check in matches()
|
|
3820
3820
|
...filter.enforcedOnly !== void 0 ? { enforcedOnly: filter.enforcedOnly } : {},
|
|
3821
3821
|
status: filter.status ?? [...BALANCE_STATUSES2],
|
|
3822
3822
|
from: filter.from,
|
|
@@ -4002,9 +4002,9 @@ var MeteringInterceptor = class {
|
|
|
4002
4002
|
const context = await this.resolveContext(executionContext, config, enrichment);
|
|
4003
4003
|
return this.metering.record({
|
|
4004
4004
|
usage,
|
|
4005
|
-
// Stryker disable next-line ConditionalExpression
|
|
4005
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { preset: undefined } is equivalent to {} because MeteringService checks preset !== undefined
|
|
4006
4006
|
...config.preset !== void 0 ? { preset: config.preset } : {},
|
|
4007
|
-
// Stryker disable next-line ConditionalExpression
|
|
4007
|
+
// Stryker disable next-line ConditionalExpression: CE true: spreading { tags: undefined } is equivalent to {} because MeteringService checks tags !== undefined
|
|
4008
4008
|
context: { ...context, enforce: true, isSystemCost: config.isSystemCost ?? false, ...config.tags !== void 0 ? { tags: config.tags } : {} }
|
|
4009
4009
|
});
|
|
4010
4010
|
}
|
|
@@ -4332,24 +4332,24 @@ function preset(provider, normalizer, ratingMode) {
|
|
|
4332
4332
|
return { provider, normalizer, ratingMode };
|
|
4333
4333
|
}
|
|
4334
4334
|
var providerPresets = {
|
|
4335
|
-
// Stryker disable next-line StringLiteral
|
|
4335
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests that exercise the full preset→MeteringService→UsageRecord path
|
|
4336
4336
|
openaiChat: preset("openai", normalizeOpenAiChatUsage, "rate-table"),
|
|
4337
|
-
// Stryker disable next-line StringLiteral
|
|
4337
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4338
4338
|
openaiResponses: preset("openai", normalizeOpenAiResponsesUsage, "rate-table"),
|
|
4339
|
-
// Stryker disable next-line StringLiteral
|
|
4339
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4340
4340
|
azureOpenai: preset("azure-openai", normalizeOpenAiChatUsage, "rate-table"),
|
|
4341
|
-
// Stryker disable next-line StringLiteral
|
|
4341
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4342
4342
|
anthropic: preset("anthropic", normalizeAnthropicUsage, "rate-table"),
|
|
4343
|
-
// Stryker disable next-line StringLiteral
|
|
4343
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4344
4344
|
gemini: preset("gemini", normalizeGeminiUsage, "rate-table"),
|
|
4345
|
-
// Stryker disable next-line StringLiteral
|
|
4345
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4346
4346
|
vertex: preset("vertex", normalizeGeminiUsage, "rate-table"),
|
|
4347
|
-
// Stryker disable next-line StringLiteral
|
|
4347
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4348
4348
|
bedrock: preset("bedrock", normalizeBedrockConverseUsage, "rate-table"),
|
|
4349
|
-
// Stryker disable next-line StringLiteral
|
|
4349
|
+
// Stryker disable next-line StringLiteral: provider ID; only observable via integration tests
|
|
4350
4350
|
mistral: preset("mistral", normalizeMistralUsage, "rate-table"),
|
|
4351
4351
|
vercelAiSdk: preset("openai", normalizeVercelAiSdkUsage, "rate-table"),
|
|
4352
|
-
// Stryker disable next-line StringLiteral
|
|
4352
|
+
// Stryker disable next-line StringLiteral: provider ID and rating mode; only observable via integration tests
|
|
4353
4353
|
openrouter: preset("openrouter", normalizeOpenRouterUsage, "provider-reported"),
|
|
4354
4354
|
/** A custom OpenAI-compatible provider (DeepSeek, xAI, Groq, …). */
|
|
4355
4355
|
openaiCompatible: (id) => preset(id, normalizeOpenAiCompatibleUsage, "rate-table")
|
package/dist/shared/index.cjs
CHANGED
|
@@ -332,9 +332,9 @@ function normalizeMistralUsage(raw) {
|
|
|
332
332
|
provider: "mistral",
|
|
333
333
|
model: str(response.model) ?? "",
|
|
334
334
|
operation: "chat",
|
|
335
|
-
// Stryker disable next-line StringLiteral
|
|
335
|
+
// Stryker disable next-line StringLiteral: provider and field names in error messages are internal diagnostics
|
|
336
336
|
inputTokens: requireNum(usage.prompt_tokens, "mistral", "usage.prompt_tokens"),
|
|
337
|
-
// Stryker disable next-line StringLiteral
|
|
337
|
+
// Stryker disable next-line StringLiteral: provider and field names in error messages are internal diagnostics
|
|
338
338
|
outputTokens: requireNum(usage.completion_tokens, "mistral", "usage.completion_tokens"),
|
|
339
339
|
raw: usage
|
|
340
340
|
});
|
package/dist/shared/index.mjs
CHANGED
|
@@ -330,9 +330,9 @@ function normalizeMistralUsage(raw) {
|
|
|
330
330
|
provider: "mistral",
|
|
331
331
|
model: str(response.model) ?? "",
|
|
332
332
|
operation: "chat",
|
|
333
|
-
// Stryker disable next-line StringLiteral
|
|
333
|
+
// Stryker disable next-line StringLiteral: provider and field names in error messages are internal diagnostics
|
|
334
334
|
inputTokens: requireNum(usage.prompt_tokens, "mistral", "usage.prompt_tokens"),
|
|
335
|
-
// Stryker disable next-line StringLiteral
|
|
335
|
+
// Stryker disable next-line StringLiteral: provider and field names in error messages are internal diagnostics
|
|
336
336
|
outputTokens: requireNum(usage.completion_tokens, "mistral", "usage.completion_tokens"),
|
|
337
337
|
raw: usage
|
|
338
338
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bymax-one/nest-ai-tokens",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
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",
|
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
"scripts": {
|
|
77
77
|
"build": "pnpm clean && tsup",
|
|
78
78
|
"check:exports": "attw --pack . --profile strict",
|
|
79
|
+
"check:mutants": "node scripts/check-mutation-directives.mjs",
|
|
79
80
|
"check:published": "node scripts/check-published-surface.mjs",
|
|
80
81
|
"check:runtime": "node scripts/check-consumer-runtime.mjs",
|
|
81
82
|
"clean": "node -e \"const {rmSync}=require('node:fs');for(const d of ['dist','coverage'])rmSync(d,{recursive:true,force:true})\"",
|
|
@@ -87,7 +88,7 @@
|
|
|
87
88
|
"mutation:dry-run": "stryker run --dryRunOnly",
|
|
88
89
|
"mutation:incremental": "stryker run --incremental",
|
|
89
90
|
"prepare": "prisma generate",
|
|
90
|
-
"prepublishOnly": "pnpm clean && pnpm typecheck && pnpm lint && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published",
|
|
91
|
+
"prepublishOnly": "pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published",
|
|
91
92
|
"release": "npm publish --provenance --access public",
|
|
92
93
|
"size": "node scripts/check-size.mjs",
|
|
93
94
|
"test": "jest",
|