source dump of claude code
at main 383 lines 48 kB view raw
1import { c as _c } from "react/compiler-runtime"; 2import * as React from 'react'; 3import type { Command } from '../commands.js'; 4import { Box } from '../ink.js'; 5import type { Screen } from '../screens/REPL.js'; 6import type { Tools } from '../Tool.js'; 7import type { RenderableMessage } from '../types/message.js'; 8import { getDisplayMessageFromCollapsed, getToolSearchOrReadInfo, getToolUseIdsFromCollapsedGroup, hasAnyToolInProgress } from '../utils/collapseReadSearch.js'; 9import { type buildMessageLookups, EMPTY_STRING_SET, getProgressMessagesFromLookup, getSiblingToolUseIDsFromLookup, getToolUseID } from '../utils/messages.js'; 10import { hasThinkingContent, Message } from './Message.js'; 11import { MessageModel } from './MessageModel.js'; 12import { shouldRenderStatically } from './Messages.js'; 13import { MessageTimestamp } from './MessageTimestamp.js'; 14import { OffscreenFreeze } from './OffscreenFreeze.js'; 15export type Props = { 16 message: RenderableMessage; 17 /** Whether the previous message in renderableMessages is also a user message. */ 18 isUserContinuation: boolean; 19 /** 20 * Whether there is non-skippable content after this message in renderableMessages. 21 * Only needs to be accurate for `collapsed_read_search` messages — used to decide 22 * if the collapsed group spinner should stay active. Pass `false` otherwise. 23 */ 24 hasContentAfter: boolean; 25 tools: Tools; 26 commands: Command[]; 27 verbose: boolean; 28 inProgressToolUseIDs: Set<string>; 29 streamingToolUseIDs: Set<string>; 30 screen: Screen; 31 canAnimate: boolean; 32 onOpenRateLimitOptions?: () => void; 33 lastThinkingBlockId: string | null; 34 latestBashOutputUUID: string | null; 35 columns: number; 36 isLoading: boolean; 37 lookups: ReturnType<typeof buildMessageLookups>; 38}; 39 40/** 41 * Scans forward from `index+1` to check if any "real" content follows. Used to 42 * decide whether a collapsed read/search group should stay in its active 43 * (grey dot, present-tense "Reading…") state while the query is still loading. 44 * 45 * Exported so Messages.tsx can compute this once per message and pass the 46 * result as a boolean prop — avoids passing the full `renderableMessages` array 47 * to each MessageRow (which React Compiler would pin in the fiber's memoCache, 48 * accumulating every historical version of the array ≈ 1-2MB over a 7-turn session). 49 */ 50export function hasContentAfterIndex(messages: RenderableMessage[], index: number, tools: Tools, streamingToolUseIDs: Set<string>): boolean { 51 for (let i = index + 1; i < messages.length; i++) { 52 const msg = messages[i]; 53 if (msg?.type === 'assistant') { 54 const content = msg.message.content[0]; 55 if (content?.type === 'thinking' || content?.type === 'redacted_thinking') { 56 continue; 57 } 58 if (content?.type === 'tool_use') { 59 if (getToolSearchOrReadInfo(content.name, content.input, tools).isCollapsible) { 60 continue; 61 } 62 // Non-collapsible tool uses appear in syntheticStreamingToolUseMessages 63 // before their ID is added to inProgressToolUseIDs. Skip while streaming 64 // to avoid briefly finalizing the read group. 65 if (streamingToolUseIDs.has(content.id)) { 66 continue; 67 } 68 } 69 return true; 70 } 71 if (msg?.type === 'system' || msg?.type === 'attachment') { 72 continue; 73 } 74 // Tool results arrive while the collapsed group is still being built 75 if (msg?.type === 'user') { 76 const content = msg.message.content[0]; 77 if (content?.type === 'tool_result') { 78 continue; 79 } 80 } 81 // Collapsible grouped_tool_use messages arrive transiently before being 82 // merged into the current collapsed group on the next render cycle 83 if (msg?.type === 'grouped_tool_use') { 84 const firstInput = msg.messages[0]?.message.content[0]?.input; 85 if (getToolSearchOrReadInfo(msg.toolName, firstInput, tools).isCollapsible) { 86 continue; 87 } 88 } 89 return true; 90 } 91 return false; 92} 93function MessageRowImpl(t0) { 94 const $ = _c(64); 95 const { 96 message: msg, 97 isUserContinuation, 98 hasContentAfter, 99 tools, 100 commands, 101 verbose, 102 inProgressToolUseIDs, 103 streamingToolUseIDs, 104 screen, 105 canAnimate, 106 onOpenRateLimitOptions, 107 lastThinkingBlockId, 108 latestBashOutputUUID, 109 columns, 110 isLoading, 111 lookups 112 } = t0; 113 const isTranscriptMode = screen === "transcript"; 114 const isGrouped = msg.type === "grouped_tool_use"; 115 const isCollapsed = msg.type === "collapsed_read_search"; 116 let t1; 117 if ($[0] !== hasContentAfter || $[1] !== inProgressToolUseIDs || $[2] !== isCollapsed || $[3] !== isLoading || $[4] !== msg) { 118 t1 = isCollapsed && (hasAnyToolInProgress(msg, inProgressToolUseIDs) || isLoading && !hasContentAfter); 119 $[0] = hasContentAfter; 120 $[1] = inProgressToolUseIDs; 121 $[2] = isCollapsed; 122 $[3] = isLoading; 123 $[4] = msg; 124 $[5] = t1; 125 } else { 126 t1 = $[5]; 127 } 128 const isActiveCollapsedGroup = t1; 129 let t2; 130 if ($[6] !== isCollapsed || $[7] !== isGrouped || $[8] !== msg) { 131 t2 = isGrouped ? msg.displayMessage : isCollapsed ? getDisplayMessageFromCollapsed(msg) : msg; 132 $[6] = isCollapsed; 133 $[7] = isGrouped; 134 $[8] = msg; 135 $[9] = t2; 136 } else { 137 t2 = $[9]; 138 } 139 const displayMsg = t2; 140 let t3; 141 if ($[10] !== isCollapsed || $[11] !== isGrouped || $[12] !== lookups || $[13] !== msg) { 142 t3 = isGrouped || isCollapsed ? [] : getProgressMessagesFromLookup(msg, lookups); 143 $[10] = isCollapsed; 144 $[11] = isGrouped; 145 $[12] = lookups; 146 $[13] = msg; 147 $[14] = t3; 148 } else { 149 t3 = $[14]; 150 } 151 const progressMessagesForMessage = t3; 152 let t4; 153 if ($[15] !== inProgressToolUseIDs || $[16] !== isCollapsed || $[17] !== isGrouped || $[18] !== lookups || $[19] !== msg || $[20] !== screen || $[21] !== streamingToolUseIDs) { 154 const siblingToolUseIDs = isGrouped || isCollapsed ? EMPTY_STRING_SET : getSiblingToolUseIDsFromLookup(msg, lookups); 155 t4 = shouldRenderStatically(msg, streamingToolUseIDs, inProgressToolUseIDs, siblingToolUseIDs, screen, lookups); 156 $[15] = inProgressToolUseIDs; 157 $[16] = isCollapsed; 158 $[17] = isGrouped; 159 $[18] = lookups; 160 $[19] = msg; 161 $[20] = screen; 162 $[21] = streamingToolUseIDs; 163 $[22] = t4; 164 } else { 165 t4 = $[22]; 166 } 167 const isStatic = t4; 168 let shouldAnimate = false; 169 if (canAnimate) { 170 if (isGrouped) { 171 let t5; 172 if ($[23] !== inProgressToolUseIDs || $[24] !== msg.messages) { 173 let t6; 174 if ($[26] !== inProgressToolUseIDs) { 175 t6 = m => { 176 const content = m.message.content[0]; 177 return content?.type === "tool_use" && inProgressToolUseIDs.has(content.id); 178 }; 179 $[26] = inProgressToolUseIDs; 180 $[27] = t6; 181 } else { 182 t6 = $[27]; 183 } 184 t5 = msg.messages.some(t6); 185 $[23] = inProgressToolUseIDs; 186 $[24] = msg.messages; 187 $[25] = t5; 188 } else { 189 t5 = $[25]; 190 } 191 shouldAnimate = t5; 192 } else { 193 if (isCollapsed) { 194 let t5; 195 if ($[28] !== inProgressToolUseIDs || $[29] !== msg) { 196 t5 = hasAnyToolInProgress(msg, inProgressToolUseIDs); 197 $[28] = inProgressToolUseIDs; 198 $[29] = msg; 199 $[30] = t5; 200 } else { 201 t5 = $[30]; 202 } 203 shouldAnimate = t5; 204 } else { 205 let t5; 206 if ($[31] !== inProgressToolUseIDs || $[32] !== msg) { 207 const toolUseID = getToolUseID(msg); 208 t5 = !toolUseID || inProgressToolUseIDs.has(toolUseID); 209 $[31] = inProgressToolUseIDs; 210 $[32] = msg; 211 $[33] = t5; 212 } else { 213 t5 = $[33]; 214 } 215 shouldAnimate = t5; 216 } 217 } 218 } 219 let t5; 220 if ($[34] !== displayMsg || $[35] !== isTranscriptMode) { 221 t5 = isTranscriptMode && displayMsg.type === "assistant" && displayMsg.message.content.some(_temp) && (displayMsg.timestamp || displayMsg.message.model); 222 $[34] = displayMsg; 223 $[35] = isTranscriptMode; 224 $[36] = t5; 225 } else { 226 t5 = $[36]; 227 } 228 const hasMetadata = t5; 229 const t6 = !hasMetadata; 230 const t7 = hasMetadata ? undefined : columns; 231 let t8; 232 if ($[37] !== commands || $[38] !== inProgressToolUseIDs || $[39] !== isActiveCollapsedGroup || $[40] !== isStatic || $[41] !== isTranscriptMode || $[42] !== isUserContinuation || $[43] !== lastThinkingBlockId || $[44] !== latestBashOutputUUID || $[45] !== lookups || $[46] !== msg || $[47] !== onOpenRateLimitOptions || $[48] !== progressMessagesForMessage || $[49] !== shouldAnimate || $[50] !== t6 || $[51] !== t7 || $[52] !== tools || $[53] !== verbose) { 233 t8 = <Message message={msg} lookups={lookups} addMargin={t6} containerWidth={t7} tools={tools} commands={commands} verbose={verbose} inProgressToolUseIDs={inProgressToolUseIDs} progressMessagesForMessage={progressMessagesForMessage} shouldAnimate={shouldAnimate} shouldShowDot={true} isTranscriptMode={isTranscriptMode} isStatic={isStatic} onOpenRateLimitOptions={onOpenRateLimitOptions} isActiveCollapsedGroup={isActiveCollapsedGroup} isUserContinuation={isUserContinuation} lastThinkingBlockId={lastThinkingBlockId} latestBashOutputUUID={latestBashOutputUUID} />; 234 $[37] = commands; 235 $[38] = inProgressToolUseIDs; 236 $[39] = isActiveCollapsedGroup; 237 $[40] = isStatic; 238 $[41] = isTranscriptMode; 239 $[42] = isUserContinuation; 240 $[43] = lastThinkingBlockId; 241 $[44] = latestBashOutputUUID; 242 $[45] = lookups; 243 $[46] = msg; 244 $[47] = onOpenRateLimitOptions; 245 $[48] = progressMessagesForMessage; 246 $[49] = shouldAnimate; 247 $[50] = t6; 248 $[51] = t7; 249 $[52] = tools; 250 $[53] = verbose; 251 $[54] = t8; 252 } else { 253 t8 = $[54]; 254 } 255 const messageEl = t8; 256 if (!hasMetadata) { 257 let t9; 258 if ($[55] !== messageEl) { 259 t9 = <OffscreenFreeze>{messageEl}</OffscreenFreeze>; 260 $[55] = messageEl; 261 $[56] = t9; 262 } else { 263 t9 = $[56]; 264 } 265 return t9; 266 } 267 let t9; 268 if ($[57] !== displayMsg || $[58] !== isTranscriptMode) { 269 t9 = <Box flexDirection="row" justifyContent="flex-end" gap={1} marginTop={1}><MessageTimestamp message={displayMsg} isTranscriptMode={isTranscriptMode} /><MessageModel message={displayMsg} isTranscriptMode={isTranscriptMode} /></Box>; 270 $[57] = displayMsg; 271 $[58] = isTranscriptMode; 272 $[59] = t9; 273 } else { 274 t9 = $[59]; 275 } 276 let t10; 277 if ($[60] !== columns || $[61] !== messageEl || $[62] !== t9) { 278 t10 = <OffscreenFreeze><Box width={columns} flexDirection="column">{t9}{messageEl}</Box></OffscreenFreeze>; 279 $[60] = columns; 280 $[61] = messageEl; 281 $[62] = t9; 282 $[63] = t10; 283 } else { 284 t10 = $[63]; 285 } 286 return t10; 287} 288 289/** 290 * Checks if a message is "streaming" - i.e., its content may still be changing. 291 * Exported for testing. 292 */ 293function _temp(c) { 294 return c.type === "text"; 295} 296export function isMessageStreaming(msg: RenderableMessage, streamingToolUseIDs: Set<string>): boolean { 297 if (msg.type === 'grouped_tool_use') { 298 return msg.messages.some(m => { 299 const content = m.message.content[0]; 300 return content?.type === 'tool_use' && streamingToolUseIDs.has(content.id); 301 }); 302 } 303 if (msg.type === 'collapsed_read_search') { 304 const toolIds = getToolUseIdsFromCollapsedGroup(msg); 305 return toolIds.some(id => streamingToolUseIDs.has(id)); 306 } 307 const toolUseID = getToolUseID(msg); 308 return !!toolUseID && streamingToolUseIDs.has(toolUseID); 309} 310 311/** 312 * Checks if all tools in a message are resolved. 313 * Exported for testing. 314 */ 315export function allToolsResolved(msg: RenderableMessage, resolvedToolUseIDs: Set<string>): boolean { 316 if (msg.type === 'grouped_tool_use') { 317 return msg.messages.every(m => { 318 const content = m.message.content[0]; 319 return content?.type === 'tool_use' && resolvedToolUseIDs.has(content.id); 320 }); 321 } 322 if (msg.type === 'collapsed_read_search') { 323 const toolIds = getToolUseIdsFromCollapsedGroup(msg); 324 return toolIds.every(id => resolvedToolUseIDs.has(id)); 325 } 326 if (msg.type === 'assistant') { 327 const block = msg.message.content[0]; 328 if (block?.type === 'server_tool_use') { 329 return resolvedToolUseIDs.has(block.id); 330 } 331 } 332 const toolUseID = getToolUseID(msg); 333 return !toolUseID || resolvedToolUseIDs.has(toolUseID); 334} 335 336/** 337 * Conservative memo comparator that only bails out when we're CERTAIN 338 * the message won't change. Fails safe by re-rendering when uncertain. 339 * 340 * Exported for testing. 341 */ 342export function areMessageRowPropsEqual(prev: Props, next: Props): boolean { 343 // Different message reference = content may have changed, must re-render 344 if (prev.message !== next.message) return false; 345 346 // Screen mode change = re-render 347 if (prev.screen !== next.screen) return false; 348 349 // Verbose toggle changes thinking block visibility 350 if (prev.verbose !== next.verbose) return false; 351 352 // collapsed_read_search is never static in prompt mode (matches shouldRenderStatically) 353 if (prev.message.type === 'collapsed_read_search' && next.screen !== 'transcript') { 354 return false; 355 } 356 357 // Width change affects Box layout 358 if (prev.columns !== next.columns) return false; 359 360 // latestBashOutputUUID affects rendering (full vs truncated output) 361 const prevIsLatestBash = prev.latestBashOutputUUID === prev.message.uuid; 362 const nextIsLatestBash = next.latestBashOutputUUID === next.message.uuid; 363 if (prevIsLatestBash !== nextIsLatestBash) return false; 364 365 // lastThinkingBlockId affects thinking block visibility — but only for 366 // messages that HAVE thinking content. Checking unconditionally busts the 367 // memo for every scrollback message whenever thinking starts/stops (CC-941). 368 if (prev.lastThinkingBlockId !== next.lastThinkingBlockId && hasThinkingContent(next.message)) { 369 return false; 370 } 371 372 // Check if this message is still "in flight" 373 const isStreaming = isMessageStreaming(prev.message, prev.streamingToolUseIDs); 374 const isResolved = allToolsResolved(prev.message, prev.lookups.resolvedToolUseIDs); 375 376 // Only bail out for truly static messages 377 if (isStreaming || !isResolved) return false; 378 379 // Static message - safe to skip re-render 380 return true; 381} 382export const MessageRow = React.memo(MessageRowImpl, areMessageRowPropsEqual); 383//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIkNvbW1hbmQiLCJCb3giLCJTY3JlZW4iLCJUb29scyIsIlJlbmRlcmFibGVNZXNzYWdlIiwiZ2V0RGlzcGxheU1lc3NhZ2VGcm9tQ29sbGFwc2VkIiwiZ2V0VG9vbFNlYXJjaE9yUmVhZEluZm8iLCJnZXRUb29sVXNlSWRzRnJvbUNvbGxhcHNlZEdyb3VwIiwiaGFzQW55VG9vbEluUHJvZ3Jlc3MiLCJidWlsZE1lc3NhZ2VMb29rdXBzIiwiRU1QVFlfU1RSSU5HX1NFVCIsImdldFByb2dyZXNzTWVzc2FnZXNGcm9tTG9va3VwIiwiZ2V0U2libGluZ1Rvb2xVc2VJRHNGcm9tTG9va3VwIiwiZ2V0VG9vbFVzZUlEIiwiaGFzVGhpbmtpbmdDb250ZW50IiwiTWVzc2FnZSIsIk1lc3NhZ2VNb2RlbCIsInNob3VsZFJlbmRlclN0YXRpY2FsbHkiLCJNZXNzYWdlVGltZXN0YW1wIiwiT2Zmc2NyZWVuRnJlZXplIiwiUHJvcHMiLCJtZXNzYWdlIiwiaXNVc2VyQ29udGludWF0aW9uIiwiaGFzQ29udGVudEFmdGVyIiwidG9vbHMiLCJjb21tYW5kcyIsInZlcmJvc2UiLCJpblByb2dyZXNzVG9vbFVzZUlEcyIsIlNldCIsInN0cmVhbWluZ1Rvb2xVc2VJRHMiLCJzY3JlZW4iLCJjYW5BbmltYXRlIiwib25PcGVuUmF0ZUxpbWl0T3B0aW9ucyIsImxhc3RUaGlua2luZ0Jsb2NrSWQiLCJsYXRlc3RCYXNoT3V0cHV0VVVJRCIsImNvbHVtbnMiLCJpc0xvYWRpbmciLCJsb29rdXBzIiwiUmV0dXJuVHlwZSIsImhhc0NvbnRlbnRBZnRlckluZGV4IiwibWVzc2FnZXMiLCJpbmRleCIsImkiLCJsZW5ndGgiLCJtc2ciLCJ0eXBlIiwiY29udGVudCIsIm5hbWUiLCJpbnB1dCIsImlzQ29sbGFwc2libGUiLCJoYXMiLCJpZCIsImZpcnN0SW5wdXQiLCJ0b29sTmFtZSIsIk1lc3NhZ2VSb3dJbXBsIiwidDAiLCIkIiwiX2MiLCJpc1RyYW5zY3JpcHRNb2RlIiwiaXNHcm91cGVkIiwiaXNDb2xsYXBzZWQiLCJ0MSIsImlzQWN0aXZlQ29sbGFwc2VkR3JvdXAiLCJ0MiIsImRpc3BsYXlNZXNzYWdlIiwiZGlzcGxheU1zZyIsInQzIiwicHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2UiLCJ0NCIsInNpYmxpbmdUb29sVXNlSURzIiwiaXNTdGF0aWMiLCJzaG91bGRBbmltYXRlIiwidDUiLCJ0NiIsIm0iLCJzb21lIiwidG9vbFVzZUlEIiwiX3RlbXAiLCJ0aW1lc3RhbXAiLCJtb2RlbCIsImhhc01ldGFkYXRhIiwidDciLCJ1bmRlZmluZWQiLCJ0OCIsIm1lc3NhZ2VFbCIsInQ5IiwidDEwIiwiYyIsImlzTWVzc2FnZVN0cmVhbWluZyIsInRvb2xJZHMiLCJhbGxUb29sc1Jlc29sdmVkIiwicmVzb2x2ZWRUb29sVXNlSURzIiwiZXZlcnkiLCJibG9jayIsImFyZU1lc3NhZ2VSb3dQcm9wc0VxdWFsIiwicHJldiIsIm5leHQiLCJwcmV2SXNMYXRlc3RCYXNoIiwidXVpZCIsIm5leHRJc0xhdGVzdEJhc2giLCJpc1N0cmVhbWluZyIsImlzUmVzb2x2ZWQiLCJNZXNzYWdlUm93IiwibWVtbyJdLCJzb3VyY2VzIjpbIk1lc3NhZ2VSb3cudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHR5cGUgeyBDb21tYW5kIH0gZnJvbSAnLi4vY29tbWFuZHMuanMnXG5pbXBvcnQgeyBCb3ggfSBmcm9tICcuLi9pbmsuanMnXG5pbXBvcnQgdHlwZSB7IFNjcmVlbiB9IGZyb20gJy4uL3NjcmVlbnMvUkVQTC5qcydcbmltcG9ydCB0eXBlIHsgVG9vbHMgfSBmcm9tICcuLi9Ub29sLmpzJ1xuaW1wb3J0IHR5cGUgeyBSZW5kZXJhYmxlTWVzc2FnZSB9IGZyb20gJy4uL3R5cGVzL21lc3NhZ2UuanMnXG5pbXBvcnQge1xuICBnZXREaXNwbGF5TWVzc2FnZUZyb21Db2xsYXBzZWQsXG4gIGdldFRvb2xTZWFyY2hPclJlYWRJbmZvLFxuICBnZXRUb29sVXNlSWRzRnJvbUNvbGxhcHNlZEdyb3VwLFxuICBoYXNBbnlUb29sSW5Qcm9ncmVzcyxcbn0gZnJvbSAnLi4vdXRpbHMvY29sbGFwc2VSZWFkU2VhcmNoLmpzJ1xuaW1wb3J0IHtcbiAgdHlwZSBidWlsZE1lc3NhZ2VMb29rdXBzLFxuICBFTVBUWV9TVFJJTkdfU0VULFxuICBnZXRQcm9ncmVzc01lc3NhZ2VzRnJvbUxvb2t1cCxcbiAgZ2V0U2libGluZ1Rvb2xVc2VJRHNGcm9tTG9va3VwLFxuICBnZXRUb29sVXNlSUQsXG59IGZyb20gJy4uL3V0aWxzL21lc3NhZ2VzLmpzJ1xuaW1wb3J0IHsgaGFzVGhpbmtpbmdDb250ZW50LCBNZXNzYWdlIH0gZnJvbSAnLi9NZXNzYWdlLmpzJ1xuaW1wb3J0IHsgTWVzc2FnZU1vZGVsIH0gZnJvbSAnLi9NZXNzYWdlTW9kZWwuanMnXG5pbXBvcnQgeyBzaG91bGRSZW5kZXJTdGF0aWNhbGx5IH0gZnJvbSAnLi9NZXNzYWdlcy5qcydcbmltcG9ydCB7IE1lc3NhZ2VUaW1lc3RhbXAgfSBmcm9tICcuL01lc3NhZ2VUaW1lc3RhbXAuanMnXG5pbXBvcnQgeyBPZmZzY3JlZW5GcmVlemUgfSBmcm9tICcuL09mZnNjcmVlbkZyZWV6ZS5qcydcblxuZXhwb3J0IHR5cGUgUHJvcHMgPSB7XG4gIG1lc3NhZ2U6IFJlbmRlcmFibGVNZXNzYWdlXG4gIC8qKiBXaGV0aGVyIHRoZSBwcmV2aW91cyBtZXNzYWdlIGluIHJlbmRlcmFibGVNZXNzYWdlcyBpcyBhbHNvIGEgdXNlciBtZXNzYWdlLiAqL1xuICBpc1VzZXJDb250aW51YXRpb246IGJvb2xlYW5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlcmUgaXMgbm9uLXNraXBwYWJsZSBjb250ZW50IGFmdGVyIHRoaXMgbWVzc2FnZSBpbiByZW5kZXJhYmxlTWVzc2FnZXMuXG4gICAqIE9ubHkgbmVlZHMgdG8gYmUgYWNjdXJhdGUgZm9yIGBjb2xsYXBzZWRfcmVhZF9zZWFyY2hgIG1lc3NhZ2VzIOKAlCB1c2VkIHRvIGRlY2lkZVxuICAgKiBpZiB0aGUgY29sbGFwc2VkIGdyb3VwIHNwaW5uZXIgc2hvdWxkIHN0YXkgYWN0aXZlLiBQYXNzIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgKi9cbiAgaGFzQ29udGVudEFmdGVyOiBib29sZWFuXG4gIHRvb2xzOiBUb29sc1xuICBjb21tYW5kczogQ29tbWFuZFtdXG4gIHZlcmJvc2U6IGJvb2xlYW5cbiAgaW5Qcm9ncmVzc1Rvb2xVc2VJRHM6IFNldDxzdHJpbmc+XG4gIHN0cmVhbWluZ1Rvb2xVc2VJRHM6IFNldDxzdHJpbmc+XG4gIHNjcmVlbjogU2NyZWVuXG4gIGNhbkFuaW1hdGU6IGJvb2xlYW5cbiAgb25PcGVuUmF0ZUxpbWl0T3B0aW9ucz86ICgpID0+IHZvaWRcbiAgbGFzdFRoaW5raW5nQmxvY2tJZDogc3RyaW5nIHwgbnVsbFxuICBsYXRlc3RCYXNoT3V0cHV0VVVJRDogc3RyaW5nIHwgbnVsbFxuICBjb2x1bW5zOiBudW1iZXJcbiAgaXNMb2FkaW5nOiBib29sZWFuXG4gIGxvb2t1cHM6IFJldHVyblR5cGU8dHlwZW9mIGJ1aWxkTWVzc2FnZUxvb2t1cHM+XG59XG5cbi8qKlxuICogU2NhbnMgZm9yd2FyZCBmcm9tIGBpbmRleCsxYCB0byBjaGVjayBpZiBhbnkgXCJyZWFsXCIgY29udGVudCBmb2xsb3dzLiBVc2VkIHRvXG4gKiBkZWNpZGUgd2hldGhlciBhIGNvbGxhcHNlZCByZWFkL3NlYXJjaCBncm91cCBzaG91bGQgc3RheSBpbiBpdHMgYWN0aXZlXG4gKiAoZ3JleSBkb3QsIHByZXNlbnQtdGVuc2UgXCJSZWFkaW5n4oCmXCIpIHN0YXRlIHdoaWxlIHRoZSBxdWVyeSBpcyBzdGlsbCBsb2FkaW5nLlxuICpcbiAqIEV4cG9ydGVkIHNvIE1lc3NhZ2VzLnRzeCBjYW4gY29tcHV0ZSB0aGlzIG9uY2UgcGVyIG1lc3NhZ2UgYW5kIHBhc3MgdGhlXG4gKiByZXN1bHQgYXMgYSBib29sZWFuIHByb3Ag4oCUIGF2b2lkcyBwYXNzaW5nIHRoZSBmdWxsIGByZW5kZXJhYmxlTWVzc2FnZXNgIGFycmF5XG4gKiB0byBlYWNoIE1lc3NhZ2VSb3cgKHdoaWNoIFJlYWN0IENvbXBpbGVyIHdvdWxkIHBpbiBpbiB0aGUgZmliZXIncyBtZW1vQ2FjaGUsXG4gKiBhY2N1bXVsYXRpbmcgZXZlcnkgaGlzdG9yaWNhbCB2ZXJzaW9uIG9mIHRoZSBhcnJheSDiiYggMS0yTUIgb3ZlciBhIDctdHVybiBzZXNzaW9uKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc0NvbnRlbnRBZnRlckluZGV4KFxuICBtZXNzYWdlczogUmVuZGVyYWJsZU1lc3NhZ2VbXSxcbiAgaW5kZXg6IG51bWJlcixcbiAgdG9vbHM6IFRvb2xzLFxuICBzdHJlYW1pbmdUb29sVXNlSURzOiBTZXQ8c3RyaW5nPixcbik6IGJvb2xlYW4ge1xuICBmb3IgKGxldCBpID0gaW5kZXggKyAxOyBpIDwgbWVzc2FnZXMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBtc2cgPSBtZXNzYWdlc1tpXVxuICAgIGlmIChtc2c/LnR5cGUgPT09ICdhc3Npc3RhbnQnKSB7XG4gICAgICBjb25zdCBjb250ZW50ID0gbXNnLm1lc3NhZ2UuY29udGVudFswXVxuICAgICAgaWYgKFxuICAgICAgICBjb250ZW50Py50eXBlID09PSAndGhpbmtpbmcnIHx8XG4gICAgICAgIGNvbnRlbnQ/LnR5cGUgPT09ICdyZWRhY3RlZF90aGlua2luZydcbiAgICAgICkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgaWYgKGNvbnRlbnQ/LnR5cGUgPT09ICd0b29sX3VzZScpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGdldFRvb2xTZWFyY2hPclJlYWRJbmZvKGNvbnRlbnQubmFtZSwgY29udGVudC5pbnB1dCwgdG9vbHMpXG4gICAgICAgICAgICAuaXNDb2xsYXBzaWJsZVxuICAgICAgICApIHtcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICAgIC8vIE5vbi1jb2xsYXBzaWJsZSB0b29sIHVzZXMgYXBwZWFyIGluIHN5bnRoZXRpY1N0cmVhbWluZ1Rvb2xVc2VNZXNzYWdlc1xuICAgICAgICAvLyBiZWZvcmUgdGhlaXIgSUQgaXMgYWRkZWQgdG8gaW5Qcm9ncmVzc1Rvb2xVc2VJRHMuIFNraXAgd2hpbGUgc3RyZWFtaW5nXG4gICAgICAgIC8vIHRvIGF2b2lkIGJyaWVmbHkgZmluYWxpemluZyB0aGUgcmVhZCBncm91cC5cbiAgICAgICAgaWYgKHN0cmVhbWluZ1Rvb2xVc2VJRHMuaGFzKGNvbnRlbnQuaWQpKSB7XG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gICAgaWYgKG1zZz8udHlwZSA9PT0gJ3N5c3RlbScgfHwgbXNnPy50eXBlID09PSAnYXR0YWNobWVudCcpIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIC8vIFRvb2wgcmVzdWx0cyBhcnJpdmUgd2hpbGUgdGhlIGNvbGxhcHNlZCBncm91cCBpcyBzdGlsbCBiZWluZyBidWlsdFxuICAgIGlmIChtc2c/LnR5cGUgPT09ICd1c2VyJykge1xuICAgICAgY29uc3QgY29udGVudCA9IG1zZy5tZXNzYWdlLmNvbnRlbnRbMF1cbiAgICAgIGlmIChjb250ZW50Py50eXBlID09PSAndG9vbF9yZXN1bHQnKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgfVxuICAgIC8vIENvbGxhcHNpYmxlIGdyb3VwZWRfdG9vbF91c2UgbWVzc2FnZXMgYXJyaXZlIHRyYW5zaWVudGx5IGJlZm9yZSBiZWluZ1xuICAgIC8vIG1lcmdlZCBpbnRvIHRoZSBjdXJyZW50IGNvbGxhcHNlZCBncm91cCBvbiB0aGUgbmV4dCByZW5kZXIgY3ljbGVcbiAgICBpZiAobXNnPy50eXBlID09PSAnZ3JvdXBlZF90b29sX3VzZScpIHtcbiAgICAgIGNvbnN0IGZpcnN0SW5wdXQgPSBtc2cubWVzc2FnZXNbMF0/Lm1lc3NhZ2UuY29udGVudFswXT8uaW5wdXRcbiAgICAgIGlmIChcbiAgICAgICAgZ2V0VG9vbFNlYXJjaE9yUmVhZEluZm8obXNnLnRvb2xOYW1lLCBmaXJzdElucHV0LCB0b29scykuaXNDb2xsYXBzaWJsZVxuICAgICAgKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlXG4gIH1cbiAgcmV0dXJuIGZhbHNlXG59XG5cbmZ1bmN0aW9uIE1lc3NhZ2VSb3dJbXBsKHtcbiAgbWVzc2FnZTogbXNnLFxuICBpc1VzZXJDb250aW51YXRpb24sXG4gIGhhc0NvbnRlbnRBZnRlcixcbiAgdG9vbHMsXG4gIGNvbW1hbmRzLFxuICB2ZXJib3NlLFxuICBpblByb2dyZXNzVG9vbFVzZUlEcyxcbiAgc3RyZWFtaW5nVG9vbFVzZUlEcyxcbiAgc2NyZWVuLFxuICBjYW5BbmltYXRlLFxuICBvbk9wZW5SYXRlTGltaXRPcHRpb25zLFxuICBsYXN0VGhpbmtpbmdCbG9ja0lkLFxuICBsYXRlc3RCYXNoT3V0cHV0VVVJRCxcbiAgY29sdW1ucyxcbiAgaXNMb2FkaW5nLFxuICBsb29rdXBzLFxufTogUHJvcHMpOiBSZWFjdC5SZWFjdE5vZGUge1xuICBjb25zdCBpc1RyYW5zY3JpcHRNb2RlID0gc2NyZWVuID09PSAndHJhbnNjcmlwdCdcbiAgY29uc3QgaXNHcm91cGVkID0gbXNnLnR5cGUgPT09ICdncm91cGVkX3Rvb2xfdXNlJ1xuICBjb25zdCBpc0NvbGxhcHNlZCA9IG1zZy50eXBlID09PSAnY29sbGFwc2VkX3JlYWRfc2VhcmNoJ1xuXG4gIC8vIEEgY29sbGFwc2VkIGdyb3VwIGlzIFwiYWN0aXZlXCIgKGdyZXkgZG90LCBwcmVzZW50IHRlbnNlIFwiUmVhZGluZ+KAplwiKSB3aGVuIGl0cyB0b29sc1xuICAvLyBhcmUgc3RpbGwgZXhlY3V0aW5nIE9SIHdoZW4gdGhlIG92ZXJhbGwgcXVlcnkgaXMgc3RpbGwgcnVubmluZyB3aXRoIG5vdGhpbmcgYWZ0ZXIgaXQuXG4gIC8vIGhhc0FueVRvb2xJblByb2dyZXNzIHRha2VzIHByaW9yaXR5OiBpZiB0b29scyBhcmUgcnVubmluZywgYWx3YXlzIHNob3cgYWN0aXZlIHJlZ2FyZGxlc3NcbiAgLy8gb2Ygd2hhdCBlbHNlIGlzIGluIHRoZSBtZXNzYWdlIGxpc3QgKGF2b2lkcyBmYWxzZSBmaW5hbGl6YXRpb24gZHVyaW5nIHBhcmFsbGVsIGV4ZWN1dGlvbikuXG4gIGNvbnN0IGlzQWN0aXZlQ29sbGFwc2VkR3JvdXAgPVxuICAgIGlzQ29sbGFwc2VkICYmXG4gICAgKGhhc0FueVRvb2xJblByb2dyZXNzKG1zZywgaW5Qcm9ncmVzc1Rvb2xVc2VJRHMpIHx8XG4gICAgICAoaXNMb2FkaW5nICYmICFoYXNDb250ZW50QWZ0ZXIpKVxuXG4gIGNvbnN0IGRpc3BsYXlNc2cgPSBpc0dyb3VwZWRcbiAgICA/IG1zZy5kaXNwbGF5TWVzc2FnZVxuICAgIDogaXNDb2xsYXBzZWRcbiAgICAgID8gZ2V0RGlzcGxheU1lc3NhZ2VGcm9tQ29sbGFwc2VkKG1zZylcbiAgICAgIDogbXNnXG5cbiAgY29uc3QgcHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2UgPVxuICAgIGlzR3JvdXBlZCB8fCBpc0NvbGxhcHNlZCA/IFtdIDogZ2V0UHJvZ3Jlc3NNZXNzYWdlc0Zyb21Mb29rdXAobXNnLCBsb29rdXBzKVxuXG4gIGNvbnN0IHNpYmxpbmdUb29sVXNlSURzID1cbiAgICBpc0dyb3VwZWQgfHwgaXNDb2xsYXBzZWRcbiAgICAgID8gRU1QVFlfU1RSSU5HX1NFVFxuICAgICAgOiBnZXRTaWJsaW5nVG9vbFVzZUlEc0Zyb21Mb29rdXAobXNnLCBsb29rdXBzKVxuXG4gIGNvbnN0IGlzU3RhdGljID0gc2hvdWxkUmVuZGVyU3RhdGljYWxseShcbiAgICBtc2csXG4gICAgc3RyZWFtaW5nVG9vbFVzZUlEcyxcbiAgICBpblByb2dyZXNzVG9vbFVzZUlEcyxcbiAgICBzaWJsaW5nVG9vbFVzZUlEcyxcbiAgICBzY3JlZW4sXG4gICAgbG9va3VwcyxcbiAgKVxuXG4gIGxldCBzaG91bGRBbmltYXRlID0gZmFsc2VcbiAgaWYgKGNhbkFuaW1hdGUpIHtcbiAgICBpZiAoaXNHcm91cGVkKSB7XG4gICAgICBzaG91bGRBbmltYXRlID0gbXNnLm1lc3NhZ2VzLnNvbWUobSA9PiB7XG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSBtLm1lc3NhZ2UuY29udGVudFswXVxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIGNvbnRlbnQ/LnR5cGUgPT09ICd0b29sX3VzZScgJiYgaW5Qcm9ncmVzc1Rvb2xVc2VJRHMuaGFzKGNvbnRlbnQuaWQpXG4gICAgICAgIClcbiAgICAgIH0pXG4gICAgfSBlbHNlIGlmIChpc0NvbGxhcHNlZCkge1xuICAgICAgc2hvdWxkQW5pbWF0ZSA9IGhhc0FueVRvb2xJblByb2dyZXNzKG1zZywgaW5Qcm9ncmVzc1Rvb2xVc2VJRHMpXG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHRvb2xVc2VJRCA9IGdldFRvb2xVc2VJRChtc2cpXG4gICAgICBzaG91bGRBbmltYXRlID0gIXRvb2xVc2VJRCB8fCBpblByb2dyZXNzVG9vbFVzZUlEcy5oYXModG9vbFVzZUlEKVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGhhc01ldGFkYXRhID1cbiAgICBpc1RyYW5zY3JpcHRNb2RlICYmXG4gICAgZGlzcGxheU1zZy50eXBlID09PSAnYXNzaXN0YW50JyAmJlxuICAgIGRpc3BsYXlNc2cubWVzc2FnZS5jb250ZW50LnNvbWUoYyA9PiBjLnR5cGUgPT09ICd0ZXh0JykgJiZcbiAgICAoZGlzcGxheU1zZy50aW1lc3RhbXAgfHwgZGlzcGxheU1zZy5tZXNzYWdlLm1vZGVsKVxuXG4gIGNvbnN0IG1lc3NhZ2VFbCA9IChcbiAgICA8TWVzc2FnZVxuICAgICAgbWVzc2FnZT17bXNnfVxuICAgICAgbG9va3Vwcz17bG9va3Vwc31cbiAgICAgIGFkZE1hcmdpbj17IWhhc01ldGFkYXRhfVxuICAgICAgY29udGFpbmVyV2lkdGg9e2hhc01ldGFkYXRhID8gdW5kZWZpbmVkIDogY29sdW1uc31cbiAgICAgIHRvb2xzPXt0b29sc31cbiAgICAgIGNvbW1hbmRzPXtjb21tYW5kc31cbiAgICAgIHZlcmJvc2U9e3ZlcmJvc2V9XG4gICAgICBpblByb2dyZXNzVG9vbFVzZUlEcz17aW5Qcm9ncmVzc1Rvb2xVc2VJRHN9XG4gICAgICBwcm9ncmVzc01lc3NhZ2VzRm9yTWVzc2FnZT17cHJvZ3Jlc3NNZXNzYWdlc0Zvck1lc3NhZ2V9XG4gICAgICBzaG91bGRBbmltYXRlPXtzaG91bGRBbmltYXRlfVxuICAgICAgc2hvdWxkU2hvd0RvdD17dHJ1ZX1cbiAgICAgIGlzVHJhbnNjcmlwdE1vZGU9e2lzVHJhbnNjcmlwdE1vZGV9XG4gICAgICBpc1N0YXRpYz17aXNTdGF0aWN9XG4gICAgICBvbk9wZW5SYXRlTGltaXRPcHRpb25zPXtvbk9wZW5SYXRlTGltaXRPcHRpb25zfVxuICAgICAgaXNBY3RpdmVDb2xsYXBzZWRHcm91cD17aXNBY3RpdmVDb2xsYXBzZWRHcm91cH1cbiAgICAgIGlzVXNlckNvbnRpbnVhdGlvbj17aXNVc2VyQ29udGludWF0aW9ufVxuICAgICAgbGFzdFRoaW5raW5nQmxvY2tJZD17bGFzdFRoaW5raW5nQmxvY2tJZH1cbiAgICAgIGxhdGVzdEJhc2hPdXRwdXRVVUlEPXtsYXRlc3RCYXNoT3V0cHV0VVVJRH1cbiAgICAvPlxuICApXG4gIC8vIE9mZnNjcmVlbkZyZWV6ZTogdGhlIG91dGVyIFJlYWN0Lm1lbW8gYWxyZWFkeSBiYWlscyBmb3Igc3RhdGljIG1lc3NhZ2VzLFxuICAvLyBzbyB0aGlzIG9ubHkgd3JhcHMgcm93cyB0aGF0IERPIHJlLXJlbmRlciDigJQgaW4tcHJvZ3Jlc3MgdG9vbHMsIGNvbGxhcHNlZFxuICAvLyByZWFkL3NlYXJjaCBzcGlubmVycywgYmFzaCBlbGFwc2VkIHRpbWVycy4gV2hlbiB0aG9zZSByb3dzIGhhdmUgc2Nyb2xsZWRcbiAgLy8gaW50byB0ZXJtaW5hbCBzY3JvbGxiYWNrIChub24tZnVsbHNjcmVlbiBleHRlcm5hbCBidWlsZHMpLCBhbnkgY29udGVudFxuICAvLyBjaGFuZ2UgZm9yY2VzIGxvZy11cGRhdGUudHMgaW50byBhIGZ1bGwgdGVybWluYWwgcmVzZXQgcGVyIHRpY2suIEZyZWV6aW5nXG4gIC8vIHJldHVybnMgdGhlIGNhY2hlZCBlbGVtZW50IHJlZiBzbyBSZWFjdCBiYWlscyBhbmQgcHJvZHVjZXMgemVybyBkaWZmLlxuICBpZiAoIWhhc01ldGFkYXRhKSB7XG4gICAgcmV0dXJuIDxPZmZzY3JlZW5GcmVlemU+e21lc3NhZ2VFbH08L09mZnNjcmVlbkZyZWV6ZT5cbiAgfVxuICAvLyBNYXJnaW4gb24gY2hpbGRyZW4sIG5vdCBoZXJlIOKAlCBlbHNlIG51bGwgaXRlbXMgKGhvb2tfc3VjY2VzcyBldGMuKSBnZXQgcGhhbnRvbSAxLXJvdyBzcGFjaW5nLlxuICByZXR1cm4gKFxuICAgIDxPZmZzY3JlZW5GcmVlemU+XG4gICAgICA8Qm94IHdpZHRoPXtjb2x1bW5zfSBmbGV4RGlyZWN0aW9uPVwiY29sdW1uXCI+XG4gICAgICAgIDxCb3hcbiAgICAgICAgICBmbGV4RGlyZWN0aW9uPVwicm93XCJcbiAgICAgICAgICBqdXN0aWZ5Q29udGVudD1cImZsZXgtZW5kXCJcbiAgICAgICAgICBnYXA9ezF9XG4gICAgICAgICAgbWFyZ2luVG9wPXsxfVxuICAgICAgICA+XG4gICAgICAgICAgPE1lc3NhZ2VUaW1lc3RhbXBcbiAgICAgICAgICAgIG1lc3NhZ2U9e2Rpc3BsYXlNc2d9XG4gICAgICAgICAgICBpc1RyYW5zY3JpcHRNb2RlPXtpc1RyYW5zY3JpcHRNb2RlfVxuICAgICAgICAgIC8+XG4gICAgICAgICAgPE1lc3NhZ2VNb2RlbFxuICAgICAgICAgICAgbWVzc2FnZT17ZGlzcGxheU1zZ31cbiAgICAgICAgICAgIGlzVHJhbnNjcmlwdE1vZGU9e2lzVHJhbnNjcmlwdE1vZGV9XG4gICAgICAgICAgLz5cbiAgICAgICAgPC9Cb3g+XG4gICAgICAgIHttZXNzYWdlRWx9XG4gICAgICA8L0JveD5cbiAgICA8L09mZnNjcmVlbkZyZWV6ZT5cbiAgKVxufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIG1lc3NhZ2UgaXMgXCJzdHJlYW1pbmdcIiAtIGkuZS4sIGl0cyBjb250ZW50IG1heSBzdGlsbCBiZSBjaGFuZ2luZy5cbiAqIEV4cG9ydGVkIGZvciB0ZXN0aW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNNZXNzYWdlU3RyZWFtaW5nKFxuICBtc2c6IFJlbmRlcmFibGVNZXNzYWdlLFxuICBzdHJlYW1pbmdUb29sVXNlSURzOiBTZXQ8c3RyaW5nPixcbik6IGJvb2xlYW4ge1xuICBpZiAobXNnLnR5cGUgPT09ICdncm91cGVkX3Rvb2xfdXNlJykge1xuICAgIHJldHVybiBtc2cubWVzc2FnZXMuc29tZShtID0+IHtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBtLm1lc3NhZ2UuY29udGVudFswXVxuICAgICAgcmV0dXJuIGNvbnRlbnQ/LnR5cGUgPT09ICd0b29sX3VzZScgJiYgc3RyZWFtaW5nVG9vbFVzZUlEcy5oYXMoY29udGVudC5pZClcbiAgICB9KVxuICB9XG4gIGlmIChtc2cudHlwZSA9PT0gJ2NvbGxhcHNlZF9yZWFkX3NlYXJjaCcpIHtcbiAgICBjb25zdCB0b29sSWRzID0gZ2V0VG9vbFVzZUlkc0Zyb21Db2xsYXBzZWRHcm91cChtc2cpXG4gICAgcmV0dXJuIHRvb2xJZHMuc29tZShpZCA9PiBzdHJlYW1pbmdUb29sVXNlSURzLmhhcyhpZCkpXG4gIH1cbiAgY29uc3QgdG9vbFVzZUlEID0gZ2V0VG9vbFVzZUlEKG1zZylcbiAgcmV0dXJuICEhdG9vbFVzZUlEICYmIHN0cmVhbWluZ1Rvb2xVc2VJRHMuaGFzKHRvb2xVc2VJRClcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYWxsIHRvb2xzIGluIGEgbWVzc2FnZSBhcmUgcmVzb2x2ZWQuXG4gKiBFeHBvcnRlZCBmb3IgdGVzdGluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFsbFRvb2xzUmVzb2x2ZWQoXG4gIG1zZzogUmVuZGVyYWJsZU1lc3NhZ2UsXG4gIHJlc29sdmVkVG9vbFVzZUlEczogU2V0PHN0cmluZz4sXG4pOiBib29sZWFuIHtcbiAgaWYgKG1zZy50eXBlID09PSAnZ3JvdXBlZF90b29sX3VzZScpIHtcbiAgICByZXR1cm4gbXNnLm1lc3NhZ2VzLmV2ZXJ5KG0gPT4ge1xuICAgICAgY29uc3QgY29udGVudCA9IG0ubWVzc2FnZS5jb250ZW50WzBdXG4gICAgICByZXR1cm4gY29udGVudD8udHlwZSA9PT0gJ3Rvb2xfdXNlJyAmJiByZXNvbHZlZFRvb2xVc2VJRHMuaGFzKGNvbnRlbnQuaWQpXG4gICAgfSlcbiAgfVxuICBpZiAobXNnLnR5cGUgPT09ICdjb2xsYXBzZWRfcmVhZF9zZWFyY2gnKSB7XG4gICAgY29uc3QgdG9vbElkcyA9IGdldFRvb2xVc2VJZHNGcm9tQ29sbGFwc2VkR3JvdXAobXNnKVxuICAgIHJldHVybiB0b29sSWRzLmV2ZXJ5KGlkID0+IHJlc29sdmVkVG9vbFVzZUlEcy5oYXMoaWQpKVxuICB9XG4gIGlmIChtc2cudHlwZSA9PT0gJ2Fzc2lzdGFudCcpIHtcbiAgICBjb25zdCBibG9jayA9IG1zZy5tZXNzYWdlLmNvbnRlbnRbMF1cbiAgICBpZiAoYmxvY2s/LnR5cGUgPT09ICdzZXJ2ZXJfdG9vbF91c2UnKSB7XG4gICAgICByZXR1cm4gcmVzb2x2ZWRUb29sVXNlSURzLmhhcyhibG9jay5pZClcbiAgICB9XG4gIH1cbiAgY29uc3QgdG9vbFVzZUlEID0gZ2V0VG9vbFVzZUlEKG1zZylcbiAgcmV0dXJuICF0b29sVXNlSUQgfHwgcmVzb2x2ZWRUb29sVXNlSURzLmhhcyh0b29sVXNlSUQpXG59XG5cbi8qKlxuICogQ29uc2VydmF0aXZlIG1lbW8gY29tcGFyYXRvciB0aGF0IG9ubHkgYmFpbHMgb3V0IHdoZW4gd2UncmUgQ0VSVEFJTlxuICogdGhlIG1lc3NhZ2Ugd29uJ3QgY2hhbmdlLiBGYWlscyBzYWZlIGJ5IHJlLXJlbmRlcmluZyB3aGVuIHVuY2VydGFpbi5cbiAqXG4gKiBFeHBvcnRlZCBmb3IgdGVzdGluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFyZU1lc3NhZ2VSb3dQcm9wc0VxdWFsKHByZXY6IFByb3BzLCBuZXh0OiBQcm9wcyk6IGJvb2xlYW4ge1xuICAvLyBEaWZmZXJlbnQgbWVzc2FnZSByZWZlcmVuY2UgPSBjb250ZW50IG1heSBoYXZlIGNoYW5nZWQsIG11c3QgcmUtcmVuZGVyXG4gIGlmIChwcmV2Lm1lc3NhZ2UgIT09IG5leHQubWVzc2FnZSkgcmV0dXJuIGZhbHNlXG5cbiAgLy8gU2NyZWVuIG1vZGUgY2hhbmdlID0gcmUtcmVuZGVyXG4gIGlmIChwcmV2LnNjcmVlbiAhPT0gbmV4dC5zY3JlZW4pIHJldHVybiBmYWxzZVxuXG4gIC8vIFZlcmJvc2UgdG9nZ2xlIGNoYW5nZXMgdGhpbmtpbmcgYmxvY2sgdmlzaWJpbGl0eVxuICBpZiAocHJldi52ZXJib3NlICE9PSBuZXh0LnZlcmJvc2UpIHJldHVybiBmYWxzZVxuXG4gIC8vIGNvbGxhcHNlZF9yZWFkX3NlYXJjaCBpcyBuZXZlciBzdGF0aWMgaW4gcHJvbXB0IG1vZGUgKG1hdGNoZXMgc2hvdWxkUmVuZGVyU3RhdGljYWxseSlcbiAgaWYgKFxuICAgIHByZXYubWVzc2FnZS50eXBlID09PSAnY29sbGFwc2VkX3JlYWRfc2VhcmNoJyAmJlxuICAgIG5leHQuc2NyZWVuICE9PSAndHJhbnNjcmlwdCdcbiAgKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICAvLyBXaWR0aCBjaGFuZ2UgYWZmZWN0cyBCb3ggbGF5b3V0XG4gIGlmIChwcmV2LmNvbHVtbnMgIT09IG5leHQuY29sdW1ucykgcmV0dXJuIGZhbHNlXG5cbiAgLy8gbGF0ZXN0QmFzaE91dHB1dFVVSUQgYWZmZWN0cyByZW5kZXJpbmcgKGZ1bGwgdnMgdHJ1bmNhdGVkIG91dHB1dClcbiAgY29uc3QgcHJldklzTGF0ZXN0QmFzaCA9IHByZXYubGF0ZXN0QmFzaE91dHB1dFVVSUQgPT09IHByZXYubWVzc2FnZS51dWlkXG4gIGNvbnN0IG5leHRJc0xhdGVzdEJhc2ggPSBuZXh0LmxhdGVzdEJhc2hPdXRwdXRVVUlEID09PSBuZXh0Lm1lc3NhZ2UudXVpZFxuICBpZiAocHJldklzTGF0ZXN0QmFzaCAhPT0gbmV4dElzTGF0ZXN0QmFzaCkgcmV0dXJuIGZhbHNlXG5cbiAgLy8gbGFzdFRoaW5raW5nQmxvY2tJZCBhZmZlY3RzIHRoaW5raW5nIGJsb2NrIHZpc2liaWxpdHkg4oCUIGJ1dCBvbmx5IGZvclxuICAvLyBtZXNzYWdlcyB0aGF0IEhBVkUgdGhpbmtpbmcgY29udGVudC4gQ2hlY2tpbmcgdW5jb25kaXRpb25hbGx5IGJ1c3RzIHRoZVxuICAvLyBtZW1vIGZvciBldmVyeSBzY3JvbGxiYWNrIG1lc3NhZ2Ugd2hlbmV2ZXIgdGhpbmtpbmcgc3RhcnRzL3N0b3BzIChDQy05NDEpLlxuICBpZiAoXG4gICAgcHJldi5sYXN0VGhpbmtpbmdCbG9ja0lkICE9PSBuZXh0Lmxhc3RUaGlua2luZ0Jsb2NrSWQgJiZcbiAgICBoYXNUaGlua2luZ0NvbnRlbnQobmV4dC5tZXNzYWdlKVxuICApIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIC8vIENoZWNrIGlmIHRoaXMgbWVzc2FnZSBpcyBzdGlsbCBcImluIGZsaWdodFwiXG4gIGNvbnN0IGlzU3RyZWFtaW5nID0gaXNNZXNzYWdlU3RyZWFtaW5nKHByZXYubWVzc2FnZSwgcHJldi5zdHJlYW1pbmdUb29sVXNlSURzKVxuICBjb25zdCBpc1Jlc29sdmVkID0gYWxsVG9vbHNSZXNvbHZlZChcbiAgICBwcmV2Lm1lc3NhZ2UsXG4gICAgcHJldi5sb29rdXBzLnJlc29sdmVkVG9vbFVzZUlEcyxcbiAgKVxuXG4gIC8vIE9ubHkgYmFpbCBvdXQgZm9yIHRydWx5IHN0YXRpYyBtZXNzYWdlc1xuICBpZiAoaXNTdHJlYW1pbmcgfHwgIWlzUmVzb2x2ZWQpIHJldHVybiBmYWxzZVxuXG4gIC8vIFN0YXRpYyBtZXNzYWdlIC0gc2FmZSB0byBza2lwIHJlLXJlbmRlclxuICByZXR1cm4gdHJ1ZVxufVxuXG5leHBvcnQgY29uc3QgTWVzc2FnZVJvdyA9IFJlYWN0Lm1l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