@dbx-tools/appkit-mastra 0.9.32 → 0.9.36
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/README.md +15 -12
- package/index.ts +1 -2
- package/lib/index.d.ts +1 -2
- package/lib/index.js +2 -2
- package/lib/src/model.js +2 -2
- package/lib/src/observability.d.ts +7 -0
- package/lib/src/observability.js +17 -1
- package/lib/src/plugin.js +3 -2
- package/lib/src/serving-sanitize.d.ts +2 -133
- package/lib/src/serving-sanitize.js +3 -325
- package/lib/src/trace-io.d.ts +14 -12
- package/lib/src/trace-io.js +157 -44
- package/package.json +277 -19
- package/src/model.ts +1 -1
- package/src/observability.ts +16 -0
- package/src/plugin.ts +2 -1
- package/src/serving-sanitize.ts +14 -357
- package/src/trace-io.ts +172 -40
package/lib/src/trace-io.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copy each Mastra chat turn's request/response onto
|
|
3
|
-
*
|
|
2
|
+
* Copy each Mastra chat turn's request/response onto its OTel root span
|
|
3
|
+
* so Databricks-managed MLflow can display them.
|
|
4
4
|
*
|
|
5
5
|
* Why this exists: MLflow's UC `<target>_trace_unified` view picks the
|
|
6
6
|
* one span whose `parent_span_id` is empty and reads request/response
|
|
@@ -10,18 +10,24 @@
|
|
|
10
10
|
* the view never reads, so chat traces arrive with both columns null
|
|
11
11
|
* even when the spans themselves look healthy.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* AppKit's HTTP instrumentation records the server span in OTel RPC metadata,
|
|
14
|
+
* which remains available even when Express makes a middleware-layer child
|
|
15
|
+
* active. When instrumentation is unavailable, this module creates one
|
|
16
|
+
* request-lifetime server span and runs Mastra under it.
|
|
17
17
|
*
|
|
18
18
|
* @module
|
|
19
19
|
*/
|
|
20
|
+
import { StringDecoder } from "node:string_decoder";
|
|
20
21
|
import { json, log, object } from "@dbx-tools/shared-core";
|
|
21
|
-
import { trace } from "@opentelemetry/api";
|
|
22
|
+
import { context, SpanKind, trace } from "@opentelemetry/api";
|
|
23
|
+
import { getRPCMetadata, RPCType } from "@opentelemetry/core";
|
|
22
24
|
const logger = log.logger("mastra/trace-io");
|
|
23
25
|
/** Cap on each payload copied onto a span, so one turn cannot bloat the export. */
|
|
24
26
|
export const TRACE_IO_LIMIT = 8_000;
|
|
27
|
+
/** Bound for a non-streaming body captured through `res.end` instead of `res.json`. */
|
|
28
|
+
const RESPONSE_BODY_LIMIT = TRACE_IO_LIMIT * 4;
|
|
29
|
+
/** Tracer scope used only when AppKit did not create a recording HTTP span. */
|
|
30
|
+
const CHAT_TURN_TRACER = "@dbx-tools/appkit-mastra/trace-io";
|
|
25
31
|
/**
|
|
26
32
|
* Mount-relative Mastra agent invoke paths that carry a chat turn body
|
|
27
33
|
* (`messages`) and stream an assistant answer. Resume / approve verbs
|
|
@@ -32,6 +38,20 @@ const AGENT_TURN_ROUTE = /^(?:\/agents\/[^/]+\/(?:stream|generate)(?:\/|$)|\/cha
|
|
|
32
38
|
/** Attribute keys the MLflow UC `*_trace_unified` view reads from the root span. */
|
|
33
39
|
export const MLFLOW_SPAN_INPUTS_ATTR = "mlflow.spanInputs";
|
|
34
40
|
export const MLFLOW_SPAN_OUTPUTS_ATTR = "mlflow.spanOutputs";
|
|
41
|
+
/** Return the assistant text from one SSE line, or an empty string. */
|
|
42
|
+
function assistantTextFromSseLine(line) {
|
|
43
|
+
if (!line.startsWith("data:"))
|
|
44
|
+
return "";
|
|
45
|
+
const frame = json.parse(line.slice(5));
|
|
46
|
+
if (!object.isRecord(frame) || frame.type !== "text-delta")
|
|
47
|
+
return "";
|
|
48
|
+
const text = typeof frame.delta === "string"
|
|
49
|
+
? frame.delta
|
|
50
|
+
: object.isRecord(frame.payload)
|
|
51
|
+
? frame.payload.text
|
|
52
|
+
: undefined;
|
|
53
|
+
return typeof text === "string" ? text : "";
|
|
54
|
+
}
|
|
35
55
|
/**
|
|
36
56
|
* Concatenate the assistant's answer out of an AI SDK SSE transcript.
|
|
37
57
|
*
|
|
@@ -43,29 +63,103 @@ export const MLFLOW_SPAN_OUTPUTS_ATTR = "mlflow.spanOutputs";
|
|
|
43
63
|
export function assistantTextFromSse(body) {
|
|
44
64
|
const parts = [];
|
|
45
65
|
for (const line of body.split("\n")) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// SSE carries comment/keepalive lines that are not JSON; they never hold
|
|
49
|
-
// assistant text, so skipping them is the intended path rather than an error.
|
|
50
|
-
const frame = json.parse(line.slice(5));
|
|
51
|
-
if (!object.isRecord(frame) || frame.type !== "text-delta")
|
|
52
|
-
continue;
|
|
53
|
-
const text = typeof frame.delta === "string"
|
|
54
|
-
? frame.delta
|
|
55
|
-
: object.isRecord(frame.payload)
|
|
56
|
-
? frame.payload.text
|
|
57
|
-
: undefined;
|
|
58
|
-
if (typeof text === "string")
|
|
66
|
+
const text = assistantTextFromSseLine(line);
|
|
67
|
+
if (text)
|
|
59
68
|
parts.push(text);
|
|
60
69
|
}
|
|
61
|
-
return parts.join("");
|
|
70
|
+
return parts.join("").slice(0, TRACE_IO_LIMIT);
|
|
71
|
+
}
|
|
72
|
+
/** Read the final assistant text from a non-streaming Mastra response. */
|
|
73
|
+
export function assistantTextFromJson(body) {
|
|
74
|
+
if (!object.isRecord(body) || typeof body.text !== "string")
|
|
75
|
+
return "";
|
|
76
|
+
return body.text.slice(0, TRACE_IO_LIMIT);
|
|
77
|
+
}
|
|
78
|
+
/** Incrementally assemble UTF-8 SSE text while retaining a bounded JSON fallback. */
|
|
79
|
+
class AssistantResponseCollector {
|
|
80
|
+
decoder = new StringDecoder("utf8");
|
|
81
|
+
answer = "";
|
|
82
|
+
body = "";
|
|
83
|
+
pendingLine = "";
|
|
84
|
+
finished = false;
|
|
85
|
+
write(chunk) {
|
|
86
|
+
if (this.finished)
|
|
87
|
+
return;
|
|
88
|
+
if (typeof chunk === "string") {
|
|
89
|
+
this.consume(chunk);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (ArrayBuffer.isView(chunk)) {
|
|
93
|
+
this.consume(this.decoder.write(Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength)));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
finish() {
|
|
97
|
+
if (this.finished)
|
|
98
|
+
return this.answer || this.jsonAnswer();
|
|
99
|
+
this.finished = true;
|
|
100
|
+
this.consume(this.decoder.end());
|
|
101
|
+
this.consumeSseLine(this.pendingLine);
|
|
102
|
+
this.pendingLine = "";
|
|
103
|
+
return this.answer || this.jsonAnswer();
|
|
104
|
+
}
|
|
105
|
+
consume(text) {
|
|
106
|
+
if (!text)
|
|
107
|
+
return;
|
|
108
|
+
if (this.body.length < RESPONSE_BODY_LIMIT) {
|
|
109
|
+
this.body += text.slice(0, RESPONSE_BODY_LIMIT - this.body.length);
|
|
110
|
+
}
|
|
111
|
+
this.pendingLine += text;
|
|
112
|
+
let newline = this.pendingLine.indexOf("\n");
|
|
113
|
+
while (newline >= 0) {
|
|
114
|
+
this.consumeSseLine(this.pendingLine.slice(0, newline).replace(/\r$/, ""));
|
|
115
|
+
this.pendingLine = this.pendingLine.slice(newline + 1);
|
|
116
|
+
newline = this.pendingLine.indexOf("\n");
|
|
117
|
+
}
|
|
118
|
+
if (this.pendingLine.length > RESPONSE_BODY_LIMIT) {
|
|
119
|
+
this.pendingLine = this.pendingLine.slice(-RESPONSE_BODY_LIMIT);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
consumeSseLine(line) {
|
|
123
|
+
if (this.answer.length >= TRACE_IO_LIMIT)
|
|
124
|
+
return;
|
|
125
|
+
const text = assistantTextFromSseLine(line);
|
|
126
|
+
this.answer += text.slice(0, TRACE_IO_LIMIT - this.answer.length);
|
|
127
|
+
}
|
|
128
|
+
jsonAnswer() {
|
|
129
|
+
return assistantTextFromJson(json.parse(this.body));
|
|
130
|
+
}
|
|
62
131
|
}
|
|
63
132
|
/**
|
|
64
|
-
*
|
|
133
|
+
* Select the span MLflow treats as the request root.
|
|
65
134
|
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
135
|
+
* OTel HTTP instrumentation stores its server span in RPC metadata. That span
|
|
136
|
+
* wins over an active Express child. If no recording local span exists, create
|
|
137
|
+
* one under the current context so enabled W3C propagation remains intact.
|
|
138
|
+
*/
|
|
139
|
+
function resolveTraceTarget() {
|
|
140
|
+
const activeContext = context.active();
|
|
141
|
+
const rpc = getRPCMetadata(activeContext);
|
|
142
|
+
if (rpc?.type === RPCType.HTTP && rpc.span.isRecording()) {
|
|
143
|
+
return { span: rpc.span, owned: false };
|
|
144
|
+
}
|
|
145
|
+
const active = trace.getActiveSpan();
|
|
146
|
+
if (active?.isRecording())
|
|
147
|
+
return { span: active, owned: false };
|
|
148
|
+
const span = trace
|
|
149
|
+
.getTracer(CHAT_TURN_TRACER)
|
|
150
|
+
.startSpan("mastra.chat_turn", { kind: SpanKind.SERVER }, activeContext);
|
|
151
|
+
if (!span.isRecording()) {
|
|
152
|
+
span.end();
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
return { span, owned: true };
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Express middleware that stamps chat turn I/O onto the exported OTel root.
|
|
159
|
+
*
|
|
160
|
+
* Tee `res.write`, `res.json`, and `res.end` instead of listening for `finish`:
|
|
161
|
+
* HTTP instrumentation ends its server span on finish, and attributes set
|
|
162
|
+
* after a span ends never reach the exporter.
|
|
69
163
|
*
|
|
70
164
|
* `path` is mount-relative (what the Mastra sub-app sees), e.g.
|
|
71
165
|
* `/agents/support/stream`.
|
|
@@ -75,47 +169,66 @@ export function chatTurnTraceIoMiddleware(req, res, next) {
|
|
|
75
169
|
next();
|
|
76
170
|
return;
|
|
77
171
|
}
|
|
78
|
-
const
|
|
79
|
-
if (!
|
|
172
|
+
const target = resolveTraceTarget();
|
|
173
|
+
if (!target) {
|
|
80
174
|
next();
|
|
81
175
|
return;
|
|
82
176
|
}
|
|
83
177
|
const messages = req.body?.messages;
|
|
84
178
|
if (messages !== undefined) {
|
|
85
|
-
span.setAttribute(MLFLOW_SPAN_INPUTS_ATTR, JSON.stringify(messages).slice(0, TRACE_IO_LIMIT));
|
|
179
|
+
target.span.setAttribute(MLFLOW_SPAN_INPUTS_ATTR, JSON.stringify(messages).slice(0, TRACE_IO_LIMIT));
|
|
86
180
|
}
|
|
87
|
-
const
|
|
181
|
+
const collector = new AssistantResponseCollector();
|
|
182
|
+
let outputRecorded = false;
|
|
183
|
+
let ownedSpanEnded = false;
|
|
88
184
|
const passThroughWrite = res.write.bind(res);
|
|
89
185
|
const passThroughEnd = res.end.bind(res);
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
186
|
+
const passThroughJson = res.json.bind(res);
|
|
187
|
+
const recordOutput = (answer) => {
|
|
188
|
+
if (outputRecorded || !answer)
|
|
189
|
+
return;
|
|
190
|
+
target.span.setAttribute(MLFLOW_SPAN_OUTPUTS_ATTR, answer.slice(0, TRACE_IO_LIMIT));
|
|
191
|
+
outputRecorded = true;
|
|
192
|
+
};
|
|
193
|
+
const endOwnedSpan = () => {
|
|
194
|
+
if (!target.owned || ownedSpanEnded)
|
|
195
|
+
return;
|
|
196
|
+
ownedSpanEnded = true;
|
|
197
|
+
target.span.end();
|
|
95
198
|
};
|
|
96
199
|
res.write = ((chunk, ...rest) => {
|
|
97
|
-
|
|
200
|
+
collector.write(chunk);
|
|
98
201
|
return passThroughWrite(chunk, ...rest);
|
|
99
202
|
});
|
|
203
|
+
res.json = ((body) => {
|
|
204
|
+
recordOutput(assistantTextFromJson(body));
|
|
205
|
+
return passThroughJson(body);
|
|
206
|
+
});
|
|
100
207
|
res.end = ((chunk, ...rest) => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
208
|
+
collector.write(chunk);
|
|
209
|
+
recordOutput(collector.finish());
|
|
210
|
+
try {
|
|
211
|
+
return passThroughEnd(chunk, ...rest);
|
|
105
212
|
}
|
|
106
|
-
|
|
213
|
+
finally {
|
|
214
|
+
endOwnedSpan();
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
res.once("close", () => {
|
|
218
|
+
recordOutput(collector.finish());
|
|
219
|
+
endOwnedSpan();
|
|
107
220
|
});
|
|
108
|
-
|
|
221
|
+
context.with(trace.setSpan(context.active(), target.span), next);
|
|
109
222
|
}
|
|
110
223
|
/**
|
|
111
224
|
* Install {@link chatTurnTraceIoMiddleware} on a Mastra Express sub-app.
|
|
112
225
|
*
|
|
113
226
|
* Call before `MastraServer.init()` so the layer sits ahead of the agent
|
|
114
|
-
* routes. Safe to call unconditionally:
|
|
115
|
-
*
|
|
227
|
+
* routes. Safe to call unconditionally: when no recording tracer is registered,
|
|
228
|
+
* the middleware is a no-op.
|
|
116
229
|
*/
|
|
117
230
|
export function attachChatTurnTraceIo(app) {
|
|
118
231
|
app.use(chatTurnTraceIoMiddleware);
|
|
119
232
|
logger.info("chat turn I/O middleware attached");
|
|
120
233
|
}
|
|
121
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2UtaW8uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHJhY2UtaW8udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtCRztBQUVILE9BQU8sRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzNELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUczQyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7QUFFN0MsbUZBQW1GO0FBQ25GLE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBRyxLQUFLLENBQUM7QUFFcEM7Ozs7O0dBS0c7QUFDSCxNQUFNLGdCQUFnQixHQUFHLG1FQUFtRSxDQUFDO0FBRTdGLG9GQUFvRjtBQUNwRixNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRyxtQkFBbUIsQ0FBQztBQUMzRCxNQUFNLENBQUMsTUFBTSx3QkFBd0IsR0FBRyxvQkFBb0IsQ0FBQztBQUU3RDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLG9CQUFvQixDQUFDLElBQVk7SUFDL0MsTUFBTSxLQUFLLEdBQWEsRUFBRSxDQUFDO0lBQzNCLEtBQUssTUFBTSxJQUFJLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ3BDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQztZQUFFLFNBQVM7UUFDeEMseUVBQXlFO1FBQ3pFLDhFQUE4RTtRQUM5RSxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4QyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFlBQVk7WUFBRSxTQUFT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SUFDeEMsQ0FBQyxDQUFtQixDQUFDO0lBRXJCLElBQUksRUFBRSxDQUFDO0FBQ1QsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSxxQkFBcUIsQ0FBQyxHQUFvQjtJQUN4RCxHQUFHLENBQUMsR0FBRyxDQUFDLHlCQUF5QixDQUFDLENBQUM7SUFDbkMsTUFBTSxDQUFDLElBQUksQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO0FBQ25ELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHkgZWFjaCBNYXN0cmEgY2hhdCB0dXJuJ3MgcmVxdWVzdC9yZXNwb25zZSBvbnRvIHRoZSBhY3RpdmUgT1RlbFxuICogcm9vdCBzcGFuIHNvIERhdGFicmlja3MtbWFuYWdlZCBNTGZsb3cgY2FuIGRpc3BsYXkgdGhlbS5cbiAqXG4gKiBXaHkgdGhpcyBleGlzdHM6IE1MZmxvdydzIFVDIGA8dGFyZ2V0Pl90cmFjZV91bmlmaWVkYCB2aWV3IHBpY2tzIHRoZVxuICogb25lIHNwYW4gd2hvc2UgYHBhcmVudF9zcGFuX2lkYCBpcyBlbXB0eSBhbmQgcmVhZHMgcmVxdWVzdC9yZXNwb25zZVxuICogZnJvbSBgbWxmbG93LnNwYW5JbnB1dHNgIC8gYG1sZmxvdy5zcGFuT3V0cHV0c2AgKG9yIHRoZSBgZ2VuX2FpLipgXG4gKiBlcXVpdmFsZW50cykgb24gVEhBVCBzcGFuIG9ubHkuIE1hc3RyYSByZWNvcmRzIHRoZSB0dXJuIG9uIGl0c1xuICogYGludm9rZV9hZ2VudGAgY2hpbGQgdW5kZXIgYG1hc3RyYS5hZ2VudF9ydW4uaW5wdXRgIC8gYC5vdXRwdXRgLCBrZXlzXG4gKiB0aGUgdmlldyBuZXZlciByZWFkcywgc28gY2hhdCB0cmFjZXMgYXJyaXZlIHdpdGggYm90aCBjb2x1bW5zIG51bGxcbiAqIGV2ZW4gd2hlbiB0aGUgc3BhbnMgdGhlbXNlbHZlcyBsb29rIGhlYWx0aHkuXG4gKlxuICogVGhlIGFjdGl2ZSBzcGFuIGluc2lkZSB0aGUgTWFzdHJhIHN1Yi1hcHAgaXMgc3RpbGwgQXBwS2l0J3MgSFRUUFxuICogc2VydmVyIHNwYW4gKE9UZWwgY29udGV4dCBpcyBhc3luYy1sb2NhbCkuIFdpdGggYE9URUxfUFJPUEFHQVRPUlM9bm9uZWBcbiAqIHRoYXQgc3BhbiBpcyB0aGUgdHJhY2Ugcm9vdCAtIHNlZSB0aGUgcGFja2FnZSBSRUFETUUncyBvYnNlcnZhYmlsaXR5XG4gKiBzZWN0aW9uIGZvciB3aHkgQXBwcyBpbmdyZXNzIGB0cmFjZXBhcmVudGAgb3RoZXJ3aXNlIGhpZGVzIGV2ZXJ5IHR1cm4uXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IGpzb24sIGxvZywgb2JqZWN0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IHRyYWNlIH0gZnJvbSBcIkBvcGVudGVsZW1ldHJ5L2FwaVwiO1xuaW1wb3J0IHR5cGUgZXhwcmVzcyBmcm9tIFwiZXhwcmVzc1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwibWFzdHJhL3RyYWNlLWlvXCIpO1xuXG4vKiogQ2FwIG9uIGVhY2ggcGF5bG9hZCBjb3BpZWQgb250byBhIHNwYW4sIHNvIG9uZSB0dXJuIGNhbm5vdCBibG9hdCB0aGUgZXhwb3J0LiAqL1xuZXhwb3J0IGNvbnN0IFRSQUNFX0lPX0xJTUlUID0gOF8wMDA7XG5cbi8qKlxuICogTW91bnQtcmVsYXRpdmUgTWFzdHJhIGFnZW50IGludm9rZSBwYXRocyB0aGF0IGNhcnJ5IGEgY2hhdCB0dXJuIGJvZHlcbiAqIChgbWVzc2FnZXNgKSBhbmQgc3RyZWFtIGFuIGFzc2lzdGFudCBhbnN3ZXIuIFJlc3VtZSAvIGFwcHJvdmUgdmVyYnNcbiAqIGFyZSBpbnRlbnRpb25hbGx5IGV4Y2x1ZGVkOiB0aGVpciBib2RpZXMgYXJlIHRvb2wgZGVjaXNpb25zLCBub3QgdGhlXG4gKiB1c2VyIHByb21wdCwgYW5kIHRoZXkgcmFyZWx5IHByb2R1Y2UgYSBmcmVzaCBhbnN3ZXIgd29ydGggc3VyZmFjaW5nLlxuICovXG5jb25zdCBBR0VOVF9UVVJOX1JPVVRFID0gL14oPzpcXC9hZ2VudHNcXC9bXi9dK1xcLyg/OnN0cmVhbXxnZW5lcmF0ZSkoPzpcXC98JCl8XFwvY2hhdFxcL1teL10rJCkvaTtcblxuLyoqIEF0dHJpYnV0ZSBrZXlzIHRoZSBNTGZsb3cgVUMgYCpfdHJhY2VfdW5pZmllZGAgdmlldyByZWFkcyBmcm9tIHRoZSByb290IHNwYW4uICovXG5leHBvcnQgY29uc3QgTUxGTE9XX1NQQU5fSU5QVVRTX0FUVFIgPSBcIm1sZmxvdy5zcGFuSW5wdXRzXCI7XG5leHBvcnQgY29uc3QgTUxGTE9XX1NQQU5fT1VUUFVUU19BVFRSID0gXCJtbGZsb3cuc3Bhbk91dHB1dHNcIjtcblxuLyoqXG4gKiBDb25jYXRlbmF0ZSB0aGUgYXNzaXN0YW50J3MgYW5zd2VyIG91dCBvZiBhbiBBSSBTREsgU1NFIHRyYW5zY3JpcHQuXG4gKlxuICogVGhlIGFnZW50IHN0cmVhbXMgaXRzIHJlcGx5IGFzIGB0ZXh0LWRlbHRhYCBmcmFtZXNcbiAqIChgZGF0YToge1widHlwZVwiOlwidGV4dC1kZWx0YVwiLFwicGF5bG9hZFwiOntcInRleHRcIjpcIi4uLlwifX1gKSwgc28gdGhlIGZ1bGxcbiAqIGFuc3dlciBvbmx5IGV2ZXIgZXhpc3RzIGFzIGRlbHRhcyBvbiB0aGUgd2lyZSBhbmQgaGFzIHRvIGJlXG4gKiByZWFzc2VtYmxlZCBoZXJlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXNzaXN0YW50VGV4dEZyb21Tc2UoYm9keTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcGFydHM6IHN0cmluZ1tdID0gW107XG4gIGZvciAoY29uc3QgbGluZSBvZiBib2R5LnNwbGl0KFwiXFxuXCIpKSB7XG4gICAgaWYgKCFsaW5lLnN0YXJ0c1dpdGgoXCJkYXRhOlwiKSkgY29udGludWU7XG4gICAgLy8gU1NFIGNhcnJpZXMgY29tbWVudC9rZWVwYWxpdmUgbGluZXMgdGhhdCBhcmUgbm90IEpTT047IHRoZXkgbmV2ZXIgaG9sZFxuICAgIC8vIGFzc2lzdGFudCB0ZXh0LCBzbyBza2lwcGluZyB0aGVtIGlzIHRoZSBpbnRlbmRlZCBwYXRoIHJhdGhlciB0aGFuIGFuIGVycm9yLlxuICAgIGNvbnN0IGZyYW1lID0ganNvbi5wYXJzZShsaW5lLnNsaWNlKDUpKTtcbiAgICBpZiAoIW9iamVjdC5pc1JlY29yZChmcmFtZSkgfHwgZnJhbWUudHlwZSAhPT0gXCJ0ZXh0LWRlbHRhXCIpIGNvbnRpbnVlO1xuICAgIGNvbnN0IHRleHQgPVxuICAgICAgdHlwZW9mIGZyYW1lLmRlbHRhID09PSBcInN0cmluZ1wiXG4gICAgICAgID8gZnJhbWUuZGVsdGFcbiAgICAgICAgOiBvYmplY3QuaXNSZWNvcmQoZnJhbWUucGF5bG9hZClcbiAgICAgICAgICA/IGZyYW1lLnBheWxvYWQudGV4dFxuICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgIGlmICh0eXBlb2YgdGV4dCA9PT0gXCJzdHJpbmdcIikgcGFydHMucHVzaCh0ZXh0KTtcbiAgfVxuICByZXR1cm4gcGFydHMuam9pbihcIlwiKTtcbn1cblxuLyoqXG4gKiBFeHByZXNzIG1pZGRsZXdhcmUgdGhhdCBzdGFtcHMgY2hhdCB0dXJuIEkvTyBvbnRvIHRoZSBhY3RpdmUgT1RlbCBzcGFuLlxuICpcbiAqIFRlZSBgcmVzLndyaXRlYCAvIGByZXMuZW5kYCBpbnN0ZWFkIG9mIGxpc3RlbmluZyBmb3IgYGZpbmlzaGA6IHRoZSBIVFRQXG4gKiBpbnN0cnVtZW50YXRpb24gZW5kcyB0aGUgcm9vdCBzcGFuIG9uIGZpbmlzaCwgYW5kIGFuIGF0dHJpYnV0ZSBzZXQgYWZ0ZXJcbiAqIGEgc3BhbiBlbmRzIG5ldmVyIHJlYWNoZXMgdGhlIGV4cG9ydGVyLlxuICpcbiAqIGBwYXRoYCBpcyBtb3VudC1yZWxhdGl2ZSAod2hhdCB0aGUgTWFzdHJhIHN1Yi1hcHAgc2VlcyksIGUuZy5cbiAqIGAvYWdlbnRzL3N1cHBvcnQvc3RyZWFtYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoYXRUdXJuVHJhY2VJb01pZGRsZXdhcmUoXG4gIHJlcTogZXhwcmVzcy5SZXF1ZXN0LFxuICByZXM6IGV4cHJlc3MuUmVzcG9uc2UsXG4gIG5leHQ6IGV4cHJlc3MuTmV4dEZ1bmN0aW9uLFxuKTogdm9pZCB7XG4gIGlmIChyZXEubWV0aG9kICE9PSBcIlBPU1RcIiB8fCAhQUdFTlRfVFVSTl9ST1VURS50ZXN0KHJlcS5wYXRoKSkge1xuICAgIG5leHQoKTtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3Qgc3BhbiA9IHRyYWNlLmdldEFjdGl2ZVNwYW4oKTtcbiAgaWYgKCFzcGFuKSB7XG4gICAgbmV4dCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IG1lc3NhZ2VzID0gKHJlcS5ib2R5IGFzIHsgbWVzc2FnZXM/OiB1bmtub3duIH0gfCB1bmRlZmluZWQpPy5tZXNzYWdlcztcbiAgaWYgKG1lc3NhZ2VzICE9PSB1bmRlZmluZWQpIHtcbiAgICBzcGFuLnNldEF0dHJpYnV0ZShNTEZMT1dfU1BBTl9JTlBVVFNfQVRUUiwgSlNPTi5zdHJpbmdpZnkobWVzc2FnZXMpLnNsaWNlKDAsIFRSQUNFX0lPX0xJTUlUKSk7XG4gIH1cblxuICBjb25zdCBjaHVua3M6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IHBhc3NUaHJvdWdoV3JpdGUgPSByZXMud3JpdGUuYmluZChyZXMpIGFzICguLi5hcmdzOiB1bmtub3duW10pID0+IGJvb2xlYW47XG4gIGNvbnN0IHBhc3NUaHJvdWdoRW5kID0gcmVzLmVuZC5iaW5kKHJlcykgYXMgKC4uLmFyZ3M6IHVua25vd25bXSkgPT4gdW5rbm93bjtcbiAgY29uc3QgY29sbGVjdCA9IChjaHVuazogdW5rbm93bik6IHZvaWQgPT4ge1xuICAgIGlmICh0eXBlb2YgY2h1bmsgPT09IFwic3RyaW5nXCIpIGNodW5rcy5wdXNoKGNodW5rKTtcbiAgICBlbHNlIGlmIChCdWZmZXIuaXNCdWZmZXIoY2h1bmspKSBjaHVua3MucHVzaChjaHVuay50b1N0cmluZyhcInV0ZjhcIikpO1xuICB9O1xuXG4gIHJlcy53cml0ZSA9ICgoY2h1bms6IHVua25vd24sIC4uLnJlc3Q6IHVua25vd25bXSkgPT4ge1xuICAgIGNvbGxlY3QoY2h1bmspO1xuICAgIHJldHVybiBwYXNzVGhyb3VnaFdyaXRlKGNodW5rLCAuLi5yZXN0KTtcbiAgfSkgYXMgdHlwZW9mIHJlcy53cml0ZTtcblxuICByZXMuZW5kID0gKChjaHVuaz86IHVua25vd24sIC4uLnJlc3Q6IHVua25vd25bXSkgPT4ge1xuICAgIGNvbGxlY3QoY2h1bmspO1xuICAgIGNvbnN0IGFuc3dlciA9IGFzc2lzdGFudFRleHRGcm9tU3NlKGNodW5rcy5qb2luKFwiXCIpKTtcbiAgICBpZiAoYW5zd2VyKSB7XG4gICAgICBzcGFuLnNldEF0dHJpYnV0ZShNTEZMT1dfU1BBTl9PVVRQVVRTX0FUVFIsIGFuc3dlci5zbGljZSgwLCBUUkFDRV9JT19MSU1JVCkpO1xuICAgIH1cbiAgICByZXR1cm4gcGFzc1Rocm91Z2hFbmQoY2h1bmssIC4uLnJlc3QpO1xuICB9KSBhcyB0eXBlb2YgcmVzLmVuZDtcblxuICBuZXh0KCk7XG59XG5cbi8qKlxuICogSW5zdGFsbCB7QGxpbmsgY2hhdFR1cm5UcmFjZUlvTWlkZGxld2FyZX0gb24gYSBNYXN0cmEgRXhwcmVzcyBzdWItYXBwLlxuICpcbiAqIENhbGwgYmVmb3JlIGBNYXN0cmFTZXJ2ZXIuaW5pdCgpYCBzbyB0aGUgbGF5ZXIgc2l0cyBhaGVhZCBvZiB0aGUgYWdlbnRcbiAqIHJvdXRlcy4gU2FmZSB0byBjYWxsIHVuY29uZGl0aW9uYWxseTogd2l0aCBubyBhY3RpdmUgc3BhbiAobG9jYWwsIG5vXG4gKiBPVExQKSB0aGUgbWlkZGxld2FyZSBpcyBhIG5vLW9wLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXR0YWNoQ2hhdFR1cm5UcmFjZUlvKGFwcDogZXhwcmVzcy5FeHByZXNzKTogdm9pZCB7XG4gIGFwcC51c2UoY2hhdFR1cm5UcmFjZUlvTWlkZGxld2FyZSk7XG4gIGxvZ2dlci5pbmZvKFwiY2hhdCB0dXJuIEkvTyBtaWRkbGV3YXJlIGF0dGFjaGVkXCIpO1xufVxuIl19
|
|
234
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2UtaW8uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHJhY2UtaW8udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtCRztBQUVILE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUVwRCxPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUMzRCxPQUFPLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQWEsTUFBTSxvQkFBb0IsQ0FBQztBQUN6RSxPQUFPLEVBQUUsY0FBYyxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRzlELE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztBQUU3QyxtRkFBbUY7QUFDbkYsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQztBQUVwQyx1RkFBdUY7QUFDdkYsTUFBTSxtQkFBbUIsR0FBRyxjQUFjLEdBQUcsQ0FBQyxDQUFDO0FBRS9DLCtFQUErRTtBQUMvRSxNQUFNLGdCQUFnQixHQUFHLG1DQUFtQyxDQUFDO0FBRTdEOzs7OztHQUtHO0FBQ0gsTUFBTSxnQkFBZ0IsR0FBRyxtRUFBbUUsQ0FBQztBQUU3RixvRkFBb0Y7QUFDcEYsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsbUJBQW1CLENBQUM7QUFDM0QsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUcsb0JBQW9CLENBQUM7QUFPN0QsdUVBQXVFO0FBQ3ZFLFNBQVMsd0JBQXdCLENBQUMsSUFBWTtJQUM1QyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUM7UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUN6QyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxD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QyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdkIsWUFBWSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ2pDLElBQUksQ0FBQztZQUNILE9BQU8sY0FBYyxDQUFDLEtBQUssRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO1FBQ3hDLENBQUM7Z0JBQVMsQ0FBQztZQUNULFlBQVksRUFBRSxDQUFDO1FBQ2pCLENBQUM7SUFDSCxDQUFDLENBQW1CLENBQUM7SUFFckIsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFO1FBQ3JCLFlBQVksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUNqQyxZQUFZLEVBQUUsQ0FBQztJQUNqQixDQUFDLENBQUMsQ0FBQztJQUVILE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQ25FLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUscUJBQXFCLENBQUMsR0FBb0I7SUFDeEQsR0FBRyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQ25DLE1BQU0sQ0FBQyxJQUFJLENBQUMsbUNBQW1DLENBQUMsQ0FBQztBQUNuRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5IGVhY2ggTWFzdHJhIGNoYXQgdHVybidzIHJlcXVlc3QvcmVzcG9uc2Ugb250byBpdHMgT1RlbCByb290IHNwYW5cbiAqIHNvIERhdGFicmlja3MtbWFuYWdlZCBNTGZsb3cgY2FuIGRpc3BsYXkgdGhlbS5cbiAqXG4gKiBXaHkgdGhpcyBleGlzdHM6IE1MZmxvdydzIFVDIGA8dGFyZ2V0Pl90cmFjZV91bmlmaWVkYCB2aWV3IHBpY2tzIHRoZVxuICogb25lIHNwYW4gd2hvc2UgYHBhcmVudF9zcGFuX2lkYCBpcyBlbXB0eSBhbmQgcmVhZHMgcmVxdWVzdC9yZXNwb25zZVxuICogZnJvbSBgbWxmbG93LnNwYW5JbnB1dHNgIC8gYG1sZmxvdy5zcGFuT3V0cHV0c2AgKG9yIHRoZSBgZ2VuX2FpLipgXG4gKiBlcXVpdmFsZW50cykgb24gVEhBVCBzcGFuIG9ubHkuIE1hc3RyYSByZWNvcmRzIHRoZSB0dXJuIG9uIGl0c1xuICogYGludm9rZV9hZ2VudGAgY2hpbGQgdW5kZXIgYG1hc3RyYS5hZ2VudF9ydW4uaW5wdXRgIC8gYC5vdXRwdXRgLCBrZXlzXG4gKiB0aGUgdmlldyBuZXZlciByZWFkcywgc28gY2hhdCB0cmFjZXMgYXJyaXZlIHdpdGggYm90aCBjb2x1bW5zIG51bGxcbiAqIGV2ZW4gd2hlbiB0aGUgc3BhbnMgdGhlbXNlbHZlcyBsb29rIGhlYWx0aHkuXG4gKlxuICogQXBwS2l0J3MgSFRUUCBpbnN0cnVtZW50YXRpb24gcmVjb3JkcyB0aGUgc2VydmVyIHNwYW4gaW4gT1RlbCBSUEMgbWV0YWRhdGEsXG4gKiB3aGljaCByZW1haW5zIGF2YWlsYWJsZSBldmVuIHdoZW4gRXhwcmVzcyBtYWtlcyBhIG1pZGRsZXdhcmUtbGF5ZXIgY2hpbGRcbiAqIGFjdGl2ZS4gV2hlbiBpbnN0cnVtZW50YXRpb24gaXMgdW5hdmFpbGFibGUsIHRoaXMgbW9kdWxlIGNyZWF0ZXMgb25lXG4gKiByZXF1ZXN0LWxpZmV0aW1lIHNlcnZlciBzcGFuIGFuZCBydW5zIE1hc3RyYSB1bmRlciBpdC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgU3RyaW5nRGVjb2RlciB9IGZyb20gXCJub2RlOnN0cmluZ19kZWNvZGVyXCI7XG5cbmltcG9ydCB7IGpzb24sIGxvZywgb2JqZWN0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGNvbnRleHQsIFNwYW5LaW5kLCB0cmFjZSwgdHlwZSBTcGFuIH0gZnJvbSBcIkBvcGVudGVsZW1ldHJ5L2FwaVwiO1xuaW1wb3J0IHsgZ2V0UlBDTWV0YWRhdGEsIFJQQ1R5cGUgfSBmcm9tIFwiQG9wZW50ZWxlbWV0cnkvY29yZVwiO1xuaW1wb3J0IHR5cGUgZXhwcmVzcyBmcm9tIFwiZXhwcmVzc1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwibWFzdHJhL3RyYWNlLWlvXCIpO1xuXG4vKiogQ2FwIG9uIGVhY2ggcGF5bG9hZCBjb3BpZWQgb250byBhIHNwYW4sIHNvIG9uZSB0dXJuIGNhbm5vdCBibG9hdCB0aGUgZXhwb3J0LiAqL1xuZXhwb3J0IGNvbnN0IFRSQUNFX0lPX0xJTUlUID0gOF8wMDA7XG5cbi8qKiBCb3VuZCBmb3IgYSBub24tc3RyZWFtaW5nIGJvZHkgY2FwdHVyZWQgdGhyb3VnaCBgcmVzLmVuZGAgaW5zdGVhZCBvZiBgcmVzLmpzb25gLiAqL1xuY29uc3QgUkVTUE9OU0VfQk9EWV9MSU1JVCA9IFRSQUNFX0lPX0xJTUlUICogNDtcblxuLyoqIFRyYWNlciBzY29wZSB1c2VkIG9ubHkgd2hlbiBBcHBLaXQgZGlkIG5vdCBjcmVhdGUgYSByZWNvcmRpbmcgSFRUUCBzcGFuLiAqL1xuY29uc3QgQ0hBVF9UVVJOX1RSQUNFUiA9IFwiQGRieC10b29scy9hcHBraXQtbWFzdHJhL3RyYWNlLWlvXCI7XG5cbi8qKlxuICogTW91bnQtcmVsYXRpdmUgTWFzdHJhIGFnZW50IGludm9rZSBwYXRocyB0aGF0IGNhcnJ5IGEgY2hhdCB0dXJuIGJvZHlcbiAqIChgbWVzc2FnZXNgKSBhbmQgc3RyZWFtIGFuIGFzc2lzdGFudCBhbnN3ZXIuIFJlc3VtZSAvIGFwcHJvdmUgdmVyYnNcbiAqIGFyZSBpbnRlbnRpb25hbGx5IGV4Y2x1ZGVkOiB0aGVpciBib2RpZXMgYXJlIHRvb2wgZGVjaXNpb25zLCBub3QgdGhlXG4gKiB1c2VyIHByb21wdCwgYW5kIHRoZXkgcmFyZWx5IHByb2R1Y2UgYSBmcmVzaCBhbnN3ZXIgd29ydGggc3VyZmFjaW5nLlxuICovXG5jb25zdCBBR0VOVF9UVVJOX1JPVVRFID0gL14oPzpcXC9hZ2VudHNcXC9bXi9dK1xcLyg/OnN0cmVhbXxnZW5lcmF0ZSkoPzpcXC98JCl8XFwvY2hhdFxcL1teL10rJCkvaTtcblxuLyoqIEF0dHJpYnV0ZSBrZXlzIHRoZSBNTGZsb3cgVUMgYCpfdHJhY2VfdW5pZmllZGAgdmlldyByZWFkcyBmcm9tIHRoZSByb290IHNwYW4uICovXG5leHBvcnQgY29uc3QgTUxGTE9XX1NQQU5fSU5QVVRTX0FUVFIgPSBcIm1sZmxvdy5zcGFuSW5wdXRzXCI7XG5leHBvcnQgY29uc3QgTUxGTE9XX1NQQU5fT1VUUFVUU19BVFRSID0gXCJtbGZsb3cuc3Bhbk91dHB1dHNcIjtcblxuaW50ZXJmYWNlIFRyYWNlVGFyZ2V0IHtcbiAgc3BhbjogU3BhbjtcbiAgb3duZWQ6IGJvb2xlYW47XG59XG5cbi8qKiBSZXR1cm4gdGhlIGFzc2lzdGFudCB0ZXh0IGZyb20gb25lIFNTRSBsaW5lLCBvciBhbiBlbXB0eSBzdHJpbmcuICovXG5mdW5jdGlvbiBhc3Npc3RhbnRUZXh0RnJvbVNzZUxpbmUobGluZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKCFsaW5lLnN0YXJ0c1dpdGgoXCJkYXRhOlwiKSkgcmV0dXJuIFwiXCI7XG4gIGNvbnN0IGZyYW1lID0ganNvbi5wYXJzZShsaW5lLnNsaWNlKDUpKTtcbiAgaWYgKCFvYmplY3QuaXNSZWNvcmQoZnJhbWUpIHx8IGZyYW1lLnR5cGUgIT09IFwidGV4dC1kZWx0YVwiKSByZXR1cm4gXCJcIjtcbiAgY29uc3QgdGV4dCA9XG4gICAgdHlwZW9mIGZyYW1lLmRlbHRhID09PSBcInN0cmluZ1wiXG4gICAgICA/IGZyYW1lLmRlbHRhXG4gICAgICA6IG9iamVjdC5pc1JlY29yZChmcmFtZS5wYXlsb2FkKVxuICAgICAgICA/IGZyYW1lLnBheWxvYWQudGV4dFxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgcmV0dXJuIHR5cGVvZiB0ZXh0ID09PSBcInN0cmluZ1wiID8gdGV4dCA6IFwiXCI7XG59XG5cbi8qKlxuICogQ29uY2F0ZW5hdGUgdGhlIGFzc2lzdGFudCdzIGFuc3dlciBvdXQgb2YgYW4gQUkgU0RLIFNTRSB0cmFuc2NyaXB0LlxuICpcbiAqIFRoZSBhZ2VudCBzdHJlYW1zIGl0cyByZXBseSBhcyBgdGV4dC1kZWx0YWAgZnJhbWVzXG4gKiAoYGRhdGE6IHtcInR5cGVcIjpcInRleHQtZGVsdGFcIixcInBheWxvYWRcIjp7XCJ0ZXh0XCI6XCIuLi5cIn19YCksIHNvIHRoZSBmdWxsXG4gKiBhbnN3ZXIgb25seSBldmVyIGV4aXN0cyBhcyBkZWx0YXMgb24gdGhlIHdpcmUgYW5kIGhhcyB0byBiZVxuICogcmVhc3NlbWJsZWQgaGVyZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2lzdGFudFRleHRGcm9tU3NlKGJvZHk6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHBhcnRzOiBzdHJpbmdbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGxpbmUgb2YgYm9keS5zcGxpdChcIlxcblwiKSkge1xuICAgIGNvbnN0IHRleHQgPSBhc3Npc3RhbnRUZXh0RnJvbVNzZUxpbmUobGluZSk7XG4gICAgaWYgKHRleHQpIHBhcnRzLnB1c2godGV4dCk7XG4gIH1cbiAgcmV0dXJuIHBhcnRzLmpvaW4oXCJcIikuc2xpY2UoMCwgVFJBQ0VfSU9fTElNSVQpO1xufVxuXG4vKiogUmVhZCB0aGUgZmluYWwgYXNzaXN0YW50IHRleHQgZnJvbSBhIG5vbi1zdHJlYW1pbmcgTWFzdHJhIHJlc3BvbnNlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2lzdGFudFRleHRGcm9tSnNvbihib2R5OiB1bmtub3duKTogc3RyaW5nIHtcbiAgaWYgKCFvYmplY3QuaXNSZWNvcmQoYm9keSkgfHwgdHlwZW9mIGJvZHkudGV4dCAhPT0gXCJzdHJpbmdcIikgcmV0dXJuIFwiXCI7XG4gIHJldHVybiBib2R5LnRleHQuc2xpY2UoMCwgVFJBQ0VfSU9fTElNSVQpO1xufVxuXG4vKiogSW5jcmVtZW50YWxseSBhc3NlbWJsZSBVVEYtOCBTU0UgdGV4dCB3aGlsZSByZXRhaW5pbmcgYSBib3VuZGVkIEpTT04gZmFsbGJhY2suICovXG5jbGFzcyBBc3Npc3RhbnRSZXNwb25zZUNvbGxlY3RvciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVjb2RlciA9IG5ldyBTdHJpbmdEZWNvZGVyKFwidXRmOFwiKTtcbiAgcHJpdmF0ZSBhbnN3ZXIgPSBcIlwiO1xuICBwcml2YXRlIGJvZHkgPSBcIlwiO1xuICBwcml2YXRlIHBlbmRpbmdMaW5lID0gXCJcIjtcbiAgcHJpdmF0ZSBmaW5pc2hlZCA9IGZhbHNlO1xuXG4gIHdyaXRlKGNodW5rOiB1bmtub3duKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZmluaXNoZWQpIHJldHVybjtcbiAgICBpZiAodHlwZW9mIGNodW5rID09PSBcInN0cmluZ1wiKSB7XG4gICAgICB0aGlzLmNvbnN1bWUoY2h1bmspO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoQXJyYXlCdWZmZXIuaXNWaWV3KGNodW5rKSkge1xuICAgICAgdGhpcy5jb25zdW1lKFxuICAgICAgICB0aGlzLmRlY29kZXIud3JpdGUoQnVmZmVyLmZyb20oY2h1bmsuYnVmZmVyLCBjaHVuay5ieXRlT2Zmc2V0LCBjaHVuay5ieXRlTGVuZ3RoKSksXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGZpbmlzaCgpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLmZpbmlzaGVkKSByZXR1cm4gdGhpcy5hbnN3ZXIgfHwgdGhpcy5qc29uQW5zd2VyKCk7XG4gICAgdGhpcy5maW5pc2hlZCA9IHRydWU7XG4gICAgdGhpcy5jb25zdW1lKHRoaXMuZGVjb2Rlci5lbmQoKSk7XG4gICAgdGhpcy5jb25zdW1lU3NlTGluZSh0aGlzLnBlbmRpbmdMaW5lKTtcbiAgICB0aGlzLnBlbmRpbmdMaW5lID0gXCJcIjtcbiAgICByZXR1cm4gdGhpcy5hbnN3ZXIgfHwgdGhpcy5qc29uQW5zd2VyKCk7XG4gIH1cblxuICBwcml2YXRlIGNvbnN1bWUodGV4dDogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCF0ZXh0KSByZXR1cm47XG4gICAgaWYgKHRoaXMuYm9keS5sZW5ndGggPCBSRVNQT05TRV9CT0RZX0xJTUlUKSB7XG4gICAgICB0aGlzLmJvZHkgKz0gdGV4dC5zbGljZSgwLCBSRVNQT05TRV9CT0RZX0xJTUlUIC0gdGhpcy5ib2R5Lmxlbmd0aCk7XG4gICAgfVxuICAgIHRoaXMucGVuZGluZ0xpbmUgKz0gdGV4dDtcbiAgICBsZXQgbmV3bGluZSA9IHRoaXMucGVuZGluZ0xpbmUuaW5kZXhPZihcIlxcblwiKTtcbiAgICB3aGlsZSAobmV3bGluZSA+PSAwKSB7XG4gICAgICB0aGlzLmNvbnN1bWVTc2VMaW5lKHRoaXMucGVuZGluZ0xpbmUuc2xpY2UoMCwgbmV3bGluZSkucmVwbGFjZSgvXFxyJC8sIFwiXCIpKTtcbiAgICAgIHRoaXMucGVuZGluZ0xpbmUgPSB0aGlzLnBlbmRpbmdMaW5lLnNsaWNlKG5ld2xpbmUgKyAxKTtcbiAgICAgIG5ld2xpbmUgPSB0aGlzLnBlbmRpbmdMaW5lLmluZGV4T2YoXCJcXG5cIik7XG4gICAgfVxuICAgIGlmICh0aGlzLnBlbmRpbmdMaW5lLmxlbmd0aCA+IFJFU1BPTlNFX0JPRFlfTElNSVQpIHtcbiAgICAgIHRoaXMucGVuZGluZ0xpbmUgPSB0aGlzLnBlbmRpbmdMaW5lLnNsaWNlKC1SRVNQT05TRV9CT0RZX0xJTUlUKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNvbnN1bWVTc2VMaW5lKGxpbmU6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLmFuc3dlci5sZW5ndGggPj0gVFJBQ0VfSU9fTElNSVQpIHJldHVybjtcbiAgICBjb25zdCB0ZXh0ID0gYXNzaXN0YW50VGV4dEZyb21Tc2VMaW5lKGxpbmUpO1xuICAgIHRoaXMuYW5zd2VyICs9IHRleHQuc2xpY2UoMCwgVFJBQ0VfSU9fTElNSVQgLSB0aGlzLmFuc3dlci5sZW5ndGgpO1xuICB9XG5cbiAgcHJpdmF0ZSBqc29uQW5zd2VyKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGFzc2lzdGFudFRleHRGcm9tSnNvbihqc29uLnBhcnNlKHRoaXMuYm9keSkpO1xuICB9XG59XG5cbi8qKlxuICogU2VsZWN0IHRoZSBzcGFuIE1MZmxvdyB0cmVhdHMgYXMgdGhlIHJlcXVlc3Qgcm9vdC5cbiAqXG4gKiBPVGVsIEhUVFAgaW5zdHJ1bWVudGF0aW9uIHN0b3JlcyBpdHMgc2VydmVyIHNwYW4gaW4gUlBDIG1ldGFkYXRhLiBUaGF0IHNwYW5cbiAqIHdpbnMgb3ZlciBhbiBhY3RpdmUgRXhwcmVzcyBjaGlsZC4gSWYgbm8gcmVjb3JkaW5nIGxvY2FsIHNwYW4gZXhpc3RzLCBjcmVhdGVcbiAqIG9uZSB1bmRlciB0aGUgY3VycmVudCBjb250ZXh0IHNvIGVuYWJsZWQgVzNDIHByb3BhZ2F0aW9uIHJlbWFpbnMgaW50YWN0LlxuICovXG5mdW5jdGlvbiByZXNvbHZlVHJhY2VUYXJnZXQoKTogVHJhY2VUYXJnZXQgfCB1bmRlZmluZWQge1xuICBjb25zdCBhY3RpdmVDb250ZXh0ID0gY29udGV4dC5hY3RpdmUoKTtcbiAgY29uc3QgcnBjID0gZ2V0UlBDTWV0YWRhdGEoYWN0aXZlQ29udGV4dCk7XG4gIGlmIChycGM/LnR5cGUgPT09IFJQQ1R5cGUuSFRUUCAmJiBycGMuc3Bhbi5pc1JlY29yZGluZygpKSB7XG4gICAgcmV0dXJuIHsgc3BhbjogcnBjLnNwYW4sIG93bmVkOiBmYWxzZSB9O1xuICB9XG5cbiAgY29uc3QgYWN0aXZlID0gdHJhY2UuZ2V0QWN0aXZlU3BhbigpO1xuICBpZiAoYWN0aXZlPy5pc1JlY29yZGluZygpKSByZXR1cm4geyBzcGFuOiBhY3RpdmUsIG93bmVkOiBmYWxzZSB9O1xuXG4gIGNvbnN0IHNwYW4gPSB0cmFjZVxuICAgIC5nZXRUcmFjZXIoQ0hBVF9UVVJOX1RSQUNFUilcbiAgICAuc3RhcnRTcGFuKFwibWFzdHJhLmNoYXRfdHVyblwiLCB7IGtpbmQ6IFNwYW5LaW5kLlNFUlZFUiB9LCBhY3RpdmVDb250ZXh0KTtcbiAgaWYgKCFzcGFuLmlzUmVjb3JkaW5nKCkpIHtcbiAgICBzcGFuLmVuZCgpO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgcmV0dXJuIHsgc3Bhbiwgb3duZWQ6IHRydWUgfTtcbn1cblxuLyoqXG4gKiBFeHByZXNzIG1pZGRsZXdhcmUgdGhhdCBzdGFtcHMgY2hhdCB0dXJuIEkvTyBvbnRvIHRoZSBleHBvcnRlZCBPVGVsIHJvb3QuXG4gKlxuICogVGVlIGByZXMud3JpdGVgLCBgcmVzLmpzb25gLCBhbmQgYHJlcy5lbmRgIGluc3RlYWQgb2YgbGlzdGVuaW5nIGZvciBgZmluaXNoYDpcbiAqIEhUVFAgaW5zdHJ1bWVudGF0aW9uIGVuZHMgaXRzIHNlcnZlciBzcGFuIG9uIGZpbmlzaCwgYW5kIGF0dHJpYnV0ZXMgc2V0XG4gKiBhZnRlciBhIHNwYW4gZW5kcyBuZXZlciByZWFjaCB0aGUgZXhwb3J0ZXIuXG4gKlxuICogYHBhdGhgIGlzIG1vdW50LXJlbGF0aXZlICh3aGF0IHRoZSBNYXN0cmEgc3ViLWFwcCBzZWVzKSwgZS5nLlxuICogYC9hZ2VudHMvc3VwcG9ydC9zdHJlYW1gLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2hhdFR1cm5UcmFjZUlvTWlkZGxld2FyZShcbiAgcmVxOiBleHByZXNzLlJlcXVlc3QsXG4gIHJlczogZXhwcmVzcy5SZXNwb25zZSxcbiAgbmV4dDogZXhwcmVzcy5OZXh0RnVuY3Rpb24sXG4pOiB2b2lkIHtcbiAgaWYgKHJlcS5tZXRob2QgIT09IFwiUE9TVFwiIHx8ICFBR0VOVF9UVVJOX1JPVVRFLnRlc3QocmVxLnBhdGgpKSB7XG4gICAgbmV4dCgpO1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCB0YXJnZXQgPSByZXNvbHZlVHJhY2VUYXJnZXQoKTtcbiAgaWYgKCF0YXJnZXQpIHtcbiAgICBuZXh0KCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgbWVzc2FnZXMgPSAocmVxLmJvZHkgYXMgeyBtZXNzYWdlcz86IHVua25vd24gfSB8IHVuZGVmaW5lZCk/Lm1lc3NhZ2VzO1xuICBpZiAobWVzc2FnZXMgIT09IHVuZGVmaW5lZCkge1xuICAgIHRhcmdldC5zcGFuLnNldEF0dHJpYnV0ZShcbiAgICAgIE1MRkxPV19TUEFOX0lOUFVUU19BVFRSLFxuICAgICAgSlNPTi5zdHJpbmdpZnkobWVzc2FnZXMpLnNsaWNlKDAsIFRSQUNFX0lPX0xJTUlUKSxcbiAgICApO1xuICB9XG5cbiAgY29uc3QgY29sbGVjdG9yID0gbmV3IEFzc2lzdGFudFJlc3BvbnNlQ29sbGVjdG9yKCk7XG4gIGxldCBvdXRwdXRSZWNvcmRlZCA9IGZhbHNlO1xuICBsZXQgb3duZWRTcGFuRW5kZWQgPSBmYWxzZTtcbiAgY29uc3QgcGFzc1Rocm91Z2hXcml0ZSA9IHJlcy53cml0ZS5iaW5kKHJlcykgYXMgKC4uLmFyZ3M6IHVua25vd25bXSkgPT4gYm9vbGVhbjtcbiAgY29uc3QgcGFzc1Rocm91Z2hFbmQgPSByZXMuZW5kLmJpbmQocmVzKSBhcyAoLi4uYXJnczogdW5rbm93bltdKSA9PiB1bmtub3duO1xuICBjb25zdCBwYXNzVGhyb3VnaEpzb24gPSByZXMuanNvbi5iaW5kKHJlcykgYXMgKGJvZHk/OiB1bmtub3duKSA9PiBleHByZXNzLlJlc3BvbnNlO1xuICBjb25zdCByZWNvcmRPdXRwdXQgPSAoYW5zd2VyOiBzdHJpbmcpOiB2b2lkID0+IHtcbiAgICBpZiAob3V0cHV0UmVjb3JkZWQgfHwgIWFuc3dlcikgcmV0dXJuO1xuICAgIHRhcmdldC5zcGFuLnNldEF0dHJpYnV0ZShNTEZMT1dfU1BBTl9PVVRQVVRTX0FUVFIsIGFuc3dlci5zbGljZSgwLCBUUkFDRV9JT19MSU1JVCkpO1xuICAgIG91dHB1dFJlY29yZGVkID0gdHJ1ZTtcbiAgfTtcbiAgY29uc3QgZW5kT3duZWRTcGFuID0gKCk6IHZvaWQgPT4ge1xuICAgIGlmICghdGFyZ2V0Lm93bmVkIHx8IG93bmVkU3BhbkVuZGVkKSByZXR1cm47XG4gICAgb3duZWRTcGFuRW5kZWQgPSB0cnVlO1xuICAgIHRhcmdldC5zcGFuLmVuZCgpO1xuICB9O1xuXG4gIHJlcy53cml0ZSA9ICgoY2h1bms6IHVua25vd24sIC4uLnJlc3Q6IHVua25vd25bXSkgPT4ge1xuICAgIGNvbGxlY3Rvci53cml0ZShjaHVuayk7XG4gICAgcmV0dXJuIHBhc3NUaHJvdWdoV3JpdGUoY2h1bmssIC4uLnJlc3QpO1xuICB9KSBhcyB0eXBlb2YgcmVzLndyaXRlO1xuXG4gIHJlcy5qc29uID0gKChib2R5PzogdW5rbm93bikgPT4ge1xuICAgIHJlY29yZE91dHB1dChhc3Npc3RhbnRUZXh0RnJvbUpzb24oYm9keSkpO1xuICAgIHJldHVybiBwYXNzVGhyb3VnaEpzb24oYm9keSk7XG4gIH0pIGFzIHR5cGVvZiByZXMuanNvbjtcblxuICByZXMuZW5kID0gKChjaHVuaz86IHVua25vd24sIC4uLnJlc3Q6IHVua25vd25bXSkgPT4ge1xuICAgIGNvbGxlY3Rvci53cml0ZShjaHVuayk7XG4gICAgcmVjb3JkT3V0cHV0KGNvbGxlY3Rvci5maW5pc2goKSk7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBwYXNzVGhyb3VnaEVuZChjaHVuaywgLi4ucmVzdCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGVuZE93bmVkU3BhbigpO1xuICAgIH1cbiAgfSkgYXMgdHlwZW9mIHJlcy5lbmQ7XG5cbiAgcmVzLm9uY2UoXCJjbG9zZVwiLCAoKSA9PiB7XG4gICAgcmVjb3JkT3V0cHV0KGNvbGxlY3Rvci5maW5pc2goKSk7XG4gICAgZW5kT3duZWRTcGFuKCk7XG4gIH0pO1xuXG4gIGNvbnRleHQud2l0aCh0cmFjZS5zZXRTcGFuKGNvbnRleHQuYWN0aXZlKCksIHRhcmdldC5zcGFuKSwgbmV4dCk7XG59XG5cbi8qKlxuICogSW5zdGFsbCB7QGxpbmsgY2hhdFR1cm5UcmFjZUlvTWlkZGxld2FyZX0gb24gYSBNYXN0cmEgRXhwcmVzcyBzdWItYXBwLlxuICpcbiAqIENhbGwgYmVmb3JlIGBNYXN0cmFTZXJ2ZXIuaW5pdCgpYCBzbyB0aGUgbGF5ZXIgc2l0cyBhaGVhZCBvZiB0aGUgYWdlbnRcbiAqIHJvdXRlcy4gU2FmZSB0byBjYWxsIHVuY29uZGl0aW9uYWxseTogd2hlbiBubyByZWNvcmRpbmcgdHJhY2VyIGlzIHJlZ2lzdGVyZWQsXG4gKiB0aGUgbWlkZGxld2FyZSBpcyBhIG5vLW9wLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXR0YWNoQ2hhdFR1cm5UcmFjZUlvKGFwcDogZXhwcmVzcy5FeHByZXNzKTogdm9pZCB7XG4gIGFwcC51c2UoY2hhdFR1cm5UcmFjZUlvTWlkZGxld2FyZSk7XG4gIGxvZ2dlci5pbmZvKFwiY2hhdCB0dXJuIEkvTyBtaWRkbGV3YXJlIGF0dGFjaGVkXCIpO1xufVxuIl19
|