@broberg/ai-sdk 0.40.0 → 0.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-KXTCLLVF.js → chunk-B74RSBT5.js} +17 -8
- package/dist/chunk-B74RSBT5.js.map +1 -0
- package/dist/index.d.ts +22 -4
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/pricing.d.ts +92 -56
- package/dist/pricing.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-KXTCLLVF.js.map +0 -1
package/dist/pricing.d.ts
CHANGED
|
@@ -1,26 +1,49 @@
|
|
|
1
|
+
/** A price that is not per-token.
|
|
2
|
+
*
|
|
3
|
+
* Six units, not the two F050 was carded for. The form-forbidding test found ten
|
|
4
|
+
* MORE hand-written price constants than super's report named — speech billed per
|
|
5
|
+
* 1000 characters, transcription per audio-minute, OCR per page, a flat LoRA
|
|
6
|
+
* training fee, and two more per-image tables. Moving only the four that had been
|
|
7
|
+
* noticed would have left `caveats` reporting "covered" while four other units sat
|
|
8
|
+
* in four adapters' private constants: the same blindness, one unit along. */
|
|
9
|
+
type MediaUnit = "per_sec" | "per_image" | "per_1k_chars" | "per_min" | "per_page" | "per_training";
|
|
10
|
+
interface MediaPrice {
|
|
11
|
+
unit: MediaUnit;
|
|
12
|
+
/** USD per second (video) or per generated image. */
|
|
13
|
+
usd: number;
|
|
14
|
+
/** ISO date a HUMAN last checked this against the vendor's published price.
|
|
15
|
+
* Not derived from the monthly token job — that job never sees these. */
|
|
16
|
+
checkedAt: string;
|
|
17
|
+
/** Where the number comes from, so the next person can re-check it. */
|
|
18
|
+
source: string;
|
|
19
|
+
}
|
|
20
|
+
/** When a human last walked the whole media table against vendor pricing pages.
|
|
21
|
+
*
|
|
22
|
+
* ONE date for the table rather than trusting every row's own: a row added later
|
|
23
|
+
* with a fresh date would otherwise pull the table's average forward while the
|
|
24
|
+
* older rows sat unrevised. Freshness reads the OLDEST answer, and this is it. */
|
|
25
|
+
declare const MEDIA_PRICING_CHECKED_AT = "2026-09-05";
|
|
26
|
+
/** Default clip length billed when the caller passes no `durationSec`.
|
|
27
|
+
*
|
|
28
|
+
* It is an ASSUMPTION, not a measurement — the provider does not tell us how long
|
|
29
|
+
* the clip it returned actually is. Every cost derived from it is stamped
|
|
30
|
+
* `costBasis: "estimated"` so a consumer (and upmetrics) can tell it apart from a
|
|
31
|
+
* cost computed off a real duration. super reported using such a number as if it
|
|
32
|
+
* were measured and passing it on to Christian; that is the damage this stamp
|
|
33
|
+
* removes. */
|
|
34
|
+
declare const DEFAULT_CLIP_SEC = 8;
|
|
35
|
+
/** Look up a non-token price. Unknown → undefined (never a fabricated 0). */
|
|
36
|
+
declare function getMediaPrice(provider: string, model: string): MediaPrice | undefined;
|
|
37
|
+
|
|
1
38
|
type PriceRegion = "eu" | "us" | "cn" | "other";
|
|
2
|
-
|
|
39
|
+
/** Fields every price row carries, whatever it is billed in. */
|
|
40
|
+
interface BasePrice {
|
|
3
41
|
/** Vendor/provider prefix (e.g. "deepseek", "anthropic"). */
|
|
4
42
|
provider: string;
|
|
5
43
|
/** Model id (OpenRouter-style "vendor/model", or the bare model for curated entries). */
|
|
6
44
|
model: string;
|
|
7
45
|
/** Human label, when known. */
|
|
8
46
|
name?: string;
|
|
9
|
-
/** USD per 1M input tokens. */
|
|
10
|
-
inputPer1M: number;
|
|
11
|
-
/** USD per 1M output tokens. */
|
|
12
|
-
outputPer1M: number;
|
|
13
|
-
/** Pricing unit: "per_1m_tokens", or "per_sec" / "per_image" for a media model.
|
|
14
|
-
* Check it before reading the token rates — they are 0 on a media row, which is a
|
|
15
|
-
* placeholder and NOT a claim that the model is free. */
|
|
16
|
-
unit: string;
|
|
17
|
-
/** USD per second of generated video. Set only when `unit` is "per_sec". */
|
|
18
|
-
perSec?: number;
|
|
19
|
-
/** USD per generated image. Set only when `unit` is "per_image". */
|
|
20
|
-
perImage?: number;
|
|
21
|
-
/** ISO date this row was last verified. Media rows carry a HUMAN-set date; token
|
|
22
|
-
* rows inherit the inventory snapshot's. */
|
|
23
|
-
checkedAt?: string;
|
|
24
47
|
/** GDPR region derived from the PROVIDER NAME — a rough grouping, not a residency
|
|
25
48
|
* claim. It is `"other"` for vertex/bfl/fal/azure precisely because those take a
|
|
26
49
|
* configurable endpoint, so their region is a property of the CALL and not of the
|
|
@@ -29,7 +52,57 @@ interface ModelPrice {
|
|
|
29
52
|
region: PriceRegion;
|
|
30
53
|
/** "curated" = authoritative hand-maintained number; "inventory" = from inventory.json. */
|
|
31
54
|
source: "curated" | "inventory";
|
|
55
|
+
/** ISO date this row was last verified. Media rows carry a HUMAN-set date; token
|
|
56
|
+
* rows inherit the inventory snapshot's. */
|
|
57
|
+
checkedAt?: string;
|
|
32
58
|
}
|
|
59
|
+
/** A model billed per token. */
|
|
60
|
+
interface TokenModelPrice extends BasePrice {
|
|
61
|
+
unit: "per_1m_tokens";
|
|
62
|
+
/** USD per 1M input tokens. */
|
|
63
|
+
inputPer1M: number;
|
|
64
|
+
/** USD per 1M output tokens. */
|
|
65
|
+
outputPer1M: number;
|
|
66
|
+
/** Set when this model ALSO carries a non-token price — and that is the one the SDK
|
|
67
|
+
* bills with (F050.2).
|
|
68
|
+
*
|
|
69
|
+
* Gemini's image models are the real case: they have honest per-token rates for the
|
|
70
|
+
* prompt AND a per-image price for the output, and `ai.image` charges the per-image
|
|
71
|
+
* one. Returning only the token row is not WRONG the way whisper's fabricated $0 was
|
|
72
|
+
* — the rates are real — it just answers a question nobody asked, and hides the
|
|
73
|
+
* number that decides the bill. Both are true, so both are here. */
|
|
74
|
+
alsoBilled?: {
|
|
75
|
+
unit: MediaUnit;
|
|
76
|
+
usd: number;
|
|
77
|
+
checkedAt: string;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/** A model billed in anything else — per second, image, 1000 chars, minute, page,
|
|
81
|
+
* or training run (F050.2).
|
|
82
|
+
*
|
|
83
|
+
* **It deliberately has NO `inputPer1M`.** Until 0.40.0 a media row carried
|
|
84
|
+
* `inputPer1M: 0`, and super's report named the fault exactly: "a field that does not
|
|
85
|
+
* apply and a price that is free are the same number again" — the very distinction
|
|
86
|
+
* `costBasis: "unpriced"` exists for, one storey down. A 0 there is a placeholder that
|
|
87
|
+
* reads as a price. Splitting the type turns reading it into a COMPILE error instead. */
|
|
88
|
+
interface MediaModelPrice extends BasePrice {
|
|
89
|
+
unit: MediaUnit;
|
|
90
|
+
/** The price, in USD, for one of whatever `unit` names. ALWAYS set on a media row —
|
|
91
|
+
* read this rather than the unit-specific aliases below. */
|
|
92
|
+
usd: number;
|
|
93
|
+
/** USD per second. Set ONLY when `unit === "per_sec"`.
|
|
94
|
+
*
|
|
95
|
+
* 0.40.0 set this-or-`perImage` from a TWO-armed ternary over SIX units, so every
|
|
96
|
+
* non-per-second price was labelled `perImage`: `azure:tts` reported
|
|
97
|
+
* `perImage: 0.016` for a price that is per 1000 CHARACTERS. A confident wrong number
|
|
98
|
+
* under a name that lies about its own unit — worse than the 0 that was reported. */
|
|
99
|
+
perSec?: number;
|
|
100
|
+
/** USD per generated image. Set ONLY when `unit === "per_image"`. */
|
|
101
|
+
perImage?: number;
|
|
102
|
+
}
|
|
103
|
+
/** A price row. Narrow on `unit` before reading rates:
|
|
104
|
+
* `if (p.unit === "per_1m_tokens") … else …`. */
|
|
105
|
+
type ModelPrice = TokenModelPrice | MediaModelPrice;
|
|
33
106
|
interface PriceFilter {
|
|
34
107
|
provider?: string;
|
|
35
108
|
region?: PriceRegion;
|
|
@@ -41,14 +114,14 @@ interface PriceFilter {
|
|
|
41
114
|
/** Every non-token price the SDK bills from (F050). Separate from
|
|
42
115
|
* {@link listModelPrices} because the two answer different questions and mixing
|
|
43
116
|
* them silently changed what an existing caller's list meant. */
|
|
44
|
-
declare function listMediaPrices():
|
|
117
|
+
declare function listMediaPrices(): MediaModelPrice[];
|
|
45
118
|
/** Exact price for a model. `modelId` accepts "vendor/model", "provider:model", or a
|
|
46
119
|
* bare model/basename. Returns undefined if unknown. */
|
|
47
120
|
declare function getModelPrice(modelId: string): ModelPrice | undefined;
|
|
48
121
|
/** Every known model price (inventory, with the curated overlay applied). */
|
|
49
|
-
declare function listModelPrices():
|
|
122
|
+
declare function listModelPrices(): TokenModelPrice[];
|
|
50
123
|
/** Filter the price list (provider / region / max input rate / free-only). */
|
|
51
|
-
declare function findModelPrices(filter?: PriceFilter):
|
|
124
|
+
declare function findModelPrices(filter?: PriceFilter): TokenModelPrice[];
|
|
52
125
|
/** Convenience USD compute for a token-priced model; undefined if unknown / not token-priced. */
|
|
53
126
|
declare function priceCall(modelId: string, inputTokens: number, outputTokens: number): number | undefined;
|
|
54
127
|
/** ISO timestamp of the inventory snapshot these prices came from.
|
|
@@ -112,41 +185,4 @@ declare function warnIfPricingStale(nowMs?: number): void;
|
|
|
112
185
|
/** Test-only: forget that we already warned. */
|
|
113
186
|
declare function resetPricingWarningForTests(): void;
|
|
114
187
|
|
|
115
|
-
/** A price that is not per-token.
|
|
116
|
-
*
|
|
117
|
-
* Six units, not the two F050 was carded for. The form-forbidding test found ten
|
|
118
|
-
* MORE hand-written price constants than super's report named — speech billed per
|
|
119
|
-
* 1000 characters, transcription per audio-minute, OCR per page, a flat LoRA
|
|
120
|
-
* training fee, and two more per-image tables. Moving only the four that had been
|
|
121
|
-
* noticed would have left `caveats` reporting "covered" while four other units sat
|
|
122
|
-
* in four adapters' private constants: the same blindness, one unit along. */
|
|
123
|
-
type MediaUnit = "per_sec" | "per_image" | "per_1k_chars" | "per_min" | "per_page" | "per_training";
|
|
124
|
-
interface MediaPrice {
|
|
125
|
-
unit: MediaUnit;
|
|
126
|
-
/** USD per second (video) or per generated image. */
|
|
127
|
-
usd: number;
|
|
128
|
-
/** ISO date a HUMAN last checked this against the vendor's published price.
|
|
129
|
-
* Not derived from the monthly token job — that job never sees these. */
|
|
130
|
-
checkedAt: string;
|
|
131
|
-
/** Where the number comes from, so the next person can re-check it. */
|
|
132
|
-
source: string;
|
|
133
|
-
}
|
|
134
|
-
/** When a human last walked the whole media table against vendor pricing pages.
|
|
135
|
-
*
|
|
136
|
-
* ONE date for the table rather than trusting every row's own: a row added later
|
|
137
|
-
* with a fresh date would otherwise pull the table's average forward while the
|
|
138
|
-
* older rows sat unrevised. Freshness reads the OLDEST answer, and this is it. */
|
|
139
|
-
declare const MEDIA_PRICING_CHECKED_AT = "2026-09-05";
|
|
140
|
-
/** Default clip length billed when the caller passes no `durationSec`.
|
|
141
|
-
*
|
|
142
|
-
* It is an ASSUMPTION, not a measurement — the provider does not tell us how long
|
|
143
|
-
* the clip it returned actually is. Every cost derived from it is stamped
|
|
144
|
-
* `costBasis: "estimated"` so a consumer (and upmetrics) can tell it apart from a
|
|
145
|
-
* cost computed off a real duration. super reported using such a number as if it
|
|
146
|
-
* were measured and passing it on to Christian; that is the damage this stamp
|
|
147
|
-
* removes. */
|
|
148
|
-
declare const DEFAULT_CLIP_SEC = 8;
|
|
149
|
-
/** Look up a non-token price. Unknown → undefined (never a fabricated 0). */
|
|
150
|
-
declare function getMediaPrice(provider: string, model: string): MediaPrice | undefined;
|
|
151
|
-
|
|
152
188
|
export { DEFAULT_CLIP_SEC, MEDIA_PRICING_CHECKED_AT, type MediaPrice, type MediaUnit, type ModelPrice, PRICING_STALE_AFTER_DAYS, type PriceFilter, type PriceRegion, type PricingFreshness, type UnitFreshness, findModelPrices, getMediaPrice, getModelPrice, listMediaPrices, listModelPrices, priceCall, pricingFreshness, pricingGeneratedAt, resetPricingWarningForTests, warnIfPricingStale };
|
package/dist/pricing.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@broberg/ai-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Unified AI/LLM SDK
|
|
3
|
+
"version": "0.41.0",
|
|
4
|
+
"description": "Unified AI/LLM SDK \u2014 one facade, all providers, all capabilities, first-class cost control on every call.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "FSL-1.1-Apache-2.0",
|
|
7
7
|
"author": "Christian Broberg <cb@webhouse.dk>",
|