@philippwassibauer/agentlens 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/.next/BUILD_ID +1 -0
  2. package/.next/app-build-manifest.json +44 -0
  3. package/.next/app-path-routes-manifest.json +1 -0
  4. package/.next/build-manifest.json +32 -0
  5. package/.next/export-marker.json +1 -0
  6. package/.next/images-manifest.json +1 -0
  7. package/.next/next-minimal-server.js.nft.json +1 -0
  8. package/.next/next-server.js.nft.json +1 -0
  9. package/.next/package.json +1 -0
  10. package/.next/prerender-manifest.json +1 -0
  11. package/.next/react-loadable-manifest.json +1 -0
  12. package/.next/required-server-files.json +1 -0
  13. package/.next/routes-manifest.json +1 -0
  14. package/.next/server/app/_not-found/page.js +1 -0
  15. package/.next/server/app/_not-found/page.js.nft.json +1 -0
  16. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  17. package/.next/server/app/_not-found.html +1 -0
  18. package/.next/server/app/_not-found.meta +6 -0
  19. package/.next/server/app/_not-found.rsc +9 -0
  20. package/.next/server/app/api/check-prs/route.js +86 -0
  21. package/.next/server/app/api/check-prs/route.js.nft.json +1 -0
  22. package/.next/server/app/api/events/route.js +86 -0
  23. package/.next/server/app/api/events/route.js.nft.json +1 -0
  24. package/.next/server/app/api/sessions/[id]/route.js +86 -0
  25. package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -0
  26. package/.next/server/app/api/sessions/route.js +86 -0
  27. package/.next/server/app/api/sessions/route.js.nft.json +1 -0
  28. package/.next/server/app/api/stats/route.js +86 -0
  29. package/.next/server/app/api/stats/route.js.nft.json +1 -0
  30. package/.next/server/app/page.js +1 -0
  31. package/.next/server/app/page.js.nft.json +1 -0
  32. package/.next/server/app/page_client-reference-manifest.js +1 -0
  33. package/.next/server/app/sessions/[id]/page.js +1 -0
  34. package/.next/server/app/sessions/[id]/page.js.nft.json +1 -0
  35. package/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -0
  36. package/.next/server/app/sessions/page.js +1 -0
  37. package/.next/server/app/sessions/page.js.nft.json +1 -0
  38. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -0
  39. package/.next/server/app-paths-manifest.json +11 -0
  40. package/.next/server/chunks/111.js +1 -0
  41. package/.next/server/chunks/19.js +1 -0
  42. package/.next/server/chunks/218.js +1 -0
  43. package/.next/server/chunks/267.js +13 -0
  44. package/.next/server/chunks/449.js +12 -0
  45. package/.next/server/chunks/522.js +2 -0
  46. package/.next/server/chunks/590.js +6 -0
  47. package/.next/server/chunks/619.js +2 -0
  48. package/.next/server/chunks/780.js +1 -0
  49. package/.next/server/chunks/787.js +1 -0
  50. package/.next/server/chunks/938.js +1 -0
  51. package/.next/server/chunks/95.js +1 -0
  52. package/.next/server/chunks/98.js +86 -0
  53. package/.next/server/chunks/font-manifest.json +1 -0
  54. package/.next/server/font-manifest.json +1 -0
  55. package/.next/server/functions-config-manifest.json +1 -0
  56. package/.next/server/interception-route-rewrite-manifest.js +1 -0
  57. package/.next/server/middleware-build-manifest.js +1 -0
  58. package/.next/server/middleware-manifest.json +6 -0
  59. package/.next/server/middleware-react-loadable-manifest.js +1 -0
  60. package/.next/server/next-font-manifest.js +1 -0
  61. package/.next/server/next-font-manifest.json +1 -0
  62. package/.next/server/pages/404.html +1 -0
  63. package/.next/server/pages/500.html +1 -0
  64. package/.next/server/pages/_app.js +1 -0
  65. package/.next/server/pages/_app.js.nft.json +1 -0
  66. package/.next/server/pages/_document.js +1 -0
  67. package/.next/server/pages/_document.js.nft.json +1 -0
  68. package/.next/server/pages/_error.js +1 -0
  69. package/.next/server/pages/_error.js.nft.json +1 -0
  70. package/.next/server/pages-manifest.json +1 -0
  71. package/.next/server/server-reference-manifest.js +1 -0
  72. package/.next/server/server-reference-manifest.json +1 -0
  73. package/.next/server/webpack-runtime.js +1 -0
  74. package/.next/static/VcvMciURiwijLrVt2jf_P/_buildManifest.js +1 -0
  75. package/.next/static/VcvMciURiwijLrVt2jf_P/_ssgManifest.js +1 -0
  76. package/.next/static/chunks/2200cc46-96120a9be9a790d7.js +1 -0
  77. package/.next/static/chunks/838-ee1ac53cffa08ff2.js +1 -0
  78. package/.next/static/chunks/919-13111e16ca5aad12.js +1 -0
  79. package/.next/static/chunks/945-08d88d38313883d1.js +2 -0
  80. package/.next/static/chunks/app/_not-found/page-52828565ce3bf1a5.js +1 -0
  81. package/.next/static/chunks/app/layout-d3c17bc5a9ba9afe.js +1 -0
  82. package/.next/static/chunks/app/page-f02e37b80f020816.js +1 -0
  83. package/.next/static/chunks/app/sessions/[id]/page-9cd58c2b3cbdb58c.js +1 -0
  84. package/.next/static/chunks/app/sessions/page-381d2eb994edfbe5.js +1 -0
  85. package/.next/static/chunks/framework-6e06c675866dc992.js +1 -0
  86. package/.next/static/chunks/main-921b2ae56ade90f2.js +1 -0
  87. package/.next/static/chunks/main-app-f7575201e7f66c72.js +1 -0
  88. package/.next/static/chunks/pages/_app-0c3037849002a4aa.js +1 -0
  89. package/.next/static/chunks/pages/_error-a647cd2c75dc4dc7.js +1 -0
  90. package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  91. package/.next/static/chunks/webpack-5a21843c4f0469c6.js +1 -0
  92. package/.next/static/css/e0ed3c3bd07a0247.css +3 -0
  93. package/.next/static/media/011e180705008d6f-s.woff2 +0 -0
  94. package/.next/static/media/0aa834ed78bf6d07-s.woff2 +0 -0
  95. package/.next/static/media/20535187d867b7b9-s.woff2 +0 -0
  96. package/.next/static/media/37786be940ec402b-s.p.woff2 +0 -0
  97. package/.next/static/media/46e154b2fcbd6033-s.woff2 +0 -0
  98. package/.next/static/media/5356a6a4f2c8c8d8-s.woff2 +0 -0
  99. package/.next/static/media/58f386aa6b1a2a92-s.woff2 +0 -0
  100. package/.next/static/media/656feb427634a431-s.woff2 +0 -0
  101. package/.next/static/media/67957d42bae0796d-s.woff2 +0 -0
  102. package/.next/static/media/704b853f32d191d5-s.woff2 +0 -0
  103. package/.next/static/media/73cb51aac9c97f90-s.woff2 +0 -0
  104. package/.next/static/media/7ba5fb2a8c88521c-s.woff2 +0 -0
  105. package/.next/static/media/886030b0b59bc5a7-s.woff2 +0 -0
  106. package/.next/static/media/92eeb95d069020cc-s.woff2 +0 -0
  107. package/.next/static/media/939c4f875ee75fbb-s.woff2 +0 -0
  108. package/.next/static/media/98e207f02528a563-s.p.woff2 +0 -0
  109. package/.next/static/media/991629005c80bdf1-s.woff2 +0 -0
  110. package/.next/static/media/99dcf268bda04fe5-s.woff2 +0 -0
  111. package/.next/static/media/bb3ef058b751a6ad-s.p.woff2 +0 -0
  112. package/.next/static/media/d26bbd13d6b70f89-s.woff2 +0 -0
  113. package/.next/static/media/d29838c109ef09b4-s.woff2 +0 -0
  114. package/.next/static/media/d3ebbfd689654d3a-s.p.woff2 +0 -0
  115. package/.next/static/media/db96af6b531dc71f-s.p.woff2 +0 -0
  116. package/.next/static/media/e40af3453d7c920a-s.woff2 +0 -0
  117. package/.next/static/media/ef4d5661765d0e49-s.woff2 +0 -0
  118. package/.next/static/media/f911b923c6adde36-s.woff2 +0 -0
  119. package/README.md +152 -0
  120. package/dist/bin/agentlens.mjs +1104 -0
  121. package/next.config.mjs +10 -0
  122. package/package.json +88 -0
