@bedolla/enrivision 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +619 -0
- package/README.md +214 -0
- package/dist/client/EnriProxyClient.d.ts +323 -0
- package/dist/client/EnriProxyClient.d.ts.map +1 -0
- package/dist/client/EnriProxyClient.js +348 -0
- package/dist/client/EnriProxyClient.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/package-info.d.ts +8 -0
- package/dist/package-info.d.ts.map +1 -0
- package/dist/package-info.js +28 -0
- package/dist/package-info.js.map +1 -0
- package/dist/server/EnriVisionServer.d.ts +63 -0
- package/dist/server/EnriVisionServer.d.ts.map +1 -0
- package/dist/server/EnriVisionServer.js +246 -0
- package/dist/server/EnriVisionServer.js.map +1 -0
- package/dist/shared/tar.d.ts +108 -0
- package/dist/shared/tar.d.ts.map +1 -0
- package/dist/shared/tar.js +346 -0
- package/dist/shared/tar.js.map +1 -0
- package/dist/shared/validation.d.ts +61 -0
- package/dist/shared/validation.d.ts.map +1 -0
- package/dist/shared/validation.js +107 -0
- package/dist/shared/validation.js.map +1 -0
- package/dist/tools/AnalyzeMediaTool.d.ts +302 -0
- package/dist/tools/AnalyzeMediaTool.d.ts.map +1 -0
- package/dist/tools/AnalyzeMediaTool.js +509 -0
- package/dist/tools/AnalyzeMediaTool.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ENRIPROXY CLIENT
|
|
3
|
+
*
|
|
4
|
+
* Minimal HTTP client for EnriProxy endpoints used by EnriVision:
|
|
5
|
+
* - POST /v1/uploads
|
|
6
|
+
* - HEAD /v1/uploads/:id
|
|
7
|
+
* - PATCH /v1/uploads/:id
|
|
8
|
+
* - POST /v1/vision/analyze
|
|
9
|
+
*
|
|
10
|
+
* @module client/EnriProxyClient
|
|
11
|
+
*/
|
|
12
|
+
import { request as httpRequest } from "node:http";
|
|
13
|
+
import { request as httpsRequest } from "node:https";
|
|
14
|
+
import { URL } from "node:url";
|
|
15
|
+
/**
|
|
16
|
+
* Error thrown when EnriProxy returns a non-2xx HTTP response.
|
|
17
|
+
*/
|
|
18
|
+
export class EnriProxyHttpError extends Error {
|
|
19
|
+
/**
|
|
20
|
+
* HTTP status code returned by the server.
|
|
21
|
+
*/
|
|
22
|
+
status;
|
|
23
|
+
/**
|
|
24
|
+
* Response headers returned by the server.
|
|
25
|
+
*/
|
|
26
|
+
headers;
|
|
27
|
+
/**
|
|
28
|
+
* Response body returned by the server (best-effort UTF-8).
|
|
29
|
+
*/
|
|
30
|
+
body;
|
|
31
|
+
/**
|
|
32
|
+
* Creates a new {@link EnriProxyHttpError}.
|
|
33
|
+
*
|
|
34
|
+
* @param message - Error message
|
|
35
|
+
* @param status - HTTP status code
|
|
36
|
+
* @param headers - Response headers
|
|
37
|
+
* @param body - Response body
|
|
38
|
+
*/
|
|
39
|
+
constructor(message, status, headers, body) {
|
|
40
|
+
super(message);
|
|
41
|
+
this.name = "EnriProxyHttpError";
|
|
42
|
+
this.status = status;
|
|
43
|
+
this.headers = headers;
|
|
44
|
+
this.body = body;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Minimal client for EnriProxy HTTP endpoints.
|
|
49
|
+
*/
|
|
50
|
+
export class EnriProxyClient {
|
|
51
|
+
/**
|
|
52
|
+
* EnriProxy base URL.
|
|
53
|
+
*/
|
|
54
|
+
baseUrl;
|
|
55
|
+
/**
|
|
56
|
+
* API key for Authorization header.
|
|
57
|
+
*/
|
|
58
|
+
apiKey;
|
|
59
|
+
/**
|
|
60
|
+
* Default timeout for requests.
|
|
61
|
+
*/
|
|
62
|
+
timeoutMs;
|
|
63
|
+
/**
|
|
64
|
+
* Creates a new {@link EnriProxyClient}.
|
|
65
|
+
*
|
|
66
|
+
* @param config - Client configuration
|
|
67
|
+
*/
|
|
68
|
+
constructor(config) {
|
|
69
|
+
this.baseUrl = config.baseUrl.replace(/\/+$/, "");
|
|
70
|
+
this.apiKey = config.apiKey;
|
|
71
|
+
this.timeoutMs = config.timeoutMs;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Creates an upload session on the server.
|
|
75
|
+
*
|
|
76
|
+
* @param params - Session parameters
|
|
77
|
+
* @returns Session response
|
|
78
|
+
*/
|
|
79
|
+
async createUploadSession(params) {
|
|
80
|
+
const url = this.buildUrl("/v1/uploads");
|
|
81
|
+
const payload = {
|
|
82
|
+
filename: params.filename,
|
|
83
|
+
size_bytes: params.sizeBytes,
|
|
84
|
+
content_type: params.contentType,
|
|
85
|
+
client_trace_id: params.clientTraceId
|
|
86
|
+
};
|
|
87
|
+
const result = await this.requestJson("POST", url, payload, this.timeoutMs);
|
|
88
|
+
if (result.status < 200 || result.status >= 300) {
|
|
89
|
+
throw new EnriProxyHttpError(`Failed to create upload session (HTTP ${result.status}).`, result.status, result.headers, result.body);
|
|
90
|
+
}
|
|
91
|
+
const parsed = JSON.parse(result.body);
|
|
92
|
+
return parsed;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Queries the current upload offset for a session.
|
|
96
|
+
*
|
|
97
|
+
* @param uploadId - Upload id
|
|
98
|
+
* @returns Offset in bytes
|
|
99
|
+
*/
|
|
100
|
+
async getUploadOffset(uploadId) {
|
|
101
|
+
const url = this.buildUrl(`/v1/uploads/${encodeURIComponent(uploadId)}`);
|
|
102
|
+
const result = await this.requestRaw("HEAD", url, undefined, undefined, this.timeoutMs);
|
|
103
|
+
if (result.status < 200 || result.status >= 300) {
|
|
104
|
+
throw new EnriProxyHttpError(`Failed to query upload offset (HTTP ${result.status}).`, result.status, result.headers, result.body);
|
|
105
|
+
}
|
|
106
|
+
const offsetHeader = this.getHeaderValue(result.headers, "upload-offset");
|
|
107
|
+
if (!offsetHeader) {
|
|
108
|
+
throw new Error("Missing Upload-Offset header in server response.");
|
|
109
|
+
}
|
|
110
|
+
const offset = Number.parseInt(offsetHeader, 10);
|
|
111
|
+
if (!Number.isFinite(offset) || offset < 0) {
|
|
112
|
+
throw new Error(`Invalid Upload-Offset header: ${offsetHeader}`);
|
|
113
|
+
}
|
|
114
|
+
return offset;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Appends a chunk to an upload session.
|
|
118
|
+
*
|
|
119
|
+
* @param params - Chunk parameters
|
|
120
|
+
* @returns New upload offset in bytes
|
|
121
|
+
*/
|
|
122
|
+
async appendUploadChunk(params) {
|
|
123
|
+
const url = this.buildUrl(`/v1/uploads/${encodeURIComponent(params.uploadId)}`);
|
|
124
|
+
const timeoutMs = params.timeoutMs ?? this.timeoutMs;
|
|
125
|
+
const headers = {
|
|
126
|
+
"Content-Type": "application/offset+octet-stream",
|
|
127
|
+
"Upload-Offset": String(params.offset),
|
|
128
|
+
"Content-Length": String(params.chunk.length)
|
|
129
|
+
};
|
|
130
|
+
const result = await this.requestRaw("PATCH", url, headers, params.chunk, timeoutMs);
|
|
131
|
+
if (result.status < 200 || result.status >= 300) {
|
|
132
|
+
throw new EnriProxyHttpError(`Failed to upload chunk (HTTP ${result.status}).`, result.status, result.headers, result.body);
|
|
133
|
+
}
|
|
134
|
+
const offsetHeader = this.getHeaderValue(result.headers, "upload-offset");
|
|
135
|
+
if (!offsetHeader) {
|
|
136
|
+
throw new Error("Missing Upload-Offset header in server response.");
|
|
137
|
+
}
|
|
138
|
+
const newOffset = Number.parseInt(offsetHeader, 10);
|
|
139
|
+
if (!Number.isFinite(newOffset) || newOffset < 0) {
|
|
140
|
+
throw new Error(`Invalid Upload-Offset header: ${offsetHeader}`);
|
|
141
|
+
}
|
|
142
|
+
return newOffset;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Triggers server-side vision analysis for an uploaded file.
|
|
146
|
+
*
|
|
147
|
+
* @param params - Analysis parameters
|
|
148
|
+
* @returns Analysis response
|
|
149
|
+
*/
|
|
150
|
+
async analyze(params) {
|
|
151
|
+
const url = this.buildUrl("/v1/vision/analyze");
|
|
152
|
+
const payload = {
|
|
153
|
+
upload_id: params.uploadId
|
|
154
|
+
};
|
|
155
|
+
if (typeof params.context === "string" && params.context.trim())
|
|
156
|
+
payload["context"] = params.context.trim();
|
|
157
|
+
if (typeof params.question === "string" && params.question.trim())
|
|
158
|
+
payload["question"] = params.question.trim();
|
|
159
|
+
if (typeof params.language === "string" && params.language.trim())
|
|
160
|
+
payload["language"] = params.language.trim();
|
|
161
|
+
if (typeof params.maxFrames === "number" && Number.isFinite(params.maxFrames))
|
|
162
|
+
payload["max_frames"] = params.maxFrames;
|
|
163
|
+
if (typeof params.transcribe === "boolean")
|
|
164
|
+
payload["transcribe"] = params.transcribe;
|
|
165
|
+
if (typeof params.transcriptionLanguage === "string" && params.transcriptionLanguage.trim()) {
|
|
166
|
+
payload["transcription_language"] = params.transcriptionLanguage.trim();
|
|
167
|
+
}
|
|
168
|
+
if (typeof params.analysisMode === "string" && params.analysisMode.trim()) {
|
|
169
|
+
payload["analysis_mode"] = params.analysisMode.trim();
|
|
170
|
+
}
|
|
171
|
+
if (params.video && typeof params.video === "object") {
|
|
172
|
+
const videoPayload = {};
|
|
173
|
+
if (typeof params.video.clipStartSeconds === "number" && Number.isFinite(params.video.clipStartSeconds)) {
|
|
174
|
+
videoPayload["clip_start_seconds"] = Math.max(0, params.video.clipStartSeconds);
|
|
175
|
+
}
|
|
176
|
+
if (typeof params.video.clipDurationSeconds === "number" &&
|
|
177
|
+
Number.isFinite(params.video.clipDurationSeconds) &&
|
|
178
|
+
params.video.clipDurationSeconds > 0) {
|
|
179
|
+
videoPayload["clip_duration_seconds"] = params.video.clipDurationSeconds;
|
|
180
|
+
}
|
|
181
|
+
if (typeof params.video.segmentSeconds === "number" && Number.isFinite(params.video.segmentSeconds)) {
|
|
182
|
+
videoPayload["segment_seconds"] = params.video.segmentSeconds;
|
|
183
|
+
}
|
|
184
|
+
if (typeof params.video.maxSegments === "number" && Number.isFinite(params.video.maxSegments)) {
|
|
185
|
+
videoPayload["max_segments"] = Math.floor(params.video.maxSegments);
|
|
186
|
+
}
|
|
187
|
+
if (typeof params.video.maxFramesPerSegment === "number" && Number.isFinite(params.video.maxFramesPerSegment)) {
|
|
188
|
+
videoPayload["max_frames_per_segment"] = Math.floor(params.video.maxFramesPerSegment);
|
|
189
|
+
}
|
|
190
|
+
if (Object.keys(videoPayload).length > 0) {
|
|
191
|
+
payload["video"] = videoPayload;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (params.document && typeof params.document === "object") {
|
|
195
|
+
const documentPayload = {};
|
|
196
|
+
if (typeof params.document.maxPagesTotal === "number" && Number.isFinite(params.document.maxPagesTotal)) {
|
|
197
|
+
documentPayload["max_pages_total"] = Math.floor(params.document.maxPagesTotal);
|
|
198
|
+
}
|
|
199
|
+
if (typeof params.document.pagesPerBatch === "number" && Number.isFinite(params.document.pagesPerBatch)) {
|
|
200
|
+
documentPayload["pages_per_batch"] = Math.floor(params.document.pagesPerBatch);
|
|
201
|
+
}
|
|
202
|
+
if (typeof params.document.maxImagesPerBatch === "number" && Number.isFinite(params.document.maxImagesPerBatch)) {
|
|
203
|
+
documentPayload["max_images_per_batch"] = Math.floor(params.document.maxImagesPerBatch);
|
|
204
|
+
}
|
|
205
|
+
if (typeof params.document.scannedTextThresholdChars === "number" &&
|
|
206
|
+
Number.isFinite(params.document.scannedTextThresholdChars)) {
|
|
207
|
+
documentPayload["scanned_text_threshold_chars"] = Math.floor(params.document.scannedTextThresholdChars);
|
|
208
|
+
}
|
|
209
|
+
if (Object.keys(documentPayload).length > 0) {
|
|
210
|
+
payload["document"] = documentPayload;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (params.audio && typeof params.audio === "object") {
|
|
214
|
+
const audioPayload = {};
|
|
215
|
+
if (typeof params.audio.timestamps === "boolean") {
|
|
216
|
+
audioPayload["timestamps"] = params.audio.timestamps;
|
|
217
|
+
}
|
|
218
|
+
if (typeof params.audio.segmentSeconds === "number" && Number.isFinite(params.audio.segmentSeconds)) {
|
|
219
|
+
audioPayload["segment_seconds"] = params.audio.segmentSeconds;
|
|
220
|
+
}
|
|
221
|
+
if (typeof params.audio.maxSegments === "number" && Number.isFinite(params.audio.maxSegments)) {
|
|
222
|
+
audioPayload["max_segments"] = Math.floor(params.audio.maxSegments);
|
|
223
|
+
}
|
|
224
|
+
if (Object.keys(audioPayload).length > 0) {
|
|
225
|
+
payload["audio"] = audioPayload;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (params.images && typeof params.images === "object") {
|
|
229
|
+
const imagesPayload = {};
|
|
230
|
+
if (typeof params.images.maxImagesTotal === "number" && Number.isFinite(params.images.maxImagesTotal)) {
|
|
231
|
+
imagesPayload["max_images_total"] = Math.floor(params.images.maxImagesTotal);
|
|
232
|
+
}
|
|
233
|
+
if (typeof params.images.imagesPerBatch === "number" && Number.isFinite(params.images.imagesPerBatch)) {
|
|
234
|
+
imagesPayload["images_per_batch"] = Math.floor(params.images.imagesPerBatch);
|
|
235
|
+
}
|
|
236
|
+
if (typeof params.images.maxDimension === "number" && Number.isFinite(params.images.maxDimension)) {
|
|
237
|
+
imagesPayload["max_dimension"] = Math.floor(params.images.maxDimension);
|
|
238
|
+
}
|
|
239
|
+
if (Object.keys(imagesPayload).length > 0) {
|
|
240
|
+
payload["images"] = imagesPayload;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
const result = await this.requestJson("POST", url, payload, this.timeoutMs);
|
|
244
|
+
if (result.status < 200 || result.status >= 300) {
|
|
245
|
+
throw new EnriProxyHttpError(`Vision analysis failed (HTTP ${result.status}).`, result.status, result.headers, result.body);
|
|
246
|
+
}
|
|
247
|
+
const parsed = JSON.parse(result.body);
|
|
248
|
+
return parsed;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Builds an absolute URL relative to the configured base URL.
|
|
252
|
+
*
|
|
253
|
+
* @param pathname - Pathname to append
|
|
254
|
+
* @returns URL instance
|
|
255
|
+
*/
|
|
256
|
+
buildUrl(pathname) {
|
|
257
|
+
return new URL(pathname, this.baseUrl);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Extracts a response header as a single string.
|
|
261
|
+
*
|
|
262
|
+
* @param headers - Response headers
|
|
263
|
+
* @param name - Header name (case-insensitive)
|
|
264
|
+
* @returns Header value when present, otherwise undefined
|
|
265
|
+
*/
|
|
266
|
+
getHeaderValue(headers, name) {
|
|
267
|
+
const target = name.toLowerCase();
|
|
268
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
269
|
+
if (key.toLowerCase() !== target) {
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (Array.isArray(value)) {
|
|
273
|
+
return value[0];
|
|
274
|
+
}
|
|
275
|
+
return value;
|
|
276
|
+
}
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Sends a JSON request and returns the response.
|
|
281
|
+
*
|
|
282
|
+
* @param method - HTTP method
|
|
283
|
+
* @param url - Target URL
|
|
284
|
+
* @param jsonBody - JSON payload
|
|
285
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
286
|
+
* @returns HTTP result
|
|
287
|
+
*/
|
|
288
|
+
async requestJson(method, url, jsonBody, timeoutMs) {
|
|
289
|
+
const body = JSON.stringify(jsonBody);
|
|
290
|
+
const headers = {
|
|
291
|
+
"Content-Type": "application/json",
|
|
292
|
+
"Content-Length": String(Buffer.byteLength(body))
|
|
293
|
+
};
|
|
294
|
+
return await this.requestRaw(method, url, headers, Buffer.from(body, "utf8"), timeoutMs);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Sends an HTTP request with optional headers and body.
|
|
298
|
+
*
|
|
299
|
+
* @param method - HTTP method
|
|
300
|
+
* @param url - Target URL
|
|
301
|
+
* @param headers - Request headers
|
|
302
|
+
* @param body - Request body
|
|
303
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
304
|
+
* @returns HTTP result
|
|
305
|
+
*/
|
|
306
|
+
async requestRaw(method, url, headers, body, timeoutMs) {
|
|
307
|
+
const isHttps = url.protocol === "https:";
|
|
308
|
+
const reqFn = isHttps ? httpsRequest : httpRequest;
|
|
309
|
+
const requestHeaders = {
|
|
310
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
311
|
+
...(headers ?? {})
|
|
312
|
+
};
|
|
313
|
+
return await new Promise((resolve, reject) => {
|
|
314
|
+
const req = reqFn(url, {
|
|
315
|
+
method,
|
|
316
|
+
headers: requestHeaders
|
|
317
|
+
}, (res) => {
|
|
318
|
+
const chunks = [];
|
|
319
|
+
let received = 0;
|
|
320
|
+
const maxResponseBytes = 50 * 1024 * 1024; // 50MB safeguard
|
|
321
|
+
res.on("data", (chunk) => {
|
|
322
|
+
received += chunk.length;
|
|
323
|
+
if (received > maxResponseBytes) {
|
|
324
|
+
req.destroy(new Error("Response exceeded maximum allowed size."));
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
chunks.push(chunk);
|
|
328
|
+
});
|
|
329
|
+
res.on("end", () => {
|
|
330
|
+
resolve({
|
|
331
|
+
status: res.statusCode ?? 0,
|
|
332
|
+
headers: res.headers,
|
|
333
|
+
body: Buffer.concat(chunks).toString("utf8")
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
req.on("error", (error) => reject(error));
|
|
338
|
+
req.setTimeout(timeoutMs, () => {
|
|
339
|
+
req.destroy(new Error(`Request timed out after ${timeoutMs}ms`));
|
|
340
|
+
});
|
|
341
|
+
if (body && body.length > 0 && method !== "HEAD") {
|
|
342
|
+
req.write(body);
|
|
343
|
+
}
|
|
344
|
+
req.end();
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=EnriProxyClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnriProxyClient.js","sourceRoot":"","sources":["../../src/client/EnriProxyClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AA8D/B;;GAEG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C;;OAEG;IACa,MAAM,CAAS;IAE/B;;OAEG;IACa,OAAO,CAAgD;IAEvE;;OAEG;IACa,IAAI,CAAS;IAE7B;;;;;;;OAOG;IACH,YACE,OAAe,EACf,MAAc,EACd,OAAsD,EACtD,IAAY;QAEZ,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAsBD;;GAEG;AACH,MAAM,OAAO,eAAe;IAC1B;;OAEG;IACc,OAAO,CAAS;IAEjC;;OAEG;IACc,MAAM,CAAS;IAEhC;;OAEG;IACc,SAAS,CAAS;IAEnC;;;;OAIG;IACH,YAAmB,MAA6B;QAC9C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IACpC,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,mBAAmB,CAAC,MAoBhC;QACC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG;YACd,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,UAAU,EAAE,MAAM,CAAC,SAAS;YAC5B,YAAY,EAAE,MAAM,CAAC,WAAW;YAChC,eAAe,EAAE,MAAM,CAAC,aAAa;SACtC,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5E,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YAChD,MAAM,IAAI,kBAAkB,CAC1B,yCAAyC,MAAM,CAAC,MAAM,IAAI,EAC1D,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,IAAI,CACZ,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAgC,CAAC;QACtE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,eAAe,CAAC,QAAgB;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACxF,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YAChD,MAAM,IAAI,kBAAkB,CAC1B,uCAAuC,MAAM,CAAC,MAAM,IAAI,EACxD,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,IAAI,CACZ,CAAC;QACJ,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAC1E,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,iCAAiC,YAAY,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,iBAAiB,CAAC,MAoB9B;QACC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAChF,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC;QAErD,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,iCAAiC;YACjD,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;YACtC,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;SAC9C,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACrF,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YAChD,MAAM,IAAI,kBAAkB,CAC1B,gCAAgC,MAAM,CAAC,MAAM,IAAI,EACjD,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,IAAI,CACZ,CAAC;QACJ,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAC1E,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,KAAK,CAAC,iCAAiC,YAAY,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,OAAO,CAAC,MAuIpB;QACC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;QAChD,MAAM,OAAO,GAA4B;YACvC,SAAS,EAAE,MAAM,CAAC,QAAQ;SAC3B,CAAC;QAEF,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;YAAE,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5G,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;YAAE,OAAO,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChH,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;YAAE,OAAO,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChH,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;YAAE,OAAO,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC;QACxH,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,SAAS;YAAE,OAAO,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC;QACtF,IAAI,OAAO,MAAM,CAAC,qBAAqB,KAAK,QAAQ,IAAI,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,EAAE,CAAC;YAC5F,OAAO,CAAC,wBAAwB,CAAC,GAAG,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC;QAC1E,CAAC;QAED,IAAI,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1E,OAAO,CAAC,eAAe,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QACxD,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,YAAY,GAA4B,EAAE,CAAC;YACjD,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,gBAAgB,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBACxG,YAAY,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAClF,CAAC;YACD,IACE,OAAO,MAAM,CAAC,KAAK,CAAC,mBAAmB,KAAK,QAAQ;gBACpD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC;gBACjD,MAAM,CAAC,KAAK,CAAC,mBAAmB,GAAG,CAAC,EACpC,CAAC;gBACD,YAAY,CAAC,uBAAuB,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC;YAC3E,CAAC;YACD,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,cAAc,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;gBACpG,YAAY,CAAC,iBAAiB,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC;YAChE,CAAC;YACD,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,WAAW,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC9F,YAAY,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YACtE,CAAC;YACD,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,mBAAmB,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,EAAE,CAAC;gBAC9G,YAAY,CAAC,wBAAwB,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACxF,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzC,OAAO,CAAC,OAAO,CAAC,GAAG,YAAY,CAAC;YAClC,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,QAAQ,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC3D,MAAM,eAAe,GAA4B,EAAE,CAAC;YACpD,IAAI,OAAO,MAAM,CAAC,QAAQ,CAAC,aAAa,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;gBACxG,eAAe,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;YACjF,CAAC;YACD,IAAI,OAAO,MAAM,CAAC,QAAQ,CAAC,aAAa,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;gBACxG,eAAe,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;YACjF,CAAC;YACD,IAAI,OAAO,MAAM,CAAC,QAAQ,CAAC,iBAAiB,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBAChH,eAAe,CAAC,sBAAsB,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;YAC1F,CAAC;YACD,IACE,OAAO,MAAM,CAAC,QAAQ,CAAC,yBAAyB,KAAK,QAAQ;gBAC7D,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAC1D,CAAC;gBACD,eAAe,CAAC,8BAA8B,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;YAC1G,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5C,OAAO,CAAC,UAAU,CAAC,GAAG,eAAe,CAAC;YACxC,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,YAAY,GAA4B,EAAE,CAAC;YACjD,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;gBACjD,YAAY,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC;YACvD,CAAC;YACD,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,cAAc,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;gBACpG,YAAY,CAAC,iBAAiB,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC;YAChE,CAAC;YACD,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,WAAW,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC9F,YAAY,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YACtE,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzC,OAAO,CAAC,OAAO,CAAC,GAAG,YAAY,CAAC;YAClC,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,aAAa,GAA4B,EAAE,CAAC;YAClD,IAAI,OAAO,MAAM,CAAC,MAAM,CAAC,cAAc,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;gBACtG,aAAa,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YAC/E,CAAC;YACD,IAAI,OAAO,MAAM,CAAC,MAAM,CAAC,cAAc,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;gBACtG,aAAa,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YAC/E,CAAC;YACD,IAAI,OAAO,MAAM,CAAC,MAAM,CAAC,YAAY,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;gBAClG,aAAa,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YAC1E,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC;YACpC,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5E,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YAChD,MAAM,IAAI,kBAAkB,CAC1B,gCAAgC,MAAM,CAAC,MAAM,IAAI,EACjD,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,IAAI,CACZ,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAA0B,CAAC;QAChE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACK,QAAQ,CAAC,QAAgB;QAC/B,OAAO,IAAI,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAED;;;;;;OAMG;IACK,cAAc,CACpB,OAAsD,EACtD,IAAY;QAEZ,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAClC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;gBACjC,SAAS;YACX,CAAC;YACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;;;OAQG;IACK,KAAK,CAAC,WAAW,CACvB,MAAsB,EACtB,GAAQ,EACR,QAAiC,EACjC,SAAiB;QAEjB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,kBAAkB;YAClC,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;SAClD,CAAC;QACF,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC;IAC3F,CAAC;IAED;;;;;;;;;OASG;IACK,KAAK,CAAC,UAAU,CACtB,MAAyC,EACzC,GAAQ,EACR,OAA2C,EAC3C,IAAwB,EACxB,SAAiB;QAEjB,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;QAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC;QAEnD,MAAM,cAAc,GAA2B;YAC7C,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;YACtC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;SACnB,CAAC;QAEF,OAAO,MAAM,IAAI,OAAO,CAAa,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACvD,MAAM,GAAG,GAAG,KAAK,CACf,GAAG,EACH;gBACE,MAAM;gBACN,OAAO,EAAE,cAAc;aACxB,EACD,CAAC,GAAG,EAAE,EAAE;gBACN,MAAM,MAAM,GAAa,EAAE,CAAC;gBAC5B,IAAI,QAAQ,GAAG,CAAC,CAAC;gBACjB,MAAM,gBAAgB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,iBAAiB;gBAE5D,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;oBAC/B,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC;oBACzB,IAAI,QAAQ,GAAG,gBAAgB,EAAE,CAAC;wBAChC,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC,CAAC;wBAClE,OAAO;oBACT,CAAC;oBACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACrB,CAAC,CAAC,CAAC;gBAEH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;oBACjB,OAAO,CAAC;wBACN,MAAM,EAAE,GAAG,CAAC,UAAU,IAAI,CAAC;wBAC3B,OAAO,EAAE,GAAG,CAAC,OAAwD;wBACrE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;qBAC7C,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC,CACF,CAAC;YAEF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAE1C,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,GAAG,EAAE;gBAC7B,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,2BAA2B,SAAS,IAAI,CAAC,CAAC,CAAC;YACnE,CAAC,CAAC,CAAC;YAEH,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACjD,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC;YACD,GAAG,CAAC,GAAG,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;GAMG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ENRIVISION - MCP ENTRYPOINT
|
|
4
|
+
*
|
|
5
|
+
* Starts the EnriVision MCP server on stdio.
|
|
6
|
+
*
|
|
7
|
+
* @module index
|
|
8
|
+
*/
|
|
9
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
10
|
+
import { EnriProxyClient } from "./client/EnriProxyClient.js";
|
|
11
|
+
import { AnalyzeMediaTool } from "./tools/AnalyzeMediaTool.js";
|
|
12
|
+
import { EnriVisionServer } from "./server/EnriVisionServer.js";
|
|
13
|
+
import { packageInfoService } from "./package-info.js";
|
|
14
|
+
/**
|
|
15
|
+
* Environment variable for EnriProxy base URL.
|
|
16
|
+
*/
|
|
17
|
+
const ENRIPROXY_URL_ENV = "ENRIPROXY_URL";
|
|
18
|
+
/**
|
|
19
|
+
* Environment variable for EnriProxy API key.
|
|
20
|
+
*/
|
|
21
|
+
const ENRIPROXY_API_KEY_ENV = "ENRIPROXY_API_KEY";
|
|
22
|
+
/**
|
|
23
|
+
* Environment variable for default request timeout in milliseconds.
|
|
24
|
+
*/
|
|
25
|
+
const ENRIVISION_TIMEOUT_MS_ENV = "ENRIVISION_TIMEOUT_MS";
|
|
26
|
+
/**
|
|
27
|
+
* Default EnriProxy URL used when env is not set.
|
|
28
|
+
*/
|
|
29
|
+
const DEFAULT_ENRIPROXY_URL = "http://127.0.0.1:8787";
|
|
30
|
+
/**
|
|
31
|
+
* Default request timeout in milliseconds.
|
|
32
|
+
*
|
|
33
|
+
* @remarks
|
|
34
|
+
* Uploads are performed in chunks; this timeout applies per request.
|
|
35
|
+
*/
|
|
36
|
+
const DEFAULT_TIMEOUT_MS = 30 * 60 * 1000;
|
|
37
|
+
/**
|
|
38
|
+
* Entry point for the MCP server.
|
|
39
|
+
*/
|
|
40
|
+
async function main() {
|
|
41
|
+
const args = process.argv.slice(2);
|
|
42
|
+
if (args[0] === "--help" || args[0] === "-h" || args[0] === "help") {
|
|
43
|
+
console.log("EnriVision");
|
|
44
|
+
console.log("");
|
|
45
|
+
console.log("This is an MCP server over stdio that uploads local media to EnriProxy for server-side extraction and analysis.");
|
|
46
|
+
console.log("");
|
|
47
|
+
console.log("Usage:");
|
|
48
|
+
console.log(" enrivision (start MCP server over stdio)");
|
|
49
|
+
console.log(" enrivision --version");
|
|
50
|
+
console.log(" enrivision --help");
|
|
51
|
+
console.log("");
|
|
52
|
+
console.log("Environment variables:");
|
|
53
|
+
console.log(" ENRIPROXY_URL (optional, default: http://127.0.0.1:8787)");
|
|
54
|
+
console.log(" ENRIPROXY_API_KEY (required)");
|
|
55
|
+
console.log(" ENRIVISION_TIMEOUT_MS (optional, default: 1800000)");
|
|
56
|
+
console.log(" ENRIVISION_DEFAULT_LANGUAGE (optional, e.g. es/en)");
|
|
57
|
+
process.exit(0);
|
|
58
|
+
}
|
|
59
|
+
if (args[0] === "--version" || args[0] === "-v" || args[0] === "version") {
|
|
60
|
+
console.log(packageInfoService.getVersion());
|
|
61
|
+
process.exit(0);
|
|
62
|
+
}
|
|
63
|
+
const serverUrl = (process.env[ENRIPROXY_URL_ENV] ?? DEFAULT_ENRIPROXY_URL).trim();
|
|
64
|
+
const apiKey = (process.env[ENRIPROXY_API_KEY_ENV] ?? "").trim();
|
|
65
|
+
const timeoutMsRaw = (process.env[ENRIVISION_TIMEOUT_MS_ENV] ?? "").trim();
|
|
66
|
+
const timeoutMs = timeoutMsRaw ? Number.parseInt(timeoutMsRaw, 10) : DEFAULT_TIMEOUT_MS;
|
|
67
|
+
const analyzeMediaTool = new AnalyzeMediaTool({
|
|
68
|
+
createClient: (baseUrl, key, timeout) => new EnriProxyClient({
|
|
69
|
+
baseUrl,
|
|
70
|
+
apiKey: key,
|
|
71
|
+
timeoutMs: timeout
|
|
72
|
+
}),
|
|
73
|
+
defaultServerUrl: serverUrl,
|
|
74
|
+
defaultApiKey: apiKey,
|
|
75
|
+
defaultTimeoutMs: Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : DEFAULT_TIMEOUT_MS
|
|
76
|
+
});
|
|
77
|
+
const server = new EnriVisionServer({
|
|
78
|
+
name: "EnriVision",
|
|
79
|
+
version: packageInfoService.getVersion(),
|
|
80
|
+
analyzeMediaTool
|
|
81
|
+
});
|
|
82
|
+
const transport = new StdioServerTransport();
|
|
83
|
+
await server.connect(transport);
|
|
84
|
+
console.error("[EnriVision] MCP server running on stdio");
|
|
85
|
+
}
|
|
86
|
+
void main().catch((error) => {
|
|
87
|
+
console.error("[EnriVision] FATAL:", error instanceof Error ? error.message : String(error));
|
|
88
|
+
process.exit(1);
|
|
89
|
+
});
|
|
90
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-info.d.ts","sourceRoot":"","sources":["../src/package-info.ts"],"names":[],"mappings":"AAIA,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,aAAa,CAAuB;;IAMrC,UAAU,IAAI,MAAM;CAkB5B;AAED,eAAO,MAAM,kBAAkB,EAAE,kBAA6C,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
export class PackageInfoService {
|
|
3
|
+
require;
|
|
4
|
+
cachedVersion = null;
|
|
5
|
+
constructor() {
|
|
6
|
+
this.require = createRequire(import.meta.url);
|
|
7
|
+
}
|
|
8
|
+
getVersion() {
|
|
9
|
+
if (this.cachedVersion !== null)
|
|
10
|
+
return this.cachedVersion;
|
|
11
|
+
const fallback = "0.0.0";
|
|
12
|
+
try {
|
|
13
|
+
const pkg = this.require("../package.json");
|
|
14
|
+
const version = pkg.version;
|
|
15
|
+
if (typeof version === "string" && version.trim().length > 0) {
|
|
16
|
+
this.cachedVersion = version;
|
|
17
|
+
return version;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// ignore
|
|
22
|
+
}
|
|
23
|
+
this.cachedVersion = fallback;
|
|
24
|
+
return fallback;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export const packageInfoService = new PackageInfoService();
|
|
28
|
+
//# sourceMappingURL=package-info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-info.js","sourceRoot":"","sources":["../src/package-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAI5C,MAAM,OAAO,kBAAkB;IACZ,OAAO,CAAc;IAC9B,aAAa,GAAkB,IAAI,CAAC;IAE5C;QACE,IAAI,CAAC,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChD,CAAC;IAEM,UAAU;QACf,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,aAAa,CAAC;QAE3D,MAAM,QAAQ,GAAG,OAAO,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAqB,CAAC;YAChE,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;YAC5B,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7D,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;gBAC7B,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAuB,IAAI,kBAAkB,EAAE,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ENRIVISION MCP SERVER
|
|
3
|
+
*
|
|
4
|
+
* Implements a minimal MCP server (stdio transport) exposing a single tool:
|
|
5
|
+
* `analyze_media`.
|
|
6
|
+
*
|
|
7
|
+
* @module server/EnriVisionServer
|
|
8
|
+
*/
|
|
9
|
+
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
10
|
+
import type { AnalyzeMediaTool } from "../tools/AnalyzeMediaTool.js";
|
|
11
|
+
/**
|
|
12
|
+
* Configuration for {@link EnriVisionServer}.
|
|
13
|
+
*/
|
|
14
|
+
export interface EnriVisionServerConfig {
|
|
15
|
+
/**
|
|
16
|
+
* Server name reported via MCP.
|
|
17
|
+
*/
|
|
18
|
+
readonly name: string;
|
|
19
|
+
/**
|
|
20
|
+
* Server version reported via MCP.
|
|
21
|
+
*/
|
|
22
|
+
readonly version: string;
|
|
23
|
+
/**
|
|
24
|
+
* Tool implementation for `analyze_media`.
|
|
25
|
+
*/
|
|
26
|
+
readonly analyzeMediaTool: AnalyzeMediaTool;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* MCP server exposing EnriVision tools.
|
|
30
|
+
*/
|
|
31
|
+
export declare class EnriVisionServer {
|
|
32
|
+
/**
|
|
33
|
+
* Underlying MCP server implementation.
|
|
34
|
+
*/
|
|
35
|
+
private readonly server;
|
|
36
|
+
/**
|
|
37
|
+
* Analyze media tool implementation.
|
|
38
|
+
*/
|
|
39
|
+
private readonly analyzeMediaTool;
|
|
40
|
+
/**
|
|
41
|
+
* Creates a new {@link EnriVisionServer}.
|
|
42
|
+
*
|
|
43
|
+
* @param config - Server configuration
|
|
44
|
+
*/
|
|
45
|
+
constructor(config: EnriVisionServerConfig);
|
|
46
|
+
/**
|
|
47
|
+
* Connects the server to a transport and starts listening.
|
|
48
|
+
*
|
|
49
|
+
* @param transport - MCP transport (stdio)
|
|
50
|
+
*/
|
|
51
|
+
connect(transport: Transport): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Registers tool list and tool call handlers.
|
|
54
|
+
*/
|
|
55
|
+
private registerToolHandlers;
|
|
56
|
+
/**
|
|
57
|
+
* Returns the JSON schema tool definition for `analyze_media`.
|
|
58
|
+
*
|
|
59
|
+
* @returns Tool definition
|
|
60
|
+
*/
|
|
61
|
+
private getAnalyzeMediaToolDefinition;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=EnriVisionServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnriVisionServer.d.ts","sourceRoot":"","sources":["../../src/server/EnriVisionServer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAC;AAQ/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;CAC7C;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IAEpD;;;;OAIG;gBACgB,MAAM,EAAE,sBAAsB;IAiBjD;;;;OAIG;IACU,OAAO,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzD;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAwC5B;;;;OAIG;IACH,OAAO,CAAC,6BAA6B;CA+JtC"}
|