inferock-bench 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/dist/init.js ADDED
@@ -0,0 +1,130 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { createInterface } from "node:readline/promises";
4
+ import { stdin as input, stdout as output } from "node:process";
5
+ import { DEFAULT_HOST, DEFAULT_PORT } from "./config.js";
6
+ import { isRecord } from "./record.js";
7
+ export async function runInit(options) {
8
+ const log = options.log ?? console.log;
9
+ const host = options.host ?? DEFAULT_HOST;
10
+ const port = options.port ?? DEFAULT_PORT;
11
+ const benchKey = options.benchKey ?? "your-dashboard-bench-key";
12
+ const detected = await detectSdks(options.cwd);
13
+ if (detected.length === 0) {
14
+ log("No supported SDK dependency found in package.json.");
15
+ log("Supported packages: openai, @anthropic-ai/sdk.");
16
+ }
17
+ else {
18
+ log(`Detected SDKs: ${detected.join(", ")}`);
19
+ }
20
+ for (const sdk of detected) {
21
+ log("");
22
+ log(instructionForSdk(sdk, host, port, benchKey));
23
+ }
24
+ log("");
25
+ log(`Start the local dashboard: npx inferock-bench start --port ${port}`);
26
+ log(`Open http://${host}:${port}/, save your provider key locally, then copy your local bench key.`);
27
+ log(`Set your SDK apiKey to process.env.INFEROCK_BENCH_KEY ?? "${benchKey}".`);
28
+ log("Provider keys stay local in the dashboard config or provider-key environment variables.");
29
+ log("The proxy prints `first call measured ✓` after the first successful proxied call.");
30
+ if (!options.patchFile)
31
+ return { detected };
32
+ const patchTarget = resolve(options.cwd, options.patchFile);
33
+ if (!options.yes && !await confirmPatch(patchTarget))
34
+ return { detected };
35
+ const patched = await patchClientFile(patchTarget, detected, host, port);
36
+ log(patched
37
+ ? `Patched ${patchTarget}`
38
+ : `No known SDK constructor without baseURL found in ${patchTarget}`);
39
+ return { detected, ...(patched ? { patchedFile: patchTarget } : {}) };
40
+ }
41
+ export async function detectSdks(cwd) {
42
+ const packageJson = await readPackageJson(cwd);
43
+ const dependencies = packageJson ? dependencyNames(packageJson) : new Set();
44
+ const detected = [];
45
+ if (dependencies.has("openai"))
46
+ detected.push("openai");
47
+ if (dependencies.has("@anthropic-ai/sdk"))
48
+ detected.push("anthropic");
49
+ return detected;
50
+ }
51
+ function instructionForSdk(sdk, host, port, benchKey) {
52
+ if (sdk === "openai") {
53
+ return [
54
+ "OpenAI base-URL change:",
55
+ "const openai = new OpenAI({",
56
+ ` apiKey: process.env.INFEROCK_BENCH_KEY ?? "${benchKey}",`,
57
+ ` baseURL: "http://${host}:${port}/v1",`,
58
+ "});",
59
+ ].join("\n");
60
+ }
61
+ return [
62
+ "Anthropic base-URL change:",
63
+ "const anthropic = new Anthropic({",
64
+ ` apiKey: process.env.INFEROCK_BENCH_KEY ?? "${benchKey}",`,
65
+ ` baseURL: "http://${host}:${port}",`,
66
+ "});",
67
+ ].join("\n");
68
+ }
69
+ async function readPackageJson(cwd) {
70
+ try {
71
+ const raw = await readFile(join(cwd, "package.json"), "utf8");
72
+ const parsed = JSON.parse(raw);
73
+ return isRecord(parsed) ? parsed : undefined;
74
+ }
75
+ catch (error) {
76
+ if (isNodeError(error) && error.code === "ENOENT")
77
+ return undefined;
78
+ throw error;
79
+ }
80
+ }
81
+ function dependencyNames(packageJson) {
82
+ const names = new Set();
83
+ for (const field of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
84
+ const value = packageJson[field];
85
+ if (!isRecord(value))
86
+ continue;
87
+ for (const name of Object.keys(value))
88
+ names.add(name);
89
+ }
90
+ return names;
91
+ }
92
+ async function patchClientFile(filePath, detected, host, port) {
93
+ const raw = await readFile(filePath, "utf8");
94
+ let next = raw;
95
+ if (detected.includes("openai")) {
96
+ next = patchConstructorBaseUrl(next, "OpenAI", `http://${host}:${port}/v1`);
97
+ }
98
+ if (detected.includes("anthropic")) {
99
+ next = patchConstructorBaseUrl(next, "Anthropic", `http://${host}:${port}`);
100
+ }
101
+ if (next === raw)
102
+ return false;
103
+ await writeFile(filePath, next, "utf8");
104
+ return true;
105
+ }
106
+ function patchConstructorBaseUrl(source, constructorName, baseUrl) {
107
+ const marker = `new ${constructorName}({`;
108
+ const start = source.indexOf(marker);
109
+ if (start === -1)
110
+ return source;
111
+ const preview = source.slice(start, start + 500);
112
+ if (/\bbaseURL\s*:/.test(preview))
113
+ return source;
114
+ const insertAt = start + marker.length;
115
+ return `${source.slice(0, insertAt)}\n baseURL: "${baseUrl}",${source.slice(insertAt)}`;
116
+ }
117
+ async function confirmPatch(filePath) {
118
+ const rl = createInterface({ input, output });
119
+ try {
120
+ const answer = await rl.question(`Patch ${filePath}? Type APPLY to continue: `);
121
+ return answer.trim() === "APPLY";
122
+ }
123
+ finally {
124
+ rl.close();
125
+ }
126
+ }
127
+ function isNodeError(error) {
128
+ return error instanceof Error && "code" in error;
129
+ }
130
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ // Copied from apps/proxy/src/provider.ts for inferock-bench Track C.
2
+ // Reuse approved by .claude/plans/oss-wave-2026-07.md "Track C Reuse Boundary".
3
+ export function isProviderName(value) {
4
+ return value === "openai" || value === "anthropic";
5
+ }
6
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,gFAAgF;AAMhF,MAAM,UAAU,cAAc,CAAC,KAAyB;IACtD,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,WAAW,CAAC;AACrD,CAAC"}
package/dist/proxy.js ADDED
@@ -0,0 +1,338 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { Hono } from "hono";
3
+ import { anthropicAdapter, ANTHROPIC_VERSION } from "./adapters/anthropic.js";
4
+ import { openAiAdapter } from "./adapters/openai.js";
5
+ import { acceptedBenchKeysFromConfig, applyProviderKeyUpdate, providerApiKey, providerBaseUrl, } from "./config.js";
6
+ import { receiptPayload, recentCallsFromRecords, renderDashboardHtml, summaryPayload, } from "./dashboard.js";
7
+ import { isProviderName } from "./provider.js";
8
+ import { isRecord, joinUrl, parseJsonRecord, stringValue, } from "./record.js";
9
+ import { createStoredBenchEvent } from "./storage.js";
10
+ import { renderLiveCounter, summarizeBenchEvents } from "./summary.js";
11
+ export function createBenchApp(options) {
12
+ const app = new Hono();
13
+ const state = { firstSuccessfulCallMeasured: false };
14
+ let activeConfig = options.config;
15
+ app.get("/", () => new Response(renderDashboardHtml(), {
16
+ headers: { "content-type": "text/html; charset=utf-8" },
17
+ }));
18
+ app.get("/health", (c) => c.json({ ok: true, service: "inferock-bench" }));
19
+ app.get("/api/summary", async (c) => {
20
+ const records = await options.store.readAll();
21
+ return c.json(summaryPayload({
22
+ records,
23
+ config: activeConfig,
24
+ env: options.env,
25
+ paths: options.paths,
26
+ }));
27
+ });
28
+ app.get("/api/rows", async (c) => {
29
+ const summary = summarizeBenchEvents(await options.store.readAll());
30
+ return c.json({ rows: summary.rows });
31
+ });
32
+ app.get("/api/calls", async (c) => {
33
+ const limit = callLimit(c.req.query("limit"));
34
+ return c.json({
35
+ limit,
36
+ calls: recentCallsFromRecords(await options.store.readAll(), limit),
37
+ });
38
+ });
39
+ app.get("/api/receipt", async (c) => c.json(receiptPayload(await options.store.readAll())));
40
+ app.post("/api/setup", async (c) => {
41
+ if (!options.paths) {
42
+ return localJsonError(503, "setup_unavailable", "Local setup persistence is unavailable.");
43
+ }
44
+ const body = parseJsonRecord(await c.req.text());
45
+ if (!body) {
46
+ return localJsonError(400, "invalid_json", "Request body must be a JSON object.");
47
+ }
48
+ const update = providerKeyUpdateFromBody(body);
49
+ if (!update) {
50
+ return localJsonError(400, "invalid_setup_payload", "Provider keys must be strings, null, or omitted.");
51
+ }
52
+ activeConfig = await applyProviderKeyUpdate({
53
+ paths: options.paths,
54
+ config: activeConfig,
55
+ update,
56
+ });
57
+ const records = await options.store.readAll();
58
+ return c.json(summaryPayload({
59
+ records,
60
+ config: activeConfig,
61
+ env: options.env,
62
+ paths: options.paths,
63
+ }));
64
+ });
65
+ app.post("/v1/chat/completions", (c) => handleProviderRoute(c, {
66
+ provider: "openai",
67
+ adapter: openAiAdapter,
68
+ providerSurface: "openai_chat_completions",
69
+ }, { ...options, config: activeConfig }, state));
70
+ app.post("/v1/messages", (c) => handleProviderRoute(c, {
71
+ provider: "anthropic",
72
+ adapter: anthropicAdapter,
73
+ providerSurface: "anthropic_messages",
74
+ }, { ...options, config: activeConfig }, state));
75
+ return app;
76
+ }
77
+ async function handleProviderRoute(c, route, options, state) {
78
+ const env = options.env ?? process.env;
79
+ const log = options.log ?? console.log;
80
+ if (!isProviderName(route.provider)) {
81
+ return localJsonError(500, "invalid_provider", "Invalid local provider route.");
82
+ }
83
+ const benchKeys = acceptedBenchKeysFromConfig(options.config, env);
84
+ if (!validLocalBenchKey(c.req.raw.headers, benchKeys)) {
85
+ return localJsonError(401, "invalid_local_bench_key", invalidLocalBenchKeyMessage(options.paths?.configFile));
86
+ }
87
+ const providerKey = providerApiKey(route.provider, options.config, env);
88
+ if (!providerKey) {
89
+ return localJsonError(503, "missing_provider_key", missingProviderKeyMessage(route.provider));
90
+ }
91
+ const bodyText = await c.req.text();
92
+ const body = parseJsonRecord(bodyText);
93
+ if (!body) {
94
+ return localJsonError(400, "invalid_json", "Request body must be a JSON object.");
95
+ }
96
+ const startedAt = new Date();
97
+ const requestId = requestIdFromHeaders(c.req.raw.headers);
98
+ const requestModel = stringValue(body.model) ?? "unknown_model";
99
+ const baseUrl = providerBaseUrl(route.provider, options.config, env);
100
+ const providerRequest = providerFetchRequest(route, {
101
+ body,
102
+ bodyText,
103
+ providerKey,
104
+ baseUrl,
105
+ incomingHeaders: c.req.raw.headers,
106
+ });
107
+ const providerFetch = options.providerFetch ?? fetch;
108
+ let response;
109
+ try {
110
+ response = await providerFetch(providerRequest.url, providerRequest.init);
111
+ }
112
+ catch {
113
+ const endedAt = new Date();
114
+ const result = route.adapter.toCanonicalEvent({
115
+ tenantId: "local",
116
+ requestId,
117
+ requestModel,
118
+ requestBody: body,
119
+ expectCompletion: true,
120
+ route: route.providerSurface,
121
+ statusCode: 502,
122
+ requestHeaders: c.req.raw.headers,
123
+ headers: new Headers(),
124
+ responseBody: providerTransportErrorBody(route.provider),
125
+ startedAt,
126
+ endedAt,
127
+ attemptIndex: 0,
128
+ });
129
+ await captureMeasuredCall(result, options, state, responseIsSuccessful(result.event), log);
130
+ return localJsonError(502, "provider_transport_error", "Provider request failed before a response was received.");
131
+ }
132
+ const responseHeaders = passThroughHeaders(response.headers);
133
+ if (shouldPassThroughStream(body, response)) {
134
+ if (!response.body) {
135
+ return localJsonError(502, "provider_stream_missing", "Provider stream response had no body.");
136
+ }
137
+ const streamInput = {
138
+ tenantId: "local",
139
+ requestId,
140
+ requestModel,
141
+ requestBody: body,
142
+ expectCompletion: true,
143
+ route: route.providerSurface,
144
+ statusCode: response.status,
145
+ requestHeaders: c.req.raw.headers,
146
+ headers: response.headers,
147
+ body: response.body,
148
+ startedAt,
149
+ attemptIndex: 0,
150
+ onTerminal: (result) => {
151
+ void captureMeasuredCall(result, options, state, response.status < 400, log)
152
+ .catch((error) => log(captureErrorMessage(error)));
153
+ },
154
+ };
155
+ return new Response(route.adapter.observeStream(streamInput), {
156
+ status: response.status,
157
+ headers: responseHeaders,
158
+ });
159
+ }
160
+ const responseBody = await response.text();
161
+ const endedAt = new Date();
162
+ const canonicalInput = {
163
+ tenantId: "local",
164
+ requestId,
165
+ requestModel,
166
+ requestBody: body,
167
+ expectCompletion: true,
168
+ route: route.providerSurface,
169
+ statusCode: response.status,
170
+ requestHeaders: c.req.raw.headers,
171
+ headers: response.headers,
172
+ responseBody,
173
+ startedAt,
174
+ endedAt,
175
+ attemptIndex: 0,
176
+ };
177
+ const result = route.adapter.toCanonicalEvent(canonicalInput);
178
+ await captureMeasuredCall(result, options, state, response.status < 400, log);
179
+ return new Response(responseBody, {
180
+ status: response.status,
181
+ headers: responseHeaders,
182
+ });
183
+ }
184
+ function providerFetchRequest(input, request) {
185
+ if (input.provider === "openai") {
186
+ const adapterRequest = input.adapter.buildRequest({
187
+ body: request.body,
188
+ apiKey: request.providerKey,
189
+ baseUrl: request.baseUrl,
190
+ });
191
+ const headers = new Headers(adapterRequest.init.headers);
192
+ copyOptionalHeader(request.incomingHeaders, headers, "openai-organization");
193
+ copyOptionalHeader(request.incomingHeaders, headers, "openai-project");
194
+ return {
195
+ url: adapterRequest.url,
196
+ init: {
197
+ ...adapterRequest.init,
198
+ headers,
199
+ },
200
+ };
201
+ }
202
+ const headers = new Headers({
203
+ "anthropic-version": request.incomingHeaders.get("anthropic-version") ?? ANTHROPIC_VERSION,
204
+ "content-type": "application/json",
205
+ "x-api-key": request.providerKey,
206
+ });
207
+ copyOptionalHeader(request.incomingHeaders, headers, "anthropic-beta");
208
+ return {
209
+ url: joinUrl(request.baseUrl, "/messages"),
210
+ init: {
211
+ method: "POST",
212
+ headers,
213
+ body: request.bodyText,
214
+ },
215
+ };
216
+ }
217
+ async function captureMeasuredCall(result, options, state, successful, log) {
218
+ await options.store.append(createStoredBenchEvent(result.event));
219
+ if (successful && !state.firstSuccessfulCallMeasured) {
220
+ state.firstSuccessfulCallMeasured = true;
221
+ log("first call measured ✓");
222
+ }
223
+ const summary = summarizeBenchEvents(await options.store.readAll());
224
+ log(renderLiveCounter(summary));
225
+ }
226
+ function validLocalBenchKey(headers, expected) {
227
+ if (expected.length === 0)
228
+ return false;
229
+ const authorization = headers.get("authorization");
230
+ const bearer = authorization?.match(/^Bearer\s+(.+)$/i)?.[1];
231
+ const key = bearer ?? headers.get("x-api-key");
232
+ return key ? expected.includes(key) : false;
233
+ }
234
+ function callLimit(value) {
235
+ if (!value)
236
+ return 12;
237
+ const parsed = Number(value);
238
+ if (!Number.isInteger(parsed))
239
+ return 12;
240
+ return Math.min(100, Math.max(1, parsed));
241
+ }
242
+ function providerKeyUpdateFromBody(body) {
243
+ const update = {};
244
+ if ("openaiApiKey" in body) {
245
+ if (!validProviderKeyUpdate(body.openaiApiKey))
246
+ return undefined;
247
+ update.openaiApiKey = body.openaiApiKey;
248
+ }
249
+ if ("anthropicApiKey" in body) {
250
+ if (!validProviderKeyUpdate(body.anthropicApiKey))
251
+ return undefined;
252
+ update.anthropicApiKey = body.anthropicApiKey;
253
+ }
254
+ return update;
255
+ }
256
+ function validProviderKeyUpdate(value) {
257
+ return typeof value === "string" || value === null;
258
+ }
259
+ function invalidLocalBenchKeyMessage(configFile) {
260
+ return configFile
261
+ ? `Invalid local inferock-bench key. Open the dashboard or find the key in ${configFile}.`
262
+ : "Invalid local inferock-bench key. Open the dashboard or check ~/.inferock-bench/config for the key.";
263
+ }
264
+ function requestIdFromHeaders(headers) {
265
+ return headers.get("x-inferock-request-id") ??
266
+ headers.get("x-request-id") ??
267
+ randomUUID();
268
+ }
269
+ function shouldPassThroughStream(body, response) {
270
+ return body.stream === true &&
271
+ response.body !== null &&
272
+ (response.headers.get("content-type") ?? "").toLowerCase().includes("text/event-stream");
273
+ }
274
+ function responseIsSuccessful(event) {
275
+ if (!isRecord(event) || !isRecord(event.response))
276
+ return false;
277
+ const statusCode = event.response.statusCode;
278
+ return typeof statusCode === "number" && statusCode < 400;
279
+ }
280
+ function localJsonError(status, code, message) {
281
+ return new Response(JSON.stringify({ error: { type: code, message } }), {
282
+ status,
283
+ headers: { "content-type": "application/json" },
284
+ });
285
+ }
286
+ function missingProviderKeyMessage(provider) {
287
+ if (provider === "openai") {
288
+ return "Missing OpenAI provider key. Set INFEROCK_BENCH_OPENAI_API_KEY or OPENAI_API_KEY locally.";
289
+ }
290
+ return "Missing Anthropic provider key. Set INFEROCK_BENCH_ANTHROPIC_API_KEY or ANTHROPIC_API_KEY locally.";
291
+ }
292
+ function providerTransportErrorBody(provider) {
293
+ if (provider === "openai") {
294
+ return JSON.stringify({
295
+ error: {
296
+ type: "transport_error",
297
+ message: "Provider request failed before a response was received.",
298
+ },
299
+ });
300
+ }
301
+ return JSON.stringify({
302
+ type: "error",
303
+ error: {
304
+ type: "transport_error",
305
+ message: "Provider request failed before a response was received.",
306
+ },
307
+ });
308
+ }
309
+ function passThroughHeaders(headers) {
310
+ const output = new Headers();
311
+ for (const [name, value] of headers.entries()) {
312
+ if (isHopByHopHeader(name))
313
+ continue;
314
+ output.set(name, value);
315
+ }
316
+ return output;
317
+ }
318
+ function isHopByHopHeader(name) {
319
+ const normalized = name.toLowerCase();
320
+ return normalized === "connection" ||
321
+ normalized === "content-encoding" ||
322
+ normalized === "content-length" ||
323
+ normalized === "keep-alive" ||
324
+ normalized === "set-cookie" ||
325
+ normalized === "transfer-encoding" ||
326
+ normalized === "upgrade";
327
+ }
328
+ function copyOptionalHeader(from, to, name) {
329
+ const value = from.get(name);
330
+ if (value)
331
+ to.set(name, value);
332
+ }
333
+ function captureErrorMessage(error) {
334
+ return error instanceof Error
335
+ ? `inferock-bench capture error: ${error.message}`
336
+ : "inferock-bench capture error";
337
+ }
338
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAQrD,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,EAItB,cAAc,EACd,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,mBAAmB,EACnB,cAAc,GACf,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,QAAQ,EACR,OAAO,EACP,eAAe,EACf,WAAW,GAEZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,sBAAsB,EAAmB,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAuBvE,MAAM,UAAU,cAAc,CAAC,OAA0B;IACvD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,KAAK,GAAe,EAAE,2BAA2B,EAAE,KAAK,EAAE,CAAC;IACjE,IAAI,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAElC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,QAAQ,CAAC,mBAAmB,EAAE,EAAE;QACrD,OAAO,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE;KACxD,CAAC,CAAC,CAAC;IACJ,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC;IAC3E,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAClC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAC9C,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC;YAC3B,OAAO;YACP,MAAM,EAAE,YAAY;YACpB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,CAAC,CAAC;IACN,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC/B,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACpE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAChC,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9C,OAAO,CAAC,CAAC,IAAI,CAAC;YACZ,KAAK;YACL,KAAK,EAAE,sBAAsB,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC;SACpE,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5F,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACjC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACnB,OAAO,cAAc,CAAC,GAAG,EAAE,mBAAmB,EAAE,yCAAyC,CAAC,CAAC;QAC7F,CAAC;QAED,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QACjD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,qCAAqC,CAAC,CAAC;QACpF,CAAC;QAED,MAAM,MAAM,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,cAAc,CACnB,GAAG,EACH,uBAAuB,EACvB,kDAAkD,CACnD,CAAC;QACJ,CAAC;QAED,YAAY,GAAG,MAAM,sBAAsB,CAAC;YAC1C,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,YAAY;YACpB,MAAM;SACP,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAC9C,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC;YAC3B,OAAO;YACP,MAAM,EAAE,YAAY;YACpB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,CAAC,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC,CAAC,EAAE,EAAE,CACrC,mBAAmB,CAAC,CAAC,EAAE;QACrB,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,aAAa;QACtB,eAAe,EAAE,yBAAyB;KAC3C,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IAEnD,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAC7B,mBAAmB,CAAC,CAAC,EAAE;QACrB,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,gBAAgB;QACzB,eAAe,EAAE,oBAAoB;KACtC,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IAEnD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,mBAAmB,CAChC,CAAU,EACV,KAAoB,EACpB,OAA0B,EAC1B,KAAiB;IAEjB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACvC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACvC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpC,OAAO,cAAc,CAAC,GAAG,EAAE,kBAAkB,EAAE,+BAA+B,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,SAAS,GAAG,2BAA2B,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnE,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;QACtD,OAAO,cAAc,CACnB,GAAG,EACH,yBAAyB,EACzB,2BAA2B,CAAC,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CACvD,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACxE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,cAAc,CACnB,GAAG,EACH,sBAAsB,EACtB,yBAAyB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAC1C,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IACpC,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,qCAAqC,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC1D,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,eAAe,CAAC;IAChE,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACrE,MAAM,eAAe,GAAG,oBAAoB,CAAC,KAAK,EAAE;QAClD,IAAI;QACJ,QAAQ;QACR,WAAW;QACX,OAAO;QACP,eAAe,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO;KACnC,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,KAAK,CAAC;IAErD,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,aAAa,CAAC,eAAe,CAAC,GAAG,EAAE,eAAe,CAAC,IAAI,CAAC,CAAC;IAC5E,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC5C,QAAQ,EAAE,OAAO;YACjB,SAAS;YACT,YAAY;YACZ,WAAW,EAAE,IAAI;YACjB,gBAAgB,EAAE,IAAI;YACtB,KAAK,EAAE,KAAK,CAAC,eAAe;YAC5B,UAAU,EAAE,GAAG;YACf,cAAc,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO;YACjC,OAAO,EAAE,IAAI,OAAO,EAAE;YACtB,YAAY,EAAE,0BAA0B,CAAC,KAAK,CAAC,QAAQ,CAAC;YACxD,SAAS;YACT,OAAO;YACP,YAAY,EAAE,CAAC;SAChB,CAAC,CAAC;QACH,MAAM,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,oBAAoB,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;QAC3F,OAAO,cAAc,CAAC,GAAG,EAAE,0BAA0B,EAAE,yDAAyD,CAAC,CAAC;IACpH,CAAC;IAED,MAAM,eAAe,GAAG,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC7D,IAAI,uBAAuB,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,OAAO,cAAc,CAAC,GAAG,EAAE,yBAAyB,EAAE,uCAAuC,CAAC,CAAC;QACjG,CAAC;QAED,MAAM,WAAW,GAAuB;YACtC,QAAQ,EAAE,OAAO;YACjB,SAAS;YACT,YAAY;YACZ,WAAW,EAAE,IAAI;YACjB,gBAAgB,EAAE,IAAI;YACtB,KAAK,EAAE,KAAK,CAAC,eAAe;YAC5B,UAAU,EAAE,QAAQ,CAAC,MAAM;YAC3B,cAAc,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO;YACjC,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,SAAS;YACT,YAAY,EAAE,CAAC;YACf,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE;gBACrB,KAAK,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,GAAG,CAAC;qBACzE,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAChE,CAAC;SACF,CAAC;QACF,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,EAAE;YAC5D,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,OAAO,EAAE,eAAe;SACzB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC;IAC3B,MAAM,cAAc,GAA0B;QAC5C,QAAQ,EAAE,OAAO;QACjB,SAAS;QACT,YAAY;QACZ,WAAW,EAAE,IAAI;QACjB,gBAAgB,EAAE,IAAI;QACtB,KAAK,EAAE,KAAK,CAAC,eAAe;QAC5B,UAAU,EAAE,QAAQ,CAAC,MAAM;QAC3B,cAAc,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO;QACjC,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,YAAY;QACZ,SAAS;QACT,OAAO;QACP,YAAY,EAAE,CAAC;KAChB,CAAC;IACF,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC9D,MAAM,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC;IAC9E,OAAO,IAAI,QAAQ,CAAC,YAAY,EAAE;QAChC,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,OAAO,EAAE,eAAe;KACzB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAoB,EAAE,OAMnD;IACC,IAAI,KAAK,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC;YAChD,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM,EAAE,OAAO,CAAC,WAAW;YAC3B,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzD,kBAAkB,CAAC,OAAO,CAAC,eAAe,EAAE,OAAO,EAAE,qBAAqB,CAAC,CAAC;QAC5E,kBAAkB,CAAC,OAAO,CAAC,eAAe,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC;QACvE,OAAO;YACL,GAAG,EAAE,cAAc,CAAC,GAAG;YACvB,IAAI,EAAE;gBACJ,GAAG,cAAc,CAAC,IAAI;gBACtB,OAAO;aACR;SACF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC;QAC1B,mBAAmB,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,iBAAiB;QAC1F,cAAc,EAAE,kBAAkB;QAClC,WAAW,EAAE,OAAO,CAAC,WAAW;KACjC,CAAC,CAAC;IACH,kBAAkB,CAAC,OAAO,CAAC,eAAe,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC;IACvE,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC;QAC1C,IAAI,EAAE;YACJ,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,OAAO,CAAC,QAAQ;SACvB;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,mBAAmB,CAChC,MAA8B,EAC9B,OAA0B,EAC1B,KAAiB,EACjB,UAAmB,EACnB,GAA2B;IAE3B,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,IAAI,UAAU,IAAI,CAAC,KAAK,CAAC,2BAA2B,EAAE,CAAC;QACrD,KAAK,CAAC,2BAA2B,GAAG,IAAI,CAAC;QACzC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IAC/B,CAAC;IACD,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACpE,GAAG,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAgB,EAAE,QAA2B;IACvE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,aAAa,EAAE,KAAK,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC/C,OAAO,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC9C,CAAC;AAED,SAAS,SAAS,CAAC,KAAyB;IAC1C,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IACzC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,yBAAyB,CAAC,IAAgB;IACjD,MAAM,MAAM,GAGR,EAAE,CAAC;IAEP,IAAI,cAAc,IAAI,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,YAAY,CAAC;YAAE,OAAO,SAAS,CAAC;QACjE,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;IAC1C,CAAC;IAED,IAAI,iBAAiB,IAAI,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,eAAe,CAAC;YAAE,OAAO,SAAS,CAAC;QACpE,MAAM,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC;IAChD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAc;IAC5C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,SAAS,2BAA2B,CAAC,UAA8B;IACjE,OAAO,UAAU;QACf,CAAC,CAAC,2EAA2E,UAAU,GAAG;QAC1F,CAAC,CAAC,qGAAqG,CAAC;AAC5G,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAgB;IAC5C,OAAO,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAC3B,UAAU,EAAE,CAAC;AACjB,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAgB,EAAE,QAAkB;IACnE,OAAO,IAAI,CAAC,MAAM,KAAK,IAAI;QACzB,QAAQ,CAAC,IAAI,KAAK,IAAI;QACtB,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;AAC7F,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAwB;IACpD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IAChE,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC;IAC7C,OAAO,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,GAAG,GAAG,CAAC;AAC5D,CAAC;AAED,SAAS,cAAc,CAAC,MAAc,EAAE,IAAY,EAAE,OAAe;IACnE,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE;QACtE,MAAM;QACN,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;KAChD,CAAC,CAAC;AACL,CAAC;AAED,SAAS,yBAAyB,CAAC,QAAsB;IACvD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,2FAA2F,CAAC;IACrG,CAAC;IACD,OAAO,oGAAoG,CAAC;AAC9G,CAAC;AAED,SAAS,0BAA0B,CAAC,QAAsB;IACxD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,SAAS,CAAC;YACpB,KAAK,EAAE;gBACL,IAAI,EAAE,iBAAiB;gBACvB,OAAO,EAAE,yDAAyD;aACnE;SACF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,IAAI,EAAE,OAAO;QACb,KAAK,EAAE;YACL,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,yDAAyD;SACnE;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAgB;IAC1C,MAAM,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;QAC9C,IAAI,gBAAgB,CAAC,IAAI,CAAC;YAAE,SAAS;QACrC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY;IACpC,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACtC,OAAO,UAAU,KAAK,YAAY;QAChC,UAAU,KAAK,kBAAkB;QACjC,UAAU,KAAK,gBAAgB;QAC/B,UAAU,KAAK,YAAY;QAC3B,UAAU,KAAK,YAAY;QAC3B,UAAU,KAAK,mBAAmB;QAClC,UAAU,KAAK,SAAS,CAAC;AAC7B,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAa,EAAE,EAAW,EAAE,IAAY;IAClE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,KAAK;QAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAc;IACzC,OAAO,KAAK,YAAY,KAAK;QAC3B,CAAC,CAAC,iCAAiC,KAAK,CAAC,OAAO,EAAE;QAClD,CAAC,CAAC,8BAA8B,CAAC;AACrC,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { WATERMARK_NAME, WATERMARK_URL } from "./config.js";
4
+ import { formatUsd } from "./summary.js";
5
+ export function createReceiptBundle(summary) {
6
+ return {
7
+ schemaVersion: "inferock-bench-receipt-v1",
8
+ title: `my AI provider cost me ${formatUsd(summary.totalLostUsd)} in failures this period`,
9
+ generatedAt: new Date().toISOString(),
10
+ period: summary.period,
11
+ totals: {
12
+ measuredCalls: summary.measuredCalls,
13
+ failures: summary.failureCount,
14
+ totalLostUsd: summary.totalLostUsd,
15
+ providerRecognizedUsd: summary.providerRecognizedUsd,
16
+ unrecognizedUsd: summary.unrecognizedUsd,
17
+ },
18
+ rows: summary.rows,
19
+ watermark: {
20
+ name: WATERMARK_NAME,
21
+ url: WATERMARK_URL,
22
+ },
23
+ };
24
+ }
25
+ export function renderReceipt(bundle, compact) {
26
+ const lines = [
27
+ formatUsd(bundle.totals.totalLostUsd),
28
+ bundle.title,
29
+ `period: ${bundle.period.since ?? "beginning"} to ${bundle.period.until}`,
30
+ `measured ${bundle.totals.measuredCalls} calls, ${bundle.totals.failures} failures`,
31
+ `provider-recognized ${formatUsd(bundle.totals.providerRecognizedUsd)} | unrecognized ${formatUsd(bundle.totals.unrecognizedUsd)}`,
32
+ ];
33
+ const rows = compact ? bundle.rows.slice(0, 6) : bundle.rows;
34
+ if (rows.length === 0) {
35
+ lines.push("no loss rows");
36
+ }
37
+ else {
38
+ lines.push("class | evidence | count | provider-recognized | unrecognized");
39
+ for (const row of rows) {
40
+ lines.push([
41
+ `${row.code}/${row.failureClass}`,
42
+ row.evidenceGrade,
43
+ String(row.count),
44
+ formatUsd(row.providerRecognizedUsd),
45
+ formatUsd(row.unrecognizedUsd),
46
+ ].join(" | "));
47
+ }
48
+ }
49
+ lines.push(`${bundle.watermark.name} - ${bundle.watermark.url}`);
50
+ return lines.join("\n");
51
+ }
52
+ export async function writeReceiptBundle(receiptsDir, bundle) {
53
+ await mkdir(receiptsDir, { recursive: true });
54
+ const filename = `receipt-${bundle.generatedAt.replace(/[:.]/g, "-")}.json`;
55
+ const path = join(receiptsDir, filename);
56
+ await writeFile(path, `${JSON.stringify(bundle, null, 2)}\n`, "utf8");
57
+ return path;
58
+ }
59
+ //# sourceMappingURL=receipt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipt.js","sourceRoot":"","sources":["../src/receipt.ts"],"names":[],"mappings":"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"}
package/dist/record.js ADDED
@@ -0,0 +1,78 @@
1
+ // Copied from apps/proxy/src/record.ts for inferock-bench Track C.
2
+ // Reuse approved by .claude/plans/oss-wave-2026-07.md "Track C Reuse Boundary".
3
+ export function isRecord(value) {
4
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5
+ }
6
+ export function asRecord(value) {
7
+ return isRecord(value) ? value : undefined;
8
+ }
9
+ export function stringValue(value) {
10
+ return typeof value === "string" ? value : undefined;
11
+ }
12
+ export function numberValue(value) {
13
+ return typeof value === "number" && Number.isFinite(value) && value >= 0
14
+ ? value
15
+ : undefined;
16
+ }
17
+ export function booleanValue(value) {
18
+ return typeof value === "boolean" ? value : undefined;
19
+ }
20
+ export function recordArray(value) {
21
+ if (!Array.isArray(value))
22
+ return undefined;
23
+ const records = value.filter(isRecord);
24
+ return records.length === value.length ? records : undefined;
25
+ }
26
+ export function parseJsonRecord(text) {
27
+ try {
28
+ const parsed = JSON.parse(text);
29
+ return asRecord(parsed);
30
+ }
31
+ catch {
32
+ return undefined;
33
+ }
34
+ }
35
+ export function textFromContent(value) {
36
+ if (typeof value === "string")
37
+ return value;
38
+ if (!Array.isArray(value))
39
+ return "";
40
+ const chunks = [];
41
+ for (const item of value) {
42
+ if (!isRecord(item))
43
+ continue;
44
+ const text = stringValue(item.text);
45
+ if (text)
46
+ chunks.push(text);
47
+ }
48
+ return chunks.join("");
49
+ }
50
+ export function compactRecord(input) {
51
+ const output = {};
52
+ for (const [key, value] of Object.entries(input)) {
53
+ if (value !== undefined)
54
+ output[key] = value;
55
+ }
56
+ return output;
57
+ }
58
+ export function collectRateLimitHeaders(headers) {
59
+ const captured = {};
60
+ for (const [name, value] of headers.entries()) {
61
+ const normalized = name.toLowerCase();
62
+ if (normalized === "retry-after" ||
63
+ normalized === "retry-after-ms" ||
64
+ normalized === "openai-processing-ms" ||
65
+ normalized === "x-should-retry" ||
66
+ normalized === "x-request-id" ||
67
+ normalized === "request-id" ||
68
+ normalized.startsWith("x-ratelimit-") ||
69
+ normalized.startsWith("anthropic-ratelimit-")) {
70
+ captured[normalized] = value;
71
+ }
72
+ }
73
+ return captured;
74
+ }
75
+ export function joinUrl(baseUrl, path) {
76
+ return baseUrl.replace(/\/+$/, "") + "/" + path.replace(/^\/+/, "");
77
+ }
78
+ //# sourceMappingURL=record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record.js","sourceRoot":"","sources":["../src/record.ts"],"names":[],"mappings":"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"}