@usagekit/providers 0.8.0 → 0.9.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.
@@ -0,0 +1,401 @@
1
+ // Endpoint request tables fetched 2026-10-11. A new field is unknown until classified here.
2
+ // Neutral fields select/filter/order results within the priced count; none adds a documented fee.
3
+ // Price coefficients: https://dataforseo.com/pricing/serp/google-organic-serp-api
4
+ // https://dataforseo.com/pricing/dataforseo-labs/dataforseo-google-api
5
+ // https://dataforseo.com/pricing/backlinks/backlinks
6
+ export const requestPricing = {
7
+ // Request field inventory: https://docs.dataforseo.com/v3/backlinks/backlinks/live/
8
+ "backlinks.backlinks.live": {
9
+ source: "https://docs.dataforseo.com/v3/backlinks/backlinks/live/",
10
+ formula: "2.4 + 0.0036 * rowCount cents; summary one row, backlinks limit, history count unknown",
11
+ priceFields: {
12
+ limit: {
13
+ formula: "(base + per-item * limit); documented default, 1..1000; zero unknown",
14
+ defaultCount: 100,
15
+ },
16
+ },
17
+ neutralFields: [
18
+ "target",
19
+ "mode",
20
+ "custom_mode",
21
+ "filters",
22
+ "order_by",
23
+ "offset",
24
+ "search_after_token",
25
+ "backlinks_status_type",
26
+ "include_subdomains",
27
+ "exclude_internal_backlinks",
28
+ "rank_scale",
29
+ "tag",
30
+ ],
31
+ },
32
+ // Request field inventory: https://docs.dataforseo.com/v3/backlinks/history/live/
33
+ "backlinks.history.live": {
34
+ source: "https://docs.dataforseo.com/v3/backlinks/history/live/",
35
+ formula: "2.4 + 0.0036 * rowCount cents; summary one row, backlinks limit, history count unknown",
36
+ priceFields: {
37
+ date_from: {
38
+ formula: "changes returned row count; count not derivable from the request",
39
+ },
40
+ date_to: {
41
+ formula: "changes returned row count; count not derivable from the request",
42
+ },
43
+ },
44
+ neutralFields: ["target", "rank_scale", "tag"],
45
+ },
46
+ // Request field inventory: https://docs.dataforseo.com/v3/backlinks/summary/live/
47
+ "backlinks.summary.live": {
48
+ source: "https://docs.dataforseo.com/v3/backlinks/summary/live/",
49
+ formula: "2.4 + 0.0036 * rowCount cents; summary one row, backlinks limit, history count unknown",
50
+ priceFields: {},
51
+ neutralFields: [
52
+ "target",
53
+ "include_subdomains",
54
+ "include_indirect_links",
55
+ "exclude_internal_backlinks",
56
+ "internal_list_limit",
57
+ "backlinks_status_type",
58
+ "backlinks_filters",
59
+ "rank_scale",
60
+ "tag",
61
+ ],
62
+ },
63
+ // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/domain_rank_overview/live/
64
+ "dataforseo_labs.google.domain_rank_overview.live": {
65
+ source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/domain_rank_overview/live/",
66
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
67
+ priceFields: {
68
+ limit: {
69
+ formula: "(base + per-item * limit); documented default, 1..1000; zero unknown",
70
+ defaultCount: 100,
71
+ },
72
+ },
73
+ neutralFields: [
74
+ "target",
75
+ "location_name",
76
+ "location_code",
77
+ "language_name",
78
+ "language_code",
79
+ "ignore_synonyms",
80
+ "offset",
81
+ "tag",
82
+ ],
83
+ },
84
+ // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/historical_rank_overview/live/
85
+ "dataforseo_labs.google.historical_rank_overview.live": {
86
+ source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/historical_rank_overview/live/",
87
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
88
+ priceFields: {
89
+ include_clickstream_data: {
90
+ formula: "true doubles entire request charge",
91
+ },
92
+ date_from: {
93
+ formula: "changes returned row count; count not derivable from the request",
94
+ },
95
+ date_to: {
96
+ formula: "changes returned row count; count not derivable from the request",
97
+ },
98
+ },
99
+ neutralFields: [
100
+ "target",
101
+ "location_name",
102
+ "location_code",
103
+ "language_name",
104
+ "language_code",
105
+ "correlate",
106
+ "ignore_synonyms",
107
+ "tag",
108
+ ],
109
+ },
110
+ // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/
111
+ "dataforseo_labs.google.keyword_ideas.live": {
112
+ source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/",
113
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
114
+ priceFields: {
115
+ include_clickstream_data: {
116
+ formula: "true doubles entire request charge",
117
+ },
118
+ limit: {
119
+ formula: "(base + per-item * limit); documented default, 1..1000; zero unknown",
120
+ defaultCount: 700,
121
+ },
122
+ offset_token: {
123
+ formula: "unknown: prior task options replace all supplied parameters except limit",
124
+ unpricedWhen: "present",
125
+ },
126
+ },
127
+ neutralFields: [
128
+ "keywords",
129
+ "location_name",
130
+ "location_code",
131
+ "language_name",
132
+ "language_code",
133
+ "closely_variants",
134
+ "ignore_synonyms",
135
+ "include_serp_info",
136
+ "offset",
137
+ "filters",
138
+ "order_by",
139
+ "tag",
140
+ ],
141
+ },
142
+ // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_overview/live/
143
+ "dataforseo_labs.google.keyword_overview.live": {
144
+ source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_overview/live/",
145
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
146
+ priceFields: {
147
+ keywords: {
148
+ formula: "base + 0.012 cents * keywords.length; clickstream doubles total",
149
+ },
150
+ include_clickstream_data: {
151
+ formula: "true doubles entire request charge",
152
+ },
153
+ },
154
+ neutralFields: [
155
+ "location_name",
156
+ "location_code",
157
+ "language_name",
158
+ "language_code",
159
+ "include_serp_info",
160
+ "tag",
161
+ ],
162
+ },
163
+ // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_suggestions/live/
164
+ "dataforseo_labs.google.keyword_suggestions.live": {
165
+ source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_suggestions/live/",
166
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
167
+ priceFields: {
168
+ include_seed_keyword: {
169
+ formula: "false neutral; true unknown because extra item count is unconfirmed",
170
+ unpricedWhen: "true",
171
+ },
172
+ include_clickstream_data: {
173
+ formula: "true doubles entire request charge",
174
+ },
175
+ limit: {
176
+ formula: "(base + per-item * limit); documented default, 1..1000; zero unknown",
177
+ defaultCount: 100,
178
+ },
179
+ offset_token: {
180
+ formula: "unknown: prior task options replace all supplied parameters except limit",
181
+ unpricedWhen: "present",
182
+ },
183
+ },
184
+ neutralFields: [
185
+ "keyword",
186
+ "location_name",
187
+ "location_code",
188
+ "language_name",
189
+ "language_code",
190
+ "include_serp_info",
191
+ "exact_match",
192
+ "ignore_synonyms",
193
+ "filters",
194
+ "order_by",
195
+ "offset",
196
+ "tag",
197
+ ],
198
+ },
199
+ // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/ranked_keywords/live/
200
+ "dataforseo_labs.google.ranked_keywords.live": {
201
+ source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/ranked_keywords/live/",
202
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
203
+ priceFields: {
204
+ include_clickstream_data: {
205
+ formula: "true doubles entire request charge",
206
+ },
207
+ limit: {
208
+ formula: "(base + per-item * limit); documented default, 1..1000; zero unknown",
209
+ defaultCount: 100,
210
+ },
211
+ },
212
+ neutralFields: [
213
+ "target",
214
+ "location_name",
215
+ "location_code",
216
+ "language_name",
217
+ "language_code",
218
+ "ignore_synonyms",
219
+ "item_types",
220
+ "offset",
221
+ "load_rank_absolute",
222
+ "historical_serp_mode",
223
+ "filters",
224
+ "order_by",
225
+ "tag",
226
+ ],
227
+ },
228
+ // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/related_keywords/live/
229
+ "dataforseo_labs.google.related_keywords.live": {
230
+ source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/related_keywords/live/",
231
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
232
+ priceFields: {
233
+ include_seed_keyword: {
234
+ formula: "false neutral; true unknown because extra item count is unconfirmed",
235
+ unpricedWhen: "true",
236
+ },
237
+ include_clickstream_data: {
238
+ formula: "true doubles entire request charge",
239
+ },
240
+ limit: {
241
+ formula: "(base + per-item * limit); documented default, 1..1000; zero unknown",
242
+ defaultCount: 100,
243
+ },
244
+ },
245
+ neutralFields: [
246
+ "keyword",
247
+ "location_name",
248
+ "location_code",
249
+ "language_name",
250
+ "language_code",
251
+ "depth",
252
+ "include_serp_info",
253
+ "ignore_synonyms",
254
+ "replace_with_core_keyword",
255
+ "filters",
256
+ "order_by",
257
+ "offset",
258
+ "tag",
259
+ ],
260
+ },
261
+ // Request field inventory: https://docs.dataforseo.com/v3/dataforseo_labs/google/relevant_pages/live/
262
+ "dataforseo_labs.google.relevant_pages.live": {
263
+ source: "https://docs.dataforseo.com/v3/dataforseo_labs/google/relevant_pages/live/",
264
+ formula: "(base + perItem * itemCount) * (clickstream ? 2 : 1); historical count unknown; ordinary base 1.2, perItem 0.012 cents; historical base 12, perItem 0.12 cents",
265
+ priceFields: {
266
+ include_clickstream_data: {
267
+ formula: "true doubles entire request charge",
268
+ },
269
+ limit: {
270
+ formula: "(base + per-item * limit); documented default, 1..1000; zero unknown",
271
+ defaultCount: 100,
272
+ },
273
+ },
274
+ neutralFields: [
275
+ "target",
276
+ "location_name",
277
+ "location_code",
278
+ "language_name",
279
+ "language_code",
280
+ "item_types",
281
+ "offset",
282
+ "historical_serp_mode",
283
+ "ignore_synonyms",
284
+ "filters",
285
+ "order_by",
286
+ "tag",
287
+ ],
288
+ },
289
+ // Request field inventory: https://docs.dataforseo.com/v3/serp/google/organic/live/advanced/
290
+ "serp.google.organic.live.advanced": {
291
+ source: "https://docs.dataforseo.com/v3/serp/google/organic/live/advanced/",
292
+ formula: "pages * (base + rectangle surcharge + AI surcharge + 0.015 * clicks) * 5^operatorCount; full base per page; surcharge scaling is a conservative bound",
293
+ priceFields: {
294
+ keyword: {
295
+ formula: "5^n for distinct documented operators after decoding and NFKC; SERP only",
296
+ },
297
+ depth: {
298
+ formula: "ceil(depth / 10), default 10; take max with max_crawl_pages",
299
+ },
300
+ load_async_ai_overview: {
301
+ formula: "true adds one base per page before operator multiplication; high task priority uses the larger pricing-table amount",
302
+ },
303
+ max_crawl_pages: {
304
+ formula: "max(ceil(depth / 10), max_crawl_pages)",
305
+ },
306
+ search_param: {
307
+ formula: "5^n for distinct documented operators after decoding and NFKC; shared with keyword",
308
+ },
309
+ people_also_ask_click_depth: {
310
+ formula: "1..4 clicks at 0.015 cents per click; reserve on every page with operator multiplication",
311
+ },
312
+ calculate_rectangles: {
313
+ formula: "true adds one base per page before operator multiplication; high task priority uses the larger pricing-table amount",
314
+ },
315
+ url: {
316
+ formula: "unknown: provider derives other request fields from URL",
317
+ unpricedWhen: "present",
318
+ },
319
+ },
320
+ neutralFields: [
321
+ "location_code",
322
+ "language_code",
323
+ "device",
324
+ "location_name",
325
+ "language_name",
326
+ "os",
327
+ "tag",
328
+ "stop_crawl_on_match",
329
+ "remove_from_url",
330
+ "group_organic_results",
331
+ "browser_screen_width",
332
+ "browser_screen_height",
333
+ "browser_screen_resolution_ratio",
334
+ "location_coordinate",
335
+ "se_domain",
336
+ "target",
337
+ "target_search_mode",
338
+ "find_targets_in",
339
+ "ignore_targets_in",
340
+ ],
341
+ },
342
+ // Request field inventory: https://docs.dataforseo.com/v3/serp/google/organic/task_post/
343
+ "serp.google.organic.task_post": {
344
+ source: "https://docs.dataforseo.com/v3/serp/google/organic/task_post/",
345
+ formula: "pages * (base + rectangle surcharge + AI surcharge + 0.015 * clicks) * 5^operatorCount; full base per page; surcharge scaling is a conservative bound",
346
+ priceFields: {
347
+ keyword: {
348
+ formula: "5^n for distinct documented operators after decoding and NFKC; SERP only",
349
+ },
350
+ depth: {
351
+ formula: "ceil(depth / 10), default 10; take max with max_crawl_pages",
352
+ },
353
+ load_async_ai_overview: {
354
+ formula: "true adds one base per page before operator multiplication; high task priority uses the larger pricing-table amount",
355
+ },
356
+ priority: {
357
+ formula: "1 normal base 0.06 cents; 2 high base 0.12 cents",
358
+ },
359
+ max_crawl_pages: {
360
+ formula: "max(ceil(depth / 10), max_crawl_pages)",
361
+ },
362
+ search_param: {
363
+ formula: "5^n for distinct documented operators after decoding and NFKC; shared with keyword",
364
+ },
365
+ people_also_ask_click_depth: {
366
+ formula: "1..4 clicks at 0.015 cents per click; reserve on every page with operator multiplication",
367
+ },
368
+ calculate_rectangles: {
369
+ formula: "true adds one base per page before operator multiplication; high task priority uses the larger pricing-table amount",
370
+ },
371
+ url: {
372
+ formula: "unknown: provider derives other request fields from URL",
373
+ unpricedWhen: "present",
374
+ },
375
+ },
376
+ neutralFields: [
377
+ "location_code",
378
+ "language_code",
379
+ "device",
380
+ "pingback_url",
381
+ "postback_url",
382
+ "postback_data",
383
+ "location_name",
384
+ "location_coordinate",
385
+ "language_name",
386
+ "tag",
387
+ "os",
388
+ "stop_crawl_on_match",
389
+ "remove_from_url",
390
+ "expand_ai_overview",
391
+ "group_organic_results",
392
+ "browser_screen_width",
393
+ "browser_screen_height",
394
+ "browser_screen_resolution_ratio",
395
+ "target_search_mode",
396
+ "find_targets_in",
397
+ "ignore_targets_in",
398
+ "se_domain",
399
+ ],
400
+ },
401
+ };
package/dist/execute.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- import type { DispatchGrant, Meter, MeterReserveInput, Operation, ReserveResult, SettleResult } from "@usagekit/core";
1
+ import type { DispatchGrant, Meter, Operation, ReserveResult, SettleResult } from "@usagekit/core";
2
2
  import type { Catalog } from "./catalog.js";
