@cartanova/qgrid-cli 2.3.4 → 2.3.5
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.
|
@@ -3,7 +3,7 @@ import { ANTHROPIC_CLAUDE_CWD, ANTHROPIC_DISALLOWED_TOOLS, anthropicConfigDir, a
|
|
|
3
3
|
import { buildStreamJsonInput, handleStreamJsonLine } from "./stream-json-adapter.js";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
|
-
import { mkdirSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { mkdirSync, unlinkSync, writeFileSync } from "node:fs";
|
|
7
7
|
//#region src/utils/providers/anthropic/claude-session.ts
|
|
8
8
|
/**
|
|
9
9
|
* claude-session — Claude CLI 세션 spawn + QgridThreadCoord 매핑 + per-session 락.
|
|
@@ -69,16 +69,19 @@ function structuredOutputRetriesEnv(raw = process.env.MAX_STRUCTURED_OUTPUT_RETR
|
|
|
69
69
|
if (!Number.isFinite(parsed)) return { MAX_STRUCTURED_OUTPUT_RETRIES: "1" };
|
|
70
70
|
return { MAX_STRUCTURED_OUTPUT_RETRIES: String(Math.max(parsed, 1)) };
|
|
71
71
|
}
|
|
72
|
+
const SYSTEM_PROMPT_ARGV_MAX_BYTES = 64 * 1024;
|
|
72
73
|
function buildClaudeArgs(opts) {
|
|
73
74
|
const useStructured = Boolean(opts.jsonSchema && opts.jsonSchema.length > 0);
|
|
75
|
+
const toolArgs = useStructured ? [
|
|
76
|
+
"--tools",
|
|
77
|
+
"",
|
|
78
|
+
"--allowed-tools",
|
|
79
|
+
"StructuredOutput"
|
|
80
|
+
] : ["--tools", ""];
|
|
81
|
+
const systemArgs = opts.systemPromptFile ? ["--system-prompt-file", opts.systemPromptFile] : ["--system-prompt", opts.system ?? ""];
|
|
74
82
|
const args = [
|
|
75
83
|
"-p",
|
|
76
|
-
...
|
|
77
|
-
"--tools",
|
|
78
|
-
"",
|
|
79
|
-
"--allowed-tools",
|
|
80
|
-
"StructuredOutput"
|
|
81
|
-
] : ["--tools", ""],
|
|
84
|
+
...toolArgs,
|
|
82
85
|
"--disallowedTools",
|
|
83
86
|
...ANTHROPIC_DISALLOWED_TOOLS,
|
|
84
87
|
"--input-format",
|
|
@@ -93,8 +96,7 @@ function buildClaudeArgs(opts) {
|
|
|
93
96
|
"project",
|
|
94
97
|
"--model",
|
|
95
98
|
applyOneMillionSuffix(opts.model, opts.needsOneMillionSuffix ?? false),
|
|
96
|
-
|
|
97
|
-
opts.system ?? "",
|
|
99
|
+
...systemArgs,
|
|
98
100
|
"--thinking",
|
|
99
101
|
"disabled",
|
|
100
102
|
"--effort",
|
|
@@ -121,9 +123,13 @@ function runClaudeSession(req, onDelta) {
|
|
|
121
123
|
return withSessionLock(sessionId, () => {
|
|
122
124
|
ensureCwd();
|
|
123
125
|
const configDir = ensureConfigDir(req.tokenId);
|
|
126
|
+
const system = req.system ?? "";
|
|
127
|
+
const useSystemPromptFile = Buffer.byteLength(system, "utf8") > SYSTEM_PROMPT_ARGV_MAX_BYTES;
|
|
128
|
+
const systemPromptFile = useSystemPromptFile ? `${configDir}/system-prompt-${sessionId}.txt` : void 0;
|
|
124
129
|
const args = buildClaudeArgs({
|
|
125
130
|
model,
|
|
126
|
-
system: req.system,
|
|
131
|
+
system: useSystemPromptFile ? void 0 : req.system,
|
|
132
|
+
systemPromptFile,
|
|
127
133
|
effort: req.effort,
|
|
128
134
|
jsonSchema: req.jsonSchema,
|
|
129
135
|
sessionId,
|
|
@@ -139,6 +145,7 @@ function runClaudeSession(req, onDelta) {
|
|
|
139
145
|
reject(/* @__PURE__ */ new Error("aborted"));
|
|
140
146
|
return;
|
|
141
147
|
}
|
|
148
|
+
if (systemPromptFile) writeFileSync(systemPromptFile, system);
|
|
142
149
|
const child = spawn("claude", args, {
|
|
143
150
|
stdio: [
|
|
144
151
|
"pipe",
|
|
@@ -172,11 +179,18 @@ function runClaudeSession(req, onDelta) {
|
|
|
172
179
|
stderrBuf = (stderrBuf + d.toString()).slice(-STDERR_CAP);
|
|
173
180
|
});
|
|
174
181
|
const stderrSuffix = () => stderrBuf.trim() ? ` — stderr: ${stderrBuf.trim()}` : "";
|
|
182
|
+
const cleanupSpawnFiles = () => {
|
|
183
|
+
if (!systemPromptFile) return;
|
|
184
|
+
try {
|
|
185
|
+
unlinkSync(systemPromptFile);
|
|
186
|
+
} catch {}
|
|
187
|
+
};
|
|
175
188
|
let cleanupAbort;
|
|
176
189
|
const timer = setTimeout(() => {
|
|
177
190
|
if (settled) return;
|
|
178
191
|
settled = true;
|
|
179
192
|
cleanupAbort?.();
|
|
193
|
+
cleanupSpawnFiles();
|
|
180
194
|
child.kill();
|
|
181
195
|
reject(/* @__PURE__ */ new Error(`Claude session timeout after ${req.timeoutMs / 1e3}s`));
|
|
182
196
|
}, req.timeoutMs);
|
|
@@ -185,6 +199,7 @@ function runClaudeSession(req, onDelta) {
|
|
|
185
199
|
settled = true;
|
|
186
200
|
clearTimeout(timer);
|
|
187
201
|
cleanupAbort?.();
|
|
202
|
+
cleanupSpawnFiles();
|
|
188
203
|
resolve({
|
|
189
204
|
...result,
|
|
190
205
|
sessionId,
|
|
@@ -196,6 +211,7 @@ function runClaudeSession(req, onDelta) {
|
|
|
196
211
|
settled = true;
|
|
197
212
|
clearTimeout(timer);
|
|
198
213
|
cleanupAbort?.();
|
|
214
|
+
cleanupSpawnFiles();
|
|
199
215
|
child.kill();
|
|
200
216
|
reject(/* @__PURE__ */ new Error("aborted"));
|
|
201
217
|
};
|
|
@@ -222,6 +238,7 @@ function runClaudeSession(req, onDelta) {
|
|
|
222
238
|
settled = true;
|
|
223
239
|
clearTimeout(timer);
|
|
224
240
|
cleanupAbort?.();
|
|
241
|
+
cleanupSpawnFiles();
|
|
225
242
|
reject(/* @__PURE__ */ new Error(`Claude session closed without result${stderrSuffix()}`));
|
|
226
243
|
});
|
|
227
244
|
child.on("error", (err) => {
|
|
@@ -229,6 +246,7 @@ function runClaudeSession(req, onDelta) {
|
|
|
229
246
|
settled = true;
|
|
230
247
|
clearTimeout(timer);
|
|
231
248
|
cleanupAbort?.();
|
|
249
|
+
cleanupSpawnFiles();
|
|
232
250
|
reject(/* @__PURE__ */ new Error(`Claude session spawn error: ${err.message}`));
|
|
233
251
|
});
|
|
234
252
|
child.stdin?.write(stdinPayload);
|
|
@@ -237,6 +255,6 @@ function runClaudeSession(req, onDelta) {
|
|
|
237
255
|
});
|
|
238
256
|
}
|
|
239
257
|
//#endregion
|
|
240
|
-
export { applyOneMillionSuffix, buildClaudeArgs, decorateAndSerialize, ensureConfigDir, makeAnthropicWorkerId, oneMillionEnv, runClaudeSession, structuredOutputRetriesEnv, withSessionLock };
|
|
258
|
+
export { SYSTEM_PROMPT_ARGV_MAX_BYTES, applyOneMillionSuffix, buildClaudeArgs, decorateAndSerialize, ensureConfigDir, makeAnthropicWorkerId, oneMillionEnv, runClaudeSession, structuredOutputRetriesEnv, withSessionLock };
|
|
241
259
|
|
|
242
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhdWRlLXNlc3Npb24uanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9hbnRocm9waWMvY2xhdWRlLXNlc3Npb24udHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBjbGF1ZGUtc2Vzc2lvbiDigJQgQ2xhdWRlIENMSSDshLjshZggc3Bhd24gKyBRZ3JpZFRocmVhZENvb3JkIOunpO2VkSArIHBlci1zZXNzaW9uIOudvS5cbiAqXG4gKiDrqYDti7DthLQ6IOunpCDtmLjstpwgZnJlc2ggYC0tc2Vzc2lvbi1pZCA8dXVpZD5g66GcIOyLpO2Wie2VnOuLpC4g7J6F66Cl7J2AIOyWtOuMke2EsOqwgCDrp4zrk6AgSlNPTkwg7J2EXG4gKiBzdGRpbiDsnLzroZwg7Z2Y66as6rOgKGAtLWlucHV0LWZvcm1hdCBzdHJlYW0tanNvbmApLCDstpzroKXsnYAg7YyM7ISc66GcIOyymOumrO2VnOuLpC5cbiAqXG4gKiDtlbXsi6wg6rOE7JW9OlxuICogIC0gY29vcmQg64qUIOyehOydmCDsoIDsnqXsnbQg7JWE64uI6528IOq4sOyhtCBRZ3JpZFRocmVhZENvb3Jke3dvcmtlcklkLHRocmVhZElkLGVwb2NoLHN5c3RlbUhhc2h9IOyXkFxuICogICAg66ek7ZWR7ZWc64ukLiB0aHJlYWRJZD3shLjshZggdXVpZCwgZXBvY2g9MCDqs6DsoJUod29ya2VyIHJlc3RhcnQg6rCc64WQIOyXhuydjCksIHdvcmtlcklkPXRva2VuIOq4sOuwmFxuICogICAg7JWI7KCVIO2VqeyEsSwgc3lzdGVtSGFzaD3smpTssq0gc3lzdGVtIO2VtOyLnC4gaXNzdWVDb252Q29udGV4dC9kZWNpZGVDb252Um91dGluZyDqs7wgcm91bmQtdHJpcC5cbiAqICAtIHdpdGhTZXNzaW9uTG9jayDsnYAgZXhwb3J0ZWQgcHJpbWl0aXZlIOuhnCDsnKDsp4DtlZzri6QuIOq4sOuzuCDqsr3roZzsl5DshJzripQg66ekIO2YuOy2nCDsg4ggc2Vzc2lvbi1pZCDrnbxcbiAqICAgIOyCrOyLpOyDgSBuby1jb250ZW50aW9uIOydtOyngOunjCwg7KeB7KCRIO2YuOy2nOyekC/thYzsiqTtirjsnZgg7KeB66Cs7ZmUIOuztOyepeydgCDrs7TsobTtlZzri6QuXG4gKiAgLSBzdHJlYW0tanNvbiDsp4HroKztmZQg7IucIFNESyBlbnZlbG9wZSh1dWlkL3Nlc3Npb25faWQvcGFyZW50X3Rvb2xfdXNlX2lkKSBkZWNvcmF0ZS5cbiAqICAtIHN0cnVjdHVyZWQgb3V0cHV0IOydvCDrlYwg7Lac66ClIO2MjOyEnOyXkCB7IHN0cnVjdHVyZWRPdXRwdXQ6IHRydWUgfSDsoITri6wo7JeG7Jy866m0IHN0cmVhbU9iamVjdCDquajsp5ApLlxuICovXG5cbmltcG9ydCB7IHNwYXduIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgcmFuZG9tVVVJRCB9IGZyb20gXCJub2RlOmNyeXB0b1wiO1xuaW1wb3J0IHsgbWtkaXJTeW5jLCB3cml0ZUZpbGVTeW5jIH0gZnJvbSBcIm5vZGU6ZnNcIjtcblxuaW1wb3J0IHsgdHlwZSBKc29uVmFsdWUgfSBmcm9tIFwiLi4vLi4vLi4vY29kZXgtcHJvdG9jb2wvc2VyZGVfanNvbi9Kc29uVmFsdWVcIjtcbmltcG9ydCB7IHR5cGUgVG9rZW5Vc2FnZUJyZWFrZG93biB9IGZyb20gXCIuLi8uLi8uLi9jb2RleC1wcm90b2NvbC92Mi9Ub2tlblVzYWdlQnJlYWtkb3duXCI7XG5pbXBvcnQgeyB0eXBlIFVzZXJJbnB1dCB9IGZyb20gXCIuLi8uLi8uLi9jb2RleC1wcm90b2NvbC92Mi9Vc2VySW5wdXRcIjtcbmltcG9ydCB7XG4gIEFOVEhST1BJQ19DTEFVREVfQ1dELFxuICBhbnRocm9waWNDb25maWdEaXIsXG4gIEFOVEhST1BJQ19ERUZBVUxUX0VGRk9SVCxcbiAgQU5USFJPUElDX0RJU0FMTE9XRURfVE9PTFMsXG4gIGFzc2VydFN1cHBvcnRlZE9uZU1pbGxpb25TdWZmaXgsXG4gIGNhbm9uaWNhbEFudGhyb3BpY01vZGVsLFxuICBuZWVkc0NsaTFtU3VmZml4LFxuICBzdXBwb3J0czFNQ29udGV4dCxcbn0gZnJvbSBcIi4vYW50aHJvcGljLWNvbnN0YW50c1wiO1xuaW1wb3J0IHtcbiAgYnVpbGRTdHJlYW1Kc29uSW5wdXQsXG4gIHR5cGUgQ2xhdWRlU3RyZWFtSnNvblN0YXRlLFxuICB0eXBlIENsYXVkZVN0cmVhbUpzb25MaW5lLFxuICB0eXBlIENsYXVkZVN0cmVhbVJlc3VsdCxcbiAgaGFuZGxlU3RyZWFtSnNvbkxpbmUsXG59IGZyb20gXCIuL3N0cmVhbS1qc29uLWFkYXB0ZXJcIjtcblxuLy8g4pSA4pSAIHBlci1zZXNzaW9uIOudvSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLy8gc2Vzc2lvbi1pZCDri6jsnIQg7KeB66Cs7ZmUIHByaW1pdGl2ZS4g6riw67O4IOqyveuhnOyXkOyEnOuKlCDrp6Qg7Zi47LacIOyDiCB1dWlkIOudvCDsgqzsi6Tsg4Egbm8tb3Ag7J207KeA66eMLFxuLy8g6rCZ7J2AIHNlc3Npb24taWQg66W8IOyngeygkSDsk7DripQg7Zi47Lac7J6Q64qUIOyXrOyghO2eiCDsp4HroKztmZQg67O07J6l7J2EIOuwm+uKlOuLpC5cbmNvbnN0IHNlc3Npb25DaGFpbnMgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTx1bmtub3duPj4oKTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdpdGhTZXNzaW9uTG9jazxUPihzZXNzaW9uSWQ6IHN0cmluZywgZm46ICgpID0+IFByb21pc2U8VD4pOiBQcm9taXNlPFQ+IHtcbiAgY29uc3QgcHJldiA9IHNlc3Npb25DaGFpbnMuZ2V0KHNlc3Npb25JZCkgPz8gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIC8vIOydtOyghCB0dXJuIOydmCDshLHtjKjsmYAg66y06rSA7ZWY6rKMIOyngeugrCDssrTsnbjsnYQg7J6H64qU64ukLlxuICBjb25zdCBuZXh0ID0gcHJldi50aGVuKGZuLCBmbik7XG4gIC8vIHRhaWw6IOyEse2MqCDrrLTqtIAgc2V0dGxlIOuQmOuKlCDtlbjrk6QuIOydtOqxuCDrp7Xsl5Ag65GQ6rOgLCBmaW5hbGx5IOyXkOyEnCBcIuyXrOyghO2eiCDrgrTqsIAg64GdXCLsnbwg65WM66eMIOyCreygnC5cbiAgLy8gKHNldCDsp4Htm4QgdW5kZWZpbmVkIOqygOyCrOuhnCDtlZjrqbQg7KCI64yAIOyCreygnCDslYgg64+8IOyEuOyFmCBpZCDqsIAg64iE7IiY65CoIOKAlCB0YWlsIOydvOy5mCDqsoDsgqzroZwg7ZqM7ZS8LilcbiAgY29uc3QgdGFpbCA9IG5leHQudGhlbihcbiAgICAoKSA9PiB7fSxcbiAgICAoKSA9PiB7fSxcbiAgKTtcbiAgc2Vzc2lvbkNoYWlucy5zZXQoc2Vzc2lvbklkLCB0YWlsKTtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgbmV4dDtcbiAgfSBmaW5hbGx5IHtcbiAgICAvLyDqt7gg7IKs7J20IOuLpOuluCB0dXJuIOydtCDssrTsnbjsnYQg7J207Ja067Cb7JWY7Jy866m0IHRhaWwg7J20IOq1kOyytOuPvCDsnojri6Qg4oCUIOq3uOuVjOuKlCDsgq3soJztlZjsp4Ag7JWK64qU64ukLlxuICAgIGlmIChzZXNzaW9uQ2hhaW5zLmdldChzZXNzaW9uSWQpID09PSB0YWlsKSBzZXNzaW9uQ2hhaW5zLmRlbGV0ZShzZXNzaW9uSWQpO1xuICB9XG59XG5cbi8vIOKUgOKUgCBjb29yZCDrp6TtlZEg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbi8vIHRva2VuIOq4sOuwmCDslYjsoJUgd29ya2VySWQg7ZWp7ISxLiBBbnRocm9waWMg7J2AIHdvcmtlciBwb29sIOydtCDsl4bsnLzrr4DroZwgdG9rZW5JZCDrpbwg6re464yA66GcIOyTtOuLpC5cbmV4cG9ydCBmdW5jdGlvbiBtYWtlQW50aHJvcGljV29ya2VySWQodG9rZW5JZDogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIHRva2VuSWQ7XG59XG5cbi8vIOKUgOKUgCBlbnZlbG9wZSBkZWNvcmF0ZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLy8gc3RyZWFtLWpzb24g7J6F66ClIOudvOyduOyXkCBTREsgZW52ZWxvcGUg67aA7LCpIO2bhCDsp4HroKztmZQuIHNlc3Npb24g7IaM7Jyg7J6Q7J24IOyXrOq4sOyEnCDtlZzri6QuXG5leHBvcnQgZnVuY3Rpb24gZGVjb3JhdGVBbmRTZXJpYWxpemUoXG4gIGxpbmVzOiBBcnJheTxDbGF1ZGVTdHJlYW1Kc29uTGluZT4sXG4gIHNlc3Npb25JZDogc3RyaW5nLFxuKTogc3RyaW5nIHtcbiAgcmV0dXJuIChcbiAgICBsaW5lc1xuICAgICAgLm1hcCgobGluZSkgPT5cbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgIC4uLmxpbmUsXG4gICAgICAgICAgc2Vzc2lvbl9pZDogc2Vzc2lvbklkLFxuICAgICAgICAgIHV1aWQ6IHJhbmRvbVVVSUQoKSxcbiAgICAgICAgICBwYXJlbnRfdG9vbF91c2VfaWQ6IG51bGwsXG4gICAgICAgIH0pLFxuICAgICAgKVxuICAgICAgLmpvaW4oXCJcXG5cIikgKyBcIlxcblwiXG4gICk7XG59XG5cbi8vIOKUgOKUgCBzcGF3biArIGNvbnN1bWUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xhdWRlU2Vzc2lvblJlcXVlc3Qge1xuICB0b2tlbklkOiBudW1iZXI7XG4gIHRva2VuOiBzdHJpbmc7IC8vIE9BdXRoIGFjY2VzcyB0b2tlblxuICBtb2RlbDogc3RyaW5nO1xuICBzeXN0ZW0/OiBzdHJpbmc7XG4gIGpzb25TY2hlbWE/OiBzdHJpbmc7IC8vIOyeiOycvOuptCBzdHJ1Y3R1cmVkIG91dHB1dFxuICBlZmZvcnQ/OiBzdHJpbmc7XG4gIHRpbWVvdXRNczogbnVtYmVyO1xuICBjb2xkSGlzdG9yeT86IEFycmF5PEpzb25WYWx1ZT47XG4gIGlucHV0OiBBcnJheTxVc2VySW5wdXQ+O1xuICBhYm9ydFNpZ25hbD86IEFib3J0U2lnbmFsO1xuICBpbmNsdWRlUGFydGlhbE1lc3NhZ2VzPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDbGF1ZGVTZXNzaW9uUmVzdWx0IGV4dGVuZHMgQ2xhdWRlU3RyZWFtUmVzdWx0IHtcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIHdvcmtlcklkOiBudW1iZXI7XG59XG5cbi8vIHBlci10b2tlbiBDTEFVREVfQ09ORklHX0RJUiDrs7TsnqUo6rKp66asKS4g6rK966GcIOq3nOy5meydgCBhbnRocm9waWNDb25maWdEaXIo7Iic7IiYIO2VqOyImCnsnbQg7IaM7JygIOKAlFxuLy8g7Jes6riw7ISgIOq3uCDqsr3roZzsl5Ag67mIIHNldHRpbmdzIOulvCDquZTslYQgY2xhdWRlLW1lbSBob29rIOuTseydhCDssKjri6jtlZzri6QuIChSMTAg6rKp66asKVxuLy8g7J20IHNlZWQg7YyM7J287J2AIGNsYXVkZS1tZW0gaG9vayAvIOyCrOyaqeyekCDshKTsoJUg7Jik7Je8IOywqOuLqOydhCDsnITtlZwg6rKp66asIOqyveqzhOuLpC4g66ekIO2YuOy2nOuniOuLpCDri6Tsi5wg7I2o7IScXG4vLyDsmbjrtoAg67OA7KGwwrfsgq3soJwg7ZuE7JeQ64+EIOuLpOydjCDsi6Ttlonsl5DshJwgc2VsZi1oZWFsaW5nIOuQmOuPhOuhnSDquLDsobQgc2VtYW50aWNzIOulvCDsnKDsp4DtlZzri6QuXG5leHBvcnQgZnVuY3Rpb24gZW5zdXJlQ29uZmlnRGlyKHRva2VuSWQ6IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IGRpciA9IGFudGhyb3BpY0NvbmZpZ0Rpcih0b2tlbklkKTtcbiAgbWtkaXJTeW5jKGRpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIHdyaXRlRmlsZVN5bmMoYCR7ZGlyfS8uY2xhdWRlLmpzb25gLCBcInt9XCIpO1xuICB3cml0ZUZpbGVTeW5jKGAke2Rpcn0vc2V0dGluZ3MuanNvbmAsIFwie31cIik7XG4gIHJldHVybiBkaXI7XG59XG5cbmxldCBjd2RFbnN1cmVkID0gZmFsc2U7XG5mdW5jdGlvbiBlbnN1cmVDd2QoKTogdm9pZCB7XG4gIGlmIChjd2RFbnN1cmVkKSByZXR1cm47XG4gIG1rZGlyU3luYyhgJHtBTlRIUk9QSUNfQ0xBVURFX0NXRH0vLmNsYXVkZWAsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICB3cml0ZUZpbGVTeW5jKGAke0FOVEhST1BJQ19DTEFVREVfQ1dEfS8uY2xhdWRlL3NldHRpbmdzLmpzb25gLCBcInt9XCIpO1xuICBjd2RFbnN1cmVkID0gdHJ1ZTtcbn1cblxuLy8gc3Bhd24gYXJncyDqtazshLEuIOupgO2LsO2EtC/qsqnrpqwvc3RydWN0dXJlZCDrqqjrk5wg67CY7JiBLlxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5T25lTWlsbGlvblN1ZmZpeChtb2RlbDogc3RyaW5nLCBuZWVkc1N1ZmZpeDogYm9vbGVhbik6IHN0cmluZyB7XG4gIGNvbnN0IGJhc2UgPSBjYW5vbmljYWxBbnRocm9waWNNb2RlbChtb2RlbCk7XG4gIHJldHVybiBuZWVkc1N1ZmZpeCA/IGAke2Jhc2V9WzFtXWAgOiBiYXNlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gb25lTWlsbGlvbkVudihzdXBwb3J0ZWQ6IGJvb2xlYW4pOiB7IENMQVVERV9DT0RFX0RJU0FCTEVfMU1fQ09OVEVYVD86IFwiMVwiIH0ge1xuICByZXR1cm4gc3VwcG9ydGVkID8ge30gOiB7IENMQVVERV9DT0RFX0RJU0FCTEVfMU1fQ09OVEVYVDogXCIxXCIgfTtcbn1cblxuLy8gU09OLTQ5NTogc3RydWN0dXJlZCBvdXRwdXQgcmV0cnkg66W8IDEg66GcIOqzoOygle2VnOuLpC4gQ0Mg6rCAIGF0dGVtcHQg66W8IHJlamVjdCDtlZjqs6AgcmV0cnkg7ZWY66m0XG4vLyBge3JlamVjdGVkfXthY2NlcHRlZH1gIOuIhOyggeydtCBBSS1TREsg7J2YIEpTT04ucGFyc2Ug66W8IOq5qOucqOumrOuvgOuhnCwgcmV0cnkg7J6Q7LK066W8IOunieyVhCDqt7gg6rK966Gc66W8XG4vLyDsm5Dsspwg7LCo64uo7ZWc64ukLiBgMGAg7J2AIENDIHF1ZXJ5IGxvb3AoYGNhbGxzVGhpc1F1ZXJ5ID49IG1heFJldHJpZXNgKeqwgCDssqsgYXR0ZW1wdCBlbWl0IOyghOyXkFxuLy8g7Iuk7Yyo7Iuc7YKk66+A66GcKGBlcnJvcl9tYXhfc3RydWN0dXJlZF9vdXRwdXRfcmV0cmllc2ApIOyZuOu2gCDqsJLsnbQgMSDrr7jrp4zsnbTslrTrj4QgMSDroZwg7YG0656o7ZSE7ZWc64ukLlxuZXhwb3J0IGZ1bmN0aW9uIHN0cnVjdHVyZWRPdXRwdXRSZXRyaWVzRW52KHJhdyA9IHByb2Nlc3MuZW52Lk1BWF9TVFJVQ1RVUkVEX09VVFBVVF9SRVRSSUVTKToge1xuICBNQVhfU1RSVUNUVVJFRF9PVVRQVVRfUkVUUklFUzogc3RyaW5nO1xufSB7XG4gIGlmICghcmF3KSByZXR1cm4geyBNQVhfU1RSVUNUVVJFRF9PVVRQVVRfUkVUUklFUzogXCIxXCIgfTtcbiAgY29uc3QgcGFyc2VkID0gTnVtYmVyLnBhcnNlSW50KHJhdywgMTApO1xuICBpZiAoIU51bWJlci5pc0Zpbml0ZShwYXJzZWQpKSByZXR1cm4geyBNQVhfU1RSVUNUVVJFRF9PVVRQVVRfUkVUUklFUzogXCIxXCIgfTtcbiAgcmV0dXJuIHsgTUFYX1NUUlVDVFVSRURfT1VUUFVUX1JFVFJJRVM6IFN0cmluZyhNYXRoLm1heChwYXJzZWQsIDEpKSB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRDbGF1ZGVBcmdzKG9wdHM6IHtcbiAgbW9kZWw6IHN0cmluZztcbiAgc3lzdGVtPzogc3RyaW5nO1xuICBlZmZvcnQ/OiBzdHJpbmc7XG4gIGpzb25TY2hlbWE/OiBzdHJpbmc7XG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICBuZWVkc09uZU1pbGxpb25TdWZmaXg/OiBib29sZWFuO1xuICBpbmNsdWRlUGFydGlhbE1lc3NhZ2VzPzogYm9vbGVhbjtcbn0pOiBBcnJheTxzdHJpbmc+IHtcbiAgY29uc3QgdXNlU3RydWN0dXJlZCA9IEJvb2xlYW4ob3B0cy5qc29uU2NoZW1hICYmIG9wdHMuanNvblNjaGVtYS5sZW5ndGggPiAwKTtcbiAgLy8gLS10b29scyBcIlwiIOuhnCDsoITssrQg7LCo64uoLCBzdHJ1Y3R1cmVkKGpzb25TY2hlbWEg7J6I7J2MKSDrqbQgU3RydWN0dXJlZE91dHB1dCDrp4wg7ZeI7JqpLlxuICBjb25zdCB0b29sQXJncyA9IHVzZVN0cnVjdHVyZWRcbiAgICA/IFtcIi0tdG9vbHNcIiwgXCJcIiwgXCItLWFsbG93ZWQtdG9vbHNcIiwgXCJTdHJ1Y3R1cmVkT3V0cHV0XCJdXG4gICAgOiBbXCItLXRvb2xzXCIsIFwiXCJdO1xuXG4gIGNvbnN0IGFyZ3M6IEFycmF5PHN0cmluZz4gPSBbXG4gICAgXCItcFwiLFxuICAgIC4uLnRvb2xBcmdzLFxuICAgIFwiLS1kaXNhbGxvd2VkVG9vbHNcIixcbiAgICAuLi5BTlRIUk9QSUNfRElTQUxMT1dFRF9UT09MUyxcbiAgICBcIi0taW5wdXQtZm9ybWF0XCIsXG4gICAgXCJzdHJlYW0tanNvblwiLFxuICAgIFwiLS1vdXRwdXQtZm9ybWF0XCIsXG4gICAgXCJzdHJlYW0tanNvblwiLFxuICAgIFwiLS12ZXJib3NlXCIsXG4gICAgLi4uKG9wdHMuaW5jbHVkZVBhcnRpYWxNZXNzYWdlcyA/IFtcIi0taW5jbHVkZS1wYXJ0aWFsLW1lc3NhZ2VzXCJdIDogW10pLFxuICAgIFwiLS1wZXJtaXNzaW9uLW1vZGVcIixcbiAgICBcImJ5cGFzc1Blcm1pc3Npb25zXCIsXG4gICAgXCItLXNldHRpbmctc291cmNlc1wiLFxuICAgIFwicHJvamVjdFwiLFxuICAgIFwiLS1tb2RlbFwiLFxuICAgIGFwcGx5T25lTWlsbGlvblN1ZmZpeChvcHRzLm1vZGVsLCBvcHRzLm5lZWRzT25lTWlsbGlvblN1ZmZpeCA/PyBmYWxzZSksXG4gICAgLy8gaW5saW5lIFtTeXN0ZW1dIOq4iOyngCDigJQg7KCV7IudIOyxhOuEkOunjChSNykuIOyDneuetSDsi5wgQ0MgZGVmYXVsdCgyM2spIOyjvOyeheuQmOuvgOuhnCDrsJjrk5zsi5wg66qF7IucLlxuICAgIFwiLS1zeXN0ZW0tcHJvbXB0XCIsXG4gICAgb3B0cy5zeXN0ZW0gPz8gXCJcIixcbiAgICBcIi0tdGhpbmtpbmdcIixcbiAgICBcImRpc2FibGVkXCIsXG4gICAgXCItLWVmZm9ydFwiLFxuICAgIG9wdHMuZWZmb3J0ID8/IEFOVEhST1BJQ19ERUZBVUxUX0VGRk9SVCxcbiAgICBcIi0tZGlzYWJsZS1zbGFzaC1jb21tYW5kc1wiLFxuICAgIFwiLS1zZXNzaW9uLWlkXCIsXG4gICAgb3B0cy5zZXNzaW9uSWQsXG4gIF07XG4gIGlmICh1c2VTdHJ1Y3R1cmVkKSBhcmdzLnB1c2goXCItLWpzb24tc2NoZW1hXCIsIG9wdHMuanNvblNjaGVtYSEpO1xuICByZXR1cm4gYXJncztcbn1cblxuLyoqXG4gKiBDbGF1ZGUg7IS47IWY7J2EIHNwYXduIO2VtCDtlZwgdHVybiDsnYQg7Iuk7ZaJ7ZWc64ukLiBwZXItc2Vzc2lvbiDrnb3snLzroZwg7KeB66Cs7ZmU65Cc64ukLlxuICogQHBhcmFtIG9uRGVsdGEg7KCQ7KeEIO2FjeyKpO2KuCBkZWx0YShzdHJlYW1UZXh0KSDrmJDripQgc3RydWN0dXJlZCDrtoDrtoQgSlNPTihzdHJlYW1PYmplY3QpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuQ2xhdWRlU2Vzc2lvbihcbiAgcmVxOiBDbGF1ZGVTZXNzaW9uUmVxdWVzdCxcbiAgb25EZWx0YTogKHRleHQ6IHN0cmluZykgPT4gdm9pZCxcbik6IFByb21pc2U8Q2xhdWRlU2Vzc2lvblJlc3VsdD4ge1xuICAvLyDsoJXqt5ztmZQg6rec7LmZ7J2AIGNhbm9uaWNhbEFudGhyb3BpY01vZGVsIOydtCDri6jrj4Ug7IaM7JygIOKAlCBkaXNwYXRjaGVyIOqwgCDsnbTrr7ggY2Fub25pY2FsIOydhCDrhJjquLDsp4Drp4wsXG4gIC8vIOyngeygkSDtmLjstpwo7YWM7Iqk7Yq4L+uvuOuemCBjYWxsZXIpIOuMgOu5hCDrsKnslrTsoIHsnLzroZwg7ZWcIOuyiCDrjZQg7Ya16rO87Iuc7YKo64ukKOydtOuvuCBjYW5vbmljYWwg7J2066m0IG5vLW9wKS5cbiAgYXNzZXJ0U3VwcG9ydGVkT25lTWlsbGlvblN1ZmZpeChyZXEubW9kZWwpO1xuICBjb25zdCBtb2RlbCA9IGNhbm9uaWNhbEFudGhyb3BpY01vZGVsKHJlcS5tb2RlbCk7XG4gIGNvbnN0IHN1cHBvcnRzT25lTWlsbGlvbiA9IHN1cHBvcnRzMU1Db250ZXh0KG1vZGVsKTtcbiAgY29uc3QgbmVlZHNPbmVNaWxsaW9uU3VmZml4ID0gbmVlZHNDbGkxbVN1ZmZpeChtb2RlbCk7XG4gIGNvbnN0IHNlc3Npb25JZCA9IHJhbmRvbVVVSUQoKTtcbiAgY29uc3QgdXNlU3RydWN0dXJlZCA9IEJvb2xlYW4ocmVxLmpzb25TY2hlbWEgJiYgcmVxLmpzb25TY2hlbWEubGVuZ3RoID4gMCk7XG4gIGNvbnN0IHdvcmtlcklkID0gbWFrZUFudGhyb3BpY1dvcmtlcklkKHJlcS50b2tlbklkKTtcblxuICByZXR1cm4gd2l0aFNlc3Npb25Mb2NrKHNlc3Npb25JZCwgKCkgPT4ge1xuICAgIGVuc3VyZUN3ZCgpO1xuICAgIGNvbnN0IGNvbmZpZ0RpciA9IGVuc3VyZUNvbmZpZ0RpcihyZXEudG9rZW5JZCk7XG5cbiAgICBjb25zdCBhcmdzID0gYnVpbGRDbGF1ZGVBcmdzKHtcbiAgICAgIG1vZGVsLFxuICAgICAgc3lzdGVtOiByZXEuc3lzdGVtLFxuICAgICAgZWZmb3J0OiByZXEuZWZmb3J0LFxuICAgICAganNvblNjaGVtYTogcmVxLmpzb25TY2hlbWEsXG4gICAgICBzZXNzaW9uSWQsXG4gICAgICBuZWVkc09uZU1pbGxpb25TdWZmaXgsXG4gICAgICBpbmNsdWRlUGFydGlhbE1lc3NhZ2VzOiByZXEuaW5jbHVkZVBhcnRpYWxNZXNzYWdlcyxcbiAgICB9KTtcblxuICAgIGNvbnN0IGlucHV0TGluZXMgPSBidWlsZFN0cmVhbUpzb25JbnB1dCh7XG4gICAgICBjb2xkSGlzdG9yeTogcmVxLmNvbGRIaXN0b3J5LFxuICAgICAgaW5wdXQ6IHJlcS5pbnB1dCxcbiAgICB9KTtcbiAgICBjb25zdCBzdGRpblBheWxvYWQgPSBkZWNvcmF0ZUFuZFNlcmlhbGl6ZShpbnB1dExpbmVzLCBzZXNzaW9uSWQpO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPENsYXVkZVNlc3Npb25SZXN1bHQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGlmIChyZXEuYWJvcnRTaWduYWw/LmFib3J0ZWQpIHtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihcImFib3J0ZWRcIikpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNoaWxkID0gc3Bhd24oXCJjbGF1ZGVcIiwgYXJncywge1xuICAgICAgICAvLyBzdGRlcnIg64+EIOy6oeyymDogaW52YWxpZCBPQXV0aCAvIOyemOuqu+uQnCDtlIzrnpjqt7ggLyBDTEkg6rKA7KadIOyLpO2MqOqwgFxuICAgICAgICAvLyBcImNsb3NlZCB3aXRob3V0IHJlc3VsdFwiIOuhnCDrrYnqsJzsp4Dsp4Ag7JWK6rKMIGNsb3NlL2Vycm9yIOyXkCBzdGRlcnIg66W8IOyLpOyWtCDrs7Trgrjri6QuXG4gICAgICAgIHN0ZGlvOiBbXCJwaXBlXCIsIFwicGlwZVwiLCBcInBpcGVcIl0sXG4gICAgICAgIGN3ZDogQU5USFJPUElDX0NMQVVERV9DV0QsXG4gICAgICAgIGVudjoge1xuICAgICAgICAgIFBBVEg6IHByb2Nlc3MuZW52LlBBVEgsXG4gICAgICAgICAgVE1QRElSOiBwcm9jZXNzLmVudi5UTVBESVIsXG4gICAgICAgICAgQ0xBVURFX0NPREVfT0FVVEhfVE9LRU46IHJlcS50b2tlbixcbiAgICAgICAgICBDTEFVREVfQ09ORklHX0RJUjogY29uZmlnRGlyLFxuICAgICAgICAgIENMQVVERV9DT0RFX0RJU0FCTEVfQVVUT19NRU1PUlk6IFwiMVwiLFxuICAgICAgICAgIENMQVVERV9DT0RFX0RJU0FCTEVfQURBUFRJVkVfVEhJTktJTkc6IFwiMVwiLFxuICAgICAgICAgIC4uLm9uZU1pbGxpb25FbnYoc3VwcG9ydHNPbmVNaWxsaW9uKSxcbiAgICAgICAgICBDTEFVREVfQ09ERV9ESVNBQkxFX0NMQVVERV9NRFM6IFwiMVwiLFxuICAgICAgICAgIENMQVVERV9DT0RFX0RJU0FCTEVfVEVSTUlOQUxfVElUTEU6IFwiMVwiLFxuICAgICAgICAgIENMQVVERV9DT0RFX0RJU0FCTEVfQlVORExFRF9TS0lMTFM6IFwiMVwiLFxuICAgICAgICAgIENMQVVERV9DT0RFX0RJU0FCTEVfV09SS0ZMT1dTOiBcIjFcIixcbiAgICAgICAgICBDTEFVREVfQ09ERV9BVFRSSUJVVElPTl9IRUFERVI6IFwiMFwiLFxuICAgICAgICAgIE1BWF9USElOS0lOR19UT0tFTlM6IFwiMFwiLFxuICAgICAgICAgIC8vIHN0cnVjdHVyZWQgb3V0cHV0IOydvCDrlYzrp4wgcmV0cnkg66W8IOqzoOygle2VnOuLpChTT04tNDk1KS4gdGV4dCDrqqjrk5zripQg7JiB7ZalIOyXhuydjC5cbiAgICAgICAgICAuLi4odXNlU3RydWN0dXJlZCA/IHN0cnVjdHVyZWRPdXRwdXRSZXRyaWVzRW52KCkgOiB7fSksXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgbGV0IHNldHRsZWQgPSBmYWxzZTtcbiAgICAgIGxldCBidWZmZXIgPSBcIlwiO1xuICAgICAgY29uc3Qgc3RyZWFtU3RhdGU6IENsYXVkZVN0cmVhbUpzb25TdGF0ZSA9IHt9O1xuICAgICAgLy8gYm91bmRlZCBzdGRlcnIg67KE7Y28KOy1nOq3vCB+NEtC66eMIOycoOyngCDigJQg66y07ZWcIOuIhOyggSDrsKnsp4ApLlxuICAgICAgbGV0IHN0ZGVyckJ1ZiA9IFwiXCI7XG4gICAgICBjb25zdCBTVERFUlJfQ0FQID0gNDA5NjtcbiAgICAgIGNoaWxkLnN0ZGVycj8ub24oXCJkYXRhXCIsIChkOiBCdWZmZXIpID0+IHtcbiAgICAgICAgc3RkZXJyQnVmID0gKHN0ZGVyckJ1ZiArIGQudG9TdHJpbmcoKSkuc2xpY2UoLVNUREVSUl9DQVApO1xuICAgICAgfSk7XG4gICAgICBjb25zdCBzdGRlcnJTdWZmaXggPSAoKSA9PiAoc3RkZXJyQnVmLnRyaW0oKSA/IGAg4oCUIHN0ZGVycjogJHtzdGRlcnJCdWYudHJpbSgpfWAgOiBcIlwiKTtcbiAgICAgIGxldCBjbGVhbnVwQWJvcnQ6ICgoKSA9PiB2b2lkKSB8IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIGlmIChzZXR0bGVkKSByZXR1cm47XG4gICAgICAgIHNldHRsZWQgPSB0cnVlO1xuICAgICAgICBjbGVhbnVwQWJvcnQ/LigpO1xuICAgICAgICBjaGlsZC5raWxsKCk7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoYENsYXVkZSBzZXNzaW9uIHRpbWVvdXQgYWZ0ZXIgJHtyZXEudGltZW91dE1zIC8gMTAwMH1zYCkpO1xuICAgICAgfSwgcmVxLnRpbWVvdXRNcyk7XG5cbiAgICAgIGNvbnN0IGZpbmlzaCA9IChyZXN1bHQ6IENsYXVkZVN0cmVhbVJlc3VsdCkgPT4ge1xuICAgICAgICBpZiAoc2V0dGxlZCkgcmV0dXJuO1xuICAgICAgICBzZXR0bGVkID0gdHJ1ZTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgY2xlYW51cEFib3J0Py4oKTtcbiAgICAgICAgcmVzb2x2ZSh7IC4uLnJlc3VsdCwgc2Vzc2lvbklkLCB3b3JrZXJJZCB9KTtcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IG9uQWJvcnQgPSAoKSA9PiB7XG4gICAgICAgIGlmIChzZXR0bGVkKSByZXR1cm47XG4gICAgICAgIHNldHRsZWQgPSB0cnVlO1xuICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgICBjbGVhbnVwQWJvcnQ/LigpO1xuICAgICAgICBjaGlsZC5raWxsKCk7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJhYm9ydGVkXCIpKTtcbiAgICAgIH07XG4gICAgICBjbGVhbnVwQWJvcnQgPSAoKSA9PiByZXEuYWJvcnRTaWduYWw/LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCBvbkFib3J0KTtcbiAgICAgIHJlcS5hYm9ydFNpZ25hbD8uYWRkRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIG9uQWJvcnQsIHsgb25jZTogdHJ1ZSB9KTtcblxuICAgICAgY2hpbGQuc3Rkb3V0Py5vbihcImRhdGFcIiwgKGQ6IEJ1ZmZlcikgPT4ge1xuICAgICAgICBpZiAoc2V0dGxlZCkgcmV0dXJuO1xuICAgICAgICBidWZmZXIgKz0gZC50b1N0cmluZygpO1xuICAgICAgICBjb25zdCBsaW5lcyA9IGJ1ZmZlci5zcGxpdChcIlxcblwiKTtcbiAgICAgICAgYnVmZmVyID0gbGluZXMucG9wKCkgPz8gXCJcIjtcbiAgICAgICAgZm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gaGFuZGxlU3RyZWFtSnNvbkxpbmUobGluZSwgb25EZWx0YSwge1xuICAgICAgICAgICAgc3RydWN0dXJlZE91dHB1dDogdXNlU3RydWN0dXJlZCxcbiAgICAgICAgICAgIHN0YXRlOiBzdHJlYW1TdGF0ZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICBmaW5pc2gocmVzdWx0KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBjaGlsZC5vbihcImNsb3NlXCIsICgpID0+IHtcbiAgICAgICAgaWYgKHNldHRsZWQpIHJldHVybjtcbiAgICAgICAgc2V0dGxlZCA9IHRydWU7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICAgIGNsZWFudXBBYm9ydD8uKCk7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoYENsYXVkZSBzZXNzaW9uIGNsb3NlZCB3aXRob3V0IHJlc3VsdCR7c3RkZXJyU3VmZml4KCl9YCkpO1xuICAgICAgfSk7XG4gICAgICBjaGlsZC5vbihcImVycm9yXCIsIChlcnIpID0+IHtcbiAgICAgICAgaWYgKHNldHRsZWQpIHJldHVybjtcbiAgICAgICAgc2V0dGxlZCA9IHRydWU7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICAgIGNsZWFudXBBYm9ydD8uKCk7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoYENsYXVkZSBzZXNzaW9uIHNwYXduIGVycm9yOiAke2Vyci5tZXNzYWdlfWApKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBzdGRpbiDsnLzroZwg7J6F66ClIEpTT05MIO2dmOumrOqzoCDri6vripTri6QuXG4gICAgICBjaGlsZC5zdGRpbj8ud3JpdGUoc3RkaW5QYXlsb2FkKTtcbiAgICAgIGNoaWxkLnN0ZGluPy5lbmQoKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbi8vIHVzYWdlIOyerOuFuOy2nCjthYzsiqTtirgg7Y647J2YKS5cbmV4cG9ydCB0eXBlIHsgVG9rZW5Vc2FnZUJyZWFrZG93biB9O1xuIl0s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
|
|
260
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhdWRlLXNlc3Npb24uanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9hbnRocm9waWMvY2xhdWRlLXNlc3Npb24udHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBjbGF1ZGUtc2Vzc2lvbiDigJQgQ2xhdWRlIENMSSDshLjshZggc3Bhd24gKyBRZ3JpZFRocmVhZENvb3JkIOunpO2VkSArIHBlci1zZXNzaW9uIOudvS5cbiAqXG4gKiDrqYDti7DthLQ6IOunpCDtmLjstpwgZnJlc2ggYC0tc2Vzc2lvbi1pZCA8dXVpZD5g66GcIOyLpO2Wie2VnOuLpC4g7J6F66Cl7J2AIOyWtOuMke2EsOqwgCDrp4zrk6AgSlNPTkwg7J2EXG4gKiBzdGRpbiDsnLzroZwg7Z2Y66as6rOgKGAtLWlucHV0LWZvcm1hdCBzdHJlYW0tanNvbmApLCDstpzroKXsnYAg7YyM7ISc66GcIOyymOumrO2VnOuLpC5cbiAqXG4gKiDtlbXsi6wg6rOE7JW9OlxuICogIC0gY29vcmQg64qUIOyehOydmCDsoIDsnqXsnbQg7JWE64uI6528IOq4sOyhtCBRZ3JpZFRocmVhZENvb3Jke3dvcmtlcklkLHRocmVhZElkLGVwb2NoLHN5c3RlbUhhc2h9IOyXkFxuICogICAg66ek7ZWR7ZWc64ukLiB0aHJlYWRJZD3shLjshZggdXVpZCwgZXBvY2g9MCDqs6DsoJUod29ya2VyIHJlc3RhcnQg6rCc64WQIOyXhuydjCksIHdvcmtlcklkPXRva2VuIOq4sOuwmFxuICogICAg7JWI7KCVIO2VqeyEsSwgc3lzdGVtSGFzaD3smpTssq0gc3lzdGVtIO2VtOyLnC4gaXNzdWVDb252Q29udGV4dC9kZWNpZGVDb252Um91dGluZyDqs7wgcm91bmQtdHJpcC5cbiAqICAtIHdpdGhTZXNzaW9uTG9jayDsnYAgZXhwb3J0ZWQgcHJpbWl0aXZlIOuhnCDsnKDsp4DtlZzri6QuIOq4sOuzuCDqsr3roZzsl5DshJzripQg66ekIO2YuOy2nCDsg4ggc2Vzc2lvbi1pZCDrnbxcbiAqICAgIOyCrOyLpOyDgSBuby1jb250ZW50aW9uIOydtOyngOunjCwg7KeB7KCRIO2YuOy2nOyekC/thYzsiqTtirjsnZgg7KeB66Cs7ZmUIOuztOyepeydgCDrs7TsobTtlZzri6QuXG4gKiAgLSBzdHJlYW0tanNvbiDsp4HroKztmZQg7IucIFNESyBlbnZlbG9wZSh1dWlkL3Nlc3Npb25faWQvcGFyZW50X3Rvb2xfdXNlX2lkKSBkZWNvcmF0ZS5cbiAqICAtIHN0cnVjdHVyZWQgb3V0cHV0IOydvCDrlYwg7Lac66ClIO2MjOyEnOyXkCB7IHN0cnVjdHVyZWRPdXRwdXQ6IHRydWUgfSDsoITri6wo7JeG7Jy866m0IHN0cmVhbU9iamVjdCDquajsp5ApLlxuICovXG5cbmltcG9ydCB7IHNwYXduIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgcmFuZG9tVVVJRCB9IGZyb20gXCJub2RlOmNyeXB0b1wiO1xuaW1wb3J0IHsgbWtkaXJTeW5jLCB1bmxpbmtTeW5jLCB3cml0ZUZpbGVTeW5jIH0gZnJvbSBcIm5vZGU6ZnNcIjtcblxuaW1wb3J0IHsgdHlwZSBKc29uVmFsdWUgfSBmcm9tIFwiLi4vLi4vLi4vY29kZXgtcHJvdG9jb2wvc2VyZGVfanNvbi9Kc29uVmFsdWVcIjtcbmltcG9ydCB7IHR5cGUgVG9rZW5Vc2FnZUJyZWFrZG93biB9IGZyb20gXCIuLi8uLi8uLi9jb2RleC1wcm90b2NvbC92Mi9Ub2tlblVzYWdlQnJlYWtkb3duXCI7XG5pbXBvcnQgeyB0eXBlIFVzZXJJbnB1dCB9IGZyb20gXCIuLi8uLi8uLi9jb2RleC1wcm90b2NvbC92Mi9Vc2VySW5wdXRcIjtcbmltcG9ydCB7XG4gIEFOVEhST1BJQ19DTEFVREVfQ1dELFxuICBhbnRocm9waWNDb25maWdEaXIsXG4gIEFOVEhST1BJQ19ERUZBVUxUX0VGRk9SVCxcbiAgQU5USFJPUElDX0RJU0FMTE9XRURfVE9PTFMsXG4gIGFzc2VydFN1cHBvcnRlZE9uZU1pbGxpb25TdWZmaXgsXG4gIGNhbm9uaWNhbEFudGhyb3BpY01vZGVsLFxuICBuZWVkc0NsaTFtU3VmZml4LFxuICBzdXBwb3J0czFNQ29udGV4dCxcbn0gZnJvbSBcIi4vYW50aHJvcGljLWNvbnN0YW50c1wiO1xuaW1wb3J0IHtcbiAgYnVpbGRTdHJlYW1Kc29uSW5wdXQsXG4gIHR5cGUgQ2xhdWRlU3RyZWFtSnNvblN0YXRlLFxuICB0eXBlIENsYXVkZVN0cmVhbUpzb25MaW5lLFxuICB0eXBlIENsYXVkZVN0cmVhbVJlc3VsdCxcbiAgaGFuZGxlU3RyZWFtSnNvbkxpbmUsXG59IGZyb20gXCIuL3N0cmVhbS1qc29uLWFkYXB0ZXJcIjtcblxuLy8g4pSA4pSAIHBlci1zZXNzaW9uIOudvSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLy8gc2Vzc2lvbi1pZCDri6jsnIQg7KeB66Cs7ZmUIHByaW1pdGl2ZS4g6riw67O4IOqyveuhnOyXkOyEnOuKlCDrp6Qg7Zi47LacIOyDiCB1dWlkIOudvCDsgqzsi6Tsg4Egbm8tb3Ag7J207KeA66eMLFxuLy8g6rCZ7J2AIHNlc3Npb24taWQg66W8IOyngeygkSDsk7DripQg7Zi47Lac7J6Q64qUIOyXrOyghO2eiCDsp4HroKztmZQg67O07J6l7J2EIOuwm+uKlOuLpC5cbmNvbnN0IHNlc3Npb25DaGFpbnMgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTx1bmtub3duPj4oKTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdpdGhTZXNzaW9uTG9jazxUPihzZXNzaW9uSWQ6IHN0cmluZywgZm46ICgpID0+IFByb21pc2U8VD4pOiBQcm9taXNlPFQ+IHtcbiAgY29uc3QgcHJldiA9IHNlc3Npb25DaGFpbnMuZ2V0KHNlc3Npb25JZCkgPz8gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIC8vIOydtOyghCB0dXJuIOydmCDshLHtjKjsmYAg66y06rSA7ZWY6rKMIOyngeugrCDssrTsnbjsnYQg7J6H64qU64ukLlxuICBjb25zdCBuZXh0ID0gcHJldi50aGVuKGZuLCBmbik7XG4gIC8vIHRhaWw6IOyEse2MqCDrrLTqtIAgc2V0dGxlIOuQmOuKlCDtlbjrk6QuIOydtOqxuCDrp7Xsl5Ag65GQ6rOgLCBmaW5hbGx5IOyXkOyEnCBcIuyXrOyghO2eiCDrgrTqsIAg64GdXCLsnbwg65WM66eMIOyCreygnC5cbiAgLy8gKHNldCDsp4Htm4QgdW5kZWZpbmVkIOqygOyCrOuhnCDtlZjrqbQg7KCI64yAIOyCreygnCDslYgg64+8IOyEuOyFmCBpZCDqsIAg64iE7IiY65CoIOKAlCB0YWlsIOydvOy5mCDqsoDsgqzroZwg7ZqM7ZS8LilcbiAgY29uc3QgdGFpbCA9IG5leHQudGhlbihcbiAgICAoKSA9PiB7fSxcbiAgICAoKSA9PiB7fSxcbiAgKTtcbiAgc2Vzc2lvbkNoYWlucy5zZXQoc2Vzc2lvbklkLCB0YWlsKTtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgbmV4dDtcbiAgfSBmaW5hbGx5IHtcbiAgICAvLyDqt7gg7IKs7J20IOuLpOuluCB0dXJuIOydtCDssrTsnbjsnYQg7J207Ja067Cb7JWY7Jy866m0IHRhaWwg7J20IOq1kOyytOuPvCDsnojri6Qg4oCUIOq3uOuVjOuKlCDsgq3soJztlZjsp4Ag7JWK64qU64ukLlxuICAgIGlmIChzZXNzaW9uQ2hhaW5zLmdldChzZXNzaW9uSWQpID09PSB0YWlsKSBzZXNzaW9uQ2hhaW5zLmRlbGV0ZShzZXNzaW9uSWQpO1xuICB9XG59XG5cbi8vIOKUgOKUgCBjb29yZCDrp6TtlZEg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbi8vIHRva2VuIOq4sOuwmCDslYjsoJUgd29ya2VySWQg7ZWp7ISxLiBBbnRocm9waWMg7J2AIHdvcmtlciBwb29sIOydtCDsl4bsnLzrr4DroZwgdG9rZW5JZCDrpbwg6re464yA66GcIOyTtOuLpC5cbmV4cG9ydCBmdW5jdGlvbiBtYWtlQW50aHJvcGljV29ya2VySWQodG9rZW5JZDogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIHRva2VuSWQ7XG59XG5cbi8vIOKUgOKUgCBlbnZlbG9wZSBkZWNvcmF0ZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLy8gc3RyZWFtLWpzb24g7J6F66ClIOudvOyduOyXkCBTREsgZW52ZWxvcGUg67aA7LCpIO2bhCDsp4HroKztmZQuIHNlc3Npb24g7IaM7Jyg7J6Q7J24IOyXrOq4sOyEnCDtlZzri6QuXG5leHBvcnQgZnVuY3Rpb24gZGVjb3JhdGVBbmRTZXJpYWxpemUoXG4gIGxpbmVzOiBBcnJheTxDbGF1ZGVTdHJlYW1Kc29uTGluZT4sXG4gIHNlc3Npb25JZDogc3RyaW5nLFxuKTogc3RyaW5nIHtcbiAgcmV0dXJuIChcbiAgICBsaW5lc1xuICAgICAgLm1hcCgobGluZSkgPT5cbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgIC4uLmxpbmUsXG4gICAgICAgICAgc2Vzc2lvbl9pZDogc2Vzc2lvbklkLFxuICAgICAgICAgIHV1aWQ6IHJhbmRvbVVVSUQoKSxcbiAgICAgICAgICBwYXJlbnRfdG9vbF91c2VfaWQ6IG51bGwsXG4gICAgICAgIH0pLFxuICAgICAgKVxuICAgICAgLmpvaW4oXCJcXG5cIikgKyBcIlxcblwiXG4gICk7XG59XG5cbi8vIOKUgOKUgCBzcGF3biArIGNvbnN1bWUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xhdWRlU2Vzc2lvblJlcXVlc3Qge1xuICB0b2tlbklkOiBudW1iZXI7XG4gIHRva2VuOiBzdHJpbmc7IC8vIE9BdXRoIGFjY2VzcyB0b2tlblxuICBtb2RlbDogc3RyaW5nO1xuICBzeXN0ZW0/OiBzdHJpbmc7XG4gIGpzb25TY2hlbWE/OiBzdHJpbmc7IC8vIOyeiOycvOuptCBzdHJ1Y3R1cmVkIG91dHB1dFxuICBlZmZvcnQ/OiBzdHJpbmc7XG4gIHRpbWVvdXRNczogbnVtYmVyO1xuICBjb2xkSGlzdG9yeT86IEFycmF5PEpzb25WYWx1ZT47XG4gIGlucHV0OiBBcnJheTxVc2VySW5wdXQ+O1xuICBhYm9ydFNpZ25hbD86IEFib3J0U2lnbmFsO1xuICBpbmNsdWRlUGFydGlhbE1lc3NhZ2VzPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDbGF1ZGVTZXNzaW9uUmVzdWx0IGV4dGVuZHMgQ2xhdWRlU3RyZWFtUmVzdWx0IHtcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIHdvcmtlcklkOiBudW1iZXI7XG59XG5cbi8vIHBlci10b2tlbiBDTEFVREVfQ09ORklHX0RJUiDrs7TsnqUo6rKp66asKS4g6rK966GcIOq3nOy5meydgCBhbnRocm9waWNDb25maWdEaXIo7Iic7IiYIO2VqOyImCnsnbQg7IaM7JygIOKAlFxuLy8g7Jes6riw7ISgIOq3uCDqsr3roZzsl5Ag67mIIHNldHRpbmdzIOulvCDquZTslYQgY2xhdWRlLW1lbSBob29rIOuTseydhCDssKjri6jtlZzri6QuIChSMTAg6rKp66asKVxuLy8g7J20IHNlZWQg7YyM7J287J2AIGNsYXVkZS1tZW0gaG9vayAvIOyCrOyaqeyekCDshKTsoJUg7Jik7Je8IOywqOuLqOydhCDsnITtlZwg6rKp66asIOqyveqzhOuLpC4g66ekIO2YuOy2nOuniOuLpCDri6Tsi5wg7I2o7IScXG4vLyDsmbjrtoAg67OA7KGwwrfsgq3soJwg7ZuE7JeQ64+EIOuLpOydjCDsi6Ttlonsl5DshJwgc2VsZi1oZWFsaW5nIOuQmOuPhOuhnSDquLDsobQgc2VtYW50aWNzIOulvCDsnKDsp4DtlZzri6QuXG5leHBvcnQgZnVuY3Rpb24gZW5zdXJlQ29uZmlnRGlyKHRva2VuSWQ6IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IGRpciA9IGFudGhyb3BpY0NvbmZpZ0Rpcih0b2tlbklkKTtcbiAgbWtkaXJTeW5jKGRpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIHdyaXRlRmlsZVN5bmMoYCR7ZGlyfS8uY2xhdWRlLmpzb25gLCBcInt9XCIpO1xuICB3cml0ZUZpbGVTeW5jKGAke2Rpcn0vc2V0dGluZ3MuanNvbmAsIFwie31cIik7XG4gIHJldHVybiBkaXI7XG59XG5cbmxldCBjd2RFbnN1cmVkID0gZmFsc2U7XG5mdW5jdGlvbiBlbnN1cmVDd2QoKTogdm9pZCB7XG4gIGlmIChjd2RFbnN1cmVkKSByZXR1cm47XG4gIG1rZGlyU3luYyhgJHtBTlRIUk9QSUNfQ0xBVURFX0NXRH0vLmNsYXVkZWAsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICB3cml0ZUZpbGVTeW5jKGAke0FOVEhST1BJQ19DTEFVREVfQ1dEfS8uY2xhdWRlL3NldHRpbmdzLmpzb25gLCBcInt9XCIpO1xuICBjd2RFbnN1cmVkID0gdHJ1ZTtcbn1cblxuLy8gc3Bhd24gYXJncyDqtazshLEuIOupgO2LsO2EtC/qsqnrpqwvc3RydWN0dXJlZCDrqqjrk5wg67CY7JiBLlxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5T25lTWlsbGlvblN1ZmZpeChtb2RlbDogc3RyaW5nLCBuZWVkc1N1ZmZpeDogYm9vbGVhbik6IHN0cmluZyB7XG4gIGNvbnN0IGJhc2UgPSBjYW5vbmljYWxBbnRocm9waWNNb2RlbChtb2RlbCk7XG4gIHJldHVybiBuZWVkc1N1ZmZpeCA/IGAke2Jhc2V9WzFtXWAgOiBiYXNlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gb25lTWlsbGlvbkVudihzdXBwb3J0ZWQ6IGJvb2xlYW4pOiB7IENMQVVERV9DT0RFX0RJU0FCTEVfMU1fQ09OVEVYVD86IFwiMVwiIH0ge1xuICByZXR1cm4gc3VwcG9ydGVkID8ge30gOiB7IENMQVVERV9DT0RFX0RJU0FCTEVfMU1fQ09OVEVYVDogXCIxXCIgfTtcbn1cblxuLy8gU09OLTQ5NTogc3RydWN0dXJlZCBvdXRwdXQgcmV0cnkg66W8IDEg66GcIOqzoOygle2VnOuLpC4gQ0Mg6rCAIGF0dGVtcHQg66W8IHJlamVjdCDtlZjqs6AgcmV0cnkg7ZWY66m0XG4vLyBge3JlamVjdGVkfXthY2NlcHRlZH1gIOuIhOyggeydtCBBSS1TREsg7J2YIEpTT04ucGFyc2Ug66W8IOq5qOucqOumrOuvgOuhnCwgcmV0cnkg7J6Q7LK066W8IOunieyVhCDqt7gg6rK966Gc66W8XG4vLyDsm5Dsspwg7LCo64uo7ZWc64ukLiBgMGAg7J2AIENDIHF1ZXJ5IGxvb3AoYGNhbGxzVGhpc1F1ZXJ5ID49IG1heFJldHJpZXNgKeqwgCDssqsgYXR0ZW1wdCBlbWl0IOyghOyXkFxuLy8g7Iuk7Yyo7Iuc7YKk66+A66GcKGBlcnJvcl9tYXhfc3RydWN0dXJlZF9vdXRwdXRfcmV0cmllc2ApIOyZuOu2gCDqsJLsnbQgMSDrr7jrp4zsnbTslrTrj4QgMSDroZwg7YG0656o7ZSE7ZWc64ukLlxuZXhwb3J0IGZ1bmN0aW9uIHN0cnVjdHVyZWRPdXRwdXRSZXRyaWVzRW52KHJhdyA9IHByb2Nlc3MuZW52Lk1BWF9TVFJVQ1RVUkVEX09VVFBVVF9SRVRSSUVTKToge1xuICBNQVhfU1RSVUNUVVJFRF9PVVRQVVRfUkVUUklFUzogc3RyaW5nO1xufSB7XG4gIGlmICghcmF3KSByZXR1cm4geyBNQVhfU1RSVUNUVVJFRF9PVVRQVVRfUkVUUklFUzogXCIxXCIgfTtcbiAgY29uc3QgcGFyc2VkID0gTnVtYmVyLnBhcnNlSW50KHJhdywgMTApO1xuICBpZiAoIU51bWJlci5pc0Zpbml0ZShwYXJzZWQpKSByZXR1cm4geyBNQVhfU1RSVUNUVVJFRF9PVVRQVVRfUkVUUklFUzogXCIxXCIgfTtcbiAgcmV0dXJuIHsgTUFYX1NUUlVDVFVSRURfT1VUUFVUX1JFVFJJRVM6IFN0cmluZyhNYXRoLm1heChwYXJzZWQsIDEpKSB9O1xufVxuXG4vLyBMaW51eCDri6jsnbwgYXJndiDsnbjsnpAg7ZWc6rOEKE1BWF9BUkdfU1RSTEVOID0gUEFHRV9TSVpFw5czMiA9IDEyOEtCLCDsu6TrhJAg7ZWY65Oc7L2U65SpIOyDgeyImClcbi8vIOyLnOyKpO2FnCDtlITroaztlITtirjqsIAg7J2066W8IOuEmOycvOuptCBleGVjdmUg6rCAIEUyQklHIOuhnCDqsbDrtoDrkJzri6QuIGRldGkg65OxIOuMgO2YlSDtlITroaztlITtirjripQg7Iuk7LihXG4vLyDtj4nqt6AgMzQzS0LCt+y1nOuMgCA0ODVLQihvcHVzLTQtOCnrnbwg7J287IOB7KCB7Jy866GcIOy0iOqzvO2VnOuLpC4g7ZWc6rOE7J2YIOygiOuwmCg2NEtCKeydhCDsnoTqs4TqsJLsnLzroZwg7J6h7JWEXG4vLyBVVEYtOCDrqYDti7DrsJTsnbTtirjCt+yYiOy4oSDrqrsg7ZWcIOyXrOycoOu2hOq5jOyngCDslYjsoIQg66eI7KeE7J2EIOuRlOuLpC5cbmV4cG9ydCBjb25zdCBTWVNURU1fUFJPTVBUX0FSR1ZfTUFYX0JZVEVTID0gNjQgKiAxMDI0O1xuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRDbGF1ZGVBcmdzKG9wdHM6IHtcbiAgbW9kZWw6IHN0cmluZztcbiAgLy8g7Iuc7Iqk7YWcIO2UhOuhrO2UhO2KuCDsoITri6zsnYAg7YGs6riw66GcIOu2hOq4sO2VnOuLpCjtmLjstpzrtoDqsIAg6rKw7KCVKTpcbiAgLy8gIC0g7J6R7Jy866m0IHN5c3RlbShpbmxpbmUpIOKGkiAtLXN5c3RlbS1wcm9tcHQgPHRleHQ+ICjtjIzsnbwgSS9PIOyXhuydjCwg6riw7KG0IOqyveuhnClcbiAgLy8gIC0g7YGs66m0IHN5c3RlbVByb21wdEZpbGUo6rK966GcKSDihpIgLS1zeXN0ZW0tcHJvbXB0LWZpbGUgPHBhdGg+IChhcmd2IO2VnOqzhCDtmoztlLwpXG4gIC8vIC0tc3lzdGVtLXByb21wdC1maWxlIOydgCAtLXN5c3RlbS1wcm9tcHQg7JmAIOuPmeydvO2VmOqyjCBkZWZhdWx0IOulvCByZXBsYWNlIO2VnOuLpChhcHBlbmQg7JWE64uYIOKAlFxuICAvLyBSNyDqsqnrpqwg67O07KG0LCDsi6TsuKEg7ZmV7J24KS4g65GYIOuLpCDsl4bsnLzrqbQg67mIIC0tc3lzdGVtLXByb21wdChkZWZhdWx0IDIzayDso7zsnoUg67Cp7KeAKS5cbiAgc3lzdGVtPzogc3RyaW5nO1xuICBzeXN0ZW1Qcm9tcHRGaWxlPzogc3RyaW5nO1xuICBlZmZvcnQ/OiBzdHJpbmc7XG4gIGpzb25TY2hlbWE/OiBzdHJpbmc7XG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICBuZWVkc09uZU1pbGxpb25TdWZmaXg/OiBib29sZWFuO1xuICBpbmNsdWRlUGFydGlhbE1lc3NhZ2VzPzogYm9vbGVhbjtcbn0pOiBBcnJheTxzdHJpbmc+IHtcbiAgY29uc3QgdXNlU3RydWN0dXJlZCA9IEJvb2xlYW4ob3B0cy5qc29uU2NoZW1hICYmIG9wdHMuanNvblNjaGVtYS5sZW5ndGggPiAwKTtcbiAgLy8gLS10b29scyBcIlwiIOuhnCDsoITssrQg7LCo64uoLCBzdHJ1Y3R1cmVkKGpzb25TY2hlbWEg7J6I7J2MKSDrqbQgU3RydWN0dXJlZE91dHB1dCDrp4wg7ZeI7JqpLlxuICBjb25zdCB0b29sQXJncyA9IHVzZVN0cnVjdHVyZWRcbiAgICA/IFtcIi0tdG9vbHNcIiwgXCJcIiwgXCItLWFsbG93ZWQtdG9vbHNcIiwgXCJTdHJ1Y3R1cmVkT3V0cHV0XCJdXG4gICAgOiBbXCItLXRvb2xzXCIsIFwiXCJdO1xuXG4gIC8vIOyLnOyKpO2FnCDtlITroaztlITtirg6IO2MjOydvCDqsr3roZzqsIAg7Jik66m0IC0tc3lzdGVtLXByb21wdC1maWxlLCDslYTri4jrqbQgaW5saW5lIC0tc3lzdGVtLXByb21wdC5cbiAgLy8gKO2YuOy2nOu2gOqwgCDtgazquLDroZwg67aE6riw7ZW0IOuRmCDspJEg7ZWY64KY66eMIOyxhOyatOuLpC4g65GYIOuLpCDsl4bsnLzrqbQg67mIIC0tc3lzdGVtLXByb21wdC4pXG4gIGNvbnN0IHN5c3RlbUFyZ3MgPSBvcHRzLnN5c3RlbVByb21wdEZpbGVcbiAgICA/IFtcIi0tc3lzdGVtLXByb21wdC1maWxlXCIsIG9wdHMuc3lzdGVtUHJvbXB0RmlsZV1cbiAgICA6IFtcIi0tc3lzdGVtLXByb21wdFwiLCBvcHRzLnN5c3RlbSA/PyBcIlwiXTtcblxuICBjb25zdCBhcmdzOiBBcnJheTxzdHJpbmc+ID0gW1xuICAgIFwiLXBcIixcbiAgICAuLi50b29sQXJncyxcbiAgICBcIi0tZGlzYWxsb3dlZFRvb2xzXCIsXG4gICAgLi4uQU5USFJPUElDX0RJU0FMTE9XRURfVE9PTFMsXG4gICAgXCItLWlucHV0LWZvcm1hdFwiLFxuICAgIFwic3RyZWFtLWpzb25cIixcbiAgICBcIi0tb3V0cHV0LWZvcm1hdFwiLFxuICAgIFwic3RyZWFtLWpzb25cIixcbiAgICBcIi0tdmVyYm9zZVwiLFxuICAgIC4uLihvcHRzLmluY2x1ZGVQYXJ0aWFsTWVzc2FnZXMgPyBbXCItLWluY2x1ZGUtcGFydGlhbC1tZXNzYWdlc1wiXSA6IFtdKSxcbiAgICBcIi0tcGVybWlzc2lvbi1tb2RlXCIsXG4gICAgXCJieXBhc3NQZXJtaXNzaW9uc1wiLFxuICAgIFwiLS1zZXR0aW5nLXNvdXJjZXNcIixcbiAgICBcInByb2plY3RcIixcbiAgICBcIi0tbW9kZWxcIixcbiAgICBhcHBseU9uZU1pbGxpb25TdWZmaXgob3B0cy5tb2RlbCwgb3B0cy5uZWVkc09uZU1pbGxpb25TdWZmaXggPz8gZmFsc2UpLFxuICAgIC8vIGlubGluZSBbU3lzdGVtXSDquIjsp4Ag4oCUIOygleyLnSDssYTrhJDrp4woUjcpLiDsg53rnrUg7IucIENDIGRlZmF1bHQoMjNrKSDso7zsnoXrkJjrr4DroZwg67CY65Oc7IucIOuqheyLnC5cbiAgICAvLyDtgazquLDsl5Ag65Sw6528IC0tc3lzdGVtLXByb21wdCjsnpHsnYwpIC8gLS1zeXN0ZW0tcHJvbXB0LWZpbGUo7YG8KeuhnCDrtoTquLAoc3lzdGVtQXJncykuXG4gICAgLi4uc3lzdGVtQXJncyxcbiAgICBcIi0tdGhpbmtpbmdcIixcbiAgICBcImRpc2FibGVkXCIsXG4gICAgXCItLWVmZm9ydFwiLFxuICAgIG9wdHMuZWZmb3J0ID8/IEFOVEhST1BJQ19ERUZBVUxUX0VGRk9SVCxcbiAgICBcIi0tZGlzYWJsZS1zbGFzaC1jb21tYW5kc1wiLFxuICAgIFwiLS1zZXNzaW9uLWlkXCIsXG4gICAgb3B0cy5zZXNzaW9uSWQsXG4gIF07XG4gIGlmICh1c2VTdHJ1Y3R1cmVkKSBhcmdzLnB1c2goXCItLWpzb24tc2NoZW1hXCIsIG9wdHMuanNvblNjaGVtYSEpO1xuICByZXR1cm4gYXJncztcbn1cblxuLyoqXG4gKiBDbGF1ZGUg7IS47IWY7J2EIHNwYXduIO2VtCDtlZwgdHVybiDsnYQg7Iuk7ZaJ7ZWc64ukLiBwZXItc2Vzc2lvbiDrnb3snLzroZwg7KeB66Cs7ZmU65Cc64ukLlxuICogQHBhcmFtIG9uRGVsdGEg7KCQ7KeEIO2FjeyKpO2KuCBkZWx0YShzdHJlYW1UZXh0KSDrmJDripQgc3RydWN0dXJlZCDrtoDrtoQgSlNPTihzdHJlYW1PYmplY3QpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuQ2xhdWRlU2Vzc2lvbihcbiAgcmVxOiBDbGF1ZGVTZXNzaW9uUmVxdWVzdCxcbiAgb25EZWx0YTogKHRleHQ6IHN0cmluZykgPT4gdm9pZCxcbik6IFByb21pc2U8Q2xhdWRlU2Vzc2lvblJlc3VsdD4ge1xuICAvLyDsoJXqt5ztmZQg6rec7LmZ7J2AIGNhbm9uaWNhbEFudGhyb3BpY01vZGVsIOydtCDri6jrj4Ug7IaM7JygIOKAlCBkaXNwYXRjaGVyIOqwgCDsnbTrr7ggY2Fub25pY2FsIOydhCDrhJjquLDsp4Drp4wsXG4gIC8vIOyngeygkSDtmLjstpwo7YWM7Iqk7Yq4L+uvuOuemCBjYWxsZXIpIOuMgOu5hCDrsKnslrTsoIHsnLzroZwg7ZWcIOuyiCDrjZQg7Ya16rO87Iuc7YKo64ukKOydtOuvuCBjYW5vbmljYWwg7J2066m0IG5vLW9wKS5cbiAgYXNzZXJ0U3VwcG9ydGVkT25lTWlsbGlvblN1ZmZpeChyZXEubW9kZWwpO1xuICBjb25zdCBtb2RlbCA9IGNhbm9uaWNhbEFudGhyb3BpY01vZGVsKHJlcS5tb2RlbCk7XG4gIGNvbnN0IHN1cHBvcnRzT25lTWlsbGlvbiA9IHN1cHBvcnRzMU1Db250ZXh0KG1vZGVsKTtcbiAgY29uc3QgbmVlZHNPbmVNaWxsaW9uU3VmZml4ID0gbmVlZHNDbGkxbVN1ZmZpeChtb2RlbCk7XG4gIGNvbnN0IHNlc3Npb25JZCA9IHJhbmRvbVVVSUQoKTtcbiAgY29uc3QgdXNlU3RydWN0dXJlZCA9IEJvb2xlYW4ocmVxLmpzb25TY2hlbWEgJiYgcmVxLmpzb25TY2hlbWEubGVuZ3RoID4gMCk7XG4gIGNvbnN0IHdvcmtlcklkID0gbWFrZUFudGhyb3BpY1dvcmtlcklkKHJlcS50b2tlbklkKTtcblxuICByZXR1cm4gd2l0aFNlc3Npb25Mb2NrKHNlc3Npb25JZCwgKCkgPT4ge1xuICAgIGVuc3VyZUN3ZCgpO1xuICAgIGNvbnN0IGNvbmZpZ0RpciA9IGVuc3VyZUNvbmZpZ0RpcihyZXEudG9rZW5JZCk7XG5cbiAgICAvLyDsi5zsiqTthZwg7ZSE66Gs7ZSE7Yq466W8IO2BrOq4sOuhnCDrtoTquLA6IDEyOEtCKGFyZ3Yg7ZWc6rOEKeydmCDsoIjrsJjsnYQg64SY7Jy866m0IO2MjOydvOuhnCDrhJjqsqggRTJCSUcg7ZqM7ZS8LlxuICAgIC8vIOyekeydgCDtlITroaztlITtirjripQg7YyM7J28IEkvTyDsl4bsnbQg6riw7KG0IGlubGluZSDqsr3roZzrpbwg6re464yA66GcIOyTtOuLpCjrjIDrtoDrtoTsnZgg7Zi47LacKS5cbiAgICAvLyDsi6TsoJwg7YyM7J28IOyTsOq4sOuKlCBhYm9ydCDssrTtgawg7J207ZuEKFByb21pc2Ug7JWIKeuhnCDrr7jrpIQsIOydtOuvuCDst6jshozrkJwg7JqU7LKt7JeUIOyTsOyngCDslYrripTri6QuXG4gICAgY29uc3Qgc3lzdGVtID0gcmVxLnN5c3RlbSA/PyBcIlwiO1xuICAgIGNvbnN0IHVzZVN5c3RlbVByb21wdEZpbGUgPSBCdWZmZXIuYnl0ZUxlbmd0aChzeXN0ZW0sIFwidXRmOFwiKSA+IFNZU1RFTV9QUk9NUFRfQVJHVl9NQVhfQllURVM7XG4gICAgY29uc3Qgc3lzdGVtUHJvbXB0RmlsZSA9IHVzZVN5c3RlbVByb21wdEZpbGVcbiAgICAgID8gYCR7Y29uZmlnRGlyfS9zeXN0ZW0tcHJvbXB0LSR7c2Vzc2lvbklkfS50eHRgXG4gICAgICA6IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IGFyZ3MgPSBidWlsZENsYXVkZUFyZ3Moe1xuICAgICAgbW9kZWwsXG4gICAgICBzeXN0ZW06IHVzZVN5c3RlbVByb21wdEZpbGUgPyB1bmRlZmluZWQgOiByZXEuc3lzdGVtLFxuICAgICAgc3lzdGVtUHJvbXB0RmlsZSxcbiAgICAgIGVmZm9ydDogcmVxLmVmZm9ydCxcbiAgICAgIGpzb25TY2hlbWE6IHJlcS5qc29uU2NoZW1hLFxuICAgICAgc2Vzc2lvbklkLFxuICAgICAgbmVlZHNPbmVNaWxsaW9uU3VmZml4LFxuICAgICAgaW5jbHVkZVBhcnRpYWxNZXNzYWdlczogcmVxLmluY2x1ZGVQYXJ0aWFsTWVzc2FnZXMsXG4gICAgfSk7XG5cbiAgICBjb25zdCBpbnB1dExpbmVzID0gYnVpbGRTdHJlYW1Kc29uSW5wdXQoe1xuICAgICAgY29sZEhpc3Rvcnk6IHJlcS5jb2xkSGlzdG9yeSxcbiAgICAgIGlucHV0OiByZXEuaW5wdXQsXG4gICAgfSk7XG4gICAgY29uc3Qgc3RkaW5QYXlsb2FkID0gZGVjb3JhdGVBbmRTZXJpYWxpemUoaW5wdXRMaW5lcywgc2Vzc2lvbklkKTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZTxDbGF1ZGVTZXNzaW9uUmVzdWx0PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBpZiAocmVxLmFib3J0U2lnbmFsPy5hYm9ydGVkKSB7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJhYm9ydGVkXCIpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyDrjIDtmJUg7Iuc7Iqk7YWcIO2UhOuhrO2UhO2KuOuKlCBzcGF3biDsp4HsoITsl5Ag7YyM7J2866GcIOq4sOuhnShhcmd2IEUyQklHIO2ajO2UvCkuIOyiheujjCDsi5wg7KCV66as7ZWc64ukLlxuICAgICAgaWYgKHN5c3RlbVByb21wdEZpbGUpIHdyaXRlRmlsZVN5bmMoc3lzdGVtUHJvbXB0RmlsZSwgc3lzdGVtKTtcblxuICAgICAgY29uc3QgY2hpbGQgPSBzcGF3bihcImNsYXVkZVwiLCBhcmdzLCB7XG4gICAgICAgIC8vIHN0ZGVyciDrj4Qg7Lqh7LKYOiBpbnZhbGlkIE9BdXRoIC8g7J6Y66q765CcIO2UjOuemOq3uCAvIENMSSDqsoDspp0g7Iuk7Yyo6rCAXG4gICAgICAgIC8vIFwiY2xvc2VkIHdpdGhvdXQgcmVzdWx0XCIg66GcIOutieqwnOyngOyngCDslYrqsowgY2xvc2UvZXJyb3Ig7JeQIHN0ZGVyciDrpbwg7Iuk7Ja0IOuztOuCuOuLpC5cbiAgICAgICAgc3RkaW86IFtcInBpcGVcIiwgXCJwaXBlXCIsIFwicGlwZVwiXSxcbiAgICAgICAgY3dkOiBBTlRIUk9QSUNfQ0xBVURFX0NXRCxcbiAgICAgICAgZW52OiB7XG4gICAgICAgICAgUEFUSDogcHJvY2Vzcy5lbnYuUEFUSCxcbiAgICAgICAgICBUTVBESVI6IHByb2Nlc3MuZW52LlRNUERJUixcbiAgICAgICAgICBDTEFVREVfQ09ERV9PQVVUSF9UT0tFTjogcmVxLnRva2VuLFxuICAgICAgICAgIENMQVVERV9DT05GSUdfRElSOiBjb25maWdEaXIsXG4gICAgICAgICAgQ0xBVURFX0NPREVfRElTQUJMRV9BVVRPX01FTU9SWTogXCIxXCIsXG4gICAgICAgICAgQ0xBVURFX0NPREVfRElTQUJMRV9BREFQVElWRV9USElOS0lORzogXCIxXCIsXG4gICAgICAgICAgLi4ub25lTWlsbGlvbkVudihzdXBwb3J0c09uZU1pbGxpb24pLFxuICAgICAgICAgIENMQVVERV9DT0RFX0RJU0FCTEVfQ0xBVURFX01EUzogXCIxXCIsXG4gICAgICAgICAgQ0xBVURFX0NPREVfRElTQUJMRV9URVJNSU5BTF9USVRMRTogXCIxXCIsXG4gICAgICAgICAgQ0xBVURFX0NPREVfRElTQUJMRV9CVU5ETEVEX1NLSUxMUzogXCIxXCIsXG4gICAgICAgICAgQ0xBVURFX0NPREVfRElTQUJMRV9XT1JLRkxPV1M6IFwiMVwiLFxuICAgICAgICAgIENMQVVERV9DT0RFX0FUVFJJQlVUSU9OX0hFQURFUjogXCIwXCIsXG4gICAgICAgICAgTUFYX1RISU5LSU5HX1RPS0VOUzogXCIwXCIsXG4gICAgICAgICAgLy8gc3RydWN0dXJlZCBvdXRwdXQg7J28IOuVjOunjCByZXRyeSDrpbwg6rOg7KCV7ZWc64ukKFNPTi00OTUpLiB0ZXh0IOuqqOuTnOuKlCDsmIHtlqUg7JeG7J2MLlxuICAgICAgICAgIC4uLih1c2VTdHJ1Y3R1cmVkID8gc3RydWN0dXJlZE91dHB1dFJldHJpZXNFbnYoKSA6IHt9KSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBsZXQgc2V0dGxlZCA9IGZhbHNlO1xuICAgICAgbGV0IGJ1ZmZlciA9IFwiXCI7XG4gICAgICBjb25zdCBzdHJlYW1TdGF0ZTogQ2xhdWRlU3RyZWFtSnNvblN0YXRlID0ge307XG4gICAgICAvLyBib3VuZGVkIHN0ZGVyciDrsoTtjbwo7LWc6re8IH40S0Lrp4wg7Jyg7KeAIOKAlCDrrLTtlZwg64iE7KCBIOuwqeyngCkuXG4gICAgICBsZXQgc3RkZXJyQnVmID0gXCJcIjtcbiAgICAgIGNvbnN0IFNUREVSUl9DQVAgPSA0MDk2O1xuICAgICAgY2hpbGQuc3RkZXJyPy5vbihcImRhdGFcIiwgKGQ6IEJ1ZmZlcikgPT4ge1xuICAgICAgICBzdGRlcnJCdWYgPSAoc3RkZXJyQnVmICsgZC50b1N0cmluZygpKS5zbGljZSgtU1RERVJSX0NBUCk7XG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHN0ZGVyclN1ZmZpeCA9ICgpID0+IChzdGRlcnJCdWYudHJpbSgpID8gYCDigJQgc3RkZXJyOiAke3N0ZGVyckJ1Zi50cmltKCl9YCA6IFwiXCIpO1xuICAgICAgLy8gc3Bhd24g7IucIOyTtCDsnoTsi5wg7Iuc7Iqk7YWcIO2UhOuhrO2UhO2KuCDtjIzsnbwg7KCV66asKO2VnCDrsojrp4wpLiDrqqjrk6Ag7KKF66OMIOqyveuhnOyXkOyEnCDtmLjstpztlZzri6QuXG4gICAgICAvLyDriITrnb3rj7zrj4Qg64uk7J2MIGVuc3VyZUNvbmZpZ0RpciDqsIAg65SU66CJ7Yag66as66W8IOyerOyCrOyaqe2VoCDrv5DsnbTsp4Drp4wsIHNlc3Npb25JZCDrs4Qg7YyM7J287J206528XG4gICAgICAvLyDsjJPsnbTrqbQg65SU7Iqk7YGs6rCAIOywqOuvgOuhnCBzZXR0bGUg7IucIOymieyLnCDsp4DsmrTri6QuXG4gICAgICBjb25zdCBjbGVhbnVwU3Bhd25GaWxlcyA9ICgpID0+IHtcbiAgICAgICAgaWYgKCFzeXN0ZW1Qcm9tcHRGaWxlKSByZXR1cm47XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdW5saW5rU3luYyhzeXN0ZW1Qcm9tcHRGaWxlKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgLy8g7J2066+4IOyXhuqxsOuCmCDqtoztlZwg66y47KCc66m0IOustOyLnCDigJQg7KCV66as64qUIGJlc3QtZWZmb3J0LlxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgbGV0IGNsZWFudXBBYm9ydDogKCgpID0+IHZvaWQpIHwgdW5kZWZpbmVkO1xuICAgICAgY29uc3QgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgaWYgKHNldHRsZWQpIHJldHVybjtcbiAgICAgICAgc2V0dGxlZCA9IHRydWU7XG4gICAgICAgIGNsZWFudXBBYm9ydD8uKCk7XG4gICAgICAgIGNsZWFudXBTcGF3bkZpbGVzKCk7XG4gICAgICAgIGNoaWxkLmtpbGwoKTtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgQ2xhdWRlIHNlc3Npb24gdGltZW91dCBhZnRlciAke3JlcS50aW1lb3V0TXMgLyAxMDAwfXNgKSk7XG4gICAgICB9LCByZXEudGltZW91dE1zKTtcblxuICAgICAgY29uc3QgZmluaXNoID0gKHJlc3VsdDogQ2xhdWRlU3RyZWFtUmVzdWx0KSA9PiB7XG4gICAgICAgIGlmIChzZXR0bGVkKSByZXR1cm47XG4gICAgICAgIHNldHRsZWQgPSB0cnVlO1xuICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgICBjbGVhbnVwQWJvcnQ/LigpO1xuICAgICAgICBjbGVhbnVwU3Bhd25GaWxlcygpO1xuICAgICAgICByZXNvbHZlKHsgLi4ucmVzdWx0LCBzZXNzaW9uSWQsIHdvcmtlcklkIH0pO1xuICAgICAgfTtcblxuICAgICAgY29uc3Qgb25BYm9ydCA9ICgpID0+IHtcbiAgICAgICAgaWYgKHNldHRsZWQpIHJldHVybjtcbiAgICAgICAgc2V0dGxlZCA9IHRydWU7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICAgIGNsZWFudXBBYm9ydD8uKCk7XG4gICAgICAgIGNsZWFudXBTcGF3bkZpbGVzKCk7XG4gICAgICAgIGNoaWxkLmtpbGwoKTtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihcImFib3J0ZWRcIikpO1xuICAgICAgfTtcbiAgICAgIGNsZWFudXBBYm9ydCA9ICgpID0+IHJlcS5hYm9ydFNpZ25hbD8ucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIG9uQWJvcnQpO1xuICAgICAgcmVxLmFib3J0U2lnbmFsPy5hZGRFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgb25BYm9ydCwgeyBvbmNlOiB0cnVlIH0pO1xuXG4gICAgICBjaGlsZC5zdGRvdXQ/Lm9uKFwiZGF0YVwiLCAoZDogQnVmZmVyKSA9PiB7XG4gICAgICAgIGlmIChzZXR0bGVkKSByZXR1cm47XG4gICAgICAgIGJ1ZmZlciArPSBkLnRvU3RyaW5nKCk7XG4gICAgICAgIGNvbnN0IGxpbmVzID0gYnVmZmVyLnNwbGl0KFwiXFxuXCIpO1xuICAgICAgICBidWZmZXIgPSBsaW5lcy5wb3AoKSA/PyBcIlwiO1xuICAgICAgICBmb3IgKGNvbnN0IGxpbmUgb2YgbGluZXMpIHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBoYW5kbGVTdHJlYW1Kc29uTGluZShsaW5lLCBvbkRlbHRhLCB7XG4gICAgICAgICAgICBzdHJ1Y3R1cmVkT3V0cHV0OiB1c2VTdHJ1Y3R1cmVkLFxuICAgICAgICAgICAgc3RhdGU6IHN0cmVhbVN0YXRlLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgIGZpbmlzaChyZXN1bHQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGNoaWxkLm9uKFwiY2xvc2VcIiwgKCkgPT4ge1xuICAgICAgICBpZiAoc2V0dGxlZCkgcmV0dXJuO1xuICAgICAgICBzZXR0bGVkID0gdHJ1ZTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgY2xlYW51cEFib3J0Py4oKTtcbiAgICAgICAgY2xlYW51cFNwYXduRmlsZXMoKTtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgQ2xhdWRlIHNlc3Npb24gY2xvc2VkIHdpdGhvdXQgcmVzdWx0JHtzdGRlcnJTdWZmaXgoKX1gKSk7XG4gICAgICB9KTtcbiAgICAgIGNoaWxkLm9uKFwiZXJyb3JcIiwgKGVycikgPT4ge1xuICAgICAgICBpZiAoc2V0dGxlZCkgcmV0dXJuO1xuICAgICAgICBzZXR0bGVkID0gdHJ1ZTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgY2xlYW51cEFib3J0Py4oKTtcbiAgICAgICAgY2xlYW51cFNwYXduRmlsZXMoKTtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgQ2xhdWRlIHNlc3Npb24gc3Bhd24gZXJyb3I6ICR7ZXJyLm1lc3NhZ2V9YCkpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIHN0ZGluIOycvOuhnCDsnoXroKUgSlNPTkwg7Z2Y66as6rOgIOuLq+uKlOuLpC5cbiAgICAgIGNoaWxkLnN0ZGluPy53cml0ZShzdGRpblBheWxvYWQpO1xuICAgICAgY2hpbGQuc3RkaW4/LmVuZCgpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuLy8gdXNhZ2Ug7J6s64W47LacKO2FjOyKpO2KuCDtjrjsnZgpLlxuZXhwb3J0IHR5cGUgeyBUb2tlblVzYWdlQnJlYWtkb3duIH07XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUE2Q0EsTUFBTSxnQ0FBZ0IsSUFBSSxLQUErQjtBQUV6RCxlQUFzQixnQkFBbUIsV0FBbUIsSUFBa0M7Q0FHNUYsTUFBTSxRQUZPLGNBQWMsSUFBSSxVQUFVLElBQUksUUFBUSxTQUFTLEVBRTVDLEtBQUssSUFBSSxHQUFHO0NBRzlCLE1BQU0sT0FBTyxLQUFLLFdBQ1YsVUFDQSxHQUNQO0FBQ0QsZUFBYyxJQUFJLFdBQVcsS0FBSztBQUNsQyxLQUFJO0FBQ0YsU0FBTyxNQUFNO1dBQ0w7QUFFUixNQUFJLGNBQWMsSUFBSSxVQUFVLEtBQUssS0FBTSxlQUFjLE9BQU8sVUFBVTs7O0FBTzlFLFNBQWdCLHNCQUFzQixTQUF5QjtBQUM3RCxRQUFPOztBQU1ULFNBQWdCLHFCQUNkLE9BQ0EsV0FDUTtBQUNSLFFBQ0UsTUFDRyxLQUFLLFNBQ0osS0FBSyxVQUFVO0VBQ2IsR0FBRztFQUNILFlBQVk7RUFDWixNQUFNLFlBQVk7RUFDbEIsb0JBQW9CO0VBQ3JCLENBQUMsQ0FDSCxDQUNBLEtBQUssS0FBSyxHQUFHOztBQTZCcEIsU0FBZ0IsZ0JBQWdCLFNBQXlCO0NBQ3ZELE1BQU0sTUFBTSxtQkFBbUIs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
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
oneMillionEnv,
|
|
13
13
|
runClaudeSession,
|
|
14
14
|
structuredOutputRetriesEnv,
|
|
15
|
+
SYSTEM_PROMPT_ARGV_MAX_BYTES,
|
|
15
16
|
withSessionLock,
|
|
16
17
|
} from "./claude-session";
|
|
17
18
|
import { buildStreamJsonInput } from "./stream-json-adapter";
|
|
@@ -238,6 +239,45 @@ describe("buildClaudeArgs (멀티턴/격리/structured)", () => {
|
|
|
238
239
|
expect(args).toContain("--system-prompt");
|
|
239
240
|
expect(args[args.indexOf("--system-prompt") + 1]).toBe("you are X");
|
|
240
241
|
});
|
|
242
|
+
|
|
243
|
+
// E2BIG 회피: 대형 시스템 프롬프트는 파일 경로로 넘겨 Linux argv 한계(128KB)를 피한다.
|
|
244
|
+
it("systemPromptFile 이 오면 --system-prompt-file 을 쓰고 inline --system-prompt 는 안 쓴다", () => {
|
|
245
|
+
const args = buildClaudeArgs({
|
|
246
|
+
model: "m",
|
|
247
|
+
systemPromptFile: "/cfg/7/system-prompt-u.txt",
|
|
248
|
+
sessionId: "u",
|
|
249
|
+
});
|
|
250
|
+
expect(args).toContain("--system-prompt-file");
|
|
251
|
+
expect(args[args.indexOf("--system-prompt-file") + 1]).toBe("/cfg/7/system-prompt-u.txt");
|
|
252
|
+
expect(args).not.toContain("--system-prompt");
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("systemPromptFile 이 inline system 보다 우선한다 (둘 다 와도 file 경로만)", () => {
|
|
256
|
+
const args = buildClaudeArgs({
|
|
257
|
+
model: "m",
|
|
258
|
+
system: "ignored inline",
|
|
259
|
+
systemPromptFile: "/cfg/7/sp.txt",
|
|
260
|
+
sessionId: "u",
|
|
261
|
+
});
|
|
262
|
+
expect(args).toContain("--system-prompt-file");
|
|
263
|
+
expect(args).not.toContain("--system-prompt");
|
|
264
|
+
expect(args).not.toContain("ignored inline");
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it("임계값(64KB)을 넘는 시스템 프롬프트가 argv 에 통째로 들어가지 않는다 (E2BIG 회귀 방지)", () => {
|
|
268
|
+
const huge = "x".repeat(SYSTEM_PROMPT_ARGV_MAX_BYTES + 1);
|
|
269
|
+
// 실제 호출부(runClaudeSession)는 huge 를 파일로 빼고 systemPromptFile 만 넘긴다.
|
|
270
|
+
const args = buildClaudeArgs({
|
|
271
|
+
model: "m",
|
|
272
|
+
systemPromptFile: "/cfg/7/sp.txt",
|
|
273
|
+
sessionId: "u",
|
|
274
|
+
});
|
|
275
|
+
// 어떤 단일 인자도 임계값을 넘지 않아야 한다(=거대 프롬프트가 argv 에 없음).
|
|
276
|
+
for (const a of args) {
|
|
277
|
+
expect(Buffer.byteLength(a, "utf8")).toBeLessThanOrEqual(SYSTEM_PROMPT_ARGV_MAX_BYTES);
|
|
278
|
+
}
|
|
279
|
+
expect(args).not.toContain(huge);
|
|
280
|
+
});
|
|
241
281
|
});
|
|
242
282
|
|
|
243
283
|
describe("decorateAndSerialize (envelope, U2 P1-#3 위임분)", () => {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import { spawn } from "node:child_process";
|
|
18
18
|
import { randomUUID } from "node:crypto";
|
|
19
|
-
import { mkdirSync, writeFileSync } from "node:fs";
|
|
19
|
+
import { mkdirSync, unlinkSync, writeFileSync } from "node:fs";
|
|
20
20
|
|
|
21
21
|
import { type JsonValue } from "../../../codex-protocol/serde_json/JsonValue";
|
|
22
22
|
import { type TokenUsageBreakdown } from "../../../codex-protocol/v2/TokenUsageBreakdown";
|
|
@@ -156,9 +156,21 @@ export function structuredOutputRetriesEnv(raw = process.env.MAX_STRUCTURED_OUTP
|
|
|
156
156
|
return { MAX_STRUCTURED_OUTPUT_RETRIES: String(Math.max(parsed, 1)) };
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
// Linux 단일 argv 인자 한계(MAX_ARG_STRLEN = PAGE_SIZE×32 = 128KB, 커널 하드코딩 상수)
|
|
160
|
+
// 시스템 프롬프트가 이를 넘으면 execve 가 E2BIG 로 거부된다. deti 등 대형 프롬프트는 실측
|
|
161
|
+
// 평균 343KB·최대 485KB(opus-4-8)라 일상적으로 초과한다. 한계의 절반(64KB)을 임계값으로 잡아
|
|
162
|
+
// UTF-8 멀티바이트·예측 못 한 여유분까지 안전 마진을 둔다.
|
|
163
|
+
export const SYSTEM_PROMPT_ARGV_MAX_BYTES = 64 * 1024;
|
|
164
|
+
|
|
159
165
|
export function buildClaudeArgs(opts: {
|
|
160
166
|
model: string;
|
|
167
|
+
// 시스템 프롬프트 전달은 크기로 분기한다(호출부가 결정):
|
|
168
|
+
// - 작으면 system(inline) → --system-prompt <text> (파일 I/O 없음, 기존 경로)
|
|
169
|
+
// - 크면 systemPromptFile(경로) → --system-prompt-file <path> (argv 한계 회피)
|
|
170
|
+
// --system-prompt-file 은 --system-prompt 와 동일하게 default 를 replace 한다(append 아님 —
|
|
171
|
+
// R7 격리 보존, 실측 확인). 둘 다 없으면 빈 --system-prompt(default 23k 주입 방지).
|
|
161
172
|
system?: string;
|
|
173
|
+
systemPromptFile?: string;
|
|
162
174
|
effort?: string;
|
|
163
175
|
jsonSchema?: string;
|
|
164
176
|
sessionId: string;
|
|
@@ -171,6 +183,12 @@ export function buildClaudeArgs(opts: {
|
|
|
171
183
|
? ["--tools", "", "--allowed-tools", "StructuredOutput"]
|
|
172
184
|
: ["--tools", ""];
|
|
173
185
|
|
|
186
|
+
// 시스템 프롬프트: 파일 경로가 오면 --system-prompt-file, 아니면 inline --system-prompt.
|
|
187
|
+
// (호출부가 크기로 분기해 둘 중 하나만 채운다. 둘 다 없으면 빈 --system-prompt.)
|
|
188
|
+
const systemArgs = opts.systemPromptFile
|
|
189
|
+
? ["--system-prompt-file", opts.systemPromptFile]
|
|
190
|
+
: ["--system-prompt", opts.system ?? ""];
|
|
191
|
+
|
|
174
192
|
const args: Array<string> = [
|
|
175
193
|
"-p",
|
|
176
194
|
...toolArgs,
|
|
@@ -189,8 +207,8 @@ export function buildClaudeArgs(opts: {
|
|
|
189
207
|
"--model",
|
|
190
208
|
applyOneMillionSuffix(opts.model, opts.needsOneMillionSuffix ?? false),
|
|
191
209
|
// inline [System] 금지 — 정식 채널만(R7). 생략 시 CC default(23k) 주입되므로 반드시 명시.
|
|
192
|
-
|
|
193
|
-
|
|
210
|
+
// 크기에 따라 --system-prompt(작음) / --system-prompt-file(큼)로 분기(systemArgs).
|
|
211
|
+
...systemArgs,
|
|
194
212
|
"--thinking",
|
|
195
213
|
"disabled",
|
|
196
214
|
"--effort",
|
|
@@ -225,9 +243,19 @@ export function runClaudeSession(
|
|
|
225
243
|
ensureCwd();
|
|
226
244
|
const configDir = ensureConfigDir(req.tokenId);
|
|
227
245
|
|
|
246
|
+
// 시스템 프롬프트를 크기로 분기: 128KB(argv 한계)의 절반을 넘으면 파일로 넘겨 E2BIG 회피.
|
|
247
|
+
// 작은 프롬프트는 파일 I/O 없이 기존 inline 경로를 그대로 쓴다(대부분의 호출).
|
|
248
|
+
// 실제 파일 쓰기는 abort 체크 이후(Promise 안)로 미뤄, 이미 취소된 요청엔 쓰지 않는다.
|
|
249
|
+
const system = req.system ?? "";
|
|
250
|
+
const useSystemPromptFile = Buffer.byteLength(system, "utf8") > SYSTEM_PROMPT_ARGV_MAX_BYTES;
|
|
251
|
+
const systemPromptFile = useSystemPromptFile
|
|
252
|
+
? `${configDir}/system-prompt-${sessionId}.txt`
|
|
253
|
+
: undefined;
|
|
254
|
+
|
|
228
255
|
const args = buildClaudeArgs({
|
|
229
256
|
model,
|
|
230
|
-
system: req.system,
|
|
257
|
+
system: useSystemPromptFile ? undefined : req.system,
|
|
258
|
+
systemPromptFile,
|
|
231
259
|
effort: req.effort,
|
|
232
260
|
jsonSchema: req.jsonSchema,
|
|
233
261
|
sessionId,
|
|
@@ -247,6 +275,9 @@ export function runClaudeSession(
|
|
|
247
275
|
return;
|
|
248
276
|
}
|
|
249
277
|
|
|
278
|
+
// 대형 시스템 프롬프트는 spawn 직전에 파일로 기록(argv E2BIG 회피). 종료 시 정리한다.
|
|
279
|
+
if (systemPromptFile) writeFileSync(systemPromptFile, system);
|
|
280
|
+
|
|
250
281
|
const child = spawn("claude", args, {
|
|
251
282
|
// stderr 도 캡처: invalid OAuth / 잘못된 플래그 / CLI 검증 실패가
|
|
252
283
|
// "closed without result" 로 뭉개지지 않게 close/error 에 stderr 를 실어 보낸다.
|
|
@@ -281,11 +312,23 @@ export function runClaudeSession(
|
|
|
281
312
|
stderrBuf = (stderrBuf + d.toString()).slice(-STDERR_CAP);
|
|
282
313
|
});
|
|
283
314
|
const stderrSuffix = () => (stderrBuf.trim() ? ` — stderr: ${stderrBuf.trim()}` : "");
|
|
315
|
+
// spawn 시 쓴 임시 시스템 프롬프트 파일 정리(한 번만). 모든 종료 경로에서 호출한다.
|
|
316
|
+
// 누락돼도 다음 ensureConfigDir 가 디렉토리를 재사용할 뿐이지만, sessionId 별 파일이라
|
|
317
|
+
// 쌓이면 디스크가 차므로 settle 시 즉시 지운다.
|
|
318
|
+
const cleanupSpawnFiles = () => {
|
|
319
|
+
if (!systemPromptFile) return;
|
|
320
|
+
try {
|
|
321
|
+
unlinkSync(systemPromptFile);
|
|
322
|
+
} catch {
|
|
323
|
+
// 이미 없거나 권한 문제면 무시 — 정리는 best-effort.
|
|
324
|
+
}
|
|
325
|
+
};
|
|
284
326
|
let cleanupAbort: (() => void) | undefined;
|
|
285
327
|
const timer = setTimeout(() => {
|
|
286
328
|
if (settled) return;
|
|
287
329
|
settled = true;
|
|
288
330
|
cleanupAbort?.();
|
|
331
|
+
cleanupSpawnFiles();
|
|
289
332
|
child.kill();
|
|
290
333
|
reject(new Error(`Claude session timeout after ${req.timeoutMs / 1000}s`));
|
|
291
334
|
}, req.timeoutMs);
|
|
@@ -295,6 +338,7 @@ export function runClaudeSession(
|
|
|
295
338
|
settled = true;
|
|
296
339
|
clearTimeout(timer);
|
|
297
340
|
cleanupAbort?.();
|
|
341
|
+
cleanupSpawnFiles();
|
|
298
342
|
resolve({ ...result, sessionId, workerId });
|
|
299
343
|
};
|
|
300
344
|
|
|
@@ -303,6 +347,7 @@ export function runClaudeSession(
|
|
|
303
347
|
settled = true;
|
|
304
348
|
clearTimeout(timer);
|
|
305
349
|
cleanupAbort?.();
|
|
350
|
+
cleanupSpawnFiles();
|
|
306
351
|
child.kill();
|
|
307
352
|
reject(new Error("aborted"));
|
|
308
353
|
};
|
|
@@ -331,6 +376,7 @@ export function runClaudeSession(
|
|
|
331
376
|
settled = true;
|
|
332
377
|
clearTimeout(timer);
|
|
333
378
|
cleanupAbort?.();
|
|
379
|
+
cleanupSpawnFiles();
|
|
334
380
|
reject(new Error(`Claude session closed without result${stderrSuffix()}`));
|
|
335
381
|
});
|
|
336
382
|
child.on("error", (err) => {
|
|
@@ -338,6 +384,7 @@ export function runClaudeSession(
|
|
|
338
384
|
settled = true;
|
|
339
385
|
clearTimeout(timer);
|
|
340
386
|
cleanupAbort?.();
|
|
387
|
+
cleanupSpawnFiles();
|
|
341
388
|
reject(new Error(`Claude session spawn error: ${err.message}`));
|
|
342
389
|
});
|
|
343
390
|
|