@@ -0,0 +1,1104 @@
1
+ #!/usr/bin/env node
2
+
3
+ // bin/cli.ts
4
+ import { join as join2, dirname, resolve } from "path";
5
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2 } from "fs";
6
+ import { homedir as homedir2 } from "os";
7
+ import { fileURLToPath } from "url";
8
+ import { spawn, exec } from "child_process";
9
+ import { createRequire } from "module";
10
+
11
+ // collector/indexer.ts
12
+ import { readdirSync, readFileSync, existsSync } from "fs";
13
+ import { join } from "path";
14
+ import { execSync } from "child_process";
15
+ import { userInfo } from "os";
16
+ import { eq as eq2 } from "drizzle-orm";
17
+
18
+ // lib/db/schema.ts
19
+ import { sql, eq, and, gte, lte, desc, asc, count } from "drizzle-orm";
20
+ import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
21
+ var sessions = sqliteTable("sessions", {
22
+ id: text("id").primaryKey(),
23
+ teamId: text("team_id").notNull(),
24
+ userId: text("user_id").notNull(),
25
+ project: text("project").notNull(),
26
+ gitRepo: text("git_repo"),
27
+ gitBranch: text("git_branch"),
28
+ piVersion: text("pi_version").notNull().default(""),
29
+ skillsUsed: text("skills_used").notNull().default("[]"),
30
+ model: text("model"),
31
+ harness: text("harness").notNull().default("pi"),
32
+ startedAt: text("started_at").notNull(),
33
+ endedAt: text("ended_at"),
34
+ status: text("status").notNull().default("active"),
35
+ createdAt: text("created_at").notNull().default(sql`(datetime('now'))`)
36
+ });
37
+ var events = sqliteTable("events", {
38
+ id: integer("id").primaryKey({ autoIncrement: true }),
39
+ sessionId: text("session_id").notNull(),
40
+ eventType: text("event_type").notNull(),
41
+ timestamp: text("timestamp").notNull(),
42
+ payload: text("payload").notNull().default("{}"),
43
+ createdAt: text("created_at").notNull().default(sql`(datetime('now'))`)
44
+ });
45
+ var pullRequests = sqliteTable("pull_requests", {
46
+ id: integer("id").primaryKey({ autoIncrement: true }),
47
+ sessionId: text("session_id").notNull(),
48
+ repo: text("repo").notNull(),
49
+ branch: text("branch").notNull(),
50
+ prNumber: integer("pr_number").notNull(),
51
+ prUrl: text("pr_url").notNull(),
52
+ prTitle: text("pr_title").notNull().default(""),
53
+ status: text("status").notNull().default("open"),
54
+ mergedAt: text("merged_at"),
55
+ reviewsApproved: integer("reviews_approved").notNull().default(0),
56
+ reviewsChangesRequested: integer("reviews_changes_requested").notNull().default(0),
57
+ reviewComments: integer("review_comments").notNull().default(0),
58
+ commitsAfterReview: integer("commits_after_review").notNull().default(0),
59
+ firstReviewAt: text("first_review_at"),
60
+ timeToMergeHours: text("time_to_merge_hours"),
61
+ // stored as text for SQLite real compat
62
+ checkedAt: text("checked_at"),
63
+ createdAt: text("created_at").notNull().default(sql`(datetime('now'))`)
64
+ });
65
+ function insertSession(db, input) {
66
+ db.insert(sessions).values({
67
+ id: input.id,
68
+ teamId: input.teamId,
69
+ userId: input.userId,
70
+ project: input.project,
71
+ gitRepo: input.gitRepo,
72
+ gitBranch: input.gitBranch,
73
+ piVersion: input.piVersion,
74
+ skillsUsed: JSON.stringify(input.skillsUsed),
75
+ model: input.model,
76
+ harness: input.harness || "pi",
77
+ startedAt: input.startedAt
78
+ }).run();
79
+ }
80
+ function insertEvent(db, input) {
81
+ db.insert(events).values({
82
+ sessionId: input.sessionId,
83
+ eventType: input.eventType,
84
+ timestamp: input.timestamp,
85
+ payload: JSON.stringify(input.payload)
86
+ }).run();
87
+ }
88
+ function upsertPullRequest(db, input) {
89
+ const existing = db.select().from(pullRequests).where(
90
+ and(eq(pullRequests.sessionId, input.sessionId), eq(pullRequests.prNumber, input.prNumber))
91
+ ).get();
92
+ if (existing) {
93
+ db.update(pullRequests).set({
94
+ status: input.status,
95
+ prTitle: input.prTitle,
96
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString()
97
+ }).where(eq(pullRequests.id, existing.id)).run();
98
+ } else {
99
+ db.insert(pullRequests).values({
100
+ sessionId: input.sessionId,
101
+ repo: input.repo,
102
+ branch: input.branch,
103
+ prNumber: input.prNumber,
104
+ prUrl: input.prUrl,
105
+ prTitle: input.prTitle,
106
+ status: input.status
107
+ }).run();
108
+ }
109
+ }
110
+
111
+ // collector/model-context.ts
112
+ var CONTEXT_WINDOWS = {
113
+ // Claude 4
114
+ "claude-opus-4-6": 2e5,
115
+ "claude-sonnet-4-6": 2e5,
116
+ // Claude 3.5+
117
+ "claude-opus-4-5": 2e5,
118
+ "claude-sonnet-4-5": 2e5,
119
+ "claude-haiku-4-5-20251001": 2e5,
120
+ // Claude 3
121
+ "claude-3-opus-20240229": 2e5,
122
+ "claude-3-sonnet-20240229": 2e5,
123
+ "claude-3-haiku-20240307": 2e5,
124
+ // OpenAI
125
+ "gpt-4o": 128e3,
126
+ "gpt-4-turbo": 128e3,
127
+ "gpt-4": 8192,
128
+ "gpt-5.3-codex": 2e5,
129
+ "o1-preview": 128e3,
130
+ "o1-mini": 128e3
131
+ };
132
+ function getContextWindow(model) {
133
+ if (!model) return null;
134
+ if (CONTEXT_WINDOWS[model]) return CONTEXT_WINDOWS[model];
135
+ for (const [key, value] of Object.entries(CONTEXT_WINDOWS)) {
136
+ if (model.startsWith(key)) return value;
137
+ }
138
+ if (model.includes("claude")) return 2e5;
139
+ if (model.includes("gpt-4")) return 128e3;
140
+ return null;
141
+ }
142
+
143
+ // collector/claude-code/parser.ts
144
+ var SUBAGENT_TOOLS = /* @__PURE__ */ new Set(["Task", "Agent"]);
145
+ function projectFromCwd(cwd) {
146
+ const parts = cwd.replace(/\/+$/, "").split("/");
147
+ return parts[parts.length - 1] || cwd;
148
+ }
149
+ function getFilePath(input) {
150
+ return input.file_path || input.path || null;
151
+ }
152
+ function summarizeToolInput(name, input) {
153
+ if (name === "Bash" && input.command) {
154
+ return String(input.command).slice(0, 200);
155
+ }
156
+ const filePath = getFilePath(input);
157
+ if ((name === "Write" || name === "Edit" || name === "MultiEdit") && filePath) {
158
+ return filePath;
159
+ }
160
+ if (name === "Read" && filePath) {
161
+ return filePath;
162
+ }
163
+ if ((name === "Task" || name === "Agent") && input.description) {
164
+ return String(input.description).slice(0, 200);
165
+ }
166
+ if ((name === "Task" || name === "Agent") && input.prompt) {
167
+ return String(input.prompt).slice(0, 200);
168
+ }
169
+ for (const val of Object.values(input)) {
170
+ if (typeof val === "string" && val.length > 0) {
171
+ return val.slice(0, 200);
172
+ }
173
+ }
174
+ return "";
175
+ }
176
+ function parseClaudeCodeSession(jsonl) {
177
+ const lines = jsonl.split("\n").filter((l) => l.trim()).map((l) => JSON.parse(l));
178
+ const events2 = [];
179
+ let sessionId = "";
180
+ let project = "";
181
+ let gitBranch = null;
182
+ let model = null;
183
+ let version = "";
184
+ let userId = "";
185
+ let startedAt = "";
186
+ let endedAt = "";
187
+ let usedSubagents = false;
188
+ let totalInputTokens = 0;
189
+ let totalOutputTokens = 0;
190
+ let totalCacheReadTokens = 0;
191
+ let totalCacheWriteTokens = 0;
192
+ const toolResults = /* @__PURE__ */ new Map();
193
+ for (const line of lines) {
194
+ if (line.type === "user") {
195
+ const content = line.message?.content;
196
+ if (Array.isArray(content)) {
197
+ for (const item of content) {
198
+ if (item.type === "tool_result" && item.tool_use_id) {
199
+ toolResults.set(item.tool_use_id, item);
200
+ }
201
+ }
202
+ }
203
+ }
204
+ }
205
+ for (const line of lines) {
206
+ const ts = line.timestamp;
207
+ if (!ts) continue;
208
+ if (!startedAt || ts < startedAt) startedAt = ts;
209
+ if (!endedAt || ts > endedAt) endedAt = ts;
210
+ if (line.type === "user" && line.sessionId && !sessionId) {
211
+ sessionId = line.sessionId;
212
+ project = projectFromCwd(line.cwd || "");
213
+ gitBranch = line.gitBranch || null;
214
+ version = line.version || "";
215
+ userId = line.message?.content?.user_id || "";
216
+ }
217
+ if (line.type === "user" && line.userType === "external") {
218
+ const content = line.message?.content;
219
+ if (typeof content === "string" && content.trim()) {
220
+ events2.push({
221
+ eventType: "user_prompt",
222
+ timestamp: ts,
223
+ payload: {
224
+ prompt_text: content,
225
+ prompt_length: content.length
226
+ }
227
+ });
228
+ }
229
+ }
230
+ if (line.type === "assistant") {
231
+ const msg = line.message || {};
232
+ const usage = msg.usage || {};
233
+ if (msg.model && !model) {
234
+ model = msg.model;
235
+ }
236
+ const inputTokens = usage.input_tokens || 0;
237
+ const outputTokens = usage.output_tokens || 0;
238
+ const cacheRead = usage.cache_read_input_tokens || 0;
239
+ const cacheWrite = usage.cache_creation_input_tokens || 0;
240
+ totalInputTokens += inputTokens;
241
+ totalOutputTokens += outputTokens;
242
+ totalCacheReadTokens += cacheRead;
243
+ totalCacheWriteTokens += cacheWrite;
244
+ const responseModel = msg.model || model;
245
+ const contextWindow = getContextWindow(responseModel);
246
+ events2.push({
247
+ eventType: "llm_response",
248
+ timestamp: ts,
249
+ payload: {
250
+ model: responseModel,
251
+ input_tokens: inputTokens,
252
+ output_tokens: outputTokens,
253
+ cache_read_tokens: cacheRead,
254
+ cache_write_tokens: cacheWrite,
255
+ total_tokens: inputTokens + outputTokens,
256
+ stop_reason: msg.stop_reason || null,
257
+ ...contextWindow ? { context_window: contextWindow } : {}
258
+ }
259
+ });
260
+ const content = msg.content || [];
261
+ if (Array.isArray(content)) {
262
+ for (const item of content) {
263
+ if (item.type === "tool_use") {
264
+ const toolUse = item;
265
+ const toolResult = toolResults.get(toolUse.id);
266
+ const isError = toolResult?.is_error === true;
267
+ const isSubagent = SUBAGENT_TOOLS.has(toolUse.name);
268
+ if (isSubagent) usedSubagents = true;
269
+ const argsSummary = summarizeToolInput(toolUse.name, toolUse.input || {});
270
+ events2.push({
271
+ eventType: "tool_call",
272
+ timestamp: ts,
273
+ payload: {
274
+ tool: toolUse.name,
275
+ args_summary: argsSummary,
276
+ result_summary: toolResult?.content ? String(toolResult.content).slice(0, 200) : "",
277
+ success: !isError,
278
+ is_error: isError,
279
+ ...isSubagent ? { is_subagent: true } : {}
280
+ }
281
+ });
282
+ const changeFilePath = getFilePath(toolUse.input || {});
283
+ if (toolUse.name === "Write" && changeFilePath) {
284
+ events2.push({
285
+ eventType: "file_change",
286
+ timestamp: ts,
287
+ payload: { path: changeFilePath, action: "create" }
288
+ });
289
+ }
290
+ if ((toolUse.name === "Edit" || toolUse.name === "MultiEdit") && changeFilePath) {
291
+ events2.push({
292
+ eventType: "file_change",
293
+ timestamp: ts,
294
+ payload: { path: changeFilePath, action: "edit" }
295
+ });
296
+ }
297
+ if (toolUse.name === "Bash" && toolUse.input?.command) {
298
+ const cmd = String(toolUse.input.command);
299
+ const resultText = toolResult?.content ? String(toolResult.content) : "";
300
+ if (cmd.includes("git commit")) {
301
+ events2.push({
302
+ eventType: "git_commit",
303
+ timestamp: ts,
304
+ payload: {
305
+ command: cmd,
306
+ result_summary: resultText.slice(0, 200)
307
+ }
308
+ });
309
+ }
310
+ if (cmd.includes("git push")) {
311
+ events2.push({
312
+ eventType: "git_push",
313
+ timestamp: ts,
314
+ payload: {
315
+ command: cmd,
316
+ result_summary: resultText.slice(0, 200)
317
+ }
318
+ });
319
+ }
320
+ if (cmd.includes("gh pr create") || cmd.includes("gh pr merge")) {
321
+ const prMatch = resultText.match(
322
+ /https:\/\/github\.com\/([^/]+\/[^/]+)\/pull\/(\d+)/
323
+ );
324
+ if (prMatch) {
325
+ events2.push({
326
+ eventType: "pr_opened",
327
+ timestamp: ts,
328
+ payload: {
329
+ command: cmd.slice(0, 200),
330
+ pr_url: prMatch[0],
331
+ repo: prMatch[1],
332
+ pr_number: parseInt(prMatch[2], 10)
333
+ }
334
+ });
335
+ }
336
+ }
337
+ }
338
+ if (isError && toolResult?.content) {
339
+ events2.push({
340
+ eventType: "error",
341
+ timestamp: ts,
342
+ payload: {
343
+ tool: toolUse.name,
344
+ message: String(toolResult.content).slice(0, 500)
345
+ }
346
+ });
347
+ }
348
+ }
349
+ }
350
+ }
351
+ }
352
+ }
353
+ events2.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
354
+ events2.unshift({
355
+ eventType: "session_start",
356
+ timestamp: startedAt,
357
+ payload: {
358
+ model,
359
+ git_branch: gitBranch,
360
+ project,
361
+ harness: "claude-code",
362
+ version,
363
+ user_id: userId
364
+ }
365
+ });
366
+ events2.push({
367
+ eventType: "session_end",
368
+ timestamp: endedAt,
369
+ payload: {
370
+ reason: "session_end_inferred"
371
+ }
372
+ });
373
+ return {
374
+ sessionId,
375
+ project,
376
+ gitBranch,
377
+ harness: "claude-code",
378
+ model,
379
+ version,
380
+ userId,
381
+ startedAt,
382
+ endedAt,
383
+ events: events2,
384
+ totalInputTokens,
385
+ totalOutputTokens,
386
+ totalCacheReadTokens,
387
+ totalCacheWriteTokens,
388
+ usedSubagents
389
+ };
390
+ }
391
+
392
+ // collector/pi/parser.ts
393
+ var SUBAGENT_TOOLS2 = /* @__PURE__ */ new Set(["subagent", "delegate", "Task", "Agent"]);
394
+ function projectFromCwd2(cwd) {
395
+ const parts = cwd.replace(/\/+$/, "").split("/");
396
+ return parts[parts.length - 1] || cwd;
397
+ }
398
+ function getFilePath2(args2) {
399
+ return args2.path || args2.file_path || null;
400
+ }
401
+ function summarizeToolInput2(name, args2) {
402
+ const lname = name.toLowerCase();
403
+ if (lname === "bash" && args2.command) {
404
+ return String(args2.command).slice(0, 200);
405
+ }
406
+ const filePath = getFilePath2(args2);
407
+ if ((lname === "write" || lname === "edit" || lname === "read") && filePath) {
408
+ return filePath;
409
+ }
410
+ if (lname === "edit" && Array.isArray(args2.multi) && args2.multi.length > 0) {
411
+ const firstPath = args2.multi[0].path || args2.multi[0].file_path || "";
412
+ const count2 = args2.multi.length;
413
+ return count2 > 1 ? `${firstPath} (+${count2 - 1} more)` : firstPath;
414
+ }
415
+ if (SUBAGENT_TOOLS2.has(name)) {
416
+ return String(args2.task || args2.description || args2.prompt || "").slice(0, 200);
417
+ }
418
+ for (const [key, val] of Object.entries(args2)) {
419
+ if (key === "content") continue;
420
+ if (typeof val === "string" && val.length > 0) {
421
+ return val.slice(0, 200);
422
+ }
423
+ }
424
+ return "";
425
+ }
426
+ function parsePiSession(jsonl, sessionDir) {
427
+ const lines = jsonl.split("\n").filter((l) => l.trim()).map((l) => JSON.parse(l));
428
+ const events2 = [];
429
+ let sessionId = "";
430
+ let project = "";
431
+ let model = null;
432
+ let version = "";
433
+ let startedAt = "";
434
+ let endedAt = "";
435
+ let usedSubagents = false;
436
+ let totalInputTokens = 0;
437
+ let totalOutputTokens = 0;
438
+ let totalCacheReadTokens = 0;
439
+ let totalCacheWriteTokens = 0;
440
+ const toolResultById = /* @__PURE__ */ new Map();
441
+ const toolResultsByIndex = [];
442
+ for (const line of lines) {
443
+ if (line.type !== "message") continue;
444
+ const msg = line.message || {};
445
+ if (msg.role !== "toolResult") continue;
446
+ const text2 = (msg.content || []).filter((c) => c.type === "text").map((c) => c.text).join("\n");
447
+ const info = {
448
+ content: text2,
449
+ isError: msg.isError === true,
450
+ ts: line.timestamp
451
+ };
452
+ if (msg.toolCallId) {
453
+ toolResultById.set(msg.toolCallId, info);
454
+ }
455
+ toolResultsByIndex.push(info);
456
+ }
457
+ let toolCallSeqIndex = 0;
458
+ for (const line of lines) {
459
+ const ts = line.timestamp;
460
+ if (!ts) continue;
461
+ if (!startedAt || ts < startedAt) startedAt = ts;
462
+ if (!endedAt || ts > endedAt) endedAt = ts;
463
+ if (line.type === "session") {
464
+ sessionId = line.id;
465
+ version = String(line.version || "");
466
+ if (line.cwd) project = projectFromCwd2(line.cwd);
467
+ }
468
+ if (line.type === "model_change" && line.modelId) {
469
+ model = line.modelId;
470
+ }
471
+ if (line.type !== "message") continue;
472
+ const msg = line.message || {};
473
+ if (msg.role === "user") {
474
+ const text2 = (msg.content || []).filter((c) => c.type === "text").map((c) => c.text).join("\n");
475
+ if (text2.trim()) {
476
+ events2.push({
477
+ eventType: "user_prompt",
478
+ timestamp: ts,
479
+ payload: { prompt_text: text2, prompt_length: text2.length }
480
+ });
481
+ }
482
+ }
483
+ if (msg.role === "assistant") {
484
+ const usage = msg.usage || {};
485
+ const inputTokens = usage.input || 0;
486
+ const outputTokens = usage.output || 0;
487
+ const cacheRead = usage.cacheRead || 0;
488
+ const cacheWrite = usage.cacheWrite || 0;
489
+ const costTotal = usage.cost?.total || 0;
490
+ totalInputTokens += inputTokens;
491
+ totalOutputTokens += outputTokens;
492
+ totalCacheReadTokens += cacheRead;
493
+ totalCacheWriteTokens += cacheWrite;
494
+ const responseModel = msg.model || model;
495
+ const contextWindow = getContextWindow(responseModel);
496
+ events2.push({
497
+ eventType: "llm_response",
498
+ timestamp: ts,
499
+ payload: {
500
+ model: responseModel,
501
+ input_tokens: inputTokens,
502
+ output_tokens: outputTokens,
503
+ cache_read_tokens: cacheRead,
504
+ cache_write_tokens: cacheWrite,
505
+ total_tokens: usage.totalTokens || inputTokens + outputTokens,
506
+ total_cost_usd: costTotal,
507
+ stop_reason: msg.stop_reason || null,
508
+ ...contextWindow ? { context_window: contextWindow } : {}
509
+ }
510
+ });
511
+ for (const c of msg.content || []) {
512
+ if (c.type !== "toolCall") continue;
513
+ const toolId = c.id;
514
+ const args2 = c.arguments || c.input || {};
515
+ const toolResult = toolResultById.get(toolId) || toolResultsByIndex[toolCallSeqIndex] || null;
516
+ const isError = toolResult?.isError === true;
517
+ const isSubagent = SUBAGENT_TOOLS2.has(c.name);
518
+ if (isSubagent) usedSubagents = true;
519
+ const argsSummary = summarizeToolInput2(c.name, args2);
520
+ events2.push({
521
+ eventType: "tool_call",
522
+ timestamp: ts,
523
+ payload: {
524
+ tool: c.name,
525
+ args_summary: argsSummary,
526
+ result_summary: toolResult?.content ? toolResult.content.slice(0, 200) : "",
527
+ success: !isError,
528
+ is_error: isError,
529
+ ...isSubagent ? { is_subagent: true } : {}
530
+ }
531
+ });
532
+ const lname = c.name.toLowerCase();
533
+ const filePath = getFilePath2(args2);
534
+ if (lname === "write" && filePath) {
535
+ events2.push({
536
+ eventType: "file_change",
537
+ timestamp: ts,
538
+ payload: { path: filePath, action: "create" }
539
+ });
540
+ }
541
+ if (lname === "edit" || lname === "multiedit") {
542
+ if (filePath) {
543
+ events2.push({
544
+ eventType: "file_change",
545
+ timestamp: ts,
546
+ payload: { path: filePath, action: "edit" }
547
+ });
548
+ }
549
+ if (Array.isArray(args2.multi)) {
550
+ const seen = /* @__PURE__ */ new Set();
551
+ for (const item of args2.multi) {
552
+ const p = item.path || item.file_path;
553
+ if (p && !seen.has(p)) {
554
+ seen.add(p);
555
+ events2.push({
556
+ eventType: "file_change",
557
+ timestamp: ts,
558
+ payload: { path: p, action: "edit" }
559
+ });
560
+ }
561
+ }
562
+ }
563
+ }
564
+ if (lname === "bash" && args2.command) {
565
+ const cmd = String(args2.command);
566
+ if (cmd.includes("git commit")) {
567
+ events2.push({
568
+ eventType: "git_commit",
569
+ timestamp: ts,
570
+ payload: {
571
+ command: cmd,
572
+ result_summary: toolResult?.content?.slice(0, 200) || ""
573
+ }
574
+ });
575
+ }
576
+ if (cmd.includes("git push")) {
577
+ events2.push({
578
+ eventType: "git_push",
579
+ timestamp: ts,
580
+ payload: {
581
+ command: cmd,
582
+ result_summary: toolResult?.content?.slice(0, 200) || ""
583
+ }
584
+ });
585
+ }
586
+ if (cmd.includes("gh pr create") || cmd.includes("gh pr merge")) {
587
+ const resultText = toolResult?.content || "";
588
+ const prMatch = resultText.match(/https:\/\/github\.com\/([^/]+\/[^/]+)\/pull\/(\d+)/);
589
+ if (prMatch) {
590
+ events2.push({
591
+ eventType: "pr_opened",
592
+ timestamp: ts,
593
+ payload: {
594
+ command: cmd.slice(0, 200),
595
+ pr_url: prMatch[0],
596
+ repo: prMatch[1],
597
+ pr_number: parseInt(prMatch[2], 10)
598
+ }
599
+ });
600
+ }
601
+ }
602
+ }
603
+ if (isError && toolResult?.content) {
604
+ events2.push({
605
+ eventType: "error",
606
+ timestamp: ts,
607
+ payload: { tool: c.name, message: toolResult.content.slice(0, 500) }
608
+ });
609
+ }
610
+ toolCallSeqIndex++;
611
+ }
612
+ }
613
+ }
614
+ events2.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
615
+ events2.unshift({
616
+ eventType: "session_start",
617
+ timestamp: startedAt,
618
+ payload: { model, project, harness: "pi", version }
619
+ });
620
+ events2.push({
621
+ eventType: "session_end",
622
+ timestamp: endedAt,
623
+ payload: { reason: "session_end_inferred" }
624
+ });
625
+ return {
626
+ sessionId,
627
+ project,
628
+ gitBranch: null,
629
+ harness: "pi",
630
+ model,
631
+ version,
632
+ userId: "",
633
+ startedAt,
634
+ endedAt,
635
+ events: events2,
636
+ totalInputTokens,
637
+ totalOutputTokens,
638
+ totalCacheReadTokens,
639
+ totalCacheWriteTokens,
640
+ usedSubagents
641
+ };
642
+ }
643
+
644
+ // collector/indexer.ts
645
+ var _cachedUserId = null;
646
+ function detectUserId() {
647
+ if (_cachedUserId) return _cachedUserId;
648
+ try {
649
+ _cachedUserId = execSync("git config user.email", { encoding: "utf-8" }).trim();
650
+ if (_cachedUserId) return _cachedUserId;
651
+ } catch {
652
+ }
653
+ _cachedUserId = userInfo().username || "unknown";
654
+ return _cachedUserId;
655
+ }
656
+ function discoverClaudeCodeSessions(projectsDir) {
657
+ if (!existsSync(projectsDir)) return [];
658
+ const files = [];
659
+ try {
660
+ const projectDirs = readdirSync(projectsDir, { withFileTypes: true });
661
+ for (const dir of projectDirs) {
662
+ if (!dir.isDirectory()) continue;
663
+ const dirPath = join(projectsDir, dir.name);
664
+ const dirEntries = readdirSync(dirPath, { withFileTypes: true });
665
+ for (const entry of dirEntries) {
666
+ if (entry.isFile() && entry.name.endsWith(".jsonl")) {
667
+ files.push(join(dirPath, entry.name));
668
+ }
669
+ }
670
+ }
671
+ } catch {
672
+ }
673
+ return files;
674
+ }
675
+ function discoverPiSessions(sessionsDir) {
676
+ if (!existsSync(sessionsDir)) return [];
677
+ const files = [];
678
+ try {
679
+ const projectDirs = readdirSync(sessionsDir, { withFileTypes: true });
680
+ for (const dir of projectDirs) {
681
+ if (!dir.isDirectory()) continue;
682
+ const dirPath = join(sessionsDir, dir.name);
683
+ const dirEntries = readdirSync(dirPath, { withFileTypes: true });
684
+ for (const entry of dirEntries) {
685
+ if (entry.isFile() && entry.name.endsWith(".jsonl")) {
686
+ files.push(join(dirPath, entry.name));
687
+ }
688
+ }
689
+ }
690
+ } catch {
691
+ }
692
+ return files;
693
+ }
694
+ function importParsedSession(db, parsed, result) {
695
+ if (!parsed.sessionId) {
696
+ return false;
697
+ }
698
+ const existing = db.select().from(sessions).where(eq2(sessions.id, parsed.sessionId)).get();
699
+ if (existing) {
700
+ result.skipped++;
701
+ return false;
702
+ }
703
+ const userId = parsed.userId || detectUserId();
704
+ insertSession(db, {
705
+ id: parsed.sessionId,
706
+ teamId: "default",
707
+ userId,
708
+ project: parsed.project,
709
+ gitRepo: null,
710
+ gitBranch: parsed.gitBranch,
711
+ piVersion: parsed.version,
712
+ skillsUsed: [],
713
+ model: parsed.model,
714
+ harness: parsed.harness,
715
+ startedAt: parsed.startedAt
716
+ });
717
+ if (parsed.endedAt) {
718
+ db.update(sessions).set({ endedAt: parsed.endedAt, status: "completed" }).where(eq2(sessions.id, parsed.sessionId)).run();
719
+ }
720
+ for (const event of parsed.events) {
721
+ insertEvent(db, {
722
+ sessionId: parsed.sessionId,
723
+ eventType: event.eventType,
724
+ timestamp: event.timestamp,
725
+ payload: event.payload
726
+ });
727
+ if (event.eventType === "pr_opened" && event.payload.pr_url) {
728
+ upsertPullRequest(db, {
729
+ sessionId: parsed.sessionId,
730
+ repo: event.payload.repo || "",
731
+ branch: parsed.gitBranch || "",
732
+ prNumber: event.payload.pr_number || 0,
733
+ prUrl: event.payload.pr_url,
734
+ prTitle: "",
735
+ // not available from bash output
736
+ status: "open"
737
+ });
738
+ }
739
+ }
740
+ result.imported++;
741
+ return true;
742
+ }
743
+ function indexSessions(db, options = {}) {
744
+ const result = { imported: 0, skipped: 0, errors: [] };
745
+ const harness = options.harness;
746
+ if (!harness || harness === "claude-code") {
747
+ const projectsDir = options.claudeProjectsDir || join(process.env.HOME || "~", ".claude", "projects");
748
+ const files = discoverClaudeCodeSessions(projectsDir);
749
+ for (const filePath of files) {
750
+ try {
751
+ const jsonl = readFileSync(filePath, "utf-8");
752
+ const parsed = parseClaudeCodeSession(jsonl);
753
+ if (!parsed.sessionId) {
754
+ result.errors.push(`No session ID found in ${filePath}`);
755
+ continue;
756
+ }
757
+ importParsedSession(db, parsed, result);
758
+ } catch (err) {
759
+ result.errors.push(`Error processing ${filePath}: ${err}`);
760
+ }
761
+ }
762
+ }
763
+ if (!harness || harness === "pi") {
764
+ const sessionsDir = options.piSessionsDir || join(process.env.HOME || "~", ".pi", "agent", "sessions");
765
+ const files = discoverPiSessions(sessionsDir);
766
+ for (const filePath of files) {
767
+ try {
768
+ const jsonl = readFileSync(filePath, "utf-8");
769
+ const dirName = join(filePath, "..").split("/").pop() || "";
770
+ const parsed = parsePiSession(jsonl, dirName);
771
+ if (!parsed.sessionId) {
772
+ result.errors.push(`No session ID found in ${filePath}`);
773
+ continue;
774
+ }
775
+ importParsedSession(db, parsed, result);
776
+ } catch (err) {
777
+ result.errors.push(`Error processing ${filePath}: ${err}`);
778
+ }
779
+ }
780
+ }
781
+ return result;
782
+ }
783
+
784
+ // collector/watcher.ts
785
+ function createWatcher(db, options = {}) {
786
+ const interval = options.pollIntervalMs ?? 5e3;
787
+ let stopped = false;
788
+ let timer = null;
789
+ function poll() {
790
+ if (stopped) return;
791
+ try {
792
+ indexSessions(db, options);
793
+ } catch {
794
+ }
795
+ if (!stopped) {
796
+ timer = setTimeout(poll, interval);
797
+ }
798
+ }
799
+ poll();
800
+ return {
801
+ stop() {
802
+ stopped = true;
803
+ if (timer) {
804
+ clearTimeout(timer);
805
+ timer = null;
806
+ }
807
+ }
808
+ };
809
+ }
810
+
811
+ // lib/db/index.ts
812
+ import Database from "better-sqlite3";
813
+ import { drizzle } from "drizzle-orm/better-sqlite3";
814
+ import { sql as sql2 } from "drizzle-orm";
815
+ import path from "path";
816
+ import fs from "fs";
817
+ import { homedir } from "os";
818
+ var _db = null;
819
+ function getDb() {
820
+ if (_db) return _db;
821
+ const dbPath2 = process.env.AGENTLENS_DB_PATH || path.join(homedir(), ".agentlens", "agentlens.db");
822
+ const dataDir2 = path.dirname(dbPath2);
823
+ if (!fs.existsSync(dataDir2)) {
824
+ fs.mkdirSync(dataDir2, { recursive: true });
825
+ }
826
+ const sqlite = new Database(dbPath2);
827
+ sqlite.pragma("journal_mode = WAL");
828
+ const db = drizzle(sqlite);
829
+ db.run(sql2`
830
+ CREATE TABLE IF NOT EXISTS sessions (
831
+ id TEXT PRIMARY KEY,
832
+ team_id TEXT NOT NULL,
833
+ user_id TEXT NOT NULL,
834
+ project TEXT NOT NULL,
835
+ git_repo TEXT,
836
+ git_branch TEXT,
837
+ pi_version TEXT NOT NULL DEFAULT '',
838
+ skills_used TEXT NOT NULL DEFAULT '[]',
839
+ model TEXT,
840
+ harness TEXT NOT NULL DEFAULT 'pi',
841
+ started_at TEXT NOT NULL,
842
+ ended_at TEXT,
843
+ status TEXT NOT NULL DEFAULT 'active',
844
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
845
+ )
846
+ `);
847
+ db.run(sql2`
848
+ CREATE TABLE IF NOT EXISTS events (
849
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
850
+ session_id TEXT NOT NULL,
851
+ event_type TEXT NOT NULL,
852
+ timestamp TEXT NOT NULL,
853
+ payload TEXT NOT NULL DEFAULT '{}',
854
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
855
+ )
856
+ `);
857
+ try {
858
+ db.run(sql2`ALTER TABLE sessions ADD COLUMN model TEXT`);
859
+ } catch {
860
+ }
861
+ db.run(sql2`CREATE INDEX IF NOT EXISTS idx_sessions_team_id ON sessions(team_id)`);
862
+ db.run(sql2`CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON sessions(user_id)`);
863
+ db.run(sql2`CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project)`);
864
+ db.run(sql2`CREATE INDEX IF NOT EXISTS idx_sessions_started_at ON sessions(started_at)`);
865
+ db.run(sql2`CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status)`);
866
+ db.run(sql2`CREATE INDEX IF NOT EXISTS idx_events_session_id ON events(session_id)`);
867
+ db.run(
868
+ sql2`CREATE INDEX IF NOT EXISTS idx_events_session_timestamp ON events(session_id, timestamp)`
869
+ );
870
+ db.run(sql2`CREATE INDEX IF NOT EXISTS idx_events_event_type ON events(event_type)`);
871
+ db.run(sql2`
872
+ CREATE TABLE IF NOT EXISTS pull_requests (
873
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
874
+ session_id TEXT NOT NULL,
875
+ repo TEXT NOT NULL,
876
+ branch TEXT NOT NULL,
877
+ pr_number INTEGER NOT NULL,
878
+ pr_url TEXT NOT NULL,
879
+ pr_title TEXT NOT NULL DEFAULT '',
880
+ status TEXT NOT NULL DEFAULT 'open',
881
+ merged_at TEXT,
882
+ reviews_approved INTEGER NOT NULL DEFAULT 0,
883
+ reviews_changes_requested INTEGER NOT NULL DEFAULT 0,
884
+ review_comments INTEGER NOT NULL DEFAULT 0,
885
+ commits_after_review INTEGER NOT NULL DEFAULT 0,
886
+ first_review_at TEXT,
887
+ time_to_merge_hours REAL,
888
+ checked_at TEXT,
889
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
890
+ UNIQUE(session_id, pr_number)
891
+ )
892
+ `);
893
+ db.run(sql2`CREATE INDEX IF NOT EXISTS idx_prs_session_id ON pull_requests(session_id)`);
894
+ db.run(sql2`CREATE INDEX IF NOT EXISTS idx_prs_status ON pull_requests(status)`);
895
+ db.run(sql2`CREATE INDEX IF NOT EXISTS idx_prs_repo_branch ON pull_requests(repo, branch)`);
896
+ try {
897
+ db.run(sql2`ALTER TABLE sessions ADD COLUMN model TEXT`);
898
+ } catch {
899
+ }
900
+ try {
901
+ db.run(sql2`ALTER TABLE sessions ADD COLUMN harness TEXT NOT NULL DEFAULT 'pi'`);
902
+ } catch {
903
+ }
904
+ db.run(sql2`
905
+ CREATE TABLE IF NOT EXISTS eval_checks (
906
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
907
+ session_id TEXT NOT NULL,
908
+ check_id TEXT NOT NULL,
909
+ check_version TEXT NOT NULL,
910
+ score REAL NOT NULL,
911
+ raw_score INTEGER NOT NULL,
912
+ reasoning TEXT NOT NULL DEFAULT '',
913
+ evidence TEXT,
914
+ model TEXT NOT NULL,
915
+ cost_usd REAL NOT NULL DEFAULT 0,
916
+ evaluated_at TEXT NOT NULL DEFAULT (datetime('now')),
917
+ UNIQUE(session_id, check_id, check_version)
918
+ )
919
+ `);
920
+ db.run(sql2`
921
+ CREATE TABLE IF NOT EXISTS eval_summaries (
922
+ session_id TEXT PRIMARY KEY,
923
+ qual_score REAL NOT NULL,
924
+ checks_passed INTEGER NOT NULL DEFAULT 0,
925
+ checks_total INTEGER NOT NULL DEFAULT 0,
926
+ total_eval_cost_usd REAL NOT NULL DEFAULT 0,
927
+ evaluated_at TEXT NOT NULL DEFAULT (datetime('now'))
928
+ )
929
+ `);
930
+ db.run(sql2`CREATE INDEX IF NOT EXISTS idx_eval_checks_session ON eval_checks(session_id)`);
931
+ db.run(
932
+ sql2`CREATE INDEX IF NOT EXISTS idx_eval_checks_lookup ON eval_checks(session_id, check_id, check_version)`
933
+ );
934
+ db.run(sql2`
935
+ CREATE TABLE IF NOT EXISTS session_insights (
936
+ session_id TEXT PRIMARY KEY,
937
+ task_category TEXT NOT NULL,
938
+ task_size TEXT NOT NULL,
939
+ workflow_tags TEXT NOT NULL DEFAULT '[]',
940
+ prompting_tags TEXT NOT NULL DEFAULT '[]',
941
+ failure_modes TEXT NOT NULL DEFAULT '[]',
942
+ complexity_factors TEXT NOT NULL DEFAULT '[]',
943
+ key_learning TEXT,
944
+ extracted_at TEXT NOT NULL DEFAULT (datetime('now')),
945
+ model TEXT NOT NULL,
946
+ synced_at TEXT
947
+ )
948
+ `);
949
+ for (const col of [
950
+ "failure_modes TEXT NOT NULL DEFAULT '[]'",
951
+ "complexity_factors TEXT NOT NULL DEFAULT '[]'",
952
+ "key_learning TEXT"
953
+ ]) {
954
+ try {
955
+ db.run(sql2.raw(`ALTER TABLE session_insights ADD COLUMN ${col}`));
956
+ } catch {
957
+ }
958
+ }
959
+ _db = db;
960
+ return db;
961
+ }
962
+
963
+ // bin/cli.ts
964
+ var args = process.argv.slice(2);
965
+ function getFlag(name) {
966
+ return args.includes(`--${name}`);
967
+ }
968
+ function getFlagValue(name) {
969
+ const idx = args.indexOf(`--${name}`);
970
+ if (idx >= 0 && idx + 1 < args.length) return args[idx + 1];
971
+ return void 0;
972
+ }
973
+ if (getFlag("help") || getFlag("h")) {
974
+ console.log(`
975
+ agentlens \u2014 observability for AI coding agents
976
+
977
+ Usage:
978
+ npx agentlens [options]
979
+
980
+ Options:
981
+ --port <number> Port for the dashboard (default: 3333)
982
+ --data <path> Data directory for the SQLite DB (default: ~/.agentlens)
983
+ --no-open Don't auto-open the browser
984
+ --help, -h Show this help message
985
+ `);
986
+ process.exit(0);
987
+ }
988
+ var port = parseInt(getFlagValue("port") || "3333", 10);
989
+ var dataDir = getFlagValue("data") || join2(homedir2(), ".agentlens");
990
+ var noOpen = getFlag("no-open");
991
+ var dbPath = join2(dataDir, "agentlens.db");
992
+ var __filename = fileURLToPath(import.meta.url);
993
+ var __dirname = dirname(__filename);
994
+ var pkgRoot = existsSync2(join2(__dirname, "..", ".next")) ? resolve(__dirname, "..") : resolve(__dirname, "..", "..");
995
+ var claudeProjectsDir = join2(homedir2(), ".claude", "projects");
996
+ var piSessionsDir = join2(homedir2(), ".pi", "agent", "sessions");
997
+ async function main() {
998
+ if (!existsSync2(dataDir)) {
999
+ mkdirSync(dataDir, { recursive: true });
1000
+ }
1001
+ process.env.AGENTLENS_DB_PATH = dbPath;
1002
+ console.log(`
1003
+ \x1B[1magentlens\x1B[0m v${getVersion()}
1004
+
1005
+ \u25B8 Dashboard: \x1B[36mhttp://localhost:${port}\x1B[0m
1006
+ \u25B8 Data: ${dbPath}
1007
+ \u25B8 Watching: ${claudeProjectsDir}
1008
+ ${piSessionsDir}
1009
+ `);
1010
+ const db = getDb();
1011
+ const startTime = Date.now();
1012
+ process.stdout.write(" Indexing sessions...");
1013
+ const result = indexSessions(db, { claudeProjectsDir, piSessionsDir });
1014
+ const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
1015
+ const total = result.imported + result.skipped;
1016
+ console.log(
1017
+ ` found ${total} session${total !== 1 ? "s" : ""}, ${result.imported} new (${elapsed}s)`
1018
+ );
1019
+ if (result.errors.length > 0) {
1020
+ console.log(` \u26A0 ${result.errors.length} error${result.errors.length !== 1 ? "s" : ""}`);
1021
+ }
1022
+ const watcher = createWatcher(db, {
1023
+ claudeProjectsDir,
1024
+ piSessionsDir,
1025
+ pollIntervalMs: 5e3
1026
+ });
1027
+ console.log(" Watching for new sessions...\n");
1028
+ const require2 = createRequire(import.meta.url);
1029
+ const nextBin = require2.resolve("next/dist/bin/next");
1030
+ const server = spawn(process.execPath, [nextBin, "start", "--port", String(port)], {
1031
+ cwd: pkgRoot,
1032
+ env: {
1033
+ ...process.env,
1034
+ AGENTLENS_DB_PATH: dbPath,
1035
+ PORT: String(port),
1036
+ HOSTNAME: "localhost"
1037
+ },
1038
+ stdio: ["ignore", "pipe", "pipe"]
1039
+ });
1040
+ let serverReady = false;
1041
+ server.stdout?.on("data", (data) => {
1042
+ const text2 = data.toString().trim();
1043
+ if (text2 && !serverReady) {
1044
+ serverReady = true;
1045
+ if (!noOpen) {
1046
+ openBrowser(`http://localhost:${port}`);
1047
+ }
1048
+ }
1049
+ });
1050
+ server.stderr?.on("data", (data) => {
1051
+ const text2 = data.toString().trim();
1052
+ if (text2) {
1053
+ if (!text2.includes("ExperimentalWarning")) {
1054
+ console.error(` [server] ${text2}`);
1055
+ }
1056
+ }
1057
+ });
1058
+ server.on("error", (err) => {
1059
+ console.error(` Failed to start server: ${err.message}`);
1060
+ cleanup(watcher, server);
1061
+ process.exit(1);
1062
+ });
1063
+ server.on("exit", (code) => {
1064
+ if (code !== 0 && code !== null) {
1065
+ console.error(` Server exited with code ${code}`);
1066
+ }
1067
+ cleanup(watcher, null);
1068
+ process.exit(code ?? 0);
1069
+ });
1070
+ function shutdown() {
1071
+ console.log("\n Shutting down...");
1072
+ cleanup(watcher, server);
1073
+ process.exit(0);
1074
+ }
1075
+ process.on("SIGINT", shutdown);
1076
+ process.on("SIGTERM", shutdown);
1077
+ }
1078
+ function cleanup(watcher, server) {
1079
+ if (watcher) watcher.stop();
1080
+ if (server && !server.killed) {
1081
+ server.kill("SIGTERM");
1082
+ }
1083
+ }
1084
+ function getVersion() {
1085
+ try {
1086
+ const pkgPath = join2(pkgRoot, "package.json");
1087
+ if (existsSync2(pkgPath)) {
1088
+ const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
1089
+ return pkg.version || "0.0.0";
1090
+ }
1091
+ } catch {
1092
+ }
1093
+ return "0.0.0";
1094
+ }
1095
+ function openBrowser(url) {
1096
+ const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
1097
+ exec(`${cmd} ${url}`, () => {
1098
+ });
1099
+ }
1100
+ main().catch((err) => {
1101
+ console.error("Fatal error:", err);
1102
+ process.exit(1);
1103
+ });
1104
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vYmluL2NsaS50cyIsICIuLi8uLi9jb2xsZWN0b3IvaW5kZXhlci50cyIsICIuLi8uLi9saWIvZGIvc2NoZW1hLnRzIiwgIi4uLy4uL2NvbGxlY3Rvci9tb2RlbC1jb250ZXh0LnRzIiwgIi4uLy4uL2NvbGxlY3Rvci9jbGF1ZGUtY29kZS9wYXJzZXIudHMiLCAiLi4vLi4vY29sbGVjdG9yL3BpL3BhcnNlci50cyIsICIuLi8uLi9jb2xsZWN0b3Ivd2F0Y2hlci50cyIsICIuLi8uLi9saWIvZGIvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogYWdlbnRsZW5zIENMSSBcdTIwMTQgc2luZ2xlIGNvbW1hbmQgdG8gaW5kZXggc2Vzc2lvbnMsIHdhdGNoIGZvciBuZXcgb25lcywgYW5kIHNlcnZlIHRoZSBkYXNoYm9hcmQuXG4gKlxuICogVXNhZ2U6XG4gKiAgIG5weCBhZ2VudGxlbnMgICAgICAgICAgICAgICAgICAgICAjIHN0YXJ0IGV2ZXJ5dGhpbmcgb24gOjMzMzNcbiAqICAgbnB4IGFnZW50bGVucyAtLXBvcnQgNDAwMCAgICAgICAgICMgY3VzdG9tIHBvcnRcbiAqICAgbnB4IGFnZW50bGVucyAtLWRhdGEgfi9teS1kYXRhICAgICMgY3VzdG9tIGRhdGEgZGlyZWN0b3J5XG4gKiAgIG5weCBhZ2VudGxlbnMgLS1uby1vcGVuICAgICAgICAgICAjIGRvbid0IGF1dG8tb3BlbiBicm93c2VyXG4gKi9cblxuaW1wb3J0IHsgam9pbiwgZGlybmFtZSwgcmVzb2x2ZSB9IGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBleGlzdHNTeW5jLCBta2RpclN5bmMsIHJlYWRGaWxlU3luYyB9IGZyb20gXCJmc1wiO1xuaW1wb3J0IHsgaG9tZWRpciB9IGZyb20gXCJvc1wiO1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gXCJ1cmxcIjtcbmltcG9ydCB7IHNwYXduLCBleGVjIH0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IGNyZWF0ZVJlcXVpcmUgfSBmcm9tIFwibW9kdWxlXCI7XG5pbXBvcnQgeyBpbmRleFNlc3Npb25zIH0gZnJvbSBcIi4uL2NvbGxlY3Rvci9pbmRleGVyXCI7XG5pbXBvcnQgeyBjcmVhdGVXYXRjaGVyLCB0eXBlIFdhdGNoZXIgfSBmcm9tIFwiLi4vY29sbGVjdG9yL3dhdGNoZXJcIjtcbmltcG9ydCB7IGdldERiIH0gZnJvbSBcIi4uL2xpYi9kYi9pbmRleFwiO1xuXG4vLyAtLS0gUGFyc2UgQ0xJIGFyZ3MgLS0tXG5cbmNvbnN0IGFyZ3MgPSBwcm9jZXNzLmFyZ3Yuc2xpY2UoMik7XG5cbmZ1bmN0aW9uIGdldEZsYWcobmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBhcmdzLmluY2x1ZGVzKGAtLSR7bmFtZX1gKTtcbn1cblxuZnVuY3Rpb24gZ2V0RmxhZ1ZhbHVlKG5hbWU6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGlkeCA9IGFyZ3MuaW5kZXhPZihgLS0ke25hbWV9YCk7XG4gIGlmIChpZHggPj0gMCAmJiBpZHggKyAxIDwgYXJncy5sZW5ndGgpIHJldHVybiBhcmdzW2lkeCArIDFdO1xuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5pZiAoZ2V0RmxhZyhcImhlbHBcIikgfHwgZ2V0RmxhZyhcImhcIikpIHtcbiAgY29uc29sZS5sb2coYFxuICBhZ2VudGxlbnMgXHUyMDE0IG9ic2VydmFiaWxpdHkgZm9yIEFJIGNvZGluZyBhZ2VudHNcblxuICBVc2FnZTpcbiAgICBucHggYWdlbnRsZW5zIFtvcHRpb25zXVxuXG4gIE9wdGlvbnM6XG4gICAgLS1wb3J0IDxudW1iZXI+ICAgIFBvcnQgZm9yIHRoZSBkYXNoYm9hcmQgKGRlZmF1bHQ6IDMzMzMpXG4gICAgLS1kYXRhIDxwYXRoPiAgICAgIERhdGEgZGlyZWN0b3J5IGZvciB0aGUgU1FMaXRlIERCIChkZWZhdWx0OiB+Ly5hZ2VudGxlbnMpXG4gICAgLS1uby1vcGVuICAgICAgICAgIERvbid0IGF1dG8tb3BlbiB0aGUgYnJvd3NlclxuICAgIC0taGVscCwgLWggICAgICAgICBTaG93IHRoaXMgaGVscCBtZXNzYWdlXG5gKTtcbiAgcHJvY2Vzcy5leGl0KDApO1xufVxuXG5jb25zdCBwb3J0ID0gcGFyc2VJbnQoZ2V0RmxhZ1ZhbHVlKFwicG9ydFwiKSB8fCBcIjMzMzNcIiwgMTApO1xuY29uc3QgZGF0YURpciA9IGdldEZsYWdWYWx1ZShcImRhdGFcIikgfHwgam9pbihob21lZGlyKCksIFwiLmFnZW50bGVuc1wiKTtcbmNvbnN0IG5vT3BlbiA9IGdldEZsYWcoXCJuby1vcGVuXCIpO1xuY29uc3QgZGJQYXRoID0gam9pbihkYXRhRGlyLCBcImFnZW50bGVucy5kYlwiKTtcblxuLy8gLS0tIFJlc29sdmUgcGFja2FnZSByb290ICh3aGVyZSAubmV4dC8gbGl2ZXMpIC0tLVxuXG5jb25zdCBfX2ZpbGVuYW1lID0gZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpO1xuY29uc3QgX19kaXJuYW1lID0gZGlybmFtZShfX2ZpbGVuYW1lKTtcbi8vIEluIHByb2R1Y3Rpb24gKGRpc3QvYmluL2FnZW50bGVucy5tanMpLCBwYWNrYWdlIHJvb3QgaXMgLi4vLi4vXG4vLyBJbiBkZXYgKGJpbi9jbGkudHMpLCBwYWNrYWdlIHJvb3QgaXMgLi4vXG5jb25zdCBwa2dSb290ID0gZXhpc3RzU3luYyhqb2luKF9fZGlybmFtZSwgXCIuLlwiLCBcIi5uZXh0XCIpKVxuICA/IHJlc29sdmUoX19kaXJuYW1lLCBcIi4uXCIpXG4gIDogcmVzb2x2ZShfX2Rpcm5hbWUsIFwiLi5cIiwgXCIuLlwiKTtcblxuLy8gLS0tIFNlc3Npb24gc291cmNlIGRpcmVjdG9yaWVzIC0tLVxuXG5jb25zdCBjbGF1ZGVQcm9qZWN0c0RpciA9IGpvaW4oaG9tZWRpcigpLCBcIi5jbGF1ZGVcIiwgXCJwcm9qZWN0c1wiKTtcbmNvbnN0IHBpU2Vzc2lvbnNEaXIgPSBqb2luKGhvbWVkaXIoKSwgXCIucGlcIiwgXCJhZ2VudFwiLCBcInNlc3Npb25zXCIpO1xuXG4vLyAtLS0gTWFpbiAtLS1cblxuYXN5bmMgZnVuY3Rpb24gbWFpbigpIHtcbiAgLy8gRW5zdXJlIGRhdGEgZGlyZWN0b3J5IGV4aXN0c1xuICBpZiAoIWV4aXN0c1N5bmMoZGF0YURpcikpIHtcbiAgICBta2RpclN5bmMoZGF0YURpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIH1cblxuICAvLyBTZXQgZW52IGZvciB0aGUgTmV4dC5qcyBzZXJ2ZXIgcHJvY2Vzc1xuICBwcm9jZXNzLmVudi5BR0VOVExFTlNfREJfUEFUSCA9IGRiUGF0aDtcblxuICBjb25zb2xlLmxvZyhgXG4gIFxceDFiWzFtYWdlbnRsZW5zXFx4MWJbMG0gdiR7Z2V0VmVyc2lvbigpfVxuXG4gIFx1MjVCOCBEYXNoYm9hcmQ6ICAgXFx4MWJbMzZtaHR0cDovL2xvY2FsaG9zdDoke3BvcnR9XFx4MWJbMG1cbiAgXHUyNUI4IERhdGE6ICAgICAgICAke2RiUGF0aH1cbiAgXHUyNUI4IFdhdGNoaW5nOiAgICAke2NsYXVkZVByb2plY3RzRGlyfVxuICAgICAgICAgICAgICAgICAke3BpU2Vzc2lvbnNEaXJ9XG5gKTtcblxuICAvLyAtLS0gSW5pdGlhbCBpbmRleCAtLS1cblxuICBjb25zdCBkYiA9IGdldERiKCk7XG4gIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG5cbiAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoXCIgIEluZGV4aW5nIHNlc3Npb25zLi4uXCIpO1xuICBjb25zdCByZXN1bHQgPSBpbmRleFNlc3Npb25zKGRiLCB7IGNsYXVkZVByb2plY3RzRGlyLCBwaVNlc3Npb25zRGlyIH0pO1xuICBjb25zdCBlbGFwc2VkID0gKChEYXRlLm5vdygpIC0gc3RhcnRUaW1lKSAvIDEwMDApLnRvRml4ZWQoMSk7XG5cbiAgY29uc3QgdG90YWwgPSByZXN1bHQuaW1wb3J0ZWQgKyByZXN1bHQuc2tpcHBlZDtcbiAgY29uc29sZS5sb2coXG4gICAgYCBmb3VuZCAke3RvdGFsfSBzZXNzaW9uJHt0b3RhbCAhPT0gMSA/IFwic1wiIDogXCJcIn0sICR7cmVzdWx0LmltcG9ydGVkfSBuZXcgKCR7ZWxhcHNlZH1zKWAsXG4gICk7XG5cbiAgaWYgKHJlc3VsdC5lcnJvcnMubGVuZ3RoID4gMCkge1xuICAgIGNvbnNvbGUubG9nKGAgIFx1MjZBMCAke3Jlc3VsdC5lcnJvcnMubGVuZ3RofSBlcnJvciR7cmVzdWx0LmVycm9ycy5sZW5ndGggIT09IDEgPyBcInNcIiA6IFwiXCJ9YCk7XG4gIH1cblxuICAvLyAtLS0gU3RhcnQgd2F0Y2hlciAtLS1cblxuICBjb25zdCB3YXRjaGVyID0gY3JlYXRlV2F0Y2hlcihkYiwge1xuICAgIGNsYXVkZVByb2plY3RzRGlyLFxuICAgIHBpU2Vzc2lvbnNEaXIsXG4gICAgcG9sbEludGVydmFsTXM6IDUwMDAsXG4gIH0pO1xuXG4gIGNvbnNvbGUubG9nKFwiICBXYXRjaGluZyBmb3IgbmV3IHNlc3Npb25zLi4uXFxuXCIpO1xuXG4gIC8vIC0tLSBTdGFydCBOZXh0LmpzIHNlcnZlciAtLS1cblxuICBjb25zdCByZXF1aXJlID0gY3JlYXRlUmVxdWlyZShpbXBvcnQubWV0YS51cmwpO1xuICBjb25zdCBuZXh0QmluID0gcmVxdWlyZS5yZXNvbHZlKFwibmV4dC9kaXN0L2Jpbi9uZXh0XCIpO1xuXG4gIGNvbnN0IHNlcnZlciA9IHNwYXduKHByb2Nlc3MuZXhlY1BhdGgsIFtuZXh0QmluLCBcInN0YXJ0XCIsIFwiLS1wb3J0XCIsIFN0cmluZyhwb3J0KV0sIHtcbiAgICBjd2Q6IHBrZ1Jvb3QsXG4gICAgZW52OiB7XG4gICAgICAuLi5wcm9jZXNzLmVudixcbiAgICAgIEFHRU5UTEVOU19EQl9QQVRIOiBkYlBhdGgsXG4gICAgICBQT1JUOiBTdHJpbmcocG9ydCksXG4gICAgICBIT1NUTkFNRTogXCJsb2NhbGhvc3RcIixcbiAgICB9LFxuICAgIHN0ZGlvOiBbXCJpZ25vcmVcIiwgXCJwaXBlXCIsIFwicGlwZVwiXSxcbiAgfSk7XG5cbiAgbGV0IHNlcnZlclJlYWR5ID0gZmFsc2U7XG5cbiAgc2VydmVyLnN0ZG91dD8ub24oXCJkYXRhXCIsIChkYXRhOiBCdWZmZXIpID0+IHtcbiAgICBjb25zdCB0ZXh0ID0gZGF0YS50b1N0cmluZygpLnRyaW0oKTtcbiAgICBpZiAodGV4dCAmJiAhc2VydmVyUmVhZHkpIHtcbiAgICAgIHNlcnZlclJlYWR5ID0gdHJ1ZTtcbiAgICAgIGlmICghbm9PcGVuKSB7XG4gICAgICAgIG9wZW5Ccm93c2VyKGBodHRwOi8vbG9jYWxob3N0OiR7cG9ydH1gKTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIHNlcnZlci5zdGRlcnI/Lm9uKFwiZGF0YVwiLCAoZGF0YTogQnVmZmVyKSA9PiB7XG4gICAgY29uc3QgdGV4dCA9IGRhdGEudG9TdHJpbmcoKS50cmltKCk7XG4gICAgaWYgKHRleHQpIHtcbiAgICAgIC8vIEZpbHRlciBvdXQgbm9pc3kgTmV4dC5qcyB3YXJuaW5nc1xuICAgICAgaWYgKCF0ZXh0LmluY2x1ZGVzKFwiRXhwZXJpbWVudGFsV2FybmluZ1wiKSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGAgIFtzZXJ2ZXJdICR7dGV4dH1gKTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIHNlcnZlci5vbihcImVycm9yXCIsIChlcnIpID0+IHtcbiAgICBjb25zb2xlLmVycm9yKGAgIEZhaWxlZCB0byBzdGFydCBzZXJ2ZXI6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgY2xlYW51cCh3YXRjaGVyLCBzZXJ2ZXIpO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfSk7XG5cbiAgc2VydmVyLm9uKFwiZXhpdFwiLCAoY29kZSkgPT4ge1xuICAgIGlmIChjb2RlICE9PSAwICYmIGNvZGUgIT09IG51bGwpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoYCAgU2VydmVyIGV4aXRlZCB3aXRoIGNvZGUgJHtjb2RlfWApO1xuICAgIH1cbiAgICBjbGVhbnVwKHdhdGNoZXIsIG51bGwpO1xuICAgIHByb2Nlc3MuZXhpdChjb2RlID8/IDApO1xuICB9KTtcblxuICAvLyAtLS0gR3JhY2VmdWwgc2h1dGRvd24gLS0tXG5cbiAgZnVuY3Rpb24gc2h1dGRvd24oKSB7XG4gICAgY29uc29sZS5sb2coXCJcXG4gIFNodXR0aW5nIGRvd24uLi5cIik7XG4gICAgY2xlYW51cCh3YXRjaGVyLCBzZXJ2ZXIpO1xuICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgfVxuXG4gIHByb2Nlc3Mub24oXCJTSUdJTlRcIiwgc2h1dGRvd24pO1xuICBwcm9jZXNzLm9uKFwiU0lHVEVSTVwiLCBzaHV0ZG93bik7XG59XG5cbmZ1bmN0aW9uIGNsZWFudXAod2F0Y2hlcjogV2F0Y2hlciB8IG51bGwsIHNlcnZlcjogUmV0dXJuVHlwZTx0eXBlb2Ygc3Bhd24+IHwgbnVsbCkge1xuICBpZiAod2F0Y2hlcikgd2F0Y2hlci5zdG9wKCk7XG4gIGlmIChzZXJ2ZXIgJiYgIXNlcnZlci5raWxsZWQpIHtcbiAgICBzZXJ2ZXIua2lsbChcIlNJR1RFUk1cIik7XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0VmVyc2lvbigpOiBzdHJpbmcge1xuICB0cnkge1xuICAgIGNvbnN0IHBrZ1BhdGggPSBqb2luKHBrZ1Jvb3QsIFwicGFja2FnZS5qc29uXCIpO1xuICAgIGlmIChleGlzdHNTeW5jKHBrZ1BhdGgpKSB7XG4gICAgICBjb25zdCBwa2cgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhwa2dQYXRoLCBcInV0Zi04XCIpKTtcbiAgICAgIHJldHVybiBwa2cudmVyc2lvbiB8fCBcIjAuMC4wXCI7XG4gICAgfVxuICB9IGNhdGNoIHt9XG4gIHJldHVybiBcIjAuMC4wXCI7XG59XG5cbmZ1bmN0aW9uIG9wZW5Ccm93c2VyKHVybDogc3RyaW5nKSB7XG4gIGNvbnN0IGNtZCA9XG4gICAgcHJvY2Vzcy5wbGF0Zm9ybSA9PT0gXCJkYXJ3aW5cIiA/IFwib3BlblwiIDogcHJvY2Vzcy5wbGF0Zm9ybSA9PT0gXCJ3aW4zMlwiID8gXCJzdGFydFwiIDogXCJ4ZGctb3BlblwiO1xuXG4gIGV4ZWMoYCR7Y21kfSAke3VybH1gLCAoKSA9PiB7XG4gICAgLy8gU2lsZW50bHkgaWdub3JlIGVycm9ycyAoZS5nLiwgbm8gZGlzcGxheSBzZXJ2ZXIpXG4gIH0pO1xufVxuXG5tYWluKCkuY2F0Y2goKGVycikgPT4ge1xuICBjb25zb2xlLmVycm9yKFwiRmF0YWwgZXJyb3I6XCIsIGVycik7XG4gIHByb2Nlc3MuZXhpdCgxKTtcbn0pO1xuIiwgIi8qKlxuICogVW5pZmllZCBzZXNzaW9uIGluZGV4ZXI6IGRpc2NvdmVycyBhbmQgaW1wb3J0cyBhZ2VudCBzZXNzaW9ucyBpbnRvIGFnZW50bGVucyBEQi5cbiAqL1xuXG5pbXBvcnQgeyByZWFkZGlyU3luYywgcmVhZEZpbGVTeW5jLCBleGlzdHNTeW5jIH0gZnJvbSBcImZzXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IGV4ZWNTeW5jIH0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IHVzZXJJbmZvIH0gZnJvbSBcIm9zXCI7XG5pbXBvcnQgdHlwZSB7IEJldHRlclNRTGl0ZTNEYXRhYmFzZSB9IGZyb20gXCJkcml6emxlLW9ybS9iZXR0ZXItc3FsaXRlM1wiO1xuaW1wb3J0IHsgZXEgfSBmcm9tIFwiZHJpenpsZS1vcm1cIjtcbmltcG9ydCB7IHNlc3Npb25zLCBpbnNlcnRTZXNzaW9uLCBpbnNlcnRFdmVudCwgdXBzZXJ0UHVsbFJlcXVlc3QgfSBmcm9tIFwiQC9saWIvZGIvc2NoZW1hXCI7XG5pbXBvcnQgeyBwYXJzZUNsYXVkZUNvZGVTZXNzaW9uIH0gZnJvbSBcIi4vY2xhdWRlLWNvZGUvcGFyc2VyXCI7XG5pbXBvcnQgeyBwYXJzZVBpU2Vzc2lvbiB9IGZyb20gXCIuL3BpL3BhcnNlclwiO1xuaW1wb3J0IHR5cGUgeyBQYXJzZWRTZXNzaW9uIH0gZnJvbSBcIi4vY2xhdWRlLWNvZGUvcGFyc2VyXCI7XG5cbi8qKiBEZXRlY3QgdXNlciBpZGVudGl0eSBmcm9tIGdpdCBjb25maWcgb3IgT1MsIGNhY2hlZC4gKi9cbmxldCBfY2FjaGVkVXNlcklkOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbmV4cG9ydCBmdW5jdGlvbiBkZXRlY3RVc2VySWQoKTogc3RyaW5nIHtcbiAgaWYgKF9jYWNoZWRVc2VySWQpIHJldHVybiBfY2FjaGVkVXNlcklkO1xuICB0cnkge1xuICAgIF9jYWNoZWRVc2VySWQgPSBleGVjU3luYyhcImdpdCBjb25maWcgdXNlci5lbWFpbFwiLCB7IGVuY29kaW5nOiBcInV0Zi04XCIgfSkudHJpbSgpO1xuICAgIGlmIChfY2FjaGVkVXNlcklkKSByZXR1cm4gX2NhY2hlZFVzZXJJZDtcbiAgfSBjYXRjaCB7XG4gICAgLyogZ2l0IG5vdCBhdmFpbGFibGUgKi9cbiAgfVxuICBfY2FjaGVkVXNlcklkID0gdXNlckluZm8oKS51c2VybmFtZSB8fCBcInVua25vd25cIjtcbiAgcmV0dXJuIF9jYWNoZWRVc2VySWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5kZXhPcHRpb25zIHtcbiAgLyoqIFBhdGggdG8gQ2xhdWRlIENvZGUgcHJvamVjdHMgZGlyZWN0b3J5IChkZWZhdWx0OiB+Ly5jbGF1ZGUvcHJvamVjdHMpICovXG4gIGNsYXVkZVByb2plY3RzRGlyPzogc3RyaW5nO1xuICAvKiogUGF0aCB0byBQaSBzZXNzaW9ucyBkaXJlY3RvcnkgKGRlZmF1bHQ6IH4vLnBpL2FnZW50L3Nlc3Npb25zKSAqL1xuICBwaVNlc3Npb25zRGlyPzogc3RyaW5nO1xuICAvKiogRmlsdGVyIHRvIGEgc3BlY2lmaWMgaGFybmVzcyAqL1xuICBoYXJuZXNzPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEluZGV4UmVzdWx0IHtcbiAgaW1wb3J0ZWQ6IG51bWJlcjtcbiAgc2tpcHBlZDogbnVtYmVyO1xuICBlcnJvcnM6IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIERpc2NvdmVyIENsYXVkZSBDb2RlIHNlc3Npb24gSlNPTkwgZmlsZXMgaW4gdGhlIHByb2plY3RzIGRpcmVjdG9yeS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRpc2NvdmVyQ2xhdWRlQ29kZVNlc3Npb25zKHByb2plY3RzRGlyOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIGlmICghZXhpc3RzU3luYyhwcm9qZWN0c0RpcikpIHJldHVybiBbXTtcblxuICBjb25zdCBmaWxlczogc3RyaW5nW10gPSBbXTtcbiAgdHJ5IHtcbiAgICBjb25zdCBwcm9qZWN0RGlycyA9IHJlYWRkaXJTeW5jKHByb2plY3RzRGlyLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gICAgZm9yIChjb25zdCBkaXIgb2YgcHJvamVjdERpcnMpIHtcbiAgICAgIGlmICghZGlyLmlzRGlyZWN0b3J5KCkpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgZGlyUGF0aCA9IGpvaW4ocHJvamVjdHNEaXIsIGRpci5uYW1lKTtcbiAgICAgIGNvbnN0IGRpckVudHJpZXMgPSByZWFkZGlyU3luYyhkaXJQYXRoLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGRpckVudHJpZXMpIHtcbiAgICAgICAgaWYgKGVudHJ5LmlzRmlsZSgpICYmIGVudHJ5Lm5hbWUuZW5kc1dpdGgoXCIuanNvbmxcIikpIHtcbiAgICAgICAgICBmaWxlcy5wdXNoKGpvaW4oZGlyUGF0aCwgZW50cnkubmFtZSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9IGNhdGNoIHtcbiAgICAvLyBEaXJlY3Rvcnkgbm90IHJlYWRhYmxlXG4gIH1cbiAgcmV0dXJuIGZpbGVzO1xufVxuXG4vKipcbiAqIERpc2NvdmVyIFBpIHNlc3Npb24gSlNPTkwgZmlsZXMgaW4gdGhlIHNlc3Npb25zIGRpcmVjdG9yeS5cbiAqIFBpIHN0b3JlcyBzZXNzaW9ucyBhdCB+Ly5waS9hZ2VudC9zZXNzaW9ucy88cHJvamVjdC1kaXI+Lzx0aW1lc3RhbXA+Xzx1dWlkPi5qc29ubFxuICovXG5leHBvcnQgZnVuY3Rpb24gZGlzY292ZXJQaVNlc3Npb25zKHNlc3Npb25zRGlyOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIGlmICghZXhpc3RzU3luYyhzZXNzaW9uc0RpcikpIHJldHVybiBbXTtcblxuICBjb25zdCBmaWxlczogc3RyaW5nW10gPSBbXTtcbiAgdHJ5IHtcbiAgICBjb25zdCBwcm9qZWN0RGlycyA9IHJlYWRkaXJTeW5jKHNlc3Npb25zRGlyLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gICAgZm9yIChjb25zdCBkaXIgb2YgcHJvamVjdERpcnMpIHtcbiAgICAgIGlmICghZGlyLmlzRGlyZWN0b3J5KCkpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgZGlyUGF0aCA9IGpvaW4oc2Vzc2lvbnNEaXIsIGRpci5uYW1lKTtcbiAgICAgIGNvbnN0IGRpckVudHJpZXMgPSByZWFkZGlyU3luYyhkaXJQYXRoLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGRpckVudHJpZXMpIHtcbiAgICAgICAgaWYgKGVudHJ5LmlzRmlsZSgpICYmIGVudHJ5Lm5hbWUuZW5kc1dpdGgoXCIuanNvbmxcIikpIHtcbiAgICAgICAgICBmaWxlcy5wdXNoKGpvaW4oZGlyUGF0aCwgZW50cnkubmFtZSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9IGNhdGNoIHtcbiAgICAvLyBEaXJlY3Rvcnkgbm90IHJlYWRhYmxlXG4gIH1cbiAgcmV0dXJuIGZpbGVzO1xufVxuXG4vKipcbiAqIEltcG9ydCBhIHBhcnNlZCBzZXNzaW9uIGludG8gdGhlIERCLiBSZXR1cm5zIHRydWUgaWYgaW1wb3J0ZWQsIGZhbHNlIGlmIHNraXBwZWQuXG4gKi9cbmZ1bmN0aW9uIGltcG9ydFBhcnNlZFNlc3Npb24oXG4gIGRiOiBCZXR0ZXJTUUxpdGUzRGF0YWJhc2UsXG4gIHBhcnNlZDogUGFyc2VkU2Vzc2lvbixcbiAgcmVzdWx0OiBJbmRleFJlc3VsdCxcbik6IGJvb2xlYW4ge1xuICBpZiAoIXBhcnNlZC5zZXNzaW9uSWQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBDaGVjayBpZiBhbHJlYWR5IGltcG9ydGVkXG4gIGNvbnN0IGV4aXN0aW5nID0gZGIuc2VsZWN0KCkuZnJvbShzZXNzaW9ucykud2hlcmUoZXEoc2Vzc2lvbnMuaWQsIHBhcnNlZC5zZXNzaW9uSWQpKS5nZXQoKTtcbiAgaWYgKGV4aXN0aW5nKSB7XG4gICAgcmVzdWx0LnNraXBwZWQrKztcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBJbnNlcnQgc2Vzc2lvblxuICBjb25zdCB1c2VySWQgPSBwYXJzZWQudXNlcklkIHx8IGRldGVjdFVzZXJJZCgpO1xuICBpbnNlcnRTZXNzaW9uKGRiLCB7XG4gICAgaWQ6IHBhcnNlZC5zZXNzaW9uSWQsXG4gICAgdGVhbUlkOiBcImRlZmF1bHRcIixcbiAgICB1c2VySWQsXG4gICAgcHJvamVjdDogcGFyc2VkLnByb2plY3QsXG4gICAgZ2l0UmVwbzogbnVsbCxcbiAgICBnaXRCcmFuY2g6IHBhcnNlZC5naXRCcmFuY2gsXG4gICAgcGlWZXJzaW9uOiBwYXJzZWQudmVyc2lvbixcbiAgICBza2lsbHNVc2VkOiBbXSxcbiAgICBtb2RlbDogcGFyc2VkLm1vZGVsLFxuICAgIGhhcm5lc3M6IHBhcnNlZC5oYXJuZXNzLFxuICAgIHN0YXJ0ZWRBdDogcGFyc2VkLnN0YXJ0ZWRBdCxcbiAgfSk7XG5cbiAgLy8gVXBkYXRlIHNlc3Npb24gZW5kIGlmIHdlIGhhdmUgaXRcbiAgaWYgKHBhcnNlZC5lbmRlZEF0KSB7XG4gICAgZGIudXBkYXRlKHNlc3Npb25zKVxuICAgICAgLnNldCh7IGVuZGVkQXQ6IHBhcnNlZC5lbmRlZEF0LCBzdGF0dXM6IFwiY29tcGxldGVkXCIgfSlcbiAgICAgIC53aGVyZShlcShzZXNzaW9ucy5pZCwgcGFyc2VkLnNlc3Npb25JZCkpXG4gICAgICAucnVuKCk7XG4gIH1cblxuICAvLyBJbnNlcnQgYWxsIGV2ZW50c1xuICBmb3IgKGNvbnN0IGV2ZW50IG9mIHBhcnNlZC5ldmVudHMpIHtcbiAgICBpbnNlcnRFdmVudChkYiwge1xuICAgICAgc2Vzc2lvbklkOiBwYXJzZWQuc2Vzc2lvbklkLFxuICAgICAgZXZlbnRUeXBlOiBldmVudC5ldmVudFR5cGUsXG4gICAgICB0aW1lc3RhbXA6IGV2ZW50LnRpbWVzdGFtcCxcbiAgICAgIHBheWxvYWQ6IGV2ZW50LnBheWxvYWQsXG4gICAgfSk7XG5cbiAgICAvLyBQb3B1bGF0ZSBwdWxsX3JlcXVlc3RzIHRhYmxlIGZyb20gcHJfb3BlbmVkIGV2ZW50c1xuICAgIGlmIChldmVudC5ldmVudFR5cGUgPT09IFwicHJfb3BlbmVkXCIgJiYgZXZlbnQucGF5bG9hZC5wcl91cmwpIHtcbiAgICAgIHVwc2VydFB1bGxSZXF1ZXN0KGRiLCB7XG4gICAgICAgIHNlc3Npb25JZDogcGFyc2VkLnNlc3Npb25JZCxcbiAgICAgICAgcmVwbzogZXZlbnQucGF5bG9hZC5yZXBvIHx8IFwiXCIsXG4gICAgICAgIGJyYW5jaDogcGFyc2VkLmdpdEJyYW5jaCB8fCBcIlwiLFxuICAgICAgICBwck51bWJlcjogZXZlbnQucGF5bG9hZC5wcl9udW1iZXIgfHwgMCxcbiAgICAgICAgcHJVcmw6IGV2ZW50LnBheWxvYWQucHJfdXJsLFxuICAgICAgICBwclRpdGxlOiBcIlwiLCAvLyBub3QgYXZhaWxhYmxlIGZyb20gYmFzaCBvdXRwdXRcbiAgICAgICAgc3RhdHVzOiBcIm9wZW5cIixcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHJlc3VsdC5pbXBvcnRlZCsrO1xuICByZXR1cm4gdHJ1ZTtcbn1cblxuLyoqXG4gKiBJbXBvcnQgc2Vzc2lvbnMgZnJvbSBkaXNjb3ZlcmVkIGZpbGVzIGludG8gdGhlIGFnZW50bGVucyBEQi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluZGV4U2Vzc2lvbnMoZGI6IEJldHRlclNRTGl0ZTNEYXRhYmFzZSwgb3B0aW9uczogSW5kZXhPcHRpb25zID0ge30pOiBJbmRleFJlc3VsdCB7XG4gIGNvbnN0IHJlc3VsdDogSW5kZXhSZXN1bHQgPSB7IGltcG9ydGVkOiAwLCBza2lwcGVkOiAwLCBlcnJvcnM6IFtdIH07XG4gIGNvbnN0IGhhcm5lc3MgPSBvcHRpb25zLmhhcm5lc3M7XG5cbiAgLy8gQ2xhdWRlIENvZGUgc2Vzc2lvbnNcbiAgaWYgKCFoYXJuZXNzIHx8IGhhcm5lc3MgPT09IFwiY2xhdWRlLWNvZGVcIikge1xuICAgIGNvbnN0IHByb2plY3RzRGlyID1cbiAgICAgIG9wdGlvbnMuY2xhdWRlUHJvamVjdHNEaXIgfHwgam9pbihwcm9jZXNzLmVudi5IT01FIHx8IFwiflwiLCBcIi5jbGF1ZGVcIiwgXCJwcm9qZWN0c1wiKTtcbiAgICBjb25zdCBmaWxlcyA9IGRpc2NvdmVyQ2xhdWRlQ29kZVNlc3Npb25zKHByb2plY3RzRGlyKTtcblxuICAgIGZvciAoY29uc3QgZmlsZVBhdGggb2YgZmlsZXMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGpzb25sID0gcmVhZEZpbGVTeW5jKGZpbGVQYXRoLCBcInV0Zi04XCIpO1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUNsYXVkZUNvZGVTZXNzaW9uKGpzb25sKTtcbiAgICAgICAgaWYgKCFwYXJzZWQuc2Vzc2lvbklkKSB7XG4gICAgICAgICAgcmVzdWx0LmVycm9ycy5wdXNoKGBObyBzZXNzaW9uIElEIGZvdW5kIGluICR7ZmlsZVBhdGh9YCk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaW1wb3J0UGFyc2VkU2Vzc2lvbihkYiwgcGFyc2VkLCByZXN1bHQpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHJlc3VsdC5lcnJvcnMucHVzaChgRXJyb3IgcHJvY2Vzc2luZyAke2ZpbGVQYXRofTogJHtlcnJ9YCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gUGkgc2Vzc2lvbnNcbiAgaWYgKCFoYXJuZXNzIHx8IGhhcm5lc3MgPT09IFwicGlcIikge1xuICAgIGNvbnN0IHNlc3Npb25zRGlyID1cbiAgICAgIG9wdGlvbnMucGlTZXNzaW9uc0RpciB8fCBqb2luKHByb2Nlc3MuZW52LkhPTUUgfHwgXCJ+XCIsIFwiLnBpXCIsIFwiYWdlbnRcIiwgXCJzZXNzaW9uc1wiKTtcbiAgICBjb25zdCBmaWxlcyA9IGRpc2NvdmVyUGlTZXNzaW9ucyhzZXNzaW9uc0Rpcik7XG5cbiAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIGZpbGVzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBqc29ubCA9IHJlYWRGaWxlU3luYyhmaWxlUGF0aCwgXCJ1dGYtOFwiKTtcbiAgICAgICAgY29uc3QgZGlyTmFtZSA9IGpvaW4oZmlsZVBhdGgsIFwiLi5cIikuc3BsaXQoXCIvXCIpLnBvcCgpIHx8IFwiXCI7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlUGlTZXNzaW9uKGpzb25sLCBkaXJOYW1lKTtcbiAgICAgICAgaWYgKCFwYXJzZWQuc2Vzc2lvbklkKSB7XG4gICAgICAgICAgcmVzdWx0LmVycm9ycy5wdXNoKGBObyBzZXNzaW9uIElEIGZvdW5kIGluICR7ZmlsZVBhdGh9YCk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaW1wb3J0UGFyc2VkU2Vzc2lvbihkYiwgcGFyc2VkLCByZXN1bHQpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHJlc3VsdC5lcnJvcnMucHVzaChgRXJyb3IgcHJvY2Vzc2luZyAke2ZpbGVQYXRofTogJHtlcnJ9YCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cbiIsICJpbXBvcnQgeyBzcWwsIGVxLCBhbmQsIGd0ZSwgbHRlLCBkZXNjLCBhc2MsIGNvdW50IH0gZnJvbSBcImRyaXp6bGUtb3JtXCI7XG5pbXBvcnQgeyBzcWxpdGVUYWJsZSwgdGV4dCwgaW50ZWdlciB9IGZyb20gXCJkcml6emxlLW9ybS9zcWxpdGUtY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBCZXR0ZXJTUUxpdGUzRGF0YWJhc2UgfSBmcm9tIFwiZHJpenpsZS1vcm0vYmV0dGVyLXNxbGl0ZTNcIjtcblxuLy8gLS0tIFRhYmxlIERlZmluaXRpb25zIC0tLVxuXG5leHBvcnQgY29uc3Qgc2Vzc2lvbnMgPSBzcWxpdGVUYWJsZShcInNlc3Npb25zXCIsIHtcbiAgaWQ6IHRleHQoXCJpZFwiKS5wcmltYXJ5S2V5KCksXG4gIHRlYW1JZDogdGV4dChcInRlYW1faWRcIikubm90TnVsbCgpLFxuICB1c2VySWQ6IHRleHQoXCJ1c2VyX2lkXCIpLm5vdE51bGwoKSxcbiAgcHJvamVjdDogdGV4dChcInByb2plY3RcIikubm90TnVsbCgpLFxuICBnaXRSZXBvOiB0ZXh0KFwiZ2l0X3JlcG9cIiksXG4gIGdpdEJyYW5jaDogdGV4dChcImdpdF9icmFuY2hcIiksXG4gIHBpVmVyc2lvbjogdGV4dChcInBpX3ZlcnNpb25cIikubm90TnVsbCgpLmRlZmF1bHQoXCJcIiksXG4gIHNraWxsc1VzZWQ6IHRleHQoXCJza2lsbHNfdXNlZFwiKS5ub3ROdWxsKCkuZGVmYXVsdChcIltdXCIpLFxuICBtb2RlbDogdGV4dChcIm1vZGVsXCIpLFxuICBoYXJuZXNzOiB0ZXh0KFwiaGFybmVzc1wiKS5ub3ROdWxsKCkuZGVmYXVsdChcInBpXCIpLFxuICBzdGFydGVkQXQ6IHRleHQoXCJzdGFydGVkX2F0XCIpLm5vdE51bGwoKSxcbiAgZW5kZWRBdDogdGV4dChcImVuZGVkX2F0XCIpLFxuICBzdGF0dXM6IHRleHQoXCJzdGF0dXNcIikubm90TnVsbCgpLmRlZmF1bHQoXCJhY3RpdmVcIiksXG4gIGNyZWF0ZWRBdDogdGV4dChcImNyZWF0ZWRfYXRcIilcbiAgICAubm90TnVsbCgpXG4gICAgLmRlZmF1bHQoc3FsYChkYXRldGltZSgnbm93JykpYCksXG59KTtcblxuZXhwb3J0IGNvbnN0IGV2ZW50cyA9IHNxbGl0ZVRhYmxlKFwiZXZlbnRzXCIsIHtcbiAgaWQ6IGludGVnZXIoXCJpZFwiKS5wcmltYXJ5S2V5KHsgYXV0b0luY3JlbWVudDogdHJ1ZSB9KSxcbiAgc2Vzc2lvbklkOiB0ZXh0KFwic2Vzc2lvbl9pZFwiKS5ub3ROdWxsKCksXG4gIGV2ZW50VHlwZTogdGV4dChcImV2ZW50X3R5cGVcIikubm90TnVsbCgpLFxuICB0aW1lc3RhbXA6IHRleHQoXCJ0aW1lc3RhbXBcIikubm90TnVsbCgpLFxuICBwYXlsb2FkOiB0ZXh0KFwicGF5bG9hZFwiKS5ub3ROdWxsKCkuZGVmYXVsdChcInt9XCIpLFxuICBjcmVhdGVkQXQ6IHRleHQoXCJjcmVhdGVkX2F0XCIpXG4gICAgLm5vdE51bGwoKVxuICAgIC5kZWZhdWx0KHNxbGAoZGF0ZXRpbWUoJ25vdycpKWApLFxufSk7XG5cbmV4cG9ydCBjb25zdCBwdWxsUmVxdWVzdHMgPSBzcWxpdGVUYWJsZShcInB1bGxfcmVxdWVzdHNcIiwge1xuICBpZDogaW50ZWdlcihcImlkXCIpLnByaW1hcnlLZXkoeyBhdXRvSW5jcmVtZW50OiB0cnVlIH0pLFxuICBzZXNzaW9uSWQ6IHRleHQoXCJzZXNzaW9uX2lkXCIpLm5vdE51bGwoKSxcbiAgcmVwbzogdGV4dChcInJlcG9cIikubm90TnVsbCgpLFxuICBicmFuY2g6IHRleHQoXCJicmFuY2hcIikubm90TnVsbCgpLFxuICBwck51bWJlcjogaW50ZWdlcihcInByX251bWJlclwiKS5ub3ROdWxsKCksXG4gIHByVXJsOiB0ZXh0KFwicHJfdXJsXCIpLm5vdE51bGwoKSxcbiAgcHJUaXRsZTogdGV4dChcInByX3RpdGxlXCIpLm5vdE51bGwoKS5kZWZhdWx0KFwiXCIpLFxuICBzdGF0dXM6IHRleHQoXCJzdGF0dXNcIikubm90TnVsbCgpLmRlZmF1bHQoXCJvcGVuXCIpLFxuICBtZXJnZWRBdDogdGV4dChcIm1lcmdlZF9hdFwiKSxcbiAgcmV2aWV3c0FwcHJvdmVkOiBpbnRlZ2VyKFwicmV2aWV3c19hcHByb3ZlZFwiKS5ub3ROdWxsKCkuZGVmYXVsdCgwKSxcbiAgcmV2aWV3c0NoYW5nZXNSZXF1ZXN0ZWQ6IGludGVnZXIoXCJyZXZpZXdzX2NoYW5nZXNfcmVxdWVzdGVkXCIpLm5vdE51bGwoKS5kZWZhdWx0KDApLFxuICByZXZpZXdDb21tZW50czogaW50ZWdlcihcInJldmlld19jb21tZW50c1wiKS5ub3ROdWxsKCkuZGVmYXVsdCgwKSxcbiAgY29tbWl0c0FmdGVyUmV2aWV3OiBpbnRlZ2VyKFwiY29tbWl0c19hZnRlcl9yZXZpZXdcIikubm90TnVsbCgpLmRlZmF1bHQoMCksXG4gIGZpcnN0UmV2aWV3QXQ6IHRleHQoXCJmaXJzdF9yZXZpZXdfYXRcIiksXG4gIHRpbWVUb01lcmdlSG91cnM6IHRleHQoXCJ0aW1lX3RvX21lcmdlX2hvdXJzXCIpLCAvLyBzdG9yZWQgYXMgdGV4dCBmb3IgU1FMaXRlIHJlYWwgY29tcGF0XG4gIGNoZWNrZWRBdDogdGV4dChcImNoZWNrZWRfYXRcIiksXG4gIGNyZWF0ZWRBdDogdGV4dChcImNyZWF0ZWRfYXRcIilcbiAgICAubm90TnVsbCgpXG4gICAgLmRlZmF1bHQoc3FsYChkYXRldGltZSgnbm93JykpYCksXG59KTtcblxuLy8gLS0tIFR5cGVzIC0tLVxuXG5leHBvcnQgaW50ZXJmYWNlIFNlc3Npb25JbnB1dCB7XG4gIGlkOiBzdHJpbmc7XG4gIHRlYW1JZDogc3RyaW5nO1xuICB1c2VySWQ6IHN0cmluZztcbiAgcHJvamVjdDogc3RyaW5nO1xuICBnaXRSZXBvOiBzdHJpbmcgfCBudWxsO1xuICBnaXRCcmFuY2g6IHN0cmluZyB8IG51bGw7XG4gIHBpVmVyc2lvbjogc3RyaW5nO1xuICBza2lsbHNVc2VkOiBzdHJpbmdbXTtcbiAgbW9kZWw/OiBzdHJpbmcgfCBudWxsO1xuICBoYXJuZXNzPzogc3RyaW5nO1xuICBzdGFydGVkQXQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFdmVudElucHV0IHtcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIGV2ZW50VHlwZTogc3RyaW5nO1xuICB0aW1lc3RhbXA6IHN0cmluZztcbiAgcGF5bG9hZDogb2JqZWN0O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNlc3Npb25Sb3cge1xuICBpZDogc3RyaW5nO1xuICB0ZWFtSWQ6IHN0cmluZztcbiAgdXNlcklkOiBzdHJpbmc7XG4gIHByb2plY3Q6IHN0cmluZztcbiAgZ2l0UmVwbzogc3RyaW5nIHwgbnVsbDtcbiAgZ2l0QnJhbmNoOiBzdHJpbmcgfCBudWxsO1xuICBwaVZlcnNpb246IHN0cmluZztcbiAgc2tpbGxzVXNlZDogc3RyaW5nW107XG4gIG1vZGVsOiBzdHJpbmcgfCBudWxsO1xuICBoYXJuZXNzOiBzdHJpbmc7XG4gIHN0YXJ0ZWRBdDogc3RyaW5nO1xuICBlbmRlZEF0OiBzdHJpbmcgfCBudWxsO1xuICBzdGF0dXM6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFdmVudFJvdyB7XG4gIGlkOiBudW1iZXI7XG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICBldmVudFR5cGU6IHN0cmluZztcbiAgdGltZXN0YW1wOiBzdHJpbmc7XG4gIHBheWxvYWQ6IGFueTtcbn1cblxuLy8gLS0tIFF1ZXJ5IEhlbHBlcnMgLS0tXG5cbnR5cGUgREIgPSBCZXR0ZXJTUUxpdGUzRGF0YWJhc2U7XG5cbmV4cG9ydCBmdW5jdGlvbiBpbnNlcnRTZXNzaW9uKGRiOiBEQiwgaW5wdXQ6IFNlc3Npb25JbnB1dCk6IHZvaWQge1xuICBkYi5pbnNlcnQoc2Vzc2lvbnMpXG4gICAgLnZhbHVlcyh7XG4gICAgICBpZDogaW5wdXQuaWQsXG4gICAgICB0ZWFtSWQ6IGlucHV0LnRlYW1JZCxcbiAgICAgIHVzZXJJZDogaW5wdXQudXNlcklkLFxuICAgICAgcHJvamVjdDogaW5wdXQucHJvamVjdCxcbiAgICAgIGdpdFJlcG86IGlucHV0LmdpdFJlcG8sXG4gICAgICBnaXRCcmFuY2g6IGlucHV0LmdpdEJyYW5jaCxcbiAgICAgIHBpVmVyc2lvbjogaW5wdXQucGlWZXJzaW9uLFxuICAgICAgc2tpbGxzVXNlZDogSlNPTi5zdHJpbmdpZnkoaW5wdXQuc2tpbGxzVXNlZCksXG4gICAgICBtb2RlbDogaW5wdXQubW9kZWwsXG4gICAgICBoYXJuZXNzOiBpbnB1dC5oYXJuZXNzIHx8IFwicGlcIixcbiAgICAgIHN0YXJ0ZWRBdDogaW5wdXQuc3RhcnRlZEF0LFxuICAgIH0pXG4gICAgLnJ1bigpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlU2Vzc2lvbkVuZChkYjogREIsIHNlc3Npb25JZDogc3RyaW5nLCBlbmRlZEF0OiBzdHJpbmcsIHN0YXR1czogc3RyaW5nKTogdm9pZCB7XG4gIGRiLnVwZGF0ZShzZXNzaW9ucykuc2V0KHsgZW5kZWRBdCwgc3RhdHVzIH0pLndoZXJlKGVxKHNlc3Npb25zLmlkLCBzZXNzaW9uSWQpKS5ydW4oKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZVNlc3Npb25Nb2RlbChkYjogREIsIHNlc3Npb25JZDogc3RyaW5nLCBtb2RlbDogc3RyaW5nKTogdm9pZCB7XG4gIGRiLnVwZGF0ZShzZXNzaW9ucykuc2V0KHsgbW9kZWwgfSkud2hlcmUoZXEoc2Vzc2lvbnMuaWQsIHNlc3Npb25JZCkpLnJ1bigpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdXBzZXJ0U2Vzc2lvbihkYjogREIsIGlucHV0OiBTZXNzaW9uSW5wdXQpOiB2b2lkIHtcbiAgLy8gVHJ5IGluc2VydCwgb24gY29uZmxpY3QgdXBkYXRlXG4gIGNvbnN0IGV4aXN0aW5nID0gZGIuc2VsZWN0KCkuZnJvbShzZXNzaW9ucykud2hlcmUoZXEoc2Vzc2lvbnMuaWQsIGlucHV0LmlkKSkuZ2V0KCk7XG5cbiAgaWYgKGV4aXN0aW5nKSB7XG4gICAgZGIudXBkYXRlKHNlc3Npb25zKVxuICAgICAgLnNldCh7XG4gICAgICAgIHVzZXJJZDogaW5wdXQudXNlcklkLFxuICAgICAgICBwcm9qZWN0OiBpbnB1dC5wcm9qZWN0LFxuICAgICAgICBnaXRSZXBvOiBpbnB1dC5naXRSZXBvLFxuICAgICAgICBnaXRCcmFuY2g6IGlucHV0LmdpdEJyYW5jaCxcbiAgICAgICAgcGlWZXJzaW9uOiBpbnB1dC5waVZlcnNpb24sXG4gICAgICAgIHNraWxsc1VzZWQ6IEpTT04uc3RyaW5naWZ5KGlucHV0LnNraWxsc1VzZWQpLFxuICAgICAgICBtb2RlbDogaW5wdXQubW9kZWwsXG4gICAgICB9KVxuICAgICAgLndoZXJlKGVxKHNlc3Npb25zLmlkLCBpbnB1dC5pZCkpXG4gICAgICAucnVuKCk7XG4gIH0gZWxzZSB7XG4gICAgaW5zZXJ0U2Vzc2lvbihkYiwgaW5wdXQpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbnNlcnRFdmVudChkYjogREIsIGlucHV0OiBFdmVudElucHV0KTogdm9pZCB7XG4gIGRiLmluc2VydChldmVudHMpXG4gICAgLnZhbHVlcyh7XG4gICAgICBzZXNzaW9uSWQ6IGlucHV0LnNlc3Npb25JZCxcbiAgICAgIGV2ZW50VHlwZTogaW5wdXQuZXZlbnRUeXBlLFxuICAgICAgdGltZXN0YW1wOiBpbnB1dC50aW1lc3RhbXAsXG4gICAgICBwYXlsb2FkOiBKU09OLnN0cmluZ2lmeShpbnB1dC5wYXlsb2FkKSxcbiAgICB9KVxuICAgIC5ydW4oKTtcbn1cblxuZnVuY3Rpb24gcGFyc2VTZXNzaW9uUm93KHJvdzogYW55KTogU2Vzc2lvblJvdyB7XG4gIHJldHVybiB7XG4gICAgaWQ6IHJvdy5pZCxcbiAgICB0ZWFtSWQ6IHJvdy50ZWFtSWQsXG4gICAgdXNlcklkOiByb3cudXNlcklkLFxuICAgIHByb2plY3Q6IHJvdy5wcm9qZWN0LFxuICAgIGdpdFJlcG86IHJvdy5naXRSZXBvLFxuICAgIGdpdEJyYW5jaDogcm93LmdpdEJyYW5jaCxcbiAgICBwaVZlcnNpb246IHJvdy5waVZlcnNpb24sXG4gICAgc2tpbGxzVXNlZDogSlNPTi5wYXJzZShyb3cuc2tpbGxzVXNlZCB8fCBcIltdXCIpLFxuICAgIG1vZGVsOiByb3cubW9kZWwgfHwgbnVsbCxcbiAgICBoYXJuZXNzOiByb3cuaGFybmVzcyB8fCBcInBpXCIsXG4gICAgc3RhcnRlZEF0OiByb3cuc3RhcnRlZEF0LFxuICAgIGVuZGVkQXQ6IHJvdy5lbmRlZEF0LFxuICAgIHN0YXR1czogcm93LnN0YXR1cyxcbiAgfTtcbn1cblxuZnVuY3Rpb24gcGFyc2VFdmVudFJvdyhyb3c6IGFueSk6IEV2ZW50Um93IHtcbiAgcmV0dXJuIHtcbiAgICBpZDogcm93LmlkLFxuICAgIHNlc3Npb25JZDogcm93LnNlc3Npb25JZCxcbiAgICBldmVudFR5cGU6IHJvdy5ldmVudFR5cGUsXG4gICAgdGltZXN0YW1wOiByb3cudGltZXN0YW1wLFxuICAgIHBheWxvYWQ6IEpTT04ucGFyc2Uocm93LnBheWxvYWQgfHwgXCJ7fVwiKSxcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNlc3Npb25XaXRoRXZlbnRzKFxuICBkYjogREIsXG4gIHNlc3Npb25JZDogc3RyaW5nLFxuKTogeyBzZXNzaW9uOiBTZXNzaW9uUm93OyBldmVudHM6IEV2ZW50Um93W10gfSB8IG51bGwge1xuICBjb25zdCBzZXNzaW9uUm93ID0gZGIuc2VsZWN0KCkuZnJvbShzZXNzaW9ucykud2hlcmUoZXEoc2Vzc2lvbnMuaWQsIHNlc3Npb25JZCkpLmdldCgpO1xuXG4gIGlmICghc2Vzc2lvblJvdykgcmV0dXJuIG51bGw7XG5cbiAgY29uc3QgZXZlbnRSb3dzID0gZGJcbiAgICAuc2VsZWN0KClcbiAgICAuZnJvbShldmVudHMpXG4gICAgLndoZXJlKGVxKGV2ZW50cy5zZXNzaW9uSWQsIHNlc3Npb25JZCkpXG4gICAgLm9yZGVyQnkoYXNjKGV2ZW50cy50aW1lc3RhbXApLCBhc2MoZXZlbnRzLmlkKSlcbiAgICAuYWxsKCk7XG5cbiAgcmV0dXJuIHtcbiAgICBzZXNzaW9uOiBwYXJzZVNlc3Npb25Sb3coc2Vzc2lvblJvdyksXG4gICAgZXZlbnRzOiBldmVudFJvd3MubWFwKHBhcnNlRXZlbnRSb3cpLFxuICB9O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIExpc3RTZXNzaW9uc0ZpbHRlciB7XG4gIHRlYW1JZDogc3RyaW5nO1xuICB1c2VySWQ/OiBzdHJpbmc7XG4gIHByb2plY3Q/OiBzdHJpbmc7XG4gIGhhcm5lc3M/OiBzdHJpbmc7XG4gIHN0YXR1cz86IHN0cmluZztcbiAgZnJvbT86IHN0cmluZztcbiAgdG8/OiBzdHJpbmc7XG4gIGxpbWl0PzogbnVtYmVyO1xuICBvZmZzZXQ/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBsaXN0U2Vzc2lvbnMoXG4gIGRiOiBEQixcbiAgZmlsdGVyOiBMaXN0U2Vzc2lvbnNGaWx0ZXIsXG4pOiB7IHNlc3Npb25zOiBTZXNzaW9uUm93W107IHRvdGFsOiBudW1iZXIgfSB7XG4gIGNvbnN0IGNvbmRpdGlvbnMgPSBbZXEoc2Vzc2lvbnMudGVhbUlkLCBmaWx0ZXIudGVhbUlkKV07XG5cbiAgaWYgKGZpbHRlci51c2VySWQpIGNvbmRpdGlvbnMucHVzaChlcShzZXNzaW9ucy51c2VySWQsIGZpbHRlci51c2VySWQpKTtcbiAgaWYgKGZpbHRlci5wcm9qZWN0KSBjb25kaXRpb25zLnB1c2goZXEoc2Vzc2lvbnMucHJvamVjdCwgZmlsdGVyLnByb2plY3QpKTtcbiAgaWYgKGZpbHRlci5oYXJuZXNzKSBjb25kaXRpb25zLnB1c2goZXEoc2Vzc2lvbnMuaGFybmVzcywgZmlsdGVyLmhhcm5lc3MpKTtcbiAgaWYgKGZpbHRlci5zdGF0dXMpIGNvbmRpdGlvbnMucHVzaChlcShzZXNzaW9ucy5zdGF0dXMsIGZpbHRlci5zdGF0dXMpKTtcbiAgaWYgKGZpbHRlci5mcm9tKSBjb25kaXRpb25zLnB1c2goZ3RlKHNlc3Npb25zLnN0YXJ0ZWRBdCwgZmlsdGVyLmZyb20pKTtcbiAgaWYgKGZpbHRlci50bykgY29uZGl0aW9ucy5wdXNoKGx0ZShzZXNzaW9ucy5zdGFydGVkQXQsIGZpbHRlci50bykpO1xuXG4gIGNvbnN0IHdoZXJlID0gY29uZGl0aW9ucy5sZW5ndGggPT09IDEgPyBjb25kaXRpb25zWzBdIDogYW5kKC4uLmNvbmRpdGlvbnMpO1xuXG4gIC8vIENvdW50IHRvdGFsXG4gIGNvbnN0IGNvdW50UmVzdWx0ID0gZGIuc2VsZWN0KHsgY291bnQ6IGNvdW50KCkgfSkuZnJvbShzZXNzaW9ucykud2hlcmUod2hlcmUhKS5nZXQoKTtcbiAgY29uc3QgdG90YWwgPSBjb3VudFJlc3VsdD8uY291bnQgPz8gMDtcblxuICAvLyBGZXRjaCBwYWdlXG4gIGNvbnN0IGxpbWl0ID0gTWF0aC5taW4oZmlsdGVyLmxpbWl0ID8/IDUwLCAyMDApO1xuICBjb25zdCBvZmZzZXQgPSBmaWx0ZXIub2Zmc2V0ID8/IDA7XG5cbiAgY29uc3Qgcm93cyA9IGRiXG4gICAgLnNlbGVjdCgpXG4gICAgLmZyb20oc2Vzc2lvbnMpXG4gICAgLndoZXJlKHdoZXJlISlcbiAgICAub3JkZXJCeShkZXNjKHNlc3Npb25zLnN0YXJ0ZWRBdCkpXG4gICAgLmxpbWl0KGxpbWl0KVxuICAgIC5vZmZzZXQob2Zmc2V0KVxuICAgIC5hbGwoKTtcblxuICByZXR1cm4ge1xuICAgIHNlc3Npb25zOiByb3dzLm1hcChwYXJzZVNlc3Npb25Sb3cpLFxuICAgIHRvdGFsLFxuICB9O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRva2VuU3RhdHMge1xuICB0b3RhbElucHV0VG9rZW5zOiBudW1iZXI7XG4gIHRvdGFsT3V0cHV0VG9rZW5zOiBudW1iZXI7XG4gIHRvdGFsQ2FjaGVSZWFkVG9rZW5zOiBudW1iZXI7XG4gIHRvdGFsQ2FjaGVXcml0ZVRva2VuczogbnVtYmVyO1xuICB0b3RhbFRva2VuczogbnVtYmVyO1xuICB0b3RhbENvc3RVc2Q6IG51bWJlcjtcbiAgbGxtQ2FsbENvdW50OiBudW1iZXI7XG4gIGF2Z0lucHV0VG9rZW5zUGVyQ2FsbDogbnVtYmVyO1xuICBwZWFrSW5wdXRUb2tlbnM6IG51bWJlcjtcbiAgY29udGV4dFdpbmRvdzogbnVtYmVyIHwgbnVsbDtcbiAgY29udGV4dFV0aWxpemF0aW9uUGN0OiBudW1iZXIgfCBudWxsO1xuICBtb2RlbDogc3RyaW5nIHwgbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFRva2VuU3RhdHMoZGI6IERCLCBzZXNzaW9uSWQ6IHN0cmluZyk6IFRva2VuU3RhdHMge1xuICBjb25zdCBldmVudFJvd3MgPSBkYlxuICAgIC5zZWxlY3QoKVxuICAgIC5mcm9tKGV2ZW50cylcbiAgICAud2hlcmUoYW5kKGVxKGV2ZW50cy5zZXNzaW9uSWQsIHNlc3Npb25JZCksIGVxKGV2ZW50cy5ldmVudFR5cGUsIFwibGxtX3Jlc3BvbnNlXCIpKSlcbiAgICAub3JkZXJCeShhc2MoZXZlbnRzLnRpbWVzdGFtcCkpXG4gICAgLmFsbCgpO1xuXG4gIGxldCB0b3RhbElucHV0ID0gMDtcbiAgbGV0IHRvdGFsT3V0cHV0ID0gMDtcbiAgbGV0IHRvdGFsQ2FjaGVSZWFkID0gMDtcbiAgbGV0IHRvdGFsQ2FjaGVXcml0ZSA9IDA7XG4gIGxldCB0b3RhbFRva2Vuc1N1bSA9IDA7XG4gIGxldCB0b3RhbENvc3QgPSAwO1xuICBsZXQgcGVha0lucHV0ID0gMDtcbiAgbGV0IGNvbnRleHRXaW5kb3c6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICBjb25zdCBtb2RlbENvdW50cyA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG5cbiAgZm9yIChjb25zdCByb3cgb2YgZXZlbnRSb3dzKSB7XG4gICAgY29uc3QgcGF5bG9hZCA9IEpTT04ucGFyc2Uocm93LnBheWxvYWQgfHwgXCJ7fVwiKTtcbiAgICB0b3RhbElucHV0ICs9IHBheWxvYWQuaW5wdXRfdG9rZW5zIHx8IDA7XG4gICAgdG90YWxPdXRwdXQgKz0gcGF5bG9hZC5vdXRwdXRfdG9rZW5zIHx8IDA7XG4gICAgdG90YWxDYWNoZVJlYWQgKz0gcGF5bG9hZC5jYWNoZV9yZWFkX3Rva2VucyB8fCAwO1xuICAgIHRvdGFsQ2FjaGVXcml0ZSArPSBwYXlsb2FkLmNhY2hlX3dyaXRlX3Rva2VucyB8fCAwO1xuICAgIHRvdGFsVG9rZW5zU3VtICs9IHBheWxvYWQudG90YWxfdG9rZW5zIHx8IDA7XG4gICAgdG90YWxDb3N0ICs9IHBheWxvYWQudG90YWxfY29zdF91c2QgfHwgMDtcblxuICAgIGlmICgocGF5bG9hZC5pbnB1dF90b2tlbnMgfHwgMCkgPiBwZWFrSW5wdXQpIHtcbiAgICAgIHBlYWtJbnB1dCA9IHBheWxvYWQuaW5wdXRfdG9rZW5zIHx8IDA7XG4gICAgfVxuXG4gICAgaWYgKHBheWxvYWQuY29udGV4dF93aW5kb3cpIHtcbiAgICAgIGNvbnRleHRXaW5kb3cgPSBwYXlsb2FkLmNvbnRleHRfd2luZG93O1xuICAgIH1cblxuICAgIGlmIChwYXlsb2FkLm1vZGVsKSB7XG4gICAgICBtb2RlbENvdW50cy5zZXQocGF5bG9hZC5tb2RlbCwgKG1vZGVsQ291bnRzLmdldChwYXlsb2FkLm1vZGVsKSB8fCAwKSArIDEpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGxsbUNhbGxDb3VudCA9IGV2ZW50Um93cy5sZW5ndGg7XG5cbiAgLy8gRmluZCBtb3N0LXVzZWQgbW9kZWxcbiAgbGV0IG1vZGVsOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgbGV0IG1heE1vZGVsQ291bnQgPSAwO1xuICBtb2RlbENvdW50cy5mb3JFYWNoKChjLCBtKSA9PiB7XG4gICAgaWYgKGMgPiBtYXhNb2RlbENvdW50KSB7XG4gICAgICBtb2RlbCA9IG07XG4gICAgICBtYXhNb2RlbENvdW50ID0gYztcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgdG90YWxJbnB1dFRva2VuczogdG90YWxJbnB1dCxcbiAgICB0b3RhbE91dHB1dFRva2VuczogdG90YWxPdXRwdXQsXG4gICAgdG90YWxDYWNoZVJlYWRUb2tlbnM6IHRvdGFsQ2FjaGVSZWFkLFxuICAgIHRvdGFsQ2FjaGVXcml0ZVRva2VuczogdG90YWxDYWNoZVdyaXRlLFxuICAgIHRvdGFsVG9rZW5zOiB0b3RhbFRva2Vuc1N1bSxcbiAgICB0b3RhbENvc3RVc2Q6IHRvdGFsQ29zdCxcbiAgICBsbG1DYWxsQ291bnQsXG4gICAgYXZnSW5wdXRUb2tlbnNQZXJDYWxsOiBsbG1DYWxsQ291bnQgPiAwID8gTWF0aC5yb3VuZCh0b3RhbElucHV0IC8gbGxtQ2FsbENvdW50KSA6IDAsXG4gICAgcGVha0lucHV0VG9rZW5zOiBwZWFrSW5wdXQsXG4gICAgY29udGV4dFdpbmRvdyxcbiAgICBjb250ZXh0VXRpbGl6YXRpb25QY3Q6XG4gICAgICBjb250ZXh0V2luZG93ICYmIHBlYWtJbnB1dCA+IDAgPyBNYXRoLnJvdW5kKChwZWFrSW5wdXQgLyBjb250ZXh0V2luZG93KSAqIDEwMDAwKSAvIDEwMCA6IG51bGwsXG4gICAgbW9kZWwsXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRFdmVudENvdW50c0J5VHlwZShkYjogREIsIHNlc3Npb25JZDogc3RyaW5nKTogUmVjb3JkPHN0cmluZywgbnVtYmVyPiB7XG4gIGNvbnN0IHJvd3MgPSBkYlxuICAgIC5zZWxlY3Qoe1xuICAgICAgZXZlbnRUeXBlOiBldmVudHMuZXZlbnRUeXBlLFxuICAgICAgY291bnQ6IGNvdW50KCksXG4gICAgfSlcbiAgICAuZnJvbShldmVudHMpXG4gICAgLndoZXJlKGVxKGV2ZW50cy5zZXNzaW9uSWQsIHNlc3Npb25JZCkpXG4gICAgLmdyb3VwQnkoZXZlbnRzLmV2ZW50VHlwZSlcbiAgICAuYWxsKCk7XG5cbiAgY29uc3QgY291bnRzOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+ID0ge1xuICAgIHVzZXJfcHJvbXB0OiAwLFxuICAgIHRvb2xfY2FsbDogMCxcbiAgICBlcnJvcjogMCxcbiAgICBmaWxlX2NoYW5nZTogMCxcbiAgICBoZWFydGJlYXQ6IDAsXG4gICAgc2Vzc2lvbl9zdGFydDogMCxcbiAgICBzZXNzaW9uX2VuZDogMCxcbiAgfTtcblxuICBmb3IgKGNvbnN0IHJvdyBvZiByb3dzKSB7XG4gICAgY291bnRzW3Jvdy5ldmVudFR5cGVdID0gcm93LmNvdW50O1xuICB9XG5cbiAgcmV0dXJuIGNvdW50cztcbn1cblxuLy8gLS0tIFBSIEhlbHBlcnMgLS0tXG5cbmV4cG9ydCBpbnRlcmZhY2UgUHVsbFJlcXVlc3RJbnB1dCB7XG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICByZXBvOiBzdHJpbmc7XG4gIGJyYW5jaDogc3RyaW5nO1xuICBwck51bWJlcjogbnVtYmVyO1xuICBwclVybDogc3RyaW5nO1xuICBwclRpdGxlOiBzdHJpbmc7XG4gIHN0YXR1czogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFB1bGxSZXF1ZXN0Um93IHtcbiAgaWQ6IG51bWJlcjtcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIHJlcG86IHN0cmluZztcbiAgYnJhbmNoOiBzdHJpbmc7XG4gIHByTnVtYmVyOiBudW1iZXI7XG4gIHByVXJsOiBzdHJpbmc7XG4gIHByVGl0bGU6IHN0cmluZztcbiAgc3RhdHVzOiBzdHJpbmc7XG4gIG1lcmdlZEF0OiBzdHJpbmcgfCBudWxsO1xuICByZXZpZXdzQXBwcm92ZWQ6IG51bWJlcjtcbiAgcmV2aWV3c0NoYW5nZXNSZXF1ZXN0ZWQ6IG51bWJlcjtcbiAgcmV2aWV3Q29tbWVudHM6IG51bWJlcjtcbiAgY29tbWl0c0FmdGVyUmV2aWV3OiBudW1iZXI7XG4gIGZpcnN0UmV2aWV3QXQ6IHN0cmluZyB8IG51bGw7XG4gIHRpbWVUb01lcmdlSG91cnM6IG51bWJlciB8IG51bGw7XG4gIGNoZWNrZWRBdDogc3RyaW5nIHwgbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVwc2VydFB1bGxSZXF1ZXN0KGRiOiBEQiwgaW5wdXQ6IFB1bGxSZXF1ZXN0SW5wdXQpOiB2b2lkIHtcbiAgY29uc3QgZXhpc3RpbmcgPSBkYlxuICAgIC5zZWxlY3QoKVxuICAgIC5mcm9tKHB1bGxSZXF1ZXN0cylcbiAgICAud2hlcmUoXG4gICAgICBhbmQoZXEocHVsbFJlcXVlc3RzLnNlc3Npb25JZCwgaW5wdXQuc2Vzc2lvbklkKSwgZXEocHVsbFJlcXVlc3RzLnByTnVtYmVyLCBpbnB1dC5wck51bWJlcikpLFxuICAgIClcbiAgICAuZ2V0KCk7XG5cbiAgaWYgKGV4aXN0aW5nKSB7XG4gICAgZGIudXBkYXRlKHB1bGxSZXF1ZXN0cylcbiAgICAgIC5zZXQoe1xuICAgICAgICBzdGF0dXM6IGlucHV0LnN0YXR1cyxcbiAgICAgICAgcHJUaXRsZTogaW5wdXQucHJUaXRsZSxcbiAgICAgICAgY2hlY2tlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICB9KVxuICAgICAgLndoZXJlKGVxKHB1bGxSZXF1ZXN0cy5pZCwgZXhpc3RpbmcuaWQpKVxuICAgICAgLnJ1bigpO1xuICB9IGVsc2Uge1xuICAgIGRiLmluc2VydChwdWxsUmVxdWVzdHMpXG4gICAgICAudmFsdWVzKHtcbiAgICAgICAgc2Vzc2lvbklkOiBpbnB1dC5zZXNzaW9uSWQsXG4gICAgICAgIHJlcG86IGlucHV0LnJlcG8sXG4gICAgICAgIGJyYW5jaDogaW5wdXQuYnJhbmNoLFxuICAgICAgICBwck51bWJlcjogaW5wdXQucHJOdW1iZXIsXG4gICAgICAgIHByVXJsOiBpbnB1dC5wclVybCxcbiAgICAgICAgcHJUaXRsZTogaW5wdXQucHJUaXRsZSxcbiAgICAgICAgc3RhdHVzOiBpbnB1dC5zdGF0dXMsXG4gICAgICB9KVxuICAgICAgLnJ1bigpO1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHJVcGRhdGVEYXRhIHtcbiAgc3RhdHVzPzogc3RyaW5nO1xuICBtZXJnZWRBdD86IHN0cmluZztcbiAgcmV2aWV3c0FwcHJvdmVkPzogbnVtYmVyO1xuICByZXZpZXdzQ2hhbmdlc1JlcXVlc3RlZD86IG51bWJlcjtcbiAgcmV2aWV3Q29tbWVudHM/OiBudW1iZXI7XG4gIGNvbW1pdHNBZnRlclJldmlldz86IG51bWJlcjtcbiAgZmlyc3RSZXZpZXdBdD86IHN0cmluZztcbiAgdGltZVRvTWVyZ2VIb3Vycz86IHN0cmluZztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZVB1bGxSZXF1ZXN0KGRiOiBEQiwgaWQ6IG51bWJlciwgZGF0YTogUHJVcGRhdGVEYXRhKTogdm9pZCB7XG4gIGRiLnVwZGF0ZShwdWxsUmVxdWVzdHMpXG4gICAgLnNldCh7XG4gICAgICAuLi5kYXRhLFxuICAgICAgY2hlY2tlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgfSlcbiAgICAud2hlcmUoZXEocHVsbFJlcXVlc3RzLmlkLCBpZCkpXG4gICAgLnJ1bigpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0T3BlblB1bGxSZXF1ZXN0cyhkYjogREIpOiBQdWxsUmVxdWVzdFJvd1tdIHtcbiAgcmV0dXJuIGRiXG4gICAgLnNlbGVjdCgpXG4gICAgLmZyb20ocHVsbFJlcXVlc3RzKVxuICAgIC53aGVyZShlcShwdWxsUmVxdWVzdHMuc3RhdHVzLCBcIm9wZW5cIikpXG4gICAgLmFsbCgpIGFzIFB1bGxSZXF1ZXN0Um93W107XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQdWxsUmVxdWVzdHNGb3JTZXNzaW9uKGRiOiBEQiwgc2Vzc2lvbklkOiBzdHJpbmcpOiBQdWxsUmVxdWVzdFJvd1tdIHtcbiAgcmV0dXJuIGRiXG4gICAgLnNlbGVjdCgpXG4gICAgLmZyb20ocHVsbFJlcXVlc3RzKVxuICAgIC53aGVyZShlcShwdWxsUmVxdWVzdHMuc2Vzc2lvbklkLCBzZXNzaW9uSWQpKVxuICAgIC5hbGwoKSBhcyBQdWxsUmVxdWVzdFJvd1tdO1xufVxuIiwgIi8qKlxuICogS25vd24gY29udGV4dCB3aW5kb3cgc2l6ZXMgZm9yIGNvbW1vbiBtb2RlbHMuXG4gKiBVc2VkIHRvIGNvbXB1dGUgY29udGV4dCB1dGlsaXphdGlvbiBwZXJjZW50YWdlLlxuICovXG5cbmNvbnN0IENPTlRFWFRfV0lORE9XUzogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHtcbiAgLy8gQ2xhdWRlIDRcbiAgXCJjbGF1ZGUtb3B1cy00LTZcIjogMjAwMDAwLFxuICBcImNsYXVkZS1zb25uZXQtNC02XCI6IDIwMDAwMCxcblxuICAvLyBDbGF1ZGUgMy41K1xuICBcImNsYXVkZS1vcHVzLTQtNVwiOiAyMDAwMDAsXG4gIFwiY2xhdWRlLXNvbm5ldC00LTVcIjogMjAwMDAwLFxuICBcImNsYXVkZS1oYWlrdS00LTUtMjAyNTEwMDFcIjogMjAwMDAwLFxuXG4gIC8vIENsYXVkZSAzXG4gIFwiY2xhdWRlLTMtb3B1cy0yMDI0MDIyOVwiOiAyMDAwMDAsXG4gIFwiY2xhdWRlLTMtc29ubmV0LTIwMjQwMjI5XCI6IDIwMDAwMCxcbiAgXCJjbGF1ZGUtMy1oYWlrdS0yMDI0MDMwN1wiOiAyMDAwMDAsXG5cbiAgLy8gT3BlbkFJXG4gIFwiZ3B0LTRvXCI6IDEyODAwMCxcbiAgXCJncHQtNC10dXJib1wiOiAxMjgwMDAsXG4gIFwiZ3B0LTRcIjogODE5MixcbiAgXCJncHQtNS4zLWNvZGV4XCI6IDIwMDAwMCxcbiAgXCJvMS1wcmV2aWV3XCI6IDEyODAwMCxcbiAgXCJvMS1taW5pXCI6IDEyODAwMCxcbn07XG5cbi8qKlxuICogTG9vayB1cCBrbm93biBjb250ZXh0IHdpbmRvdyBmb3IgYSBtb2RlbC5cbiAqIERvZXMgcHJlZml4IG1hdGNoaW5nOiBcImNsYXVkZS1zb25uZXQtNC02XCIgbWF0Y2hlcyBcImNsYXVkZS1zb25uZXQtNC02XCIuXG4gKiBSZXR1cm5zIG51bGwgaWYgbW9kZWwgaXMgdW5rbm93bi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENvbnRleHRXaW5kb3cobW9kZWw6IHN0cmluZyB8IG51bGwpOiBudW1iZXIgfCBudWxsIHtcbiAgaWYgKCFtb2RlbCkgcmV0dXJuIG51bGw7XG5cbiAgLy8gRXhhY3QgbWF0Y2hcbiAgaWYgKENPTlRFWFRfV0lORE9XU1ttb2RlbF0pIHJldHVybiBDT05URVhUX1dJTkRPV1NbbW9kZWxdO1xuXG4gIC8vIFByZWZpeCBtYXRjaCAoaGFuZGxlcyB2ZXJzaW9uZWQgbW9kZWwgbmFtZXMgbGlrZSBcImNsYXVkZS1zb25uZXQtNC02LTIwMjYwMzAxXCIpXG4gIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKENPTlRFWFRfV0lORE9XUykpIHtcbiAgICBpZiAobW9kZWwuc3RhcnRzV2l0aChrZXkpKSByZXR1cm4gdmFsdWU7XG4gIH1cblxuICAvLyBGYW1pbHkgbWF0Y2hcbiAgaWYgKG1vZGVsLmluY2x1ZGVzKFwiY2xhdWRlXCIpKSByZXR1cm4gMjAwMDAwO1xuICBpZiAobW9kZWwuaW5jbHVkZXMoXCJncHQtNFwiKSkgcmV0dXJuIDEyODAwMDtcblxuICByZXR1cm4gbnVsbDtcbn1cbiIsICIvKipcbiAqIFBhcnNlIGEgQ2xhdWRlIENvZGUgc2Vzc2lvbiBKU09OTCBzdHJpbmcgaW50byBhZ2VudGxlbnMgZXZlbnRzLlxuICovXG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFyc2VkRXZlbnQge1xuICBldmVudFR5cGU6IHN0cmluZztcbiAgdGltZXN0YW1wOiBzdHJpbmc7XG4gIHBheWxvYWQ6IFJlY29yZDxzdHJpbmcsIGFueT47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFyc2VkU2Vzc2lvbiB7XG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICBwcm9qZWN0OiBzdHJpbmc7XG4gIGdpdEJyYW5jaDogc3RyaW5nIHwgbnVsbDtcbiAgaGFybmVzczogc3RyaW5nO1xuICBtb2RlbDogc3RyaW5nIHwgbnVsbDtcbiAgdmVyc2lvbjogc3RyaW5nO1xuICB1c2VySWQ6IHN0cmluZztcbiAgc3RhcnRlZEF0OiBzdHJpbmc7XG4gIGVuZGVkQXQ6IHN0cmluZztcbiAgZXZlbnRzOiBQYXJzZWRFdmVudFtdO1xuICB0b3RhbElucHV0VG9rZW5zOiBudW1iZXI7XG4gIHRvdGFsT3V0cHV0VG9rZW5zOiBudW1iZXI7XG4gIHRvdGFsQ2FjaGVSZWFkVG9rZW5zOiBudW1iZXI7XG4gIHRvdGFsQ2FjaGVXcml0ZVRva2VuczogbnVtYmVyO1xuICB1c2VkU3ViYWdlbnRzOiBib29sZWFuO1xufVxuXG5pbnRlcmZhY2UgVG9vbFVzZUl0ZW0ge1xuICB0eXBlOiBcInRvb2xfdXNlXCI7XG4gIGlkOiBzdHJpbmc7XG4gIG5hbWU6IHN0cmluZztcbiAgaW5wdXQ6IFJlY29yZDxzdHJpbmcsIGFueT47XG59XG5cbmludGVyZmFjZSBUb29sUmVzdWx0SXRlbSB7XG4gIHR5cGU6IFwidG9vbF9yZXN1bHRcIjtcbiAgdG9vbF91c2VfaWQ6IHN0cmluZztcbiAgY29udGVudDogc3RyaW5nO1xuICBpc19lcnJvcj86IGJvb2xlYW47XG59XG5cbmltcG9ydCB7IGdldENvbnRleHRXaW5kb3cgfSBmcm9tIFwiLi4vbW9kZWwtY29udGV4dFwiO1xuXG5jb25zdCBTVUJBR0VOVF9UT09MUyA9IG5ldyBTZXQoW1wiVGFza1wiLCBcIkFnZW50XCJdKTtcblxuLyoqXG4gKiBEZXJpdmUgYSBwcm9qZWN0IG5hbWUgZnJvbSB0aGUgY3dkIHBhdGguXG4gKiBlLmcuIFwiL1VzZXJzL2Rldi9teS1wcm9qZWN0XCIgXHUyMTkyIFwibXktcHJvamVjdFwiXG4gKi9cbmZ1bmN0aW9uIHByb2plY3RGcm9tQ3dkKGN3ZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcGFydHMgPSBjd2QucmVwbGFjZSgvXFwvKyQvLCBcIlwiKS5zcGxpdChcIi9cIik7XG4gIHJldHVybiBwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXSB8fCBjd2Q7XG59XG5cbi8qKlxuICogU3VtbWFyaXplIHRvb2wgaW5wdXQgZm9yIGRpc3BsYXkuXG4gKi9cbi8qKiBHZXQgZmlsZSBwYXRoIGZyb20gdG9vbCBhcmdzIFx1MjAxNCBDQyB1c2VzIGZpbGVfcGF0aCwgUGkgdXNlcyBwYXRoLiAqL1xuZnVuY3Rpb24gZ2V0RmlsZVBhdGgoaW5wdXQ6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBzdHJpbmcgfCBudWxsIHtcbiAgcmV0dXJuIGlucHV0LmZpbGVfcGF0aCB8fCBpbnB1dC5wYXRoIHx8IG51bGw7XG59XG5cbmZ1bmN0aW9uIHN1bW1hcml6ZVRvb2xJbnB1dChuYW1lOiBzdHJpbmcsIGlucHV0OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogc3RyaW5nIHtcbiAgaWYgKG5hbWUgPT09IFwiQmFzaFwiICYmIGlucHV0LmNvbW1hbmQpIHtcbiAgICByZXR1cm4gU3RyaW5nKGlucHV0LmNvbW1hbmQpLnNsaWNlKDAsIDIwMCk7XG4gIH1cbiAgY29uc3QgZmlsZVBhdGggPSBnZXRGaWxlUGF0aChpbnB1dCk7XG4gIGlmICgobmFtZSA9PT0gXCJXcml0ZVwiIHx8IG5hbWUgPT09IFwiRWRpdFwiIHx8IG5hbWUgPT09IFwiTXVsdGlFZGl0XCIpICYmIGZpbGVQYXRoKSB7XG4gICAgcmV0dXJuIGZpbGVQYXRoO1xuICB9XG4gIGlmIChuYW1lID09PSBcIlJlYWRcIiAmJiBmaWxlUGF0aCkge1xuICAgIHJldHVybiBmaWxlUGF0aDtcbiAgfVxuICBpZiAoKG5hbWUgPT09IFwiVGFza1wiIHx8IG5hbWUgPT09IFwiQWdlbnRcIikgJiYgaW5wdXQuZGVzY3JpcHRpb24pIHtcbiAgICByZXR1cm4gU3RyaW5nKGlucHV0LmRlc2NyaXB0aW9uKS5zbGljZSgwLCAyMDApO1xuICB9XG4gIGlmICgobmFtZSA9PT0gXCJUYXNrXCIgfHwgbmFtZSA9PT0gXCJBZ2VudFwiKSAmJiBpbnB1dC5wcm9tcHQpIHtcbiAgICByZXR1cm4gU3RyaW5nKGlucHV0LnByb21wdCkuc2xpY2UoMCwgMjAwKTtcbiAgfVxuICAvLyBHZW5lcmljOiBmaXJzdCBzdHJpbmcgdmFsdWVcbiAgZm9yIChjb25zdCB2YWwgb2YgT2JqZWN0LnZhbHVlcyhpbnB1dCkpIHtcbiAgICBpZiAodHlwZW9mIHZhbCA9PT0gXCJzdHJpbmdcIiAmJiB2YWwubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIHZhbC5zbGljZSgwLCAyMDApO1xuICAgIH1cbiAgfVxuICByZXR1cm4gXCJcIjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlQ2xhdWRlQ29kZVNlc3Npb24oanNvbmw6IHN0cmluZyk6IFBhcnNlZFNlc3Npb24ge1xuICBjb25zdCBsaW5lcyA9IGpzb25sXG4gICAgLnNwbGl0KFwiXFxuXCIpXG4gICAgLmZpbHRlcigobCkgPT4gbC50cmltKCkpXG4gICAgLm1hcCgobCkgPT4gSlNPTi5wYXJzZShsKSk7XG5cbiAgY29uc3QgZXZlbnRzOiBQYXJzZWRFdmVudFtdID0gW107XG4gIGxldCBzZXNzaW9uSWQgPSBcIlwiO1xuICBsZXQgcHJvamVjdCA9IFwiXCI7XG4gIGxldCBnaXRCcmFuY2g6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBsZXQgbW9kZWw6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBsZXQgdmVyc2lvbiA9IFwiXCI7XG4gIGxldCB1c2VySWQgPSBcIlwiO1xuICBsZXQgc3RhcnRlZEF0ID0gXCJcIjtcbiAgbGV0IGVuZGVkQXQgPSBcIlwiO1xuICBsZXQgdXNlZFN1YmFnZW50cyA9IGZhbHNlO1xuXG4gIGxldCB0b3RhbElucHV0VG9rZW5zID0gMDtcbiAgbGV0IHRvdGFsT3V0cHV0VG9rZW5zID0gMDtcbiAgbGV0IHRvdGFsQ2FjaGVSZWFkVG9rZW5zID0gMDtcbiAgbGV0IHRvdGFsQ2FjaGVXcml0ZVRva2VucyA9IDA7XG5cbiAgLy8gQnVpbGQgYSBtYXAgb2YgdG9vbF91c2VfaWQgXHUyMTkyIHRvb2xfcmVzdWx0IGZvciBtYXRjaGluZ1xuICBjb25zdCB0b29sUmVzdWx0cyA9IG5ldyBNYXA8c3RyaW5nLCBUb29sUmVzdWx0SXRlbT4oKTtcbiAgZm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG4gICAgaWYgKGxpbmUudHlwZSA9PT0gXCJ1c2VyXCIpIHtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBsaW5lLm1lc3NhZ2U/LmNvbnRlbnQ7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShjb250ZW50KSkge1xuICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgY29udGVudCkge1xuICAgICAgICAgIGlmIChpdGVtLnR5cGUgPT09IFwidG9vbF9yZXN1bHRcIiAmJiBpdGVtLnRvb2xfdXNlX2lkKSB7XG4gICAgICAgICAgICB0b29sUmVzdWx0cy5zZXQoaXRlbS50b29sX3VzZV9pZCwgaXRlbSBhcyBUb29sUmVzdWx0SXRlbSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG4gICAgY29uc3QgdHMgPSBsaW5lLnRpbWVzdGFtcDtcbiAgICBpZiAoIXRzKSBjb250aW51ZTtcblxuICAgIC8vIFRyYWNrIHRpbWVzdGFtcHNcbiAgICBpZiAoIXN0YXJ0ZWRBdCB8fCB0cyA8IHN0YXJ0ZWRBdCkgc3RhcnRlZEF0ID0gdHM7XG4gICAgaWYgKCFlbmRlZEF0IHx8IHRzID4gZW5kZWRBdCkgZW5kZWRBdCA9IHRzO1xuXG4gICAgLy8gRXh0cmFjdCBzZXNzaW9uIG1ldGFkYXRhIGZyb20gZmlyc3QgdXNlciBtZXNzYWdlXG4gICAgaWYgKGxpbmUudHlwZSA9PT0gXCJ1c2VyXCIgJiYgbGluZS5zZXNzaW9uSWQgJiYgIXNlc3Npb25JZCkge1xuICAgICAgc2Vzc2lvbklkID0gbGluZS5zZXNzaW9uSWQ7XG4gICAgICBwcm9qZWN0ID0gcHJvamVjdEZyb21Dd2QobGluZS5jd2QgfHwgXCJcIik7XG4gICAgICBnaXRCcmFuY2ggPSBsaW5lLmdpdEJyYW5jaCB8fCBudWxsO1xuICAgICAgdmVyc2lvbiA9IGxpbmUudmVyc2lvbiB8fCBcIlwiO1xuICAgICAgdXNlcklkID0gbGluZS5tZXNzYWdlPy5jb250ZW50Py51c2VyX2lkIHx8IFwiXCI7XG4gICAgfVxuXG4gICAgLy8gVXNlciBwcm9tcHRzOiBvbmx5IGV4dGVybmFsLCB3aXRoIHN0cmluZyBjb250ZW50IChub3QgdG9vbF9yZXN1bHQgYXJyYXlzKVxuICAgIGlmIChsaW5lLnR5cGUgPT09IFwidXNlclwiICYmIGxpbmUudXNlclR5cGUgPT09IFwiZXh0ZXJuYWxcIikge1xuICAgICAgY29uc3QgY29udGVudCA9IGxpbmUubWVzc2FnZT8uY29udGVudDtcbiAgICAgIGlmICh0eXBlb2YgY29udGVudCA9PT0gXCJzdHJpbmdcIiAmJiBjb250ZW50LnRyaW0oKSkge1xuICAgICAgICBldmVudHMucHVzaCh7XG4gICAgICAgICAgZXZlbnRUeXBlOiBcInVzZXJfcHJvbXB0XCIsXG4gICAgICAgICAgdGltZXN0YW1wOiB0cyxcbiAgICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgICBwcm9tcHRfdGV4dDogY29udGVudCxcbiAgICAgICAgICAgIHByb21wdF9sZW5ndGg6IGNvbnRlbnQubGVuZ3RoLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFzc2lzdGFudCBtZXNzYWdlczogZXh0cmFjdCBsbG1fcmVzcG9uc2UgKyB0b29sX2NhbGwgZXZlbnRzXG4gICAgaWYgKGxpbmUudHlwZSA9PT0gXCJhc3Npc3RhbnRcIikge1xuICAgICAgY29uc3QgbXNnID0gbGluZS5tZXNzYWdlIHx8IHt9O1xuICAgICAgY29uc3QgdXNhZ2UgPSBtc2cudXNhZ2UgfHwge307XG5cbiAgICAgIC8vIEV4dHJhY3QgbW9kZWxcbiAgICAgIGlmIChtc2cubW9kZWwgJiYgIW1vZGVsKSB7XG4gICAgICAgIG1vZGVsID0gbXNnLm1vZGVsO1xuICAgICAgfVxuXG4gICAgICAvLyBMTE0gcmVzcG9uc2UgZXZlbnRcbiAgICAgIGNvbnN0IGlucHV0VG9rZW5zID0gdXNhZ2UuaW5wdXRfdG9rZW5zIHx8IDA7XG4gICAgICBjb25zdCBvdXRwdXRUb2tlbnMgPSB1c2FnZS5vdXRwdXRfdG9rZW5zIHx8IDA7XG4gICAgICBjb25zdCBjYWNoZVJlYWQgPSB1c2FnZS5jYWNoZV9yZWFkX2lucHV0X3Rva2VucyB8fCAwO1xuICAgICAgY29uc3QgY2FjaGVXcml0ZSA9IHVzYWdlLmNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2VucyB8fCAwO1xuXG4gICAgICB0b3RhbElucHV0VG9rZW5zICs9IGlucHV0VG9rZW5zO1xuICAgICAgdG90YWxPdXRwdXRUb2tlbnMgKz0gb3V0cHV0VG9rZW5zO1xuICAgICAgdG90YWxDYWNoZVJlYWRUb2tlbnMgKz0gY2FjaGVSZWFkO1xuICAgICAgdG90YWxDYWNoZVdyaXRlVG9rZW5zICs9IGNhY2hlV3JpdGU7XG5cbiAgICAgIGNvbnN0IHJlc3BvbnNlTW9kZWwgPSBtc2cubW9kZWwgfHwgbW9kZWw7XG4gICAgICBjb25zdCBjb250ZXh0V2luZG93ID0gZ2V0Q29udGV4dFdpbmRvdyhyZXNwb25zZU1vZGVsKTtcblxuICAgICAgZXZlbnRzLnB1c2goe1xuICAgICAgICBldmVudFR5cGU6IFwibGxtX3Jlc3BvbnNlXCIsXG4gICAgICAgIHRpbWVzdGFtcDogdHMsXG4gICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICBtb2RlbDogcmVzcG9uc2VNb2RlbCxcbiAgICAgICAgICBpbnB1dF90b2tlbnM6IGlucHV0VG9rZW5zLFxuICAgICAgICAgIG91dHB1dF90b2tlbnM6IG91dHB1dFRva2VucyxcbiAgICAgICAgICBjYWNoZV9yZWFkX3Rva2VuczogY2FjaGVSZWFkLFxuICAgICAgICAgIGNhY2hlX3dyaXRlX3Rva2VuczogY2FjaGVXcml0ZSxcbiAgICAgICAgICB0b3RhbF90b2tlbnM6IGlucHV0VG9rZW5zICsgb3V0cHV0VG9rZW5zLFxuICAgICAgICAgIHN0b3BfcmVhc29uOiBtc2cuc3RvcF9yZWFzb24gfHwgbnVsbCxcbiAgICAgICAgICAuLi4oY29udGV4dFdpbmRvdyA/IHsgY29udGV4dF93aW5kb3c6IGNvbnRleHRXaW5kb3cgfSA6IHt9KSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBFeHRyYWN0IHRvb2xfdXNlIGl0ZW1zIGZyb20gY29udGVudFxuICAgICAgY29uc3QgY29udGVudCA9IG1zZy5jb250ZW50IHx8IFtdO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29udGVudCkpIHtcbiAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIGNvbnRlbnQpIHtcbiAgICAgICAgICBpZiAoaXRlbS50eXBlID09PSBcInRvb2xfdXNlXCIpIHtcbiAgICAgICAgICAgIGNvbnN0IHRvb2xVc2UgPSBpdGVtIGFzIFRvb2xVc2VJdGVtO1xuICAgICAgICAgICAgY29uc3QgdG9vbFJlc3VsdCA9IHRvb2xSZXN1bHRzLmdldCh0b29sVXNlLmlkKTtcbiAgICAgICAgICAgIGNvbnN0IGlzRXJyb3IgPSB0b29sUmVzdWx0Py5pc19lcnJvciA9PT0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbnN0IGlzU3ViYWdlbnQgPSBTVUJBR0VOVF9UT09MUy5oYXModG9vbFVzZS5uYW1lKTtcblxuICAgICAgICAgICAgaWYgKGlzU3ViYWdlbnQpIHVzZWRTdWJhZ2VudHMgPSB0cnVlO1xuXG4gICAgICAgICAgICBjb25zdCBhcmdzU3VtbWFyeSA9IHN1bW1hcml6ZVRvb2xJbnB1dCh0b29sVXNlLm5hbWUsIHRvb2xVc2UuaW5wdXQgfHwge30pO1xuXG4gICAgICAgICAgICBldmVudHMucHVzaCh7XG4gICAgICAgICAgICAgIGV2ZW50VHlwZTogXCJ0b29sX2NhbGxcIixcbiAgICAgICAgICAgICAgdGltZXN0YW1wOiB0cyxcbiAgICAgICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgICAgIHRvb2w6IHRvb2xVc2UubmFtZSxcbiAgICAgICAgICAgICAgICBhcmdzX3N1bW1hcnk6IGFyZ3NTdW1tYXJ5LFxuICAgICAgICAgICAgICAgIHJlc3VsdF9zdW1tYXJ5OiB0b29sUmVzdWx0Py5jb250ZW50ID8gU3RyaW5nKHRvb2xSZXN1bHQuY29udGVudCkuc2xpY2UoMCwgMjAwKSA6IFwiXCIsXG4gICAgICAgICAgICAgICAgc3VjY2VzczogIWlzRXJyb3IsXG4gICAgICAgICAgICAgICAgaXNfZXJyb3I6IGlzRXJyb3IsXG4gICAgICAgICAgICAgICAgLi4uKGlzU3ViYWdlbnQgPyB7IGlzX3N1YmFnZW50OiB0cnVlIH0gOiB7fSksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gRmlsZSBjaGFuZ2UgZXZlbnRzIGZvciBXcml0ZS9FZGl0XG4gICAgICAgICAgICBjb25zdCBjaGFuZ2VGaWxlUGF0aCA9IGdldEZpbGVQYXRoKHRvb2xVc2UuaW5wdXQgfHwge30pO1xuICAgICAgICAgICAgaWYgKHRvb2xVc2UubmFtZSA9PT0gXCJXcml0ZVwiICYmIGNoYW5nZUZpbGVQYXRoKSB7XG4gICAgICAgICAgICAgIGV2ZW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgICBldmVudFR5cGU6IFwiZmlsZV9jaGFuZ2VcIixcbiAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IHRzLFxuICAgICAgICAgICAgICAgIHBheWxvYWQ6IHsgcGF0aDogY2hhbmdlRmlsZVBhdGgsIGFjdGlvbjogXCJjcmVhdGVcIiB9LFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgodG9vbFVzZS5uYW1lID09PSBcIkVkaXRcIiB8fCB0b29sVXNlLm5hbWUgPT09IFwiTXVsdGlFZGl0XCIpICYmIGNoYW5nZUZpbGVQYXRoKSB7XG4gICAgICAgICAgICAgIGV2ZW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgICBldmVudFR5cGU6IFwiZmlsZV9jaGFuZ2VcIixcbiAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IHRzLFxuICAgICAgICAgICAgICAgIHBheWxvYWQ6IHsgcGF0aDogY2hhbmdlRmlsZVBhdGgsIGFjdGlvbjogXCJlZGl0XCIgfSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEdpdCBjb21taXQgZGV0ZWN0aW9uIGZyb20gQmFzaCBjb21tYW5kc1xuICAgICAgICAgICAgaWYgKHRvb2xVc2UubmFtZSA9PT0gXCJCYXNoXCIgJiYgdG9vbFVzZS5pbnB1dD8uY29tbWFuZCkge1xuICAgICAgICAgICAgICBjb25zdCBjbWQgPSBTdHJpbmcodG9vbFVzZS5pbnB1dC5jb21tYW5kKTtcbiAgICAgICAgICAgICAgY29uc3QgcmVzdWx0VGV4dCA9IHRvb2xSZXN1bHQ/LmNvbnRlbnQgPyBTdHJpbmcodG9vbFJlc3VsdC5jb250ZW50KSA6IFwiXCI7XG4gICAgICAgICAgICAgIGlmIChjbWQuaW5jbHVkZXMoXCJnaXQgY29tbWl0XCIpKSB7XG4gICAgICAgICAgICAgICAgZXZlbnRzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiBcImdpdF9jb21taXRcIixcbiAgICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogdHMsXG4gICAgICAgICAgICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbW1hbmQ6IGNtZCxcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0X3N1bW1hcnk6IHJlc3VsdFRleHQuc2xpY2UoMCwgMjAwKSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKGNtZC5pbmNsdWRlcyhcImdpdCBwdXNoXCIpKSB7XG4gICAgICAgICAgICAgICAgZXZlbnRzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiBcImdpdF9wdXNoXCIsXG4gICAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IHRzLFxuICAgICAgICAgICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgICAgICAgICBjb21tYW5kOiBjbWQsXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdF9zdW1tYXJ5OiByZXN1bHRUZXh0LnNsaWNlKDAsIDIwMCksXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIC8vIFBSIGRldGVjdGlvbiBmcm9tIGdoIHByIGNyZWF0ZSAvIHJlc3VsdCBVUkxzXG4gICAgICAgICAgICAgIGlmIChjbWQuaW5jbHVkZXMoXCJnaCBwciBjcmVhdGVcIikgfHwgY21kLmluY2x1ZGVzKFwiZ2ggcHIgbWVyZ2VcIikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwck1hdGNoID0gcmVzdWx0VGV4dC5tYXRjaChcbiAgICAgICAgICAgICAgICAgIC9odHRwczpcXC9cXC9naXRodWJcXC5jb21cXC8oW14vXStcXC9bXi9dKylcXC9wdWxsXFwvKFxcZCspLyxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGlmIChwck1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICBldmVudHMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogXCJwcl9vcGVuZWRcIixcbiAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wOiB0cyxcbiAgICAgICAgICAgICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbW1hbmQ6IGNtZC5zbGljZSgwLCAyMDApLFxuICAgICAgICAgICAgICAgICAgICAgIHByX3VybDogcHJNYXRjaFswXSxcbiAgICAgICAgICAgICAgICAgICAgICByZXBvOiBwck1hdGNoWzFdLFxuICAgICAgICAgICAgICAgICAgICAgIHByX251bWJlcjogcGFyc2VJbnQocHJNYXRjaFsyXSwgMTApLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEVycm9yIGV2ZW50cyBmb3IgZmFpbGVkIHRvb2wgY2FsbHNcbiAgICAgICAgICAgIGlmIChpc0Vycm9yICYmIHRvb2xSZXN1bHQ/LmNvbnRlbnQpIHtcbiAgICAgICAgICAgICAgZXZlbnRzLnB1c2goe1xuICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogXCJlcnJvclwiLFxuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogdHMsXG4gICAgICAgICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgICAgICAgdG9vbDogdG9vbFVzZS5uYW1lLFxuICAgICAgICAgICAgICAgICAgbWVzc2FnZTogU3RyaW5nKHRvb2xSZXN1bHQuY29udGVudCkuc2xpY2UoMCwgNTAwKSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBTb3J0IGV2ZW50cyBieSB0aW1lc3RhbXBcbiAgZXZlbnRzLnNvcnQoKGEsIGIpID0+IGEudGltZXN0YW1wLmxvY2FsZUNvbXBhcmUoYi50aW1lc3RhbXApKTtcblxuICAvLyBBZGQgc2Vzc2lvbl9zdGFydCBhcyBmaXJzdCBldmVudFxuICBldmVudHMudW5zaGlmdCh7XG4gICAgZXZlbnRUeXBlOiBcInNlc3Npb25fc3RhcnRcIixcbiAgICB0aW1lc3RhbXA6IHN0YXJ0ZWRBdCxcbiAgICBwYXlsb2FkOiB7XG4gICAgICBtb2RlbCxcbiAgICAgIGdpdF9icmFuY2g6IGdpdEJyYW5jaCxcbiAgICAgIHByb2plY3QsXG4gICAgICBoYXJuZXNzOiBcImNsYXVkZS1jb2RlXCIsXG4gICAgICB2ZXJzaW9uLFxuICAgICAgdXNlcl9pZDogdXNlcklkLFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIEFkZCBzZXNzaW9uX2VuZCBhcyBsYXN0IGV2ZW50XG4gIGV2ZW50cy5wdXNoKHtcbiAgICBldmVudFR5cGU6IFwic2Vzc2lvbl9lbmRcIixcbiAgICB0aW1lc3RhbXA6IGVuZGVkQXQsXG4gICAgcGF5bG9hZDoge1xuICAgICAgcmVhc29uOiBcInNlc3Npb25fZW5kX2luZmVycmVkXCIsXG4gICAgfSxcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICBzZXNzaW9uSWQsXG4gICAgcHJvamVjdCxcbiAgICBnaXRCcmFuY2gsXG4gICAgaGFybmVzczogXCJjbGF1ZGUtY29kZVwiLFxuICAgIG1vZGVsLFxuICAgIHZlcnNpb24sXG4gICAgdXNlcklkLFxuICAgIHN0YXJ0ZWRBdCxcbiAgICBlbmRlZEF0LFxuICAgIGV2ZW50cyxcbiAgICB0b3RhbElucHV0VG9rZW5zLFxuICAgIHRvdGFsT3V0cHV0VG9rZW5zLFxuICAgIHRvdGFsQ2FjaGVSZWFkVG9rZW5zLFxuICAgIHRvdGFsQ2FjaGVXcml0ZVRva2VucyxcbiAgICB1c2VkU3ViYWdlbnRzLFxuICB9O1xufVxuIiwgIi8qKlxuICogUGFyc2UgYSBQaSBzZXNzaW9uIEpTT05MIHN0cmluZyBpbnRvIGFnZW50bGVucyBldmVudHMuXG4gKlxuICogUGkgc2Vzc2lvbiBmb3JtYXQgKHJlYWwgZGF0YSBmcm9tIH4vLnBpL2FnZW50L3Nlc3Npb25zLyk6XG4gKiAtIHR5cGU6IFwic2Vzc2lvblwiIFx1MjAxNCBtZXRhZGF0YTogeyBpZCwgdmVyc2lvbiwgY3dkLCB0aW1lc3RhbXAgfVxuICogLSB0eXBlOiBcIm1vZGVsX2NoYW5nZVwiIFx1MjAxNCB7IHByb3ZpZGVyLCBtb2RlbElkIH1cbiAqIC0gdHlwZTogXCJ0aGlua2luZ19sZXZlbF9jaGFuZ2VcIiBcdTIwMTQgeyB0aGlua2luZ0xldmVsIH1cbiAqIC0gdHlwZTogXCJtZXNzYWdlXCIgXHUyMDE0IGNvbnZlcnNhdGlvbiB0dXJuczpcbiAqICAgLSByb2xlOiBcInVzZXJcIiAgICAgICBcdTIwMTQgY29udGVudDogW3t0eXBlOlwidGV4dFwiLCB0ZXh0OlwiLi4uXCJ9XVxuICogICAtIHJvbGU6IFwiYXNzaXN0YW50XCIgIFx1MjAxNCBjb250ZW50OiBbe3R5cGU6XCJ0b29sQ2FsbFwifFwidGV4dFwifFwidGhpbmtpbmdcIiwgLi4ufV0sXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlOiB7aW5wdXQsIG91dHB1dCwgY2FjaGVSZWFkLCBjYWNoZVdyaXRlLCB0b3RhbFRva2VucywgY29zdDp7dG90YWwsLi4ufX1cbiAqICAgLSByb2xlOiBcInRvb2xSZXN1bHRcIiBcdTIwMTQgY29udGVudDogW3t0eXBlOlwidGV4dFwiLCB0ZXh0OlwiLi4uXCJ9XSxcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbENhbGxJZDogXCIuLi5cIiwgdG9vbE5hbWU6IFwiLi4uXCIsIGlzRXJyb3I6IGJvb2xcbiAqXG4gKiBUb29sIGFyZ3VtZW50IGtleXMgKGZyb20gcmVhbCBQaSBkYXRhKTpcbiAqICAgd3JpdGUvZWRpdC9yZWFkIFx1MjE5MiBhcmdzLnBhdGggKE5PVCBmaWxlX3BhdGggXHUyMDE0IHRoYXQncyBDbGF1ZGUgQ29kZSlcbiAqICAgYmFzaCAgICAgICAgICAgIFx1MjE5MiBhcmdzLmNvbW1hbmRcbiAqL1xuXG5pbXBvcnQgdHlwZSB7IFBhcnNlZEV2ZW50LCBQYXJzZWRTZXNzaW9uIH0gZnJvbSBcIi4uL2NsYXVkZS1jb2RlL3BhcnNlclwiO1xuaW1wb3J0IHsgZ2V0Q29udGV4dFdpbmRvdyB9IGZyb20gXCIuLi9tb2RlbC1jb250ZXh0XCI7XG5cbmNvbnN0IFNVQkFHRU5UX1RPT0xTID0gbmV3IFNldChbXCJzdWJhZ2VudFwiLCBcImRlbGVnYXRlXCIsIFwiVGFza1wiLCBcIkFnZW50XCJdKTtcblxuLyoqIEV4dHJhY3QgdGhlIGxhc3QgcGF0aCBzZWdtZW50IGFzIHRoZSBwcm9qZWN0IG5hbWUuICovXG5mdW5jdGlvbiBwcm9qZWN0RnJvbUN3ZChjd2Q6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHBhcnRzID0gY3dkLnJlcGxhY2UoL1xcLyskLywgXCJcIikuc3BsaXQoXCIvXCIpO1xuICByZXR1cm4gcGFydHNbcGFydHMubGVuZ3RoIC0gMV0gfHwgY3dkO1xufVxuXG4vKiogR2V0IHRoZSBmaWxlIHBhdGggZnJvbSB0b29sIGFyZ3MgXHUyMDE0IFBpIHVzZXMgYHBhdGhgLCBDbGF1ZGUgQ29kZSB1c2VzIGBmaWxlX3BhdGhgLiAqL1xuZnVuY3Rpb24gZ2V0RmlsZVBhdGgoYXJnczogUmVjb3JkPHN0cmluZywgYW55Pik6IHN0cmluZyB8IG51bGwge1xuICByZXR1cm4gYXJncy5wYXRoIHx8IGFyZ3MuZmlsZV9wYXRoIHx8IG51bGw7XG59XG5cbi8qKiBCdWlsZCBhIG9uZS1saW5lIHN1bW1hcnkgb2YgdG9vbCBhcmd1bWVudHMgZm9yIGRpc3BsYXkuICovXG5mdW5jdGlvbiBzdW1tYXJpemVUb29sSW5wdXQobmFtZTogc3RyaW5nLCBhcmdzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogc3RyaW5nIHtcbiAgY29uc3QgbG5hbWUgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG4gIGlmIChsbmFtZSA9PT0gXCJiYXNoXCIgJiYgYXJncy5jb21tYW5kKSB7XG4gICAgcmV0dXJuIFN0cmluZyhhcmdzLmNvbW1hbmQpLnNsaWNlKDAsIDIwMCk7XG4gIH1cbiAgY29uc3QgZmlsZVBhdGggPSBnZXRGaWxlUGF0aChhcmdzKTtcbiAgaWYgKChsbmFtZSA9PT0gXCJ3cml0ZVwiIHx8IGxuYW1lID09PSBcImVkaXRcIiB8fCBsbmFtZSA9PT0gXCJyZWFkXCIpICYmIGZpbGVQYXRoKSB7XG4gICAgcmV0dXJuIGZpbGVQYXRoO1xuICB9XG4gIC8vIG11bHRpLWVkaXQ6IHN1bW1hcml6ZSBmaXJzdCBwYXRoXG4gIGlmIChsbmFtZSA9PT0gXCJlZGl0XCIgJiYgQXJyYXkuaXNBcnJheShhcmdzLm11bHRpKSAmJiBhcmdzLm11bHRpLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCBmaXJzdFBhdGggPSBhcmdzLm11bHRpWzBdLnBhdGggfHwgYXJncy5tdWx0aVswXS5maWxlX3BhdGggfHwgXCJcIjtcbiAgICBjb25zdCBjb3VudCA9IGFyZ3MubXVsdGkubGVuZ3RoO1xuICAgIHJldHVybiBjb3VudCA+IDEgPyBgJHtmaXJzdFBhdGh9ICgrJHtjb3VudCAtIDF9IG1vcmUpYCA6IGZpcnN0UGF0aDtcbiAgfVxuICBpZiAoU1VCQUdFTlRfVE9PTFMuaGFzKG5hbWUpKSB7XG4gICAgcmV0dXJuIFN0cmluZyhhcmdzLnRhc2sgfHwgYXJncy5kZXNjcmlwdGlvbiB8fCBhcmdzLnByb21wdCB8fCBcIlwiKS5zbGljZSgwLCAyMDApO1xuICB9XG4gIC8vIEdlbmVyaWM6IGZpcnN0IG5vbi1jb250ZW50IHN0cmluZyB2YWx1ZVxuICBmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgT2JqZWN0LmVudHJpZXMoYXJncykpIHtcbiAgICBpZiAoa2V5ID09PSBcImNvbnRlbnRcIikgY29udGludWU7IC8vIHNraXAgZmlsZSBjb250ZW50XG4gICAgaWYgKHR5cGVvZiB2YWwgPT09IFwic3RyaW5nXCIgJiYgdmFsLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiB2YWwuc2xpY2UoMCwgMjAwKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIFwiXCI7XG59XG5cbi8vIFx1MjUwMFx1MjUwMCBUeXBlcyBmb3IgZmlyc3QtcGFzcyBjb2xsZWN0aW9uIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxuXG5pbnRlcmZhY2UgVG9vbFJlc3VsdEluZm8ge1xuICBjb250ZW50OiBzdHJpbmc7XG4gIGlzRXJyb3I6IGJvb2xlYW47XG4gIHRzOiBzdHJpbmc7XG59XG5cbi8vIFx1MjUwMFx1MjUwMCBNYWluIHBhcnNlciBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUGlTZXNzaW9uKGpzb25sOiBzdHJpbmcsIHNlc3Npb25EaXI/OiBzdHJpbmcpOiBQYXJzZWRTZXNzaW9uIHtcbiAgY29uc3QgbGluZXMgPSBqc29ubFxuICAgIC5zcGxpdChcIlxcblwiKVxuICAgIC5maWx0ZXIoKGwpID0+IGwudHJpbSgpKVxuICAgIC5tYXAoKGwpID0+IEpTT04ucGFyc2UobCkpO1xuXG4gIGNvbnN0IGV2ZW50czogUGFyc2VkRXZlbnRbXSA9IFtdO1xuICBsZXQgc2Vzc2lvbklkID0gXCJcIjtcbiAgbGV0IHByb2plY3QgPSBcIlwiO1xuICBsZXQgbW9kZWw6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBsZXQgdmVyc2lvbiA9IFwiXCI7XG4gIGxldCBzdGFydGVkQXQgPSBcIlwiO1xuICBsZXQgZW5kZWRBdCA9IFwiXCI7XG4gIGxldCB1c2VkU3ViYWdlbnRzID0gZmFsc2U7XG5cbiAgbGV0IHRvdGFsSW5wdXRUb2tlbnMgPSAwO1xuICBsZXQgdG90YWxPdXRwdXRUb2tlbnMgPSAwO1xuICBsZXQgdG90YWxDYWNoZVJlYWRUb2tlbnMgPSAwO1xuICBsZXQgdG90YWxDYWNoZVdyaXRlVG9rZW5zID0gMDtcblxuICAvLyBcdTI1MDBcdTI1MDAgRmlyc3QgcGFzczogaW5kZXggdG9vbFJlc3VsdCBtZXNzYWdlcyBieSB0b29sQ2FsbElkIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxuICAvLyBSZWFsIFBpIGRhdGEgaGFzIHRvb2xDYWxsSWQgb24gdG9vbFJlc3VsdCBtZXNzYWdlcyBmb3IgZXhhY3QgbWF0Y2hpbmcuXG4gIC8vIEZhbGwgYmFjayB0byBzZXF1ZW50aWFsIGluZGV4IG1hdGNoaW5nIHdoZW4gdG9vbENhbGxJZCBpcyBhYnNlbnQuXG5cbiAgY29uc3QgdG9vbFJlc3VsdEJ5SWQgPSBuZXcgTWFwPHN0cmluZywgVG9vbFJlc3VsdEluZm8+KCk7XG4gIGNvbnN0IHRvb2xSZXN1bHRzQnlJbmRleDogVG9vbFJlc3VsdEluZm9bXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgbGluZSBvZiBsaW5lcykge1xuICAgIGlmIChsaW5lLnR5cGUgIT09IFwibWVzc2FnZVwiKSBjb250aW51ZTtcbiAgICBjb25zdCBtc2cgPSBsaW5lLm1lc3NhZ2UgfHwge307XG4gICAgaWYgKG1zZy5yb2xlICE9PSBcInRvb2xSZXN1bHRcIikgY29udGludWU7XG5cbiAgICBjb25zdCB0ZXh0ID0gKG1zZy5jb250ZW50IHx8IFtdKVxuICAgICAgLmZpbHRlcigoYzogYW55KSA9PiBjLnR5cGUgPT09IFwidGV4dFwiKVxuICAgICAgLm1hcCgoYzogYW55KSA9PiBjLnRleHQpXG4gICAgICAuam9pbihcIlxcblwiKTtcbiAgICBjb25zdCBpbmZvOiBUb29sUmVzdWx0SW5mbyA9IHtcbiAgICAgIGNvbnRlbnQ6IHRleHQsXG4gICAgICBpc0Vycm9yOiBtc2cuaXNFcnJvciA9PT0gdHJ1ZSxcbiAgICAgIHRzOiBsaW5lLnRpbWVzdGFtcCxcbiAgICB9O1xuXG4gICAgaWYgKG1zZy50b29sQ2FsbElkKSB7XG4gICAgICB0b29sUmVzdWx0QnlJZC5zZXQobXNnLnRvb2xDYWxsSWQsIGluZm8pO1xuICAgIH1cbiAgICB0b29sUmVzdWx0c0J5SW5kZXgucHVzaChpbmZvKTtcbiAgfVxuXG4gIC8vIFx1MjUwMFx1MjUwMCBTZWNvbmQgcGFzczogZ2VuZXJhdGUgZXZlbnRzIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxuXG4gIGxldCB0b29sQ2FsbFNlcUluZGV4ID0gMDsgLy8gZmFsbGJhY2sgc2VxdWVudGlhbCBjb3VudGVyXG5cbiAgZm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG4gICAgY29uc3QgdHMgPSBsaW5lLnRpbWVzdGFtcDtcbiAgICBpZiAoIXRzKSBjb250aW51ZTtcblxuICAgIGlmICghc3RhcnRlZEF0IHx8IHRzIDwgc3RhcnRlZEF0KSBzdGFydGVkQXQgPSB0cztcbiAgICBpZiAoIWVuZGVkQXQgfHwgdHMgPiBlbmRlZEF0KSBlbmRlZEF0ID0gdHM7XG5cbiAgICAvLyBTZXNzaW9uIG1ldGFkYXRhXG4gICAgaWYgKGxpbmUudHlwZSA9PT0gXCJzZXNzaW9uXCIpIHtcbiAgICAgIHNlc3Npb25JZCA9IGxpbmUuaWQ7XG4gICAgICB2ZXJzaW9uID0gU3RyaW5nKGxpbmUudmVyc2lvbiB8fCBcIlwiKTtcbiAgICAgIGlmIChsaW5lLmN3ZCkgcHJvamVjdCA9IHByb2plY3RGcm9tQ3dkKGxpbmUuY3dkKTtcbiAgICB9XG5cbiAgICAvLyBNb2RlbCBjaGFuZ2VzXG4gICAgaWYgKGxpbmUudHlwZSA9PT0gXCJtb2RlbF9jaGFuZ2VcIiAmJiBsaW5lLm1vZGVsSWQpIHtcbiAgICAgIG1vZGVsID0gbGluZS5tb2RlbElkO1xuICAgIH1cblxuICAgIC8vIFNraXAgbm9uLW1lc3NhZ2UgbGluZXMgZnJvbSBoZXJlIG9uXG4gICAgaWYgKGxpbmUudHlwZSAhPT0gXCJtZXNzYWdlXCIpIGNvbnRpbnVlO1xuICAgIGNvbnN0IG1zZyA9IGxpbmUubWVzc2FnZSB8fCB7fTtcblxuICAgIC8vIFx1MjUwMFx1MjUwMCBVc2VyIHByb21wdHMgXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXG4gICAgaWYgKG1zZy5yb2xlID09PSBcInVzZXJcIikge1xuICAgICAgY29uc3QgdGV4dCA9IChtc2cuY29udGVudCB8fCBbXSlcbiAgICAgICAgLmZpbHRlcigoYzogYW55KSA9PiBjLnR5cGUgPT09IFwidGV4dFwiKVxuICAgICAgICAubWFwKChjOiBhbnkpID0+IGMudGV4dClcbiAgICAgICAgLmpvaW4oXCJcXG5cIik7XG4gICAgICBpZiAodGV4dC50cmltKCkpIHtcbiAgICAgICAgZXZlbnRzLnB1c2goe1xuICAgICAgICAgIGV2ZW50VHlwZTogXCJ1c2VyX3Byb21wdFwiLFxuICAgICAgICAgIHRpbWVzdGFtcDogdHMsXG4gICAgICAgICAgcGF5bG9hZDogeyBwcm9tcHRfdGV4dDogdGV4dCwgcHJvbXB0X2xlbmd0aDogdGV4dC5sZW5ndGggfSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gXHUyNTAwXHUyNTAwIEFzc2lzdGFudCBtZXNzYWdlcyBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcbiAgICBpZiAobXNnLnJvbGUgPT09IFwiYXNzaXN0YW50XCIpIHtcbiAgICAgIGNvbnN0IHVzYWdlID0gbXNnLnVzYWdlIHx8IHt9O1xuICAgICAgY29uc3QgaW5wdXRUb2tlbnMgPSB1c2FnZS5pbnB1dCB8fCAwO1xuICAgICAgY29uc3Qgb3V0cHV0VG9rZW5zID0gdXNhZ2Uub3V0cHV0IHx8IDA7XG4gICAgICBjb25zdCBjYWNoZVJlYWQgPSB1c2FnZS5jYWNoZVJlYWQgfHwgMDtcbiAgICAgIGNvbnN0IGNhY2hlV3JpdGUgPSB1c2FnZS5jYWNoZVdyaXRlIHx8IDA7XG4gICAgICBjb25zdCBjb3N0VG90YWwgPSB1c2FnZS5jb3N0Py50b3RhbCB8fCAwO1xuXG4gICAgICB0b3RhbElucHV0VG9rZW5zICs9IGlucHV0VG9rZW5zO1xuICAgICAgdG90YWxPdXRwdXRUb2tlbnMgKz0gb3V0cHV0VG9rZW5zO1xuICAgICAgdG90YWxDYWNoZVJlYWRUb2tlbnMgKz0gY2FjaGVSZWFkO1xuICAgICAgdG90YWxDYWNoZVdyaXRlVG9rZW5zICs9IGNhY2hlV3JpdGU7XG5cbiAgICAgIGNvbnN0IHJlc3BvbnNlTW9kZWwgPSBtc2cubW9kZWwgfHwgbW9kZWw7XG4gICAgICBjb25zdCBjb250ZXh0V2luZG93ID0gZ2V0Q29udGV4dFdpbmRvdyhyZXNwb25zZU1vZGVsKTtcblxuICAgICAgZXZlbnRzLnB1c2goe1xuICAgICAgICBldmVudFR5cGU6IFwibGxtX3Jlc3BvbnNlXCIsXG4gICAgICAgIHRpbWVzdGFtcDogdHMsXG4gICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICBtb2RlbDogcmVzcG9uc2VNb2RlbCxcbiAgICAgICAgICBpbnB1dF90b2tlbnM6IGlucHV0VG9rZW5zLFxuICAgICAgICAgIG91dHB1dF90b2tlbnM6IG91dHB1dFRva2VucyxcbiAgICAgICAgICBjYWNoZV9yZWFkX3Rva2VuczogY2FjaGVSZWFkLFxuICAgICAgICAgIGNhY2hlX3dyaXRlX3Rva2VuczogY2FjaGVXcml0ZSxcbiAgICAgICAgICB0b3RhbF90b2tlbnM6IHVzYWdlLnRvdGFsVG9rZW5zIHx8IGlucHV0VG9rZW5zICsgb3V0cHV0VG9rZW5zLFxuICAgICAgICAgIHRvdGFsX2Nvc3RfdXNkOiBjb3N0VG90YWwsXG4gICAgICAgICAgc3RvcF9yZWFzb246IG1zZy5zdG9wX3JlYXNvbiB8fCBudWxsLFxuICAgICAgICAgIC4uLihjb250ZXh0V2luZG93ID8geyBjb250ZXh0X3dpbmRvdzogY29udGV4dFdpbmRvdyB9IDoge30pLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFx1MjUwMFx1MjUwMCBUb29sIGNhbGxzIHdpdGhpbiBhc3Npc3RhbnQgY29udGVudCBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcbiAgICAgIGZvciAoY29uc3QgYyBvZiBtc2cuY29udGVudCB8fCBbXSkge1xuICAgICAgICBpZiAoYy50eXBlICE9PSBcInRvb2xDYWxsXCIpIGNvbnRpbnVlO1xuXG4gICAgICAgIGNvbnN0IHRvb2xJZCA9IGMuaWQ7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSBjLmFyZ3VtZW50cyB8fCBjLmlucHV0IHx8IHt9O1xuXG4gICAgICAgIC8vIE1hdGNoIHRvIHJlc3VsdDogcHJlZmVyIGV4YWN0IGlkIG1hdGNoLCBmYWxsIGJhY2sgdG8gaW5kZXhcbiAgICAgICAgY29uc3QgdG9vbFJlc3VsdCA9XG4gICAgICAgICAgdG9vbFJlc3VsdEJ5SWQuZ2V0KHRvb2xJZCkgfHwgdG9vbFJlc3VsdHNCeUluZGV4W3Rvb2xDYWxsU2VxSW5kZXhdIHx8IG51bGw7XG4gICAgICAgIGNvbnN0IGlzRXJyb3IgPSB0b29sUmVzdWx0Py5pc0Vycm9yID09PSB0cnVlO1xuICAgICAgICBjb25zdCBpc1N1YmFnZW50ID0gU1VCQUdFTlRfVE9PTFMuaGFzKGMubmFtZSk7XG4gICAgICAgIGlmIChpc1N1YmFnZW50KSB1c2VkU3ViYWdlbnRzID0gdHJ1ZTtcblxuICAgICAgICBjb25zdCBhcmdzU3VtbWFyeSA9IHN1bW1hcml6ZVRvb2xJbnB1dChjLm5hbWUsIGFyZ3MpO1xuXG4gICAgICAgIGV2ZW50cy5wdXNoKHtcbiAgICAgICAgICBldmVudFR5cGU6IFwidG9vbF9jYWxsXCIsXG4gICAgICAgICAgdGltZXN0YW1wOiB0cyxcbiAgICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgICB0b29sOiBjLm5hbWUsXG4gICAgICAgICAgICBhcmdzX3N1bW1hcnk6IGFyZ3NTdW1tYXJ5LFxuICAgICAgICAgICAgcmVzdWx0X3N1bW1hcnk6IHRvb2xSZXN1bHQ/LmNvbnRlbnQgPyB0b29sUmVzdWx0LmNvbnRlbnQuc2xpY2UoMCwgMjAwKSA6IFwiXCIsXG4gICAgICAgICAgICBzdWNjZXNzOiAhaXNFcnJvcixcbiAgICAgICAgICAgIGlzX2Vycm9yOiBpc0Vycm9yLFxuICAgICAgICAgICAgLi4uKGlzU3ViYWdlbnQgPyB7IGlzX3N1YmFnZW50OiB0cnVlIH0gOiB7fSksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gXHUyNTAwXHUyNTAwIEZpbGUgY2hhbmdlcyBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcbiAgICAgICAgY29uc3QgbG5hbWUgPSBjLm5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgY29uc3QgZmlsZVBhdGggPSBnZXRGaWxlUGF0aChhcmdzKTtcblxuICAgICAgICBpZiAobG5hbWUgPT09IFwid3JpdGVcIiAmJiBmaWxlUGF0aCkge1xuICAgICAgICAgIGV2ZW50cy5wdXNoKHtcbiAgICAgICAgICAgIGV2ZW50VHlwZTogXCJmaWxlX2NoYW5nZVwiLFxuICAgICAgICAgICAgdGltZXN0YW1wOiB0cyxcbiAgICAgICAgICAgIHBheWxvYWQ6IHsgcGF0aDogZmlsZVBhdGgsIGFjdGlvbjogXCJjcmVhdGVcIiB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChsbmFtZSA9PT0gXCJlZGl0XCIgfHwgbG5hbWUgPT09IFwibXVsdGllZGl0XCIpIHtcbiAgICAgICAgICBpZiAoZmlsZVBhdGgpIHtcbiAgICAgICAgICAgIGV2ZW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgZXZlbnRUeXBlOiBcImZpbGVfY2hhbmdlXCIsXG4gICAgICAgICAgICAgIHRpbWVzdGFtcDogdHMsXG4gICAgICAgICAgICAgIHBheWxvYWQ6IHsgcGF0aDogZmlsZVBhdGgsIGFjdGlvbjogXCJlZGl0XCIgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBIYW5kbGUgbXVsdGktZWRpdDogYXJyYXkgb2Yge3BhdGgsIG9sZFRleHQsIG5ld1RleHR9XG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYXJncy5tdWx0aSkpIHtcbiAgICAgICAgICAgIGNvbnN0IHNlZW4gPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBhcmdzLm11bHRpKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHAgPSBpdGVtLnBhdGggfHwgaXRlbS5maWxlX3BhdGg7XG4gICAgICAgICAgICAgIGlmIChwICYmICFzZWVuLmhhcyhwKSkge1xuICAgICAgICAgICAgICAgIHNlZW4uYWRkKHApO1xuICAgICAgICAgICAgICAgIGV2ZW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogXCJmaWxlX2NoYW5nZVwiLFxuICAgICAgICAgICAgICAgICAgdGltZXN0YW1wOiB0cyxcbiAgICAgICAgICAgICAgICAgIHBheWxvYWQ6IHsgcGF0aDogcCwgYWN0aW9uOiBcImVkaXRcIiB9LFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gXHUyNTAwXHUyNTAwIEdpdCBkZXRlY3Rpb24gXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXG4gICAgICAgIGlmIChsbmFtZSA9PT0gXCJiYXNoXCIgJiYgYXJncy5jb21tYW5kKSB7XG4gICAgICAgICAgY29uc3QgY21kID0gU3RyaW5nKGFyZ3MuY29tbWFuZCk7XG4gICAgICAgICAgaWYgKGNtZC5pbmNsdWRlcyhcImdpdCBjb21taXRcIikpIHtcbiAgICAgICAgICAgIGV2ZW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgZXZlbnRUeXBlOiBcImdpdF9jb21taXRcIixcbiAgICAgICAgICAgICAgdGltZXN0YW1wOiB0cyxcbiAgICAgICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgICAgIGNvbW1hbmQ6IGNtZCxcbiAgICAgICAgICAgICAgICByZXN1bHRfc3VtbWFyeTogdG9vbFJlc3VsdD8uY29udGVudD8uc2xpY2UoMCwgMjAwKSB8fCBcIlwiLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChjbWQuaW5jbHVkZXMoXCJnaXQgcHVzaFwiKSkge1xuICAgICAgICAgICAgZXZlbnRzLnB1c2goe1xuICAgICAgICAgICAgICBldmVudFR5cGU6IFwiZ2l0X3B1c2hcIixcbiAgICAgICAgICAgICAgdGltZXN0YW1wOiB0cyxcbiAgICAgICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgICAgIGNvbW1hbmQ6IGNtZCxcbiAgICAgICAgICAgICAgICByZXN1bHRfc3VtbWFyeTogdG9vbFJlc3VsdD8uY29udGVudD8uc2xpY2UoMCwgMjAwKSB8fCBcIlwiLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIFBSIGRldGVjdGlvbiBmcm9tIGdoIHByIGNyZWF0ZSAvIHJlc3VsdCBVUkxzXG4gICAgICAgICAgaWYgKGNtZC5pbmNsdWRlcyhcImdoIHByIGNyZWF0ZVwiKSB8fCBjbWQuaW5jbHVkZXMoXCJnaCBwciBtZXJnZVwiKSkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0VGV4dCA9IHRvb2xSZXN1bHQ/LmNvbnRlbnQgfHwgXCJcIjtcbiAgICAgICAgICAgIGNvbnN0IHByTWF0Y2ggPSByZXN1bHRUZXh0Lm1hdGNoKC9odHRwczpcXC9cXC9naXRodWJcXC5jb21cXC8oW14vXStcXC9bXi9dKylcXC9wdWxsXFwvKFxcZCspLyk7XG4gICAgICAgICAgICBpZiAocHJNYXRjaCkge1xuICAgICAgICAgICAgICBldmVudHMucHVzaCh7XG4gICAgICAgICAgICAgICAgZXZlbnRUeXBlOiBcInByX29wZW5lZFwiLFxuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogdHMsXG4gICAgICAgICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgICAgICAgY29tbWFuZDogY21kLnNsaWNlKDAsIDIwMCksXG4gICAgICAgICAgICAgICAgICBwcl91cmw6IHByTWF0Y2hbMF0sXG4gICAgICAgICAgICAgICAgICByZXBvOiBwck1hdGNoWzFdLFxuICAgICAgICAgICAgICAgICAgcHJfbnVtYmVyOiBwYXJzZUludChwck1hdGNoWzJdLCAxMCksXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gXHUyNTAwXHUyNTAwIEVycm9yIGV2ZW50cyBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcbiAgICAgICAgaWYgKGlzRXJyb3IgJiYgdG9vbFJlc3VsdD8uY29udGVudCkge1xuICAgICAgICAgIGV2ZW50cy5wdXNoKHtcbiAgICAgICAgICAgIGV2ZW50VHlwZTogXCJlcnJvclwiLFxuICAgICAgICAgICAgdGltZXN0YW1wOiB0cyxcbiAgICAgICAgICAgIHBheWxvYWQ6IHsgdG9vbDogYy5uYW1lLCBtZXNzYWdlOiB0b29sUmVzdWx0LmNvbnRlbnQuc2xpY2UoMCwgNTAwKSB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdG9vbENhbGxTZXFJbmRleCsrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFNvcnQgZXZlbnRzIGJ5IHRpbWVzdGFtcFxuICBldmVudHMuc29ydCgoYSwgYikgPT4gYS50aW1lc3RhbXAubG9jYWxlQ29tcGFyZShiLnRpbWVzdGFtcCkpO1xuXG4gIC8vIEJvb2tlbmQgZXZlbnRzXG4gIGV2ZW50cy51bnNoaWZ0KHtcbiAgICBldmVudFR5cGU6IFwic2Vzc2lvbl9zdGFydFwiLFxuICAgIHRpbWVzdGFtcDogc3RhcnRlZEF0LFxuICAgIHBheWxvYWQ6IHsgbW9kZWwsIHByb2plY3QsIGhhcm5lc3M6IFwicGlcIiwgdmVyc2lvbiB9LFxuICB9KTtcbiAgZXZlbnRzLnB1c2goe1xuICAgIGV2ZW50VHlwZTogXCJzZXNzaW9uX2VuZFwiLFxuICAgIHRpbWVzdGFtcDogZW5kZWRBdCxcbiAgICBwYXlsb2FkOiB7IHJlYXNvbjogXCJzZXNzaW9uX2VuZF9pbmZlcnJlZFwiIH0sXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgc2Vzc2lvbklkLFxuICAgIHByb2plY3QsXG4gICAgZ2l0QnJhbmNoOiBudWxsLFxuICAgIGhhcm5lc3M6IFwicGlcIixcbiAgICBtb2RlbCxcbiAgICB2ZXJzaW9uLFxuICAgIHVzZXJJZDogXCJcIixcbiAgICBzdGFydGVkQXQsXG4gICAgZW5kZWRBdCxcbiAgICBldmVudHMsXG4gICAgdG90YWxJbnB1dFRva2VucyxcbiAgICB0b3RhbE91dHB1dFRva2VucyxcbiAgICB0b3RhbENhY2hlUmVhZFRva2VucyxcbiAgICB0b3RhbENhY2hlV3JpdGVUb2tlbnMsXG4gICAgdXNlZFN1YmFnZW50cyxcbiAgfTtcbn1cbiIsICIvKipcbiAqIEZpbGUgd2F0Y2hlcjogcG9sbHMgZm9yIG5ldy91cGRhdGVkIHNlc3Npb24gSlNPTkwgZmlsZXMgYW5kIGltcG9ydHMgdGhlbS5cbiAqIFVzZXMgcG9sbGluZyAobm90IGZzLndhdGNoKSBmb3IgcmVsaWFiaWxpdHkgYWNyb3NzIHBsYXRmb3JtcyBhbmQgbmV0d29yayBkcml2ZXMuXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBCZXR0ZXJTUUxpdGUzRGF0YWJhc2UgfSBmcm9tIFwiZHJpenpsZS1vcm0vYmV0dGVyLXNxbGl0ZTNcIjtcbmltcG9ydCB7IGluZGV4U2Vzc2lvbnMsIHR5cGUgSW5kZXhPcHRpb25zIH0gZnJvbSBcIi4vaW5kZXhlclwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIFdhdGNoZXJPcHRpb25zIGV4dGVuZHMgSW5kZXhPcHRpb25zIHtcbiAgLyoqIFBvbGwgaW50ZXJ2YWwgaW4gbWlsbGlzZWNvbmRzIChkZWZhdWx0OiA1MDAwKSAqL1xuICBwb2xsSW50ZXJ2YWxNcz86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBXYXRjaGVyIHtcbiAgc3RvcDogKCkgPT4gdm9pZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVdhdGNoZXIoZGI6IEJldHRlclNRTGl0ZTNEYXRhYmFzZSwgb3B0aW9uczogV2F0Y2hlck9wdGlvbnMgPSB7fSk6IFdhdGNoZXIge1xuICBjb25zdCBpbnRlcnZhbCA9IG9wdGlvbnMucG9sbEludGVydmFsTXMgPz8gNTAwMDtcbiAgbGV0IHN0b3BwZWQgPSBmYWxzZTtcbiAgbGV0IHRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PiB8IG51bGwgPSBudWxsO1xuXG4gIGZ1bmN0aW9uIHBvbGwoKSB7XG4gICAgaWYgKHN0b3BwZWQpIHJldHVybjtcblxuICAgIHRyeSB7XG4gICAgICBpbmRleFNlc3Npb25zKGRiLCBvcHRpb25zKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIFN3YWxsb3cgZXJyb3JzIFx1MjAxNCBrZWVwIHBvbGxpbmdcbiAgICB9XG5cbiAgICBpZiAoIXN0b3BwZWQpIHtcbiAgICAgIHRpbWVyID0gc2V0VGltZW91dChwb2xsLCBpbnRlcnZhbCk7XG4gICAgfVxuICB9XG5cbiAgLy8gU3RhcnQgZmlyc3QgcG9sbCBpbW1lZGlhdGVseVxuICBwb2xsKCk7XG5cbiAgcmV0dXJuIHtcbiAgICBzdG9wKCkge1xuICAgICAgc3RvcHBlZCA9IHRydWU7XG4gICAgICBpZiAodGltZXIpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgdGltZXIgPSBudWxsO1xuICAgICAgfVxuICAgIH0sXG4gIH07XG59XG4iLCAiaW1wb3J0IERhdGFiYXNlIGZyb20gXCJiZXR0ZXItc3FsaXRlM1wiO1xuaW1wb3J0IHsgZHJpenpsZSB9IGZyb20gXCJkcml6emxlLW9ybS9iZXR0ZXItc3FsaXRlM1wiO1xuaW1wb3J0IHsgc3FsIH0gZnJvbSBcImRyaXp6bGUtb3JtXCI7XG5pbXBvcnQgdHlwZSB7IEJldHRlclNRTGl0ZTNEYXRhYmFzZSB9IGZyb20gXCJkcml6emxlLW9ybS9iZXR0ZXItc3FsaXRlM1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCB7IGhvbWVkaXIgfSBmcm9tIFwib3NcIjtcblxubGV0IF9kYjogQmV0dGVyU1FMaXRlM0RhdGFiYXNlIHwgbnVsbCA9IG51bGw7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREYigpOiBCZXR0ZXJTUUxpdGUzRGF0YWJhc2Uge1xuICBpZiAoX2RiKSByZXR1cm4gX2RiO1xuXG4gIGNvbnN0IGRiUGF0aCA9XG4gICAgcHJvY2Vzcy5lbnYuQUdFTlRMRU5TX0RCX1BBVEggfHwgcGF0aC5qb2luKGhvbWVkaXIoKSwgXCIuYWdlbnRsZW5zXCIsIFwiYWdlbnRsZW5zLmRiXCIpO1xuICBjb25zdCBkYXRhRGlyID0gcGF0aC5kaXJuYW1lKGRiUGF0aCk7XG4gIGlmICghZnMuZXhpc3RzU3luYyhkYXRhRGlyKSkge1xuICAgIGZzLm1rZGlyU3luYyhkYXRhRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgfVxuICBjb25zdCBzcWxpdGUgPSBuZXcgRGF0YWJhc2UoZGJQYXRoKTtcblxuICAvLyBFbmFibGUgV0FMIG1vZGUgZm9yIGJldHRlciBjb25jdXJyZW50IHJlYWQvd3JpdGVcbiAgc3FsaXRlLnByYWdtYShcImpvdXJuYWxfbW9kZSA9IFdBTFwiKTtcblxuICBjb25zdCBkYiA9IGRyaXp6bGUoc3FsaXRlKTtcblxuICAvLyBBdXRvLWNyZWF0ZSB0YWJsZXMgaWYgdGhleSBkb24ndCBleGlzdFxuICBkYi5ydW4oc3FsYFxuICAgIENSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTIHNlc3Npb25zIChcbiAgICAgIGlkIFRFWFQgUFJJTUFSWSBLRVksXG4gICAgICB0ZWFtX2lkIFRFWFQgTk9UIE5VTEwsXG4gICAgICB1c2VyX2lkIFRFWFQgTk9UIE5VTEwsXG4gICAgICBwcm9qZWN0IFRFWFQgTk9UIE5VTEwsXG4gICAgICBnaXRfcmVwbyBURVhULFxuICAgICAgZ2l0X2JyYW5jaCBURVhULFxuICAgICAgcGlfdmVyc2lvbiBURVhUIE5PVCBOVUxMIERFRkFVTFQgJycsXG4gICAgICBza2lsbHNfdXNlZCBURVhUIE5PVCBOVUxMIERFRkFVTFQgJ1tdJyxcbiAgICAgIG1vZGVsIFRFWFQsXG4gICAgICBoYXJuZXNzIFRFWFQgTk9UIE5VTEwgREVGQVVMVCAncGknLFxuICAgICAgc3RhcnRlZF9hdCBURVhUIE5PVCBOVUxMLFxuICAgICAgZW5kZWRfYXQgVEVYVCxcbiAgICAgIHN0YXR1cyBURVhUIE5PVCBOVUxMIERFRkFVTFQgJ2FjdGl2ZScsXG4gICAgICBjcmVhdGVkX2F0IFRFWFQgTk9UIE5VTEwgREVGQVVMVCAoZGF0ZXRpbWUoJ25vdycpKVxuICAgIClcbiAgYCk7XG4gIGRiLnJ1bihzcWxgXG4gICAgQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgZXZlbnRzIChcbiAgICAgIGlkIElOVEVHRVIgUFJJTUFSWSBLRVkgQVVUT0lOQ1JFTUVOVCxcbiAgICAgIHNlc3Npb25faWQgVEVYVCBOT1QgTlVMTCxcbiAgICAgIGV2ZW50X3R5cGUgVEVYVCBOT1QgTlVMTCxcbiAgICAgIHRpbWVzdGFtcCBURVhUIE5PVCBOVUxMLFxuICAgICAgcGF5bG9hZCBURVhUIE5PVCBOVUxMIERFRkFVTFQgJ3t9JyxcbiAgICAgIGNyZWF0ZWRfYXQgVEVYVCBOT1QgTlVMTCBERUZBVUxUIChkYXRldGltZSgnbm93JykpXG4gICAgKVxuICBgKTtcblxuICAvLyBNaWdyYXRpb25zIGZvciBleGlzdGluZyBkYXRhYmFzZXNcbiAgdHJ5IHtcbiAgICBkYi5ydW4oc3FsYEFMVEVSIFRBQkxFIHNlc3Npb25zIEFERCBDT0xVTU4gbW9kZWwgVEVYVGApO1xuICB9IGNhdGNoIHtcbiAgICAvLyBDb2x1bW4gYWxyZWFkeSBleGlzdHNcbiAgfVxuXG4gIC8vIENyZWF0ZSBpbmRleGVzXG4gIGRiLnJ1bihzcWxgQ1JFQVRFIElOREVYIElGIE5PVCBFWElTVFMgaWR4X3Nlc3Npb25zX3RlYW1faWQgT04gc2Vzc2lvbnModGVhbV9pZClgKTtcbiAgZGIucnVuKHNxbGBDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyBpZHhfc2Vzc2lvbnNfdXNlcl9pZCBPTiBzZXNzaW9ucyh1c2VyX2lkKWApO1xuICBkYi5ydW4oc3FsYENSRUFURSBJTkRFWCBJRiBOT1QgRVhJU1RTIGlkeF9zZXNzaW9uc19wcm9qZWN0IE9OIHNlc3Npb25zKHByb2plY3QpYCk7XG4gIGRiLnJ1bihzcWxgQ1JFQVRFIElOREVYIElGIE5PVCBFWElTVFMgaWR4X3Nlc3Npb25zX3N0YXJ0ZWRfYXQgT04gc2Vzc2lvbnMoc3RhcnRlZF9hdClgKTtcbiAgZGIucnVuKHNxbGBDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyBpZHhfc2Vzc2lvbnNfc3RhdHVzIE9OIHNlc3Npb25zKHN0YXR1cylgKTtcbiAgZGIucnVuKHNxbGBDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyBpZHhfZXZlbnRzX3Nlc3Npb25faWQgT04gZXZlbnRzKHNlc3Npb25faWQpYCk7XG4gIGRiLnJ1bihcbiAgICBzcWxgQ1JFQVRFIElOREVYIElGIE5PVCBFWElTVFMgaWR4X2V2ZW50c19zZXNzaW9uX3RpbWVzdGFtcCBPTiBldmVudHMoc2Vzc2lvbl9pZCwgdGltZXN0YW1wKWAsXG4gICk7XG4gIGRiLnJ1bihzcWxgQ1JFQVRFIElOREVYIElGIE5PVCBFWElTVFMgaWR4X2V2ZW50c19ldmVudF90eXBlIE9OIGV2ZW50cyhldmVudF90eXBlKWApO1xuXG4gIC8vIFBSIHRyYWNraW5nIHRhYmxlXG4gIGRiLnJ1bihzcWxgXG4gICAgQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgcHVsbF9yZXF1ZXN0cyAoXG4gICAgICBpZCBJTlRFR0VSIFBSSU1BUlkgS0VZIEFVVE9JTkNSRU1FTlQsXG4gICAgICBzZXNzaW9uX2lkIFRFWFQgTk9UIE5VTEwsXG4gICAgICByZXBvIFRFWFQgTk9UIE5VTEwsXG4gICAgICBicmFuY2ggVEVYVCBOT1QgTlVMTCxcbiAgICAgIHByX251bWJlciBJTlRFR0VSIE5PVCBOVUxMLFxuICAgICAgcHJfdXJsIFRFWFQgTk9UIE5VTEwsXG4gICAgICBwcl90aXRsZSBURVhUIE5PVCBOVUxMIERFRkFVTFQgJycsXG4gICAgICBzdGF0dXMgVEVYVCBOT1QgTlVMTCBERUZBVUxUICdvcGVuJyxcbiAgICAgIG1lcmdlZF9hdCBURVhULFxuICAgICAgcmV2aWV3c19hcHByb3ZlZCBJTlRFR0VSIE5PVCBOVUxMIERFRkFVTFQgMCxcbiAgICAgIHJldmlld3NfY2hhbmdlc19yZXF1ZXN0ZWQgSU5URUdFUiBOT1QgTlVMTCBERUZBVUxUIDAsXG4gICAgICByZXZpZXdfY29tbWVudHMgSU5URUdFUiBOT1QgTlVMTCBERUZBVUxUIDAsXG4gICAgICBjb21taXRzX2FmdGVyX3JldmlldyBJTlRFR0VSIE5PVCBOVUxMIERFRkFVTFQgMCxcbiAgICAgIGZpcnN0X3Jldmlld19hdCBURVhULFxuICAgICAgdGltZV90b19tZXJnZV9ob3VycyBSRUFMLFxuICAgICAgY2hlY2tlZF9hdCBURVhULFxuICAgICAgY3JlYXRlZF9hdCBURVhUIE5PVCBOVUxMIERFRkFVTFQgKGRhdGV0aW1lKCdub3cnKSksXG4gICAgICBVTklRVUUoc2Vzc2lvbl9pZCwgcHJfbnVtYmVyKVxuICAgIClcbiAgYCk7XG4gIGRiLnJ1bihzcWxgQ1JFQVRFIElOREVYIElGIE5PVCBFWElTVFMgaWR4X3Byc19zZXNzaW9uX2lkIE9OIHB1bGxfcmVxdWVzdHMoc2Vzc2lvbl9pZClgKTtcbiAgZGIucnVuKHNxbGBDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyBpZHhfcHJzX3N0YXR1cyBPTiBwdWxsX3JlcXVlc3RzKHN0YXR1cylgKTtcbiAgZGIucnVuKHNxbGBDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyBpZHhfcHJzX3JlcG9fYnJhbmNoIE9OIHB1bGxfcmVxdWVzdHMocmVwbywgYnJhbmNoKWApO1xuXG4gIC8vIE1pZ3JhdGlvbnM6IGFkZCBjb2x1bW5zIHRoYXQgbWF5IGJlIG1pc3NpbmcgaW4gZXhpc3RpbmcgREJzXG4gIHRyeSB7XG4gICAgZGIucnVuKHNxbGBBTFRFUiBUQUJMRSBzZXNzaW9ucyBBREQgQ09MVU1OIG1vZGVsIFRFWFRgKTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gQ29sdW1uIGFscmVhZHkgZXhpc3RzXG4gIH1cbiAgdHJ5IHtcbiAgICBkYi5ydW4oc3FsYEFMVEVSIFRBQkxFIHNlc3Npb25zIEFERCBDT0xVTU4gaGFybmVzcyBURVhUIE5PVCBOVUxMIERFRkFVTFQgJ3BpJ2ApO1xuICB9IGNhdGNoIHtcbiAgICAvLyBDb2x1bW4gYWxyZWFkeSBleGlzdHNcbiAgfVxuXG4gIC8vIEV2YWx1YXRpb24gdGFibGVzXG4gIGRiLnJ1bihzcWxgXG4gICAgQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgZXZhbF9jaGVja3MgKFxuICAgICAgaWQgSU5URUdFUiBQUklNQVJZIEtFWSBBVVRPSU5DUkVNRU5ULFxuICAgICAgc2Vzc2lvbl9pZCBURVhUIE5PVCBOVUxMLFxuICAgICAgY2hlY2tfaWQgVEVYVCBOT1QgTlVMTCxcbiAgICAgIGNoZWNrX3ZlcnNpb24gVEVYVCBOT1QgTlVMTCxcbiAgICAgIHNjb3JlIFJFQUwgTk9UIE5VTEwsXG4gICAgICByYXdfc2NvcmUgSU5URUdFUiBOT1QgTlVMTCxcbiAgICAgIHJlYXNvbmluZyBURVhUIE5PVCBOVUxMIERFRkFVTFQgJycsXG4gICAgICBldmlkZW5jZSBURVhULFxuICAgICAgbW9kZWwgVEVYVCBOT1QgTlVMTCxcbiAgICAgIGNvc3RfdXNkIFJFQUwgTk9UIE5VTEwgREVGQVVMVCAwLFxuICAgICAgZXZhbHVhdGVkX2F0IFRFWFQgTk9UIE5VTEwgREVGQVVMVCAoZGF0ZXRpbWUoJ25vdycpKSxcbiAgICAgIFVOSVFVRShzZXNzaW9uX2lkLCBjaGVja19pZCwgY2hlY2tfdmVyc2lvbilcbiAgICApXG4gIGApO1xuICBkYi5ydW4oc3FsYFxuICAgIENSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTIGV2YWxfc3VtbWFyaWVzIChcbiAgICAgIHNlc3Npb25faWQgVEVYVCBQUklNQVJZIEtFWSxcbiAgICAgIHF1YWxfc2NvcmUgUkVBTCBOT1QgTlVMTCxcbiAgICAgIGNoZWNrc19wYXNzZWQgSU5URUdFUiBOT1QgTlVMTCBERUZBVUxUIDAsXG4gICAgICBjaGVja3NfdG90YWwgSU5URUdFUiBOT1QgTlVMTCBERUZBVUxUIDAsXG4gICAgICB0b3RhbF9ldmFsX2Nvc3RfdXNkIFJFQUwgTk9UIE5VTEwgREVGQVVMVCAwLFxuICAgICAgZXZhbHVhdGVkX2F0IFRFWFQgTk9UIE5VTEwgREVGQVVMVCAoZGF0ZXRpbWUoJ25vdycpKVxuICAgIClcbiAgYCk7XG4gIGRiLnJ1bihzcWxgQ1JFQVRFIElOREVYIElGIE5PVCBFWElTVFMgaWR4X2V2YWxfY2hlY2tzX3Nlc3Npb24gT04gZXZhbF9jaGVja3Moc2Vzc2lvbl9pZClgKTtcbiAgZGIucnVuKFxuICAgIHNxbGBDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyBpZHhfZXZhbF9jaGVja3NfbG9va3VwIE9OIGV2YWxfY2hlY2tzKHNlc3Npb25faWQsIGNoZWNrX2lkLCBjaGVja192ZXJzaW9uKWAsXG4gICk7XG5cbiAgLy8gU2Vzc2lvbiBpbnNpZ2h0cyB0YWJsZSAodGVhbSBpbnNpZ2h0cyBmZWF0dXJlKVxuICBkYi5ydW4oc3FsYFxuICAgIENSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTIHNlc3Npb25faW5zaWdodHMgKFxuICAgICAgc2Vzc2lvbl9pZCBURVhUIFBSSU1BUlkgS0VZLFxuICAgICAgdGFza19jYXRlZ29yeSBURVhUIE5PVCBOVUxMLFxuICAgICAgdGFza19zaXplIFRFWFQgTk9UIE5VTEwsXG4gICAgICB3b3JrZmxvd190YWdzIFRFWFQgTk9UIE5VTEwgREVGQVVMVCAnW10nLFxuICAgICAgcHJvbXB0aW5nX3RhZ3MgVEVYVCBOT1QgTlVMTCBERUZBVUxUICdbXScsXG4gICAgICBmYWlsdXJlX21vZGVzIFRFWFQgTk9UIE5VTEwgREVGQVVMVCAnW10nLFxuICAgICAgY29tcGxleGl0eV9mYWN0b3JzIFRFWFQgTk9UIE5VTEwgREVGQVVMVCAnW10nLFxuICAgICAga2V5X2xlYXJuaW5nIFRFWFQsXG4gICAgICBleHRyYWN0ZWRfYXQgVEVYVCBOT1QgTlVMTCBERUZBVUxUIChkYXRldGltZSgnbm93JykpLFxuICAgICAgbW9kZWwgVEVYVCBOT1QgTlVMTCxcbiAgICAgIHN5bmNlZF9hdCBURVhUXG4gICAgKVxuICBgKTtcblxuICAvLyBNaWdyYXRpb25zIGZvciBzZXNzaW9uX2luc2lnaHRzIG5ldyBjb2x1bW5zXG4gIGZvciAoY29uc3QgY29sIG9mIFtcbiAgICBcImZhaWx1cmVfbW9kZXMgVEVYVCBOT1QgTlVMTCBERUZBVUxUICdbXSdcIixcbiAgICBcImNvbXBsZXhpdHlfZmFjdG9ycyBURVhUIE5PVCBOVUxMIERFRkFVTFQgJ1tdJ1wiLFxuICAgIFwia2V5X2xlYXJuaW5nIFRFWFRcIixcbiAgXSkge1xuICAgIHRyeSB7XG4gICAgICBkYi5ydW4oc3FsLnJhdyhgQUxURVIgVEFCTEUgc2Vzc2lvbl9pbnNpZ2h0cyBBREQgQ09MVU1OICR7Y29sfWApKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIENvbHVtbiBhbHJlYWR5IGV4aXN0c1xuICAgIH1cbiAgfVxuXG4gIF9kYiA9IGRiO1xuICByZXR1cm4gZGI7XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7QUFVQSxTQUFTLFFBQUFBLE9BQU0sU0FBUyxlQUFlO0FBQ3ZDLFNBQVMsY0FBQUMsYUFBWSxXQUFXLGdCQUFBQyxxQkFBb0I7QUFDcEQsU0FBUyxXQUFBQyxnQkFBZTtBQUN4QixTQUFTLHFCQUFxQjtBQUM5QixTQUFTLE9BQU8sWUFBWTtBQUM1QixTQUFTLHFCQUFxQjs7O0FDWDlCLFNBQVMsYUFBYSxjQUFjLGtCQUFrQjtBQUN0RCxTQUFTLFlBQVk7QUFDckIsU0FBUyxnQkFBZ0I7QUFDekIsU0FBUyxnQkFBZ0I7QUFFekIsU0FBUyxNQUFBQyxXQUFVOzs7QUNUbkIsU0FBUyxLQUFLLElBQUksS0FBSyxLQUFLLEtBQUssTUFBTSxLQUFLLGFBQWE7QUFDekQsU0FBUyxhQUFhLE1BQU0sZUFBZTtBQUtwQyxJQUFNLFdBQVcsWUFBWSxZQUFZO0FBQUEsRUFDOUMsSUFBSSxLQUFLLElBQUksRUFBRSxXQUFXO0FBQUEsRUFDMUIsUUFBUSxLQUFLLFNBQVMsRUFBRSxRQUFRO0FBQUEsRUFDaEMsUUFBUSxLQUFLLFNBQVMsRUFBRSxRQUFRO0FBQUEsRUFDaEMsU0FBUyxLQUFLLFNBQVMsRUFBRSxRQUFRO0FBQUEsRUFDakMsU0FBUyxLQUFLLFVBQVU7QUFBQSxFQUN4QixXQUFXLEtBQUssWUFBWTtBQUFBLEVBQzVCLFdBQVcsS0FBSyxZQUFZ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RCxhQUFPLElBQUksV0FBVztBQUFBLElBQ3hCO0FBQUEsRUFDRixRQUFRO0FBQUEsRUFBQztBQUNULFNBQU87QUFDVDtBQUVBLFNBQVMsWUFBWSxLQUFhO0FBQ2hDLFFBQU0sTUFDSixRQUFRLGFBQWEsV0FBVyxTQUFTLFFBQVEsYUFBYSxVQUFVLFVBQVU7QUFFcEYsT0FBSyxHQUFHLEdBQUcsSUFBSSxHQUFHLElBQUksTUFBTTtBQUFBLEVBRTVCLENBQUM7QUFDSDtBQUVBLEtBQUssRUFBRSxNQUFNLENBQUMsUUFBUTtBQUNwQixVQUFRLE1BQU0sZ0JBQWdCLEdBQUc7QUFDakMsVUFBUSxLQUFLLENBQUM7QUFDaEIsQ0FBQzsiLAogICJuYW1lcyI6IFsiam9pbiIsICJleGlzdHNTeW5jIiwgInJlYWRGaWxlU3luYyIsICJob21lZGlyIiwgImVxIiwgImV2ZW50cyIsICJTVUJBR0VOVF9UT09MUyIsICJwcm9qZWN0RnJvbUN3ZCIsICJnZXRGaWxlUGF0aCIsICJhcmdzIiwgInN1bW1hcml6ZVRvb2xJbnB1dCIsICJjb3VudCIsICJldmVudHMiLCAidGV4dCIsICJlcSIsICJzcWwiLCAiZGJQYXRoIiwgImRhdGFEaXIiLCAiam9pbiIsICJob21lZGlyIiwgImV4aXN0c1N5bmMiLCAicmVxdWlyZSIsICJ0ZXh0IiwgInJlYWRGaWxlU3luYyJdCn0K