@lcv-ideas-software/cross-review 4.0.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/CHANGELOG.md +2568 -0
- package/LICENSE +201 -0
- package/NOTICE +26 -0
- package/README.md +208 -0
- package/SECURITY.md +52 -0
- package/dist/scripts/api-streaming-smoke.d.ts +1 -0
- package/dist/scripts/api-streaming-smoke.js +78 -0
- package/dist/scripts/api-streaming-smoke.js.map +1 -0
- package/dist/scripts/runtime-default-smoke.d.ts +1 -0
- package/dist/scripts/runtime-default-smoke.js +88 -0
- package/dist/scripts/runtime-default-smoke.js.map +1 -0
- package/dist/scripts/runtime-smoke.d.ts +1 -0
- package/dist/scripts/runtime-smoke.js +148 -0
- package/dist/scripts/runtime-smoke.js.map +1 -0
- package/dist/scripts/smoke.d.ts +1 -0
- package/dist/scripts/smoke.js +6156 -0
- package/dist/scripts/smoke.js.map +1 -0
- package/dist/src/core/cache-manifest.d.ts +22 -0
- package/dist/src/core/cache-manifest.js +133 -0
- package/dist/src/core/cache-manifest.js.map +1 -0
- package/dist/src/core/caller-tokens.d.ts +32 -0
- package/dist/src/core/caller-tokens.js +240 -0
- package/dist/src/core/caller-tokens.js.map +1 -0
- package/dist/src/core/config.d.ts +9 -0
- package/dist/src/core/config.js +643 -0
- package/dist/src/core/config.js.map +1 -0
- package/dist/src/core/convergence.d.ts +5 -0
- package/dist/src/core/convergence.js +186 -0
- package/dist/src/core/convergence.js.map +1 -0
- package/dist/src/core/cost.d.ts +59 -0
- package/dist/src/core/cost.js +359 -0
- package/dist/src/core/cost.js.map +1 -0
- package/dist/src/core/file-config.d.ts +316 -0
- package/dist/src/core/file-config.js +490 -0
- package/dist/src/core/file-config.js.map +1 -0
- package/dist/src/core/orchestrator.d.ts +199 -0
- package/dist/src/core/orchestrator.js +3430 -0
- package/dist/src/core/orchestrator.js.map +1 -0
- package/dist/src/core/prompt-parts.d.ts +58 -0
- package/dist/src/core/prompt-parts.js +122 -0
- package/dist/src/core/prompt-parts.js.map +1 -0
- package/dist/src/core/relator-lottery.d.ts +23 -0
- package/dist/src/core/relator-lottery.js +112 -0
- package/dist/src/core/relator-lottery.js.map +1 -0
- package/dist/src/core/reports.d.ts +2 -0
- package/dist/src/core/reports.js +82 -0
- package/dist/src/core/reports.js.map +1 -0
- package/dist/src/core/session-store.d.ts +149 -0
- package/dist/src/core/session-store.js +1923 -0
- package/dist/src/core/session-store.js.map +1 -0
- package/dist/src/core/status.d.ts +61 -0
- package/dist/src/core/status.js +249 -0
- package/dist/src/core/status.js.map +1 -0
- package/dist/src/core/timeouts.d.ts +2 -0
- package/dist/src/core/timeouts.js +3 -0
- package/dist/src/core/timeouts.js.map +1 -0
- package/dist/src/core/types.d.ts +604 -0
- package/dist/src/core/types.js +36 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/dashboard/server.d.ts +2 -0
- package/dist/src/dashboard/server.js +339 -0
- package/dist/src/dashboard/server.js.map +1 -0
- package/dist/src/mcp/server.d.ts +54 -0
- package/dist/src/mcp/server.js +1584 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/observability/logger.d.ts +9 -0
- package/dist/src/observability/logger.js +24 -0
- package/dist/src/observability/logger.js.map +1 -0
- package/dist/src/peers/anthropic.d.ts +14 -0
- package/dist/src/peers/anthropic.js +290 -0
- package/dist/src/peers/anthropic.js.map +1 -0
- package/dist/src/peers/base.d.ts +72 -0
- package/dist/src/peers/base.js +416 -0
- package/dist/src/peers/base.js.map +1 -0
- package/dist/src/peers/deepseek.d.ts +12 -0
- package/dist/src/peers/deepseek.js +246 -0
- package/dist/src/peers/deepseek.js.map +1 -0
- package/dist/src/peers/errors.d.ts +2 -0
- package/dist/src/peers/errors.js +185 -0
- package/dist/src/peers/errors.js.map +1 -0
- package/dist/src/peers/gemini.d.ts +13 -0
- package/dist/src/peers/gemini.js +215 -0
- package/dist/src/peers/gemini.js.map +1 -0
- package/dist/src/peers/grok.d.ts +17 -0
- package/dist/src/peers/grok.js +346 -0
- package/dist/src/peers/grok.js.map +1 -0
- package/dist/src/peers/model-selection.d.ts +4 -0
- package/dist/src/peers/model-selection.js +260 -0
- package/dist/src/peers/model-selection.js.map +1 -0
- package/dist/src/peers/openai.d.ts +14 -0
- package/dist/src/peers/openai.js +299 -0
- package/dist/src/peers/openai.js.map +1 -0
- package/dist/src/peers/perplexity.d.ts +18 -0
- package/dist/src/peers/perplexity.js +375 -0
- package/dist/src/peers/perplexity.js.map +1 -0
- package/dist/src/peers/registry.d.ts +3 -0
- package/dist/src/peers/registry.js +77 -0
- package/dist/src/peers/registry.js.map +1 -0
- package/dist/src/peers/retry.d.ts +2 -0
- package/dist/src/peers/retry.js +36 -0
- package/dist/src/peers/retry.js.map +1 -0
- package/dist/src/peers/stub.d.ts +13 -0
- package/dist/src/peers/stub.js +344 -0
- package/dist/src/peers/stub.js.map +1 -0
- package/dist/src/peers/text.d.ts +18 -0
- package/dist/src/peers/text.js +39 -0
- package/dist/src/peers/text.js.map +1 -0
- package/dist/src/security/redact.d.ts +2 -0
- package/dist/src/security/redact.js +128 -0
- package/dist/src/security/redact.js.map +1 -0
- package/docs/api-keys.md +34 -0
- package/docs/architecture.md +118 -0
- package/docs/caching.md +135 -0
- package/docs/costs.md +40 -0
- package/docs/evidence-preflight.md +88 -0
- package/docs/github-security-baseline.md +32 -0
- package/docs/model-selection.md +105 -0
- package/docs/reports/cross-review-v2-api-capability-smoke-2026-04-30.md +354 -0
- package/docs/reports/cross-review-v2-format-recovery-findings-2026-04-28.md +223 -0
- package/docs/reports/cross-review-v2-official-provider-docs-refresh-2026-05-05.md +60 -0
- package/docs/reports/cross-review-v2-token-streaming-smoke-2026-04-30.md +119 -0
- package/package.json +88 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
// v2.21.0 (caching): cost layer extends to merge cache_read/cache_write
|
|
2
|
+
// tokens and surface estimated cache savings on CostEstimate.
|
|
3
|
+
// v2.26.0 (full pricing model + no-hardcoded-financials): cost_rates is
|
|
4
|
+
// now a complete schema supporting base + extended-tier (>threshold) +
|
|
5
|
+
// cache (read/write) + promo (limited-time discount until
|
|
6
|
+
// promo_expires_at). selectRate() chooses the right value per
|
|
7
|
+
// (category, tier, promo-active?) at estimation time. The legacy
|
|
8
|
+
// cache-rates.json fallback was REMOVED per operator directive
|
|
9
|
+
// 2026-05-11 ("nada hardcoded para preços financeiros — o sistema deve
|
|
10
|
+
// travar até o operador configurar as variáveis"). When cache rate env
|
|
11
|
+
// vars are absent, selectRate() gracefully degrades to the input rate
|
|
12
|
+
// (zero savings) instead of synthesizing prices from a static file.
|
|
13
|
+
/**
|
|
14
|
+
* v2.26.0: select the right per-million USD rate for a given (category,
|
|
15
|
+
* tier, promo-active?) combination, with graceful fallback to the next
|
|
16
|
+
* available rate when fields are absent or expired.
|
|
17
|
+
*
|
|
18
|
+
* Selection priority (each step falls through to the next when the
|
|
19
|
+
* corresponding field is unset OR the condition does not apply):
|
|
20
|
+
* 1. promo_<category>_extended_per_million — IFF in promo period AND
|
|
21
|
+
* large prompt AND field set
|
|
22
|
+
* 2. promo_<category>_per_million — IFF in promo period AND field set
|
|
23
|
+
* 3. <category>_extended_per_million — IFF large prompt AND field set
|
|
24
|
+
* 4. <category>_per_million — base rate, set
|
|
25
|
+
* 5. (cache_read / cache_write only) recurse into "input" category
|
|
26
|
+
* — gracefully degrade to "no cache discount" billing when the
|
|
27
|
+
* operator stops configuring cache rates entirely
|
|
28
|
+
*
|
|
29
|
+
* Fallback semantics intent (operator directive 2026-05-11):
|
|
30
|
+
* - When promo expires (today >= promo_expires_at) or promo fields are
|
|
31
|
+
* unset, automatically use base rates without operator intervention.
|
|
32
|
+
* - When extended-tier rates are unset for a tier-aware provider, use
|
|
33
|
+
* base for ALL prompt sizes (no penalty for missing config).
|
|
34
|
+
* - When cache rates are unset entirely, treat cache tokens as fresh
|
|
35
|
+
* input (no discount, no penalty). The provider may still bill them
|
|
36
|
+
* at a lower rate; we just stop modeling that detail.
|
|
37
|
+
*
|
|
38
|
+
* `now` is injected so tests and FinOps replays can pin the clock.
|
|
39
|
+
*/
|
|
40
|
+
export function selectRate(rate, category, totalInputTokens, now = new Date()) {
|
|
41
|
+
const inPromo = rate.promo_expires_at != null && Date.parse(rate.promo_expires_at) > now.getTime();
|
|
42
|
+
const isExtended = rate.threshold_tokens != null && totalInputTokens > rate.threshold_tokens;
|
|
43
|
+
const promoBase = {
|
|
44
|
+
input: rate.promo_input_per_million,
|
|
45
|
+
output: rate.promo_output_per_million,
|
|
46
|
+
cache_read: rate.promo_cache_read_per_million,
|
|
47
|
+
cache_write: rate.promo_cache_write_per_million,
|
|
48
|
+
}[category];
|
|
49
|
+
const promoExtended = {
|
|
50
|
+
input: rate.promo_input_extended_per_million,
|
|
51
|
+
output: rate.promo_output_extended_per_million,
|
|
52
|
+
cache_read: rate.promo_cache_read_extended_per_million,
|
|
53
|
+
cache_write: rate.promo_cache_write_extended_per_million,
|
|
54
|
+
}[category];
|
|
55
|
+
const base = {
|
|
56
|
+
input: rate.input_per_million,
|
|
57
|
+
output: rate.output_per_million,
|
|
58
|
+
cache_read: rate.cache_read_per_million,
|
|
59
|
+
cache_write: rate.cache_write_per_million,
|
|
60
|
+
}[category];
|
|
61
|
+
const extended = {
|
|
62
|
+
input: rate.input_extended_per_million,
|
|
63
|
+
output: rate.output_extended_per_million,
|
|
64
|
+
cache_read: rate.cache_read_extended_per_million,
|
|
65
|
+
cache_write: rate.cache_write_extended_per_million,
|
|
66
|
+
}[category];
|
|
67
|
+
if (inPromo) {
|
|
68
|
+
if (isExtended && promoExtended != null) {
|
|
69
|
+
return { rate_per_million: promoExtended, tier_used: "promo_extended" };
|
|
70
|
+
}
|
|
71
|
+
if (promoBase != null) {
|
|
72
|
+
return { rate_per_million: promoBase, tier_used: "promo" };
|
|
73
|
+
}
|
|
74
|
+
// No promo rate for this category → fall through to non-promo cascade.
|
|
75
|
+
}
|
|
76
|
+
if (isExtended && extended != null) {
|
|
77
|
+
return { rate_per_million: extended, tier_used: "extended" };
|
|
78
|
+
}
|
|
79
|
+
if (base != null) {
|
|
80
|
+
return { rate_per_million: base, tier_used: "base" };
|
|
81
|
+
}
|
|
82
|
+
// v2.26.0 graceful degradation: when a cache category has no rate at
|
|
83
|
+
// all (operator stopped configuring it OR provider discontinued the
|
|
84
|
+
// cache discount), bill cache tokens at the input rate instead of
|
|
85
|
+
// dropping them silently. The tier_used reflects the input tier so
|
|
86
|
+
// FinOps still sees promo/extended applied to the input fallback.
|
|
87
|
+
if (category === "cache_read" || category === "cache_write") {
|
|
88
|
+
return selectRate(rate, "input", totalInputTokens, now);
|
|
89
|
+
}
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
export function mergeUsage(items) {
|
|
93
|
+
const total = {};
|
|
94
|
+
for (const item of items) {
|
|
95
|
+
if (!item)
|
|
96
|
+
continue;
|
|
97
|
+
total.input_tokens = (total.input_tokens ?? 0) + (item.input_tokens ?? 0);
|
|
98
|
+
total.output_tokens = (total.output_tokens ?? 0) + (item.output_tokens ?? 0);
|
|
99
|
+
total.total_tokens = (total.total_tokens ?? 0) + (item.total_tokens ?? 0);
|
|
100
|
+
total.reasoning_tokens = (total.reasoning_tokens ?? 0) + (item.reasoning_tokens ?? 0);
|
|
101
|
+
// v2.21.0 (caching): merge cache telemetry. cache_read/write are
|
|
102
|
+
// additive across calls; mode/key_hash are NOT merged because they
|
|
103
|
+
// are per-call attributes (different rounds may hit different
|
|
104
|
+
// cache scopes or modes).
|
|
105
|
+
total.cache_read_tokens = (total.cache_read_tokens ?? 0) + (item.cache_read_tokens ?? 0);
|
|
106
|
+
total.cache_write_tokens = (total.cache_write_tokens ?? 0) + (item.cache_write_tokens ?? 0);
|
|
107
|
+
}
|
|
108
|
+
return total;
|
|
109
|
+
}
|
|
110
|
+
export function estimateCost(config, peer, usage) {
|
|
111
|
+
const rate = config.cost_rates[peer];
|
|
112
|
+
if (!usage || !rate) {
|
|
113
|
+
return { currency: "USD", estimated: false, source: "unknown-rate" };
|
|
114
|
+
}
|
|
115
|
+
const inputTokens = usage.input_tokens ?? 0;
|
|
116
|
+
const outputTokens = usage.output_tokens ?? 0;
|
|
117
|
+
const cacheReadTokens = usage.cache_read_tokens ?? 0;
|
|
118
|
+
const cacheWriteTokens = usage.cache_write_tokens ?? 0;
|
|
119
|
+
// v2.26.0: tier selection considers the FULL prompt size (fresh input +
|
|
120
|
+
// cached read + cache write) because providers like Gemini price by
|
|
121
|
+
// total prompt length, not by post-cache fresh input.
|
|
122
|
+
const totalInputForTier = inputTokens + cacheReadTokens + cacheWriteTokens;
|
|
123
|
+
const inputSel = selectRate(rate, "input", totalInputForTier);
|
|
124
|
+
const outputSel = selectRate(rate, "output", totalInputForTier);
|
|
125
|
+
const cacheReadSel = cacheReadTokens > 0 ? selectRate(rate, "cache_read", totalInputForTier) : undefined;
|
|
126
|
+
const cacheWriteSel = cacheWriteTokens > 0 ? selectRate(rate, "cache_write", totalInputForTier) : undefined;
|
|
127
|
+
// selectRate always returns a value for input/output because base
|
|
128
|
+
// _INPUT/_OUTPUT_USD_PER_MILLION is required at parse time.
|
|
129
|
+
const inputCost = inputSel ? (inputTokens / 1_000_000) * inputSel.rate_per_million : 0;
|
|
130
|
+
const outputCost = outputSel ? (outputTokens / 1_000_000) * outputSel.rate_per_million : 0;
|
|
131
|
+
const cacheReadCost = cacheReadSel
|
|
132
|
+
? (cacheReadTokens / 1_000_000) * cacheReadSel.rate_per_million
|
|
133
|
+
: 0;
|
|
134
|
+
const cacheWriteCost = cacheWriteSel
|
|
135
|
+
? (cacheWriteTokens / 1_000_000) * cacheWriteSel.rate_per_million
|
|
136
|
+
: 0;
|
|
137
|
+
// v3.0.0 (Perplexity 6th peer): three additional cost dimensions —
|
|
138
|
+
// (1) per-1000-requests fee scaled by search_context_size,
|
|
139
|
+
// (2) citation_tokens (sonar-deep-research only),
|
|
140
|
+
// (3) deep_research_reasoning_tokens (sonar-deep-research only),
|
|
141
|
+
// (4) search_queries per-1000 fee (sonar-deep-research only).
|
|
142
|
+
// All four are zero for non-perplexity peers (their cost_rates entry
|
|
143
|
+
// never defines these fields) AND zero for non-deep-research
|
|
144
|
+
// perplexity models (operator leaves citation/reasoning/queries
|
|
145
|
+
// rates unset; usage.citation_tokens / usage.num_search_queries are
|
|
146
|
+
// absent). When `disable_search` is true the request fee is zero
|
|
147
|
+
// because no web search runs; the operator config-driven check
|
|
148
|
+
// mirrors the adapter's `disable_search` flag exactly.
|
|
149
|
+
let requestCost = 0;
|
|
150
|
+
let citationTokensCost = 0;
|
|
151
|
+
let deepResearchReasoningTokensCost = 0;
|
|
152
|
+
let searchQueriesCost = 0;
|
|
153
|
+
// v3.0.0 R1 fix (codex cross-review catch 2026-05-12): the per-call
|
|
154
|
+
// `usage.search_performed` signal from PerplexityAdapter overrides
|
|
155
|
+
// the global config for request-fee attribution. The relator
|
|
156
|
+
// (generate) role ALWAYS forces disable_search:true on the wire
|
|
157
|
+
// regardless of operator config, so charging a request fee based
|
|
158
|
+
// only on the config would bill for searches that did not run.
|
|
159
|
+
// When the signal is unset (legacy / stub / non-perplexity peers),
|
|
160
|
+
// fall back to the config check to preserve backward compatibility.
|
|
161
|
+
// Defensive against minimal test configs without a `perplexity`
|
|
162
|
+
// sub-config: the gate first narrows by peer === "perplexity", so
|
|
163
|
+
// for any other peer the search-cost block is never entered.
|
|
164
|
+
if (peer === "perplexity") {
|
|
165
|
+
const callSearchPerformed = usage.search_performed ?? !config.perplexity?.disable_search;
|
|
166
|
+
if (callSearchPerformed) {
|
|
167
|
+
const size = config.perplexity?.search_context_size ?? "low";
|
|
168
|
+
const requestFeePer1000 = size === "high"
|
|
169
|
+
? rate.request_fee_high_per_1000
|
|
170
|
+
: size === "medium"
|
|
171
|
+
? rate.request_fee_medium_per_1000
|
|
172
|
+
: rate.request_fee_low_per_1000;
|
|
173
|
+
if (typeof requestFeePer1000 === "number" && requestFeePer1000 > 0) {
|
|
174
|
+
requestCost = requestFeePer1000 / 1000;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (peer === "perplexity") {
|
|
179
|
+
const citationTokens = usage.citation_tokens ?? 0;
|
|
180
|
+
if (citationTokens > 0 && typeof rate.citation_tokens_per_million === "number") {
|
|
181
|
+
citationTokensCost = (citationTokens / 1_000_000) * rate.citation_tokens_per_million;
|
|
182
|
+
}
|
|
183
|
+
// sonar-deep-research bills reasoning_tokens at a separate rate
|
|
184
|
+
// from output. Other Perplexity models fold reasoning into output
|
|
185
|
+
// (the field is undefined). usage.reasoning_tokens is reused —
|
|
186
|
+
// there's no separate field — and only the presence of the rate
|
|
187
|
+
// config decides whether to bill separately.
|
|
188
|
+
const reasoningTokens = usage.reasoning_tokens ?? 0;
|
|
189
|
+
if (reasoningTokens > 0 &&
|
|
190
|
+
typeof rate.deep_research_reasoning_tokens_per_million === "number") {
|
|
191
|
+
deepResearchReasoningTokensCost =
|
|
192
|
+
(reasoningTokens / 1_000_000) * rate.deep_research_reasoning_tokens_per_million;
|
|
193
|
+
}
|
|
194
|
+
const numSearchQueries = usage.num_search_queries ?? 0;
|
|
195
|
+
if (numSearchQueries > 0 && typeof rate.search_queries_per_1000 === "number") {
|
|
196
|
+
searchQueriesCost = (numSearchQueries / 1000) * rate.search_queries_per_1000;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const total = inputCost +
|
|
200
|
+
outputCost +
|
|
201
|
+
cacheReadCost +
|
|
202
|
+
cacheWriteCost +
|
|
203
|
+
requestCost +
|
|
204
|
+
citationTokensCost +
|
|
205
|
+
deepResearchReasoningTokensCost +
|
|
206
|
+
searchQueriesCost;
|
|
207
|
+
const base = {
|
|
208
|
+
currency: "USD",
|
|
209
|
+
input_cost: inputCost,
|
|
210
|
+
output_cost: outputCost,
|
|
211
|
+
total_cost: total,
|
|
212
|
+
estimated: true,
|
|
213
|
+
source: "configured-rate",
|
|
214
|
+
};
|
|
215
|
+
if (cacheReadCost > 0)
|
|
216
|
+
base.cache_read_cost = cacheReadCost;
|
|
217
|
+
if (cacheWriteCost > 0)
|
|
218
|
+
base.cache_write_cost = cacheWriteCost;
|
|
219
|
+
if (requestCost > 0)
|
|
220
|
+
base.request_cost = requestCost;
|
|
221
|
+
if (citationTokensCost > 0)
|
|
222
|
+
base.citation_tokens_cost = citationTokensCost;
|
|
223
|
+
if (deepResearchReasoningTokensCost > 0) {
|
|
224
|
+
base.deep_research_reasoning_tokens_cost = deepResearchReasoningTokensCost;
|
|
225
|
+
}
|
|
226
|
+
if (searchQueriesCost > 0)
|
|
227
|
+
base.search_queries_cost = searchQueriesCost;
|
|
228
|
+
// Surface the selected tier (priority: extended/promo over base) for
|
|
229
|
+
// FinOps audit. When categories disagree (rare; only when promo or
|
|
230
|
+
// extended apply to one but not the other), pick input's tier as the
|
|
231
|
+
// representative — operators reading reports care most about which
|
|
232
|
+
// BILLING regime the call landed under.
|
|
233
|
+
if (inputSel)
|
|
234
|
+
base.tier_used = inputSel.tier_used;
|
|
235
|
+
// v2.21.0 (caching): when cache telemetry is present, populate
|
|
236
|
+
// savings on the CostEstimate so dashboards + reports see it next to
|
|
237
|
+
// input/output cost.
|
|
238
|
+
if (cacheReadTokens > 0 || cacheWriteTokens > 0) {
|
|
239
|
+
const savings = estimateCacheSavings(peer, usage, rate);
|
|
240
|
+
if (savings.unknown) {
|
|
241
|
+
base.cache_savings_unknown = true;
|
|
242
|
+
}
|
|
243
|
+
else if (savings.savings_usd > 0) {
|
|
244
|
+
base.cache_savings_usd = savings.savings_usd;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return base;
|
|
248
|
+
}
|
|
249
|
+
export function mergeCost(costs) {
|
|
250
|
+
let known = false;
|
|
251
|
+
let total = 0;
|
|
252
|
+
let cacheRead = 0;
|
|
253
|
+
let cacheWrite = 0;
|
|
254
|
+
let savings = 0;
|
|
255
|
+
let savingsKnown = false;
|
|
256
|
+
let savingsUnknown = false;
|
|
257
|
+
// v3.0.0 (Perplexity 6th peer): accumulate the four Perplexity-specific
|
|
258
|
+
// line items so multi-call sessions show the full pricing breakdown
|
|
259
|
+
// in session reports + the dashboard. These remain zero for sessions
|
|
260
|
+
// that don't include perplexity peer calls.
|
|
261
|
+
let request = 0;
|
|
262
|
+
let citationTokens = 0;
|
|
263
|
+
let deepResearchReasoningTokens = 0;
|
|
264
|
+
let searchQueries = 0;
|
|
265
|
+
for (const cost of costs) {
|
|
266
|
+
if (cost?.total_cost == null) {
|
|
267
|
+
// continue to inspect savings even when total is missing
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
known = true;
|
|
271
|
+
total += cost.total_cost;
|
|
272
|
+
}
|
|
273
|
+
if (cost?.cache_read_cost != null)
|
|
274
|
+
cacheRead += cost.cache_read_cost;
|
|
275
|
+
if (cost?.cache_write_cost != null)
|
|
276
|
+
cacheWrite += cost.cache_write_cost;
|
|
277
|
+
if (cost?.cache_savings_usd != null) {
|
|
278
|
+
savings += cost.cache_savings_usd;
|
|
279
|
+
savingsKnown = true;
|
|
280
|
+
}
|
|
281
|
+
if (cost?.cache_savings_unknown) {
|
|
282
|
+
savingsUnknown = true;
|
|
283
|
+
}
|
|
284
|
+
if (cost?.request_cost != null)
|
|
285
|
+
request += cost.request_cost;
|
|
286
|
+
if (cost?.citation_tokens_cost != null)
|
|
287
|
+
citationTokens += cost.citation_tokens_cost;
|
|
288
|
+
if (cost?.deep_research_reasoning_tokens_cost != null) {
|
|
289
|
+
deepResearchReasoningTokens += cost.deep_research_reasoning_tokens_cost;
|
|
290
|
+
}
|
|
291
|
+
if (cost?.search_queries_cost != null)
|
|
292
|
+
searchQueries += cost.search_queries_cost;
|
|
293
|
+
}
|
|
294
|
+
if (!known) {
|
|
295
|
+
return { currency: "USD", estimated: false, source: "unknown-rate" };
|
|
296
|
+
}
|
|
297
|
+
const merged = {
|
|
298
|
+
currency: "USD",
|
|
299
|
+
total_cost: total,
|
|
300
|
+
estimated: true,
|
|
301
|
+
source: "configured-rate",
|
|
302
|
+
};
|
|
303
|
+
if (cacheRead > 0)
|
|
304
|
+
merged.cache_read_cost = cacheRead;
|
|
305
|
+
if (cacheWrite > 0)
|
|
306
|
+
merged.cache_write_cost = cacheWrite;
|
|
307
|
+
if (savingsKnown && savings > 0)
|
|
308
|
+
merged.cache_savings_usd = savings;
|
|
309
|
+
if (savingsUnknown)
|
|
310
|
+
merged.cache_savings_unknown = true;
|
|
311
|
+
if (request > 0)
|
|
312
|
+
merged.request_cost = request;
|
|
313
|
+
if (citationTokens > 0)
|
|
314
|
+
merged.citation_tokens_cost = citationTokens;
|
|
315
|
+
if (deepResearchReasoningTokens > 0) {
|
|
316
|
+
merged.deep_research_reasoning_tokens_cost = deepResearchReasoningTokens;
|
|
317
|
+
}
|
|
318
|
+
if (searchQueries > 0)
|
|
319
|
+
merged.search_queries_cost = searchQueries;
|
|
320
|
+
return merged;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* v2.21.0 (caching): estimate the savings that flowed from a cache hit
|
|
324
|
+
* vs the fresh input rate for the same peer. Returns { unknown: true }
|
|
325
|
+
* when the rate card has no entry for the provider — operators see
|
|
326
|
+
* "we got a cache hit but cannot price it" instead of a silent zero.
|
|
327
|
+
*/
|
|
328
|
+
/**
|
|
329
|
+
* v2.26.0: estimate cache-read savings using ONLY env-configured rates
|
|
330
|
+
* via selectRate(). The legacy `cache-rates.json` fallback was removed
|
|
331
|
+
* per operator directive 2026-05-11 ("nada hardcoded para preços
|
|
332
|
+
* financeiros") — when an operator omits cache rate env vars, the
|
|
333
|
+
* intelligent fallback in selectRate() treats cache reads as priced at
|
|
334
|
+
* the input rate (zero savings) rather than synthesizing a fictional
|
|
335
|
+
* cached rate from a hardcoded JSON. Returns `unknown: true` only when
|
|
336
|
+
* no configRate is provided at all (defensive — `estimateCost()` already
|
|
337
|
+
* short-circuits with "unknown-rate" before reaching this path).
|
|
338
|
+
*/
|
|
339
|
+
export function estimateCacheSavings(peer, usage, configRate) {
|
|
340
|
+
void peer; // peer is kept in the signature for API stability + future telemetry
|
|
341
|
+
const readTokens = usage.cache_read_tokens ?? 0;
|
|
342
|
+
if (readTokens <= 0)
|
|
343
|
+
return { savings_usd: 0, unknown: false };
|
|
344
|
+
if (!configRate)
|
|
345
|
+
return { savings_usd: 0, unknown: true };
|
|
346
|
+
const totalInputForTier = (usage.input_tokens ?? 0) + readTokens + (usage.cache_write_tokens ?? 0);
|
|
347
|
+
const freshSel = selectRate(configRate, "input", totalInputForTier);
|
|
348
|
+
const cachedSel = selectRate(configRate, "cache_read", totalInputForTier);
|
|
349
|
+
// Both should be defined because input is required and cache_read
|
|
350
|
+
// gracefully degrades to input. Defensive guard for type narrowing.
|
|
351
|
+
if (!freshSel || !cachedSel)
|
|
352
|
+
return { savings_usd: 0, unknown: true };
|
|
353
|
+
if (freshSel.rate_per_million <= cachedSel.rate_per_million) {
|
|
354
|
+
return { savings_usd: 0, unknown: false };
|
|
355
|
+
}
|
|
356
|
+
const delta = freshSel.rate_per_million - cachedSel.rate_per_million;
|
|
357
|
+
return { savings_usd: (delta * readTokens) / 1_000_000, unknown: false };
|
|
358
|
+
}
|
|
359
|
+
//# sourceMappingURL=cost.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../../../src/core/cost.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,8DAA8D;AAC9D,wEAAwE;AACxE,uEAAuE;AACvE,0DAA0D;AAC1D,8DAA8D;AAC9D,iEAAiE;AACjE,+DAA+D;AAC/D,uEAAuE;AACvE,uEAAuE;AACvE,sEAAsE;AACtE,oEAAoE;AAQpE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,UAAU,CACxB,IAAc,EACd,QAAsB,EACtB,gBAAwB,EACxB,MAAY,IAAI,IAAI,EAAE;IAEtB,MAAM,OAAO,GACX,IAAI,CAAC,gBAAgB,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;IACrF,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,IAAI,IAAI,IAAI,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,CAAC;IAC7F,MAAM,SAAS,GACb;QACE,KAAK,EAAE,IAAI,CAAC,uBAAuB;QACnC,MAAM,EAAE,IAAI,CAAC,wBAAwB;QACrC,UAAU,EAAE,IAAI,CAAC,4BAA4B;QAC7C,WAAW,EAAE,IAAI,CAAC,6BAA6B;KAElD,CAAC,QAAQ,CAAC,CAAC;IACZ,MAAM,aAAa,GACjB;QACE,KAAK,EAAE,IAAI,CAAC,gCAAgC;QAC5C,MAAM,EAAE,IAAI,CAAC,iCAAiC;QAC9C,UAAU,EAAE,IAAI,CAAC,qCAAqC;QACtD,WAAW,EAAE,IAAI,CAAC,sCAAsC;KAE3D,CAAC,QAAQ,CAAC,CAAC;IACZ,MAAM,IAAI,GACR;QACE,KAAK,EAAE,IAAI,CAAC,iBAAiB;QAC7B,MAAM,EAAE,IAAI,CAAC,kBAAkB;QAC/B,UAAU,EAAE,IAAI,CAAC,sBAAsB;QACvC,WAAW,EAAE,IAAI,CAAC,uBAAuB;KAE5C,CAAC,QAAQ,CAAC,CAAC;IACZ,MAAM,QAAQ,GACZ;QACE,KAAK,EAAE,IAAI,CAAC,0BAA0B;QACtC,MAAM,EAAE,IAAI,CAAC,2BAA2B;QACxC,UAAU,EAAE,IAAI,CAAC,+BAA+B;QAChD,WAAW,EAAE,IAAI,CAAC,gCAAgC;KAErD,CAAC,QAAQ,CAAC,CAAC;IACZ,IAAI,OAAO,EAAE,CAAC;QACZ,IAAI,UAAU,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;YACxC,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC;QAC1E,CAAC;QACD,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;YACtB,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;QAC7D,CAAC;QACD,uEAAuE;IACzE,CAAC;IACD,IAAI,UAAU,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;QACnC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;IAC/D,CAAC;IACD,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;QACjB,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IACvD,CAAC;IACD,qEAAqE;IACrE,oEAAoE;IACpE,kEAAkE;IAClE,mEAAmE;IACnE,kEAAkE;IAClE,IAAI,QAAQ,KAAK,YAAY,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;QAC5D,OAAO,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAoC;IAC7D,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,KAAK,CAAC,YAAY,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC;QAC1E,KAAK,CAAC,aAAa,GAAG,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,CAAC,CAAC;QAC7E,KAAK,CAAC,YAAY,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC;QAC1E,KAAK,CAAC,gBAAgB,GAAG,CAAC,KAAK,CAAC,gBAAgB,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,CAAC,CAAC;QACtF,iEAAiE;QACjE,mEAAmE;QACnE,8DAA8D;QAC9D,0BAA0B;QAC1B,KAAK,CAAC,iBAAiB,GAAG,CAAC,KAAK,CAAC,iBAAiB,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,IAAI,CAAC,CAAC,CAAC;QACzF,KAAK,CAAC,kBAAkB,GAAG,CAAC,KAAK,CAAC,kBAAkB,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,CAAC,CAAC;IAC9F,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAiB,EAAE,IAAY,EAAE,KAAkB;IAC9E,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QACpB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACvE,CAAC;IACD,MAAM,WAAW,GAAG,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC;IAC5C,MAAM,YAAY,GAAG,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;IAC9C,MAAM,eAAe,GAAG,KAAK,CAAC,iBAAiB,IAAI,CAAC,CAAC;IACrD,MAAM,gBAAgB,GAAG,KAAK,CAAC,kBAAkB,IAAI,CAAC,CAAC;IACvD,wEAAwE;IACxE,oEAAoE;IACpE,sDAAsD;IACtD,MAAM,iBAAiB,GAAG,WAAW,GAAG,eAAe,GAAG,gBAAgB,CAAC;IAC3E,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAChE,MAAM,YAAY,GAChB,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,YAAY,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACtF,MAAM,aAAa,GACjB,gBAAgB,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxF,kEAAkE;IAClE,4DAA4D;IAC5D,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,SAAS,CAAC,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IACvF,MAAM,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3F,MAAM,aAAa,GAAG,YAAY;QAChC,CAAC,CAAC,CAAC,eAAe,GAAG,SAAS,CAAC,GAAG,YAAY,CAAC,gBAAgB;QAC/D,CAAC,CAAC,CAAC,CAAC;IACN,MAAM,cAAc,GAAG,aAAa;QAClC,CAAC,CAAC,CAAC,gBAAgB,GAAG,SAAS,CAAC,GAAG,aAAa,CAAC,gBAAgB;QACjE,CAAC,CAAC,CAAC,CAAC;IACN,mEAAmE;IACnE,2DAA2D;IAC3D,kDAAkD;IAClD,iEAAiE;IACjE,8DAA8D;IAC9D,qEAAqE;IACrE,6DAA6D;IAC7D,gEAAgE;IAChE,oEAAoE;IACpE,iEAAiE;IACjE,+DAA+D;IAC/D,uDAAuD;IACvD,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,kBAAkB,GAAG,CAAC,CAAC;IAC3B,IAAI,+BAA+B,GAAG,CAAC,CAAC;IACxC,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAC1B,oEAAoE;IACpE,mEAAmE;IACnE,6DAA6D;IAC7D,gEAAgE;IAChE,iEAAiE;IACjE,+DAA+D;IAC/D,mEAAmE;IACnE,oEAAoE;IACpE,gEAAgE;IAChE,kEAAkE;IAClE,6DAA6D;IAC7D,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QAC1B,MAAM,mBAAmB,GAAG,KAAK,CAAC,gBAAgB,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,cAAc,CAAC;QACzF,IAAI,mBAAmB,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,EAAE,mBAAmB,IAAI,KAAK,CAAC;YAC7D,MAAM,iBAAiB,GACrB,IAAI,KAAK,MAAM;gBACb,CAAC,CAAC,IAAI,CAAC,yBAAyB;gBAChC,CAAC,CAAC,IAAI,KAAK,QAAQ;oBACjB,CAAC,CAAC,IAAI,CAAC,2BAA2B;oBAClC,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC;YACtC,IAAI,OAAO,iBAAiB,KAAK,QAAQ,IAAI,iBAAiB,GAAG,CAAC,EAAE,CAAC;gBACnE,WAAW,GAAG,iBAAiB,GAAG,IAAI,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QAC1B,MAAM,cAAc,GAAG,KAAK,CAAC,eAAe,IAAI,CAAC,CAAC;QAClD,IAAI,cAAc,GAAG,CAAC,IAAI,OAAO,IAAI,CAAC,2BAA2B,KAAK,QAAQ,EAAE,CAAC;YAC/E,kBAAkB,GAAG,CAAC,cAAc,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,2BAA2B,CAAC;QACvF,CAAC;QACD,gEAAgE;QAChE,kEAAkE;QAClE,+DAA+D;QAC/D,gEAAgE;QAChE,6CAA6C;QAC7C,MAAM,eAAe,GAAG,KAAK,CAAC,gBAAgB,IAAI,CAAC,CAAC;QACpD,IACE,eAAe,GAAG,CAAC;YACnB,OAAO,IAAI,CAAC,0CAA0C,KAAK,QAAQ,EACnE,CAAC;YACD,+BAA+B;gBAC7B,CAAC,eAAe,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,0CAA0C,CAAC;QACpF,CAAC;QACD,MAAM,gBAAgB,GAAG,KAAK,CAAC,kBAAkB,IAAI,CAAC,CAAC;QACvD,IAAI,gBAAgB,GAAG,CAAC,IAAI,OAAO,IAAI,CAAC,uBAAuB,KAAK,QAAQ,EAAE,CAAC;YAC7E,iBAAiB,GAAG,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,uBAAuB,CAAC;QAC/E,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GACT,SAAS;QACT,UAAU;QACV,aAAa;QACb,cAAc;QACd,WAAW;QACX,kBAAkB;QAClB,+BAA+B;QAC/B,iBAAiB,CAAC;IACpB,MAAM,IAAI,GAAiB;QACzB,QAAQ,EAAE,KAAK;QACf,UAAU,EAAE,SAAS;QACrB,WAAW,EAAE,UAAU;QACvB,UAAU,EAAE,KAAK;QACjB,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,iBAAiB;KAC1B,CAAC;IACF,IAAI,aAAa,GAAG,CAAC;QAAE,IAAI,CAAC,eAAe,GAAG,aAAa,CAAC;IAC5D,IAAI,cAAc,GAAG,CAAC;QAAE,IAAI,CAAC,gBAAgB,GAAG,cAAc,CAAC;IAC/D,IAAI,WAAW,GAAG,CAAC;QAAE,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;IACrD,IAAI,kBAAkB,GAAG,CAAC;QAAE,IAAI,CAAC,oBAAoB,GAAG,kBAAkB,CAAC;IAC3E,IAAI,+BAA+B,GAAG,CAAC,EAAE,CAAC;QACxC,IAAI,CAAC,mCAAmC,GAAG,+BAA+B,CAAC;IAC7E,CAAC;IACD,IAAI,iBAAiB,GAAG,CAAC;QAAE,IAAI,CAAC,mBAAmB,GAAG,iBAAiB,CAAC;IACxE,qEAAqE;IACrE,mEAAmE;IACnE,qEAAqE;IACrE,mEAAmE;IACnE,wCAAwC;IACxC,IAAI,QAAQ;QAAE,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;IAClD,+DAA+D;IAC/D,qEAAqE;IACrE,qBAAqB;IACrB,IAAI,eAAe,GAAG,CAAC,IAAI,gBAAgB,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QACxD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC;QACpC,CAAC;aAAM,IAAI,OAAO,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC;QAC/C,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAsC;IAC9D,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,wEAAwE;IACxE,oEAAoE;IACpE,qEAAqE;IACrE,4CAA4C;IAC5C,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,2BAA2B,GAAG,CAAC,CAAC;IACpC,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,EAAE,UAAU,IAAI,IAAI,EAAE,CAAC;YAC7B,yDAAyD;QAC3D,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,IAAI,CAAC;YACb,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC;QAC3B,CAAC;QACD,IAAI,IAAI,EAAE,eAAe,IAAI,IAAI;YAAE,SAAS,IAAI,IAAI,CAAC,eAAe,CAAC;QACrE,IAAI,IAAI,EAAE,gBAAgB,IAAI,IAAI;YAAE,UAAU,IAAI,IAAI,CAAC,gBAAgB,CAAC;QACxE,IAAI,IAAI,EAAE,iBAAiB,IAAI,IAAI,EAAE,CAAC;YACpC,OAAO,IAAI,IAAI,CAAC,iBAAiB,CAAC;YAClC,YAAY,GAAG,IAAI,CAAC;QACtB,CAAC;QACD,IAAI,IAAI,EAAE,qBAAqB,EAAE,CAAC;YAChC,cAAc,GAAG,IAAI,CAAC;QACxB,CAAC;QACD,IAAI,IAAI,EAAE,YAAY,IAAI,IAAI;YAAE,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC;QAC7D,IAAI,IAAI,EAAE,oBAAoB,IAAI,IAAI;YAAE,cAAc,IAAI,IAAI,CAAC,oBAAoB,CAAC;QACpF,IAAI,IAAI,EAAE,mCAAmC,IAAI,IAAI,EAAE,CAAC;YACtD,2BAA2B,IAAI,IAAI,CAAC,mCAAmC,CAAC;QAC1E,CAAC;QACD,IAAI,IAAI,EAAE,mBAAmB,IAAI,IAAI;YAAE,aAAa,IAAI,IAAI,CAAC,mBAAmB,CAAC;IACnF,CAAC;IACD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACvE,CAAC;IACD,MAAM,MAAM,GAAiB;QAC3B,QAAQ,EAAE,KAAK;QACf,UAAU,EAAE,KAAK;QACjB,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,iBAAiB;KAC1B,CAAC;IACF,IAAI,SAAS,GAAG,CAAC;QAAE,MAAM,CAAC,eAAe,GAAG,SAAS,CAAC;IACtD,IAAI,UAAU,GAAG,CAAC;QAAE,MAAM,CAAC,gBAAgB,GAAG,UAAU,CAAC;IACzD,IAAI,YAAY,IAAI,OAAO,GAAG,CAAC;QAAE,MAAM,CAAC,iBAAiB,GAAG,OAAO,CAAC;IACpE,IAAI,cAAc;QAAE,MAAM,CAAC,qBAAqB,GAAG,IAAI,CAAC;IACxD,IAAI,OAAO,GAAG,CAAC;QAAE,MAAM,CAAC,YAAY,GAAG,OAAO,CAAC;IAC/C,IAAI,cAAc,GAAG,CAAC;QAAE,MAAM,CAAC,oBAAoB,GAAG,cAAc,CAAC;IACrE,IAAI,2BAA2B,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,CAAC,mCAAmC,GAAG,2BAA2B,CAAC;IAC3E,CAAC;IACD,IAAI,aAAa,GAAG,CAAC;QAAE,MAAM,CAAC,mBAAmB,GAAG,aAAa,CAAC;IAClE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAY,EACZ,KAAiB,EACjB,UAAgC;IAEhC,KAAK,IAAI,CAAC,CAAC,qEAAqE;IAChF,MAAM,UAAU,GAAG,KAAK,CAAC,iBAAiB,IAAI,CAAC,CAAC;IAChD,IAAI,UAAU,IAAI,CAAC;QAAE,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC/D,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC1D,MAAM,iBAAiB,GACrB,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,UAAU,GAAG,CAAC,KAAK,CAAC,kBAAkB,IAAI,CAAC,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,UAAU,CAAC,UAAU,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;IACpE,MAAM,SAAS,GAAG,UAAU,CAAC,UAAU,EAAE,YAAY,EAAE,iBAAiB,CAAC,CAAC;IAC1E,kEAAkE;IAClE,oEAAoE;IACpE,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACtE,IAAI,QAAQ,CAAC,gBAAgB,IAAI,SAAS,CAAC,gBAAgB,EAAE,CAAC;QAC5D,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5C,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,gBAAgB,GAAG,SAAS,CAAC,gBAAgB,CAAC;IACrE,OAAO,EAAE,WAAW,EAAE,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC3E,CAAC"}
|