@qverisai/mcp 0.7.5 → 0.9.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +145 -0
  2. package/README.md +297 -236
  3. package/dist/api/client.d.ts +9 -0
  4. package/dist/api/client.d.ts.map +1 -1
  5. package/dist/api/client.js +113 -76
  6. package/dist/api/client.js.map +1 -1
  7. package/dist/http.d.ts +99 -0
  8. package/dist/http.d.ts.map +1 -0
  9. package/dist/http.js +564 -0
  10. package/dist/http.js.map +1 -0
  11. package/dist/index.d.ts +107 -3
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +176 -60
  14. package/dist/index.js.map +1 -1
  15. package/dist/output-schemas.d.ts +12 -0
  16. package/dist/output-schemas.d.ts.map +1 -0
  17. package/dist/output-schemas.js +61 -0
  18. package/dist/output-schemas.js.map +1 -0
  19. package/dist/retry.d.ts +42 -0
  20. package/dist/retry.d.ts.map +1 -0
  21. package/dist/retry.js +69 -0
  22. package/dist/retry.js.map +1 -0
  23. package/dist/server-card.d.ts +85 -0
  24. package/dist/server-card.d.ts.map +1 -0
  25. package/dist/server-card.js +87 -0
  26. package/dist/server-card.js.map +1 -0
  27. package/dist/tools/audit-utils.d.ts.map +1 -1
  28. package/dist/tools/audit-utils.js +11 -16
  29. package/dist/tools/audit-utils.js.map +1 -1
  30. package/dist/tools/credits-ledger.d.ts +1 -2
  31. package/dist/tools/credits-ledger.d.ts.map +1 -1
  32. package/dist/tools/credits-ledger.js.map +1 -1
  33. package/dist/tools/execute.d.ts.map +1 -1
  34. package/dist/tools/execute.js.map +1 -1
  35. package/dist/tools/get-by-ids.d.ts.map +1 -1
  36. package/dist/tools/get-by-ids.js +1 -2
  37. package/dist/tools/get-by-ids.js.map +1 -1
  38. package/dist/tools/usage-history.d.ts +1 -2
  39. package/dist/tools/usage-history.d.ts.map +1 -1
  40. package/dist/tools/usage-history.js.map +1 -1
  41. package/dist/types.d.ts +6 -0
  42. package/dist/types.d.ts.map +1 -1
  43. package/package.json +70 -59
