@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.
- package/CHANGELOG.md +145 -0
- package/README.md +297 -236
- package/dist/api/client.d.ts +9 -0
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +113 -76
- package/dist/api/client.js.map +1 -1
- package/dist/http.d.ts +99 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +564 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +107 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +176 -60
- package/dist/index.js.map +1 -1
- package/dist/output-schemas.d.ts +12 -0
- package/dist/output-schemas.d.ts.map +1 -0
- package/dist/output-schemas.js +61 -0
- package/dist/output-schemas.js.map +1 -0
- package/dist/retry.d.ts +42 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +69 -0
- package/dist/retry.js.map +1 -0
- package/dist/server-card.d.ts +85 -0
- package/dist/server-card.d.ts.map +1 -0
- package/dist/server-card.js +87 -0
- package/dist/server-card.js.map +1 -0
- package/dist/tools/audit-utils.d.ts.map +1 -1
- package/dist/tools/audit-utils.js +11 -16
- package/dist/tools/audit-utils.js.map +1 -1
- package/dist/tools/credits-ledger.d.ts +1 -2
- package/dist/tools/credits-ledger.d.ts.map +1 -1
- package/dist/tools/credits-ledger.js.map +1 -1
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/execute.js.map +1 -1
- package/dist/tools/get-by-ids.d.ts.map +1 -1
- package/dist/tools/get-by-ids.js +1 -2
- package/dist/tools/get-by-ids.js.map +1 -1
- package/dist/tools/usage-history.d.ts +1 -2
- package/dist/tools/usage-history.d.ts.map +1 -1
- package/dist/tools/usage-history.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +70 -59
package/dist/api/client.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module api/client
|
|
8
8
|
*/
|
|
9
|
+
import { computeRetryDelayMs, DEFAULT_BASE_DELAY_MS, DEFAULT_MAX_DELAY_MS, parseRetryAfterMs, resolveMaxRetries, RETRYABLE_STATUS, } from '../retry.js';
|
|
9
10
|
/** Region-specific API base URLs */
|
|
10
11
|
const REGION_URLS = {
|
|
11
12
|
global: 'https://qveris.ai/api/v1',
|
|
@@ -61,6 +62,8 @@ export class QverisClient {
|
|
|
61
62
|
apiKey;
|
|
62
63
|
baseUrl;
|
|
63
64
|
defaultTimeoutMs;
|
|
65
|
+
maxRetries;
|
|
66
|
+
rateLimitRetries = 0;
|
|
64
67
|
constructor(config) {
|
|
65
68
|
if (!config.apiKey) {
|
|
66
69
|
throw new Error('Qveris API key is required');
|
|
@@ -69,6 +72,22 @@ export class QverisClient {
|
|
|
69
72
|
// Resolve base URL: explicit > env > key prefix auto-detect
|
|
70
73
|
this.baseUrl = resolveBaseUrl(config.apiKey, config.baseUrl);
|
|
71
74
|
this.defaultTimeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
75
|
+
// Retries for 429/503: explicit config wins, then the env var (the MCP
|
|
76
|
+
// server itself is env-configured), then the default.
|
|
77
|
+
this.maxRetries = resolveMaxRetries(config.maxRetries ?? process.env.QVERIS_MAX_RETRIES);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* How many times the client has backed off on a rate-limited (429) /
|
|
81
|
+
* transient (503) response so far — retried pressure, not failure.
|
|
82
|
+
*/
|
|
83
|
+
get rateLimitRetryCount() {
|
|
84
|
+
return this.rateLimitRetries;
|
|
85
|
+
}
|
|
86
|
+
/** Sleep for `ms` (a seam so tests can stub out the wait). */
|
|
87
|
+
async sleep(ms) {
|
|
88
|
+
if (ms <= 0)
|
|
89
|
+
return;
|
|
90
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
72
91
|
}
|
|
73
92
|
/**
|
|
74
93
|
* Makes an authenticated HTTP request to the Qveris API.
|
|
@@ -82,7 +101,6 @@ export class QverisClient {
|
|
|
82
101
|
}
|
|
83
102
|
}
|
|
84
103
|
}
|
|
85
|
-
const controller = new AbortController();
|
|
86
104
|
const resolvedTimeoutMs = timeoutMs ?? this.defaultTimeoutMs;
|
|
87
105
|
const queryParams = Object.fromEntries(url.searchParams.entries());
|
|
88
106
|
const requestContext = {
|
|
@@ -94,83 +112,108 @@ export class QverisClient {
|
|
|
94
112
|
...(Object.keys(queryParams).length > 0 && { query_params: queryParams }),
|
|
95
113
|
timeout_ms: resolvedTimeoutMs,
|
|
96
114
|
};
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
115
|
+
// Retry rate-limited (429) / transient (503) responses: honor Retry-After,
|
|
116
|
+
// otherwise exponential backoff with jitter, bounded by maxRetries. Each
|
|
117
|
+
// attempt is a fresh fetch with its own timeout.
|
|
118
|
+
for (let attempt = 0;; attempt++) {
|
|
119
|
+
const controller = new AbortController();
|
|
120
|
+
const timeout = setTimeout(() => controller.abort(), resolvedTimeoutMs);
|
|
121
|
+
// eslint-disable-next-line no-useless-assignment -- TS definite-assignment needs the init across try/finally
|
|
122
|
+
let retryDelayMs = null;
|
|
123
|
+
try {
|
|
124
|
+
const response = await fetch(url.toString(), {
|
|
125
|
+
method,
|
|
126
|
+
headers: {
|
|
127
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
128
|
+
'Content-Type': 'application/json',
|
|
129
|
+
},
|
|
130
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
131
|
+
signal: controller.signal,
|
|
132
|
+
});
|
|
133
|
+
if (RETRYABLE_STATUS.has(response.status) && attempt < this.maxRetries) {
|
|
134
|
+
retryDelayMs = computeRetryDelayMs({
|
|
135
|
+
retryAfterMs: parseRetryAfterMs(response.headers.get('retry-after')),
|
|
136
|
+
attempt,
|
|
137
|
+
baseDelayMs: DEFAULT_BASE_DELAY_MS,
|
|
138
|
+
maxDelayMs: DEFAULT_MAX_DELAY_MS,
|
|
139
|
+
});
|
|
140
|
+
// Discard the body so the connection is released before we retry.
|
|
141
|
+
// (`.cancel?.()` so a body without cancel — e.g. a test double —
|
|
142
|
+
// can't throw here and mask the rate-limit as a network error.)
|
|
143
|
+
await response.body?.cancel?.().catch(() => undefined);
|
|
144
|
+
this.rateLimitRetries++;
|
|
120
145
|
}
|
|
121
|
-
|
|
122
|
-
|
|
146
|
+
else if (!response.ok) {
|
|
147
|
+
const status = response.status;
|
|
148
|
+
let errorMessage;
|
|
149
|
+
let errorDetails;
|
|
150
|
+
try {
|
|
151
|
+
const errorBody = (await response.json());
|
|
152
|
+
errorMessage =
|
|
153
|
+
errorBody.error_message ||
|
|
154
|
+
errorBody.message ||
|
|
155
|
+
errorBody.error ||
|
|
156
|
+
response.statusText;
|
|
157
|
+
errorDetails = errorBody;
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
errorMessage = response.statusText || `HTTP ${status}`;
|
|
161
|
+
}
|
|
162
|
+
// Provide actionable hints for specific status codes
|
|
163
|
+
if (status === 402) {
|
|
164
|
+
const pricingHost = this.baseUrl.includes('qveris.cn') ? 'https://qveris.cn' : 'https://qveris.ai';
|
|
165
|
+
errorMessage = `Insufficient credits. ${errorMessage}. Purchase credits at ${pricingHost}/pricing`;
|
|
166
|
+
}
|
|
167
|
+
const error = {
|
|
168
|
+
status,
|
|
169
|
+
message: errorMessage,
|
|
170
|
+
...(errorDetails !== undefined && { details: errorDetails }),
|
|
171
|
+
observability: withErrorContext(requestContext, 'http_error', status, extractRequestId(response)),
|
|
172
|
+
};
|
|
173
|
+
throw error;
|
|
123
174
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
175
|
+
else {
|
|
176
|
+
try {
|
|
177
|
+
return (await response.json());
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
const error = {
|
|
181
|
+
status: response.status,
|
|
182
|
+
message: 'Invalid or empty JSON response from API',
|
|
183
|
+
observability: withErrorContext(requestContext, 'invalid_json', response.status, extractRequestId(response)),
|
|
184
|
+
};
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
128
187
|
}
|
|
129
|
-
const error = {
|
|
130
|
-
status,
|
|
131
|
-
message: errorMessage,
|
|
132
|
-
...(errorDetails !== undefined && { details: errorDetails }),
|
|
133
|
-
observability: withErrorContext(requestContext, 'http_error', status, extractRequestId(response)),
|
|
134
|
-
};
|
|
135
|
-
throw error;
|
|
136
|
-
}
|
|
137
|
-
try {
|
|
138
|
-
return await response.json();
|
|
139
188
|
}
|
|
140
|
-
catch {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
189
|
+
catch (err) {
|
|
190
|
+
if (isApiError(err)) {
|
|
191
|
+
throw err;
|
|
192
|
+
}
|
|
193
|
+
if (err instanceof Error && err.name === 'AbortError') {
|
|
194
|
+
const cause = getErrorCause(err);
|
|
195
|
+
const error = {
|
|
196
|
+
status: 408,
|
|
197
|
+
message: 'Request timed out. Check connectivity or increase timeout.',
|
|
198
|
+
observability: withErrorContext(requestContext, 'timeout', 0),
|
|
199
|
+
...(cause && { cause }),
|
|
200
|
+
};
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
154
203
|
const cause = getErrorCause(err);
|
|
155
204
|
const error = {
|
|
156
|
-
status:
|
|
157
|
-
message: '
|
|
158
|
-
observability: withErrorContext(requestContext, '
|
|
205
|
+
status: 0,
|
|
206
|
+
message: getErrorMessage(err, 'Network request failed'),
|
|
207
|
+
observability: withErrorContext(requestContext, 'network_error', 0),
|
|
159
208
|
...(cause && { cause }),
|
|
160
209
|
};
|
|
161
210
|
throw error;
|
|
162
211
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
...(cause && { cause }),
|
|
169
|
-
};
|
|
170
|
-
throw error;
|
|
171
|
-
}
|
|
172
|
-
finally {
|
|
173
|
-
clearTimeout(timeout);
|
|
212
|
+
finally {
|
|
213
|
+
clearTimeout(timeout);
|
|
214
|
+
}
|
|
215
|
+
// Only reached on the retry path (success returns, errors throw above).
|
|
216
|
+
await this.sleep(retryDelayMs ?? 0);
|
|
174
217
|
}
|
|
175
218
|
}
|
|
176
219
|
/**
|
|
@@ -243,16 +286,10 @@ function withErrorContext(context, errorType, httpStatus, requestId) {
|
|
|
243
286
|
}
|
|
244
287
|
function extractRequestId(response) {
|
|
245
288
|
const headers = response.headers;
|
|
246
|
-
return (headers?.get('x-request-id') ??
|
|
247
|
-
headers?.get('x-qveris-request-id') ??
|
|
248
|
-
headers?.get('x-correlation-id') ??
|
|
249
|
-
undefined);
|
|
289
|
+
return (headers?.get('x-request-id') ?? headers?.get('x-qveris-request-id') ?? headers?.get('x-correlation-id') ?? undefined);
|
|
250
290
|
}
|
|
251
291
|
function isApiError(error) {
|
|
252
|
-
return
|
|
253
|
-
error !== null &&
|
|
254
|
-
'status' in error &&
|
|
255
|
-
'message' in error);
|
|
292
|
+
return typeof error === 'object' && error !== null && 'status' in error && 'message' in error;
|
|
256
293
|
}
|
|
257
294
|
function getErrorMessage(error, fallback) {
|
|
258
295
|
if (error instanceof Error && error.message)
|
package/dist/api/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
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 { type Server as HttpServer } from 'node:http';
|
|
20
|
+
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
21
|
+
import { type ServerCardInfo } from './server-card.js';
|
|
22
|
+
/** Transport selection plus the HTTP-mode settings. */
|
|
23
|
+
export interface TransportConfig {
|
|
24
|
+
mode: 'stdio' | 'http';
|
|
25
|
+
host: string;
|
|
26
|
+
port: number;
|
|
27
|
+
/** Request path the MCP endpoint is served on (default `/mcp`). */
|
|
28
|
+
path: string;
|
|
29
|
+
/** Extra `Host` header values accepted when DNS-rebinding protection is on. */
|
|
30
|
+
allowedHosts: string[];
|
|
31
|
+
/** Extra `Origin` header values accepted when DNS-rebinding protection is on. */
|
|
32
|
+
allowedOrigins: string[];
|
|
33
|
+
/** Reject requests whose Host/Origin isn't allow-listed (default on). */
|
|
34
|
+
enableDnsRebindingProtection: boolean;
|
|
35
|
+
/** Return JSON responses instead of an SSE stream (default off). */
|
|
36
|
+
enableJsonResponse: boolean;
|
|
37
|
+
/** Shared bearer token required on the MCP endpoint; unset = no inbound auth. */
|
|
38
|
+
authToken?: string;
|
|
39
|
+
/** Require a caller bearer and bind it to each new MCP session. Embedders set this directly. */
|
|
40
|
+
requireSessionBearer?: boolean;
|
|
41
|
+
/** Allow a non-loopback bind without a token (auth delegated externally). */
|
|
42
|
+
allowUnauthenticated: boolean;
|
|
43
|
+
/** Max accepted request body size in bytes (413 beyond it). */
|
|
44
|
+
maxBodyBytes: number;
|
|
45
|
+
/** Idle session TTL in ms; stale sessions are closed and evicted. */
|
|
46
|
+
sessionTimeoutMs: number;
|
|
47
|
+
/** Public origin (e.g. behind a TLS proxy) used in discovery documents. */
|
|
48
|
+
publicUrl?: string;
|
|
49
|
+
}
|
|
50
|
+
/** Credential context supplied only while constructing a new MCP session. */
|
|
51
|
+
export interface HttpSessionAuth {
|
|
52
|
+
/** Present only when requireSessionBearer is enabled. Never logged or persisted by the transport. */
|
|
53
|
+
bearerToken?: string;
|
|
54
|
+
}
|
|
55
|
+
/** The embedding service rejected the credential supplied for a new session. */
|
|
56
|
+
export declare class SessionAuthenticationError extends Error {
|
|
57
|
+
readonly name = "SessionAuthenticationError";
|
|
58
|
+
}
|
|
59
|
+
/** The embedding service could not validate a supplied credential safely. */
|
|
60
|
+
export declare class SessionAuthenticationUnavailableError extends Error {
|
|
61
|
+
readonly name = "SessionAuthenticationUnavailableError";
|
|
62
|
+
}
|
|
63
|
+
/** The embedding service rate-limited creation of a new authenticated session. */
|
|
64
|
+
export declare class SessionRateLimitError extends Error {
|
|
65
|
+
readonly name = "SessionRateLimitError";
|
|
66
|
+
readonly retryAfterSeconds: number;
|
|
67
|
+
constructor(message: string, retryAfterSeconds?: number);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Resolve the transport configuration from environment and CLI flags.
|
|
71
|
+
*
|
|
72
|
+
* HTTP mode is selected when `--http` is passed, `QVERIS_MCP_TRANSPORT=http`,
|
|
73
|
+
* or an HTTP port/host is explicitly set; otherwise the transport stays stdio
|
|
74
|
+
* so existing local configs are unaffected.
|
|
75
|
+
*/
|
|
76
|
+
export declare function resolveTransportConfig(env: NodeJS.ProcessEnv, argv?: string[]): TransportConfig;
|
|
77
|
+
/** Handle to a running HTTP server. */
|
|
78
|
+
export interface RunningHttpServer {
|
|
79
|
+
httpServer: HttpServer;
|
|
80
|
+
/** The port actually bound (useful when config.port is 0). */
|
|
81
|
+
port: number;
|
|
82
|
+
/** Close all sessions and stop the HTTP server. */
|
|
83
|
+
close: () => Promise<void>;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Start the Streamable HTTP server.
|
|
87
|
+
*
|
|
88
|
+
* @param config - Resolved HTTP transport settings.
|
|
89
|
+
* @param makeServer - Factory that builds a fresh Qveris {@link Server} for a
|
|
90
|
+
* new client session. Called once per `initialize`.
|
|
91
|
+
* @param cardInfo - Metadata for the discovery documents (Server Card + Catalog).
|
|
92
|
+
* When omitted those endpoints are not served.
|
|
93
|
+
* @param logger - Where to write startup/lifecycle lines (defaults to stderr,
|
|
94
|
+
* keeping stdout clean).
|
|
95
|
+
* @throws if binding a non-loopback host without an auth token and without an
|
|
96
|
+
* explicit opt-out (fail-closed).
|
|
97
|
+
*/
|
|
98
|
+
export declare function startHttpServer(config: TransportConfig, makeServer: (sessionId: string, auth: HttpSessionAuth) => Server | Promise<Server>, cardInfo?: ServerCardInfo, logger?: (message: string) => void): Promise<RunningHttpServer>;
|
|
99
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAAsC,KAAK,MAAM,IAAI,UAAU,EAAuB,MAAM,WAAW,CAAC;AAG/G,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAIxE,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAE1B,uDAAuD;AACvD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iFAAiF;IACjF,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,yEAAyE;IACzE,4BAA4B,EAAE,OAAO,CAAC;IACtC,oEAAoE;IACpE,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gGAAgG;IAChG,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,6EAA6E;IAC7E,oBAAoB,EAAE,OAAO,CAAC;IAC9B,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,gBAAgB,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B,qGAAqG;IACrG,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,gFAAgF;AAChF,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,SAAkB,IAAI,gCAAgC;CACvD;AAED,6EAA6E;AAC7E,qBAAa,qCAAsC,SAAQ,KAAK;IAC9D,SAAkB,IAAI,2CAA2C;CAClE;AAED,kFAAkF;AAClF,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,SAAkB,IAAI,2BAA2B;IACjD,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;gBAEvB,OAAO,EAAE,MAAM,EAAE,iBAAiB,SAAK;CAKpD;AAmED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,GAAE,MAAM,EAAO,GAAG,eAAe,CA8CnG;AAuED,uCAAuC;AACvC,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,UAAU,CAAC;IACvB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,eAAe,EACvB,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,EAClF,QAAQ,CAAC,EAAE,cAAc,EACzB,MAAM,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAiD,GAC7E,OAAO,CAAC,iBAAiB,CAAC,CA0V5B"}
|