@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
- ...useStructured ? [
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
- "--system-prompt",
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
- "--system-prompt",
193
- opts.system ?? "",
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cartanova/qgrid-cli",
3
- "version": "2.3.4",
3
+ "version": "2.3.5",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/cartanova-ai/qgrid"