@ancplua/qyl-api-schema 0.5.13 → 0.5.15

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.
@@ -10,17 +10,8 @@ using Qyl.Api.Contracts.Common;
10
10
 
11
11
  namespace Qyl.Api.Contracts.Cost;
12
12
 
13
- @doc("How a provider-owned API supplied a cost value.")
14
- enum ProviderCostSourceKind {
15
- @doc("Actual billed cost returned by a provider organization or cloud billing API.")
16
- actualBilledCost: "actual_billed_cost",
17
-
18
- @doc("A public SKU price returned by an official provider or cloud pricing API.")
19
- officialPublicCatalog: "official_public_catalog",
20
- }
21
-
22
- @doc("Current synchronization state for a provider-owned cost source.")
23
- enum ProviderCostSourceStatus {
13
+ @doc("Current synchronization state for a provider-owned billing source.")
14
+ enum ProviderBillingSourceStatus {
24
15
  @doc("The source has no configured provider credential or cloud identity.")
25
16
  unconfigured: "unconfigured",
26
17
 
@@ -33,45 +24,36 @@ enum ProviderCostSourceStatus {
33
24
  @doc("The last successful provider response is older than its freshness window.")
34
25
  stale: "stale",
35
26
 
36
- @doc("The latest provider fetch failed; no raw credential or upstream response is exposed.")
27
+ @doc("The latest provider billing fetch failed; no raw credential or upstream response is exposed.")
37
28
  syncFailed: "sync_failed",
38
-
39
- @doc("Provider cost exists but cannot be attributed to the reported trace clusters.")
40
- notAttributable: "not_attributable",
41
29
  }
42
30
 
43
- @doc("Granularity at which a cost value can be attributed to telemetry.")
44
- enum ProviderCostAttribution {
31
+ @doc("Granularity at which official provider-billed cost can be attributed to telemetry.")
32
+ enum ProviderBillingAttribution {
45
33
  @doc("The provider API identified the model and period represented by the value.")
46
34
  providerModelPeriod: "provider_model_period",
47
35
 
48
36
  @doc("The provider API identified only a provider/account period, not a model or request.")
49
37
  providerPeriod: "provider_period",
50
38
 
51
- @doc("The value was supplied explicitly as a what-if scenario input.")
52
- scenario: "scenario",
53
-
54
39
  @doc("No defensible attribution is available.")
55
40
  unavailable: "unavailable",
56
41
  }
57
42
 
58
- @doc("Provenance for cost data fetched directly from a provider-owned API.")
59
- model ProviderCostSource {
43
+ @doc("Provenance for billed cost data fetched directly from a provider-owned API.")
44
+ model ProviderBillingSource {
60
45
  @doc("Canonical GenAI provider or cloud billing system name.")
61
46
  provider: string;
62
47
 
63
- @doc("Whether the API returned billed cost or a public catalog price.")
64
- kind: ProviderCostSourceKind;
65
-
66
- @doc("Current synchronization and attribution state.")
67
- status: ProviderCostSourceStatus;
48
+ @doc("Current billing synchronization state.")
49
+ status: ProviderBillingSourceStatus;
68
50
 
69
51
  @doc("Official provider-owned API endpoint used for the fetch.")
70
52
  @encodedName("application/json", "source_endpoint")
71
53
  sourceEndpoint: UrlString;
72
54
 
73
55
  @doc("Attribution granularity supported by this source response.")
74
- attribution: ProviderCostAttribution;
56
+ attribution: ProviderBillingAttribution;
75
57
 
76
58
  @doc("UTC time of the latest fetch attempt.")
77
59
  @encodedName("application/json", "last_attempt_at")
@@ -81,11 +63,11 @@ model ProviderCostSource {
81
63
  @encodedName("application/json", "last_success_at")
82
64
  lastSuccessAt?: utcDateTime;
83
65
 
84
- @doc("Start of the provider billing or catalog validity period.")
66
+ @doc("Start of the provider billing period.")
85
67
  @encodedName("application/json", "period_start")
86
68
  periodStart?: utcDateTime;
87
69
 
88
- @doc("End of the provider billing or catalog validity period.")
70
+ @doc("End of the provider billing period.")
89
71
  @encodedName("application/json", "period_end")
90
72
  periodEnd?: utcDateTime;
91
73
 
@@ -106,6 +88,494 @@ model ProviderCostSource {
106
88
  failureCategory?: string;
107
89
  }
108
90
 
91
+ @doc("Current synchronization state for a configured live model catalog.")
92
+ enum ModelCatalogSourceStatus {
93
+ @doc("The source is registered, but its required credential or activation is not configured.")
94
+ unconfigured: "unconfigured",
95
+
96
+ @doc("The source is configured, but no fetch has completed yet.")
97
+ pending: "pending",
98
+
99
+ @doc("The most recent successful catalog fetch is inside its freshness window.")
100
+ current: "current",
101
+
102
+ @doc("The last successful catalog response is older than its freshness window.")
103
+ stale: "stale",
104
+
105
+ @doc("The latest catalog fetch failed; no raw credential or upstream response is exposed.")
106
+ syncFailed: "sync_failed",
107
+ }
108
+
109
+ @doc("Synchronization metadata for one configurable live model catalog source.")
110
+ model ModelCatalogSource {
111
+ @doc("Unique stable identifier of the configured catalog source.")
112
+ @encodedName("application/json", "source_id")
113
+ sourceId: string;
114
+
115
+ @doc("Configured source priority used for deterministic selection when multiple current catalogs match. Zero is highest priority; lower values win.")
116
+ priority: Count;
117
+
118
+ status: ModelCatalogSourceStatus;
119
+
120
+ @doc("Rate-selection semantics published by this source's active snapshot.")
121
+ @encodedName("application/json", "price_semantics")
122
+ priceSemantics?: ModelCatalogPriceSemantics;
123
+
124
+ @doc("Configured API endpoint used to fetch the live model catalog.")
125
+ @encodedName("application/json", "source_endpoint")
126
+ sourceEndpoint: UrlString;
127
+
128
+ @doc("UTC time of the latest fetch attempt.")
129
+ @encodedName("application/json", "last_attempt_at")
130
+ lastAttemptAt?: utcDateTime;
131
+
132
+ @doc("UTC time when the source was last verified successfully, including a verification that retained unchanged content.")
133
+ @encodedName("application/json", "last_verified_at")
134
+ lastVerifiedAt?: utcDateTime;
135
+
136
+ @doc("UTC time when the content of the currently retained catalog snapshot was retrieved.")
137
+ @encodedName("application/json", "retrieved_at")
138
+ retrievedAt?: utcDateTime;
139
+
140
+ @doc("Content-addressed identifier of the catalog snapshot currently used for estimates.")
141
+ @encodedName("application/json", "active_snapshot_id")
142
+ activeSnapshotId?: string;
143
+
144
+ @doc("Number of model records in the active catalog snapshot.")
145
+ @encodedName("application/json", "model_count")
146
+ modelCount?: Count;
147
+
148
+ @doc("Stable, non-sensitive failure category for the last attempt.")
149
+ @encodedName("application/json", "failure_category")
150
+ failureCategory?: string;
151
+ }
152
+
153
+ @doc("How a live catalog rate was selected when estimating cluster cost.")
154
+ enum ModelCatalogPriceSemantics {
155
+ @doc("The catalog source publishes its lowest available model rate rather than an official bill or a uniquely routed endpoint price. A conditional rate applies only when its conditions are proven.")
156
+ minimumAvailableRate: "minimum_available_rate",
157
+
158
+ @doc("The source's published rate was applied without selecting a lower conditional rate.")
159
+ publishedRate: "published_rate",
160
+ }
161
+
162
+ @doc("Deterministic exact match used to resolve an observed model identity to a catalog record. Fuzzy, prefix, suffix, date, and alias matching are not permitted.")
163
+ enum ModelCatalogMatchKind {
164
+ @doc("The observed model value exactly matched the catalog model identifier.")
165
+ exactModelId: "exact_model_id",
166
+
167
+ @doc("The observed model value exactly matched the catalog canonical slug.")
168
+ exactCanonicalSlug: "exact_canonical_slug",
169
+ }
170
+
171
+ @doc("Telemetry attribute used as the observed model identity for an exact catalog match.")
172
+ enum ModelCatalogObservedIdentityBasis {
173
+ @doc("The observed identity came from the provider response model.")
174
+ responseModel: "response_model",
175
+
176
+ @doc("No response model was available, so the observed identity came from the request model.")
177
+ requestModelFallback: "request_model_fallback",
178
+ }
179
+
180
+ @doc("Provenance for the live catalog rates used to estimate one cluster.")
181
+ model ModelCatalogPriceProvenance {
182
+ @doc("Unique stable identifier of the configured catalog source.")
183
+ @encodedName("application/json", "source_id")
184
+ sourceId: string;
185
+
186
+ @doc("Configured API endpoint from which the catalog was retrieved.")
187
+ @encodedName("application/json", "source_endpoint")
188
+ sourceEndpoint: UrlString;
189
+
190
+ @doc("Content-addressed identifier of the exact catalog snapshot used for this estimate.")
191
+ @encodedName("application/json", "snapshot_id")
192
+ snapshotId: string;
193
+
194
+ @doc("Exact model identifier selected from the source catalog.")
195
+ @encodedName("application/json", "price_model_id")
196
+ priceModelId: string;
197
+
198
+ @doc("Exact observed telemetry value compared with the selected catalog record.")
199
+ @encodedName("application/json", "observed_model_id")
200
+ observedModelId: string;
201
+
202
+ @encodedName("application/json", "observed_model_identity_basis")
203
+ observedModelIdentityBasis: ModelCatalogObservedIdentityBasis;
204
+
205
+ @encodedName("application/json", "model_match_kind")
206
+ modelMatchKind: ModelCatalogMatchKind;
207
+
208
+ @doc("UTC time when the current catalog snapshot used for this counterfactual estimate was retrieved. For historical audit periods, this is not evidence of the price that applied historically.")
209
+ @encodedName("application/json", "retrieved_at")
210
+ retrievedAt: utcDateTime;
211
+
212
+ @encodedName("application/json", "price_semantics")
213
+ priceSemantics: ModelCatalogPriceSemantics;
214
+ }
215
+
216
+ @doc("How a catalog rate charges its measured quantity.")
217
+ enum ModelCatalogBillingMode {
218
+ @doc("The rate is multiplied by a measured unit quantity.")
219
+ perUnit: "per_unit",
220
+
221
+ @doc("The rate is charged once for each observed request.")
222
+ perRequest: "per_request",
223
+ }
224
+
225
+ @doc("How a selected catalog rate relates to the source's published base rate for the same component.")
226
+ enum ModelCatalogRateRelation {
227
+ @doc("The selected rate is the published base rate for this component.")
228
+ baseRate: "base_rate",
229
+
230
+ @doc("The selected rate is an additive surcharge alongside the published base rate.")
231
+ additiveSurcharge: "additive_surcharge",
232
+
233
+ @doc("A source subtype rate replaces the inclusive published base rate for its target usage dimension. Conditional evidence is present only when an ordered source override altered that subtype rate.")
234
+ replacesInclusiveBaseRate: "replaces_inclusive_base_rate",
235
+
236
+ @doc("A proven ordered source override replaces the previously published rate for its target usage dimension.")
237
+ replacesPublishedRate: "replaces_published_rate",
238
+ }
239
+
240
+ @doc("One-based position of a conditional override in its source response.")
241
+ @minValue(1)
242
+ scalar ModelCatalogSourceOrder extends int64;
243
+
244
+ @doc("Ordered evidence proving whether a conditional catalog override applied to an observed request quantity.")
245
+ model ModelCatalogConditionalRateEvidence {
246
+ @doc("One-based position of this override in the source response; later matching overrides win. Tier zero is reserved for the published base rate and is not a source override.")
247
+ @encodedName("application/json", "source_order")
248
+ sourceOrder: ModelCatalogSourceOrder;
249
+
250
+ @doc("Observed per-call usage dimension evaluated by the source condition.")
251
+ @encodedName("application/json", "condition_usage_dimension")
252
+ conditionUsageDimension: string;
253
+
254
+ @doc("Exclusive minimum quantity declared by the source condition.")
255
+ @encodedName("application/json", "exclusive_minimum_quantity")
256
+ @minValue(0)
257
+ exclusiveMinimumQuantity: float64;
258
+
259
+ @doc("Observed per-call quantity compared with the exclusive minimum.")
260
+ @encodedName("application/json", "observed_per_call_quantity")
261
+ @minValue(0)
262
+ observedPerCallQuantity: float64;
263
+ }
264
+
265
+ @doc("Fields shared by every included token or request pricing component.")
266
+ model ModelCatalogTokenEstimateComponentBase {
267
+ @doc("Source-defined pricing component, such as prompt, completion, request, cache read, cache write, or internal reasoning.")
268
+ component: string;
269
+
270
+ @doc("Qyl-observed usage dimension to which this rate was applied, such as input_tokens or output_tokens.")
271
+ @encodedName("application/json", "usage_dimension")
272
+ usageDimension: string;
273
+
274
+ @doc("Source-declared unit represented by the rate.")
275
+ unit: string;
276
+
277
+ @doc("Source-specific billing mode retained from the catalog or deterministically derived from the provider-defined meter.")
278
+ @encodedName("application/json", "source_billing_mode")
279
+ sourceBillingMode: string;
280
+
281
+ @encodedName("application/json", "billing_mode")
282
+ billingMode: ModelCatalogBillingMode;
283
+
284
+ @doc("Measured quantity to which the catalog unit price was applied.")
285
+ @minValue(0)
286
+ quantity: float64;
287
+
288
+ @doc("Catalog price in USD per source-defined unit.")
289
+ @encodedName("application/json", "unit_price_usd")
290
+ unitPriceUsd: CostUsd;
291
+
292
+ @doc("Estimated USD contribution of this component for the reported cluster period.")
293
+ @encodedName("application/json", "estimated_cost_usd")
294
+ estimatedCostUsd: CostUsd;
295
+ }
296
+
297
+ model ModelCatalogTokenBaseRateComponent extends ModelCatalogTokenEstimateComponentBase {
298
+ @encodedName("application/json", "rate_relation")
299
+ rateRelation: "base_rate";
300
+ }
301
+
302
+ model ModelCatalogTokenAdditiveSurchargeComponent extends ModelCatalogTokenEstimateComponentBase {
303
+ @encodedName("application/json", "rate_relation")
304
+ rateRelation: "additive_surcharge";
305
+ }
306
+
307
+ model ModelCatalogTokenInclusiveReplacementRateComponent extends ModelCatalogTokenEstimateComponentBase {
308
+ @encodedName("application/json", "rate_relation")
309
+ rateRelation: "replaces_inclusive_base_rate";
310
+
311
+ @doc("Inclusive base usage dimension replaced by this subtype rate.")
312
+ @encodedName("application/json", "replaces_usage_dimension")
313
+ replacesUsageDimension: string;
314
+
315
+ @doc("Ordered override evidence when the source conditionally altered this subtype rate.")
316
+ @encodedName("application/json", "conditional_evidence")
317
+ conditionalEvidence?: ModelCatalogConditionalRateEvidence;
318
+ }
319
+
320
+ model ModelCatalogTokenConditionalOverrideRateComponent extends ModelCatalogTokenEstimateComponentBase {
321
+ @encodedName("application/json", "rate_relation")
322
+ rateRelation: "replaces_published_rate";
323
+
324
+ @doc("Published usage dimension whose prior base, surcharge, or subtype rate was replaced.")
325
+ @encodedName("application/json", "replaces_usage_dimension")
326
+ replacesUsageDimension: string;
327
+
328
+ @encodedName("application/json", "conditional_evidence")
329
+ conditionalEvidence: ModelCatalogConditionalRateEvidence;
330
+ }
331
+
332
+ @doc("One evidenced token or request component contributing to a current-catalog estimate. The rate_relation literal selects the required evidence shape.")
333
+ @oneOf
334
+ union ModelCatalogTokenEstimateComponent {
335
+ baseRate: ModelCatalogTokenBaseRateComponent,
336
+ additiveSurcharge: ModelCatalogTokenAdditiveSurchargeComponent,
337
+ inclusiveReplacementRate: ModelCatalogTokenInclusiveReplacementRateComponent,
338
+ conditionalOverrideRate: ModelCatalogTokenConditionalOverrideRateComponent,
339
+ }
340
+
341
+ @doc("Why a catalog meter or conditional adjustment was not included in a token-and-request estimate.")
342
+ enum ModelCatalogTokenExclusionReason {
343
+ @doc("The optional usage subtype was not observed; inclusive base input or output tokens remain priced.")
344
+ usageNotObserved: "usage_not_observed",
345
+
346
+ @doc("A conditional adjustment was not applied because its activation condition was not proven.")
347
+ conditionalAdjustmentNotApplied: "conditional_adjustment_not_applied",
348
+
349
+ @doc("The adjustment matched, but a later matching source override replaced it for the same meter.")
350
+ supersededByLaterOverride: "superseded_by_later_override",
351
+
352
+ @doc("The meter is outside the token-and-request estimate boundary and telemetry did not prove that it applied.")
353
+ outsideTokenEstimateScope: "outside_token_estimate_scope",
354
+
355
+ @doc("Telemetry proved the meter applied, but qyl does not support its usage dimension.")
356
+ unsupportedUsageDimension: "unsupported_usage_dimension",
357
+
358
+ @doc("Telemetry proved the meter applied, but qyl does not support its billing mode.")
359
+ unsupportedBillingMode: "unsupported_billing_mode",
360
+ }
361
+
362
+ model ModelCatalogBaseRateEvidence {
363
+ @encodedName("application/json", "rate_relation")
364
+ rateRelation: "base_rate";
365
+ }
366
+
367
+ model ModelCatalogAdditiveSurchargeEvidence {
368
+ @encodedName("application/json", "rate_relation")
369
+ rateRelation: "additive_surcharge";
370
+ }
371
+
372
+ model ModelCatalogInclusiveReplacementEvidence {
373
+ @encodedName("application/json", "rate_relation")
374
+ rateRelation: "replaces_inclusive_base_rate";
375
+
376
+ @doc("Inclusive base usage dimension replaced by this subtype rate.")
377
+ @encodedName("application/json", "replaces_usage_dimension")
378
+ replacesUsageDimension: string;
379
+
380
+ @doc("Ordered evidence when a source override altered the selected subtype rate.")
381
+ @encodedName("application/json", "conditional_evidence")
382
+ conditionalEvidence?: ModelCatalogConditionalRateEvidence;
383
+ }
384
+
385
+ model ModelCatalogPublishedReplacementEvidence {
386
+ @encodedName("application/json", "rate_relation")
387
+ rateRelation: "replaces_published_rate";
388
+
389
+ @doc("Published usage dimension whose prior base, surcharge, or subtype rate was replaced.")
390
+ @encodedName("application/json", "replaces_usage_dimension")
391
+ replacesUsageDimension: string;
392
+
393
+ @encodedName("application/json", "conditional_evidence")
394
+ conditionalEvidence: ModelCatalogConditionalRateEvidence;
395
+ }
396
+
397
+ @doc("Relation-specific evidence for a catalog rate omitted from a token-and-request estimate. The rate_relation literal selects the required target and ordered evidence shape.")
398
+ @oneOf
399
+ union ModelCatalogExclusionRateEvidence {
400
+ baseRate: ModelCatalogBaseRateEvidence,
401
+ additiveSurcharge: ModelCatalogAdditiveSurchargeEvidence,
402
+ inclusiveReplacement: ModelCatalogInclusiveReplacementEvidence,
403
+ publishedReplacement: ModelCatalogPublishedReplacementEvidence,
404
+ }
405
+
406
+ @doc("Fields shared by every catalog meter or conditional adjustment excluded from a token-and-request estimate.")
407
+ model ModelCatalogTokenEstimateExclusionBase {
408
+ component: string;
409
+
410
+ @encodedName("application/json", "usage_dimension")
411
+ usageDimension: string;
412
+
413
+ unit: string;
414
+
415
+ @doc("Source-specific billing mode retained from the catalog or deterministically derived from the provider-defined meter, including unsupported modes.")
416
+ @encodedName("application/json", "source_billing_mode")
417
+ sourceBillingMode: string;
418
+
419
+ @doc("Relation, replacement target, and ordered override evidence for the omitted rate.")
420
+ @encodedName("application/json", "rate_evidence")
421
+ rateEvidence: ModelCatalogExclusionRateEvidence;
422
+
423
+ @doc("Catalog rate omitted from the estimate, when the source supplied one.")
424
+ @encodedName("application/json", "unit_price_usd")
425
+ unitPriceUsd?: CostUsd;
426
+ }
427
+
428
+ model ModelCatalogSupportedBillingExclusionBase extends ModelCatalogTokenEstimateExclusionBase {
429
+ @encodedName("application/json", "billing_mode")
430
+ billingMode: ModelCatalogBillingMode;
431
+ }
432
+
433
+ model ModelCatalogOptionallyNormalizedBillingExclusionBase extends ModelCatalogTokenEstimateExclusionBase {
434
+ @doc("Normalized billing mode when qyl recognizes the source meter; absent when the source meter has no supported normalization.")
435
+ @encodedName("application/json", "billing_mode")
436
+ billingMode?: ModelCatalogBillingMode;
437
+ }
438
+
439
+ model ModelCatalogUsageNotObservedExclusion extends ModelCatalogSupportedBillingExclusionBase {
440
+ reason: "usage_not_observed";
441
+ }
442
+
443
+ model ModelCatalogOutsideTokenScopeExclusion extends ModelCatalogOptionallyNormalizedBillingExclusionBase {
444
+ reason: "outside_token_estimate_scope";
445
+ }
446
+
447
+ model ModelCatalogUnsupportedUsageExclusion extends ModelCatalogOptionallyNormalizedBillingExclusionBase {
448
+ reason: "unsupported_usage_dimension";
449
+ }
450
+
451
+ model ModelCatalogUnsupportedBillingExclusion extends ModelCatalogTokenEstimateExclusionBase {
452
+ @doc("Normalized billing mode when the source mode has a partial known mapping; absent when no supported normalization exists.")
453
+ @encodedName("application/json", "billing_mode")
454
+ billingMode?: ModelCatalogBillingMode;
455
+
456
+ reason: "unsupported_billing_mode";
457
+ }
458
+
459
+ model ModelCatalogConditionalExclusionBase {
460
+ component: string;
461
+
462
+ @encodedName("application/json", "usage_dimension")
463
+ usageDimension: string;
464
+
465
+ unit: string;
466
+
467
+ @doc("Source-specific billing mode retained from the catalog or deterministically derived from the provider-defined meter.")
468
+ @encodedName("application/json", "source_billing_mode")
469
+ sourceBillingMode: string;
470
+
471
+ @doc("Normalized billing mode when qyl recognizes the conditional source meter; absent when the source meter has no supported normalization.")
472
+ @encodedName("application/json", "billing_mode")
473
+ billingMode?: ModelCatalogBillingMode;
474
+
475
+ @doc("The ordered source override that was not applied or was superseded.")
476
+ @encodedName("application/json", "rate_evidence")
477
+ rateEvidence: ModelCatalogPublishedReplacementEvidence;
478
+
479
+ @doc("Catalog rate omitted from the estimate, when the source supplied one.")
480
+ @encodedName("application/json", "unit_price_usd")
481
+ unitPriceUsd?: CostUsd;
482
+ }
483
+
484
+ model ModelCatalogConditionalAdjustmentNotAppliedExclusion extends ModelCatalogConditionalExclusionBase {
485
+ reason: "conditional_adjustment_not_applied";
486
+ }
487
+
488
+ model ModelCatalogSupersededOverrideExclusion extends ModelCatalogConditionalExclusionBase {
489
+ reason: "superseded_by_later_override";
490
+ }
491
+
492
+ @doc("Auditable catalog meter or conditional adjustment excluded from a token-and-request estimate. The reason literal selects the required evidence shape.")
493
+ @oneOf
494
+ union ModelCatalogTokenEstimateExclusion {
495
+ usageNotObserved: ModelCatalogUsageNotObservedExclusion,
496
+ conditionalAdjustmentNotApplied: ModelCatalogConditionalAdjustmentNotAppliedExclusion,
497
+ supersededByLaterOverride: ModelCatalogSupersededOverrideExclusion,
498
+ outsideTokenEstimateScope: ModelCatalogOutsideTokenScopeExclusion,
499
+ unsupportedUsageDimension: ModelCatalogUnsupportedUsageExclusion,
500
+ unsupportedBillingMode: ModelCatalogUnsupportedBillingExclusion,
501
+ }
502
+
503
+ @doc("Calculated all-or-nothing current-catalog token and request estimate for a complete workflow cluster.")
504
+ model GenAiEtlCatalogTokenCalculatedEstimate {
505
+ status: "calculated";
506
+
507
+ @doc("Estimated token and request cost for the reported cluster period using the current catalog snapshot; this is counterfactual for historical periods and is not an official billed total.")
508
+ @encodedName("application/json", "estimated_catalog_token_cost_usd")
509
+ estimatedCatalogTokenCostUsd: CostUsd;
510
+
511
+ @doc("Estimated token and request cost per observed cluster call; this is not an official billed total.")
512
+ @encodedName("application/json", "estimated_catalog_token_cost_per_call_usd")
513
+ estimatedCatalogTokenCostPerCallUsd: CostUsd;
514
+
515
+ @doc("Exact catalog snapshot and model-match evidence.")
516
+ provenance: ModelCatalogPriceProvenance;
517
+
518
+ @doc("Included token or request usage and rate contributions. Ordered source overrides carry conditional evidence; ordinary inclusive subtype replacements do not require it.")
519
+ @minItems(1)
520
+ components: ModelCatalogTokenEstimateComponent[];
521
+
522
+ @doc("Meters or conditional adjustments explicitly omitted from this calculated estimate.")
523
+ @minItems(1)
524
+ exclusions?: ModelCatalogTokenEstimateExclusion[];
525
+ }
526
+
527
+ model GenAiEtlCatalogTokenEstimateFailureBase {
528
+ @doc("Available meter or conditional evidence explaining why the cluster estimate failed closed.")
529
+ @minItems(1)
530
+ exclusions?: ModelCatalogTokenEstimateExclusion[];
531
+ }
532
+
533
+ model GenAiEtlCatalogTokenSourceUnavailableEstimate extends GenAiEtlCatalogTokenEstimateFailureBase {
534
+ status: "source_unavailable";
535
+ }
536
+
537
+ model GenAiEtlCatalogTokenStaleSourceEstimate extends GenAiEtlCatalogTokenEstimateFailureBase {
538
+ status: "stale_source";
539
+ }
540
+
541
+ model GenAiEtlCatalogTokenMissingModelIdentityEstimate extends GenAiEtlCatalogTokenEstimateFailureBase {
542
+ status: "missing_model_identity";
543
+ }
544
+
545
+ model GenAiEtlCatalogTokenModelNotFoundEstimate extends GenAiEtlCatalogTokenEstimateFailureBase {
546
+ status: "model_not_found";
547
+ }
548
+
549
+ model GenAiEtlCatalogTokenAmbiguousModelEstimate extends GenAiEtlCatalogTokenEstimateFailureBase {
550
+ status: "ambiguous_model";
551
+ }
552
+
553
+ model GenAiEtlCatalogTokenIncompleteUsageEstimate extends GenAiEtlCatalogTokenEstimateFailureBase {
554
+ status: "incomplete_usage";
555
+ }
556
+
557
+ model GenAiEtlCatalogTokenConditionalPricingUnresolvableEstimate extends GenAiEtlCatalogTokenEstimateFailureBase {
558
+ status: "conditional_pricing_unresolvable";
559
+ }
560
+
561
+ model GenAiEtlCatalogTokenUnsupportedPricingEstimate extends GenAiEtlCatalogTokenEstimateFailureBase {
562
+ status: "unsupported_pricing";
563
+ }
564
+
565
+ @doc("All-or-nothing current-catalog token and request estimate. The status literal selects the complete calculated or fail-closed response shape.")
566
+ @oneOf
567
+ union GenAiEtlCatalogTokenCostEstimate {
568
+ calculated: GenAiEtlCatalogTokenCalculatedEstimate,
569
+ sourceUnavailable: GenAiEtlCatalogTokenSourceUnavailableEstimate,
570
+ staleSource: GenAiEtlCatalogTokenStaleSourceEstimate,
571
+ missingModelIdentity: GenAiEtlCatalogTokenMissingModelIdentityEstimate,
572
+ modelNotFound: GenAiEtlCatalogTokenModelNotFoundEstimate,
573
+ ambiguousModel: GenAiEtlCatalogTokenAmbiguousModelEstimate,
574
+ incompleteUsage: GenAiEtlCatalogTokenIncompleteUsageEstimate,
575
+ conditionalPricingUnresolvable: GenAiEtlCatalogTokenConditionalPricingUnresolvableEstimate,
576
+ unsupportedPricing: GenAiEtlCatalogTokenUnsupportedPricingEstimate,
577
+ }
578
+
109
579
  @doc("Task family inferred for a repeated GenAI workflow cluster.")
110
580
  enum GenAiEtlTaskFamily {
111
581
  openReasoningGeneration: "open_reasoning_generation",
@@ -143,10 +613,22 @@ enum GenAiEtlCandidatePath {
143
613
  insufficientEvidence: "insufficient_evidence",
144
614
  }
145
615
 
146
- @doc("Task-specific metric that can falsify a proposed replacement.")
616
+ @doc("Evidence status of the proposed replacement path.")
617
+ enum GenAiEtlCandidateStatus {
618
+ @doc("The path is a heuristic hypothesis that still requires the declared validation metrics and promotion gates.")
619
+ hypothesisOnly: "hypothesis_only",
620
+
621
+ @doc("Available evidence is insufficient to propose a replacement path.")
622
+ insufficientEvidence: "insufficient_evidence",
623
+ }
624
+
625
+ @doc("Task-specific metrics that can falsify a proposed replacement.")
147
626
  enum GenAiEtlValidationMetric {
148
627
  accuracy: "accuracy",
149
628
  macroF1: "macro_f1",
629
+ calibrationError: "calibration_error",
630
+ spanPrecision: "span_precision",
631
+ spanRecall: "span_recall",
150
632
  spanF1: "span_f1",
151
633
  fieldExactMatch: "field_exact_match",
152
634
  schemaValidity: "schema_validity",
@@ -176,7 +658,8 @@ enum GenAiEtlEvidenceSignal {
176
658
  outputContract: "output_contract",
177
659
  providerModel: "provider_model",
178
660
  tokenUsage: "token_usage",
179
- providerCost: "provider_cost",
661
+ @doc("A complete current-catalog token-and-request estimate with exact model and snapshot provenance.")
662
+ catalogTokenEstimate: "catalog_token_estimate",
180
663
  recurringSchema: "recurring_schema",
181
664
  boundedReference: "bounded_reference",
182
665
  taskMetric: "task_metric",
@@ -275,19 +758,9 @@ model GenAiEtlAuditCluster {
275
758
  @encodedName("application/json", "p95_latency_ms")
276
759
  p95LatencyMs: DurationMs;
277
760
 
278
- @doc("Provider-sourced cost attributable to this cluster, absent when attribution is not defensible.")
279
- @encodedName("application/json", "observed_cost_usd")
280
- observedCostUsd?: CostUsd;
281
-
282
- @encodedName("application/json", "cost_per_call_usd")
283
- costPerCallUsd?: CostUsd;
284
-
285
- @encodedName("application/json", "cost_attribution")
286
- costAttribution: ProviderCostAttribution;
287
-
288
- @doc("Fraction of attributable spend represented by this cluster.")
289
- @encodedName("application/json", "spend_share")
290
- spendShare?: Ratio;
761
+ @doc("Outcome and, when calculated, detailed current-catalog token-and-request estimate for this cluster. Aggregate provider billing is never attributed to a cluster.")
762
+ @encodedName("application/json", "catalog_token_estimate")
763
+ catalogTokenEstimate: GenAiEtlCatalogTokenCostEstimate;
291
764
 
292
765
  @doc("Fraction of calls with a task-specific correctness signal.")
293
766
  @encodedName("application/json", "measurable_coverage")
@@ -297,11 +770,17 @@ model GenAiEtlAuditCluster {
297
770
  @encodedName("application/json", "safe_deferral_coverage")
298
771
  safeDeferralCoverage?: Ratio;
299
772
 
773
+ @doc("Evidence status qualifying the proposed candidate path.")
774
+ @encodedName("application/json", "candidate_status")
775
+ candidateStatus: GenAiEtlCandidateStatus;
776
+
300
777
  @encodedName("application/json", "candidate_path")
301
778
  candidatePath: GenAiEtlCandidatePath;
302
779
 
303
- @encodedName("application/json", "validation_metric")
304
- validationMetric: GenAiEtlValidationMetric;
780
+ @doc("Task-specific metrics required to falsify the proposed replacement.")
781
+ @encodedName("application/json", "validation_metrics")
782
+ @minItems(1)
783
+ validationMetrics: GenAiEtlValidationMetric[];
305
784
 
306
785
  @encodedName("application/json", "residual_path")
307
786
  residualPath: GenAiEtlResidualPath;
@@ -327,17 +806,17 @@ model GenAiEtlAuditSummary {
327
806
  @encodedName("application/json", "total_output_tokens")
328
807
  totalOutputTokens: TokenCount;
329
808
 
330
- @doc("Provider-sourced cost attributable to the returned trace population.")
331
- @encodedName("application/json", "attributed_cost_usd")
332
- attributedCostUsd?: CostUsd;
809
+ @doc("Counterfactual token and request cost of the full observed audit population before the cluster response limit is applied, using the current live catalog snapshot; this is not an official billed total or a historical price claim.")
810
+ @encodedName("application/json", "estimated_catalog_token_cost_usd")
811
+ estimatedCatalogTokenCostUsd?: CostUsd;
333
812
 
334
- @doc("Fraction of calls covered by provider cost attribution.")
335
- @encodedName("application/json", "priced_call_coverage")
336
- pricedCallCoverage: Ratio;
813
+ @doc("Fraction of observed calls covered by all-or-nothing calculated token-and-request estimates; missing pricing is not treated as zero.")
814
+ @encodedName("application/json", "catalog_token_priced_call_coverage")
815
+ catalogTokenPricedCallCoverage: Ratio;
337
816
 
338
- @doc("Fraction of attributable spend represented by the returned top clusters.")
339
- @encodedName("application/json", "economic_concentration")
340
- economicConcentration?: Ratio;
817
+ @doc("Returned top-cluster token-and-request estimate divided by estimated_catalog_token_cost_usd for the full observed audit population.")
818
+ @encodedName("application/json", "estimated_token_economic_concentration")
819
+ estimatedTokenEconomicConcentration?: Ratio;
341
820
 
342
821
  @doc("Fraction of calls with a task-specific correctness signal.")
343
822
  @encodedName("application/json", "measurable_coverage")
@@ -347,9 +826,9 @@ model GenAiEtlAuditSummary {
347
826
  @encodedName("application/json", "safe_deferral_coverage")
348
827
  safeDeferralCoverage?: Ratio;
349
828
 
350
- @doc("Fraction of attributable spend attached to ETL-shaped candidates.")
351
- @encodedName("application/json", "candidate_etl_spend_share")
352
- candidateEtlSpendShare?: Ratio;
829
+ @doc("Fraction of estimated current-catalog token-and-request spend attached to ETL-shaped candidates.")
830
+ @encodedName("application/json", "candidate_etl_estimated_token_spend_share")
831
+ candidateEtlEstimatedTokenSpendShare?: Ratio;
353
832
  }
354
833
 
355
834
  @doc("Trace-level ETL audit for a bounded period.")
@@ -365,8 +844,13 @@ model GenAiEtlAuditReport {
365
844
 
366
845
  summary: GenAiEtlAuditSummary;
367
846
 
368
- @encodedName("application/json", "cost_sources")
369
- costSources: ProviderCostSource[];
847
+ @doc("Provider-owned aggregate billing sources. These totals are not attributed to clusters or used as evaluation baselines.")
848
+ @encodedName("application/json", "billing_sources")
849
+ billingSources: ProviderBillingSource[];
850
+
851
+ @doc("Configured live model catalog sources and their current synchronization state.")
852
+ @encodedName("application/json", "catalog_sources")
853
+ catalogSources: ModelCatalogSource[];
370
854
 
371
855
  clusters: GenAiEtlAuditCluster[];
372
856
  }
@@ -379,7 +863,7 @@ model GenAiEtlClusterScenario {
379
863
  @doc("Fraction of cluster calls the replacement is expected to serve safely.")
380
864
  coverage: Ratio;
381
865
 
382
- @doc("Explicit baseline cost per call. When absent, qyl uses provider-attributed cluster cost and otherwise fails closed.")
866
+ @doc("Explicit scenario baseline cost per call. It wins over a calculated catalog estimate; when both are absent, evaluation fails closed.")
383
867
  @encodedName("application/json", "frontier_cost_per_call_usd")
384
868
  frontierCostPerCallUsd?: CostUsd;
385
869
 
@@ -400,19 +884,22 @@ model GenAiEtlAuditEvaluationRequest {
400
884
  scenarios: GenAiEtlClusterScenario[];
401
885
  }
402
886
 
403
- @doc("Whether the replaceable-value formula had a defensible baseline cost.")
404
- enum GenAiEtlCalculationStatus {
405
- calculated: "calculated",
406
- missingFrontierCost: "missing_frontier_cost",
887
+ @doc("Evidence basis for the frontier cost used in a replacement-value calculation.")
888
+ enum GenAiEtlFrontierCostBasis {
889
+ @doc("The request supplied an explicit what-if scenario cost, which takes precedence over a catalog estimate.")
890
+ scenario: "scenario",
891
+
892
+ @doc("A token-and-request live model catalog estimate was used; this is not an official billed total.")
893
+ catalogTokenEstimate: "catalog_token_estimate",
894
+
895
+ @doc("No defensible frontier cost was available.")
896
+ unavailable: "unavailable",
407
897
  }
408
898
 
409
- @doc("Result of replaceable_value = calls * coverage * (frontier - alternative) - maintenance - error.")
410
- model GenAiEtlClusterEvaluation {
899
+ model GenAiEtlClusterEvaluationBase {
411
900
  @encodedName("application/json", "cluster_id")
412
901
  clusterId: string;
413
902
 
414
- status: GenAiEtlCalculationStatus;
415
-
416
903
  @encodedName("application/json", "call_count")
417
904
  callCount: Count;
418
905
 
@@ -424,30 +911,60 @@ model GenAiEtlClusterEvaluation {
424
911
  @encodedName("application/json", "residual_call_count")
425
912
  residualCallCount: float64;
426
913
 
427
- @encodedName("application/json", "frontier_cost_per_call_usd")
428
- frontierCostPerCallUsd?: CostUsd;
429
-
430
- @encodedName("application/json", "frontier_cost_basis")
431
- frontierCostBasis: ProviderCostAttribution;
432
-
433
914
  @encodedName("application/json", "alternative_cost_per_call_usd")
434
915
  alternativeCostPerCallUsd: CostUsd;
435
916
 
436
- @encodedName("application/json", "current_period_cost_usd")
437
- currentPeriodCostUsd?: CostUsd;
438
-
439
- @encodedName("application/json", "gross_replaceable_value_usd")
440
- grossReplaceableValueUsd?: float64;
441
-
442
917
  @encodedName("application/json", "period_maintenance_cost_usd")
443
918
  periodMaintenanceCostUsd: CostUsd;
444
919
 
445
920
  @encodedName("application/json", "period_error_cost_usd")
446
921
  periodErrorCostUsd: CostUsd;
922
+ }
923
+
924
+ model GenAiEtlCalculatedClusterEvaluationBase extends GenAiEtlClusterEvaluationBase {
925
+ status: "calculated";
926
+
927
+ @encodedName("application/json", "frontier_cost_per_call_usd")
928
+ frontierCostPerCallUsd: CostUsd;
929
+
930
+ @encodedName("application/json", "current_period_cost_usd")
931
+ currentPeriodCostUsd: CostUsd;
932
+
933
+ @encodedName("application/json", "gross_replaceable_value_usd")
934
+ grossReplaceableValueUsd: float64;
447
935
 
448
936
  @doc("Net period value; this may be negative when maintenance or error cost exceeds gross savings.")
449
937
  @encodedName("application/json", "net_replaceable_value_usd")
450
- netReplaceableValueUsd?: float64;
938
+ netReplaceableValueUsd: float64;
939
+ }
940
+
941
+ model GenAiEtlScenarioClusterEvaluation extends GenAiEtlCalculatedClusterEvaluationBase {
942
+ @encodedName("application/json", "frontier_cost_basis")
943
+ frontierCostBasis: "scenario";
944
+ }
945
+
946
+ model GenAiEtlCatalogTokenClusterEvaluation extends GenAiEtlCalculatedClusterEvaluationBase {
947
+ @encodedName("application/json", "frontier_cost_basis")
948
+ frontierCostBasis: "catalog_token_estimate";
949
+
950
+ @doc("Exact live-catalog snapshot and model-match evidence used for the calculated frontier cost.")
951
+ @encodedName("application/json", "catalog_provenance")
952
+ catalogProvenance: ModelCatalogPriceProvenance;
953
+ }
954
+
955
+ model GenAiEtlUnavailableClusterEvaluation extends GenAiEtlClusterEvaluationBase {
956
+ status: "missing_frontier_cost";
957
+
958
+ @encodedName("application/json", "frontier_cost_basis")
959
+ frontierCostBasis: "unavailable";
960
+ }
961
+
962
+ @doc("Result of replaceable_value = calls * coverage * (frontier - alternative) - maintenance - error. The frontier_cost_basis literal selects a complete calculated result or a fail-closed unavailable result.")
963
+ @oneOf
964
+ union GenAiEtlClusterEvaluation {
965
+ scenario: GenAiEtlScenarioClusterEvaluation,
966
+ catalogTokenEstimate: GenAiEtlCatalogTokenClusterEvaluation,
967
+ unavailable: GenAiEtlUnavailableClusterEvaluation,
451
968
  }
452
969
 
453
970
  @doc("Batch result for ETL replacement scenarios.")