3
- import type { ProviderRequest, ProviderResponse } from "./types.js";
3
+ import type { PricedRequest } from "./priced-request.js";
4
+ import type { ProviderResponse } from "./types.js";
4
5
  export type ProviderExecution = {
5
6
  outcome: "completed";
6
7
  response: ProviderResponse;
@@ -20,10 +21,9 @@ export type ProviderExecution = {
20
21
  export type ProviderExecutionInput = {
21
22
  meter: Meter;
22
23
  catalog: Catalog;
23
- input: Omit<MeterReserveInput, "operation" | "options">;
24
- request: ProviderRequest;
25
- /** Reads the entire response before resolving. Inject credentials here, never in accounting. */
26
- dispatch(request: ProviderRequest): Promise<{
24
+ request: PricedRequest;
25
+ /** Sends the priced bytes and reads the entire response. Add credentials only at transport. */
26
+ dispatch(request: PricedRequest): Promise<{
27
27
  response: ProviderResponse;
28
28
  body: unknown;
29
29
  }>;
@@ -32,5 +32,7 @@ export type ProviderExecutionInput = {
32
32
  leaseTtlMs?: number;
33
33
  };
34
34
  /** Execute one provider request. A replay, rejected reserve or lost grant never calls dispatch.
35
+ * Submits provider receipt evidence only. Hosts settle platform customer-charge measurements
36
+ * separately, using a unit distinct from the provider's units to retain the customer hold.
35
37
  * Long transports must finish within leaseTtlMs; streaming/recovery workers are host-owned. */
36
- export declare function executeProviderRequest({ meter, catalog, input, request, dispatch, now, holder, leaseTtlMs, }: ProviderExecutionInput): Promise<ProviderExecution>;
38
+ export declare function executeProviderRequest({ meter, catalog, request, dispatch, now, holder, leaseTtlMs, }: ProviderExecutionInput): Promise<ProviderExecution>;
package/dist/execute.js CHANGED
@@ -1,15 +1,9 @@
1
1
  /** Execute one provider request. A replay, rejected reserve or lost grant never calls dispatch.
2
+ * Submits provider receipt evidence only. Hosts settle platform customer-charge measurements
3
+ * separately, using a unit distinct from the provider's units to retain the customer hold.
2
4
  * Long transports must finish within leaseTtlMs; streaming/recovery workers are host-owned. */
3
- export async function executeProviderRequest({ meter, catalog, input, request, dispatch, now = () => new Date(), holder = "provider-wrapper", leaseTtlMs = 60000, }) {
4
- const matched = catalog.match(input.provider, request);
5
- const { estimate, ...base } = input;
6
- const reserved = await meter.reserve({
7
- ...base,
8
- operation: matched.operation === "unknown" ? "unknown" : matched.operation.id,
9
- ...(matched.operation === "unknown"
10
- ? {}
11
- : { ...(estimate === undefined ? {} : { estimate }), options: matched.options }),
12
- });
5
+ export async function executeProviderRequest({ meter, catalog, request, dispatch, now = () => new Date(), holder = "provider-wrapper", leaseTtlMs = 60000, }) {
6
+ const { matched, input, admission: reserved } = request;
13
7
  if (matched.operation === "unknown")
14
8
  return { outcome: "not_dispatched", result: reserved };
15
9
  const ref = {
@@ -50,7 +44,7 @@ export async function executeProviderRequest({ meter, catalog, input, request, d
50
44
  let returned, receipt;
51
45
  try {
52
46
  returned = await dispatch(request);
53
- receipt = catalog.extract(input.provider, matched.operation.id, request, returned.response, returned.body);
47
+ receipt = catalog.extract(input.provider, matched.operation.id, request.parsed, returned.response, returned.body);
54
48
  }
55
49
  catch {
56
50
  const settled = await settle({
package/dist/index.d.ts CHANGED
@@ -8,7 +8,6 @@ export type { Catalog, CatalogConnection, CatalogEstimate, CatalogMatch, Estimat
8
8
  export { proposePlanBudget } from "./budget.js";
9
9
  export type { BudgetTarget } from "./budget.js";
10
10
  export { listEstimate, selectPriceRow } from "./prices.js";
11
- export { matchOperation } from "./match.js";
12
11
  export { pointer } from "./pointer.js";
13
12
  export { decimalQuantity, numberText, moneyFromCents, moneyFromDollars, requestsMeasured, } from "./receipts.js";
14
13
  export { loadFixtures, missingFixtures, verifyFixture } from "./fixtures.js";
@@ -19,3 +18,5 @@ export { executeProviderRequest } from "./execute.js";
19
18
  export type { ProviderExecution, ProviderExecutionInput } from "./execute.js";
20
19
  export { parseBillingExport } from "./billing.js";
21
20
  export type { ParsedBillingExport } from "./billing.js";
21
+ export { PricedRequest, RequestPricingError, dispatchPricedRequest, applyProviderCredentials, isJsonMediaType, } from "./priced-request.js";
22
+ export type { RequestPricingInput, ProviderCredentials } from "./priced-request.js";
package/dist/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  export { createCatalog, probeByPointers } from "./catalog.js";
2
2
  export { proposePlanBudget } from "./budget.js";
3
3
  export { listEstimate, selectPriceRow } from "./prices.js";
4
- export { matchOperation } from "./match.js";
5
4
  export { pointer } from "./pointer.js";
6
5
  export { decimalQuantity, numberText, moneyFromCents, moneyFromDollars, requestsMeasured, } from "./receipts.js";
7
6
  export { loadFixtures, missingFixtures, verifyFixture } from "./fixtures.js";
@@ -9,3 +8,4 @@ export { dataforseo } from "./dataforseo/index.js";
9
8
  export { serpapi } from "./serpapi/index.js";
10
9
  export { executeProviderRequest } from "./execute.js";
11
10
  export { parseBillingExport } from "./billing.js";
11
+ export { PricedRequest, RequestPricingError, dispatchPricedRequest, applyProviderCredentials, isJsonMediaType, } from "./priced-request.js";
@@ -0,0 +1,49 @@
1
+ import type { Meter, MeterReserveInput, ProviderAuth, Quantity, ReserveResult } from "@usagekit/core";
2
+ import type { Catalog, CatalogMatch } from "./catalog.js";
3
+ import type { ProviderRequest } from "./types.js";
4
+ export type RequestPricingInput = {
5
+ meter: Meter;
6
+ catalog: Catalog;
7
+ input: Omit<MeterReserveInput, "operation" | "options">;
8
+ /** Uint8Array is wire data; other bodies are host-supplied JSON values or text. */
9
+ request: ProviderRequest;
10
+ expectedOperation?: string;
11
+ rejectUnknown?: boolean;
12
+ /** Only non-strict proxy dispatch may reserve an unknown, unpriced request. */
13
+ allowUnknownDispatch?: boolean;
14
+ };
15
+ /** Trusted transport credentials are supplied separately and are never part of priced state. */
16
+ export type ProviderCredentials = {
17
+ secret: string;
18
+ };
19
+ export declare class RequestPricingError extends Error {
20
+ readonly code: "invalid_json" | "invalid_provider_request" | "operation_mismatch" | "unknown_operation";
21
+ constructor(code: "invalid_json" | "invalid_provider_request" | "operation_mismatch" | "unknown_operation", message?: string);
22
+ }
23
+ /** RFC 9110 media types are case-insensitive; structured JSON suffixes are JSON too. */
24
+ export declare function isJsonMediaType(value: string | null | undefined): boolean;
25
+ /** Only pricing/admission can construct this snapshot. Bytes are copied on access, and all
26
+ * other state is deeply frozen. Neither caller mutations nor dispatch can change the price
27
+ * inputs. Credential fields are stripped before pricing; dispatch adds trusted authentication
28
+ * to a copy without retaining it in this snapshot. */
29
+ export declare class PricedRequest {
30
+ #private;
31
+ readonly method: string;
32
+ readonly url: string;
33
+ readonly headers: Readonly<Record<string, string>>;
34
+ readonly parsed: ProviderRequest;
35
+ readonly matched: CatalogMatch;
36
+ readonly input: RequestPricingInput["input"];
37
+ readonly admission: ReserveResult;
38
+ readonly estimate: readonly Quantity[];
39
+ readonly auth: Readonly<ProviderAuth>;
40
+ private constructor();
41
+ get body(): Uint8Array<ArrayBuffer> | undefined;
42
+ static price({ meter, catalog, input, request, expectedOperation, rejectUnknown, allowUnknownDispatch, }: RequestPricingInput): Promise<PricedRequest>;
43
+ }
44
+ /** Apply trusted credentials to disposable transport objects. Hosts validate on throwaway
45
+ * objects before pricing; using this same helper at dispatch keeps both paths identical.
46
+ * Invalid credentials always throw a stable error without the credential value or cause. */
47
+ export declare function applyProviderCredentials(auth: Readonly<ProviderAuth>, url: URL, headers: Headers, credentials: ProviderCredentials): void;
48
+ /** The only fetch boundary used by proxy and recorder. Pass null explicitly for no auth. */
49
+ export declare function dispatchPricedRequest(request: PricedRequest, transport: typeof fetch, signal: AbortSignal, credentials: ProviderCredentials | null): Promise<Response>;