@exponential_app/engine 0.0.0-stage → 0.1.1
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 +201 -0
- package/NOTICE +54 -0
- package/README.md +35 -2
- package/dist/capabilities.js +29 -0
- package/dist/capabilities.js.map +9 -0
- package/dist/chunks/index-3nf9f7pv.js +315 -0
- package/dist/chunks/index-3nf9f7pv.js.map +10 -0
- package/dist/chunks/index-3rgr16n2.js +443 -0
- package/dist/chunks/index-3rgr16n2.js.map +9 -0
- package/dist/chunks/index-79swfbsm.js +366 -0
- package/dist/chunks/index-79swfbsm.js.map +10 -0
- package/dist/chunks/index-knntt4cb.js +259 -0
- package/dist/chunks/index-knntt4cb.js.map +10 -0
- package/dist/chunks/index-m2845dn6.js +72 -0
- package/dist/chunks/index-m2845dn6.js.map +10 -0
- package/dist/chunks/index-pqpnz4ns.js +2213 -0
- package/dist/chunks/index-pqpnz4ns.js.map +9 -0
- package/dist/chunks/index-q4zws02e.js +2301 -0
- package/dist/chunks/index-q4zws02e.js.map +10 -0
- package/dist/chunks/index-s3xjr701.js +170 -0
- package/dist/chunks/index-s3xjr701.js.map +10 -0
- package/dist/chunks/index-sk8b0dh4.js +126 -0
- package/dist/chunks/index-sk8b0dh4.js.map +10 -0
- package/dist/chunks/index-tvsykgcv.js +3015 -0
- package/dist/chunks/index-tvsykgcv.js.map +19 -0
- package/dist/chunks/index-v0m7r4y3.js +6869 -0
- package/dist/chunks/index-v0m7r4y3.js.map +13 -0
- package/dist/consent.js +24 -0
- package/dist/consent.js.map +9 -0
- package/dist/index.js +654 -0
- package/dist/index.js.map +12 -0
- package/dist/lifecycle.js +11 -0
- package/dist/lifecycle.js.map +9 -0
- package/dist/outbox.js +27 -0
- package/dist/outbox.js.map +9 -0
- package/dist/pdf.js +15 -0
- package/dist/pdf.js.map +9 -0
- package/dist/providers.js +26 -0
- package/dist/providers.js.map +9 -0
- package/dist/runner.js +24 -0
- package/dist/runner.js.map +9 -0
- package/dist/tools.js +38 -0
- package/dist/tools.js.map +9 -0
- package/dist/types/domain-contract/src/app-records.d.ts +3148 -0
- package/dist/types/domain-contract/src/app-share.d.ts +222 -0
- package/dist/types/domain-contract/src/apps.d.ts +612 -0
- package/dist/types/eengine/fixtures/providers.json +55 -0
- package/dist/types/eengine/src/broker.d.ts +80 -0
- package/dist/types/eengine/src/capabilities.d.ts +88 -0
- package/dist/types/eengine/src/consent.d.ts +50 -0
- package/dist/types/eengine/src/index.d.ts +12 -0
- package/dist/types/eengine/src/instance.d.ts +131 -0
- package/dist/types/eengine/src/lifecycle.d.ts +64 -0
- package/dist/types/eengine/src/outbox.d.ts +3 -0
- package/dist/types/eengine/src/pdf.d.ts +36 -0
- package/dist/types/eengine/src/providers.d.ts +38 -0
- package/dist/types/eengine/src/runner.d.ts +82 -0
- package/dist/types/eengine/src/stores.d.ts +125 -0
- package/dist/types/eengine/src/synced.d.ts +59 -0
- package/dist/types/eengine/src/tools.d.ts +79 -0
- package/dist/types/eengine/src/web/index.d.ts +20 -0
- package/dist/types/eengine/src/web/mcp.d.ts +27 -0
- package/dist/types/eengine/src/web/platform.d.ts +91 -0
- package/dist/types/eengine/src/web/stores.d.ts +125 -0
- package/dist/types/emcp/fixtures/automations.json +521 -0
- package/dist/types/emcp/fixtures/hub.json +498 -0
- package/dist/types/emcp/src/access.d.ts +55 -0
- package/dist/types/emcp/src/audit.d.ts +22 -0
- package/dist/types/emcp/src/automations.d.ts +111 -0
- package/dist/types/emcp/src/exposes.d.ts +242 -0
- package/dist/types/emcp/src/hub.d.ts +63 -0
- package/dist/types/emcp/src/index.d.ts +7 -0
- package/dist/types/emcp/src/pure.d.ts +11 -0
- package/dist/types/emcp/src/upstream.d.ts +288 -0
- package/dist/types/emcp/src/vault.d.ts +34 -0
- package/dist/web/index.js +791 -0
- package/dist/web/index.js.map +13 -0
- package/fixtures/bundle.json +1165 -0
- package/fixtures/capabilities.json +434 -0
- package/fixtures/consent.json +146 -0
- package/fixtures/lifecycle.json +125 -0
- package/fixtures/outbox.json +22 -0
- package/fixtures/providers.json +55 -0
- package/fixtures/runner.json +2167 -0
- package/package.json +92 -4
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import {
|
|
2
|
+
renderPdf2
|
|
3
|
+
} from "./index-3nf9f7pv.js";
|
|
4
|
+
import {
|
|
5
|
+
capabilities_default
|
|
6
|
+
} from "./index-3rgr16n2.js";
|
|
7
|
+
|
|
8
|
+
// packages/eengine/src/tools.ts
|
|
9
|
+
var CAPABILITY_TOOLS2 = capabilities_default.tools;
|
|
10
|
+
var MIME_BY_EXTENSION2 = capabilities_default.v1.mimeByExtension;
|
|
11
|
+
var toolDef2 = (name) => CAPABILITY_TOOLS2.find((t) => t.name === name) ?? null;
|
|
12
|
+
var nativeCaller2 = (capabilities) => async (tool, args) => {
|
|
13
|
+
const at = tool.indexOf(`_`);
|
|
14
|
+
const capability = capabilities.find((c) => c.name === tool.slice(0, at));
|
|
15
|
+
if (!capability)
|
|
16
|
+
return { content: [{ type: `text`, text: `unavailable` }], isError: true };
|
|
17
|
+
return capability.call(tool.slice(at + 1), args);
|
|
18
|
+
};
|
|
19
|
+
var isObject = (v) => typeof v === `object` && v !== null && !Array.isArray(v);
|
|
20
|
+
function typeMatches(type, v) {
|
|
21
|
+
switch (type) {
|
|
22
|
+
case `object`:
|
|
23
|
+
return isObject(v);
|
|
24
|
+
case `array`:
|
|
25
|
+
return Array.isArray(v);
|
|
26
|
+
case `string`:
|
|
27
|
+
return typeof v === `string`;
|
|
28
|
+
case `boolean`:
|
|
29
|
+
return typeof v === `boolean`;
|
|
30
|
+
case `null`:
|
|
31
|
+
return v === null;
|
|
32
|
+
case `number`:
|
|
33
|
+
return typeof v === `number` && Number.isFinite(v);
|
|
34
|
+
case `integer`:
|
|
35
|
+
return typeof v === `number` && Number.isInteger(v);
|
|
36
|
+
default:
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function jsonEqual(a, b) {
|
|
41
|
+
if (a === b)
|
|
42
|
+
return true;
|
|
43
|
+
if (Array.isArray(a))
|
|
44
|
+
return Array.isArray(b) && a.length === b.length && a.every((x, i) => jsonEqual(x, b[i]));
|
|
45
|
+
if (isObject(a) && isObject(b)) {
|
|
46
|
+
const ka = Object.keys(a);
|
|
47
|
+
return ka.length === Object.keys(b).length && ka.every((k) => (k in b) && jsonEqual(a[k], b[k]));
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
var pointer = (path) => path.length ? path.map((p) => `/${p.replace(/~/g, `~0`).replace(/\//g, `~1`)}`).join(``) : `/`;
|
|
52
|
+
var DATE_TIME = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(\.\d+)?([Zz]|[+-](\d{2}):(\d{2}))$/;
|
|
53
|
+
var TOKEN = /^[A-Za-z0-9._-]{1,64}$/;
|
|
54
|
+
var BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
55
|
+
function dateTimeValid(s) {
|
|
56
|
+
const m = DATE_TIME.exec(s);
|
|
57
|
+
if (!m)
|
|
58
|
+
return false;
|
|
59
|
+
const [mo, d, h, mi, se] = [m[2], m[3], m[4], m[5], m[6]].map(Number);
|
|
60
|
+
if (mo < 1 || mo > 12 || d < 1 || d > 31 || h > 23 || mi > 59 || se > 60)
|
|
61
|
+
return false;
|
|
62
|
+
if (m[9] !== undefined && (Number(m[9]) > 23 || Number(m[10]) > 59))
|
|
63
|
+
return false;
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
function uriValid(s) {
|
|
67
|
+
if (!/^https?:\/\/[^\s]+$/i.test(s) || /[\u0000-\u001f\u007f]/.test(s))
|
|
68
|
+
return false;
|
|
69
|
+
try {
|
|
70
|
+
const url = new URL(s);
|
|
71
|
+
return (url.protocol === `http:` || url.protocol === `https:`) && url.hostname !== ``;
|
|
72
|
+
} catch {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function formatValid(format, s) {
|
|
77
|
+
switch (format) {
|
|
78
|
+
case `date-time`:
|
|
79
|
+
return dateTimeValid(s);
|
|
80
|
+
case `token`:
|
|
81
|
+
return TOKEN.test(s);
|
|
82
|
+
case `uri`:
|
|
83
|
+
return uriValid(s);
|
|
84
|
+
case `base64`:
|
|
85
|
+
return base64Decode2(s) !== null;
|
|
86
|
+
default:
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function schemaViolation2(schema, value, path = []) {
|
|
91
|
+
const at = (keyword, p = path) => `${pointer(p)} ${keyword}`;
|
|
92
|
+
if (schema.type !== undefined) {
|
|
93
|
+
const types = Array.isArray(schema.type) ? schema.type : [schema.type];
|
|
94
|
+
if (!types.some((t) => typeMatches(t, value)))
|
|
95
|
+
return at(`type`);
|
|
96
|
+
}
|
|
97
|
+
if (isObject(value)) {
|
|
98
|
+
const properties = schema.properties ?? {};
|
|
99
|
+
for (const key of schema.required ?? [])
|
|
100
|
+
if (!(key in value))
|
|
101
|
+
return at(`required`, [...path, key]);
|
|
102
|
+
if (schema.additionalProperties === false) {
|
|
103
|
+
const unknown = Object.keys(value).filter((k) => !(k in properties)).sort();
|
|
104
|
+
if (unknown.length)
|
|
105
|
+
return at(`additionalProperties`, [...path, unknown[0]]);
|
|
106
|
+
}
|
|
107
|
+
for (const [key, sub] of Object.entries(properties)) {
|
|
108
|
+
if (!(key in value))
|
|
109
|
+
continue;
|
|
110
|
+
const v = schemaViolation2(sub, value[key], [...path, key]);
|
|
111
|
+
if (v)
|
|
112
|
+
return v;
|
|
113
|
+
}
|
|
114
|
+
for (const [key, needs] of Object.entries(schema.dependentRequired ?? {})) {
|
|
115
|
+
if (!(key in value))
|
|
116
|
+
continue;
|
|
117
|
+
for (const need of needs)
|
|
118
|
+
if (!(need in value))
|
|
119
|
+
return at(`dependentRequired`, [...path, need]);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (schema.anyOf && !schema.anyOf.some((s) => schemaViolation2(s, value, path) === null))
|
|
123
|
+
return at(`anyOf`);
|
|
124
|
+
if (schema.oneOf && schema.oneOf.filter((s) => schemaViolation2(s, value, path) === null).length !== 1)
|
|
125
|
+
return at(`oneOf`);
|
|
126
|
+
if (Array.isArray(value)) {
|
|
127
|
+
if (typeof schema.minItems === `number` && value.length < schema.minItems)
|
|
128
|
+
return at(`minItems`);
|
|
129
|
+
if (typeof schema.maxItems === `number` && value.length > schema.maxItems)
|
|
130
|
+
return at(`maxItems`);
|
|
131
|
+
if (schema.items) {
|
|
132
|
+
for (let i = 0;i < value.length; i++) {
|
|
133
|
+
const v = schemaViolation2(schema.items, value[i], [...path, String(i)]);
|
|
134
|
+
if (v)
|
|
135
|
+
return v;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (typeof value === `number`) {
|
|
140
|
+
if (typeof schema.minimum === `number` && value < schema.minimum)
|
|
141
|
+
return at(`minimum`);
|
|
142
|
+
if (typeof schema.maximum === `number` && value > schema.maximum)
|
|
143
|
+
return at(`maximum`);
|
|
144
|
+
}
|
|
145
|
+
if (typeof value === `string`) {
|
|
146
|
+
const length = [...value].length;
|
|
147
|
+
if (typeof schema.minLength === `number` && length < schema.minLength)
|
|
148
|
+
return at(`minLength`);
|
|
149
|
+
if (typeof schema.maxLength === `number` && length > schema.maxLength)
|
|
150
|
+
return at(`maxLength`);
|
|
151
|
+
}
|
|
152
|
+
if (schema.enum && !schema.enum.some((e) => jsonEqual(e, value)))
|
|
153
|
+
return at(`enum`);
|
|
154
|
+
if (typeof value === `string` && typeof schema.format === `string` && !formatValid(schema.format, value))
|
|
155
|
+
return at(`format`);
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
function validateToolArguments2(tool, args) {
|
|
159
|
+
const def = toolDef2(tool);
|
|
160
|
+
if (!def)
|
|
161
|
+
return { error: `unknownTool` };
|
|
162
|
+
const violation = schemaViolation2(def.inputSchema, args);
|
|
163
|
+
if (violation)
|
|
164
|
+
return { error: `invalidParams: ${violation}` };
|
|
165
|
+
const out = { ...args };
|
|
166
|
+
for (const [key, sub] of Object.entries(def.inputSchema.properties ?? {})) {
|
|
167
|
+
if (!(key in out) && `default` in sub)
|
|
168
|
+
out[key] = structuredClone(sub.default);
|
|
169
|
+
}
|
|
170
|
+
return { arguments: out };
|
|
171
|
+
}
|
|
172
|
+
var B64 = `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`;
|
|
173
|
+
function base64Encode2(bytes) {
|
|
174
|
+
let out = ``;
|
|
175
|
+
for (let i = 0;i < bytes.length; i += 3) {
|
|
176
|
+
const n = bytes[i] << 16 | (bytes[i + 1] ?? 0) << 8 | (bytes[i + 2] ?? 0);
|
|
177
|
+
out += B64[n >> 18 & 63] + B64[n >> 12 & 63];
|
|
178
|
+
out += i + 1 < bytes.length ? B64[n >> 6 & 63] : `=`;
|
|
179
|
+
out += i + 2 < bytes.length ? B64[n & 63] : `=`;
|
|
180
|
+
}
|
|
181
|
+
return out;
|
|
182
|
+
}
|
|
183
|
+
function base64Decode2(s) {
|
|
184
|
+
if (!BASE64.test(s))
|
|
185
|
+
return null;
|
|
186
|
+
const pad = s.endsWith(`==`) ? 2 : s.endsWith(`=`) ? 1 : 0;
|
|
187
|
+
const out = new Uint8Array(s.length / 4 * 3 - pad);
|
|
188
|
+
let o = 0;
|
|
189
|
+
for (let i = 0;i < s.length; i += 4) {
|
|
190
|
+
const c = [0, 1, 2, 3].map((k) => s[i + k] === `=` ? 0 : B64.indexOf(s[i + k]));
|
|
191
|
+
const n = c[0] << 18 | c[1] << 12 | c[2] << 6 | c[3];
|
|
192
|
+
const last = i + 4 === s.length;
|
|
193
|
+
if (last && pad === 2 && (n & 65535) !== 0)
|
|
194
|
+
return null;
|
|
195
|
+
if (last && pad === 1 && (n & 255) !== 0)
|
|
196
|
+
return null;
|
|
197
|
+
out[o++] = n >> 16 & 255;
|
|
198
|
+
if (o < out.length)
|
|
199
|
+
out[o++] = n >> 8 & 255;
|
|
200
|
+
if (o < out.length)
|
|
201
|
+
out[o++] = n & 255;
|
|
202
|
+
}
|
|
203
|
+
return out;
|
|
204
|
+
}
|
|
205
|
+
var startsWith = (bytes, prefix) => prefix.every((b, i) => bytes[i] === b);
|
|
206
|
+
var PNG_SIGNATURE = [137, 80, 78, 71, 13, 10, 26, 10];
|
|
207
|
+
function sniffMime2(bytes) {
|
|
208
|
+
if (startsWith(bytes, [37, 80, 68, 70, 45]))
|
|
209
|
+
return `application/pdf`;
|
|
210
|
+
if (startsWith(bytes, [255, 216, 255]))
|
|
211
|
+
return `image/jpeg`;
|
|
212
|
+
if (startsWith(bytes, PNG_SIGNATURE))
|
|
213
|
+
return `image/png`;
|
|
214
|
+
if (startsWith(bytes, [71, 73, 70, 56]))
|
|
215
|
+
return `image/gif`;
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
function mimeFor2(name, bytes, given, isText) {
|
|
219
|
+
if (given)
|
|
220
|
+
return given;
|
|
221
|
+
const dot = name.lastIndexOf(`.`);
|
|
222
|
+
const ext = dot >= 0 ? name.slice(dot + 1).toLowerCase() : ``;
|
|
223
|
+
if (ext && Object.hasOwn(MIME_BY_EXTENSION2, ext))
|
|
224
|
+
return MIME_BY_EXTENSION2[ext];
|
|
225
|
+
return sniffMime2(bytes) ?? (isText ? `text/plain` : `application/octet-stream`);
|
|
226
|
+
}
|
|
227
|
+
function newNotificationId2() {
|
|
228
|
+
const bytes = new Uint8Array(16);
|
|
229
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
230
|
+
return `n-${[...bytes].map((b) => b.toString(16).padStart(2, `0`)).join(``)}`;
|
|
231
|
+
}
|
|
232
|
+
var toolResult2 = (structuredContent) => ({ content: [{ type: `text`, text: JSON.stringify(structuredContent) }], structuredContent });
|
|
233
|
+
var toolError2 = (text) => ({ content: [{ type: `text`, text }], isError: true });
|
|
234
|
+
|
|
235
|
+
class BridgeError extends Error {
|
|
236
|
+
reason;
|
|
237
|
+
outcome;
|
|
238
|
+
constructor(reason, outcome) {
|
|
239
|
+
super(reason);
|
|
240
|
+
this.reason = reason;
|
|
241
|
+
this.outcome = outcome;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
var utf8 = (s) => new TextEncoder().encode(s);
|
|
245
|
+
async function appFile(input, id) {
|
|
246
|
+
const bytes = await input.blobs.get(input.context.app, id);
|
|
247
|
+
if (!bytes)
|
|
248
|
+
throw new BridgeError(`notFound: ${id}`, `isError`);
|
|
249
|
+
return bytes;
|
|
250
|
+
}
|
|
251
|
+
async function nativeArguments(input, args) {
|
|
252
|
+
const { app } = input.context;
|
|
253
|
+
switch (input.tool) {
|
|
254
|
+
case `files_save`: {
|
|
255
|
+
const name = args.name;
|
|
256
|
+
const isText = typeof args.text === `string`;
|
|
257
|
+
const bytes = isText ? utf8(args.text) : await appFile(input, args.fileId);
|
|
258
|
+
return { name, mimeType: mimeFor2(name, bytes, args.mimeType, isText), data: base64Encode2(bytes) };
|
|
259
|
+
}
|
|
260
|
+
case `share_send`: {
|
|
261
|
+
const out = {};
|
|
262
|
+
for (const key of [`title`, `text`, `url`])
|
|
263
|
+
if (key in args)
|
|
264
|
+
out[key] = args[key];
|
|
265
|
+
if (typeof args.fileId === `string`) {
|
|
266
|
+
const bytes = await appFile(input, args.fileId);
|
|
267
|
+
const name = args.name;
|
|
268
|
+
out.file = { name, mimeType: mimeFor2(name, bytes, args.mimeType, false), data: base64Encode2(bytes) };
|
|
269
|
+
}
|
|
270
|
+
return out;
|
|
271
|
+
}
|
|
272
|
+
case `print_print`: {
|
|
273
|
+
const bytes = await appFile(input, args.fileId);
|
|
274
|
+
const mimeType = sniffMime2(bytes);
|
|
275
|
+
const ext = mimeType === `application/pdf` ? `pdf` : mimeType === `image/png` ? `png` : mimeType === `image/jpeg` ? `jpg` : null;
|
|
276
|
+
if (!ext)
|
|
277
|
+
throw new BridgeError(`unsupportedFile`, `isError`);
|
|
278
|
+
return { name: args.name ?? `document.${ext}`, mimeType, data: base64Encode2(bytes) };
|
|
279
|
+
}
|
|
280
|
+
case `notifications_post`: {
|
|
281
|
+
const screen = args.screen;
|
|
282
|
+
if (screen !== undefined && !input.context.screens.includes(screen))
|
|
283
|
+
throw new BridgeError(`invalidParams: /screen enum`, `invalidParams`);
|
|
284
|
+
return {
|
|
285
|
+
id: `${app}/${args.id}`,
|
|
286
|
+
title: args.title,
|
|
287
|
+
body: args.body ?? null,
|
|
288
|
+
at: args.at ?? null,
|
|
289
|
+
tap: screen === undefined ? null : { type: `notificationTap`, app, screen, params: args.params ?? {} }
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
case `notifications_cancel`:
|
|
293
|
+
return { id: `${app}/${args.id}` };
|
|
294
|
+
default:
|
|
295
|
+
return args;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
async function storeFiles(input, value) {
|
|
299
|
+
if (Array.isArray(value)) {
|
|
300
|
+
const out = [];
|
|
301
|
+
for (const item of value)
|
|
302
|
+
out.push(await storeFiles(input, item));
|
|
303
|
+
return out;
|
|
304
|
+
}
|
|
305
|
+
if (!isObject(value))
|
|
306
|
+
return value;
|
|
307
|
+
let out = {};
|
|
308
|
+
let bytes = null;
|
|
309
|
+
if (typeof value.data === `string`) {
|
|
310
|
+
bytes = base64Decode2(value.data);
|
|
311
|
+
if (!bytes)
|
|
312
|
+
throw new BridgeError(`badResult: data format`, `isError`);
|
|
313
|
+
}
|
|
314
|
+
const fileId = bytes ? await input.blobs.put(input.context.app, value.name, value.mimeType, bytes) : null;
|
|
315
|
+
for (const [key, v] of Object.entries(value))
|
|
316
|
+
if (!(bytes && key === `data`))
|
|
317
|
+
out[key] = await storeFiles(input, v);
|
|
318
|
+
if (bytes)
|
|
319
|
+
out = { ...out, size: bytes.length, fileId };
|
|
320
|
+
return out;
|
|
321
|
+
}
|
|
322
|
+
async function bridgeCall2(input) {
|
|
323
|
+
const validated = validateToolArguments2(input.tool, input.arguments);
|
|
324
|
+
if (`error` in validated)
|
|
325
|
+
return { result: toolError2(validated.error), outcome: validated.error === `unknownTool` ? `unknown` : `invalidParams` };
|
|
326
|
+
const def = toolDef2(input.tool);
|
|
327
|
+
const args = validated.arguments;
|
|
328
|
+
try {
|
|
329
|
+
if (input.tool === `print_pdf`) {
|
|
330
|
+
const rendered = await renderPdf2(args, (id) => input.blobs.get(input.context.app, id));
|
|
331
|
+
if (`error` in rendered)
|
|
332
|
+
return { result: toolError2(rendered.error), outcome: `isError` };
|
|
333
|
+
const name = args.name ?? pdfFileName2(args.title);
|
|
334
|
+
const fileId = await input.blobs.put(input.context.app, name, `application/pdf`, rendered.bytes);
|
|
335
|
+
return { result: toolResult2({ file: { name, mimeType: `application/pdf`, size: rendered.bytes.length, fileId }, pages: rendered.pages }), outcome: `ok` };
|
|
336
|
+
}
|
|
337
|
+
if (input.tool === `notifications_post` && args.id === undefined)
|
|
338
|
+
args.id = (input.newId ?? newNotificationId2)();
|
|
339
|
+
const nativeArgs = await nativeArguments(input, args);
|
|
340
|
+
let answer;
|
|
341
|
+
try {
|
|
342
|
+
answer = await input.native(input.tool, nativeArgs);
|
|
343
|
+
} catch (error) {
|
|
344
|
+
return { result: toolError2(`nativeFailed: ${error instanceof Error ? error.message : String(error)}`), outcome: `rpcError` };
|
|
345
|
+
}
|
|
346
|
+
if (isObject(answer) && answer.isError === true)
|
|
347
|
+
return { result: answer, outcome: `isError` };
|
|
348
|
+
const structured = isObject(answer) ? answer.structuredContent : undefined;
|
|
349
|
+
const violation = schemaViolation2(def.nativeOutputSchema, structured);
|
|
350
|
+
if (violation)
|
|
351
|
+
return { result: toolError2(`badResult: ${violation}`), outcome: `isError` };
|
|
352
|
+
if (input.tool === `notifications_post`)
|
|
353
|
+
return { result: toolResult2({ id: args.id }), outcome: `ok` };
|
|
354
|
+
return { result: toolResult2(await storeFiles(input, structured)), outcome: `ok` };
|
|
355
|
+
} catch (error) {
|
|
356
|
+
if (error instanceof BridgeError)
|
|
357
|
+
return { result: toolError2(error.reason), outcome: error.outcome };
|
|
358
|
+
throw error;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
var pdfFileName2 = (title) => `${title.replace(/[/\\:*?"<>|\u0000-\u001f\u007f-\u009f]/g, `-`)}.pdf`;
|
|
362
|
+
|
|
363
|
+
export { CAPABILITY_TOOLS2, MIME_BY_EXTENSION2, toolDef2, nativeCaller2, schemaViolation2, validateToolArguments2, base64Encode2, base64Decode2, sniffMime2, mimeFor2, newNotificationId2, toolResult2, toolError2, bridgeCall2, pdfFileName2 };
|
|
364
|
+
|
|
365
|
+
//# debugId=EC2CD4A2199C0CA164756E2164756E21
|
|
366
|
+
//# sourceMappingURL=index-79swfbsm.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../packages/eengine/src/tools.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"// VAPP-265: capabilities v1. The tools' schemas, the JSON-schema subset that\n// checks them, and THE BRIDGE between the broker's `call` verdict and a host's\n// native provider (the same for app UI and agents). Pure and browser-safe;\n// locked by `fixtures/capabilities.json` (`tools`, `validateCases`, `bridgeCases`).\n\nimport type { HubOutcome } from \"@exp/emcp\"\n\nimport fixture from \"../fixtures/capabilities.json\" with { type: \"json\" }\nimport { renderPdf } from \"./pdf\"\n\nexport type JsonSchema = Record<string, unknown>\n\nexport interface CapabilityTool {\n name: string\n runs: `native` | `engine`\n description: string\n inputSchema: JsonSchema\n nativeOutputSchema: JsonSchema | null\n outputSchema: JsonSchema\n}\n\nexport const CAPABILITY_TOOLS = fixture.tools as unknown as readonly CapabilityTool[]\nexport const MIME_BY_EXTENSION: Readonly<Record<string, string>> = fixture.v1.mimeByExtension\n\nexport const toolDef = (name: string): CapabilityTool | null => CAPABILITY_TOOLS.find((t) => t.name === name) ?? null\n\n/** A host's native provider of one capability (`name`, like the crate's\n * `Capability`); `call` gets the bare tool (`pick`) and the mapped native\n * arguments, and answers an MCP call result (`structuredContent` per\n * `nativeOutputSchema`, or `isError`). */\nexport interface NativeCapability {\n name: string\n call(tool: string, args: Record<string, unknown>): Promise<unknown>\n}\n\n/** `bridgeCall`'s `native` over a host's capabilities: `photos_pick` → the\n * `photos` provider's `pick`; a capability the host lacks answers `unavailable`. */\nexport const nativeCaller =\n (capabilities: readonly NativeCapability[]) =>\n async (tool: string, args: Record<string, unknown>): Promise<unknown> => {\n const at = tool.indexOf(`_`)\n const capability = capabilities.find((c) => c.name === tool.slice(0, at))\n if (!capability) return { content: [{ type: `text`, text: `unavailable` }], isError: true }\n return capability.call(tool.slice(at + 1), args)\n }\n\n// ---------------------------------------------------------------------------\n// The schema subset\n\nconst isObject = (v: unknown): v is Record<string, unknown> => typeof v === `object` && v !== null && !Array.isArray(v)\n\nfunction typeMatches(type: string, v: unknown): boolean {\n switch (type) {\n case `object`:\n return isObject(v)\n case `array`:\n return Array.isArray(v)\n case `string`:\n return typeof v === `string`\n case `boolean`:\n return typeof v === `boolean`\n case `null`:\n return v === null\n case `number`:\n return typeof v === `number` && Number.isFinite(v)\n case `integer`:\n return typeof v === `number` && Number.isInteger(v)\n default:\n return false\n }\n}\n\nfunction jsonEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (Array.isArray(a)) return Array.isArray(b) && a.length === b.length && a.every((x, i) => jsonEqual(x, b[i]))\n if (isObject(a) && isObject(b)) {\n const ka = Object.keys(a)\n return ka.length === Object.keys(b).length && ka.every((k) => k in b && jsonEqual(a[k], b[k]))\n }\n return false\n}\n\nconst pointer = (path: readonly string[]): string => (path.length ? path.map((p) => `/${p.replace(/~/g, `~0`).replace(/\\//g, `~1`)}`).join(``) : `/`)\n\nconst DATE_TIME = /^(\\d{4})-(\\d{2})-(\\d{2})[Tt](\\d{2}):(\\d{2}):(\\d{2})(\\.\\d+)?([Zz]|[+-](\\d{2}):(\\d{2}))$/\nconst TOKEN = /^[A-Za-z0-9._-]{1,64}$/\nconst BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/\n\nfunction dateTimeValid(s: string): boolean {\n const m = DATE_TIME.exec(s)\n if (!m) return false\n const [mo, d, h, mi, se] = [m[2], m[3], m[4], m[5], m[6]].map(Number)\n if (mo < 1 || mo > 12 || d < 1 || d > 31 || h > 23 || mi > 59 || se > 60) return false\n if (m[9] !== undefined && (Number(m[9]) > 23 || Number(m[10]) > 59)) return false\n return true\n}\n\nfunction uriValid(s: string): boolean {\n if (!/^https?:\\/\\/[^\\s]+$/i.test(s) || /[\\u0000-\\u001f\\u007f]/.test(s)) return false\n try {\n const url = new URL(s)\n return (url.protocol === `http:` || url.protocol === `https:`) && url.hostname !== ``\n } catch {\n return false\n }\n}\n\nfunction formatValid(format: string, s: string): boolean {\n switch (format) {\n case `date-time`:\n return dateTimeValid(s)\n case `token`:\n return TOKEN.test(s)\n case `uri`:\n return uriValid(s)\n case `base64`:\n return base64Decode(s) !== null\n default:\n return true\n }\n}\n\n/** The first violation of `value` against `schema` as `<pointer> <keyword>`, or null. */\nexport function schemaViolation(schema: JsonSchema, value: unknown, path: readonly string[] = []): string | null {\n const at = (keyword: string, p: readonly string[] = path) => `${pointer(p)} ${keyword}`\n if (schema.type !== undefined) {\n const types = Array.isArray(schema.type) ? (schema.type as string[]) : [schema.type as string]\n if (!types.some((t) => typeMatches(t, value))) return at(`type`)\n }\n if (isObject(value)) {\n const properties = (schema.properties ?? {}) as Record<string, JsonSchema>\n for (const key of (schema.required ?? []) as string[]) if (!(key in value)) return at(`required`, [...path, key])\n if (schema.additionalProperties === false) {\n const unknown = Object.keys(value).filter((k) => !(k in properties)).sort()\n if (unknown.length) return at(`additionalProperties`, [...path, unknown[0]])\n }\n for (const [key, sub] of Object.entries(properties)) {\n if (!(key in value)) continue\n const v = schemaViolation(sub, value[key], [...path, key])\n if (v) return v\n }\n for (const [key, needs] of Object.entries((schema.dependentRequired ?? {}) as Record<string, string[]>)) {\n if (!(key in value)) continue\n for (const need of needs) if (!(need in value)) return at(`dependentRequired`, [...path, need])\n }\n }\n if (schema.anyOf && !(schema.anyOf as JsonSchema[]).some((s) => schemaViolation(s, value, path) === null)) return at(`anyOf`)\n if (schema.oneOf && (schema.oneOf as JsonSchema[]).filter((s) => schemaViolation(s, value, path) === null).length !== 1) return at(`oneOf`)\n if (Array.isArray(value)) {\n if (typeof schema.minItems === `number` && value.length < schema.minItems) return at(`minItems`)\n if (typeof schema.maxItems === `number` && value.length > schema.maxItems) return at(`maxItems`)\n if (schema.items) {\n for (let i = 0; i < value.length; i++) {\n const v = schemaViolation(schema.items as JsonSchema, value[i], [...path, String(i)])\n if (v) return v\n }\n }\n }\n if (typeof value === `number`) {\n if (typeof schema.minimum === `number` && value < schema.minimum) return at(`minimum`)\n if (typeof schema.maximum === `number` && value > schema.maximum) return at(`maximum`)\n }\n if (typeof value === `string`) {\n const length = [...value].length\n if (typeof schema.minLength === `number` && length < schema.minLength) return at(`minLength`)\n if (typeof schema.maxLength === `number` && length > schema.maxLength) return at(`maxLength`)\n }\n if (schema.enum && !(schema.enum as unknown[]).some((e) => jsonEqual(e, value))) return at(`enum`)\n if (typeof value === `string` && typeof schema.format === `string` && !formatValid(schema.format, value)) return at(`format`)\n return null\n}\n\nexport type ValidateResult = { arguments: Record<string, unknown> } | { error: string }\n\n/** A call's arguments against the tool's `inputSchema`; a missing top-level\n * property with a `default` gets it. */\nexport function validateToolArguments(tool: string, args: unknown): ValidateResult {\n const def = toolDef(tool)\n if (!def) return { error: `unknownTool` }\n const violation = schemaViolation(def.inputSchema, args)\n if (violation) return { error: `invalidParams: ${violation}` }\n const out: Record<string, unknown> = { ...(args as Record<string, unknown>) }\n for (const [key, sub] of Object.entries((def.inputSchema.properties ?? {}) as Record<string, JsonSchema>)) {\n if (!(key in out) && `default` in sub) out[key] = structuredClone(sub.default)\n }\n return { arguments: out }\n}\n\n// ---------------------------------------------------------------------------\n// Bytes\n\nconst B64 = `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`\n\nexport function base64Encode(bytes: Uint8Array): string {\n let out = ``\n for (let i = 0; i < bytes.length; i += 3) {\n const n = (bytes[i] << 16) | ((bytes[i + 1] ?? 0) << 8) | (bytes[i + 2] ?? 0)\n out += B64[(n >> 18) & 63] + B64[(n >> 12) & 63]\n out += i + 1 < bytes.length ? B64[(n >> 6) & 63] : `=`\n out += i + 2 < bytes.length ? B64[n & 63] : `=`\n }\n return out\n}\n\n/** Strict: the standard alphabet, padded, no whitespace, zero trailing bits; null otherwise. */\nexport function base64Decode(s: string): Uint8Array | null {\n if (!BASE64.test(s)) return null\n const pad = s.endsWith(`==`) ? 2 : s.endsWith(`=`) ? 1 : 0\n const out = new Uint8Array((s.length / 4) * 3 - pad)\n let o = 0\n for (let i = 0; i < s.length; i += 4) {\n const c = [0, 1, 2, 3].map((k) => (s[i + k] === `=` ? 0 : B64.indexOf(s[i + k])))\n const n = (c[0] << 18) | (c[1] << 12) | (c[2] << 6) | c[3]\n const last = i + 4 === s.length\n if (last && pad === 2 && (n & 0xffff) !== 0) return null\n if (last && pad === 1 && (n & 0xff) !== 0) return null\n out[o++] = (n >> 16) & 255\n if (o < out.length) out[o++] = (n >> 8) & 255\n if (o < out.length) out[o++] = n & 255\n }\n return out\n}\n\nconst startsWith = (bytes: Uint8Array, prefix: readonly number[]) => prefix.every((b, i) => bytes[i] === b)\nconst PNG_SIGNATURE = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a] as const\n\n/** The type the bytes tell (PDF, JPEG, PNG, GIF), or null. */\nexport function sniffMime(bytes: Uint8Array): string | null {\n if (startsWith(bytes, [0x25, 0x50, 0x44, 0x46, 0x2d])) return `application/pdf`\n if (startsWith(bytes, [0xff, 0xd8, 0xff])) return `image/jpeg`\n if (startsWith(bytes, PNG_SIGNATURE)) return `image/png`\n if (startsWith(bytes, [0x47, 0x49, 0x46, 0x38])) return `image/gif`\n return null\n}\n\n/** A file's MIME type: the given one, else its name's extension, else its bytes,\n * else text/plain for a text and application/octet-stream. */\nexport function mimeFor(name: string, bytes: Uint8Array, given: string | null | undefined, isText: boolean): string {\n if (given) return given\n const dot = name.lastIndexOf(`.`)\n const ext = dot >= 0 ? name.slice(dot + 1).toLowerCase() : ``\n if (ext && Object.hasOwn(MIME_BY_EXTENSION, ext)) return MIME_BY_EXTENSION[ext]\n return sniffMime(bytes) ?? (isText ? `text/plain` : `application/octet-stream`)\n}\n\n/** A notification id the app did not name: `n-` + 32 lowercase hex. */\nexport function newNotificationId(): string {\n const bytes = new Uint8Array(16)\n globalThis.crypto.getRandomValues(bytes)\n return `n-${[...bytes].map((b) => b.toString(16).padStart(2, `0`)).join(``)}`\n}\n\n// ---------------------------------------------------------------------------\n// The bridge\n\nexport interface BlobStore {\n get(app: string, id: string): Promise<Uint8Array | null>\n /** Stores the bytes as an app file; answers its id. */\n put(app: string, name: string, mimeType: string, bytes: Uint8Array): Promise<string>\n}\n\nexport interface BridgeContext {\n app: string\n screens: readonly string[]\n}\n\nexport interface McpCallResult {\n content: { type: `text`; text: string }[]\n structuredContent?: unknown\n isError?: true\n}\n\nexport interface BridgeInput {\n tool: string\n arguments: unknown\n context: BridgeContext\n blobs: BlobStore\n native: (tool: string, args: Record<string, unknown>) => Promise<unknown>\n newId?: () => string\n}\n\nexport interface BridgeOutput {\n result: McpCallResult\n outcome: HubOutcome\n}\n\nexport const toolResult = (structuredContent: unknown): McpCallResult => ({ content: [{ type: `text`, text: JSON.stringify(structuredContent) }], structuredContent })\nexport const toolError = (text: string): McpCallResult => ({ content: [{ type: `text`, text }], isError: true })\n\nclass BridgeError extends Error {\n constructor(\n readonly reason: string,\n readonly outcome: HubOutcome,\n ) {\n super(reason)\n }\n}\n\nconst utf8 = (s: string) => new TextEncoder().encode(s)\n\nasync function appFile(input: BridgeInput, id: string): Promise<Uint8Array> {\n const bytes = await input.blobs.get(input.context.app, id)\n if (!bytes) throw new BridgeError(`notFound: ${id}`, `isError`)\n return bytes\n}\n\n/** The validated arguments → the native's arguments. */\nasync function nativeArguments(input: BridgeInput, args: Record<string, unknown>): Promise<Record<string, unknown>> {\n const { app } = input.context\n switch (input.tool) {\n case `files_save`: {\n const name = args.name as string\n const isText = typeof args.text === `string`\n const bytes = isText ? utf8(args.text as string) : await appFile(input, args.fileId as string)\n return { name, mimeType: mimeFor(name, bytes, args.mimeType as string | undefined, isText), data: base64Encode(bytes) }\n }\n case `share_send`: {\n const out: Record<string, unknown> = {}\n for (const key of [`title`, `text`, `url`]) if (key in args) out[key] = args[key]\n if (typeof args.fileId === `string`) {\n const bytes = await appFile(input, args.fileId)\n const name = args.name as string\n out.file = { name, mimeType: mimeFor(name, bytes, args.mimeType as string | undefined, false), data: base64Encode(bytes) }\n }\n return out\n }\n case `print_print`: {\n const bytes = await appFile(input, args.fileId as string)\n const mimeType = sniffMime(bytes)\n const ext = mimeType === `application/pdf` ? `pdf` : mimeType === `image/png` ? `png` : mimeType === `image/jpeg` ? `jpg` : null\n if (!ext) throw new BridgeError(`unsupportedFile`, `isError`)\n return { name: (args.name as string | undefined) ?? `document.${ext}`, mimeType, data: base64Encode(bytes) }\n }\n case `notifications_post`: {\n const screen = args.screen as string | undefined\n if (screen !== undefined && !input.context.screens.includes(screen)) throw new BridgeError(`invalidParams: /screen enum`, `invalidParams`)\n return {\n id: `${app}/${args.id as string}`,\n title: args.title,\n body: args.body ?? null,\n at: args.at ?? null,\n tap: screen === undefined ? null : { type: `notificationTap`, app, screen, params: args.params ?? {} },\n }\n }\n case `notifications_cancel`:\n return { id: `${app}/${args.id as string}` }\n default:\n return args\n }\n}\n\n/** Stores every object carrying `data` (depth first, in order): it loses `data`, gains `size` and `fileId`. */\nasync function storeFiles(input: BridgeInput, value: unknown): Promise<unknown> {\n if (Array.isArray(value)) {\n const out: unknown[] = []\n for (const item of value) out.push(await storeFiles(input, item))\n return out\n }\n if (!isObject(value)) return value\n let out: Record<string, unknown> = {}\n let bytes: Uint8Array | null = null\n if (typeof value.data === `string`) {\n bytes = base64Decode(value.data)\n if (!bytes) throw new BridgeError(`badResult: data format`, `isError`)\n }\n const fileId = bytes ? await input.blobs.put(input.context.app, value.name as string, value.mimeType as string, bytes) : null\n for (const [key, v] of Object.entries(value)) if (!(bytes && key === `data`)) out[key] = await storeFiles(input, v)\n if (bytes) out = { ...out, size: bytes.length, fileId }\n return out\n}\n\n/** One capability call from the broker's `call` verdict to its answer. */\nexport async function bridgeCall(input: BridgeInput): Promise<BridgeOutput> {\n const validated = validateToolArguments(input.tool, input.arguments)\n if (`error` in validated) return { result: toolError(validated.error), outcome: validated.error === `unknownTool` ? `unknown` : `invalidParams` }\n const def = toolDef(input.tool) as CapabilityTool\n const args = validated.arguments\n try {\n if (input.tool === `print_pdf`) {\n const rendered = await renderPdf(args as never, (id) => input.blobs.get(input.context.app, id))\n if (`error` in rendered) return { result: toolError(rendered.error), outcome: `isError` }\n const name = (args.name as string | undefined) ?? pdfFileName(args.title as string)\n const fileId = await input.blobs.put(input.context.app, name, `application/pdf`, rendered.bytes)\n return { result: toolResult({ file: { name, mimeType: `application/pdf`, size: rendered.bytes.length, fileId }, pages: rendered.pages }), outcome: `ok` }\n }\n if (input.tool === `notifications_post` && args.id === undefined) args.id = (input.newId ?? newNotificationId)()\n const nativeArgs = await nativeArguments(input, args)\n let answer: unknown\n try {\n answer = await input.native(input.tool, nativeArgs)\n } catch (error) {\n return { result: toolError(`nativeFailed: ${error instanceof Error ? error.message : String(error)}`), outcome: `rpcError` }\n }\n if (isObject(answer) && answer.isError === true) return { result: answer as unknown as McpCallResult, outcome: `isError` }\n const structured = isObject(answer) ? answer.structuredContent : undefined\n const violation = schemaViolation(def.nativeOutputSchema as JsonSchema, structured)\n if (violation) return { result: toolError(`badResult: ${violation}`), outcome: `isError` }\n if (input.tool === `notifications_post`) return { result: toolResult({ id: args.id }), outcome: `ok` }\n return { result: toolResult(await storeFiles(input, structured)), outcome: `ok` }\n } catch (error) {\n if (error instanceof BridgeError) return { result: toolError(error.reason), outcome: error.outcome }\n throw error\n }\n}\n\n/** print.pdf's default file name: the title with `/\\:*?\"<>|` and controls as `-`, + `.pdf`. */\nexport const pdfFileName = (title: string): string => `${title.replace(/[/\\\\:*?\"<>|\\u0000-\\u001f\\u007f-\\u009f]/g, `-`)}.pdf`\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;AAqBO,IAAM,oBAAmB,qBAAQ;AACjC,IAAM,qBAAsD,qBAAQ,GAAG;AAEvE,IAAM,WAAU,CAAC,SAAwC,kBAAiB,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI,KAAK;AAa1G,IAAM,gBACX,CAAC,iBACD,OAAO,MAAc,SAAoD;AAAA,EACvE,MAAM,KAAK,KAAK,QAAQ,GAAG;AAAA,EAC3B,MAAM,aAAa,aAAa,KAAK,CAAC,MAAM,EAAE,SAAS,KAAK,MAAM,GAAG,EAAE,CAAC;AAAA,EACxE,IAAI,CAAC;AAAA,IAAY,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,cAAc,CAAC,GAAG,SAAS,KAAK;AAAA,EAC1F,OAAO,WAAW,KAAK,KAAK,MAAM,KAAK,CAAC,GAAG,IAAI;AAAA;AAMnD,IAAM,WAAW,CAAC,MAA6C,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AAEtH,SAAS,WAAW,CAAC,MAAc,GAAqB;AAAA,EACtD,QAAQ;AAAA,IACN,KAAK;AAAA,MACH,OAAO,SAAS,CAAC;AAAA,IACnB,KAAK;AAAA,MACH,OAAO,MAAM,QAAQ,CAAC;AAAA,IACxB,KAAK;AAAA,MACH,OAAO,OAAO,MAAM;AAAA,IACtB,KAAK;AAAA,MACH,OAAO,OAAO,MAAM;AAAA,IACtB,KAAK;AAAA,MACH,OAAO,MAAM;AAAA,IACf,KAAK;AAAA,MACH,OAAO,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC;AAAA,IACnD,KAAK;AAAA,MACH,OAAO,OAAO,MAAM,YAAY,OAAO,UAAU,CAAC;AAAA,IACpD;AAAA,MACE,OAAO;AAAA;AAAA;AAIb,SAAS,SAAS,CAAC,GAAY,GAAqB;AAAA,EAClD,IAAI,MAAM;AAAA,IAAG,OAAO;AAAA,EACpB,IAAI,MAAM,QAAQ,CAAC;AAAA,IAAG,OAAO,MAAM,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,GAAG,MAAM,UAAU,GAAG,EAAE,EAAE,CAAC;AAAA,EAC9G,IAAI,SAAS,CAAC,KAAK,SAAS,CAAC,GAAG;AAAA,IAC9B,MAAM,KAAK,OAAO,KAAK,CAAC;AAAA,IACxB,OAAO,GAAG,WAAW,OAAO,KAAK,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,OAAM,KAAK,MAAK,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;AAAA,EAC/F;AAAA,EACA,OAAO;AAAA;AAGT,IAAM,UAAU,CAAC,SAAqC,KAAK,SAAS,KAAK,IAAI,CAAC,MAAM,IAAI,EAAE,QAAQ,MAAM,IAAI,EAAE,QAAQ,OAAO,IAAI,GAAG,EAAE,KAAK,EAAE,IAAI;AAEjJ,IAAM,YAAY;AAClB,IAAM,QAAQ;AACd,IAAM,SAAS;AAEf,SAAS,aAAa,CAAC,GAAoB;AAAA,EACzC,MAAM,IAAI,UAAU,KAAK,CAAC;AAAA,EAC1B,IAAI,CAAC;AAAA,IAAG,OAAO;AAAA,EACf,OAAO,IAAI,GAAG,GAAG,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,MAAM;AAAA,EACpE,IAAI,KAAK,KAAK,KAAK,MAAM,IAAI,KAAK,IAAI,MAAM,IAAI,MAAM,KAAK,MAAM,KAAK;AAAA,IAAI,OAAO;AAAA,EACjF,IAAI,EAAE,OAAO,cAAc,OAAO,EAAE,EAAE,IAAI,MAAM,OAAO,EAAE,GAAG,IAAI;AAAA,IAAK,OAAO;AAAA,EAC5E,OAAO;AAAA;AAGT,SAAS,QAAQ,CAAC,GAAoB;AAAA,EACpC,IAAI,CAAC,uBAAuB,KAAK,CAAC,KAAK,wBAAwB,KAAK,CAAC;AAAA,IAAG,OAAO;AAAA,EAC/E,IAAI;AAAA,IACF,MAAM,MAAM,IAAI,IAAI,CAAC;AAAA,IACrB,QAAQ,IAAI,aAAa,WAAW,IAAI,aAAa,aAAa,IAAI,aAAa;AAAA,IACnF,MAAM;AAAA,IACN,OAAO;AAAA;AAAA;AAIX,SAAS,WAAW,CAAC,QAAgB,GAAoB;AAAA,EACvD,QAAQ;AAAA,IACN,KAAK;AAAA,MACH,OAAO,cAAc,CAAC;AAAA,IACxB,KAAK;AAAA,MACH,OAAO,MAAM,KAAK,CAAC;AAAA,IACrB,KAAK;AAAA,MACH,OAAO,SAAS,CAAC;AAAA,IACnB,KAAK;AAAA,MACH,OAAO,cAAa,CAAC,MAAM;AAAA,IAC7B;AAAA,MACE,OAAO;AAAA;AAAA;AAKN,SAAS,gBAAe,CAAC,QAAoB,OAAgB,OAA0B,CAAC,GAAkB;AAAA,EAC/G,MAAM,KAAK,CAAC,SAAiB,IAAuB,SAAS,GAAG,QAAQ,CAAC,KAAK;AAAA,EAC9E,IAAI,OAAO,SAAS,WAAW;AAAA,IAC7B,MAAM,QAAQ,MAAM,QAAQ,OAAO,IAAI,IAAK,OAAO,OAAoB,CAAC,OAAO,IAAc;AAAA,IAC7F,IAAI,CAAC,MAAM,KAAK,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC;AAAA,MAAG,OAAO,GAAG,MAAM;AAAA,EACjE;AAAA,EACA,IAAI,SAAS,KAAK,GAAG;AAAA,IACnB,MAAM,aAAc,OAAO,cAAc,CAAC;AAAA,IAC1C,WAAW,OAAQ,OAAO,YAAY,CAAC;AAAA,MAAgB,IAAI,EAAE,OAAO;AAAA,QAAQ,OAAO,GAAG,YAAY,CAAC,GAAG,MAAM,GAAG,CAAC;AAAA,IAChH,IAAI,OAAO,yBAAyB,OAAO;AAAA,MACzC,MAAM,UAAU,OAAO,KAAK,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,WAAW,EAAE,KAAK;AAAA,MAC1E,IAAI,QAAQ;AAAA,QAAQ,OAAO,GAAG,wBAAwB,CAAC,GAAG,MAAM,QAAQ,EAAE,CAAC;AAAA,IAC7E;AAAA,IACA,YAAY,KAAK,QAAQ,OAAO,QAAQ,UAAU,GAAG;AAAA,MACnD,IAAI,EAAE,OAAO;AAAA,QAAQ;AAAA,MACrB,MAAM,IAAI,iBAAgB,KAAK,MAAM,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC;AAAA,MACzD,IAAI;AAAA,QAAG,OAAO;AAAA,IAChB;AAAA,IACA,YAAY,KAAK,UAAU,OAAO,QAAS,OAAO,qBAAqB,CAAC,CAA8B,GAAG;AAAA,MACvG,IAAI,EAAE,OAAO;AAAA,QAAQ;AAAA,MACrB,WAAW,QAAQ;AAAA,QAAO,IAAI,EAAE,QAAQ;AAAA,UAAQ,OAAO,GAAG,qBAAqB,CAAC,GAAG,MAAM,IAAI,CAAC;AAAA,IAChG;AAAA,EACF;AAAA,EACA,IAAI,OAAO,SAAS,CAAE,OAAO,MAAuB,KAAK,CAAC,MAAM,iBAAgB,GAAG,OAAO,IAAI,MAAM,IAAI;AAAA,IAAG,OAAO,GAAG,OAAO;AAAA,EAC5H,IAAI,OAAO,SAAU,OAAO,MAAuB,OAAO,CAAC,MAAM,iBAAgB,GAAG,OAAO,IAAI,MAAM,IAAI,EAAE,WAAW;AAAA,IAAG,OAAO,GAAG,OAAO;AAAA,EAC1I,IAAI,MAAM,QAAQ,KAAK,GAAG;AAAA,IACxB,IAAI,OAAO,OAAO,aAAa,YAAY,MAAM,SAAS,OAAO;AAAA,MAAU,OAAO,GAAG,UAAU;AAAA,IAC/F,IAAI,OAAO,OAAO,aAAa,YAAY,MAAM,SAAS,OAAO;AAAA,MAAU,OAAO,GAAG,UAAU;AAAA,IAC/F,IAAI,OAAO,OAAO;AAAA,MAChB,SAAS,IAAI,EAAG,IAAI,MAAM,QAAQ,KAAK;AAAA,QACrC,MAAM,IAAI,iBAAgB,OAAO,OAAqB,MAAM,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC;AAAA,QACpF,IAAI;AAAA,UAAG,OAAO;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAAA,EACA,IAAI,OAAO,UAAU,UAAU;AAAA,IAC7B,IAAI,OAAO,OAAO,YAAY,YAAY,QAAQ,OAAO;AAAA,MAAS,OAAO,GAAG,SAAS;AAAA,IACrF,IAAI,OAAO,OAAO,YAAY,YAAY,QAAQ,OAAO;AAAA,MAAS,OAAO,GAAG,SAAS;AAAA,EACvF;AAAA,EACA,IAAI,OAAO,UAAU,UAAU;AAAA,IAC7B,MAAM,SAAS,CAAC,GAAG,KAAK,EAAE;AAAA,IAC1B,IAAI,OAAO,OAAO,cAAc,YAAY,SAAS,OAAO;AAAA,MAAW,OAAO,GAAG,WAAW;AAAA,IAC5F,IAAI,OAAO,OAAO,cAAc,YAAY,SAAS,OAAO;AAAA,MAAW,OAAO,GAAG,WAAW;AAAA,EAC9F;AAAA,EACA,IAAI,OAAO,QAAQ,CAAE,OAAO,KAAmB,KAAK,CAAC,MAAM,UAAU,GAAG,KAAK,CAAC;AAAA,IAAG,OAAO,GAAG,MAAM;AAAA,EACjG,IAAI,OAAO,UAAU,YAAY,OAAO,OAAO,WAAW,YAAY,CAAC,YAAY,OAAO,QAAQ,KAAK;AAAA,IAAG,OAAO,GAAG,QAAQ;AAAA,EAC5H,OAAO;AAAA;AAOF,SAAS,sBAAqB,CAAC,MAAc,MAA+B;AAAA,EACjF,MAAM,MAAM,SAAQ,IAAI;AAAA,EACxB,IAAI,CAAC;AAAA,IAAK,OAAO,EAAE,OAAO,cAAc;AAAA,EACxC,MAAM,YAAY,iBAAgB,IAAI,aAAa,IAAI;AAAA,EACvD,IAAI;AAAA,IAAW,OAAO,EAAE,OAAO,kBAAkB,YAAY;AAAA,EAC7D,MAAM,MAA+B,KAAM,KAAiC;AAAA,EAC5E,YAAY,KAAK,QAAQ,OAAO,QAAS,IAAI,YAAY,cAAc,CAAC,CAAgC,GAAG;AAAA,IACzG,IAAI,EAAE,OAAO,QAAQ,aAAa;AAAA,MAAK,IAAI,OAAO,gBAAgB,IAAI,OAAO;AAAA,EAC/E;AAAA,EACA,OAAO,EAAE,WAAW,IAAI;AAAA;AAM1B,IAAM,MAAM;AAEL,SAAS,aAAY,CAAC,OAA2B;AAAA,EACtD,IAAI,MAAM;AAAA,EACV,SAAS,IAAI,EAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;AAAA,IACxC,MAAM,IAAK,MAAM,MAAM,MAAQ,MAAM,IAAI,MAAM,MAAM,KAAM,MAAM,IAAI,MAAM;AAAA,IAC3E,OAAO,IAAK,KAAK,KAAM,MAAM,IAAK,KAAK,KAAM;AAAA,IAC7C,OAAO,IAAI,IAAI,MAAM,SAAS,IAAK,KAAK,IAAK,MAAM;AAAA,IACnD,OAAO,IAAI,IAAI,MAAM,SAAS,IAAI,IAAI,MAAM;AAAA,EAC9C;AAAA,EACA,OAAO;AAAA;AAIF,SAAS,aAAY,CAAC,GAA8B;AAAA,EACzD,IAAI,CAAC,OAAO,KAAK,CAAC;AAAA,IAAG,OAAO;AAAA,EAC5B,MAAM,MAAM,EAAE,SAAS,IAAI,IAAI,IAAI,EAAE,SAAS,GAAG,IAAI,IAAI;AAAA,EACzD,MAAM,MAAM,IAAI,WAAY,EAAE,SAAS,IAAK,IAAI,GAAG;AAAA,EACnD,IAAI,IAAI;AAAA,EACR,SAAS,IAAI,EAAG,IAAI,EAAE,QAAQ,KAAK,GAAG;AAAA,IACpC,MAAM,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,MAAO,EAAE,IAAI,OAAO,MAAM,IAAI,IAAI,QAAQ,EAAE,IAAI,EAAE,CAAE;AAAA,IAChF,MAAM,IAAK,EAAE,MAAM,KAAO,EAAE,MAAM,KAAO,EAAE,MAAM,IAAK,EAAE;AAAA,IACxD,MAAM,OAAO,IAAI,MAAM,EAAE;AAAA,IACzB,IAAI,QAAQ,QAAQ,MAAM,IAAI,WAAY;AAAA,MAAG,OAAO;AAAA,IACpD,IAAI,QAAQ,QAAQ,MAAM,IAAI,SAAU;AAAA,MAAG,OAAO;AAAA,IAClD,IAAI,OAAQ,KAAK,KAAM;AAAA,IACvB,IAAI,IAAI,IAAI;AAAA,MAAQ,IAAI,OAAQ,KAAK,IAAK;AAAA,IAC1C,IAAI,IAAI,IAAI;AAAA,MAAQ,IAAI,OAAO,IAAI;AAAA,EACrC;AAAA,EACA,OAAO;AAAA;AAGT,IAAM,aAAa,CAAC,OAAmB,WAA8B,OAAO,MAAM,CAAC,GAAG,MAAM,MAAM,OAAO,CAAC;AAC1G,IAAM,gBAAgB,CAAC,KAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,EAAI;AAG9D,SAAS,UAAS,CAAC,OAAkC;AAAA,EAC1D,IAAI,WAAW,OAAO,CAAC,IAAM,IAAM,IAAM,IAAM,EAAI,CAAC;AAAA,IAAG,OAAO;AAAA,EAC9D,IAAI,WAAW,OAAO,CAAC,KAAM,KAAM,GAAI,CAAC;AAAA,IAAG,OAAO;AAAA,EAClD,IAAI,WAAW,OAAO,aAAa;AAAA,IAAG,OAAO;AAAA,EAC7C,IAAI,WAAW,OAAO,CAAC,IAAM,IAAM,IAAM,EAAI,CAAC;AAAA,IAAG,OAAO;AAAA,EACxD,OAAO;AAAA;AAKF,SAAS,QAAO,CAAC,MAAc,OAAmB,OAAkC,QAAyB;AAAA,EAClH,IAAI;AAAA,IAAO,OAAO;AAAA,EAClB,MAAM,MAAM,KAAK,YAAY,GAAG;AAAA,EAChC,MAAM,MAAM,OAAO,IAAI,KAAK,MAAM,MAAM,CAAC,EAAE,YAAY,IAAI;AAAA,EAC3D,IAAI,OAAO,OAAO,OAAO,oBAAmB,GAAG;AAAA,IAAG,OAAO,mBAAkB;AAAA,EAC3E,OAAO,WAAU,KAAK,MAAM,SAAS,eAAe;AAAA;AAI/C,SAAS,kBAAiB,GAAW;AAAA,EAC1C,MAAM,QAAQ,IAAI,WAAW,EAAE;AAAA,EAC/B,WAAW,OAAO,gBAAgB,KAAK;AAAA,EACvC,OAAO,KAAK,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAAA;AAqCrE,IAAM,cAAa,CAAC,uBAA+C,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,iBAAiB,EAAE,CAAC,GAAG,kBAAkB;AAC7J,IAAM,aAAY,CAAC,UAAiC,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,GAAG,SAAS,KAAK;AAAA;AAE9G,MAAM,oBAAoB,MAAM;AAAA,EAEnB;AAAA,EACA;AAAA,EAFX,WAAW,CACA,QACA,SACT;AAAA,IACA,MAAM,MAAM;AAAA,IAHH;AAAA,IACA;AAAA;AAIb;AAEA,IAAM,OAAO,CAAC,MAAc,IAAI,YAAY,EAAE,OAAO,CAAC;AAEtD,eAAe,OAAO,CAAC,OAAoB,IAAiC;AAAA,EAC1E,MAAM,QAAQ,MAAM,MAAM,MAAM,IAAI,MAAM,QAAQ,KAAK,EAAE;AAAA,EACzD,IAAI,CAAC;AAAA,IAAO,MAAM,IAAI,YAAY,aAAa,MAAM,SAAS;AAAA,EAC9D,OAAO;AAAA;AAIT,eAAe,eAAe,CAAC,OAAoB,MAAiE;AAAA,EAClH,QAAQ,QAAQ,MAAM;AAAA,EACtB,QAAQ,MAAM;AAAA,IACZ,KAAK,cAAc;AAAA,MACjB,MAAM,OAAO,KAAK;AAAA,MAClB,MAAM,SAAS,OAAO,KAAK,SAAS;AAAA,MACpC,MAAM,QAAQ,SAAS,KAAK,KAAK,IAAc,IAAI,MAAM,QAAQ,OAAO,KAAK,MAAgB;AAAA,MAC7F,OAAO,EAAE,MAAM,UAAU,SAAQ,MAAM,OAAO,KAAK,UAAgC,MAAM,GAAG,MAAM,cAAa,KAAK,EAAE;AAAA,IACxH;AAAA,IACA,KAAK,cAAc;AAAA,MACjB,MAAM,MAA+B,CAAC;AAAA,MACtC,WAAW,OAAO,CAAC,SAAS,QAAQ,KAAK;AAAA,QAAG,IAAI,OAAO;AAAA,UAAM,IAAI,OAAO,KAAK;AAAA,MAC7E,IAAI,OAAO,KAAK,WAAW,UAAU;AAAA,QACnC,MAAM,QAAQ,MAAM,QAAQ,OAAO,KAAK,MAAM;AAAA,QAC9C,MAAM,OAAO,KAAK;AAAA,QAClB,IAAI,OAAO,EAAE,MAAM,UAAU,SAAQ,MAAM,OAAO,KAAK,UAAgC,KAAK,GAAG,MAAM,cAAa,KAAK,EAAE;AAAA,MAC3H;AAAA,MACA,OAAO;AAAA,IACT;AAAA,IACA,KAAK,eAAe;AAAA,MAClB,MAAM,QAAQ,MAAM,QAAQ,OAAO,KAAK,MAAgB;AAAA,MACxD,MAAM,WAAW,WAAU,KAAK;AAAA,MAChC,MAAM,MAAM,aAAa,oBAAoB,QAAQ,aAAa,cAAc,QAAQ,aAAa,eAAe,QAAQ;AAAA,MAC5H,IAAI,CAAC;AAAA,QAAK,MAAM,IAAI,YAAY,mBAAmB,SAAS;AAAA,MAC5D,OAAO,EAAE,MAAO,KAAK,QAA+B,YAAY,OAAO,UAAU,MAAM,cAAa,KAAK,EAAE;AAAA,IAC7G;AAAA,IACA,KAAK,sBAAsB;AAAA,MACzB,MAAM,SAAS,KAAK;AAAA,MACpB,IAAI,WAAW,aAAa,CAAC,MAAM,QAAQ,QAAQ,SAAS,MAAM;AAAA,QAAG,MAAM,IAAI,YAAY,+BAA+B,eAAe;AAAA,MACzI,OAAO;AAAA,QACL,IAAI,GAAG,OAAO,KAAK;AAAA,QACnB,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK,QAAQ;AAAA,QACnB,IAAI,KAAK,MAAM;AAAA,QACf,KAAK,WAAW,YAAY,OAAO,EAAE,MAAM,mBAAmB,KAAK,QAAQ,QAAQ,KAAK,UAAU,CAAC,EAAE;AAAA,MACvG;AAAA,IACF;AAAA,IACA,KAAK;AAAA,MACH,OAAO,EAAE,IAAI,GAAG,OAAO,KAAK,KAAe;AAAA,IAC7C;AAAA,MACE,OAAO;AAAA;AAAA;AAKb,eAAe,UAAU,CAAC,OAAoB,OAAkC;AAAA,EAC9E,IAAI,MAAM,QAAQ,KAAK,GAAG;AAAA,IACxB,MAAM,MAAiB,CAAC;AAAA,IACxB,WAAW,QAAQ;AAAA,MAAO,IAAI,KAAK,MAAM,WAAW,OAAO,IAAI,CAAC;AAAA,IAChE,OAAO;AAAA,EACT;AAAA,EACA,IAAI,CAAC,SAAS,KAAK;AAAA,IAAG,OAAO;AAAA,EAC7B,IAAI,MAA+B,CAAC;AAAA,EACpC,IAAI,QAA2B;AAAA,EAC/B,IAAI,OAAO,MAAM,SAAS,UAAU;AAAA,IAClC,QAAQ,cAAa,MAAM,IAAI;AAAA,IAC/B,IAAI,CAAC;AAAA,MAAO,MAAM,IAAI,YAAY,0BAA0B,SAAS;AAAA,EACvE;AAAA,EACA,MAAM,SAAS,QAAQ,MAAM,MAAM,MAAM,IAAI,MAAM,QAAQ,KAAK,MAAM,MAAgB,MAAM,UAAoB,KAAK,IAAI;AAAA,EACzH,YAAY,KAAK,MAAM,OAAO,QAAQ,KAAK;AAAA,IAAG,IAAI,EAAE,SAAS,QAAQ;AAAA,MAAS,IAAI,OAAO,MAAM,WAAW,OAAO,CAAC;AAAA,EAClH,IAAI;AAAA,IAAO,MAAM,KAAK,KAAK,MAAM,MAAM,QAAQ,OAAO;AAAA,EACtD,OAAO;AAAA;AAIF,eAAe,WAAU,CAAC,OAA2C;AAAA,EAC1E,MAAM,YAAY,uBAAsB,MAAM,MAAM,MAAM,SAAS;AAAA,EACnE,IAAI,WAAW;AAAA,IAAW,OAAO,EAAE,QAAQ,WAAU,UAAU,KAAK,GAAG,SAAS,UAAU,UAAU,gBAAgB,YAAY,gBAAgB;AAAA,EAChJ,MAAM,MAAM,SAAQ,MAAM,IAAI;AAAA,EAC9B,MAAM,OAAO,UAAU;AAAA,EACvB,IAAI;AAAA,IACF,IAAI,MAAM,SAAS,aAAa;AAAA,MAC9B,MAAM,WAAW,MAAM,WAAU,MAAe,CAAC,OAAO,MAAM,MAAM,IAAI,MAAM,QAAQ,KAAK,EAAE,CAAC;AAAA,MAC9F,IAAI,WAAW;AAAA,QAAU,OAAO,EAAE,QAAQ,WAAU,SAAS,KAAK,GAAG,SAAS,UAAU;AAAA,MACxF,MAAM,OAAQ,KAAK,QAA+B,aAAY,KAAK,KAAe;AAAA,MAClF,MAAM,SAAS,MAAM,MAAM,MAAM,IAAI,MAAM,QAAQ,KAAK,MAAM,mBAAmB,SAAS,KAAK;AAAA,MAC/F,OAAO,EAAE,QAAQ,YAAW,EAAE,MAAM,EAAE,MAAM,UAAU,mBAAmB,MAAM,SAAS,MAAM,QAAQ,OAAO,GAAG,OAAO,SAAS,MAAM,CAAC,GAAG,SAAS,KAAK;AAAA,IAC1J;AAAA,IACA,IAAI,MAAM,SAAS,wBAAwB,KAAK,OAAO;AAAA,MAAW,KAAK,MAAM,MAAM,SAAS,oBAAmB;AAAA,IAC/G,MAAM,aAAa,MAAM,gBAAgB,OAAO,IAAI;AAAA,IACpD,IAAI;AAAA,IACJ,IAAI;AAAA,MACF,SAAS,MAAM,MAAM,OAAO,MAAM,MAAM,UAAU;AAAA,MAClD,OAAO,OAAO;AAAA,MACd,OAAO,EAAE,QAAQ,WAAU,iBAAiB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG,GAAG,SAAS,WAAW;AAAA;AAAA,IAE7H,IAAI,SAAS,MAAM,KAAK,OAAO,YAAY;AAAA,MAAM,OAAO,EAAE,QAAQ,QAAoC,SAAS,UAAU;AAAA,IACzH,MAAM,aAAa,SAAS,MAAM,IAAI,OAAO,oBAAoB;AAAA,IACjE,MAAM,YAAY,iBAAgB,IAAI,oBAAkC,UAAU;AAAA,IAClF,IAAI;AAAA,MAAW,OAAO,EAAE,QAAQ,WAAU,cAAc,WAAW,GAAG,SAAS,UAAU;AAAA,IACzF,IAAI,MAAM,SAAS;AAAA,MAAsB,OAAO,EAAE,QAAQ,YAAW,EAAE,IAAI,KAAK,GAAG,CAAC,GAAG,SAAS,KAAK;AAAA,IACrG,OAAO,EAAE,QAAQ,YAAW,MAAM,WAAW,OAAO,UAAU,CAAC,GAAG,SAAS,KAAK;AAAA,IAChF,OAAO,OAAO;AAAA,IACd,IAAI,iBAAiB;AAAA,MAAa,OAAO,EAAE,QAAQ,WAAU,MAAM,MAAM,GAAG,SAAS,MAAM,QAAQ;AAAA,IACnG,MAAM;AAAA;AAAA;AAKH,IAAM,eAAc,CAAC,UAA0B,GAAG,MAAM,QAAQ,2CAA2C,GAAG;",
|
|
8
|
+
"debugId": "EC2CD4A2199C0CA164756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|