@knpkv/agent-usage 0.1.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/LICENSE +21 -0
- package/README.md +111 -0
- package/dist/client/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/client/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/client/assets/index-CUuLXODk.css +1 -0
- package/dist/client/assets/index-DB-VXWqy.js +55 -0
- package/dist/client/index.html +15 -0
- package/dist/core/Attribution.d.ts +59 -0
- package/dist/core/Attribution.js +108 -0
- package/dist/core/Attribution.js.map +1 -0
- package/dist/core/Balances.d.ts +27 -0
- package/dist/core/Balances.js +63 -0
- package/dist/core/Balances.js.map +1 -0
- package/dist/core/ClaudeLimits.d.ts +58 -0
- package/dist/core/ClaudeLimits.js +125 -0
- package/dist/core/ClaudeLimits.js.map +1 -0
- package/dist/core/ClaudeLimitsLive.d.ts +18 -0
- package/dist/core/ClaudeLimitsLive.js +36 -0
- package/dist/core/ClaudeLimitsLive.js.map +1 -0
- package/dist/core/ClaudeReader.d.ts +27 -0
- package/dist/core/ClaudeReader.js +154 -0
- package/dist/core/ClaudeReader.js.map +1 -0
- package/dist/core/CodexReader.d.ts +91 -0
- package/dist/core/CodexReader.js +365 -0
- package/dist/core/CodexReader.js.map +1 -0
- package/dist/core/Database.d.ts +4 -0
- package/dist/core/Database.js +65 -0
- package/dist/core/Database.js.map +1 -0
- package/dist/core/Ingest.d.ts +55 -0
- package/dist/core/Ingest.js +267 -0
- package/dist/core/Ingest.js.map +1 -0
- package/dist/core/Model.d.ts +160 -0
- package/dist/core/Model.js +125 -0
- package/dist/core/Model.js.map +1 -0
- package/dist/core/Pricing.d.ts +42 -0
- package/dist/core/Pricing.js +126 -0
- package/dist/core/Pricing.js.map +1 -0
- package/dist/core/Readers.d.ts +42 -0
- package/dist/core/Readers.js +18 -0
- package/dist/core/Readers.js.map +1 -0
- package/dist/core/Report.d.ts +53 -0
- package/dist/core/Report.js +270 -0
- package/dist/core/Report.js.map +1 -0
- package/dist/core/Store.d.ts +94 -0
- package/dist/core/Store.js +376 -0
- package/dist/core/Store.js.map +1 -0
- package/dist/core/Tickets.d.ts +42 -0
- package/dist/core/Tickets.js +125 -0
- package/dist/core/Tickets.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +65 -0
- package/dist/main.js.map +1 -0
- package/dist/server/Api.d.ts +304 -0
- package/dist/server/Api.js +20 -0
- package/dist/server/Api.js.map +1 -0
- package/dist/server/Config.d.ts +27 -0
- package/dist/server/Config.js +49 -0
- package/dist/server/Config.js.map +1 -0
- package/dist/server/Handlers.d.ts +5 -0
- package/dist/server/Handlers.js +48 -0
- package/dist/server/Handlers.js.map +1 -0
- package/dist/server/HttpApplication.d.ts +7 -0
- package/dist/server/HttpApplication.js +70 -0
- package/dist/server/HttpApplication.js.map +1 -0
- package/dist/server/OwnerSession.d.ts +60 -0
- package/dist/server/OwnerSession.js +206 -0
- package/dist/server/OwnerSession.js.map +1 -0
- package/dist/server/Runtime.d.ts +57 -0
- package/dist/server/Runtime.js +85 -0
- package/dist/server/Runtime.js.map +1 -0
- package/dist/server/Server.d.ts +15 -0
- package/dist/server/Server.js +39 -0
- package/dist/server/Server.js.map +1 -0
- package/dist/shared/contracts.d.ts +309 -0
- package/dist/shared/contracts.js +105 -0
- package/dist/shared/contracts.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turning stored facts into what the graphs draw: usage per local period and Booking, and limit
|
|
3
|
+
* series as steps.
|
|
4
|
+
*
|
|
5
|
+
* **Mental model**
|
|
6
|
+
*
|
|
7
|
+
* - **Periods are the viewer's.** The browser sends its IANA zone; hours, days and weeks start at
|
|
8
|
+
* local midnight (weeks on Monday), so a daylight-saving day is 23 or 25 hours long. Each stored
|
|
9
|
+
* 15-minute bucket belongs to exactly one period, because every zone offset is a multiple of 15.
|
|
10
|
+
* - **Bookings and costs are derived here** (ADR 0002), from Attribution Inputs, the Known
|
|
11
|
+
* Projects and today's prices. Typed keys of unknown projects are counted by prefix, not hidden.
|
|
12
|
+
* Unpriced tokens are carried beside the cost, never folded into it as zero.
|
|
13
|
+
* - **A step line needs its starting value.** Each limit series begins at the range's left edge
|
|
14
|
+
* with the reading in force there, taken from the last snapshot before it.
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*/
|
|
18
|
+
import { Data, Effect, Option } from "effect";
|
|
19
|
+
import { attribute, bookingId, projectOf } from "./Attribution.js";
|
|
20
|
+
import { totalTokens } from "./Model.js";
|
|
21
|
+
import { groupCost } from "./Pricing.js";
|
|
22
|
+
import { BUCKET_MILLIS } from "./Store.js";
|
|
23
|
+
export class UnknownTimeZone extends Data.TaggedError("UnknownTimeZone") {
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Accepts any zone `Intl.DateTimeFormat` accepts, aliases and `Etc/GMT+5` included. The list
|
|
27
|
+
* `Intl.supportedValuesOf` returns is narrower than what the formatter takes, and a browser sends
|
|
28
|
+
* whatever its own runtime resolved.
|
|
29
|
+
*/
|
|
30
|
+
export const checkTimeZone = (zone) => Effect.try({
|
|
31
|
+
try: () => new Intl.DateTimeFormat("en-CA", { timeZone: zone }).resolvedOptions().timeZone,
|
|
32
|
+
catch: () => new UnknownTimeZone({ zone })
|
|
33
|
+
}).pipe(Effect.as(zone));
|
|
34
|
+
const formatters = new Map();
|
|
35
|
+
const formatterFor = (timeZone) => {
|
|
36
|
+
const cached = formatters.get(timeZone);
|
|
37
|
+
if (cached !== undefined)
|
|
38
|
+
return cached;
|
|
39
|
+
const created = new Intl.DateTimeFormat("en-CA", {
|
|
40
|
+
timeZone,
|
|
41
|
+
year: "numeric",
|
|
42
|
+
month: "2-digit",
|
|
43
|
+
day: "2-digit",
|
|
44
|
+
hour: "2-digit",
|
|
45
|
+
hourCycle: "h23",
|
|
46
|
+
timeZoneName: "longOffset"
|
|
47
|
+
});
|
|
48
|
+
formatters.set(timeZone, created);
|
|
49
|
+
return created;
|
|
50
|
+
};
|
|
51
|
+
const pad = (value) => String(value).padStart(2, "0");
|
|
52
|
+
/** The local period an instant falls in, as a sortable key. */
|
|
53
|
+
const periodKey = (instant, timeZone, bucket) => {
|
|
54
|
+
const parts = new Map(formatterFor(timeZone).formatToParts(instant).map((part) => [part.type, part.value]));
|
|
55
|
+
const year = Number(parts.get("year"));
|
|
56
|
+
const month = Number(parts.get("month"));
|
|
57
|
+
const day = Number(parts.get("day"));
|
|
58
|
+
// The offset keeps the hour that repeats when clocks go back apart from its first occurrence.
|
|
59
|
+
if (bucket === "hour") {
|
|
60
|
+
return `${year}-${pad(month)}-${pad(day)}T${parts.get("hour") ?? "00"}${parts.get("timeZoneName") ?? ""}`;
|
|
61
|
+
}
|
|
62
|
+
if (bucket === "day")
|
|
63
|
+
return `${year}-${pad(month)}-${pad(day)}`;
|
|
64
|
+
// Calendar arithmetic on the local date alone: back up to Monday.
|
|
65
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
66
|
+
const sinceMonday = (date.getUTCDay() + 6) % 7;
|
|
67
|
+
const monday = new Date(Date.UTC(year, month - 1, day - sinceMonday));
|
|
68
|
+
return `${monday.getUTCFullYear()}-${pad(monday.getUTCMonth() + 1)}-${pad(monday.getUTCDate())}`;
|
|
69
|
+
};
|
|
70
|
+
/** Every local period the range touches, each with the first 15-minute instant inside the range. */
|
|
71
|
+
export const periodsOf = (options) => {
|
|
72
|
+
const periods = [];
|
|
73
|
+
const first = options.from - (options.from % BUCKET_MILLIS);
|
|
74
|
+
for (let instant = first; instant < options.to; instant += BUCKET_MILLIS) {
|
|
75
|
+
const key = periodKey(instant, options.timeZone, options.bucket);
|
|
76
|
+
if (periods.at(-1)?.key !== key)
|
|
77
|
+
periods.push({ key, start: Math.max(instant, options.from) });
|
|
78
|
+
}
|
|
79
|
+
return periods;
|
|
80
|
+
};
|
|
81
|
+
/** Which period a bucket start belongs to, by binary search over period starts. */
|
|
82
|
+
const periodIndex = (periods, bucketStart, end) => {
|
|
83
|
+
const first = periods[0]?.start;
|
|
84
|
+
if (first === undefined)
|
|
85
|
+
return null;
|
|
86
|
+
// The range may start inside a 15-minute bucket; the store already kept only the events inside
|
|
87
|
+
// the range, so that first partial bucket belongs to the first period.
|
|
88
|
+
const instant = bucketStart < first && bucketStart + BUCKET_MILLIS > first ? first : bucketStart;
|
|
89
|
+
if (instant < first || instant >= end)
|
|
90
|
+
return null;
|
|
91
|
+
let low = 0;
|
|
92
|
+
let high = periods.length - 1;
|
|
93
|
+
while (low < high) {
|
|
94
|
+
const middle = Math.ceil((low + high) / 2);
|
|
95
|
+
if ((periods[middle]?.start ?? 0) <= instant)
|
|
96
|
+
low = middle;
|
|
97
|
+
else
|
|
98
|
+
high = middle - 1;
|
|
99
|
+
}
|
|
100
|
+
return low;
|
|
101
|
+
};
|
|
102
|
+
const zeroTokens = { input: 0, output: 0, reasoning: 0, cacheRead: 0, cacheWrite5m: 0, cacheWrite1h: 0 };
|
|
103
|
+
const addTokens = (left, right) => ({
|
|
104
|
+
input: left.input + right.input,
|
|
105
|
+
output: left.output + right.output,
|
|
106
|
+
reasoning: left.reasoning + right.reasoning,
|
|
107
|
+
cacheRead: left.cacheRead + right.cacheRead,
|
|
108
|
+
cacheWrite5m: left.cacheWrite5m + right.cacheWrite5m,
|
|
109
|
+
cacheWrite1h: left.cacheWrite1h + right.cacheWrite1h
|
|
110
|
+
});
|
|
111
|
+
/**
|
|
112
|
+
* Usage per period and Booking. `end` bounds the last period; groups outside every period are
|
|
113
|
+
* dropped. Titles are looked up by ticket key.
|
|
114
|
+
*/
|
|
115
|
+
export const buildUsageReport = (groups, periods, titles, projects, end = Number.POSITIVE_INFINITY) => {
|
|
116
|
+
const bookings = new Map();
|
|
117
|
+
const cells = new Map();
|
|
118
|
+
const unpricedModels = new Set();
|
|
119
|
+
let unpricedTokens = 0;
|
|
120
|
+
const ignored = new Map();
|
|
121
|
+
for (const group of groups) {
|
|
122
|
+
const period = periodIndex(periods, group.bucketStart, end);
|
|
123
|
+
if (period === null)
|
|
124
|
+
continue;
|
|
125
|
+
const { booking, ignoredKey } = attribute(group.attribution, projects);
|
|
126
|
+
if (ignoredKey !== null) {
|
|
127
|
+
const prefix = projectOf(ignoredKey);
|
|
128
|
+
ignored.set(prefix, (ignored.get(prefix) ?? 0) + group.requests);
|
|
129
|
+
}
|
|
130
|
+
const id = bookingId(booking);
|
|
131
|
+
const tokens = totalTokens(group.tokens);
|
|
132
|
+
const cost = groupCost(group);
|
|
133
|
+
const costUsd = Option.getOrElse(cost, () => 0);
|
|
134
|
+
const unpriced = Option.isNone(cost) ? tokens : 0;
|
|
135
|
+
if (Option.isNone(cost)) {
|
|
136
|
+
unpricedModels.add(group.model);
|
|
137
|
+
unpricedTokens += tokens;
|
|
138
|
+
}
|
|
139
|
+
const existing = bookings.get(id);
|
|
140
|
+
const current = existing ?? {
|
|
141
|
+
summary: {
|
|
142
|
+
id,
|
|
143
|
+
booking,
|
|
144
|
+
title: booking._tag === "Ticket" ? titles[booking.key] ?? { _tag: "Unknown", reason: "NotLookedUp" } : null,
|
|
145
|
+
requests: 0,
|
|
146
|
+
tokens: zeroTokens,
|
|
147
|
+
costUsd: 0,
|
|
148
|
+
unpricedTokens: 0
|
|
149
|
+
},
|
|
150
|
+
agents: new Set(),
|
|
151
|
+
unpricedModels: new Set()
|
|
152
|
+
};
|
|
153
|
+
current.agents.add(group.agent);
|
|
154
|
+
if (Option.isNone(cost))
|
|
155
|
+
current.unpricedModels.add(group.model);
|
|
156
|
+
bookings.set(id, {
|
|
157
|
+
...current,
|
|
158
|
+
summary: {
|
|
159
|
+
...current.summary,
|
|
160
|
+
requests: current.summary.requests + group.requests,
|
|
161
|
+
tokens: addTokens(current.summary.tokens, group.tokens),
|
|
162
|
+
costUsd: current.summary.costUsd + costUsd,
|
|
163
|
+
unpricedTokens: current.summary.unpricedTokens + unpriced
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
const cellKey = `${period}\u0000${id}`;
|
|
167
|
+
const cell = cells.get(cellKey) ?? { period, booking: id, tokens: 0, costUsd: 0, unpricedTokens: 0 };
|
|
168
|
+
cells.set(cellKey, {
|
|
169
|
+
...cell,
|
|
170
|
+
tokens: cell.tokens + tokens,
|
|
171
|
+
costUsd: cell.costUsd + costUsd,
|
|
172
|
+
unpricedTokens: cell.unpricedTokens + unpriced
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
const summaries = [...bookings.values()]
|
|
176
|
+
.map((booking) => ({
|
|
177
|
+
...booking.summary,
|
|
178
|
+
agents: [...booking.agents].sort(),
|
|
179
|
+
unpricedModels: [...booking.unpricedModels].sort()
|
|
180
|
+
}))
|
|
181
|
+
.sort((left, right) => right.costUsd - left.costUsd || totalTokens(right.tokens) - totalTokens(left.tokens) ||
|
|
182
|
+
left.id.localeCompare(right.id));
|
|
183
|
+
const order = new Map(summaries.map((summary, index) => [summary.id, index]));
|
|
184
|
+
return {
|
|
185
|
+
periods,
|
|
186
|
+
bookings: summaries,
|
|
187
|
+
cells: [...cells.values()].sort((left, right) => left.period - right.period || (order.get(left.booking) ?? 0) - (order.get(right.booking) ?? 0)),
|
|
188
|
+
unpriced: { tokens: unpricedTokens, models: [...unpricedModels].sort() },
|
|
189
|
+
ignoredKeys: [...ignored]
|
|
190
|
+
.map(([prefix, requests]) => ({ prefix, requests }))
|
|
191
|
+
.sort((left, right) => right.requests - left.requests || left.prefix.localeCompare(right.prefix))
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
/**
|
|
195
|
+
* Which series a snapshot continues. Codex reports windows by slot (`primary`, `secondary`) and a
|
|
196
|
+
* plan change moves the weekly window between slots, so Codex series follow the window's length.
|
|
197
|
+
* Claude names each window, and two weekly windows (`seven_day`, `seven_day_opus`) are different
|
|
198
|
+
* allowances, so Claude series follow the name.
|
|
199
|
+
*/
|
|
200
|
+
const seriesKey = (snapshot) => snapshot.source === "codex-rollout" && snapshot.windowMinutes !== null
|
|
201
|
+
? `${snapshot.agent}\u0000${snapshot.windowMinutes}m`
|
|
202
|
+
: `${snapshot.agent}\u0000${snapshot.label}`;
|
|
203
|
+
const sameReading = (left, right) => left._tag === "Known" && right._tag === "Known"
|
|
204
|
+
? left.usedPercent === right.usedPercent && left.resetsAt === right.resetsAt
|
|
205
|
+
: left._tag === "Unknown" && right._tag === "Unknown" && left.reason === right.reason;
|
|
206
|
+
/**
|
|
207
|
+
* Limit series over a range, from every snapshot up to its end in time order. Each series starts
|
|
208
|
+
* at `from` with the reading in force there when one exists.
|
|
209
|
+
*/
|
|
210
|
+
export const buildLimitsReport = (snapshots, range) => {
|
|
211
|
+
const series = new Map();
|
|
212
|
+
const latest = new Map();
|
|
213
|
+
const append = (entry, at, reading) => {
|
|
214
|
+
const point = { at: Math.max(at, range.from), reading };
|
|
215
|
+
// Before the range, only the newest reading matters: it becomes the left-edge point.
|
|
216
|
+
if (at < range.from) {
|
|
217
|
+
entry.points = [point];
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
// An unchanged reading continues the step it repeats; a failed poll in between has already
|
|
221
|
+
// broken it with an Unknown point, so a recovery still starts a new one.
|
|
222
|
+
const last = entry.points.at(-1);
|
|
223
|
+
if (last !== undefined && sameReading(last.reading, reading))
|
|
224
|
+
return;
|
|
225
|
+
entry.points.push(point);
|
|
226
|
+
};
|
|
227
|
+
const ordered = [...snapshots].sort((left, right) => left.observedAt - right.observedAt);
|
|
228
|
+
for (const snapshot of ordered) {
|
|
229
|
+
if (snapshot.observedAt >= range.to)
|
|
230
|
+
continue;
|
|
231
|
+
const key = seriesKey(snapshot);
|
|
232
|
+
// The tiles show the newest observation, so "read … ago" moves on with unchanged readings.
|
|
233
|
+
latest.set(key, snapshot);
|
|
234
|
+
const entry = series.get(key) ??
|
|
235
|
+
{
|
|
236
|
+
agent: snapshot.agent,
|
|
237
|
+
label: snapshot.label,
|
|
238
|
+
windowMinutes: snapshot.windowMinutes,
|
|
239
|
+
source: snapshot.source,
|
|
240
|
+
points: []
|
|
241
|
+
};
|
|
242
|
+
entry.label = snapshot.label;
|
|
243
|
+
entry.windowMinutes = snapshot.windowMinutes;
|
|
244
|
+
series.set(key, entry);
|
|
245
|
+
append(entry, snapshot.observedAt, snapshot.reading);
|
|
246
|
+
// A source that could not be read at all breaks every window it reports, so no level is
|
|
247
|
+
// carried across the outage.
|
|
248
|
+
if (snapshot.label === "*") {
|
|
249
|
+
for (const [other, otherEntry] of series) {
|
|
250
|
+
if (other !== key && otherEntry.agent === snapshot.agent && otherEntry.source === snapshot.source) {
|
|
251
|
+
append(otherEntry, snapshot.observedAt, snapshot.reading);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const byOrder = (left, right) => left.agent.localeCompare(right.agent) || left.label.localeCompare(right.label);
|
|
257
|
+
// A series with no Known reading still in force inside the range has nothing to draw.
|
|
258
|
+
const live = [...series.values()].map((entry) => ({
|
|
259
|
+
agent: entry.agent,
|
|
260
|
+
label: entry.label,
|
|
261
|
+
windowMinutes: entry.windowMinutes,
|
|
262
|
+
points: entry.points
|
|
263
|
+
})).filter((entry) => entry.points.some((point) => point.reading._tag === "Known" &&
|
|
264
|
+
(point.at > range.from || point.reading.resetsAt === null || point.reading.resetsAt > range.from)));
|
|
265
|
+
return {
|
|
266
|
+
series: live.sort(byOrder),
|
|
267
|
+
latest: [...latest.values()].sort(byOrder)
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
//# sourceMappingURL=Report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Report.js","sourceRoot":"","sources":["../../src/core/Report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE7C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAElE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,aAAa,EAA+B,MAAM,YAAY,CAAA;AAIvE,MAAM,OAAO,eAAgB,SAAQ,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAA4B;CAAG;AAEtG;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAY,EAA0C,EAAE,CACpF,MAAM,CAAC,GAAG,CAAC;IACT,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,eAAe,EAAE,CAAC,QAAQ;IAC1F,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC;CAC3C,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;AAE1B,MAAM,UAAU,GAAG,IAAI,GAAG,EAA+B,CAAA;AAEzD,MAAM,YAAY,GAAG,CAAC,QAAgB,EAAuB,EAAE;IAC7D,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACvC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAA;IACvC,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QAC/C,QAAQ;QACR,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;QACf,SAAS,EAAE,KAAK;QAChB,YAAY,EAAE,YAAY;KAC3B,CAAC,CAAA;IACF,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IACjC,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,GAAG,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AAErE,+DAA+D;AAC/D,MAAM,SAAS,GAAG,CAAC,OAAe,EAAE,QAAgB,EAAE,MAAoB,EAAU,EAAE;IACpF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC3G,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAA;IACxC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;IACpC,8FAA8F;IAC9F,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,GAAG,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAA;IAC3G,CAAC;IACD,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,GAAG,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,CAAA;IAChE,kEAAkE;IAClE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;IACrD,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;IAC9C,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,GAAG,WAAW,CAAC,CAAC,CAAA;IACrE,OAAO,GAAG,MAAM,CAAC,cAAc,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,EAAE,CAAA;AAClG,CAAC,CAAA;AAED,oGAAoG;AACpG,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAKzB,EAAyB,EAAE;IAC1B,MAAM,OAAO,GAAkB,EAAE,CAAA;IACjC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,aAAa,CAAC,CAAA;IAC3D,KAAK,IAAI,OAAO,GAAG,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,EAAE,EAAE,OAAO,IAAI,aAAa,EAAE,CAAC;QACzE,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;QAChE,IAAI,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,GAAG;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChG,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED,mFAAmF;AACnF,MAAM,WAAW,GAAG,CAAC,OAA8B,EAAE,WAAmB,EAAE,GAAW,EAAiB,EAAE;IACtG,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,CAAA;IAC/B,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IACpC,+FAA+F;IAC/F,uEAAuE;IACvE,MAAM,OAAO,GAAG,WAAW,GAAG,KAAK,IAAI,WAAW,GAAG,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAA;IAChG,IAAI,OAAO,GAAG,KAAK,IAAI,OAAO,IAAI,GAAG;QAAE,OAAO,IAAI,CAAA;IAClD,IAAI,GAAG,GAAG,CAAC,CAAA;IACX,IAAI,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAA;IAC7B,OAAO,GAAG,GAAG,IAAI,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;QAC1C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,IAAI,OAAO;YAAE,GAAG,GAAG,MAAM,CAAA;;YACrD,IAAI,GAAG,MAAM,GAAG,CAAC,CAAA;IACxB,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AAED,MAAM,UAAU,GAAW,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAA;AAEhH,MAAM,SAAS,GAAG,CAAC,IAAY,EAAE,KAAa,EAAU,EAAE,CAAC,CAAC;IAC1D,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK;IAC/B,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM;IAClC,SAAS,EAAE,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS;IAC3C,SAAS,EAAE,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS;IAC3C,YAAY,EAAE,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY;IACpD,YAAY,EAAE,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY;CACrD,CAAC,CAAA;AAQF;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,MAAiC,EACjC,OAA8B,EAC9B,MAAkD,EAClD,QAA6B,EAC7B,GAAG,GAAW,MAAM,CAAC,iBAAiB,EACzB,EAAE;IACf,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAA;IAClD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqB,CAAA;IAC1C,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAA;IACxC,IAAI,cAAc,GAAG,CAAC,CAAA;IACtB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAA;IAEzC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;QAC3D,IAAI,MAAM,KAAK,IAAI;YAAE,SAAQ;QAC7B,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;QACtE,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,CAAC,CAAA;YACpC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAA;QAClE,CAAC;QACD,MAAM,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,CAAA;QAC7B,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QACxC,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;QAC7B,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;QAC/C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;QACjD,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YAC/B,cAAc,IAAI,MAAM,CAAA;QAC1B,CAAC;QAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACjC,MAAM,OAAO,GAAmB,QAAQ,IAAI;YAC1C,OAAO,EAAE;gBACP,EAAE;gBACF,OAAO;gBACP,KAAK,EAAE,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI;gBAC3G,QAAQ,EAAE,CAAC;gBACX,MAAM,EAAE,UAAU;gBAClB,OAAO,EAAE,CAAC;gBACV,cAAc,EAAE,CAAC;aAClB;YACD,MAAM,EAAE,IAAI,GAAG,EAAE;YACjB,cAAc,EAAE,IAAI,GAAG,EAAE;SAC1B,CAAA;QACD,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAC/B,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAChE,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE;YACf,GAAG,OAAO;YACV,OAAO,EAAE;gBACP,GAAG,OAAO,CAAC,OAAO;gBAClB,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ;gBACnD,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;gBACvD,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO,GAAG,OAAO;gBAC1C,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,cAAc,GAAG,QAAQ;aAC1D;SACF,CAAC,CAAA;QAEF,MAAM,OAAO,GAAG,GAAG,MAAM,SAAS,EAAE,EAAE,CAAA;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,CAAA;QACpG,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE;YACjB,GAAG,IAAI;YACP,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,MAAM;YAC5B,OAAO,EAAE,IAAI,CAAC,OAAO,GAAG,OAAO;YAC/B,cAAc,EAAE,IAAI,CAAC,cAAc,GAAG,QAAQ;SAC/C,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;SACrC,GAAG,CAAC,CAAC,OAAO,EAAkB,EAAE,CAAC,CAAC;QACjC,GAAG,OAAO,CAAC,OAAO;QAClB,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;QAClC,cAAc,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,IAAI,EAAE;KACnD,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACpB,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;QACpF,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAChC,CAAA;IACH,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;IAC7E,OAAO;QACL,OAAO;QACP,QAAQ,EAAE,SAAS;QACnB,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAC9C,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAC/F;QACD,QAAQ,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,GAAG,cAAc,CAAC,CAAC,IAAI,EAAE,EAAE;QACxE,WAAW,EAAE,CAAC,GAAG,OAAO,CAAC;aACtB,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;aACnD,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;KACpG,CAAA;AACH,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,SAAS,GAAG,CAAC,QAAuB,EAAU,EAAE,CACpD,QAAQ,CAAC,MAAM,KAAK,eAAe,IAAI,QAAQ,CAAC,aAAa,KAAK,IAAI;IACpE,CAAC,CAAC,GAAG,QAAQ,CAAC,KAAK,SAAS,QAAQ,CAAC,aAAa,GAAG;IACrD,CAAC,CAAC,GAAG,QAAQ,CAAC,KAAK,SAAS,QAAQ,CAAC,KAAK,EAAE,CAAA;AAEhD,MAAM,WAAW,GAAG,CAAC,IAA8B,EAAE,KAA+B,EAAW,EAAE,CAC/F,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;IAC7C,CAAC,CAAC,IAAI,CAAC,WAAW,KAAK,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ;IAC5E,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAA;AAEzF;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,SAAuC,EACvC,KAAY,EACoB,EAAE;IAQlC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoB,CAAA;IAC1C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAyB,CAAA;IAC/C,MAAM,MAAM,GAAG,CAAC,KAAe,EAAE,EAAU,EAAE,OAAiC,EAAE,EAAE;QAChF,MAAM,KAAK,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAA;QACvD,qFAAqF;QACrF,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAA;YACtB,OAAM;QACR,CAAC;QACD,2FAA2F;QAC3F,yEAAyE;QACzE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QAChC,IAAI,IAAI,KAAK,SAAS,IAAI,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;YAAE,OAAM;QACpE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC1B,CAAC,CAAA;IACD,MAAM,OAAO,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,CAAA;IACxF,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC/B,IAAI,QAAQ,CAAC,UAAU,IAAI,KAAK,CAAC,EAAE;YAAE,SAAQ;QAC7C,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAA;QAC/B,2FAA2F;QAC3F,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;QACzB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;YAC3B;gBACE,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,aAAa,EAAE,QAAQ,CAAC,aAAa;gBACrC,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,MAAM,EAAE,EAAE;aACX,CAAA;QACH,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAA;QAC5B,KAAK,CAAC,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAA;QAC5C,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACtB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;QACpD,wFAAwF;QACxF,6BAA6B;QAC7B,IAAI,QAAQ,CAAC,KAAK,KAAK,GAAG,EAAE,CAAC;YAC3B,KAAK,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,MAAM,EAAE,CAAC;gBACzC,IAAI,KAAK,KAAK,GAAG,IAAI,UAAU,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,IAAI,UAAU,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;oBAClG,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;gBAC3D,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,IAAwD,EAAE,KAAkB,EAAE,EAAE,CAC/F,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAChF,sFAAsF;IACtF,MAAM,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAe,EAAE,CAAC,CAAC;QAC7D,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CACnB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAC1B,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,OAAO;QAC9B,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAClG,CACF,CAAA;IACD,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;QAC1B,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;KAC3C,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Context, Effect, Layer, Option, Schema } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import { Agent, type BalanceReading, type LimitSnapshot, type UsageEvent } from "./Model.js";
|
|
4
|
+
declare const StoreError_base: Schema.Class<StoreError, Schema.TaggedStruct<"StoreError", {
|
|
5
|
+
readonly operation: Schema.String;
|
|
6
|
+
readonly cause: Schema.Defect;
|
|
7
|
+
}>, import("effect/Cause").YieldableError>;
|
|
8
|
+
export declare class StoreError extends StoreError_base {
|
|
9
|
+
}
|
|
10
|
+
/** How far a source file has been read, and the reader state to resume with (reader-owned JSON). */
|
|
11
|
+
export declare const Cursor: Schema.Struct<{
|
|
12
|
+
/** Device and inode: a file that was replaced reads from 0 again. */
|
|
13
|
+
readonly identity: Schema.String;
|
|
14
|
+
readonly offset: Schema.Int;
|
|
15
|
+
readonly state: Schema.String;
|
|
16
|
+
}>;
|
|
17
|
+
export type Cursor = typeof Cursor.Type;
|
|
18
|
+
export interface Chunk {
|
|
19
|
+
readonly agent: Agent;
|
|
20
|
+
readonly fileKey: string;
|
|
21
|
+
readonly cursor: Cursor;
|
|
22
|
+
readonly events: ReadonlyArray<UsageEvent>;
|
|
23
|
+
readonly snapshots: ReadonlyArray<LimitSnapshot>;
|
|
24
|
+
readonly balances: ReadonlyArray<BalanceReading>;
|
|
25
|
+
}
|
|
26
|
+
/** A half-open time range in epoch milliseconds. */
|
|
27
|
+
export interface Range {
|
|
28
|
+
readonly from: number;
|
|
29
|
+
readonly to: number;
|
|
30
|
+
}
|
|
31
|
+
/** A range on one Machine: every read is scoped to the Machine this server runs as (ADR 0001). */
|
|
32
|
+
export interface MachineRange extends Range {
|
|
33
|
+
readonly machine: string;
|
|
34
|
+
}
|
|
35
|
+
/** Usage summed over one 15-minute bucket and every dimension that prices or books it. */
|
|
36
|
+
export declare const UsageGroup: Schema.Struct<{
|
|
37
|
+
readonly bucketStart: Schema.Int;
|
|
38
|
+
readonly agent: Schema.Literals<readonly ["claude", "codex"]>;
|
|
39
|
+
readonly model: Schema.String;
|
|
40
|
+
readonly fast: Schema.Boolean;
|
|
41
|
+
readonly longPrompt: Schema.Boolean;
|
|
42
|
+
readonly attribution: Schema.Struct<{
|
|
43
|
+
readonly cwd: Schema.String;
|
|
44
|
+
readonly branch: Schema.String;
|
|
45
|
+
readonly activeTicket: Schema.NullOr<Schema.String>;
|
|
46
|
+
}>;
|
|
47
|
+
readonly requests: Schema.Int;
|
|
48
|
+
readonly tokens: Schema.Struct<{
|
|
49
|
+
readonly input: Schema.Int;
|
|
50
|
+
readonly output: Schema.Int;
|
|
51
|
+
readonly reasoning: Schema.Int;
|
|
52
|
+
readonly cacheRead: Schema.Int;
|
|
53
|
+
readonly cacheWrite5m: Schema.Int;
|
|
54
|
+
readonly cacheWrite1h: Schema.Int;
|
|
55
|
+
}>;
|
|
56
|
+
}>;
|
|
57
|
+
export type UsageGroup = typeof UsageGroup.Type;
|
|
58
|
+
export declare const TicketTitle: Schema.Struct<{
|
|
59
|
+
readonly key: Schema.String;
|
|
60
|
+
/** Null when the lookup ran and found no title. */
|
|
61
|
+
readonly summary: Schema.NullOr<Schema.String>;
|
|
62
|
+
readonly fetchedAt: Schema.Int;
|
|
63
|
+
}>;
|
|
64
|
+
export type TicketTitle = typeof TicketTitle.Type;
|
|
65
|
+
export declare const BUCKET_MILLIS: number;
|
|
66
|
+
declare const UsageStore_base: Context.ServiceClass<UsageStore, "@knpkv/agent-usage/core/Store/UsageStore", {
|
|
67
|
+
readonly cursor: (agent: Agent, fileKey: string) => Effect.Effect<Option.Option<Cursor>, StoreError>;
|
|
68
|
+
/** Writes a chunk's events, observations and cursor in one transaction. */
|
|
69
|
+
readonly commitChunk: (chunk: Chunk) => Effect.Effect<{
|
|
70
|
+
readonly eventsAdded: number;
|
|
71
|
+
}, StoreError>;
|
|
72
|
+
/** Records observations made outside a file chunk, such as a limit poll. */
|
|
73
|
+
readonly recordObservations: (snapshots: ReadonlyArray<LimitSnapshot>, balances: ReadonlyArray<BalanceReading>) => Effect.Effect<void, StoreError>;
|
|
74
|
+
readonly usageGroups: (range: MachineRange) => Effect.Effect<ReadonlyArray<UsageGroup>, StoreError>;
|
|
75
|
+
/** Every distinct branch and working directory ever recorded: what vouches for Known Projects. */
|
|
76
|
+
readonly places: (machine: string) => Effect.Effect<ReadonlyArray<{
|
|
77
|
+
readonly branch: string;
|
|
78
|
+
readonly cwd: string;
|
|
79
|
+
}>, StoreError>;
|
|
80
|
+
/**
|
|
81
|
+
* A Machine's limit history for a range, compressed: per series, the last observation before the
|
|
82
|
+
* range, every change inside it (an equal reading after a failed poll counts as a change, so the
|
|
83
|
+
* recovery shows), and the last observation before the range ends.
|
|
84
|
+
*/
|
|
85
|
+
readonly limitSnapshots: (range: MachineRange) => Effect.Effect<ReadonlyArray<LimitSnapshot>, StoreError>;
|
|
86
|
+
/** The newest reading of each balance kind on each machine. */
|
|
87
|
+
readonly latestBalances: (machine: string) => Effect.Effect<ReadonlyArray<BalanceReading>, StoreError>;
|
|
88
|
+
readonly tickets: (keys: ReadonlyArray<string>) => Effect.Effect<ReadonlyArray<TicketTitle>, StoreError>;
|
|
89
|
+
readonly saveTicket: (ticket: TicketTitle) => Effect.Effect<void, StoreError>;
|
|
90
|
+
}>;
|
|
91
|
+
export declare class UsageStore extends UsageStore_base {
|
|
92
|
+
static readonly layer: Layer.Layer<UsageStore, StoreError, SqlClient.SqlClient>;
|
|
93
|
+
}
|
|
94
|
+
export {};
|