@dbx-tools/shared-model 0.3.44 → 0.4.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.
@@ -0,0 +1,686 @@
1
+ /**
2
+ * OpenAI Responses API <-> Chat Completions translation.
3
+ *
4
+ * Some clients speak only the Responses API (`POST /v1/responses`) - the Codex
5
+ * CLI is the motivating one. Databricks now also exposes native Responses
6
+ * surfaces (`/serving-endpoints/responses` and `/serving-endpoints/open-responses`),
7
+ * while most endpoints still speak Chat Completions at `/invocations`. This
8
+ * module bridges the two, in both directions:
9
+ *
10
+ * - {@link responsesToChat} lowers a Responses request body to a chat
11
+ * completions body (instructions -> system message, typed `input` items ->
12
+ * `messages`, `tools`/`tool_choice` carried through, function-call outputs
13
+ * folded back into the transcript).
14
+ * - {@link chatToResponsesRequest} raises a chat-completions request into a
15
+ * Responses request (the inverse of {@link responsesToChat}), for routing a
16
+ * chat client at a Responses-only model like Codex.
17
+ * - {@link chatToResponse} lifts a non-streaming chat completion back into a
18
+ * Responses `response` object.
19
+ * - {@link responseToChatCompletion} lifts a native Responses `response`
20
+ * back into a chat-completions body (the inverse of {@link chatToResponse}).
21
+ * - {@link createResponsesStreamTranslator} lifts a streaming chat completion
22
+ * (an OpenAI SSE `chat.completion.chunk` stream) into the Responses SSE
23
+ * event stream those clients consume (`response.created`,
24
+ * `response.output_text.delta`, function-call argument deltas,
25
+ * `response.completed`).
26
+ * - {@link readResponsesOutput} reads the other direction: pull the answer
27
+ * text and citations out of a `response` object returned by an endpoint
28
+ * that speaks Responses natively (the Databricks native web-search tool).
29
+ * - {@link sanitizeResponsesTools} keeps only `function` tools on a Responses
30
+ * request body (for `/open-responses` / Anthropic, which reject Codex
31
+ * built-ins like `web_search`).
32
+ * - {@link sanitizeOpenResponsesInput} rewrites `output_*` content part types
33
+ * in `input` to `input_*`, and drops Claude thinking / reasoning blocks
34
+ * that Open Responses rejects on replay (`redacted_thinking`, …).
35
+ *
36
+ * Only the surface real clients exercise is translated; unknown fields are
37
+ * ignored rather than rejected, so a newer client degrades instead of breaking.
38
+ *
39
+ * Browser-safe: pure functions over plain JSON, no transport and no Node
40
+ * built-ins, so the same translation runs in a proxy, a server route, or a test.
41
+ *
42
+ * @module
43
+ */
44
+ import { string } from "@dbx-tools/shared-core";
45
+ import { chatContentToText } from "./openai-chat.js";
46
+ /**
47
+ * Lower a Responses request body to a chat-completions body. Returns the chat
48
+ * body plus whether the caller asked for streaming (the server needs it to pick
49
+ * the upstream `accept` header and the translation path).
50
+ */
51
+ export function responsesToChat(body) {
52
+ const messages = [];
53
+ // `instructions` becomes the leading system message.
54
+ if (typeof body.instructions === "string" && body.instructions.length > 0) {
55
+ messages.push({ role: "system", content: body.instructions });
56
+ }
57
+ // `input` is an array of typed items: messages, function_call, and
58
+ // function_call_output. Fold each into the chat transcript.
59
+ const input = Array.isArray(body.input) ? body.input : [];
60
+ for (const raw of input) {
61
+ if (!raw || typeof raw !== "object")
62
+ continue;
63
+ const item = raw;
64
+ const type = item.type;
65
+ if (type === "function_call") {
66
+ // A prior tool call the model made; re-attach it to an assistant turn.
67
+ messages.push({
68
+ role: "assistant",
69
+ content: null,
70
+ tool_calls: [toChatToolCall(item)],
71
+ });
72
+ continue;
73
+ }
74
+ if (type === "function_call_output") {
75
+ // The tool's result, keyed back to the call it answers.
76
+ messages.push({
77
+ role: "tool",
78
+ tool_call_id: String(item.call_id ?? item.id ?? ""),
79
+ content: typeof item.output === "string" ? item.output : chatContentToText(item.output),
80
+ });
81
+ continue;
82
+ }
83
+ // Default: a message item with a role and typed content.
84
+ const role = typeof item.role === "string" ? item.role : "user";
85
+ // Chat has no "developer" role; treat it as system (its intent here).
86
+ const chatRole = role === "developer" ? "system" : role;
87
+ messages.push({ role: chatRole, content: chatContentToText(item.content) });
88
+ }
89
+ const chat = {
90
+ model: body.model,
91
+ messages,
92
+ stream: body.stream === true,
93
+ };
94
+ // Carry through function-calling config when present. Responses function
95
+ // tools are FLAT (`{type:"function", name, description, parameters}`); chat
96
+ // wants them NESTED (`{type:"function", function:{name, …}}`). Clients also
97
+ // send built-in tool types (local_shell, web_search, …) that Databricks chat
98
+ // rejects ("Missing 'function' in the tool specification"), so we translate
99
+ // only function tools and drop the rest.
100
+ if (Array.isArray(body.tools) && body.tools.length > 0) {
101
+ const chatTools = body.tools
102
+ .map(toChatTool)
103
+ .filter((t) => t !== undefined);
104
+ if (chatTools.length > 0) {
105
+ chat.tools = chatTools;
106
+ if (body.tool_choice !== undefined)
107
+ chat.tool_choice = body.tool_choice;
108
+ // NOTE: do NOT forward `parallel_tool_calls`. Clients send it, but
109
+ // Databricks Model Serving's chat API rejects unknown fields
110
+ // ("parallel_tool_calls: Extra inputs are not permitted"), which would
111
+ // fail the whole turn. Drop it.
112
+ }
113
+ }
114
+ return { chat, stream: body.stream === true };
115
+ }
116
+ /**
117
+ * Raise a chat-completions request into a Responses request body. Inverse of
118
+ * {@link responsesToChat}: used when a chat client hits a Responses-only
119
+ * Databricks model (e.g. Codex) so the proxy can POST to
120
+ * `/serving-endpoints/responses` without the client knowing.
121
+ */
122
+ export function chatToResponsesRequest(body) {
123
+ const messages = Array.isArray(body.messages) ? body.messages : [];
124
+ const input = [];
125
+ let instructions;
126
+ for (const raw of messages) {
127
+ if (!raw || typeof raw !== "object")
128
+ continue;
129
+ const message = raw;
130
+ const role = typeof message.role === "string" ? message.role : "user";
131
+ // Leading system / developer messages become top-level `instructions`.
132
+ if ((role === "system" || role === "developer") &&
133
+ instructions === undefined &&
134
+ input.length === 0) {
135
+ const text = chatContentToText(message.content);
136
+ if (text)
137
+ instructions = text;
138
+ continue;
139
+ }
140
+ if (role === "tool") {
141
+ input.push({
142
+ type: "function_call_output",
143
+ call_id: String(message.tool_call_id ?? ""),
144
+ output: chatContentToText(message.content),
145
+ });
146
+ continue;
147
+ }
148
+ if (role === "assistant" &&
149
+ Array.isArray(message.tool_calls) &&
150
+ message.tool_calls.length > 0) {
151
+ for (const rawCall of message.tool_calls) {
152
+ if (!rawCall || typeof rawCall !== "object")
153
+ continue;
154
+ input.push(toFunctionCallItem(rawCall));
155
+ }
156
+ const text = chatContentToText(message.content);
157
+ if (text) {
158
+ input.push({ type: "message", role: "assistant", content: text });
159
+ }
160
+ continue;
161
+ }
162
+ input.push({
163
+ type: "message",
164
+ role,
165
+ content: chatContentToText(message.content),
166
+ });
167
+ }
168
+ const responses = {
169
+ model: body.model,
170
+ input,
171
+ stream: body.stream === true,
172
+ };
173
+ if (instructions)
174
+ responses.instructions = instructions;
175
+ // Chat tools are nested (`function: { name, … }`); Responses wants them flat.
176
+ if (Array.isArray(body.tools) && body.tools.length > 0) {
177
+ const tools = body.tools
178
+ .map(toResponsesTool)
179
+ .filter((t) => t !== undefined);
180
+ if (tools.length > 0) {
181
+ responses.tools = tools;
182
+ if (body.tool_choice !== undefined)
183
+ responses.tool_choice = body.tool_choice;
184
+ }
185
+ }
186
+ // Prefer Responses' max_output_tokens naming; fall back from chat max_tokens.
187
+ if (typeof body.max_output_tokens === "number") {
188
+ responses.max_output_tokens = body.max_output_tokens;
189
+ }
190
+ else if (typeof body.max_tokens === "number") {
191
+ responses.max_output_tokens = body.max_tokens;
192
+ }
193
+ return { responses, stream: body.stream === true };
194
+ }
195
+ /** Lift a non-streaming chat completion JSON into a Responses `response` object. */
196
+ export function chatToResponse(chat, model) {
197
+ const choices = Array.isArray(chat.choices) ? chat.choices : [];
198
+ const first = (choices[0] ?? {});
199
+ const message = (first.message ?? {});
200
+ const output = [];
201
+ const text = typeof message.content === "string" ? message.content : "";
202
+ if (text) {
203
+ output.push({
204
+ type: "message",
205
+ role: "assistant",
206
+ content: [{ type: "output_text", text }],
207
+ });
208
+ }
209
+ // Surface any tool calls as Responses `function_call` output items.
210
+ const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
211
+ for (const raw of toolCalls) {
212
+ output.push(toFunctionCallItem(raw));
213
+ }
214
+ const usage = (chat.usage ?? {});
215
+ return {
216
+ id: String(chat.id ?? "resp"),
217
+ object: "response",
218
+ created_at: typeof chat.created === "number" ? chat.created : 0,
219
+ model,
220
+ status: "completed",
221
+ output,
222
+ usage: {
223
+ input_tokens: Number(usage.prompt_tokens ?? 0),
224
+ output_tokens: Number(usage.completion_tokens ?? 0),
225
+ total_tokens: Number(usage.total_tokens ?? 0),
226
+ },
227
+ };
228
+ }
229
+ /**
230
+ * Lift a native Responses `response` object into a chat-completions body.
231
+ * Inverse of {@link chatToResponse}: used after a Responses-only upstream call
232
+ * when the client spoke Chat Completions.
233
+ */
234
+ export function responseToChatCompletion(response, model) {
235
+ const { text } = readResponsesOutput(response);
236
+ const toolCalls = [];
237
+ const output = Array.isArray(response.output) ? response.output : [];
238
+ for (const raw of output) {
239
+ if (!raw || typeof raw !== "object")
240
+ continue;
241
+ const item = raw;
242
+ if (item.type !== "function_call")
243
+ continue;
244
+ toolCalls.push(toChatToolCall(item));
245
+ }
246
+ const message = {
247
+ role: "assistant",
248
+ content: text || null,
249
+ };
250
+ if (toolCalls.length > 0)
251
+ message.tool_calls = toolCalls;
252
+ const usage = (response.usage ?? {});
253
+ return {
254
+ id: String(response.id ?? "chatcmpl"),
255
+ object: "chat.completion",
256
+ created: typeof response.created_at === "number" ? response.created_at : 0,
257
+ model,
258
+ choices: [
259
+ {
260
+ index: 0,
261
+ message,
262
+ finish_reason: toolCalls.length > 0 ? "tool_calls" : "stop",
263
+ },
264
+ ],
265
+ usage: {
266
+ prompt_tokens: Number(usage.input_tokens ?? 0),
267
+ completion_tokens: Number(usage.output_tokens ?? 0),
268
+ total_tokens: Number(usage.total_tokens ?? 0),
269
+ },
270
+ };
271
+ }
272
+ /**
273
+ * A tool call's `arguments` JSON. Both wires carry it as an unparsed string;
274
+ * anything else (absent, an already-parsed object) becomes an empty literal so
275
+ * the receiving side always has valid JSON to parse.
276
+ */
277
+ function callArguments(value) {
278
+ return typeof value === "string" ? value : "{}";
279
+ }
280
+ /**
281
+ * The Responses `function_call` item for a tool call in either spelling: a chat
282
+ * `tool_calls[]` entry (`{id, function:{name, arguments}}`) or an item that is
283
+ * already flat.
284
+ */
285
+ function toFunctionCallItem(call) {
286
+ const fn = (call.function ?? call);
287
+ return {
288
+ type: "function_call",
289
+ call_id: String(call.call_id ?? call.id ?? ""),
290
+ name: String(fn.name ?? ""),
291
+ arguments: callArguments(fn.arguments),
292
+ };
293
+ }
294
+ /** The chat `tool_calls[]` entry for a Responses `function_call` item. */
295
+ function toChatToolCall(item) {
296
+ return {
297
+ id: String(item.call_id ?? item.id ?? ""),
298
+ type: "function",
299
+ function: {
300
+ name: String(item.name ?? ""),
301
+ arguments: callArguments(item.arguments),
302
+ },
303
+ };
304
+ }
305
+ /**
306
+ * The chat-nested spelling (`{type:"function", function:{name, …}}`) of a tool
307
+ * spec, or `undefined` for a built-in Responses tool (`web_search`,
308
+ * `local_shell`, …) that chat cannot express and Databricks rejects.
309
+ */
310
+ function toChatTool(value) {
311
+ if (!value || typeof value !== "object")
312
+ return undefined;
313
+ const tool = value;
314
+ if (tool.type !== "function")
315
+ return undefined;
316
+ if (tool.function && typeof tool.function === "object")
317
+ return tool; // already nested
318
+ if (typeof tool.name !== "string")
319
+ return undefined;
320
+ return {
321
+ type: "function",
322
+ function: {
323
+ name: tool.name,
324
+ ...(tool.description ? { description: tool.description } : {}),
325
+ ...(tool.parameters ? { parameters: tool.parameters } : {}),
326
+ },
327
+ };
328
+ }
329
+ /**
330
+ * The flat Responses spelling (`{type:"function", name, …}`) of a tool spec.
331
+ * Inverse of {@link toChatTool}; non-function tools are dropped the same way.
332
+ */
333
+ function toResponsesTool(value) {
334
+ if (!value || typeof value !== "object")
335
+ return undefined;
336
+ const tool = value;
337
+ if (tool.type !== "function")
338
+ return undefined;
339
+ if (tool.function && typeof tool.function === "object") {
340
+ const fn = tool.function;
341
+ return {
342
+ type: "function",
343
+ name: fn.name,
344
+ ...(fn.description ? { description: fn.description } : {}),
345
+ ...(fn.parameters ? { parameters: fn.parameters } : {}),
346
+ };
347
+ }
348
+ return typeof tool.name === "string" ? tool : undefined; // already flat
349
+ }
350
+ /** One Server-Sent Event, ready to write to the client. */
351
+ function sse(event, data) {
352
+ return `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
353
+ }
354
+ /**
355
+ * Translate an upstream chat-completions SSE stream into the Responses SSE
356
+ * event stream a Responses client consumes.
357
+ *
358
+ * Upstream chunks are `chat.completion.chunk` objects whose `choices[0].delta`
359
+ * carries incremental `content` (assistant text) and/or `tool_calls` (function
360
+ * calls, streamed by `index` with partial `arguments`). We emit the Responses
361
+ * lifecycle around them:
362
+ *
363
+ * response.created
364
+ * -> per text run: output_item.added → output_text.delta* → output_item.done
365
+ * -> per tool call: output_item.added → function_call_arguments.delta*
366
+ * → function_call_arguments.done → output_item.done
367
+ * response.completed (with the assembled final `response` object)
368
+ *
369
+ * The translator is intentionally tolerant: malformed/keepalive lines yield
370
+ * nothing.
371
+ */
372
+ export function createResponsesStreamTranslator(model, responseId) {
373
+ let started = false;
374
+ let outputIndex = 0;
375
+ // Text run state: whether a message item is currently open, and its buffer.
376
+ let textOpen = false;
377
+ let textBuffer = "";
378
+ let textItemId = "";
379
+ const tools = new Map();
380
+ const created = () => sse("response.created", {
381
+ type: "response.created",
382
+ response: { id: responseId, object: "response", status: "in_progress", model, output: [] },
383
+ });
384
+ function openText() {
385
+ textOpen = true;
386
+ textItemId = `${responseId}-msg-${outputIndex}`;
387
+ const ev = sse("response.output_item.added", {
388
+ type: "response.output_item.added",
389
+ output_index: outputIndex,
390
+ item: { id: textItemId, type: "message", role: "assistant", content: [] },
391
+ });
392
+ return ev;
393
+ }
394
+ function closeText() {
395
+ if (!textOpen)
396
+ return "";
397
+ const item = {
398
+ id: textItemId,
399
+ type: "message",
400
+ role: "assistant",
401
+ content: [{ type: "output_text", text: textBuffer }],
402
+ };
403
+ const ev = sse("response.output_text.done", {
404
+ type: "response.output_text.done",
405
+ item_id: textItemId,
406
+ output_index: outputIndex,
407
+ content_index: 0,
408
+ text: textBuffer,
409
+ }) +
410
+ sse("response.output_item.done", {
411
+ type: "response.output_item.done",
412
+ output_index: outputIndex,
413
+ item,
414
+ });
415
+ textOpen = false;
416
+ textBuffer = "";
417
+ outputIndex += 1;
418
+ return ev;
419
+ }
420
+ function feed(chunk) {
421
+ let out = "";
422
+ if (!started) {
423
+ started = true;
424
+ out += created();
425
+ }
426
+ const choices = Array.isArray(chunk.choices) ? chunk.choices : [];
427
+ const choice = (choices[0] ?? {});
428
+ const delta = (choice.delta ?? {});
429
+ // Assistant text deltas.
430
+ if (typeof delta.content === "string" && delta.content.length > 0) {
431
+ if (!textOpen)
432
+ out += openText();
433
+ textBuffer += delta.content;
434
+ out += sse("response.output_text.delta", {
435
+ type: "response.output_text.delta",
436
+ item_id: textItemId,
437
+ output_index: outputIndex,
438
+ content_index: 0,
439
+ delta: delta.content,
440
+ });
441
+ }
442
+ // Tool-call deltas: each is keyed by `index`; `arguments` arrives in pieces.
443
+ const toolDeltas = Array.isArray(delta.tool_calls) ? delta.tool_calls : [];
444
+ for (const rawTc of toolDeltas) {
445
+ const tc = rawTc;
446
+ const idx = Number(tc.index ?? 0);
447
+ const fn = (tc.function ?? {});
448
+ let state = tools.get(idx);
449
+ if (!state) {
450
+ // First fragment for this call: a text run (if open) must close first so
451
+ // output ordering stays monotonic, then we open a function_call item.
452
+ out += closeText();
453
+ state = {
454
+ outputIndex,
455
+ callId: String(tc.id ?? `${responseId}-call-${idx}`),
456
+ name: String(fn.name ?? ""),
457
+ args: "",
458
+ };
459
+ tools.set(idx, state);
460
+ out += sse("response.output_item.added", {
461
+ type: "response.output_item.added",
462
+ output_index: state.outputIndex,
463
+ item: {
464
+ id: state.callId,
465
+ type: "function_call",
466
+ call_id: state.callId,
467
+ name: state.name,
468
+ arguments: "",
469
+ },
470
+ });
471
+ outputIndex += 1;
472
+ }
473
+ if (typeof fn.name === "string" && fn.name && !state.name)
474
+ state.name = fn.name;
475
+ if (typeof fn.arguments === "string" && fn.arguments.length > 0) {
476
+ state.args += fn.arguments;
477
+ out += sse("response.function_call_arguments.delta", {
478
+ type: "response.function_call_arguments.delta",
479
+ item_id: state.callId,
480
+ output_index: state.outputIndex,
481
+ delta: fn.arguments,
482
+ });
483
+ }
484
+ }
485
+ return out;
486
+ }
487
+ function finish() {
488
+ let out = closeText();
489
+ // Close any open tool calls, emitting their assembled arguments.
490
+ for (const state of tools.values()) {
491
+ out += sse("response.function_call_arguments.done", {
492
+ type: "response.function_call_arguments.done",
493
+ item_id: state.callId,
494
+ output_index: state.outputIndex,
495
+ arguments: state.args,
496
+ });
497
+ out += sse("response.output_item.done", {
498
+ type: "response.output_item.done",
499
+ output_index: state.outputIndex,
500
+ item: {
501
+ id: state.callId,
502
+ type: "function_call",
503
+ call_id: state.callId,
504
+ name: state.name,
505
+ arguments: state.args,
506
+ },
507
+ });
508
+ }
509
+ out += sse("response.completed", {
510
+ type: "response.completed",
511
+ response: { id: responseId, object: "response", status: "completed", model },
512
+ });
513
+ return out;
514
+ }
515
+ return { feed, finish };
516
+ }
517
+ /**
518
+ * Read the answer text and cited sources out of a Responses `response` payload.
519
+ *
520
+ * This is the inverse of {@link chatToResponse}: it consumes what an endpoint
521
+ * speaking Responses natively returns, rather than producing it. The Databricks
522
+ * native web-search tool answers this way, with each source attached as a
523
+ * `url_citation` annotation on the content part that used it.
524
+ *
525
+ * Prefers the flattened `output_text` when the payload carries it, and falls
526
+ * back to walking `output[].content[].text`. Every field is optional upstream,
527
+ * so a payload missing any of it yields empty results rather than throwing.
528
+ */
529
+ export function readResponsesOutput(payload) {
530
+ const output = Array.isArray(payload.output) ? payload.output : [];
531
+ const texts = [];
532
+ const citations = [];
533
+ const seen = new Set();
534
+ for (const rawItem of output) {
535
+ if (!rawItem || typeof rawItem !== "object")
536
+ continue;
537
+ const content = rawItem.content;
538
+ if (!Array.isArray(content))
539
+ continue;
540
+ for (const rawPart of content) {
541
+ if (!rawPart || typeof rawPart !== "object")
542
+ continue;
543
+ const part = rawPart;
544
+ const text = string.trimToEmpty(part.text);
545
+ if (text)
546
+ texts.push(text);
547
+ const annotations = Array.isArray(part.annotations) ? part.annotations : [];
548
+ for (const rawAnn of annotations) {
549
+ if (!rawAnn || typeof rawAnn !== "object")
550
+ continue;
551
+ const ann = rawAnn;
552
+ const url = string.trimToEmpty(ann.url);
553
+ if (!url || seen.has(url))
554
+ continue;
555
+ seen.add(url);
556
+ const title = string.trimToEmpty(ann.title);
557
+ citations.push({ url, ...(title ? { title } : {}) });
558
+ }
559
+ }
560
+ }
561
+ return { text: string.trimToEmpty(payload.output_text) || texts.join("\n").trim(), citations };
562
+ }
563
+ /**
564
+ * Strip tool types the upstream model doesn't support from a Responses request
565
+ * body, returning a shallow copy safe to forward (the input is not mutated).
566
+ *
567
+ * Clients like the Codex CLI include built-in Responses tools (`web_search`,
568
+ * `local_shell`, `custom`, ...) alongside their `function` tools. Databricks'
569
+ * Open Responses surface for Anthropic/Claude (and other non-OpenAI providers)
570
+ * only accepts `function` tools and hard-errors otherwise:
571
+ * "Anthropic does not support tool type 'web_search'. Only 'function' is supported."
572
+ * Call this before forwarding to `/serving-endpoints/open-responses`. The OpenAI
573
+ * `/serving-endpoints/responses` path should keep built-ins (GPT supports them).
574
+ * If filtering empties the list, `tools` / `tool_choice` / `parallel_tool_calls`
575
+ * are dropped so we never send an empty `tools: []`.
576
+ */
577
+ export function sanitizeResponsesTools(body) {
578
+ if (!Array.isArray(body.tools) || body.tools.length === 0)
579
+ return body;
580
+ const fnTools = body.tools.filter((t) => t && typeof t === "object" && t.type === "function");
581
+ if (fnTools.length === body.tools.length)
582
+ return body; // nothing to strip
583
+ const next = { ...body };
584
+ if (fnTools.length > 0) {
585
+ next.tools = fnTools;
586
+ }
587
+ else {
588
+ delete next.tools;
589
+ delete next.tool_choice;
590
+ delete next.parallel_tool_calls;
591
+ }
592
+ return next;
593
+ }
594
+ /**
595
+ * Content-part / input-item types Claude extended thinking uses on the wire.
596
+ *
597
+ * Shared so both wire surfaces strip the same set: the Responses path here
598
+ * ({@link sanitizeOpenResponsesInput}) and the Chat Completions path in
599
+ * `@dbx-tools/appkit-mastra`'s serving sanitize. Anthropic signs these blocks,
600
+ * so a replay that mutates one is rejected outright - both paths must agree on
601
+ * what counts as a reasoning block.
602
+ */
603
+ export const REASONING_TYPES = new Set([
604
+ "reasoning",
605
+ "thinking",
606
+ "redacted_thinking",
607
+ ]);
608
+ /**
609
+ * Rewrite Responses `input` so Open Responses will accept it.
610
+ *
611
+ * Two OpenAI / Codex shapes that Databricks Open Responses (Claude, Gemini, …)
612
+ * reject:
613
+ *
614
+ * 1. Prior assistant turns with `output_text` / `output_*` content parts —
615
+ * Open Responses only allows `input_text`, `input_image`, `input_file`,
616
+ * `input_audio`. Map every `output_<kind>` part to `input_<kind>`.
617
+ * 2. Replayed extended-thinking blocks (`thinking`, `redacted_thinking`,
618
+ * `reasoning` content parts, and top-level `reasoning` input items). Claude
619
+ * signs those; any client round-trip that mutates them (or a cross-provider
620
+ * replay) fails with e.g.
621
+ * "messages.N.content.M: Invalid `data` in `redacted_thinking` block"
622
+ * Strip them — the UI/client already showed the thinking; replay does not
623
+ * need the signed blob. Same policy as appkit-mastra's serving sanitize.
624
+ *
625
+ * Returns a shallow copy when anything changes; otherwise the input body.
626
+ */
627
+ export function sanitizeOpenResponsesInput(body) {
628
+ if (!Array.isArray(body.input) || body.input.length === 0)
629
+ return body;
630
+ let changed = false;
631
+ const input = [];
632
+ for (const raw of body.input) {
633
+ if (!raw || typeof raw !== "object") {
634
+ input.push(raw);
635
+ continue;
636
+ }
637
+ const item = raw;
638
+ // Top-level Responses reasoning items (not message content parts).
639
+ if (typeof item.type === "string" && REASONING_TYPES.has(item.type)) {
640
+ changed = true;
641
+ continue;
642
+ }
643
+ if (!Array.isArray(item.content)) {
644
+ input.push(raw);
645
+ continue;
646
+ }
647
+ let partChanged = false;
648
+ const content = [];
649
+ for (const part of item.content) {
650
+ if (!part || typeof part !== "object") {
651
+ content.push(part);
652
+ continue;
653
+ }
654
+ const p = part;
655
+ if (typeof p.type === "string" && REASONING_TYPES.has(p.type)) {
656
+ partChanged = true;
657
+ continue;
658
+ }
659
+ if (typeof p.type === "string" && p.type.startsWith("output_")) {
660
+ partChanged = true;
661
+ content.push({ ...p, type: `input_${p.type.slice("output_".length)}` });
662
+ continue;
663
+ }
664
+ content.push(part);
665
+ }
666
+ if (!partChanged) {
667
+ input.push(raw);
668
+ continue;
669
+ }
670
+ changed = true;
671
+ // Drop assistant turns that only carried thinking (nothing left to replay).
672
+ if (content.length === 0 && item.role === "assistant")
673
+ continue;
674
+ input.push({ ...item, content });
675
+ }
676
+ return changed ? { ...body, input } : body;
677
+ }
678
+ /**
679
+ * Full Open Responses request sanitizer: strip non-`function` tools, rewrite
680
+ * `output_*` content parts, and drop thinking / reasoning blocks. Safe no-op
681
+ * when nothing needs changing.
682
+ */
683
+ export function sanitizeOpenResponsesRequest(body) {
684
+ return sanitizeOpenResponsesInput(sanitizeResponsesTools(body));
685
+ }
686
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLXJlc3BvbnNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9vcGVuYWktcmVzcG9uc2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EwQ0c7QUFFSCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFaEQsT0FBTyxFQUF1QyxpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUV2Rjs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FBQyxJQUE2QjtJQUkzRCxNQUFNLFFBQVEsR0FBa0IsRUFBRSxDQUFDO0lBRW5DLHFEQUFxRDtJQUNyRCxJQUFJLE9BQU8sSUFBSSxDQUFDLFlBQVksS0FBSyxRQUFRLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDMUUsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFFRCxtRUFBbUU7SUFDbkUsNERBQTREO0lBQzVELE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDMUQsS0FBSyxNQUFNLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsR0FBRyxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVE7WUFBRSxTQUFTO1FBQzlDLE1BQU0sSUFBSSxHQUFHLEdBQThCLENBQUM7UUFDNUMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztRQUV2QixJQUFJLElBQUksS0FBSyxlQUFlLEVBQUUsQ0FBQztZQUM3Qix1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TUFBTSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQ3hFLFNBQVM7WUFDWCxDQUFDO1lBQ0QsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNyQixDQUFDO1FBRUQsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ2pCLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDaEIsU0FBUztRQUNYLENBQUM7UUFDRCxPQUFPLEdBQUcsSUFBSSxDQUFDO1FBQ2YsNEVBQTRFO1FBQzVFLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxXQUFXO1lBQUUsU0FBUztRQUNoRSxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQsT0FBTyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztBQUM3QyxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSw0QkFBNEIsQ0FDMUMsSUFBNkI7SUFFN0IsT0FBTywwQkFBMEIsQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ2xFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE9wZW5BSSBSZXNwb25zZXMgQVBJIDwtPiBDaGF0IENvbXBsZXRpb25zIHRyYW5zbGF0aW9uLlxuICpcbiAqIFNvbWUgY2xpZW50cyBzcGVhayBvbmx5IHRoZSBSZXNwb25zZXMgQVBJIChgUE9TVCAvdjEvcmVzcG9uc2VzYCkgLSB0aGUgQ29kZXhcbiAqIENMSSBpcyB0aGUgbW90aXZhdGluZyBvbmUuIERhdGFicmlja3Mgbm93IGFsc28gZXhwb3NlcyBuYXRpdmUgUmVzcG9uc2VzXG4gKiBzdXJmYWNlcyAoYC9zZXJ2aW5nLWVuZHBvaW50cy9yZXNwb25zZXNgIGFuZCBgL3NlcnZpbmctZW5kcG9pbnRzL29wZW4tcmVzcG9uc2VzYCksXG4gKiB3aGlsZSBtb3N0IGVuZHBvaW50cyBzdGlsbCBzcGVhayBDaGF0IENvbXBsZXRpb25zIGF0IGAvaW52b2NhdGlvbnNgLiBUaGlzXG4gKiBtb2R1bGUgYnJpZGdlcyB0aGUgdHdvLCBpbiBib3RoIGRpcmVjdGlvbnM6XG4gKlxuICogICAtIHtAbGluayByZXNwb25zZXNUb0NoYXR9IGxvd2VycyBhIFJlc3BvbnNlcyByZXF1ZXN0IGJvZHkgdG8gYSBjaGF0XG4gKiAgICAgY29tcGxldGlvbnMgYm9keSAoaW5zdHJ1Y3Rpb25zIC0+IHN5c3RlbSBtZXNzYWdlLCB0eXBlZCBgaW5wdXRgIGl0ZW1zIC0+XG4gKiAgICAgYG1lc3NhZ2VzYCwgYHRvb2xzYC9gdG9vbF9jaG9pY2VgIGNhcnJpZWQgdGhyb3VnaCwgZnVuY3Rpb24tY2FsbCBvdXRwdXRzXG4gKiAgICAgZm9sZGVkIGJhY2sgaW50byB0aGUgdHJhbnNjcmlwdCkuXG4gKiAgIC0ge0BsaW5rIGNoYXRUb1Jlc3BvbnNlc1JlcXVlc3R9IHJhaXNlcyBhIGNoYXQtY29tcGxldGlvbnMgcmVxdWVzdCBpbnRvIGFcbiAqICAgICBSZXNwb25zZXMgcmVxdWVzdCAodGhlIGludmVyc2Ugb2Yge0BsaW5rIHJlc3BvbnNlc1RvQ2hhdH0pLCBmb3Igcm91dGluZyBhXG4gKiAgICAgY2hhdCBjbGllbnQgYXQgYSBSZXNwb25zZXMtb25seSBtb2RlbCBsaWtlIENvZGV4LlxuICogICAtIHtAbGluayBjaGF0VG9SZXNwb25zZX0gbGlmdHMgYSBub24tc3RyZWFtaW5nIGNoYXQgY29tcGxldGlvbiBiYWNrIGludG8gYVxuICogICAgIFJlc3BvbnNlcyBgcmVzcG9uc2VgIG9iamVjdC5cbiAqICAgLSB7QGxpbmsgcmVzcG9uc2VUb0NoYXRDb21wbGV0aW9ufSBsaWZ0cyBhIG5hdGl2ZSBSZXNwb25zZXMgYHJlc3BvbnNlYFxuICogICAgIGJhY2sgaW50byBhIGNoYXQtY29tcGxldGlvbnMgYm9keSAodGhlIGludmVyc2Ugb2Yge0BsaW5rIGNoYXRUb1Jlc3BvbnNlfSkuXG4gKiAgIC0ge0BsaW5rIGNyZWF0ZVJlc3BvbnNlc1N0cmVhbVRyYW5zbGF0b3J9IGxpZnRzIGEgc3RyZWFtaW5nIGNoYXQgY29tcGxldGlvblxuICogICAgIChhbiBPcGVuQUkgU1NFIGBjaGF0LmNvbXBsZXRpb24uY2h1bmtgIHN0cmVhbSkgaW50byB0aGUgUmVzcG9uc2VzIFNTRVxuICogICAgIGV2ZW50IHN0cmVhbSB0aG9zZSBjbGllbnRzIGNvbnN1bWUgKGByZXNwb25zZS5jcmVhdGVkYCxcbiAqICAgICBgcmVzcG9uc2Uub3V0cHV0X3RleHQuZGVsdGFgLCBmdW5jdGlvbi1jYWxsIGFyZ3VtZW50IGRlbHRhcyxcbiAqICAgICBgcmVzcG9uc2UuY29tcGxldGVkYCkuXG4gKiAgIC0ge0BsaW5rIHJlYWRSZXNwb25zZXNPdXRwdXR9IHJlYWRzIHRoZSBvdGhlciBkaXJlY3Rpb246IHB1bGwgdGhlIGFuc3dlclxuICogICAgIHRleHQgYW5kIGNpdGF0aW9ucyBvdXQgb2YgYSBgcmVzcG9uc2VgIG9iamVjdCByZXR1cm5lZCBieSBhbiBlbmRwb2ludFxuICogICAgIHRoYXQgc3BlYWtzIFJlc3BvbnNlcyBuYXRpdmVseSAodGhlIERhdGFicmlja3MgbmF0aXZlIHdlYi1zZWFyY2ggdG9vbCkuXG4gKiAgIC0ge0BsaW5rIHNhbml0aXplUmVzcG9uc2VzVG9vbHN9IGtlZXBzIG9ubHkgYGZ1bmN0aW9uYCB0b29scyBvbiBhIFJlc3BvbnNlc1xuICogICAgIHJlcXVlc3QgYm9keSAoZm9yIGAvb3Blbi1yZXNwb25zZXNgIC8gQW50aHJvcGljLCB3aGljaCByZWplY3QgQ29kZXhcbiAqICAgICBidWlsdC1pbnMgbGlrZSBgd2ViX3NlYXJjaGApLlxuICogICAtIHtAbGluayBzYW5pdGl6ZU9wZW5SZXNwb25zZXNJbnB1dH0gcmV3cml0ZXMgYG91dHB1dF8qYCBjb250ZW50IHBhcnQgdHlwZXNcbiAqICAgICBpbiBgaW5wdXRgIHRvIGBpbnB1dF8qYCwgYW5kIGRyb3BzIENsYXVkZSB0aGlua2luZyAvIHJlYXNvbmluZyBibG9ja3NcbiAqICAgICB0aGF0IE9wZW4gUmVzcG9uc2VzIHJlamVjdHMgb24gcmVwbGF5IChgcmVkYWN0ZWRfdGhpbmtpbmdgLCDigKYpLlxuICpcbiAqIE9ubHkgdGhlIHN1cmZhY2UgcmVhbCBjbGllbnRzIGV4ZXJjaXNlIGlzIHRyYW5zbGF0ZWQ7IHVua25vd24gZmllbGRzIGFyZVxuICogaWdub3JlZCByYXRoZXIgdGhhbiByZWplY3RlZCwgc28gYSBuZXdlciBjbGllbnQgZGVncmFkZXMgaW5zdGVhZCBvZiBicmVha2luZy5cbiAqXG4gKiBCcm93c2VyLXNhZmU6IHB1cmUgZnVuY3Rpb25zIG92ZXIgcGxhaW4gSlNPTiwgbm8gdHJhbnNwb3J0IGFuZCBubyBOb2RlXG4gKiBidWlsdC1pbnMsIHNvIHRoZSBzYW1lIHRyYW5zbGF0aW9uIHJ1bnMgaW4gYSBwcm94eSwgYSBzZXJ2ZXIgcm91dGUsIG9yIGEgdGVzdC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgc3RyaW5nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcblxuaW1wb3J0IHsgdHlwZSBDaGF0TWVzc2FnZSwgdHlwZSBDaGF0VG9vbENhbGwsIGNoYXRDb250ZW50VG9UZXh0IH0gZnJvbSBcIi4vb3BlbmFpLWNoYXRcIjtcblxuLyoqXG4gKiBMb3dlciBhIFJlc3BvbnNlcyByZXF1ZXN0IGJvZHkgdG8gYSBjaGF0LWNvbXBsZXRpb25zIGJvZHkuIFJldHVybnMgdGhlIGNoYXRcbiAqIGJvZHkgcGx1cyB3aGV0aGVyIHRoZSBjYWxsZXIgYXNrZWQgZm9yIHN0cmVhbWluZyAodGhlIHNlcnZlciBuZWVkcyBpdCB0byBwaWNrXG4gKiB0aGUgdXBzdHJlYW0gYGFjY2VwdGAgaGVhZGVyIGFuZCB0aGUgdHJhbnNsYXRpb24gcGF0aCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNwb25zZXNUb0NoYXQoYm9keTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiB7XG4gIGNoYXQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBzdHJlYW06IGJvb2xlYW47XG59IHtcbiAgY29uc3QgbWVzc2FnZXM6IENoYXRNZXNzYWdlW10gPSBbXTtcblxuICAvLyBgaW5zdHJ1Y3Rpb25zYCBiZWNvbWVzIHRoZSBsZWFkaW5nIHN5c3RlbSBtZXNzYWdlLlxuICBpZiAodHlwZW9mIGJvZHkuaW5zdHJ1Y3Rpb25zID09PSBcInN0cmluZ1wiICYmIGJvZHkuaW5zdHJ1Y3Rpb25zLmxlbmd0aCA+IDApIHtcbiAgICBtZXNzYWdlcy5wdXNoKHsgcm9sZTogXCJzeXN0ZW1cIiwgY29udGVudDogYm9keS5pbnN0cnVjdGlvbnMgfSk7XG4gIH1cblxuICAvLyBgaW5wdXRgIGlzIGFuIGFycmF5IG9mIHR5cGVkIGl0ZW1zOiBtZXNzYWdlcywgZnVuY3Rpb25fY2FsbCwgYW5kXG4gIC8vIGZ1bmN0aW9uX2NhbGxfb3V0cHV0LiBGb2xkIGVhY2ggaW50byB0aGUgY2hhdCB0cmFuc2NyaXB0LlxuICBjb25zdCBpbnB1dCA9IEFycmF5LmlzQXJyYXkoYm9keS5pbnB1dCkgPyBib2R5LmlucHV0IDogW107XG4gIGZvciAoY29uc3QgcmF3IG9mIGlucHV0KSB7XG4gICAgaWYgKCFyYXcgfHwgdHlwZW9mIHJhdyAhPT0gXCJvYmplY3RcIikgY29udGludWU7XG4gICAgY29uc3QgaXRlbSA9IHJhdyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICBjb25zdCB0eXBlID0gaXRlbS50eXBlO1xuXG4gICAgaWYgKHR5cGUgPT09IFwiZnVuY3Rpb25fY2FsbFwiKSB7XG4gICAgICAvLyBBIHByaW9yIHRvb2wgY2FsbCB0aGUgbW9kZWwgbWFkZTsgcmUtYXR0YWNoIGl0IHRvIGFuIGFzc2lzdGFudCB0dXJuLlxuICAgICAgbWVzc2FnZXMucHVzaCh7XG4gICAgICAgIHJvbGU6IFwiYXNzaXN0YW50XCIsXG4gICAgICAgIGNvbnRlbnQ6IG51bGwsXG4gICAgICAgIHRvb2xfY2FsbHM6IFt0b0NoYXRUb29sQ2FsbChpdGVtKV0sXG4gICAgICB9KTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmICh0eXBlID09PSBcImZ1bmN0aW9uX2NhbGxfb3V0cHV0XCIpIHtcbiAgICAgIC8vIFRoZSB0b29sJ3MgcmVzdWx0LCBrZXllZCBiYWNrIHRvIHRoZSBjYWxsIGl0IGFuc3dlcnMuXG4gICAgICBtZXNzYWdlcy5wdXNoKHtcbiAgICAgICAgcm9sZTogXCJ0b29sXCIsXG4gICAgICAgIHRvb2xfY2FsbF9pZDogU3RyaW5nKGl0ZW0uY2FsbF9pZCA/PyBpdGVtLmlkID8/IFwiXCIpLFxuICAgICAgICBjb250ZW50OiB0eXBlb2YgaXRlbS5vdXRwdXQgPT09IFwic3RyaW5nXCIgPyBpdGVtLm91dHB1dCA6IGNoYXRDb250ZW50VG9UZXh0KGl0ZW0ub3V0cHV0KSxcbiAgICAgIH0pO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gRGVmYXVsdDogYSBtZXNzYWdlIGl0ZW0gd2l0aCBhIHJvbGUgYW5kIHR5cGVkIGNvbnRlbnQuXG4gICAgY29uc3Qgcm9sZSA9IHR5cGVvZiBpdGVtLnJvbGUgPT09IFwic3RyaW5nXCIgPyBpdGVtLnJvbGUgOiBcInVzZXJcIjtcbiAgICAvLyBDaGF0IGhhcyBubyBcImRldmVsb3BlclwiIHJvbGU7IHRyZWF0IGl0IGFzIHN5c3RlbSAoaXRzIGludGVudCBoZXJlKS5cbiAgICBjb25zdCBjaGF0Um9sZSA9IHJvbGUgPT09IFwiZGV2ZWxvcGVyXCIgPyBcInN5c3RlbVwiIDogcm9sZTtcbiAgICBtZXNzYWdlcy5wdXNoKHsgcm9sZTogY2hhdFJvbGUsIGNvbnRlbnQ6IGNoYXRDb250ZW50VG9UZXh0KGl0ZW0uY29udGVudCkgfSk7XG4gIH1cblxuICBjb25zdCBjaGF0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcbiAgICBtb2RlbDogYm9keS5tb2RlbCxcbiAgICBtZXNzYWdlcyxcbiAgICBzdHJlYW06IGJvZHkuc3RyZWFtID09PSB0cnVlLFxuICB9O1xuXG4gIC8vIENhcnJ5IHRocm91Z2ggZnVuY3Rpb24tY2FsbGluZyBjb25maWcgd2hlbiBwcmVzZW50LiBSZXNwb25zZXMgZnVuY3Rpb25cbiAgLy8gdG9vbHMgYXJlIEZMQVQgKGB7dHlwZTpcImZ1bmN0aW9uXCIsIG5hbWUsIGRlc2NyaXB0aW9uLCBwYXJhbWV0ZXJzfWApOyBjaGF0XG4gIC8vIHdhbnRzIHRoZW0gTkVTVEVEIChge3R5cGU6XCJmdW5jdGlvblwiLCBmdW5jdGlvbjp7bmFtZSwg4oCmfX1gKS4gQ2xpZW50cyBhbHNvXG4gIC8vIHNlbmQgYnVpbHQtaW4gdG9vbCB0eXBlcyAobG9jYWxfc2hlbGwsIHdlYl9zZWFyY2gsIOKApikgdGhhdCBEYXRhYnJpY2tzIGNoYXRcbiAgLy8gcmVqZWN0cyAoXCJNaXNzaW5nICdmdW5jdGlvbicgaW4gdGhlIHRvb2wgc3BlY2lmaWNhdGlvblwiKSwgc28gd2UgdHJhbnNsYXRlXG4gIC8vIG9ubHkgZnVuY3Rpb24gdG9vbHMgYW5kIGRyb3AgdGhlIHJlc3QuXG4gIGlmIChBcnJheS5pc0FycmF5KGJvZHkudG9vbHMpICYmIGJvZHkudG9vbHMubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGNoYXRUb29scyA9IGJvZHkudG9vbHNcbiAgICAgIC5tYXAodG9DaGF0VG9vbClcbiAgICAgIC5maWx0ZXIoKHQpOiB0IGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0+IHQgIT09IHVuZGVmaW5lZCk7XG4gICAgaWYgKGNoYXRUb29scy5sZW5ndGggPiAwKSB7XG4gICAgICBjaGF0LnRvb2xzID0gY2hhdFRvb2xzO1xuICAgICAgaWYgKGJvZHkudG9vbF9jaG9pY2UgIT09IHVuZGVmaW5lZCkgY2hhdC50b29sX2Nob2ljZSA9IGJvZHkudG9vbF9jaG9pY2U7XG4gICAgICAvLyBOT1RFOiBkbyBOT1QgZm9yd2FyZCBgcGFyYWxsZWxfdG9vbF9jYWxsc2AuIENsaWVudHMgc2VuZCBpdCwgYnV0XG4gICAgICAvLyBEYXRhYnJpY2tzIE1vZGVsIFNlcnZpbmcncyBjaGF0IEFQSSByZWplY3RzIHVua25vd24gZmllbGRzXG4gICAgICAvLyAoXCJwYXJhbGxlbF90b29sX2NhbGxzOiBFeHRyYSBpbnB1dHMgYXJlIG5vdCBwZXJtaXR0ZWRcIiksIHdoaWNoIHdvdWxkXG4gICAgICAvLyBmYWlsIHRoZSB3aG9sZSB0dXJuLiBEcm9wIGl0LlxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7IGNoYXQsIHN0cmVhbTogYm9keS5zdHJlYW0gPT09IHRydWUgfTtcbn1cblxuLyoqXG4gKiBSYWlzZSBhIGNoYXQtY29tcGxldGlvbnMgcmVxdWVzdCBpbnRvIGEgUmVzcG9uc2VzIHJlcXVlc3QgYm9keS4gSW52ZXJzZSBvZlxuICoge0BsaW5rIHJlc3BvbnNlc1RvQ2hhdH06IHVzZWQgd2hlbiBhIGNoYXQgY2xpZW50IGhpdHMgYSBSZXNwb25zZXMtb25seVxuICogRGF0YWJyaWNrcyBtb2RlbCAoZS5nLiBDb2RleCkgc28gdGhlIHByb3h5IGNhbiBQT1NUIHRvXG4gKiBgL3NlcnZpbmctZW5kcG9pbnRzL3Jlc3BvbnNlc2Agd2l0aG91dCB0aGUgY2xpZW50IGtub3dpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGF0VG9SZXNwb25zZXNSZXF1ZXN0KGJvZHk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KToge1xuICByZXNwb25zZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBzdHJlYW06IGJvb2xlYW47XG59IHtcbiAgY29uc3QgbWVzc2FnZXMgPSBBcnJheS5pc0FycmF5KGJvZHkubWVzc2FnZXMpID8gYm9keS5tZXNzYWdlcyA6IFtdO1xuICBjb25zdCBpbnB1dDogdW5rbm93bltdID0gW107XG4gIGxldCBpbnN0cnVjdGlvbnM6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBmb3IgKGNvbnN0IHJhdyBvZiBtZXNzYWdlcykge1xuICAgIGlmICghcmF3IHx8IHR5cGVvZiByYXcgIT09IFwib2JqZWN0XCIpIGNvbnRpbnVlO1xuICAgIGNvbnN0IG1lc3NhZ2UgPSByYXcgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgY29uc3Qgcm9sZSA9IHR5cGVvZiBtZXNzYWdlLnJvbGUgPT09IFwic3RyaW5nXCIgPyBtZXNzYWdlLnJvbGUgOiBcInVzZXJcIjtcblxuICAgIC8vIExlYWRpbmcgc3lzdGVtIC8gZGV2ZWxvcGVyIG1lc3NhZ2VzIGJlY29tZSB0b3AtbGV2ZWwgYGluc3RydWN0aW9uc2AuXG4gICAgaWYgKFxuICAgICAgKHJvbGUgPT09IFwic3lzdGVtXCIgfHwgcm9sZSA9PT0gXCJkZXZlbG9wZXJcIikgJiZcbiAgICAgIGluc3RydWN0aW9ucyA9PT0gdW5kZWZpbmVkICYmXG4gICAgICBpbnB1dC5sZW5ndGggPT09IDBcbiAgICApIHtcbiAgICAgIGNvbnN0IHRleHQgPSBjaGF0Q29udGVudFRvVGV4dChtZXNzYWdlLmNvbnRlbnQpO1xuICAgICAgaWYgKHRleHQpIGluc3RydWN0aW9ucyA9IHRleHQ7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAocm9sZSA9PT0gXCJ0b29sXCIpIHtcbiAgICAgIGlucHV0LnB1c2goe1xuICAgICAgICB0eXBlOiBcImZ1bmN0aW9uX2NhbGxfb3V0cHV0XCIsXG4gICAgICAgIGNhbGxfaWQ6IFN0cmluZyhtZXNzYWdlLnRvb2xfY2FsbF9pZCA/PyBcIlwiKSxcbiAgICAgICAgb3V0cHV0OiBjaGF0Q29udGVudFRvVGV4dChtZXNzYWdlLmNvbnRlbnQpLFxuICAgICAgfSk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICByb2xlID09PSBcImFzc2lzdGFudFwiICYmXG4gICAgICBBcnJheS5pc0FycmF5KG1lc3NhZ2UudG9vbF9jYWxscykgJiZcbiAgICAgIG1lc3NhZ2UudG9vbF9jYWxscy5sZW5ndGggPiAwXG4gICAgKSB7XG4gICAgICBmb3IgKGNvbnN0IHJhd0NhbGwgb2YgbWVzc2FnZS50b29sX2NhbGxzKSB7XG4gICAgICAgIGlmICghcmF3Q2FsbCB8fCB0eXBlb2YgcmF3Q2FsbCAhPT0gXCJvYmplY3RcIikgY29udGludWU7XG4gICAgICAgIGlucHV0LnB1c2godG9GdW5jdGlvbkNhbGxJdGVtKHJhd0NhbGwgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHRleHQgPSBjaGF0Q29udGVudFRvVGV4dChtZXNzYWdlLmNvbnRlbnQpO1xuICAgICAgaWYgKHRleHQpIHtcbiAgICAgICAgaW5wdXQucHVzaCh7IHR5cGU6IFwibWVzc2FnZVwiLCByb2xlOiBcImFzc2lzdGFudFwiLCBjb250ZW50OiB0ZXh0IH0pO1xuICAgICAgfVxuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaW5wdXQucHVzaCh7XG4gICAgICB0eXBlOiBcIm1lc3NhZ2VcIixcbiAgICAgIHJvbGUsXG4gICAgICBjb250ZW50OiBjaGF0Q29udGVudFRvVGV4dChtZXNzYWdlLmNvbnRlbnQpLFxuICAgIH0pO1xuICB9XG5cbiAgY29uc3QgcmVzcG9uc2VzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcbiAgICBtb2RlbDogYm9keS5tb2RlbCxcbiAgICBpbnB1dCxcbiAgICBzdHJlYW06IGJvZHkuc3RyZWFtID09PSB0cnVlLFxuICB9O1xuICBpZiAoaW5zdHJ1Y3Rpb25zKSByZXNwb25zZXMuaW5zdHJ1Y3Rpb25zID0gaW5zdHJ1Y3Rpb25zO1xuXG4gIC8vIENoYXQgdG9vbHMgYXJlIG5lc3RlZCAoYGZ1bmN0aW9uOiB7IG5hbWUsIOKApiB9YCk7IFJlc3BvbnNlcyB3YW50cyB0aGVtIGZsYXQuXG4gIGlmIChBcnJheS5pc0FycmF5KGJvZHkudG9vbHMpICYmIGJvZHkudG9vbHMubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IHRvb2xzID0gYm9keS50b29sc1xuICAgICAgLm1hcCh0b1Jlc3BvbnNlc1Rvb2wpXG4gICAgICAuZmlsdGVyKCh0KTogdCBpcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9PiB0ICE9PSB1bmRlZmluZWQpO1xuICAgIGlmICh0b29scy5sZW5ndGggPiAwKSB7XG4gICAgICByZXNwb25zZXMudG9vbHMgPSB0b29scztcbiAgICAgIGlmIChib2R5LnRvb2xfY2hvaWNlICE9PSB1bmRlZmluZWQpIHJlc3BvbnNlcy50b29sX2Nob2ljZSA9IGJvZHkudG9vbF9jaG9pY2U7XG4gICAgfVxuICB9XG5cbiAgLy8gUHJlZmVyIFJlc3BvbnNlcycgbWF4X291dHB1dF90b2tlbnMgbmFtaW5nOyBmYWxsIGJhY2sgZnJvbSBjaGF0IG1heF90b2tlbnMuXG4gIGlmICh0eXBlb2YgYm9keS5tYXhfb3V0cHV0X3Rva2VucyA9PT0gXCJudW1iZXJcIikge1xuICAgIHJlc3BvbnNlcy5tYXhfb3V0cHV0X3Rva2VucyA9IGJvZHkubWF4X291dHB1dF90b2tlbnM7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGJvZHkubWF4X3Rva2VucyA9PT0gXCJudW1iZXJcIikge1xuICAgIHJlc3BvbnNlcy5tYXhfb3V0cHV0X3Rva2VucyA9IGJvZHkubWF4X3Rva2VucztcbiAgfVxuXG4gIHJldHVybiB7IHJlc3BvbnNlcywgc3RyZWFtOiBib2R5LnN0cmVhbSA9PT0gdHJ1ZSB9O1xufVxuXG4vKiogTGlmdCBhIG5vbi1zdHJlYW1pbmcgY2hhdCBjb21wbGV0aW9uIEpTT04gaW50byBhIFJlc3BvbnNlcyBgcmVzcG9uc2VgIG9iamVjdC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGF0VG9SZXNwb25zZShjaGF0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgbW9kZWw6IHN0cmluZyk6IHVua25vd24ge1xuICBjb25zdCBjaG9pY2VzID0gQXJyYXkuaXNBcnJheShjaGF0LmNob2ljZXMpID8gY2hhdC5jaG9pY2VzIDogW107XG4gIGNvbnN0IGZpcnN0ID0gKGNob2ljZXNbMF0gPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCBtZXNzYWdlID0gKGZpcnN0Lm1lc3NhZ2UgPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCBvdXRwdXQ6IHVua25vd25bXSA9IFtdO1xuXG4gIGNvbnN0IHRleHQgPSB0eXBlb2YgbWVzc2FnZS5jb250ZW50ID09PSBcInN0cmluZ1wiID8gbWVzc2FnZS5jb250ZW50IDogXCJcIjtcbiAgaWYgKHRleHQpIHtcbiAgICBvdXRwdXQucHVzaCh7XG4gICAgICB0eXBlOiBcIm1lc3NhZ2VcIixcbiAgICAgIHJvbGU6IFwiYXNzaXN0YW50XCIsXG4gICAgICBjb250ZW50OiBbeyB0eXBlOiBcIm91dHB1dF90ZXh0XCIsIHRleHQgfV0sXG4gICAgfSk7XG4gIH1cblxuICAvLyBTdXJmYWNlIGFueSB0b29sIGNhbGxzIGFzIFJlc3BvbnNlcyBgZnVuY3Rpb25fY2FsbGAgb3V0cHV0IGl0ZW1zLlxuICBjb25zdCB0b29sQ2FsbHMgPSBBcnJheS5pc0FycmF5KG1lc3NhZ2UudG9vbF9jYWxscykgPyBtZXNzYWdlLnRvb2xfY2FsbHMgOiBbXTtcbiAgZm9yIChjb25zdCByYXcgb2YgdG9vbENhbGxzKSB7XG4gICAgb3V0cHV0LnB1c2godG9GdW5jdGlvbkNhbGxJdGVtKHJhdyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikpO1xuICB9XG5cbiAgY29uc3QgdXNhZ2UgPSAoY2hhdC51c2FnZSA/PyB7fSkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIHJldHVybiB7XG4gICAgaWQ6IFN0cmluZyhjaGF0LmlkID8/IFwicmVzcFwiKSxcbiAgICBvYmplY3Q6IFwicmVzcG9uc2VcIixcbiAgICBjcmVhdGVkX2F0OiB0eXBlb2YgY2hhdC5jcmVhdGVkID09PSBcIm51bWJlclwiID8gY2hhdC5jcmVhdGVkIDogMCxcbiAgICBtb2RlbCxcbiAgICBzdGF0dXM6IFwiY29tcGxldGVkXCIsXG4gICAgb3V0cHV0LFxuICAgIHVzYWdlOiB7XG4gICAgICBpbnB1dF90b2tlbnM6IE51bWJlcih1c2FnZS5wcm9tcHRfdG9rZW5zID8/IDApLFxuICAgICAgb3V0cHV0X3Rva2VuczogTnVtYmVyKHVzYWdlLmNvbXBsZXRpb25fdG9rZW5zID8/IDApLFxuICAgICAgdG90YWxfdG9rZW5zOiBOdW1iZXIodXNhZ2UudG90YWxfdG9rZW5zID8/IDApLFxuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICogTGlmdCBhIG5hdGl2ZSBSZXNwb25zZXMgYHJlc3BvbnNlYCBvYmplY3QgaW50byBhIGNoYXQtY29tcGxldGlvbnMgYm9keS5cbiAqIEludmVyc2Ugb2Yge0BsaW5rIGNoYXRUb1Jlc3BvbnNlfTogdXNlZCBhZnRlciBhIFJlc3BvbnNlcy1vbmx5IHVwc3RyZWFtIGNhbGxcbiAqIHdoZW4gdGhlIGNsaWVudCBzcG9rZSBDaGF0IENvbXBsZXRpb25zLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzcG9uc2VUb0NoYXRDb21wbGV0aW9uKFxuICByZXNwb25zZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIG1vZGVsOiBzdHJpbmcsXG4pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGNvbnN0IHsgdGV4dCB9ID0gcmVhZFJlc3BvbnNlc091dHB1dChyZXNwb25zZSk7XG4gIGNvbnN0IHRvb2xDYWxsczogdW5rbm93bltdID0gW107XG4gIGNvbnN0IG91dHB1dCA9IEFycmF5LmlzQXJyYXkocmVzcG9uc2Uub3V0cHV0KSA/IHJlc3BvbnNlLm91dHB1dCA6IFtdO1xuICBmb3IgKGNvbnN0IHJhdyBvZiBvdXRwdXQpIHtcbiAgICBpZiAoIXJhdyB8fCB0eXBlb2YgcmF3ICE9PSBcIm9iamVjdFwiKSBjb250aW51ZTtcbiAgICBjb25zdCBpdGVtID0gcmF3IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgIGlmIChpdGVtLnR5cGUgIT09IFwiZnVuY3Rpb25fY2FsbFwiKSBjb250aW51ZTtcbiAgICB0b29sQ2FsbHMucHVzaCh0b0NoYXRUb29sQ2FsbChpdGVtKSk7XG4gIH1cblxuICBjb25zdCBtZXNzYWdlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcbiAgICByb2xlOiBcImFzc2lzdGFudFwiLFxuICAgIGNvbnRlbnQ6IHRleHQgfHwgbnVsbCxcbiAgfTtcbiAgaWYgKHRvb2xDYWxscy5sZW5ndGggPiAwKSBtZXNzYWdlLnRvb2xfY2FsbHMgPSB0b29sQ2FsbHM7XG5cbiAgY29uc3QgdXNhZ2UgPSAocmVzcG9uc2UudXNhZ2UgPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICByZXR1cm4ge1xuICAgIGlkOiBTdHJpbmcocmVzcG9uc2UuaWQgPz8gXCJjaGF0Y21wbFwiKSxcbiAgICBvYmplY3Q6IFwiY2hhdC5jb21wbGV0aW9uXCIsXG4gICAgY3JlYXRlZDogdHlwZW9mIHJlc3BvbnNlLmNyZWF0ZWRfYXQgPT09IFwibnVtYmVyXCIgPyByZXNwb25zZS5jcmVhdGVkX2F0IDogMCxcbiAgICBtb2RlbCxcbiAgICBjaG9pY2VzOiBbXG4gICAgICB7XG4gICAgICAgIGluZGV4OiAwLFxuICAgICAgICBtZXNzYWdlLFxuICAgICAgICBmaW5pc2hfcmVhc29uOiB0b29sQ2FsbHMubGVuZ3RoID4gMCA/IFwidG9vbF9jYWxsc1wiIDogXCJzdG9wXCIsXG4gICAgICB9LFxuICAgIF0sXG4gICAgdXNhZ2U6IHtcbiAgICAgIHByb21wdF90b2tlbnM6IE51bWJlcih1c2FnZS5pbnB1dF90b2tlbnMgPz8gMCksXG4gICAgICBjb21wbGV0aW9uX3Rva2VuczogTnVtYmVyKHVzYWdlLm91dHB1dF90b2tlbnMgPz8gMCksXG4gICAgICB0b3RhbF90b2tlbnM6IE51bWJlcih1c2FnZS50b3RhbF90b2tlbnMgPz8gMCksXG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBBIHRvb2wgY2FsbCdzIGBhcmd1bWVudHNgIEpTT04uIEJvdGggd2lyZXMgY2FycnkgaXQgYXMgYW4gdW5wYXJzZWQgc3RyaW5nO1xuICogYW55dGhpbmcgZWxzZSAoYWJzZW50LCBhbiBhbHJlYWR5LXBhcnNlZCBvYmplY3QpIGJlY29tZXMgYW4gZW1wdHkgbGl0ZXJhbCBzb1xuICogdGhlIHJlY2VpdmluZyBzaWRlIGFsd2F5cyBoYXMgdmFsaWQgSlNPTiB0byBwYXJzZS5cbiAqL1xuZnVuY3Rpb24gY2FsbEFyZ3VtZW50cyh2YWx1ZTogdW5rbm93bik6IHN0cmluZyB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgPyB2YWx1ZSA6IFwie31cIjtcbn1cblxuLyoqXG4gKiBUaGUgUmVzcG9uc2VzIGBmdW5jdGlvbl9jYWxsYCBpdGVtIGZvciBhIHRvb2wgY2FsbCBpbiBlaXRoZXIgc3BlbGxpbmc6IGEgY2hhdFxuICogYHRvb2xfY2FsbHNbXWAgZW50cnkgKGB7aWQsIGZ1bmN0aW9uOntuYW1lLCBhcmd1bWVudHN9fWApIG9yIGFuIGl0ZW0gdGhhdCBpc1xuICogYWxyZWFkeSBmbGF0LlxuICovXG5mdW5jdGlvbiB0b0Z1bmN0aW9uQ2FsbEl0ZW0oY2FsbDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGNvbnN0IGZuID0gKGNhbGwuZnVuY3Rpb24gPz8gY2FsbCkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIHJldHVybiB7XG4gICAgdHlwZTogXCJmdW5jdGlvbl9jYWxsXCIsXG4gICAgY2FsbF9pZDogU3RyaW5nKGNhbGwuY2FsbF9pZCA/PyBjYWxsLmlkID8/IFwiXCIpLFxuICAgIG5hbWU6IFN0cmluZyhmbi5uYW1lID8/IFwiXCIpLFxuICAgIGFyZ3VtZW50czogY2FsbEFyZ3VtZW50cyhmbi5hcmd1bWVudHMpLFxuICB9O1xufVxuXG4vKiogVGhlIGNoYXQgYHRvb2xfY2FsbHNbXWAgZW50cnkgZm9yIGEgUmVzcG9uc2VzIGBmdW5jdGlvbl9jYWxsYCBpdGVtLiAqL1xuZnVuY3Rpb24gdG9DaGF0VG9vbENhbGwoaXRlbTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBDaGF0VG9vbENhbGwge1xuICByZXR1cm4ge1xuICAgIGlkOiBTdHJpbmcoaXRlbS5jYWxsX2lkID8/IGl0ZW0uaWQgPz8gXCJcIiksXG4gICAgdHlwZTogXCJmdW5jdGlvblwiLFxuICAgIGZ1bmN0aW9uOiB7XG4gICAgICBuYW1lOiBTdHJpbmcoaXRlbS5uYW1lID8/IFwiXCIpLFxuICAgICAgYXJndW1lbnRzOiBjYWxsQXJndW1lbnRzKGl0ZW0uYXJndW1lbnRzKSxcbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIFRoZSBjaGF0LW5lc3RlZCBzcGVsbGluZyAoYHt0eXBlOlwiZnVuY3Rpb25cIiwgZnVuY3Rpb246e25hbWUsIOKApn19YCkgb2YgYSB0b29sXG4gKiBzcGVjLCBvciBgdW5kZWZpbmVkYCBmb3IgYSBidWlsdC1pbiBSZXNwb25zZXMgdG9vbCAoYHdlYl9zZWFyY2hgLFxuICogYGxvY2FsX3NoZWxsYCwg4oCmKSB0aGF0IGNoYXQgY2Fubm90IGV4cHJlc3MgYW5kIERhdGFicmlja3MgcmVqZWN0cy5cbiAqL1xuZnVuY3Rpb24gdG9DaGF0VG9vbCh2YWx1ZTogdW5rbm93bik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkIHtcbiAgaWYgKCF2YWx1ZSB8fCB0eXBlb2YgdmFsdWUgIT09IFwib2JqZWN0XCIpIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IHRvb2wgPSB2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgaWYgKHRvb2wudHlwZSAhPT0gXCJmdW5jdGlvblwiKSByZXR1cm4gdW5kZWZpbmVkO1xuICBpZiAodG9vbC5mdW5jdGlvbiAmJiB0eXBlb2YgdG9vbC5mdW5jdGlvbiA9PT0gXCJvYmplY3RcIikgcmV0dXJuIHRvb2w7IC8vIGFscmVhZHkgbmVzdGVkXG4gIGlmICh0eXBlb2YgdG9vbC5uYW1lICE9PSBcInN0cmluZ1wiKSByZXR1cm4gdW5kZWZpbmVkO1xuICByZXR1cm4ge1xuICAgIHR5cGU6IFwiZnVuY3Rpb25cIixcbiAgICBmdW5jdGlvbjoge1xuICAgICAgbmFtZTogdG9vbC5uYW1lLFxuICAgICAgLi4uKHRvb2wuZGVzY3JpcHRpb24gPyB7IGRlc2NyaXB0aW9uOiB0b29sLmRlc2NyaXB0aW9uIH0gOiB7fSksXG4gICAgICAuLi4odG9vbC5wYXJhbWV0ZXJzID8geyBwYXJhbWV0ZXJzOiB0b29sLnBhcmFtZXRlcnMgfSA6IHt9KSxcbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIFRoZSBmbGF0IFJlc3BvbnNlcyBzcGVsbGluZyAoYHt0eXBlOlwiZnVuY3Rpb25cIiwgbmFtZSwg4oCmfWApIG9mIGEgdG9vbCBzcGVjLlxuICogSW52ZXJzZSBvZiB7QGxpbmsgdG9DaGF0VG9vbH07IG5vbi1mdW5jdGlvbiB0b29scyBhcmUgZHJvcHBlZCB0aGUgc2FtZSB3YXkuXG4gKi9cbmZ1bmN0aW9uIHRvUmVzcG9uc2VzVG9vbCh2YWx1ZTogdW5rbm93bik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkIHtcbiAgaWYgKCF2YWx1ZSB8fCB0eXBlb2YgdmFsdWUgIT09IFwib2JqZWN0XCIpIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IHRvb2wgPSB2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgaWYgKHRvb2wudHlwZSAhPT0gXCJmdW5jdGlvblwiKSByZXR1cm4gdW5kZWZpbmVkO1xuICBpZiAodG9vbC5mdW5jdGlvbiAmJiB0eXBlb2YgdG9vbC5mdW5jdGlvbiA9PT0gXCJvYmplY3RcIikge1xuICAgIGNvbnN0IGZuID0gdG9vbC5mdW5jdGlvbiBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogXCJmdW5jdGlvblwiLFxuICAgICAgbmFtZTogZm4ubmFtZSxcbiAgICAgIC4uLihmbi5kZXNjcmlwdGlvbiA/IHsgZGVzY3JpcHRpb246IGZuLmRlc2NyaXB0aW9uIH0gOiB7fSksXG4gICAgICAuLi4oZm4ucGFyYW1ldGVycyA/IHsgcGFyYW1ldGVyczogZm4ucGFyYW1ldGVycyB9IDoge30pLFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIHR5cGVvZiB0b29sLm5hbWUgPT09IFwic3RyaW5nXCIgPyB0b29sIDogdW5kZWZpbmVkOyAvLyBhbHJlYWR5IGZsYXRcbn1cblxuLyoqIE9uZSBTZXJ2ZXItU2VudCBFdmVudCwgcmVhZHkgdG8gd3JpdGUgdG8gdGhlIGNsaWVudC4gKi9cbmZ1bmN0aW9uIHNzZShldmVudDogc3RyaW5nLCBkYXRhOiB1bmtub3duKTogc3RyaW5nIHtcbiAgcmV0dXJuIGBldmVudDogJHtldmVudH1cXG5kYXRhOiAke0pTT04uc3RyaW5naWZ5KGRhdGEpfVxcblxcbmA7XG59XG5cbi8qKlxuICogSW5jcmVtZW50YWwgY2hhdC1jaHVuayAtPiBSZXNwb25zZXMtU1NFIHRyYW5zbGF0b3IuIGBmZWVkYCBhbmQgYGZpbmlzaGAgYm90aFxuICogcmV0dXJuIHRoZSBTU0UgYnl0ZXMgdG8gZm9yd2FyZCwgb3IgYFwiXCJgIHdoZW4gYSBjaHVuayBwcm9kdWNlZCBubyBldmVudC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXNwb25zZXNTdHJlYW1UcmFuc2xhdG9yIHtcbiAgLyoqIFRyYW5zbGF0ZSBvbmUgdXBzdHJlYW0gYGNoYXQuY29tcGxldGlvbi5jaHVua2Agb2JqZWN0LiAqL1xuICBmZWVkKGNodW5rOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHN0cmluZztcbiAgLyoqIENsb3NlIGFueSBvcGVuIGl0ZW1zIGFuZCBlbWl0IGByZXNwb25zZS5jb21wbGV0ZWRgLiBDYWxsIG9uY2UsIGF0IGVuZCBvZiBzdHJlYW0uICovXG4gIGZpbmlzaCgpOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVHJhbnNsYXRlIGFuIHVwc3RyZWFtIGNoYXQtY29tcGxldGlvbnMgU1NFIHN0cmVhbSBpbnRvIHRoZSBSZXNwb25zZXMgU1NFXG4gKiBldmVudCBzdHJlYW0gYSBSZXNwb25zZXMgY2xpZW50IGNvbnN1bWVzLlxuICpcbiAqIFVwc3RyZWFtIGNodW5rcyBhcmUgYGNoYXQuY29tcGxldGlvbi5jaHVua2Agb2JqZWN0cyB3aG9zZSBgY2hvaWNlc1swXS5kZWx0YWBcbiAqIGNhcnJpZXMgaW5jcmVtZW50YWwgYGNvbnRlbnRgIChhc3Npc3RhbnQgdGV4dCkgYW5kL29yIGB0b29sX2NhbGxzYCAoZnVuY3Rpb25cbiAqIGNhbGxzLCBzdHJlYW1lZCBieSBgaW5kZXhgIHdpdGggcGFydGlhbCBgYXJndW1lbnRzYCkuIFdlIGVtaXQgdGhlIFJlc3BvbnNlc1xuICogbGlmZWN5Y2xlIGFyb3VuZCB0aGVtOlxuICpcbiAqICAgcmVzcG9uc2UuY3JlYXRlZFxuICogICAtPiBwZXIgdGV4dCBydW46ICBvdXRwdXRfaXRlbS5hZGRlZCDihpIgb3V0cHV0X3RleHQuZGVsdGEqIOKGkiBvdXRwdXRfaXRlbS5kb25lXG4gKiAgIC0+IHBlciB0b29sIGNhbGw6IG91dHB1dF9pdGVtLmFkZGVkIOKGkiBmdW5jdGlvbl9jYWxsX2FyZ3VtZW50cy5kZWx0YSpcbiAqICAgICAgICAgICAgICAgICAgICAgICDihpIgZnVuY3Rpb25fY2FsbF9hcmd1bWVudHMuZG9uZSDihpIgb3V0cHV0X2l0ZW0uZG9uZVxuICogICByZXNwb25zZS5jb21wbGV0ZWQgICAod2l0aCB0aGUgYXNzZW1ibGVkIGZpbmFsIGByZXNwb25zZWAgb2JqZWN0KVxuICpcbiAqIFRoZSB0cmFuc2xhdG9yIGlzIGludGVudGlvbmFsbHkgdG9sZXJhbnQ6IG1hbGZvcm1lZC9rZWVwYWxpdmUgbGluZXMgeWllbGRcbiAqIG5vdGhpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVSZXNwb25zZXNTdHJlYW1UcmFuc2xhdG9yKFxuICBtb2RlbDogc3RyaW5nLFxuICByZXNwb25zZUlkOiBzdHJpbmcsXG4pOiBSZXNwb25zZXNTdHJlYW1UcmFuc2xhdG9yIHtcbiAgbGV0IHN0YXJ0ZWQgPSBmYWxzZTtcbiAgbGV0IG91dHB1dEluZGV4ID0gMDtcblxuICAvLyBUZXh0IHJ1biBzdGF0ZTogd2hldGhlciBhIG1lc3NhZ2UgaXRlbSBpcyBjdXJyZW50bHkgb3BlbiwgYW5kIGl0cyBidWZmZXIuXG4gIGxldCB0ZXh0T3BlbiA9IGZhbHNlO1xuICBsZXQgdGV4dEJ1ZmZlciA9IFwiXCI7XG4gIGxldCB0ZXh0SXRlbUlkID0gXCJcIjtcblxuICAvLyBUb29sLWNhbGwgc3RhdGUsIGtleWVkIGJ5IHRoZSB1cHN0cmVhbSBgdG9vbF9jYWxsc1tdLmluZGV4YC5cbiAgaW50ZXJmYWNlIFRvb2xTdGF0ZSB7XG4gICAgb3V0cHV0SW5kZXg6IG51bWJlcjtcbiAgICBjYWxsSWQ6IHN0cmluZztcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgYXJnczogc3RyaW5nO1xuICB9XG4gIGNvbnN0IHRvb2xzID0gbmV3IE1hcDxudW1iZXIsIFRvb2xTdGF0ZT4oKTtcblxuICBjb25zdCBjcmVhdGVkID0gKCkgPT5cbiAgICBzc2UoXCJyZXNwb25zZS5jcmVhdGVkXCIsIHtcbiAgICAgIHR5cGU6IFwicmVzcG9uc2UuY3JlYXRlZFwiLFxuICAgICAgcmVzcG9uc2U6IHsgaWQ6IHJlc3BvbnNlSWQsIG9iamVjdDogXCJyZXNwb25zZVwiLCBzdGF0dXM6IFwiaW5fcHJvZ3Jlc3NcIiwgbW9kZWwsIG91dHB1dDogW10gfSxcbiAgICB9KTtcblxuICBmdW5jdGlvbiBvcGVuVGV4dCgpOiBzdHJpbmcge1xuICAgIHRleHRPcGVuID0gdHJ1ZTtcbiAgICB0ZXh0SXRlbUlkID0gYCR7cmVzcG9uc2VJZH0tbXNnLSR7b3V0cHV0SW5kZXh9YDtcbiAgICBjb25zdCBldiA9IHNzZShcInJlc3BvbnNlLm91dHB1dF9pdGVtLmFkZGVkXCIsIHtcbiAgICAgIHR5cGU6IFwicmVzcG9uc2Uub3V0cHV0X2l0ZW0uYWRkZWRcIixcbiAgICAgIG91dHB1dF9pbmRleDogb3V0cHV0SW5kZXgsXG4gICAgICBpdGVtOiB7IGlkOiB0ZXh0SXRlbUlkLCB0eXBlOiBcIm1lc3NhZ2VcIiwgcm9sZTogXCJhc3Npc3RhbnRcIiwgY29udGVudDogW10gfSxcbiAgICB9KTtcbiAgICByZXR1cm4gZXY7XG4gIH1cblxuICBmdW5jdGlvbiBjbG9zZVRleHQoKTogc3RyaW5nIHtcbiAgICBpZiAoIXRleHRPcGVuKSByZXR1cm4gXCJcIjtcbiAgICBjb25zdCBpdGVtID0ge1xuICAgICAgaWQ6IHRleHRJdGVtSWQsXG4gICAgICB0eXBlOiBcIm1lc3NhZ2VcIixcbiAgICAgIHJvbGU6IFwiYXNzaXN0YW50XCIsXG4gICAgICBjb250ZW50OiBbeyB0eXBlOiBcIm91dHB1dF90ZXh0XCIsIHRleHQ6IHRleHRCdWZmZXIgfV0sXG4gICAgfTtcbiAgICBjb25zdCBldiA9XG4gICAgICBzc2UoXCJyZXNwb25zZS5vdXRwdXRfdGV4dC5kb25lXCIsIHtcbiAgICAgICAgdHlwZTogXCJyZXNwb25zZS5vdXRwdXRfdGV4dC5kb25lXCIsXG4gICAgICAgIGl0ZW1faWQ6IHRleHRJdGVtSWQsXG4gICAgICAgIG91dHB1dF9pbmRleDogb3V0cHV0SW5kZXgsXG4gICAgICAgIGNvbnRlbnRfaW5kZXg6IDAsXG4gICAgICAgIHRleHQ6IHRleHRCdWZmZXIsXG4gICAgICB9KSArXG4gICAgICBzc2UoXCJyZXNwb25zZS5vdXRwdXRfaXRlbS5kb25lXCIsIHtcbiAgICAgICAgdHlwZTogXCJyZXNwb25zZS5vdXRwdXRfaXRlbS5kb25lXCIsXG4gICAgICAgIG91dHB1dF9pbmRleDogb3V0cHV0SW5kZXgsXG4gICAgICAgIGl0ZW0sXG4gICAgICB9KTtcbiAgICB0ZXh0T3BlbiA9IGZhbHNlO1xuICAgIHRleHRCdWZmZXIgPSBcIlwiO1xuICAgIG91dHB1dEluZGV4ICs9IDE7XG4gICAgcmV0dXJuIGV2O1xuICB9XG5cbiAgZnVuY3Rpb24gZmVlZChjaHVuazogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBzdHJpbmcge1xuICAgIGxldCBvdXQgPSBcIlwiO1xuICAgIGlmICghc3RhcnRlZCkge1xuICAgICAgc3RhcnRlZCA9IHRydWU7XG4gICAgICBvdXQgKz0gY3JlYXRlZCgpO1xuICAgIH1cbiAgICBjb25zdCBjaG9pY2VzID0gQXJyYXkuaXNBcnJheShjaHVuay5jaG9pY2VzKSA/IGNodW5rLmNob2ljZXMgOiBbXTtcbiAgICBjb25zdCBjaG9pY2UgPSAoY2hvaWNlc1swXSA/PyB7fSkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgY29uc3QgZGVsdGEgPSAoY2hvaWNlLmRlbHRhID8/IHt9KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuICAgIC8vIEFzc2lzdGFudCB0ZXh0IGRlbHRhcy5cbiAgICBpZiAodHlwZW9mIGRlbHRhLmNvbnRlbnQgPT09IFwic3RyaW5nXCIgJiYgZGVsdGEuY29udGVudC5sZW5ndGggPiAwKSB7XG4gICAgICBpZiAoIXRleHRPcGVuKSBvdXQgKz0gb3BlblRleHQoKTtcbiAgICAgIHRleHRCdWZmZXIgKz0gZGVsdGEuY29udGVudDtcbiAgICAgIG91dCArPSBzc2UoXCJyZXNwb25zZS5vdXRwdXRfdGV4dC5kZWx0YVwiLCB7XG4gICAgICAgIHR5cGU6IFwicmVzcG9uc2Uub3V0cHV0X3RleHQuZGVsdGFcIixcbiAgICAgICAgaXRlbV9pZDogdGV4dEl0ZW1JZCxcbiAgICAgICAgb3V0cHV0X2luZGV4OiBvdXRwdXRJbmRleCxcbiAgICAgICAgY29udGVudF9pbmRleDogMCxcbiAgICAgICAgZGVsdGE6IGRlbHRhLmNvbnRlbnQsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBUb29sLWNhbGwgZGVsdGFzOiBlYWNoIGlzIGtleWVkIGJ5IGBpbmRleGA7IGBhcmd1bWVudHNgIGFycml2ZXMgaW4gcGllY2VzLlxuICAgIGNvbnN0IHRvb2xEZWx0YXMgPSBBcnJheS5pc0FycmF5KGRlbHRhLnRvb2xfY2FsbHMpID8gZGVsdGEudG9vbF9jYWxscyA6IFtdO1xuICAgIGZvciAoY29uc3QgcmF3VGMgb2YgdG9vbERlbHRhcykge1xuICAgICAgY29uc3QgdGMgPSByYXdUYyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIGNvbnN0IGlkeCA9IE51bWJlcih0Yy5pbmRleCA/PyAwKTtcbiAgICAgIGNvbnN0IGZuID0gKHRjLmZ1bmN0aW9uID8/IHt9KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIGxldCBzdGF0ZSA9IHRvb2xzLmdldChpZHgpO1xuICAgICAgaWYgKCFzdGF0ZSkge1xuICAgICAgICAvLyBGaXJzdCBmcmFnbWVudCBmb3IgdGhpcyBjYWxsOiBhIHRleHQgcnVuIChpZiBvcGVuKSBtdXN0IGNsb3NlIGZpcnN0IHNvXG4gICAgICAgIC8vIG91dHB1dCBvcmRlcmluZyBzdGF5cyBtb25vdG9uaWMsIHRoZW4gd2Ugb3BlbiBhIGZ1bmN0aW9uX2NhbGwgaXRlbS5cbiAgICAgICAgb3V0ICs9IGNsb3NlVGV4dCgpO1xuICAgICAgICBzdGF0ZSA9IHtcbiAgICAgICAgICBvdXRwdXRJbmRleCxcbiAgICAgICAgICBjYWxsSWQ6IFN0cmluZyh0Yy5pZCA/PyBgJHtyZXNwb25zZUlkfS1jYWxsLSR7aWR4fWApLFxuICAgICAgICAgIG5hbWU6IFN0cmluZyhmbi5uYW1lID8/IFwiXCIpLFxuICAgICAgICAgIGFyZ3M6IFwiXCIsXG4gICAgICAgIH07XG4gICAgICAgIHRvb2xzLnNldChpZHgsIHN0YXRlKTtcbiAgICAgICAgb3V0ICs9IHNzZShcInJlc3BvbnNlLm91dHB1dF9pdGVtLmFkZGVkXCIsIHtcbiAgICAgICAgICB0eXBlOiBcInJlc3BvbnNlLm91dHB1dF9pdGVtLmFkZGVkXCIsXG4gICAgICAgICAgb3V0cHV0X2luZGV4OiBzdGF0ZS5vdXRwdXRJbmRleCxcbiAgICAgICAgICBpdGVtOiB7XG4gICAgICAgICAgICBpZDogc3RhdGUuY2FsbElkLFxuICAgICAgICAgICAgdHlwZTogXCJmdW5jdGlvbl9jYWxsXCIsXG4gICAgICAgICAgICBjYWxsX2lkOiBzdGF0ZS5jYWxsSWQsXG4gICAgICAgICAgICBuYW1lOiBzdGF0ZS5uYW1lLFxuICAgICAgICAgICAgYXJndW1lbnRzOiBcIlwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBvdXRwdXRJbmRleCArPSAxO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiBmbi5uYW1lID09PSBcInN0cmluZ1wiICYmIGZuLm5hbWUgJiYgIXN0YXRlLm5hbWUpIHN0YXRlLm5hbWUgPSBmbi5uYW1lO1xuICAgICAgaWYgKHR5cGVvZiBmbi5hcmd1bWVudHMgPT09IFwic3RyaW5nXCIgJiYgZm4uYXJndW1lbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgc3RhdGUuYXJncyArPSBmbi5hcmd1bWVudHM7XG4gICAgICAgIG91dCArPSBzc2UoXCJyZXNwb25zZS5mdW5jdGlvbl9jYWxsX2FyZ3VtZW50cy5kZWx0YVwiLCB7XG4gICAgICAgICAgdHlwZTogXCJyZXNwb25zZS5mdW5jdGlvbl9jYWxsX2FyZ3VtZW50cy5kZWx0YVwiLFxuICAgICAgICAgIGl0ZW1faWQ6IHN0YXRlLmNhbGxJZCxcbiAgICAgICAgICBvdXRwdXRfaW5kZXg6IHN0YXRlLm91dHB1dEluZGV4LFxuICAgICAgICAgIGRlbHRhOiBmbi5hcmd1bWVudHMsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gb3V0O1xuICB9XG5cbiAgZnVuY3Rpb24gZmluaXNoKCk6IHN0cmluZyB7XG4gICAgbGV0IG91dCA9IGNsb3NlVGV4dCgpO1xuICAgIC8vIENsb3NlIGFueSBvcGVuIHRvb2wgY2FsbHMsIGVtaXR0aW5nIHRoZWlyIGFzc2VtYmxlZCBhcmd1bWVudHMuXG4gICAgZm9yIChjb25zdCBzdGF0ZSBvZiB0b29scy52YWx1ZXMoKSkge1xuICAgICAgb3V0ICs9IHNzZShcInJlc3BvbnNlLmZ1bmN0aW9uX2NhbGxfYXJndW1lbnRzLmRvbmVcIiwge1xuICAgICAgICB0eXBlOiBcInJlc3BvbnNlLmZ1bmN0aW9uX2NhbGxfYXJndW1lbnRzLmRvbmVcIixcbiAgICAgICAgaXRlbV9pZDogc3RhdGUuY2FsbElkLFxuICAgICAgICBvdXRwdXRfaW5kZXg6IHN0YXRlLm91dHB1dEluZGV4LFxuICAgICAgICBhcmd1bWVudHM6IHN0YXRlLmFyZ3MsXG4gICAgICB9KTtcbiAgICAgIG91dCArPSBzc2UoXCJyZXNwb25zZS5vdXRwdXRfaXRlbS5kb25lXCIsIHtcbiAgICAgICAgdHlwZTogXCJyZXNwb25zZS5vdXRwdXRfaXRlbS5kb25lXCIsXG4gICAgICAgIG91dHB1dF9pbmRleDogc3RhdGUub3V0cHV0SW5kZXgsXG4gICAgICAgIGl0ZW06IHtcbiAgICAgICAgICBpZDogc3RhdGUuY2FsbElkLFxuICAgICAgICAgIHR5cGU6IFwiZnVuY3Rpb25fY2FsbFwiLFxuICAgICAgICAgIGNhbGxfaWQ6IHN0YXRlLmNhbGxJZCxcbiAgICAgICAgICBuYW1lOiBzdGF0ZS5uYW1lLFxuICAgICAgICAgIGFyZ3VtZW50czogc3RhdGUuYXJncyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICBvdXQgKz0gc3NlKFwicmVzcG9uc2UuY29tcGxldGVkXCIsIHtcbiAgICAgIHR5cGU6IFwicmVzcG9uc2UuY29tcGxldGVkXCIsXG4gICAgICByZXNwb25zZTogeyBpZDogcmVzcG9uc2VJZCwgb2JqZWN0OiBcInJlc3BvbnNlXCIsIHN0YXR1czogXCJjb21wbGV0ZWRcIiwgbW9kZWwgfSxcbiAgICB9KTtcbiAgICByZXR1cm4gb3V0O1xuICB9XG5cbiAgcmV0dXJuIHsgZmVlZCwgZmluaXNoIH07XG59XG5cbi8qKiBBIHNvdXJjZSB0aGUgbW9kZWwgY2l0ZWQsIGFzIGNhcnJpZWQgYnkgYSBSZXNwb25zZXMgY29udGVudC1wYXJ0IGFubm90YXRpb24uICovXG5leHBvcnQgaW50ZXJmYWNlIFJlc3BvbnNlc0NpdGF0aW9uIHtcbiAgdXJsOiBzdHJpbmc7XG4gIHRpdGxlPzogc3RyaW5nO1xufVxuXG4vKiogV2hhdCB7QGxpbmsgcmVhZFJlc3BvbnNlc091dHB1dH0gcHVsbHMgb3V0IG9mIGEgYHJlc3BvbnNlYCBvYmplY3QuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlc3BvbnNlc091dHB1dCB7XG4gIC8qKiBUaGUgYXNzaXN0YW50J3MgYW5zd2VyLCB3aXRoIHRoZSBvdXRwdXQgaXRlbXMgY29uY2F0ZW5hdGVkLiAqL1xuICB0ZXh0OiBzdHJpbmc7XG4gIC8qKiBDaXRlZCBzb3VyY2VzIGluIGZpcnN0LXNlZW4gb3JkZXIsIGRlZHVwbGljYXRlZCBieSBVUkwuICovXG4gIGNpdGF0aW9uczogUmVzcG9uc2VzQ2l0YXRpb25bXTtcbn1cblxuLyoqXG4gKiBSZWFkIHRoZSBhbnN3ZXIgdGV4dCBhbmQgY2l0ZWQgc291cmNlcyBvdXQgb2YgYSBSZXNwb25zZXMgYHJlc3BvbnNlYCBwYXlsb2FkLlxuICpcbiAqIFRoaXMgaXMgdGhlIGludmVyc2Ugb2Yge0BsaW5rIGNoYXRUb1Jlc3BvbnNlfTogaXQgY29uc3VtZXMgd2hhdCBhbiBlbmRwb2ludFxuICogc3BlYWtpbmcgUmVzcG9uc2VzIG5hdGl2ZWx5IHJldHVybnMsIHJhdGhlciB0aGFuIHByb2R1Y2luZyBpdC4gVGhlIERhdGFicmlja3NcbiAqIG5hdGl2ZSB3ZWItc2VhcmNoIHRvb2wgYW5zd2VycyB0aGlzIHdheSwgd2l0aCBlYWNoIHNvdXJjZSBhdHRhY2hlZCBhcyBhXG4gKiBgdXJsX2NpdGF0aW9uYCBhbm5vdGF0aW9uIG9uIHRoZSBjb250ZW50IHBhcnQgdGhhdCB1c2VkIGl0LlxuICpcbiAqIFByZWZlcnMgdGhlIGZsYXR0ZW5lZCBgb3V0cHV0X3RleHRgIHdoZW4gdGhlIHBheWxvYWQgY2FycmllcyBpdCwgYW5kIGZhbGxzXG4gKiBiYWNrIHRvIHdhbGtpbmcgYG91dHB1dFtdLmNvbnRlbnRbXS50ZXh0YC4gRXZlcnkgZmllbGQgaXMgb3B0aW9uYWwgdXBzdHJlYW0sXG4gKiBzbyBhIHBheWxvYWQgbWlzc2luZyBhbnkgb2YgaXQgeWllbGRzIGVtcHR5IHJlc3VsdHMgcmF0aGVyIHRoYW4gdGhyb3dpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkUmVzcG9uc2VzT3V0cHV0KHBheWxvYWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogUmVzcG9uc2VzT3V0cHV0IHtcbiAgY29uc3Qgb3V0cHV0ID0gQXJyYXkuaXNBcnJheShwYXlsb2FkLm91dHB1dCkgPyAocGF5bG9hZC5vdXRwdXQgYXMgdW5rbm93bltdKSA6IFtdO1xuICBjb25zdCB0ZXh0czogc3RyaW5nW10gPSBbXTtcbiAgY29uc3QgY2l0YXRpb25zOiBSZXNwb25zZXNDaXRhdGlvbltdID0gW107XG4gIGNvbnN0IHNlZW4gPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICBmb3IgKGNvbnN0IHJhd0l0ZW0gb2Ygb3V0cHV0KSB7XG4gICAgaWYgKCFyYXdJdGVtIHx8IHR5cGVvZiByYXdJdGVtICE9PSBcIm9iamVjdFwiKSBjb250aW51ZTtcbiAgICBjb25zdCBjb250ZW50ID0gKHJhd0l0ZW0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLmNvbnRlbnQ7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGNvbnRlbnQpKSBjb250aW51ZTtcbiAgICBmb3IgKGNvbnN0IHJhd1BhcnQgb2YgY29udGVudCkge1xuICAgICAgaWYgKCFyYXdQYXJ0IHx8IHR5cGVvZiByYXdQYXJ0ICE9PSBcIm9iamVjdFwiKSBjb250aW51ZTtcbiAgICAgIGNvbnN0IHBhcnQgPSByYXdQYXJ0IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgY29uc3QgdGV4dCA9IHN0cmluZy50cmltVG9FbXB0eShwYXJ0LnRleHQpO1xuICAgICAgaWYgKHRleHQpIHRleHRzLnB1c2godGV4dCk7XG4gICAgICBjb25zdCBhbm5vdGF0aW9ucyA9IEFycmF5LmlzQXJyYXkocGFydC5hbm5vdGF0aW9ucykgPyBwYXJ0LmFubm90YXRpb25zIDogW107XG4gICAgICBmb3IgKGNvbnN0IHJhd0FubiBvZiBhbm5vdGF0aW9ucykge1xuICAgICAgICBpZiAoIXJhd0FubiB8fCB0eXBlb2YgcmF3QW5uICE9PSBcIm9iamVjdFwiKSBjb250aW51ZTtcbiAgICAgICAgY29uc3QgYW5uID0gcmF3QW5uIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgICBjb25zdCB1cmwgPSBzdHJpbmcudHJpbVRvRW1wdHkoYW5uLnVybCk7XG4gICAgICAgIGlmICghdXJsIHx8IHNlZW4uaGFzKHVybCkpIGNvbnRpbnVlO1xuICAgICAgICBzZWVuLmFkZCh1cmwpO1xuICAgICAgICBjb25zdCB0aXRsZSA9IHN0cmluZy50cmltVG9FbXB0eShhbm4udGl0bGUpO1xuICAgICAgICBjaXRhdGlvbnMucHVzaCh7IHVybCwgLi4uKHRpdGxlID8geyB0aXRsZSB9IDoge30pIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7IHRleHQ6IHN0cmluZy50cmltVG9FbXB0eShwYXlsb2FkLm91dHB1dF90ZXh0KSB8fCB0ZXh0cy5qb2luKFwiXFxuXCIpLnRyaW0oKSwgY2l0YXRpb25zIH07XG59XG5cbi8qKlxuICogU3RyaXAgdG9vbCB0eXBlcyB0aGUgdXBzdHJlYW0gbW9kZWwgZG9lc24ndCBzdXBwb3J0IGZyb20gYSBSZXNwb25zZXMgcmVxdWVzdFxuICogYm9keSwgcmV0dXJuaW5nIGEgc2hhbGxvdyBjb3B5IHNhZmUgdG8gZm9yd2FyZCAodGhlIGlucHV0IGlzIG5vdCBtdXRhdGVkKS5cbiAqXG4gKiBDbGllbnRzIGxpa2UgdGhlIENvZGV4IENMSSBpbmNsdWRlIGJ1aWx0LWluIFJlc3BvbnNlcyB0b29scyAoYHdlYl9zZWFyY2hgLFxuICogYGxvY2FsX3NoZWxsYCwgYGN1c3RvbWAsIC4uLikgYWxvbmdzaWRlIHRoZWlyIGBmdW5jdGlvbmAgdG9vbHMuIERhdGFicmlja3MnXG4gKiBPcGVuIFJlc3BvbnNlcyBzdXJmYWNlIGZvciBBbnRocm9waWMvQ2xhdWRlIChhbmQgb3RoZXIgbm9uLU9wZW5BSSBwcm92aWRlcnMpXG4gKiBvbmx5IGFjY2VwdHMgYGZ1bmN0aW9uYCB0b29scyBhbmQgaGFyZC1lcnJvcnMgb3RoZXJ3aXNlOlxuICogICBcIkFudGhyb3BpYyBkb2VzIG5vdCBzdXBwb3J0IHRvb2wgdHlwZSAnd2ViX3NlYXJjaCcuIE9ubHkgJ2Z1bmN0aW9uJyBpcyBzdXBwb3J0ZWQuXCJcbiAqIENhbGwgdGhpcyBiZWZvcmUgZm9yd2FyZGluZyB0byBgL3NlcnZpbmctZW5kcG9pbnRzL29wZW4tcmVzcG9uc2VzYC4gVGhlIE9wZW5BSVxuICogYC9zZXJ2aW5nLWVuZHBvaW50cy9yZXNwb25zZXNgIHBhdGggc2hvdWxkIGtlZXAgYnVpbHQtaW5zIChHUFQgc3VwcG9ydHMgdGhlbSkuXG4gKiBJZiBmaWx0ZXJpbmcgZW1wdGllcyB0aGUgbGlzdCwgYHRvb2xzYCAvIGB0b29sX2Nob2ljZWAgLyBgcGFyYWxsZWxfdG9vbF9jYWxsc2BcbiAqIGFyZSBkcm9wcGVkIHNvIHdlIG5ldmVyIHNlbmQgYW4gZW1wdHkgYHRvb2xzOiBbXWAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzYW5pdGl6ZVJlc3BvbnNlc1Rvb2xzKGJvZHk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICBpZiAoIUFycmF5LmlzQXJyYXkoYm9keS50b29scykgfHwgYm9keS50b29scy5sZW5ndGggPT09IDApIHJldHVybiBib2R5O1xuICBjb25zdCBmblRvb2xzID0gYm9keS50b29scy5maWx0ZXIoXG4gICAgKHQpID0+IHQgJiYgdHlwZW9mIHQgPT09IFwib2JqZWN0XCIgJiYgKHQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLnR5cGUgPT09IFwiZnVuY3Rpb25cIixcbiAgKTtcbiAgaWYgKGZuVG9vbHMubGVuZ3RoID09PSBib2R5LnRvb2xzLmxlbmd0aCkgcmV0dXJuIGJvZHk7IC8vIG5vdGhpbmcgdG8gc3RyaXBcbiAgY29uc3QgbmV4dDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7IC4uLmJvZHkgfTtcbiAgaWYgKGZuVG9vbHMubGVuZ3RoID4gMCkge1xuICAgIG5leHQudG9vbHMgPSBmblRvb2xzO1xuICB9IGVsc2Uge1xuICAgIGRlbGV0ZSBuZXh0LnRvb2xzO1xuICAgIGRlbGV0ZSBuZXh0LnRvb2xfY2hvaWNlO1xuICAgIGRlbGV0ZSBuZXh0LnBhcmFsbGVsX3Rvb2xfY2FsbHM7XG4gIH1cbiAgcmV0dXJuIG5leHQ7XG59XG5cbi8qKlxuICogQ29udGVudC1wYXJ0IC8gaW5wdXQtaXRlbSB0eXBlcyBDbGF1ZGUgZXh0ZW5kZWQgdGhpbmtpbmcgdXNlcyBvbiB0aGUgd2lyZS5cbiAqXG4gKiBTaGFyZWQgc28gYm90aCB3aXJlIHN1cmZhY2VzIHN0cmlwIHRoZSBzYW1lIHNldDogdGhlIFJlc3BvbnNlcyBwYXRoIGhlcmVcbiAqICh7QGxpbmsgc2FuaXRpemVPcGVuUmVzcG9uc2VzSW5wdXR9KSBhbmQgdGhlIENoYXQgQ29tcGxldGlvbnMgcGF0aCBpblxuICogYEBkYngtdG9vbHMvYXBwa2l0LW1hc3RyYWAncyBzZXJ2aW5nIHNhbml0aXplLiBBbnRocm9waWMgc2lnbnMgdGhlc2UgYmxvY2tzLFxuICogc28gYSByZXBsYXkgdGhhdCBtdXRhdGVzIG9uZSBpcyByZWplY3RlZCBvdXRyaWdodCAtIGJvdGggcGF0aHMgbXVzdCBhZ3JlZSBvblxuICogd2hhdCBjb3VudHMgYXMgYSByZWFzb25pbmcgYmxvY2suXG4gKi9cbmV4cG9ydCBjb25zdCBSRUFTT05JTkdfVFlQRVM6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0KFtcbiAgXCJyZWFzb25pbmdcIixcbiAgXCJ0aGlua2luZ1wiLFxuICBcInJlZGFjdGVkX3RoaW5raW5nXCIsXG5dKTtcblxuLyoqXG4gKiBSZXdyaXRlIFJlc3BvbnNlcyBgaW5wdXRgIHNvIE9wZW4gUmVzcG9uc2VzIHdpbGwgYWNjZXB0IGl0LlxuICpcbiAqIFR3byBPcGVuQUkgLyBDb2RleCBzaGFwZXMgdGhhdCBEYXRhYnJpY2tzIE9wZW4gUmVzcG9uc2VzIChDbGF1ZGUsIEdlbWluaSwg4oCmKVxuICogcmVqZWN0OlxuICpcbiAqIDEuIFByaW9yIGFzc2lzdGFudCB0dXJucyB3aXRoIGBvdXRwdXRfdGV4dGAgLyBgb3V0cHV0XypgIGNvbnRlbnQgcGFydHMg4oCUXG4gKiAgICBPcGVuIFJlc3BvbnNlcyBvbmx5IGFsbG93cyBgaW5wdXRfdGV4dGAsIGBpbnB1dF9pbWFnZWAsIGBpbnB1dF9maWxlYCxcbiAqICAgIGBpbnB1dF9hdWRpb2AuIE1hcCBldmVyeSBgb3V0cHV0XzxraW5kPmAgcGFydCB0byBgaW5wdXRfPGtpbmQ+YC5cbiAqIDIuIFJlcGxheWVkIGV4dGVuZGVkLXRoaW5raW5nIGJsb2NrcyAoYHRoaW5raW5nYCwgYHJlZGFjdGVkX3RoaW5raW5nYCxcbiAqICAgIGByZWFzb25pbmdgIGNvbnRlbnQgcGFydHMsIGFuZCB0b3AtbGV2ZWwgYHJlYXNvbmluZ2AgaW5wdXQgaXRlbXMpLiBDbGF1ZGVcbiAqICAgIHNpZ25zIHRob3NlOyBhbnkgY2xpZW50IHJvdW5kLXRyaXAgdGhhdCBtdXRhdGVzIHRoZW0gKG9yIGEgY3Jvc3MtcHJvdmlkZXJcbiAqICAgIHJlcGxheSkgZmFpbHMgd2l0aCBlLmcuXG4gKiAgICAgIFwibWVzc2FnZXMuTi5jb250ZW50Lk06IEludmFsaWQgYGRhdGFgIGluIGByZWRhY3RlZF90aGlua2luZ2AgYmxvY2tcIlxuICogICAgU3RyaXAgdGhlbSDigJQgdGhlIFVJL2NsaWVudCBhbHJlYWR5IHNob3dlZCB0aGUgdGhpbmtpbmc7IHJlcGxheSBkb2VzIG5vdFxuICogICAgbmVlZCB0aGUgc2lnbmVkIGJsb2IuIFNhbWUgcG9saWN5IGFzIGFwcGtpdC1tYXN0cmEncyBzZXJ2aW5nIHNhbml0aXplLlxuICpcbiAqIFJldHVybnMgYSBzaGFsbG93IGNvcHkgd2hlbiBhbnl0aGluZyBjaGFuZ2VzOyBvdGhlcndpc2UgdGhlIGlucHV0IGJvZHkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzYW5pdGl6ZU9wZW5SZXNwb25zZXNJbnB1dChib2R5OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgaWYgKCFBcnJheS5pc0FycmF5KGJvZHkuaW5wdXQpIHx8IGJvZHkuaW5wdXQubGVuZ3RoID09PSAwKSByZXR1cm4gYm9keTtcblxuICBsZXQgY2hhbmdlZCA9IGZhbHNlO1xuICBjb25zdCBpbnB1dDogdW5rbm93bltdID0gW107XG5cbiAgZm9yIChjb25zdCByYXcgb2YgYm9keS5pbnB1dCkge1xuICAgIGlmICghcmF3IHx8IHR5cGVvZiByYXcgIT09IFwib2JqZWN0XCIpIHtcbiAgICAgIGlucHV0LnB1c2gocmF3KTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBpdGVtID0gcmF3IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4gICAgLy8gVG9wLWxldmVsIFJlc3BvbnNlcyByZWFzb25pbmcgaXRlbXMgKG5vdCBtZXNzYWdlIGNvbnRlbnQgcGFydHMpLlxuICAgIGlmICh0eXBlb2YgaXRlbS50eXBlID09PSBcInN0cmluZ1wiICYmIFJFQVNPTklOR19UWVBFUy5oYXMoaXRlbS50eXBlKSkge1xuICAgICAgY2hhbmdlZCA9IHRydWU7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoaXRlbS5jb250ZW50KSkge1xuICAgICAgaW5wdXQucHVzaChyYXcpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgbGV0IHBhcnRDaGFuZ2VkID0gZmFsc2U7XG4gICAgY29uc3QgY29udGVudDogdW5rbm93bltdID0gW107XG4gICAgZm9yIChjb25zdCBwYXJ0IG9mIGl0ZW0uY29udGVudCkge1xuICAgICAgaWYgKCFwYXJ0IHx8IHR5cGVvZiBwYXJ0ICE9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIGNvbnRlbnQucHVzaChwYXJ0KTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCBwID0gcGFydCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIGlmICh0eXBlb2YgcC50eXBlID09PSBcInN0cmluZ1wiICYmIFJFQVNPTklOR19UWVBFUy5oYXMocC50eXBlKSkge1xuICAgICAgICBwYXJ0Q2hhbmdlZCA9IHRydWU7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiBwLnR5cGUgPT09IFwic3RyaW5nXCIgJiYgcC50eXBlLnN0YXJ0c1dpdGgoXCJvdXRwdXRfXCIpKSB7XG4gICAgICAgIHBhcnRDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgY29udGVudC5wdXNoKHsgLi4ucCwgdHlwZTogYGlucHV0XyR7cC50eXBlLnNsaWNlKFwib3V0cHV0X1wiLmxlbmd0aCl9YCB9KTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb250ZW50LnB1c2gocGFydCk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJ0Q2hhbmdlZCkge1xuICAgICAgaW5wdXQucHVzaChyYXcpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNoYW5nZWQgPSB0cnVlO1xuICAgIC8vIERyb3AgYXNzaXN0YW50IHR1cm5zIHRoYXQgb25seSBjYXJyaWVkIHRoaW5raW5nIChub3RoaW5nIGxlZnQgdG8gcmVwbGF5KS5cbiAgICBpZiAoY29udGVudC5sZW5ndGggPT09IDAgJiYgaXRlbS5yb2xlID09PSBcImFzc2lzdGFudFwiKSBjb250aW51ZTtcbiAgICBpbnB1dC5wdXNoKHsgLi4uaXRlbSwgY29udGVudCB9KTtcbiAgfVxuXG4gIHJldHVybiBjaGFuZ2VkID8geyAuLi5ib2R5LCBpbnB1dCB9IDogYm9keTtcbn1cblxuLyoqXG4gKiBGdWxsIE9wZW4gUmVzcG9uc2VzIHJlcXVlc3Qgc2FuaXRpemVyOiBzdHJpcCBub24tYGZ1bmN0aW9uYCB0b29scywgcmV3cml0ZVxuICogYG91dHB1dF8qYCBjb250ZW50IHBhcnRzLCBhbmQgZHJvcCB0aGlua2luZyAvIHJlYXNvbmluZyBibG9ja3MuIFNhZmUgbm8tb3BcbiAqIHdoZW4gbm90aGluZyBuZWVkcyBjaGFuZ2luZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNhbml0aXplT3BlblJlc3BvbnNlc1JlcXVlc3QoXG4gIGJvZHk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICByZXR1cm4gc2FuaXRpemVPcGVuUmVzcG9uc2VzSW5wdXQoc2FuaXRpemVSZXNwb25zZXNUb29scyhib2R5KSk7XG59XG4iXX0=