package/dist/http.js ADDED
@@ -0,0 +1,564 @@
1
+ /**
2
+ * Streamable HTTP transport for the Qveris MCP server.
3
+ *
4
+ * Adds a remote transport mode (MCP Streamable HTTP) alongside the default
5
+ * stdio transport, so the same server can run locally over stdio or be deployed
6
+ * behind HTTP for Claude Desktop Custom Connectors and other remote MCP clients.
7
+ *
8
+ * The transport is stateful: each client session gets its own
9
+ * {@link StreamableHTTPServerTransport} (and its own Qveris {@link Server}),
10
+ * keyed by the `Mcp-Session-Id` header the SDK assigns on `initialize`.
11
+ *
12
+ * Embedders may require a bearer per session and receive it only in the
13
+ * asynchronous server factory. The transport binds an irreversible credential
14
+ * fingerprint to the MCP session so later requests cannot switch identities.
15
+ * Validation and client construction remain the embedding service's policy.
16
+ *
17
+ * @module @qverisai/mcp/http
18
+ */
19
+ import { createHash, randomUUID, timingSafeEqual } from 'node:crypto';
20
+ import { createServer } from 'node:http';
21
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
22
+ import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
23
+ import { buildCatalog, buildServerCard, CATALOG_PATH, SERVER_CARD_MEDIA_TYPE, } from './server-card.js';
24
+ /** The embedding service rejected the credential supplied for a new session. */
25
+ export class SessionAuthenticationError extends Error {
26
+ name = 'SessionAuthenticationError';
27
+ }
28
+ /** The embedding service could not validate a supplied credential safely. */
29
+ export class SessionAuthenticationUnavailableError extends Error {
30
+ name = 'SessionAuthenticationUnavailableError';
31
+ }
32
+ /** The embedding service rate-limited creation of a new authenticated session. */
33
+ export class SessionRateLimitError extends Error {
34
+ name = 'SessionRateLimitError';
35
+ retryAfterSeconds;
36
+ constructor(message, retryAfterSeconds = 60) {
37
+ super(message);
38
+ this.retryAfterSeconds =
39
+ Number.isFinite(retryAfterSeconds) && retryAfterSeconds > 0 ? Math.min(86_400, Math.ceil(retryAfterSeconds)) : 60;
40
+ }
41
+ }
42
+ const DEFAULT_PORT = 3000;
43
+ const DEFAULT_HOST = '127.0.0.1';
44
+ const DEFAULT_PATH = '/mcp';
45
+ const DEFAULT_MAX_BODY_BYTES = 4 * 1024 * 1024; // 4 MiB
46
+ const DEFAULT_SESSION_TIMEOUT_MS = 5 * 60 * 1000; // 5 min
47
+ const SWEEP_INTERVAL_MS = 60 * 1000; // idle-session sweep cadence
48
+ const MAX_PORT = 65535;
49
+ class BodyTooLargeError extends Error {
50
+ }
51
+ class JsonParseError extends Error {
52
+ }
53
+ function parseList(value) {
54
+ if (!value)
55
+ return [];
56
+ return value
57
+ .split(',')
58
+ .map((item) => item.trim())
59
+ .filter((item) => item.length > 0);
60
+ }
61
+ function parseBool(value, fallback) {
62
+ if (value === undefined)
63
+ return fallback;
64
+ const normalized = value.trim().toLowerCase();
65
+ if (['1', 'true', 'yes', 'on'].includes(normalized))
66
+ return true;
67
+ if (['0', 'false', 'no', 'off'].includes(normalized))
68
+ return false;
69
+ return fallback;
70
+ }
71
+ function parsePositiveInt(value, fallback) {
72
+ if (value === undefined)
73
+ return fallback;
74
+ const parsed = Number(value);
75
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
76
+ }
77
+ function readFlag(argv, name) {
78
+ // Supports `--name value` and `--name=value`.
79
+ for (let i = 0; i < argv.length; i++) {
80
+ const arg = argv[i];
81
+ if (arg === name) {
82
+ const next = argv[i + 1];
83
+ return next && !next.startsWith('--') ? next : '';
84
+ }
85
+ if (arg.startsWith(`${name}=`)) {
86
+ return arg.slice(name.length + 1);
87
+ }
88
+ }
89
+ return undefined;
90
+ }
91
+ function hasFlag(argv, name) {
92
+ return argv.some((arg) => arg === name || arg.startsWith(`${name}=`));
93
+ }
94
+ // Matches the whole IPv4 loopback range 127.0.0.0/8 (and only that) — a precise
95
+ // address check, not a `startsWith('127.')` prefix that would also accept a
96
+ // hostname like `127.example.com`.
97
+ const IPV4_LOOPBACK = /^127(?:\.(?:0|[1-9]\d?|1\d\d|2[0-4]\d|25[0-5])){3}$/;
98
+ function isLoopbackHost(host) {
99
+ const h = host
100
+ .trim()
101
+ .toLowerCase()
102
+ .replace(/^\[|\]$/g, ''); // strip IPv6 brackets
103
+ return h === 'localhost' || h === '::1' || IPV4_LOOPBACK.test(h);
104
+ }
105
+ /**
106
+ * Resolve the transport configuration from environment and CLI flags.
107
+ *
108
+ * HTTP mode is selected when `--http` is passed, `QVERIS_MCP_TRANSPORT=http`,
109
+ * or an HTTP port/host is explicitly set; otherwise the transport stays stdio
110
+ * so existing local configs are unaffected.
111
+ */
112
+ export function resolveTransportConfig(env, argv = []) {
113
+ const portFlag = readFlag(argv, '--port');
114
+ const hostFlag = readFlag(argv, '--host');
115
+ const pathFlag = readFlag(argv, '--path');
116
+ const envPort = env.QVERIS_MCP_HTTP_PORT;
117
+ const envHost = env.QVERIS_MCP_HTTP_HOST;
118
+ const envTransport = env.QVERIS_MCP_TRANSPORT?.trim().toLowerCase();
119
+ const httpRequested = hasFlag(argv, '--http') ||
120
+ envTransport === 'http' ||
121
+ portFlag !== undefined ||
122
+ envPort !== undefined ||
123
+ hostFlag !== undefined ||
124
+ envHost !== undefined;
125
+ const mode = envTransport === 'stdio' ? 'stdio' : httpRequested ? 'http' : 'stdio';
126
+ const rawPort = portFlag || envPort;
127
+ const parsedPort = Number(rawPort);
128
+ const port = rawPort !== undefined &&
129
+ rawPort.trim() !== '' && // e.g. a bare `--port` -> '' -> Number('') === 0; fall back instead
130
+ Number.isInteger(parsedPort) &&
131
+ parsedPort >= 0 &&
132
+ parsedPort <= MAX_PORT
133
+ ? parsedPort
134
+ : DEFAULT_PORT;
135
+ return {
136
+ mode,
137
+ host: hostFlag || envHost || DEFAULT_HOST,
138
+ port,
139
+ path: pathFlag || env.QVERIS_MCP_HTTP_PATH || DEFAULT_PATH,
140
+ allowedHosts: parseList(env.QVERIS_MCP_ALLOWED_HOSTS),
141
+ allowedOrigins: parseList(env.QVERIS_MCP_ALLOWED_ORIGINS),
142
+ enableDnsRebindingProtection: parseBool(env.QVERIS_MCP_DNS_REBINDING_PROTECTION, true),
143
+ enableJsonResponse: parseBool(env.QVERIS_MCP_HTTP_JSON, false),
144
+ authToken: env.QVERIS_MCP_HTTP_AUTH_TOKEN?.trim() || undefined,
145
+ requireSessionBearer: false,
146
+ allowUnauthenticated: parseBool(env.QVERIS_MCP_HTTP_ALLOW_UNAUTHENTICATED, false),
147
+ maxBodyBytes: parsePositiveInt(env.QVERIS_MCP_MAX_BODY_BYTES, DEFAULT_MAX_BODY_BYTES),
148
+ sessionTimeoutMs: parsePositiveInt(env.QVERIS_MCP_SESSION_TIMEOUT_MS, DEFAULT_SESSION_TIMEOUT_MS),
149
+ publicUrl: env.QVERIS_MCP_PUBLIC_URL?.trim().replace(/\/+$/, '') || undefined,
150
+ };
151
+ }
152
+ /** Absolute origin for discovery URLs: the configured public origin, or derived
153
+ * from the request (honoring an `X-Forwarded-Proto` from a TLS-terminating proxy). */
154
+ function requestOrigin(req, publicUrl) {
155
+ if (publicUrl)
156
+ return publicUrl;
157
+ const forwarded = req.headers['x-forwarded-proto'];
158
+ const proto = (typeof forwarded === 'string' ? forwarded.split(',')[0].trim() : undefined) || 'http';
159
+ const host = req.headers.host ?? 'localhost';
160
+ return `${proto}://${host}`;
161
+ }
162
+ /** Read and JSON-parse a request body with a hard size cap. */
163
+ async function readJsonBody(req, maxBytes) {
164
+ const chunks = [];
165
+ let total = 0;
166
+ for await (const chunk of req) {
167
+ const buf = chunk;
168
+ total += buf.length;
169
+ if (total > maxBytes) {
170
+ throw new BodyTooLargeError(`Request body exceeds ${maxBytes} bytes`);
171
+ }
172
+ chunks.push(buf);
173
+ }
174
+ if (chunks.length === 0)
175
+ return undefined;
176
+ const raw = Buffer.concat(chunks).toString('utf8');
177
+ if (raw.trim().length === 0)
178
+ return undefined;
179
+ try {
180
+ return JSON.parse(raw);
181
+ }
182
+ catch (err) {
183
+ throw new JsonParseError(err instanceof Error ? err.message : 'Invalid JSON');
184
+ }
185
+ }
186
+ function writeJson(res, status, body, headers = {}) {
187
+ const payload = JSON.stringify(body);
188
+ res.writeHead(status, { 'Content-Type': 'application/json', ...headers });
189
+ res.end(payload);
190
+ }
191
+ function jsonRpcError(id, code, message) {
192
+ return { jsonrpc: '2.0', error: { code, message }, id: id ?? null };
193
+ }
194
+ /** Constant-time bearer check against the configured token. */
195
+ function bearerMatches(authHeader, token) {
196
+ const provided = readBearerToken(authHeader);
197
+ if (!provided)
198
+ return false;
199
+ // Compare fixed-length SHA-256 digests so the comparison is constant-time
200
+ // *and* doesn't leak the expected token's length via an early length check.
201
+ const providedHash = createHash('sha256').update(provided).digest();
202
+ const expectedHash = createHash('sha256').update(token).digest();
203
+ return timingSafeEqual(providedHash, expectedHash);
204
+ }
205
+ function readBearerToken(authHeader) {
206
+ if (!authHeader)
207
+ return undefined;
208
+ const match = /^Bearer\s+(.+)$/i.exec(authHeader);
209
+ const token = match?.[1]?.trim();
210
+ return token || undefined;
211
+ }
212
+ function credentialFingerprint(token) {
213
+ return createHash('sha256').update(token).digest();
214
+ }
215
+ function credentialMatches(fingerprint, token) {
216
+ if (!fingerprint || !token)
217
+ return false;
218
+ return timingSafeEqual(fingerprint, credentialFingerprint(token));
219
+ }
220
+ /**
221
+ * Start the Streamable HTTP server.
222
+ *
223
+ * @param config - Resolved HTTP transport settings.
224
+ * @param makeServer - Factory that builds a fresh Qveris {@link Server} for a
225
+ * new client session. Called once per `initialize`.
226
+ * @param cardInfo - Metadata for the discovery documents (Server Card + Catalog).
227
+ * When omitted those endpoints are not served.
228
+ * @param logger - Where to write startup/lifecycle lines (defaults to stderr,
229
+ * keeping stdout clean).
230
+ * @throws if binding a non-loopback host without an auth token and without an
231
+ * explicit opt-out (fail-closed).
232
+ */
233
+ export async function startHttpServer(config, makeServer, cardInfo, logger = (message) => process.stderr.write(message)) {
234
+ const nonLoopback = !isLoopbackHost(config.host);
235
+ if (config.requireSessionBearer && config.authToken) {
236
+ throw new Error('Shared authToken cannot be combined with per-session bearer authentication.');
237
+ }
238
+ if (config.requireSessionBearer && config.allowUnauthenticated) {
239
+ throw new Error('allowUnauthenticated cannot be enabled with per-session bearer authentication.');
240
+ }
241
+ if (nonLoopback && !config.requireSessionBearer && !config.authToken && !config.allowUnauthenticated) {
242
+ throw new Error(`Refusing to start: HTTP transport is binding a non-loopback host (${config.host}) with no authentication. ` +
243
+ `Set QVERIS_MCP_HTTP_AUTH_TOKEN to require a bearer token, or set ` +
244
+ `QVERIS_MCP_HTTP_ALLOW_UNAUTHENTICATED=true if an external layer (proxy/gateway) authenticates requests.`);
245
+ }
246
+ if (nonLoopback && !config.requireSessionBearer && !config.authToken) {
247
+ logger('[qveris] WARNING: HTTP transport exposed on a non-loopback host without an auth token. ' +
248
+ 'Ensure an external auth layer protects the endpoint.\n');
249
+ }
250
+ // The reserved public paths are matched before the transport path; a custom
251
+ // QVERIS_MCP_HTTP_PATH set to one of them would shadow the MCP endpoint, so
252
+ // fail fast rather than start a silently-broken server (consistent with the
253
+ // fail-closed auth check above). The card path (config.path + '/server-card')
254
+ // can't equal config.path, so it isn't a collision candidate.
255
+ const reservedPaths = cardInfo ? ['/health', CATALOG_PATH] : ['/health'];
256
+ if (reservedPaths.includes(config.path)) {
257
+ throw new Error(`Refusing to start: QVERIS_MCP_HTTP_PATH="${config.path}" collides with a reserved ` +
258
+ `endpoint (${reservedPaths.join(', ')}) and would shadow the MCP transport; choose a different path.`);
259
+ }
260
+ const transports = new Map();
261
+ const sessionCredentialFingerprints = new Map();
262
+ const lastSeen = new Map();
263
+ const inflight = new Map(); // requests currently being handled per session
264
+ let boundPort = config.port;
265
+ // In-flight guards keep the idle sweep from evicting a session that has an
266
+ // active request or a live (long-lived) SSE stream. A session is only
267
+ // eligible for idle eviction once it has zero in-flight requests.
268
+ const retain = (sessionId) => {
269
+ inflight.set(sessionId, (inflight.get(sessionId) ?? 0) + 1);
270
+ };
271
+ const release = (sessionId) => {
272
+ const remaining = (inflight.get(sessionId) ?? 0) - 1;
273
+ if (remaining > 0)
274
+ inflight.set(sessionId, remaining);
275
+ else
276
+ inflight.delete(sessionId);
277
+ };
278
+ // The SDK matches the Host header (which includes the port) against
279
+ // allowedHosts. Build the effective list once the real port is known so DNS
280
+ // rebinding protection works even when config.port is 0 (ephemeral).
281
+ const effectiveAllowedHosts = () => {
282
+ const base = [`${config.host}:${boundPort}`, `localhost:${boundPort}`, `127.0.0.1:${boundPort}`];
283
+ return [...new Set([...base, ...config.allowedHosts])];
284
+ };
285
+ const evict = (sessionId) => {
286
+ lastSeen.delete(sessionId);
287
+ inflight.delete(sessionId);
288
+ sessionCredentialFingerprints.delete(sessionId);
289
+ if (transports.get(sessionId))
290
+ transports.delete(sessionId);
291
+ };
292
+ const createTransport = async (auth) => {
293
+ const fingerprint = auth.bearerToken ? credentialFingerprint(auth.bearerToken) : undefined;
294
+ const transport = new StreamableHTTPServerTransport({
295
+ sessionIdGenerator: () => randomUUID(),
296
+ enableJsonResponse: config.enableJsonResponse,
297
+ enableDnsRebindingProtection: config.enableDnsRebindingProtection,
298
+ allowedHosts: effectiveAllowedHosts(),
299
+ allowedOrigins: config.allowedOrigins,
300
+ onsessioninitialized: (sessionId) => {
301
+ transports.set(sessionId, transport);
302
+ if (fingerprint)
303
+ sessionCredentialFingerprints.set(sessionId, fingerprint);
304
+ lastSeen.set(sessionId, Date.now());
305
+ logger(`[qveris] MCP session initialized: ${sessionId}\n`);
306
+ },
307
+ });
308
+ transport.onclose = () => {
309
+ const sessionId = transport.sessionId;
310
+ if (sessionId && transports.get(sessionId) === transport) {
311
+ evict(sessionId);
312
+ logger(`[qveris] MCP session closed: ${sessionId}\n`);
313
+ }
314
+ };
315
+ let server;
316
+ try {
317
+ server = await makeServer(randomUUID(), auth);
318
+ await server.connect(transport);
319
+ return transport;
320
+ }
321
+ catch (error) {
322
+ await transport.close().catch(() => undefined);
323
+ if (server)
324
+ await server.close().catch(() => undefined);
325
+ throw error;
326
+ }
327
+ };
328
+ const handler = async (req, res) => {
329
+ try {
330
+ const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);
331
+ // Lightweight, unauthenticated health check for load balancers.
332
+ if (req.method === 'GET' && url.pathname === '/health') {
333
+ writeJson(res, 200, { status: 'ok', transport: 'streamable-http' });
334
+ return;
335
+ }
336
+ // Public, unauthenticated discovery documents (Server Card + Catalog).
337
+ // Like robots.txt / OAuth metadata, these are meant to be crawled without
338
+ // credentials, so they are handled before the auth check.
339
+ const cardPath = `${config.path}/server-card`;
340
+ if (cardInfo && (url.pathname === cardPath || url.pathname === CATALOG_PATH)) {
341
+ const cors = {
342
+ 'Access-Control-Allow-Origin': '*',
343
+ 'Access-Control-Allow-Methods': 'GET, OPTIONS',
344
+ 'Access-Control-Allow-Headers': 'Accept',
345
+ };
346
+ if (req.method === 'OPTIONS') {
347
+ req.resume();
348
+ res.writeHead(204, { ...cors, 'Access-Control-Max-Age': '86400' });
349
+ res.end();
350
+ return;
351
+ }
352
+ if (req.method === 'GET') {
353
+ const origin = requestOrigin(req, config.publicUrl);
354
+ // With a configured public origin the response is host-independent and
355
+ // freely cacheable. When the origin is derived from the request Host,
356
+ // don't let a shared cache serve it cross-host (cache-poisoning): mark
357
+ // it no-store and Vary on the headers it depends on.
358
+ const cache = config.publicUrl
359
+ ? { 'Cache-Control': 'public, max-age=3600' }
360
+ : { 'Cache-Control': 'no-store', Vary: 'Host, X-Forwarded-Proto' };
361
+ if (url.pathname === cardPath) {
362
+ const card = buildServerCard(cardInfo, `${origin}${config.path}`);
363
+ writeJson(res, 200, card, { ...cors, ...cache, 'Content-Type': SERVER_CARD_MEDIA_TYPE });
364
+ }
365
+ else {
366
+ const catalog = buildCatalog(cardInfo, `${origin}${cardPath}`);
367
+ writeJson(res, 200, catalog, { ...cors, ...cache });
368
+ }
369
+ return;
370
+ }
371
+ req.resume();
372
+ res.writeHead(405, { Allow: 'GET, OPTIONS' });
373
+ res.end();
374
+ return;
375
+ }
376
+ if (url.pathname !== config.path) {
377
+ req.resume(); // drain the body so the connection can be reused/closed
378
+ writeJson(res, 404, jsonRpcError(null, -32601, `Not found: ${url.pathname}`));
379
+ return;
380
+ }
381
+ // Inbound auth (when a token is configured) on the MCP endpoint.
382
+ if (config.authToken && !bearerMatches(req.headers['authorization'], config.authToken)) {
383
+ req.resume(); // drain the (unread) body before short-circuiting
384
+ writeJson(res, 401, jsonRpcError(null, -32001, 'Unauthorized'), {
385
+ 'WWW-Authenticate': 'Bearer',
386
+ });
387
+ return;
388
+ }
389
+ const sessionBearer = config.requireSessionBearer ? readBearerToken(req.headers['authorization']) : undefined;
390
+ if (config.requireSessionBearer && !sessionBearer) {
391
+ req.resume();
392
+ writeJson(res, 401, jsonRpcError(null, -32001, 'Bearer credential required'), {
393
+ 'WWW-Authenticate': 'Bearer',
394
+ });
395
+ return;
396
+ }
397
+ const sessionId = req.headers['mcp-session-id'];
398
+ const existing = typeof sessionId === 'string' ? transports.get(sessionId) : undefined;
399
+ if (config.requireSessionBearer &&
400
+ existing &&
401
+ typeof sessionId === 'string' &&
402
+ !credentialMatches(sessionCredentialFingerprints.get(sessionId), sessionBearer)) {
403
+ req.resume();
404
+ writeJson(res, 401, jsonRpcError(null, -32001, 'Session credential mismatch'), {
405
+ 'WWW-Authenticate': 'Bearer',
406
+ });
407
+ return;
408
+ }
409
+ if (typeof sessionId === 'string' && existing)
410
+ lastSeen.set(sessionId, Date.now());
411
+ if (req.method === 'POST') {
412
+ let body;
413
+ try {
414
+ body = await readJsonBody(req, config.maxBodyBytes);
415
+ }
416
+ catch (err) {
417
+ if (err instanceof BodyTooLargeError) {
418
+ // Don't drain the rest of an oversized upload — terminate the
419
+ // connection so an attacker can't keep streaming a huge body.
420
+ writeJson(res, 413, jsonRpcError(null, -32600, 'Request body too large'), {
421
+ Connection: 'close',
422
+ });
423
+ req.destroy();
424
+ return;
425
+ }
426
+ if (err instanceof JsonParseError) {
427
+ writeJson(res, 400, jsonRpcError(null, -32700, 'Parse error'));
428
+ return;
429
+ }
430
+ throw err;
431
+ }
432
+ let transport = existing;
433
+ if (!transport) {
434
+ if (sessionId !== undefined) {
435
+ writeJson(res, 404, jsonRpcError(null, -32001, 'Session not found'));
436
+ return;
437
+ }
438
+ if (!isInitializeRequest(body)) {
439
+ writeJson(res, 400, jsonRpcError(null, -32000, 'Missing session ID: first request must be initialize'));
440
+ return;
441
+ }
442
+ try {
443
+ transport = await createTransport({ bearerToken: sessionBearer });
444
+ }
445
+ catch (error) {
446
+ if (error instanceof SessionAuthenticationError) {
447
+ writeJson(res, 401, jsonRpcError(null, -32001, 'Invalid session credential'), {
448
+ 'WWW-Authenticate': 'Bearer',
449
+ });
450
+ return;
451
+ }
452
+ if (error instanceof SessionAuthenticationUnavailableError) {
453
+ writeJson(res, 503, jsonRpcError(null, -32002, 'Credential validation temporarily unavailable'), {
454
+ 'Retry-After': '5',
455
+ });
456
+ return;
457
+ }
458
+ if (error instanceof SessionRateLimitError) {
459
+ writeJson(res, 429, jsonRpcError(null, -32003, 'Session creation rate limit exceeded'), {
460
+ 'Retry-After': String(error.retryAfterSeconds),
461
+ });
462
+ return;
463
+ }
464
+ throw error;
465
+ }
466
+ }
467
+ // Guard only requests against an existing session (a known id); a fresh
468
+ // initialize gets its id mid-handle and can't be swept in that window.
469
+ if (existing && typeof sessionId === 'string') {
470
+ retain(sessionId);
471
+ try {
472
+ await transport.handleRequest(req, res, body);
473
+ }
474
+ finally {
475
+ release(sessionId);
476
+ }
477
+ }
478
+ else {
479
+ await transport.handleRequest(req, res, body);
480
+ }
481
+ return;
482
+ }
483
+ // GET (SSE stream) and DELETE (session teardown) require a live session.
484
+ if (req.method === 'GET' || req.method === 'DELETE') {
485
+ if (!existing || typeof sessionId !== 'string') {
486
+ writeJson(res, 404, jsonRpcError(null, -32001, 'Invalid or missing session ID'));
487
+ return;
488
+ }
489
+ // A GET holds the SSE stream open for the session's lifetime; retaining
490
+ // it keeps the idle sweep from tearing down an active channel.
491
+ retain(sessionId);
492
+ try {
493
+ await existing.handleRequest(req, res);
494
+ }
495
+ finally {
496
+ release(sessionId);
497
+ }
498
+ return;
499
+ }
500
+ req.resume();
501
+ res.writeHead(405, { Allow: 'GET, POST, DELETE' });
502
+ res.end();
503
+ }
504
+ catch (error) {
505
+ logger(`[qveris] HTTP handler error: ${error instanceof Error ? error.message : error}\n`);
506
+ if (!res.headersSent) {
507
+ writeJson(res, 500, jsonRpcError(null, -32603, 'Internal server error'));
508
+ }
509
+ }
510
+ };
511
+ const httpServer = createServer((req, res) => {
512
+ void handler(req, res);
513
+ });
514
+ await new Promise((resolve, reject) => {
515
+ httpServer.once('error', reject);
516
+ httpServer.listen(config.port, config.host, () => {
517
+ httpServer.removeListener('error', reject);
518
+ const address = httpServer.address();
519
+ if (address)
520
+ boundPort = address.port;
521
+ resolve();
522
+ });
523
+ });
524
+ // Keep a persistent error handler so a post-startup server error (e.g. EMFILE)
525
+ // is logged instead of crashing the process as an unhandled 'error' event.
526
+ httpServer.on('error', (err) => {
527
+ logger(`[qveris] HTTP server error: ${err.message}\n`);
528
+ });
529
+ // Evict idle sessions so abandoned connections don't leak transports/servers.
530
+ // Sessions with an in-flight request or an open SSE stream are skipped so an
531
+ // active call is never torn down mid-flight.
532
+ const sweep = setInterval(() => {
533
+ const now = Date.now();
534
+ for (const [sessionId, seen] of lastSeen) {
535
+ if (now - seen > config.sessionTimeoutMs && !inflight.get(sessionId)) {
536
+ const transport = transports.get(sessionId);
537
+ evict(sessionId);
538
+ if (transport)
539
+ void transport.close().catch(() => undefined);
540
+ logger(`[qveris] MCP session evicted (idle): ${sessionId}\n`);
541
+ }
542
+ }
543
+ }, SWEEP_INTERVAL_MS);
544
+ sweep.unref();
545
+ logger(`[qveris] Qveris MCP Server started (streamable-http) on http://${config.host}:${boundPort}${config.path}\n`);
546
+ const close = async () => {
547
+ clearInterval(sweep);
548
+ for (const transport of transports.values()) {
549
+ await transport.close().catch(() => undefined);
550
+ }
551
+ transports.clear();
552
+ sessionCredentialFingerprints.clear();
553
+ lastSeen.clear();
554
+ inflight.clear();
555
+ await new Promise((resolve) => {
556
+ httpServer.close(() => resolve());
557
+ // Don't wait out idle keep-alive sockets (clients pool connections and
558
+ // hold them open for seconds); force them closed so shutdown is prompt.
559
+ httpServer.closeAllConnections?.();
560
+ });
561
+ };
562
+ return { httpServer, port: boundPort, close };
563
+ }
564
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,YAAY,EAAwE,MAAM,WAAW,CAAC;AAI/G,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAEzE,OAAO,EACL,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,sBAAsB,GAEvB,MAAM,kBAAkB,CAAC;AAqC1B,gFAAgF;AAChF,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACjC,IAAI,GAAG,4BAA4B,CAAC;CACvD;AAED,6EAA6E;AAC7E,MAAM,OAAO,qCAAsC,SAAQ,KAAK;IAC5C,IAAI,GAAG,uCAAuC,CAAC;CAClE;AAED,kFAAkF;AAClF,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC5B,IAAI,GAAG,uBAAuB,CAAC;IACxC,iBAAiB,CAAS;IAEnC,YAAY,OAAe,EAAE,iBAAiB,GAAG,EAAE;QACjD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,iBAAiB;YACpB,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,iBAAiB,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtH,CAAC;CACF;AAED,MAAM,YAAY,GAAG,IAAI,CAAC;AAC1B,MAAM,YAAY,GAAG,WAAW,CAAC;AACjC,MAAM,YAAY,GAAG,MAAM,CAAC;AAC5B,MAAM,sBAAsB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,QAAQ;AACxD,MAAM,0BAA0B,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,QAAQ;AAC1D,MAAM,iBAAiB,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,6BAA6B;AAClE,MAAM,QAAQ,GAAG,KAAK,CAAC;AAEvB,MAAM,iBAAkB,SAAQ,KAAK;CAAG;AACxC,MAAM,cAAe,SAAQ,KAAK;CAAG;AAErC,SAAS,SAAS,CAAC,KAAyB;IAC1C,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,KAAK;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,SAAS,CAAC,KAAyB,EAAE,QAAiB;IAC7D,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACzC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IACjE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IACnE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAyB,EAAE,QAAgB;IACnE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACzC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AACpE,CAAC;AAED,SAAS,QAAQ,CAAC,IAAc,EAAE,IAAY;IAC5C,8CAA8C;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACzB,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,CAAC;QACD,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;YAC/B,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,OAAO,CAAC,IAAc,EAAE,IAAY;IAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,gFAAgF;AAChF,4EAA4E;AAC5E,mCAAmC;AACnC,MAAM,aAAa,GAAG,qDAAqD,CAAC;AAE5E,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,CAAC,GAAG,IAAI;SACX,IAAI,EAAE;SACN,WAAW,EAAE;SACb,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,sBAAsB;IAClD,OAAO,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,KAAK,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAsB,EAAE,OAAiB,EAAE;IAChF,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAE1C,MAAM,OAAO,GAAG,GAAG,CAAC,oBAAoB,CAAC;IACzC,MAAM,OAAO,GAAG,GAAG,CAAC,oBAAoB,CAAC;IACzC,MAAM,YAAY,GAAG,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAEpE,MAAM,aAAa,GACjB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;QACvB,YAAY,KAAK,MAAM;QACvB,QAAQ,KAAK,SAAS;QACtB,OAAO,KAAK,SAAS;QACrB,QAAQ,KAAK,SAAS;QACtB,OAAO,KAAK,SAAS,CAAC;IAExB,MAAM,IAAI,GAA4B,YAAY,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAE5G,MAAM,OAAO,GAAG,QAAQ,IAAI,OAAO,CAAC;IACpC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,IAAI,GACR,OAAO,KAAK,SAAS;QACrB,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,oEAAoE;QAC7F,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC;QAC5B,UAAU,IAAI,CAAC;QACf,UAAU,IAAI,QAAQ;QACpB,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,YAAY,CAAC;IAEnB,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,QAAQ,IAAI,OAAO,IAAI,YAAY;QACzC,IAAI;QACJ,IAAI,EAAE,QAAQ,IAAI,GAAG,CAAC,oBAAoB,IAAI,YAAY;QAC1D,YAAY,EAAE,SAAS,CAAC,GAAG,CAAC,wBAAwB,CAAC;QACrD,cAAc,EAAE,SAAS,CAAC,GAAG,CAAC,0BAA0B,CAAC;QACzD,4BAA4B,EAAE,SAAS,CAAC,GAAG,CAAC,mCAAmC,EAAE,IAAI,CAAC;QACtF,kBAAkB,EAAE,SAAS,CAAC,GAAG,CAAC,oBAAoB,EAAE,KAAK,CAAC;QAC9D,SAAS,EAAE,GAAG,CAAC,0BAA0B,EAAE,IAAI,EAAE,IAAI,SAAS;QAC9D,oBAAoB,EAAE,KAAK;QAC3B,oBAAoB,EAAE,SAAS,CAAC,GAAG,CAAC,qCAAqC,EAAE,KAAK,CAAC;QACjF,YAAY,EAAE,gBAAgB,CAAC,GAAG,CAAC,yBAAyB,EAAE,sBAAsB,CAAC;QACrF,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,CAAC,6BAA6B,EAAE,0BAA0B,CAAC;QACjG,SAAS,EAAE,GAAG,CAAC,qBAAqB,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,SAAS;KAC9E,CAAC;AACJ,CAAC;AAED;uFACuF;AACvF,SAAS,aAAa,CAAC,GAAoB,EAAE,SAA6B;IACxE,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,CAAC,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC;IACrG,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC;IAC7C,OAAO,GAAG,KAAK,MAAM,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED,+DAA+D;AAC/D,KAAK,UAAU,YAAY,CAAC,GAAoB,EAAE,QAAgB;IAChE,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,KAAe,CAAC;QAC5B,KAAK,IAAI,GAAG,CAAC,MAAM,CAAC;QACpB,IAAI,KAAK,GAAG,QAAQ,EAAE,CAAC;YACrB,MAAM,IAAI,iBAAiB,CAAC,wBAAwB,QAAQ,QAAQ,CAAC,CAAC;QACxE,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,cAAc,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,GAAmB,EAAE,MAAc,EAAE,IAAa,EAAE,UAAkC,EAAE;IACzG,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACrC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC1E,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAED,SAAS,YAAY,CAAC,EAAW,EAAE,IAAY,EAAE,OAAe;IAC9D,OAAO,EAAE,OAAO,EAAE,KAAc,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC;AAC/E,CAAC;AAED,+DAA+D;AAC/D,SAAS,aAAa,CAAC,UAA8B,EAAE,KAAa;IAClE,MAAM,QAAQ,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAC7C,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,0EAA0E;IAC1E,4EAA4E;IAC5E,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;IACpE,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;IACjE,OAAO,eAAe,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,eAAe,CAAC,UAA8B;IACrD,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAClC,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;IACjC,OAAO,KAAK,IAAI,SAAS,CAAC;AAC5B,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAa;IAC1C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,iBAAiB,CAAC,WAA+B,EAAE,KAAyB;IACnF,IAAI,CAAC,WAAW,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzC,OAAO,eAAe,CAAC,WAAW,EAAE,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC;AACpE,CAAC;AAWD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAuB,EACvB,UAAkF,EAClF,QAAyB,EACzB,SAAoC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;IAE9E,MAAM,WAAW,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjD,IAAI,MAAM,CAAC,oBAAoB,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;IACjG,CAAC;IACD,IAAI,MAAM,CAAC,oBAAoB,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;QAC/D,MAAM,IAAI,KAAK,CAAC,gFAAgF,CAAC,CAAC;IACpG,CAAC;IACD,IAAI,WAAW,IAAI,CAAC,MAAM,CAAC,oBAAoB,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC;QACrG,MAAM,IAAI,KAAK,CACb,qEAAqE,MAAM,CAAC,IAAI,4BAA4B;YAC1G,mEAAmE;YACnE,yGAAyG,CAC5G,CAAC;IACJ,CAAC;IACD,IAAI,WAAW,IAAI,CAAC,MAAM,CAAC,oBAAoB,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACrE,MAAM,CACJ,yFAAyF;YACvF,wDAAwD,CAC3D,CAAC;IACJ,CAAC;IACD,4EAA4E;IAC5E,4EAA4E;IAC5E,4EAA4E;IAC5E,8EAA8E;IAC9E,8DAA8D;IAC9D,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACzE,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CACb,4CAA4C,MAAM,CAAC,IAAI,6BAA6B;YAClF,aAAa,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,gEAAgE,CACxG,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,GAAG,EAAyC,CAAC;IACpE,MAAM,6BAA6B,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAC,+CAA+C;IAC3F,IAAI,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC;IAE5B,2EAA2E;IAC3E,sEAAsE;IACtE,kEAAkE;IAClE,MAAM,MAAM,GAAG,CAAC,SAAiB,EAAQ,EAAE;QACzC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,CAAC,SAAiB,EAAQ,EAAE;QAC1C,MAAM,SAAS,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACrD,IAAI,SAAS,GAAG,CAAC;YAAE,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;;YACjD,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC,CAAC;IAEF,oEAAoE;IACpE,4EAA4E;IAC5E,qEAAqE;IACrE,MAAM,qBAAqB,GAAG,GAAa,EAAE;QAC3C,MAAM,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,IAAI,SAAS,EAAE,EAAE,aAAa,SAAS,EAAE,EAAE,aAAa,SAAS,EAAE,CAAC,CAAC;QACjG,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,CAAC,SAAiB,EAAQ,EAAE;QACxC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC3B,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC3B,6BAA6B,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAChD,IAAI,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC9D,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,KAAK,EAAE,IAAqB,EAA0C,EAAE;QAC9F,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,qBAAqB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3F,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC;YAClD,kBAAkB,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE;YACtC,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;YAC7C,4BAA4B,EAAE,MAAM,CAAC,4BAA4B;YACjE,YAAY,EAAE,qBAAqB,EAAE;YACrC,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,oBAAoB,EAAE,CAAC,SAAS,EAAE,EAAE;gBAClC,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;gBACrC,IAAI,WAAW;oBAAE,6BAA6B,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;gBAC3E,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;gBACpC,MAAM,CAAC,qCAAqC,SAAS,IAAI,CAAC,CAAC;YAC7D,CAAC;SACF,CAAC,CAAC;QACH,SAAS,CAAC,OAAO,GAAG,GAAG,EAAE;YACvB,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;YACtC,IAAI,SAAS,IAAI,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,SAAS,EAAE,CAAC;gBACzD,KAAK,CAAC,SAAS,CAAC,CAAC;gBACjB,MAAM,CAAC,gCAAgC,SAAS,IAAI,CAAC,CAAC;YACxD,CAAC;QACH,CAAC,CAAC;QACF,IAAI,MAA0B,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,UAAU,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,CAAC;YAC9C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAChC,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC/C,IAAI,MAAM;gBAAE,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACxD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,KAAK,EAAE,GAAoB,EAAE,GAAmB,EAAiB,EAAE;QACjF,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,UAAU,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC,CAAC;YAEjF,gEAAgE;YAChE,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACvD,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC,CAAC;gBACpE,OAAO;YACT,CAAC;YAED,uEAAuE;YACvE,0EAA0E;YAC1E,0DAA0D;YAC1D,MAAM,QAAQ,GAAG,GAAG,MAAM,CAAC,IAAI,cAAc,CAAC;YAC9C,IAAI,QAAQ,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,EAAE,CAAC;gBAC7E,MAAM,IAAI,GAAG;oBACX,6BAA6B,EAAE,GAAG;oBAClC,8BAA8B,EAAE,cAAc;oBAC9C,8BAA8B,EAAE,QAAQ;iBACzC,CAAC;gBACF,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBAC7B,GAAG,CAAC,MAAM,EAAE,CAAC;oBACb,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,wBAAwB,EAAE,OAAO,EAAE,CAAC,CAAC;oBACnE,GAAG,CAAC,GAAG,EAAE,CAAC;oBACV,OAAO;gBACT,CAAC;gBACD,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;oBACzB,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;oBACpD,uEAAuE;oBACvE,sEAAsE;oBACtE,uEAAuE;oBACvE,qDAAqD;oBACrD,MAAM,KAAK,GAA2B,MAAM,CAAC,SAAS;wBACpD,CAAC,CAAC,EAAE,eAAe,EAAE,sBAAsB,EAAE;wBAC7C,CAAC,CAAC,EAAE,eAAe,EAAE,UAAU,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAAC;oBACrE,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;wBAC9B,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,EAAE,GAAG,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;wBAClE,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAAE,CAAC,CAAC;oBAC3F,CAAC;yBAAM,CAAC;wBACN,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,GAAG,MAAM,GAAG,QAAQ,EAAE,CAAC,CAAC;wBAC/D,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;oBACtD,CAAC;oBACD,OAAO;gBACT,CAAC;gBACD,GAAG,CAAC,MAAM,EAAE,CAAC;gBACb,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;gBAC9C,GAAG,CAAC,GAAG,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YAED,IAAI,GAAG,CAAC,QAAQ,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC;gBACjC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,wDAAwD;gBACtE,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,cAAc,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;gBAC9E,OAAO;YACT,CAAC;YAED,iEAAiE;YACjE,IAAI,MAAM,CAAC,SAAS,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;gBACvF,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,kDAAkD;gBAChE,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,EAAE;oBAC9D,kBAAkB,EAAE,QAAQ;iBAC7B,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,MAAM,aAAa,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC9G,IAAI,MAAM,CAAC,oBAAoB,IAAI,CAAC,aAAa,EAAE,CAAC;gBAClD,GAAG,CAAC,MAAM,EAAE,CAAC;gBACb,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,4BAA4B,CAAC,EAAE;oBAC5E,kBAAkB,EAAE,QAAQ;iBAC7B,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YAChD,MAAM,QAAQ,GAAG,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACvF,IACE,MAAM,CAAC,oBAAoB;gBAC3B,QAAQ;gBACR,OAAO,SAAS,KAAK,QAAQ;gBAC7B,CAAC,iBAAiB,CAAC,6BAA6B,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC,EAC/E,CAAC;gBACD,GAAG,CAAC,MAAM,EAAE,CAAC;gBACb,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,6BAA6B,CAAC,EAAE;oBAC7E,kBAAkB,EAAE,QAAQ;iBAC7B,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YACD,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,QAAQ;gBAAE,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YAEnF,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC1B,IAAI,IAAa,CAAC;gBAClB,IAAI,CAAC;oBACH,IAAI,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;gBACtD,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,IAAI,GAAG,YAAY,iBAAiB,EAAE,CAAC;wBACrC,8DAA8D;wBAC9D,8DAA8D;wBAC9D,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,wBAAwB,CAAC,EAAE;4BACxE,UAAU,EAAE,OAAO;yBACpB,CAAC,CAAC;wBACH,GAAG,CAAC,OAAO,EAAE,CAAC;wBACd,OAAO;oBACT,CAAC;oBACD,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;wBAClC,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC;wBAC/D,OAAO;oBACT,CAAC;oBACD,MAAM,GAAG,CAAC;gBACZ,CAAC;gBAED,IAAI,SAAS,GAAG,QAAQ,CAAC;gBACzB,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;wBAC5B,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC;wBACrE,OAAO;oBACT,CAAC;oBACD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;wBAC/B,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,sDAAsD,CAAC,CAAC,CAAC;wBACxG,OAAO;oBACT,CAAC;oBACD,IAAI,CAAC;wBACH,SAAS,GAAG,MAAM,eAAe,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC,CAAC;oBACpE,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,IAAI,KAAK,YAAY,0BAA0B,EAAE,CAAC;4BAChD,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,4BAA4B,CAAC,EAAE;gCAC5E,kBAAkB,EAAE,QAAQ;6BAC7B,CAAC,CAAC;4BACH,OAAO;wBACT,CAAC;wBACD,IAAI,KAAK,YAAY,qCAAqC,EAAE,CAAC;4BAC3D,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,+CAA+C,CAAC,EAAE;gCAC/F,aAAa,EAAE,GAAG;6BACnB,CAAC,CAAC;4BACH,OAAO;wBACT,CAAC;wBACD,IAAI,KAAK,YAAY,qBAAqB,EAAE,CAAC;4BAC3C,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,sCAAsC,CAAC,EAAE;gCACtF,aAAa,EAAE,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC;6BAC/C,CAAC,CAAC;4BACH,OAAO;wBACT,CAAC;wBACD,MAAM,KAAK,CAAC;oBACd,CAAC;gBACH,CAAC;gBAED,wEAAwE;gBACxE,uEAAuE;gBACvE,IAAI,QAAQ,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;oBAC9C,MAAM,CAAC,SAAS,CAAC,CAAC;oBAClB,IAAI,CAAC;wBACH,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;oBAChD,CAAC;4BAAS,CAAC;wBACT,OAAO,CAAC,SAAS,CAAC,CAAC;oBACrB,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;gBAChD,CAAC;gBACD,OAAO;YACT,CAAC;YAED,yEAAyE;YACzE,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACpD,IAAI,CAAC,QAAQ,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;oBAC/C,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,+BAA+B,CAAC,CAAC,CAAC;oBACjF,OAAO;gBACT,CAAC;gBACD,wEAAwE;gBACxE,+DAA+D;gBAC/D,MAAM,CAAC,SAAS,CAAC,CAAC;gBAClB,IAAI,CAAC;oBACH,MAAM,QAAQ,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBACzC,CAAC;wBAAS,CAAC;oBACT,OAAO,CAAC,SAAS,CAAC,CAAC;gBACrB,CAAC;gBACD,OAAO;YACT,CAAC;YAED,GAAG,CAAC,MAAM,EAAE,CAAC;YACb,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;YACnD,GAAG,CAAC,GAAG,EAAE,CAAC;QACZ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,gCAAgC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;YAC3F,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBACrB,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC3C,KAAK,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACjC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;YAC/C,UAAU,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC3C,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,EAAwB,CAAC;YAC3D,IAAI,OAAO;gBAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;YACtC,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,+EAA+E;IAC/E,2EAA2E;IAC3E,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;QACpC,MAAM,CAAC,+BAA+B,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAC9E,6EAA6E;IAC7E,6CAA6C;IAC7C,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzC,IAAI,GAAG,GAAG,IAAI,GAAG,MAAM,CAAC,gBAAgB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACrE,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC5C,KAAK,CAAC,SAAS,CAAC,CAAC;gBACjB,IAAI,SAAS;oBAAE,KAAK,SAAS,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBAC7D,MAAM,CAAC,wCAAwC,SAAS,IAAI,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;IACH,CAAC,EAAE,iBAAiB,CAAC,CAAC;IACtB,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,MAAM,CAAC,kEAAkE,MAAM,CAAC,IAAI,IAAI,SAAS,GAAG,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;IAErH,MAAM,KAAK,GAAG,KAAK,IAAmB,EAAE;QACtC,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,KAAK,MAAM,SAAS,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;YAC5C,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACjD,CAAC;QACD,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,6BAA6B,CAAC,KAAK,EAAE,CAAC;QACtC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACjB,QAAQ,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YAClC,uEAAuE;YACvE,wEAAwE;YACxE,UAAU,CAAC,mBAAmB,EAAE,EAAE,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAChD,CAAC"}