@felan-ai/felan 0.15.0 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/application.js +2 -0
- package/dist/application.js.map +1 -1
- package/dist/cli-main.d.ts.map +1 -1
- package/dist/cli-main.js +63 -0
- package/dist/cli-main.js.map +1 -1
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.d.ts.map +1 -1
- package/dist/extensions.js +2 -2
- package/dist/extensions.js.map +1 -1
- package/dist/gain.d.ts +13 -0
- package/dist/gain.d.ts.map +1 -0
- package/dist/gain.js +45 -0
- package/dist/gain.js.map +1 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +48 -9
- package/dist/runtime.js.map +1 -1
- package/dist/savings.d.ts +87 -0
- package/dist/savings.d.ts.map +1 -0
- package/dist/savings.js +347 -0
- package/dist/savings.js.map +1 -0
- package/dist/settings.d.ts +8 -4
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +55 -11
- package/dist/settings.js.map +1 -1
- package/dist/subagents/host.d.ts +2 -1
- package/dist/subagents/host.d.ts.map +1 -1
- package/dist/subagents/host.js +1 -0
- package/dist/subagents/host.js.map +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { AgentRuntime, SavingsMeasurement, SavingsModelReference, SavingsReporter, SavingsReporterProvider } from '@felan-ai/agent-core';
|
|
2
|
+
export type { SavingsCategory, SavingsMeasurement, SavingsModelReference, SavingsOutcome, SavingsReporter, SavingsReporterProvider, SavingsTokenUsage, } from '@felan-ai/agent-core';
|
|
3
|
+
export interface SavingsPrice {
|
|
4
|
+
readonly model: SavingsModelReference;
|
|
5
|
+
readonly input: number;
|
|
6
|
+
readonly output: number;
|
|
7
|
+
readonly cacheRead: number;
|
|
8
|
+
readonly cacheWrite: number;
|
|
9
|
+
readonly tiers?: readonly SavingsPriceTier[];
|
|
10
|
+
readonly fingerprint: string;
|
|
11
|
+
}
|
|
12
|
+
export interface SavingsPriceTier {
|
|
13
|
+
readonly input: number;
|
|
14
|
+
readonly output: number;
|
|
15
|
+
readonly cacheRead: number;
|
|
16
|
+
readonly cacheWrite: number;
|
|
17
|
+
readonly inputTokensAbove: number;
|
|
18
|
+
}
|
|
19
|
+
export interface SavingsPriceSource {
|
|
20
|
+
resolveModel(model: SavingsModelReference): SavingsPrice | undefined | Promise<SavingsPrice | undefined>;
|
|
21
|
+
}
|
|
22
|
+
export interface SavingsServiceOptions {
|
|
23
|
+
readonly runtime: AgentRuntime;
|
|
24
|
+
readonly rootSessionId: string;
|
|
25
|
+
readonly projectKey: string;
|
|
26
|
+
readonly priceSource?: SavingsPriceSource;
|
|
27
|
+
readonly now?: () => Date;
|
|
28
|
+
readonly writerId?: string;
|
|
29
|
+
}
|
|
30
|
+
export type SavingsScope = 'session' | 'project' | 'all';
|
|
31
|
+
export interface SavingsQuery {
|
|
32
|
+
readonly scope?: SavingsScope;
|
|
33
|
+
readonly sessionId?: string;
|
|
34
|
+
readonly projectKey?: string;
|
|
35
|
+
readonly producerId?: string;
|
|
36
|
+
readonly from?: Date;
|
|
37
|
+
readonly to?: Date;
|
|
38
|
+
}
|
|
39
|
+
export interface SavingsTokenTotals {
|
|
40
|
+
readonly input: number;
|
|
41
|
+
readonly output: number;
|
|
42
|
+
readonly cacheRead: number;
|
|
43
|
+
readonly cacheWrite: number;
|
|
44
|
+
readonly cacheWrite1h: number;
|
|
45
|
+
}
|
|
46
|
+
export interface SavingsOutcomeTotals {
|
|
47
|
+
readonly costUsd?: number;
|
|
48
|
+
readonly model?: SavingsModelReference;
|
|
49
|
+
readonly tokens?: SavingsTokenTotals;
|
|
50
|
+
readonly priceSource: 'producer-reported' | 'model-catalog' | 'unavailable';
|
|
51
|
+
readonly priceFingerprint?: string;
|
|
52
|
+
}
|
|
53
|
+
export interface SavingsBucket {
|
|
54
|
+
readonly day: string;
|
|
55
|
+
readonly sessionId: string;
|
|
56
|
+
readonly projectKey: string;
|
|
57
|
+
readonly producerId: string;
|
|
58
|
+
readonly category: SavingsMeasurement['category'];
|
|
59
|
+
readonly operation?: string;
|
|
60
|
+
readonly basis: SavingsMeasurement['basis'];
|
|
61
|
+
readonly tool?: string;
|
|
62
|
+
readonly techniques?: readonly string[];
|
|
63
|
+
readonly calls: number;
|
|
64
|
+
readonly baseline: SavingsOutcomeTotals;
|
|
65
|
+
readonly actual: SavingsOutcomeTotals;
|
|
66
|
+
}
|
|
67
|
+
export interface SavingsReport {
|
|
68
|
+
readonly scope: SavingsScope;
|
|
69
|
+
readonly bucketCount: number;
|
|
70
|
+
readonly calls: number;
|
|
71
|
+
readonly baselineCostUsd: number;
|
|
72
|
+
readonly actualCostUsd: number;
|
|
73
|
+
readonly savedCostUsd: number;
|
|
74
|
+
readonly hasUnpricedMeasurements: boolean;
|
|
75
|
+
readonly buckets: readonly SavingsBucket[];
|
|
76
|
+
readonly diagnostics: readonly string[];
|
|
77
|
+
}
|
|
78
|
+
export declare class SavingsService implements SavingsReporterProvider {
|
|
79
|
+
#private;
|
|
80
|
+
constructor(options: SavingsServiceOptions);
|
|
81
|
+
createReporter(producerId: string): SavingsReporter;
|
|
82
|
+
report(producerId: string, measurement: SavingsMeasurement): Promise<void>;
|
|
83
|
+
query(query?: SavingsQuery): Promise<SavingsReport>;
|
|
84
|
+
}
|
|
85
|
+
export declare function createModelPriceSource(resolveModel: (model: SavingsModelReference) => SavingsPrice | undefined): SavingsPriceSource;
|
|
86
|
+
export declare function formatSavingsReport(report: SavingsReport, detailed?: boolean): string;
|
|
87
|
+
//# sourceMappingURL=savings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"savings.d.ts","sourceRoot":"","sources":["../src/savings.ts"],"names":[],"mappings":"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"}
|
package/dist/savings.js
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
const ROOT = 'savings/v1';
|
|
3
|
+
const WRITER_PATTERN = /^(?:savings\/v1\/)?writers\/([a-f0-9-]{36})\/(\d+)\.json$/u;
|
|
4
|
+
const MAX_BUCKETS = 2_000;
|
|
5
|
+
const MAX_SNAPSHOT_BYTES = 2 * 1024 * 1024;
|
|
6
|
+
const MAX_GENERATIONS = 4;
|
|
7
|
+
const encoder = new TextEncoder();
|
|
8
|
+
const decoder = new TextDecoder();
|
|
9
|
+
export class SavingsService {
|
|
10
|
+
#storage;
|
|
11
|
+
#options;
|
|
12
|
+
#writerId;
|
|
13
|
+
#buckets = new Map();
|
|
14
|
+
#sequence = 0;
|
|
15
|
+
#queue = Promise.resolve();
|
|
16
|
+
#persistenceErrors = 0;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.#options = options;
|
|
19
|
+
this.#storage = options.runtime.storage('agent');
|
|
20
|
+
this.#writerId = options.writerId ?? randomUUID();
|
|
21
|
+
if (!/^[a-f0-9-]{36}$/u.test(this.#writerId))
|
|
22
|
+
throw new Error('writerId must be a UUID');
|
|
23
|
+
}
|
|
24
|
+
createReporter(producerId) {
|
|
25
|
+
if (!isProducerId(producerId))
|
|
26
|
+
throw new Error('producerId must be a bounded identifier');
|
|
27
|
+
return {
|
|
28
|
+
report: (measurement) => this.report(producerId, measurement),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async report(producerId, measurement) {
|
|
32
|
+
await this.#enqueue(async () => {
|
|
33
|
+
const bucket = await this.#normalize(producerId, measurement);
|
|
34
|
+
const key = bucketKey(bucket);
|
|
35
|
+
const previous = this.#buckets.get(key);
|
|
36
|
+
this.#buckets.set(key, previous ? mergeBuckets(previous, bucket) : bucket);
|
|
37
|
+
while (this.#buckets.size > MAX_BUCKETS)
|
|
38
|
+
this.#buckets.delete(this.#buckets.keys().next().value);
|
|
39
|
+
try {
|
|
40
|
+
await this.#persist();
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
this.#persistenceErrors += 1;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async query(query = {}) {
|
|
48
|
+
const snapshots = await readSnapshots(this.#storage);
|
|
49
|
+
const own = [...this.#buckets.values()];
|
|
50
|
+
const all = [
|
|
51
|
+
...snapshots.filter(({ snapshot }) => snapshot.writerId !== this.#writerId).flatMap(({ snapshot }) => snapshot.buckets),
|
|
52
|
+
...own,
|
|
53
|
+
];
|
|
54
|
+
const selected = filterBuckets(all, query, this.#options.rootSessionId, this.#options.projectKey);
|
|
55
|
+
const deduped = dedupeSnapshots(selected);
|
|
56
|
+
const diagnostics = snapshots.flatMap(({ error }) => error === undefined ? [] : [error]);
|
|
57
|
+
if (this.#persistenceErrors > 0)
|
|
58
|
+
diagnostics.push(`${this.#persistenceErrors} savings writes failed`);
|
|
59
|
+
const baseline = sumCost(deduped, 'baseline');
|
|
60
|
+
const actual = sumCost(deduped, 'actual');
|
|
61
|
+
return {
|
|
62
|
+
scope: query.scope ?? (query.sessionId ? 'session' : query.projectKey ? 'project' : 'all'),
|
|
63
|
+
bucketCount: deduped.length,
|
|
64
|
+
calls: deduped.reduce((total, bucket) => total + bucket.calls, 0),
|
|
65
|
+
baselineCostUsd: baseline.value,
|
|
66
|
+
actualCostUsd: actual.value,
|
|
67
|
+
savedCostUsd: baseline.value - actual.value,
|
|
68
|
+
hasUnpricedMeasurements: baseline.unpriced || actual.unpriced,
|
|
69
|
+
buckets: deduped,
|
|
70
|
+
diagnostics,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async #normalize(producerId, measurement) {
|
|
74
|
+
validateMeasurement(producerId, measurement);
|
|
75
|
+
const baseline = await resolveOutcome(measurement.baseline, this.#options.priceSource);
|
|
76
|
+
const actual = await resolveOutcome(measurement.actual, this.#options.priceSource);
|
|
77
|
+
const now = (this.#options.now ?? (() => new Date()))();
|
|
78
|
+
return {
|
|
79
|
+
day: now.toISOString().slice(0, 10),
|
|
80
|
+
sessionId: this.#options.rootSessionId,
|
|
81
|
+
projectKey: this.#options.projectKey,
|
|
82
|
+
producerId,
|
|
83
|
+
category: measurement.category,
|
|
84
|
+
...(measurement.operation === undefined ? {} : { operation: measurement.operation }),
|
|
85
|
+
basis: measurement.basis,
|
|
86
|
+
...(measurement.dimensions?.tool === undefined ? {} : { tool: measurement.dimensions.tool }),
|
|
87
|
+
...(measurement.dimensions?.techniques === undefined ? {} : { techniques: measurement.dimensions.techniques }),
|
|
88
|
+
calls: measurement.calls ?? 1,
|
|
89
|
+
baseline,
|
|
90
|
+
actual,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
async #persist() {
|
|
94
|
+
const snapshot = {
|
|
95
|
+
version: 1,
|
|
96
|
+
writerId: this.#writerId,
|
|
97
|
+
sequence: ++this.#sequence,
|
|
98
|
+
updatedAt: new Date().toISOString(),
|
|
99
|
+
buckets: [...this.#buckets.values()],
|
|
100
|
+
};
|
|
101
|
+
const bytes = encoder.encode(JSON.stringify(snapshot));
|
|
102
|
+
if (bytes.byteLength > MAX_SNAPSHOT_BYTES)
|
|
103
|
+
throw new Error('Savings snapshot exceeds size limit');
|
|
104
|
+
const directory = `${ROOT}/writers/${this.#writerId}`;
|
|
105
|
+
await this.#storage.mkdir(directory, { recursive: true });
|
|
106
|
+
await this.#storage.writeFile(`${directory}/${snapshot.sequence}.json`, bytes);
|
|
107
|
+
const files = await this.#storage.listFiles(directory, { pattern: '*.json' });
|
|
108
|
+
for (const file of files.sort((a, b) => Number.parseInt(a) - Number.parseInt(b)).slice(0, -MAX_GENERATIONS)) {
|
|
109
|
+
await this.#storage.remove(`${directory}/${file}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
#enqueue(operation) {
|
|
113
|
+
const previous = this.#queue;
|
|
114
|
+
const current = previous.then(operation);
|
|
115
|
+
this.#queue = current.then(() => { }, () => { });
|
|
116
|
+
return current;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export function createModelPriceSource(resolveModel) {
|
|
120
|
+
return { resolveModel };
|
|
121
|
+
}
|
|
122
|
+
export function formatSavingsReport(report, detailed = false) {
|
|
123
|
+
const lines = [
|
|
124
|
+
`Felan savings — ${report.scope}`,
|
|
125
|
+
`Estimated cost avoided: ${formatUsd(report.savedCostUsd)}`,
|
|
126
|
+
`Measured decisions: ${report.calls}`,
|
|
127
|
+
];
|
|
128
|
+
if (report.hasUnpricedMeasurements)
|
|
129
|
+
lines.push('Some measurements have unavailable pricing and are excluded from the USD total.');
|
|
130
|
+
if (detailed && report.buckets.length > 0)
|
|
131
|
+
lines.push('', ...formatSavingsTable(report.buckets));
|
|
132
|
+
lines.push(...report.diagnostics.map((diagnostic) => `Warning: ${diagnostic}`));
|
|
133
|
+
return lines.join('\n');
|
|
134
|
+
}
|
|
135
|
+
function formatSavingsTable(buckets) {
|
|
136
|
+
const grouped = new Map();
|
|
137
|
+
for (const bucket of buckets) {
|
|
138
|
+
const key = JSON.stringify([bucket.category, bucket.producerId]);
|
|
139
|
+
const previous = grouped.get(key);
|
|
140
|
+
const savedCostUsd = cost(bucket.baseline) - cost(bucket.actual);
|
|
141
|
+
grouped.set(key, previous
|
|
142
|
+
? { ...previous, calls: previous.calls + bucket.calls, savedCostUsd: previous.savedCostUsd + savedCostUsd }
|
|
143
|
+
: { category: bucket.category, producerId: bucket.producerId, calls: bucket.calls, savedCostUsd });
|
|
144
|
+
}
|
|
145
|
+
const categoryOrder = [
|
|
146
|
+
'output-optimization',
|
|
147
|
+
'model-routing',
|
|
148
|
+
'context-management',
|
|
149
|
+
'other',
|
|
150
|
+
];
|
|
151
|
+
const rows = [...grouped.values()]
|
|
152
|
+
.sort((left, right) => categoryOrder.indexOf(left.category) - categoryOrder.indexOf(right.category)
|
|
153
|
+
|| left.producerId.localeCompare(right.producerId))
|
|
154
|
+
.map((row) => [formatCategory(row.category), row.producerId, String(row.calls), formatUsd(row.savedCostUsd)]);
|
|
155
|
+
const headers = ['Category', 'Extension', 'Decisions', 'Savings'];
|
|
156
|
+
const widths = headers.map((header, index) => Math.max(header.length, ...rows.map((row) => row[index].length)));
|
|
157
|
+
const renderRow = (row) => row
|
|
158
|
+
.map((value, index) => index < 2 ? value.padEnd(widths[index]) : value.padStart(widths[index]))
|
|
159
|
+
.join(' ')
|
|
160
|
+
.trimEnd();
|
|
161
|
+
return [
|
|
162
|
+
renderRow(headers),
|
|
163
|
+
widths.map((width) => '-'.repeat(width)).join(' '),
|
|
164
|
+
...rows.map(renderRow),
|
|
165
|
+
];
|
|
166
|
+
}
|
|
167
|
+
function formatCategory(category) {
|
|
168
|
+
return category.split('-').map((word, index) => index === 0 ? `${word[0].toUpperCase()}${word.slice(1)}` : word).join(' ');
|
|
169
|
+
}
|
|
170
|
+
function validateMeasurement(producerId, measurement) {
|
|
171
|
+
if (!isProducerId(producerId) || !['output-optimization', 'model-routing', 'context-management', 'other'].includes(measurement.category))
|
|
172
|
+
throw new Error('Invalid savings category or producer');
|
|
173
|
+
if (measurement.operation !== undefined && !isSlug(measurement.operation, 64))
|
|
174
|
+
throw new Error('Invalid savings operation');
|
|
175
|
+
if (!measurement.basis || !['observed-comparison', 'estimated-baseline'].includes(measurement.basis.kind) || !isSlug(measurement.basis.method, 128))
|
|
176
|
+
throw new Error('Invalid savings basis');
|
|
177
|
+
if (measurement.calls !== undefined && (!Number.isSafeInteger(measurement.calls) || measurement.calls < 1 || measurement.calls > 10_000))
|
|
178
|
+
throw new Error('Invalid savings call count');
|
|
179
|
+
for (const outcome of [measurement.baseline, measurement.actual])
|
|
180
|
+
validateOutcome(outcome);
|
|
181
|
+
for (const value of [measurement.dimensions?.tool, ...(measurement.dimensions?.techniques ?? [])]) {
|
|
182
|
+
if (value !== undefined && !isSlug(value, 64))
|
|
183
|
+
throw new Error('Invalid savings dimension');
|
|
184
|
+
}
|
|
185
|
+
if ((measurement.dimensions?.techniques?.length ?? 0) > 16)
|
|
186
|
+
throw new Error('Too many savings techniques');
|
|
187
|
+
}
|
|
188
|
+
function validateOutcome(outcome) {
|
|
189
|
+
if (outcome.costUsd === undefined && outcome.tokens === undefined)
|
|
190
|
+
throw new Error('Savings outcome needs cost or tokens');
|
|
191
|
+
if (outcome.costUsd !== undefined && (!Number.isFinite(outcome.costUsd) || outcome.costUsd < 0))
|
|
192
|
+
throw new Error('Invalid savings cost');
|
|
193
|
+
if (outcome.model && (!isSlug(outcome.model.provider, 64) || !isSlug(outcome.model.id, 128)))
|
|
194
|
+
throw new Error('Invalid savings model');
|
|
195
|
+
if (outcome.tokens)
|
|
196
|
+
for (const value of Object.values(outcome.tokens))
|
|
197
|
+
if (value !== undefined && (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0))
|
|
198
|
+
throw new Error('Invalid savings tokens');
|
|
199
|
+
}
|
|
200
|
+
async function resolveOutcome(outcome, source) {
|
|
201
|
+
const tokens = outcome.tokens === undefined ? undefined : totals(outcome.tokens);
|
|
202
|
+
if (outcome.costUsd !== undefined)
|
|
203
|
+
return { costUsd: outcome.costUsd, ...(outcome.model ? { model: outcome.model } : {}), ...(tokens === undefined ? {} : { tokens }), priceSource: 'producer-reported' };
|
|
204
|
+
if (!source || !outcome.model || tokens === undefined)
|
|
205
|
+
return { ...(outcome.model ? { model: outcome.model } : {}), ...(tokens === undefined ? {} : { tokens }), priceSource: 'unavailable' };
|
|
206
|
+
const price = await source.resolveModel(outcome.model);
|
|
207
|
+
if (!price)
|
|
208
|
+
return { model: outcome.model, tokens, priceSource: 'unavailable' };
|
|
209
|
+
return { costUsd: calculateCost(price, tokens), model: outcome.model, tokens, priceSource: 'model-catalog', priceFingerprint: price.fingerprint };
|
|
210
|
+
}
|
|
211
|
+
function calculateCost(price, tokens) {
|
|
212
|
+
const inputTokens = tokens.input + tokens.cacheRead + tokens.cacheWrite;
|
|
213
|
+
let rates = price;
|
|
214
|
+
let threshold = -1;
|
|
215
|
+
for (const tier of price.tiers ?? [])
|
|
216
|
+
if (inputTokens > tier.inputTokensAbove && tier.inputTokensAbove > threshold) {
|
|
217
|
+
rates = tier;
|
|
218
|
+
threshold = tier.inputTokensAbove;
|
|
219
|
+
}
|
|
220
|
+
const shortWrite = tokens.cacheWrite - tokens.cacheWrite1h;
|
|
221
|
+
return rates.input * tokens.input / 1e6 + rates.output * tokens.output / 1e6 + rates.cacheRead * tokens.cacheRead / 1e6 + (rates.cacheWrite * shortWrite + rates.input * 2 * tokens.cacheWrite1h) / 1e6;
|
|
222
|
+
}
|
|
223
|
+
function totals(tokens) {
|
|
224
|
+
return { input: tokens.input, output: tokens.output, cacheRead: tokens.cacheRead ?? 0, cacheWrite: tokens.cacheWrite ?? 0, cacheWrite1h: tokens.cacheWrite1h ?? 0 };
|
|
225
|
+
}
|
|
226
|
+
function mergeBuckets(left, right) {
|
|
227
|
+
return { ...left, calls: left.calls + right.calls, baseline: mergeOutcome(left.baseline, right.baseline), actual: mergeOutcome(left.actual, right.actual) };
|
|
228
|
+
}
|
|
229
|
+
function mergeOutcome(left, right) {
|
|
230
|
+
const tokens = left.tokens && right.tokens ? Object.fromEntries(Object.keys(left.tokens).map((key) => [key, left.tokens[key] + right.tokens[key]])) : undefined;
|
|
231
|
+
return { ...(left.costUsd === undefined || right.costUsd === undefined ? {} : { costUsd: left.costUsd + right.costUsd }), ...(left.model ? { model: left.model } : {}), ...(tokens ? { tokens } : {}), priceSource: left.priceSource, ...(left.priceFingerprint ? { priceFingerprint: left.priceFingerprint } : {}) };
|
|
232
|
+
}
|
|
233
|
+
function bucketKey(bucket) {
|
|
234
|
+
return JSON.stringify([bucket.day, bucket.sessionId, bucket.projectKey, bucket.producerId, bucket.category, bucket.operation, bucket.basis, bucket.tool, bucket.techniques, bucket.baseline.model, bucket.baseline.priceSource, bucket.baseline.priceFingerprint, bucket.actual.model, bucket.actual.priceSource, bucket.actual.priceFingerprint]);
|
|
235
|
+
}
|
|
236
|
+
function filterBuckets(buckets, query, sessionId, projectKey) {
|
|
237
|
+
const scope = query.scope ?? (query.sessionId ? 'session' : query.projectKey ? 'project' : 'all');
|
|
238
|
+
return buckets.filter((bucket) => (scope !== 'session' || bucket.sessionId === (query.sessionId ?? sessionId)) && (scope !== 'project' || bucket.projectKey === (query.projectKey ?? projectKey)) && (query.producerId === undefined || bucket.producerId === query.producerId) && (query.from === undefined || bucket.day >= query.from.toISOString().slice(0, 10)) && (query.to === undefined || bucket.day <= query.to.toISOString().slice(0, 10)));
|
|
239
|
+
}
|
|
240
|
+
function dedupeSnapshots(buckets) {
|
|
241
|
+
const result = new Map();
|
|
242
|
+
for (const bucket of buckets)
|
|
243
|
+
result.set(bucketKey(bucket), result.has(bucketKey(bucket)) ? mergeBuckets(result.get(bucketKey(bucket)), bucket) : bucket);
|
|
244
|
+
return [...result.values()];
|
|
245
|
+
}
|
|
246
|
+
function sumCost(buckets, side) {
|
|
247
|
+
let value = 0;
|
|
248
|
+
let unpriced = false;
|
|
249
|
+
for (const bucket of buckets) {
|
|
250
|
+
const outcome = bucket[side];
|
|
251
|
+
if (outcome.costUsd === undefined)
|
|
252
|
+
unpriced = true;
|
|
253
|
+
else
|
|
254
|
+
value += outcome.costUsd;
|
|
255
|
+
}
|
|
256
|
+
return { value, unpriced };
|
|
257
|
+
}
|
|
258
|
+
function cost(outcome) { return outcome.costUsd ?? 0; }
|
|
259
|
+
function formatUsd(value) { return `${value < 0 ? '-' : ''}$${Math.abs(value).toFixed(2)}`; }
|
|
260
|
+
function isSlug(value, max) { return value.length > 0 && value.length <= max && /^[a-z0-9][a-z0-9._/-]*$/u.test(value); }
|
|
261
|
+
function isProducerId(value) { return value.length > 0 && value.length <= 128 && /^[A-Za-z0-9@][A-Za-z0-9@._/-]*$/u.test(value); }
|
|
262
|
+
async function readSnapshots(storage) {
|
|
263
|
+
let files;
|
|
264
|
+
try {
|
|
265
|
+
files = await storage.listFiles(ROOT, { recursive: true, pattern: '**/*.json', limit: 10_000 });
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
if (error.code === 'ENOENT')
|
|
269
|
+
return [];
|
|
270
|
+
return [{ snapshot: emptySnapshot(), error: `Unable to read savings storage: ${errorMessage(error)}` }];
|
|
271
|
+
}
|
|
272
|
+
const generations = new Map();
|
|
273
|
+
for (const path of files) {
|
|
274
|
+
const match = WRITER_PATTERN.exec(path.replaceAll('\\', '/'));
|
|
275
|
+
if (!match)
|
|
276
|
+
continue;
|
|
277
|
+
const entries = generations.get(match[1]) ?? [];
|
|
278
|
+
entries.push({ path, sequence: Number(match[2]) });
|
|
279
|
+
generations.set(match[1], entries);
|
|
280
|
+
}
|
|
281
|
+
const results = [];
|
|
282
|
+
for (const entries of generations.values()) {
|
|
283
|
+
entries.sort((a, b) => b.sequence - a.sequence);
|
|
284
|
+
let invalid = false;
|
|
285
|
+
for (const { path } of entries) {
|
|
286
|
+
try {
|
|
287
|
+
const storagePath = path.startsWith(`${ROOT}/`) ? path : `${ROOT}/${path}`;
|
|
288
|
+
const value = JSON.parse(decoder.decode(await storage.readFile(storagePath, { maxBytes: MAX_SNAPSHOT_BYTES })));
|
|
289
|
+
if (!isSnapshot(value))
|
|
290
|
+
throw new Error('invalid snapshot');
|
|
291
|
+
results.push({ snapshot: value, ...(invalid ? { error: 'Latest savings snapshot was invalid; used a fallback generation' } : {}) });
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
invalid = true;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (invalid) {
|
|
299
|
+
const writerId = WRITER_PATTERN.exec(entries[0].path.replaceAll('\\', '/'))?.[1];
|
|
300
|
+
if (!results.some(({ snapshot }) => snapshot.writerId === writerId))
|
|
301
|
+
results.push({ snapshot: emptySnapshot(), error: 'All savings snapshot generations were invalid' });
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return results;
|
|
305
|
+
}
|
|
306
|
+
function isSnapshot(value) {
|
|
307
|
+
if (!value || typeof value !== 'object')
|
|
308
|
+
return false;
|
|
309
|
+
const snapshot = value;
|
|
310
|
+
return snapshot.version === 1
|
|
311
|
+
&& typeof snapshot.writerId === 'string'
|
|
312
|
+
&& /^[a-f0-9-]{36}$/u.test(snapshot.writerId)
|
|
313
|
+
&& Number.isSafeInteger(snapshot.sequence)
|
|
314
|
+
&& snapshot.sequence >= 1
|
|
315
|
+
&& typeof snapshot.updatedAt === 'string'
|
|
316
|
+
&& Array.isArray(snapshot.buckets)
|
|
317
|
+
&& snapshot.buckets.length <= MAX_BUCKETS
|
|
318
|
+
&& snapshot.buckets.every(isPersistedBucket);
|
|
319
|
+
}
|
|
320
|
+
function isPersistedBucket(value) {
|
|
321
|
+
if (!value || typeof value !== 'object')
|
|
322
|
+
return false;
|
|
323
|
+
const bucket = value;
|
|
324
|
+
if (typeof bucket.day !== 'string' || typeof bucket.sessionId !== 'string' || typeof bucket.projectKey !== 'string')
|
|
325
|
+
return false;
|
|
326
|
+
try {
|
|
327
|
+
validateMeasurement(bucket.producerId, {
|
|
328
|
+
category: bucket.category,
|
|
329
|
+
...(bucket.operation === undefined ? {} : { operation: bucket.operation }),
|
|
330
|
+
baseline: bucket.baseline,
|
|
331
|
+
actual: bucket.actual,
|
|
332
|
+
basis: bucket.basis,
|
|
333
|
+
calls: bucket.calls,
|
|
334
|
+
dimensions: {
|
|
335
|
+
...(bucket.tool === undefined ? {} : { tool: bucket.tool }),
|
|
336
|
+
...(bucket.techniques === undefined ? {} : { techniques: bucket.techniques }),
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
return isSlug(bucket.day, 10) && isSlug(bucket.sessionId, 128) && isSlug(bucket.projectKey, 128);
|
|
344
|
+
}
|
|
345
|
+
function emptySnapshot() { return { version: 1, writerId: randomUUID(), sequence: 0, updatedAt: new Date(0).toISOString(), buckets: [] }; }
|
|
346
|
+
function errorMessage(error) { return error instanceof Error ? error.message : String(error); }
|
|
347
|
+
//# sourceMappingURL=savings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"savings.js","sourceRoot":"","sources":["../src/savings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAmHzC,MAAM,IAAI,GAAG,YAAY,CAAC;AAC1B,MAAM,cAAc,GAAG,4DAA4D,CAAC;AACpF,MAAM,WAAW,GAAG,KAAK,CAAC;AAC1B,MAAM,kBAAkB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAC3C,MAAM,eAAe,GAAG,CAAC,CAAC;AAC1B,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAClC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,MAAM,OAAO,cAAc;IAChB,QAAQ,CAAsB;IAC9B,QAAQ,CAAwB;IAChC,SAAS,CAAS;IAClB,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;IACrD,SAAS,GAAG,CAAC,CAAC;IACd,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,kBAAkB,GAAG,CAAC,CAAC;IAEvB,YAAY,OAA8B;QACxC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,IAAI,UAAU,EAAE,CAAC;QAClD,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC3F,CAAC;IAED,cAAc,CAAC,UAAkB;QAC/B,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC1F,OAAO;YACL,MAAM,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC;SAC9D,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,UAAkB,EAAE,WAA+B;QAC9D,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YAC7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;YAC9D,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;YAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC3E,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,WAAW;gBAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAM,CAAC,CAAC;YAClG,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC,kBAAkB,IAAI,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAsB,EAAE;QAClC,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrD,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG;YACV,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;YACvH,GAAG,GAAG;SACP,CAAC;QACF,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAClG,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC1C,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACzF,IAAI,IAAI,CAAC,kBAAkB,GAAG,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,kBAAkB,wBAAwB,CAAC,CAAC;QACtG,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC1C,OAAO;YACL,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;YAC1F,WAAW,EAAE,OAAO,CAAC,MAAM;YAC3B,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;YACjE,eAAe,EAAE,QAAQ,CAAC,KAAK;YAC/B,aAAa,EAAE,MAAM,CAAC,KAAK;YAC3B,YAAY,EAAE,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK;YAC3C,uBAAuB,EAAE,QAAQ,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ;YAC7D,OAAO,EAAE,OAAO;YAChB,WAAW;SACZ,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,UAAkB,EAAE,WAA+B;QAClE,mBAAmB,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACvF,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACnF,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QACxD,OAAO;YACL,GAAG,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;YACnC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,aAAa;YACtC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU;YACpC,UAAU;YACV,QAAQ,EAAE,WAAW,CAAC,QAAQ;YAC9B,GAAG,CAAC,WAAW,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,SAAS,EAAE,CAAC;YACpF,KAAK,EAAE,WAAW,CAAC,KAAK;YACxB,GAAG,CAAC,WAAW,CAAC,UAAU,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;YAC5F,GAAG,CAAC,WAAW,CAAC,UAAU,EAAE,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,WAAW,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;YAC9G,KAAK,EAAE,WAAW,CAAC,KAAK,IAAI,CAAC;YAC7B,QAAQ;YACR,MAAM;SACP,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,MAAM,QAAQ,GAAa;YACzB,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,IAAI,CAAC,SAAS;YACxB,QAAQ,EAAE,EAAE,IAAI,CAAC,SAAS;YAC1B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;SACrC,CAAC;QACF,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QACvD,IAAI,KAAK,CAAC,UAAU,GAAG,kBAAkB;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAClG,MAAM,SAAS,GAAG,GAAG,IAAI,YAAY,IAAI,CAAC,SAAS,EAAE,CAAC;QACtD,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,SAAS,IAAI,QAAQ,CAAC,QAAQ,OAAO,EAAE,KAAK,CAAC,CAAC;QAC/E,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC9E,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC;YAC5G,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,SAAS,IAAI,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,QAAQ,CAAI,SAA2B;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC;QAC7B,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC/C,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAED,MAAM,UAAU,sBAAsB,CACpC,YAAwE;IAExE,OAAO,EAAE,YAAY,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAqB,EAAE,QAAQ,GAAG,KAAK;IACzE,MAAM,KAAK,GAAG;QACZ,mBAAmB,MAAM,CAAC,KAAK,EAAE;QACjC,2BAA2B,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE;QAC3D,uBAAuB,MAAM,CAAC,KAAK,EAAE;KACtC,CAAC;IACF,IAAI,MAAM,CAAC,uBAAuB;QAAE,KAAK,CAAC,IAAI,CAAC,iFAAiF,CAAC,CAAC;IAClI,IAAI,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACjG,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,YAAY,UAAU,EAAE,CAAC,CAAC,CAAC;IAChF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAiC;IAC3D,MAAM,OAAO,GAAG,IAAI,GAAG,EAKnB,CAAC;IACL,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;QACjE,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ;YACvB,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,CAAC,YAAY,GAAG,YAAY,EAAE;YAC3G,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;IACvG,CAAC;IAED,MAAM,aAAa,GAA8C;QAC/D,qBAAqB;QACrB,eAAe;QACf,oBAAoB;QACpB,OAAO;KACR,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;SAC/B,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC;WAC9F,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;SACpD,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAChH,MAAM,OAAO,GAAG,CAAC,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACjH,MAAM,SAAS,GAAG,CAAC,GAAsB,EAAU,EAAE,CAAC,GAAG;SACtD,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAE,CAAC,CAAC;SAChG,IAAI,CAAC,IAAI,CAAC;SACV,OAAO,EAAE,CAAC;IACb,OAAO;QACL,SAAS,CAAC,OAAO,CAAC;QAClB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACnD,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;KACvB,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,QAAwC;IAC9D,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC9H,CAAC;AAED,SAAS,mBAAmB,CAAC,UAAkB,EAAE,WAA+B;IAC9E,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,qBAAqB,EAAE,eAAe,EAAE,oBAAoB,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAClM,IAAI,WAAW,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC5H,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC,CAAC,qBAAqB,EAAE,oBAAoB,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC9L,IAAI,WAAW,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,KAAK,GAAG,CAAC,IAAI,WAAW,CAAC,KAAK,GAAG,MAAM,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IACxL,KAAK,MAAM,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC;QAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC3F,KAAK,MAAM,KAAK,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,CAAC,WAAW,CAAC,UAAU,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAClG,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC9F,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;AAC7G,CAAC;AAED,SAAS,eAAe,CAAC,OAAuB;IAC9C,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC3H,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IACzI,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACvI,IAAI,OAAO,CAAC,MAAM;QAAE,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;AACxN,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,OAAuB,EAAE,MAAsC;IAC3F,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjF,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,mBAAmB,EAAE,CAAC;IAC1M,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;IAC9L,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACvD,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;IAChF,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;AACpJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAmB,EAAE,MAA0B;IACpE,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;IACxE,IAAI,KAAK,GAAoC,KAAK,CAAC;IACnD,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC;IACnB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,EAAE;QAAE,IAAI,WAAW,GAAG,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,gBAAgB,GAAG,SAAS,EAAE,CAAC;YACnH,KAAK,GAAG,IAAI,CAAC;YACb,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACpC,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC;IAC3D,OAAO,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,GAAG,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,GAAG,UAAU,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC;AAC1M,CAAC;AAED,SAAS,MAAM,CAAC,MAAyB;IACvC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC;AACtK,CAAC;AAED,SAAS,YAAY,CAAC,IAAmB,EAAE,KAAoB;IAC7D,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;AAC9J,CAAC;AAED,SAAS,YAAY,CAAC,IAA0B,EAAE,KAA2B;IAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,EAAG,IAAI,CAAC,MAA4C,CAAC,GAAG,CAAE,GAAI,KAAK,CAAC,MAA4C,CAAC,GAAG,CAAE,CAAC,CAAC,CAAkC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjR,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACxT,CAAC;AAED,SAAS,SAAS,CAAC,MAAqB;IACtC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC;AACrV,CAAC;AAED,SAAS,aAAa,CAAC,OAAiC,EAAE,KAAmB,EAAE,SAAiB,EAAE,UAAkB;IAClH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAClG,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,UAAU,KAAK,CAAC,KAAK,CAAC,UAAU,IAAI,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,IAAI,MAAM,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,SAAS,IAAI,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AACzb,CAAC;AAED,SAAS,eAAe,CAAC,OAAiC;IACxD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAyB,CAAC;IAChD,KAAK,MAAM,MAAM,IAAI,OAAO;QAAE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC3J,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,OAAO,CAAC,OAAiC,EAAE,IAA2B;IAC7E,IAAI,KAAK,GAAG,CAAC,CAAC;IAAC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACpC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAAC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAAC,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;YAAE,QAAQ,GAAG,IAAI,CAAC;;YAAM,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAAC,CAAC;IAClJ,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,IAAI,CAAC,OAA6B,IAAY,OAAO,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;AACrF,SAAS,SAAS,CAAC,KAAa,IAAY,OAAO,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC7G,SAAS,MAAM,CAAC,KAAa,EAAE,GAAW,IAAa,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG,IAAI,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAClJ,SAAS,YAAY,CAAC,KAAa,IAAa,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG,IAAI,kCAAkC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnJ,KAAK,UAAU,aAAa,CAAC,OAA4B;IACvD,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QAAC,KAAK,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAAC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACtH,IAAK,KAA2B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QAC9D,OAAO,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,mCAAmC,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1G,CAAC;IACD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAqD,CAAC;IACjF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QAC9D,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACnD,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,OAAO,GAAkD,EAAE,CAAC;IAClE,KAAK,MAAM,OAAO,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAChD,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;gBAC3E,MAAM,KAAK,GAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,CAAC;gBACzH,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;gBAC5D,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,iEAAiE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACpI,MAAM;YACR,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAClF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC;gBAAE,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,+CAA+C,EAAE,CAAC,CAAC;QAC3K,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,QAAQ,GAAG,KAAiB,CAAC;IACnC,OAAO,QAAQ,CAAC,OAAO,KAAK,CAAC;WACxB,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ;WACrC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;WAC1C,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC;WACvC,QAAQ,CAAC,QAAQ,IAAI,CAAC;WACtB,OAAO,QAAQ,CAAC,SAAS,KAAK,QAAQ;WACtC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;WAC/B,QAAQ,CAAC,OAAO,CAAC,MAAM,IAAI,WAAW;WACtC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc;IACvC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,MAAM,GAAG,KAAsB,CAAC;IACtC,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAClI,IAAI,CAAC;QACH,mBAAmB,CAAC,MAAM,CAAC,UAAU,EAAE;YACrC,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,GAAG,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;YAC1E,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,UAAU,EAAE;gBACV,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC3D,GAAG,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;aAC9E;SACF,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,KAAK,CAAC;IAAC,CAAC;IACzB,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AACnG,CAAC;AACD,SAAS,aAAa,KAAe,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACrJ,SAAS,YAAY,CAAC,KAAc,IAAY,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/settings.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { SettingsManager } from '@felan-ai/agent-core';
|
|
2
|
-
import type { ExtensionConfigOverride } from '@felan-ai/agent-core';
|
|
1
|
+
import { SettingsManager, type ExtensionConfigDefinition, type ExtensionConfigOverride, type ExtensionConfigValue } from '@felan-ai/agent-core';
|
|
3
2
|
import { type OutputStyle } from '@felan-ai/ext-output-style';
|
|
4
3
|
import { type BuiltinExtensionName, type BuiltinExtensionSettings } from './extensions.js';
|
|
5
4
|
import type { LocalSubagentSettings } from './subagents/host.js';
|
|
@@ -10,7 +9,12 @@ export interface FelanSettings {
|
|
|
10
9
|
readonly felanTui?: FelanTuiSettings;
|
|
11
10
|
readonly extensionConfig?: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
|
|
12
11
|
}
|
|
13
|
-
export
|
|
12
|
+
export interface ResolvedExtensionConfigSettings {
|
|
13
|
+
readonly overrides: readonly ExtensionConfigOverride[];
|
|
14
|
+
readonly configs: ReadonlyMap<string, Readonly<Record<string, ExtensionConfigValue>>>;
|
|
15
|
+
readonly warnings: readonly string[];
|
|
16
|
+
}
|
|
17
|
+
export declare function resolveExtensionConfigSettings(settings: FelanSettings, definitions: readonly ExtensionConfigDefinition[]): ResolvedExtensionConfigSettings;
|
|
14
18
|
export declare function setExtensionConfigValue(agentDir: string, extensionId: string, field: string, value: unknown): Promise<void>;
|
|
15
19
|
export interface FelanTuiSettings {
|
|
16
20
|
readonly toolDisplay?: LocalToolDisplayMode;
|
|
@@ -19,7 +23,7 @@ export interface FelanTuiSettings {
|
|
|
19
23
|
}
|
|
20
24
|
export type LocalToolDisplayMode = 'grouped' | 'full';
|
|
21
25
|
export type LocalDependencyOnboardingChoice = 'continue';
|
|
22
|
-
export declare function getLocalOutputStyle(settingsManager: SettingsManager): OutputStyle;
|
|
26
|
+
export declare function getLocalOutputStyle(settingsManager: SettingsManager, resolvedConfig?: Readonly<Record<string, ExtensionConfigValue>> | null): OutputStyle;
|
|
23
27
|
export declare function createLocalSettingsManager(cwd: string, agentDir: string): SettingsManager;
|
|
24
28
|
export declare function getFelanSettings(settingsManager: SettingsManager): FelanSettings;
|
|
25
29
|
export declare function getLocalToolDisplayMode(settingsManager: SettingsManager): LocalToolDisplayMode;
|
package/dist/settings.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAIA,OAAO,
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"}
|
package/dist/settings.js
CHANGED
|
@@ -2,16 +2,51 @@ import { randomUUID } from 'node:crypto';
|
|
|
2
2
|
import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { VERSION as PI_VERSION } from '@earendil-works/pi-coding-agent';
|
|
5
|
-
import { SettingsManager } from '@felan-ai/agent-core';
|
|
5
|
+
import { SettingsManager, resolveExtensionConfigs, validateExtensionConfigValue, } from '@felan-ai/agent-core';
|
|
6
6
|
import { parseOutputStyle, } from '@felan-ai/ext-output-style';
|
|
7
7
|
import { builtinExtensionPackages, } from './extensions.js';
|
|
8
8
|
import { withLocalFileLock } from './lock.js';
|
|
9
|
-
export function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
export function resolveExtensionConfigSettings(settings, definitions) {
|
|
10
|
+
const configuredExtensions = settings.extensionConfig;
|
|
11
|
+
if (configuredExtensions === undefined) {
|
|
12
|
+
return { overrides: [], configs: resolveExtensionConfigs(definitions), warnings: [] };
|
|
13
|
+
}
|
|
14
|
+
if (!isRecord(configuredExtensions)) {
|
|
15
|
+
return {
|
|
16
|
+
overrides: [],
|
|
17
|
+
configs: resolveExtensionConfigs(definitions),
|
|
18
|
+
warnings: ['settings.json.extensionConfig must be an object; using extension defaults.'],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const overrides = [];
|
|
22
|
+
const warnings = [];
|
|
23
|
+
for (const definition of definitions) {
|
|
24
|
+
const configured = configuredExtensions[definition.id];
|
|
25
|
+
if (configured === undefined)
|
|
26
|
+
continue;
|
|
27
|
+
const source = `settings.json.extensionConfig.${definition.id}`;
|
|
28
|
+
if (!isRecord(configured)) {
|
|
29
|
+
warnings.push(`${source} must be an object; using extension defaults.`);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const values = {};
|
|
33
|
+
for (const [field, value] of Object.entries(configured)) {
|
|
34
|
+
if (!Object.hasOwn(definition.fields, field)) {
|
|
35
|
+
warnings.push(`${source} contains unknown field: ${definition.id}.${field}; ignoring it.`);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
values[field] = validateExtensionConfigValue(definition, field, value, `${source}.${field}`);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
warnings.push(`${errorMessage(error)}; using the default value.`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (Object.keys(values).length > 0) {
|
|
46
|
+
overrides.push({ extensionId: definition.id, values, source });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { overrides, configs: resolveExtensionConfigs(definitions, overrides), warnings };
|
|
15
50
|
}
|
|
16
51
|
export async function setExtensionConfigValue(agentDir, extensionId, field, value) {
|
|
17
52
|
await updateGlobalFelanSettings(agentDir, (settings) => {
|
|
@@ -26,11 +61,17 @@ export async function setExtensionConfigValue(agentDir, extensionId, field, valu
|
|
|
26
61
|
settings.extensionConfig = extensionConfig;
|
|
27
62
|
});
|
|
28
63
|
}
|
|
29
|
-
export function getLocalOutputStyle(settingsManager) {
|
|
64
|
+
export function getLocalOutputStyle(settingsManager, resolvedConfig) {
|
|
30
65
|
const rawSettings = settingsManager.getGlobalSettings();
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
66
|
+
if (resolvedConfig !== undefined) {
|
|
67
|
+
if (resolvedConfig?.style !== undefined)
|
|
68
|
+
return parseOutputStyle(resolvedConfig.style);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
const extensionConfig = rawSettings.extensionConfig;
|
|
72
|
+
if (isRecord(extensionConfig) && isRecord(extensionConfig.outputStyle) && extensionConfig.outputStyle.style !== undefined) {
|
|
73
|
+
return parseOutputStyle(extensionConfig.outputStyle.style);
|
|
74
|
+
}
|
|
34
75
|
}
|
|
35
76
|
return parseOutputStyle(rawSettings.outputStyle);
|
|
36
77
|
}
|
|
@@ -208,4 +249,7 @@ function isAlreadyExistsFile(error) {
|
|
|
208
249
|
function isRecord(value) {
|
|
209
250
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
210
251
|
}
|
|
252
|
+
function errorMessage(error) {
|
|
253
|
+
return error instanceof Error ? error.message : String(error);
|
|
254
|
+
}
|
|
211
255
|
//# sourceMappingURL=settings.js.map
|