@dollhousemcp/mcp-server 2.0.17 → 2.0.18

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 (51) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/elements/BaseElement.d.ts +1 -0
  3. package/dist/elements/BaseElement.d.ts.map +1 -1
  4. package/dist/elements/BaseElement.js +7 -1
  5. package/dist/elements/agents/AgentManager.js +2 -2
  6. package/dist/elements/base/ElementFileOperations.js +2 -2
  7. package/dist/elements/ensembles/EnsembleManager.js +3 -3
  8. package/dist/elements/memories/MemoryManager.js +2 -2
  9. package/dist/elements/skills/SkillManager.js +2 -2
  10. package/dist/elements/templates/TemplateManager.js +2 -2
  11. package/dist/generated/version.d.ts +2 -2
  12. package/dist/generated/version.js +3 -3
  13. package/dist/handlers/ElementCRUDHandler.d.ts.map +1 -1
  14. package/dist/handlers/ElementCRUDHandler.js +3 -2
  15. package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts +1 -0
  16. package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts.map +1 -1
  17. package/dist/handlers/mcp-aql/MCPAQLHandler.js +35 -14
  18. package/dist/handlers/mcp-aql/policies/ElementPolicies.d.ts +9 -1
  19. package/dist/handlers/mcp-aql/policies/ElementPolicies.d.ts.map +1 -1
  20. package/dist/handlers/mcp-aql/policies/ElementPolicies.js +63 -4
  21. package/dist/handlers/strategies/AgentActivationStrategy.d.ts.map +1 -1
  22. package/dist/handlers/strategies/AgentActivationStrategy.js +5 -1
  23. package/dist/handlers/strategies/BaseActivationStrategy.d.ts +1 -0
  24. package/dist/handlers/strategies/BaseActivationStrategy.d.ts.map +1 -1
  25. package/dist/handlers/strategies/BaseActivationStrategy.js +15 -1
  26. package/dist/handlers/strategies/EnsembleActivationStrategy.d.ts.map +1 -1
  27. package/dist/handlers/strategies/EnsembleActivationStrategy.js +5 -1
  28. package/dist/handlers/strategies/MemoryActivationStrategy.d.ts.map +1 -1
  29. package/dist/handlers/strategies/MemoryActivationStrategy.js +5 -1
  30. package/dist/handlers/strategies/PersonaActivationStrategy.d.ts.map +1 -1
  31. package/dist/handlers/strategies/PersonaActivationStrategy.js +5 -1
  32. package/dist/handlers/strategies/SkillActivationStrategy.d.ts.map +1 -1
  33. package/dist/handlers/strategies/SkillActivationStrategy.js +5 -1
  34. package/dist/handlers/strategies/TemplateActivationStrategy.d.ts.map +1 -1
  35. package/dist/handlers/strategies/TemplateActivationStrategy.js +7 -2
  36. package/dist/persona/PersonaElement.js +2 -2
  37. package/dist/services/SerializationService.d.ts.map +1 -1
  38. package/dist/services/SerializationService.js +7 -1
  39. package/dist/types/elements/IElement.d.ts +9 -0
  40. package/dist/types/elements/IElement.d.ts.map +1 -1
  41. package/dist/types/elements/IElement.js +1 -1
  42. package/dist/web/public/permissions.css +190 -2
  43. package/dist/web/public/permissions.js +171 -30
  44. package/dist/web/public/setup.js +131 -60
  45. package/dist/web/routes/permissionRoutes.d.ts.map +1 -1
  46. package/dist/web/routes/permissionRoutes.js +77 -5
  47. package/dist/web/routes/setupRoutes.d.ts.map +1 -1
  48. package/dist/web/routes/setupRoutes.js +16 -2
  49. package/package.json +1 -1
  50. package/scripts/pretooluse-dollhouse.sh +39 -1
  51. package/server.json +2 -2
@@ -18,13 +18,13 @@
18
18
  const PLATFORMS = [
19
19
  // Claude Desktop & Claude Code panels are handwritten in HTML (unique structure)
20
20
  { id: 'claude-desktop', rootKey: 'mcpServers' },
21
- { id: 'claude-code', rootKey: 'mcpServers', cli: 'claude', hookSupport: 'verified', hookCommand: `bash ${HOOK_BASE_SCRIPT_PATH}`, hookConfigPath: '<code>~/.claude/settings.json</code>' },
21
+ { id: 'claude-code', rootKey: 'mcpServers', cli: 'claude', hookCommand: `bash ${HOOK_BASE_SCRIPT_PATH}`, hookConfigPath: '<code>~/.claude/settings.json</code>' },
22
22
  // These panels are generated from this data by renderGeneratedPanels()
23
- { id: 'cursor', rootKey: 'mcpServers', installClient: 'cursor', openClient: 'cursor', configPath: '<code>.cursor/mcp.json</code> in your project, or <code>~/.cursor/mcp.json</code> for all projects', hint: 'Or configure via Settings &gt; MCP Servers in the Cursor UI.', hookSupport: 'partial', hookCommand: `bash ${HOOKS_DIR}/pretooluse-cursor.sh`, hookConfigPath: '<code>.cursor/hooks.json</code> in your project, or <code>~/.cursor/hooks.json</code> for all projects' },
24
- { id: 'vscode', rootKey: 'servers', installClient: 'vscode', configPath: '<code>.vscode/mcp.json</code> in your workspace', hint: 'VS Code uses <code>"servers"</code>, not <code>"mcpServers"</code>.', hookSupport: 'partial', hookCommand: `bash ${HOOKS_DIR}/pretooluse-vscode.sh`, hookConfigPath: '<code>~/.copilot/hooks/dollhouse-permissions.json</code> plus <code>chat.hookFilesLocations</code> in VS Code user settings' },
25
- { id: 'codex', rootKey: 'mcpServers', installClient: 'codex', openClient: 'codex', cli: 'codex', toml: true, tomlPath: '<code>~/.codex/config.toml</code> (Codex uses TOML, not JSON)', hookSupport: 'partial', hookCommand: `bash ${HOOKS_DIR}/pretooluse-codex.sh`, hookConfigPath: '<code>~/.codex/hooks.json</code> and <code>~/.codex/config.toml</code>' },
26
- { id: 'gemini', rootKey: 'mcpServers', installClient: 'gemini-cli', openClient: 'gemini-cli', cli: 'gemini', configPath: '<code>~/.gemini/settings.json</code> or <code>.gemini/settings.json</code> in your project', hookSupport: 'partial', hookCommand: `bash ${HOOKS_DIR}/pretooluse-gemini.sh`, hookConfigPath: '<code>~/.gemini/settings.json</code> or <code>.gemini/settings.json</code> in your project' },
27
- { id: 'windsurf', rootKey: 'mcpServers', installClient: 'windsurf', openClient: 'windsurf', configPath: '<code>~/.codeium/windsurf/mcp_config.json</code>', hint: 'Or click the MCPs icon in the Cascade panel &gt; Configure.', hookSupport: 'partial', hookCommand: `bash ${HOOKS_DIR}/pretooluse-windsurf.sh`, hookConfigPath: '<code>~/.codeium/windsurf/hooks.json</code> or <code>.windsurf/hooks.json</code> in your project' },
23
+ { id: 'cursor', rootKey: 'mcpServers', installClient: 'cursor', openClient: 'cursor', configPath: '<code>.cursor/mcp.json</code> in your project, or <code>~/.cursor/mcp.json</code> for all projects', hint: 'Or configure via Settings &gt; MCP Servers in the Cursor UI.', hookCommand: `bash ${HOOKS_DIR}/pretooluse-cursor.sh`, hookConfigPath: '<code>.cursor/hooks.json</code> in your project, or <code>~/.cursor/hooks.json</code> for all projects' },
24
+ { id: 'vscode', rootKey: 'servers', installClient: 'vscode', configPath: '<code>.vscode/mcp.json</code> in your workspace', hint: 'VS Code uses <code>"servers"</code>, not <code>"mcpServers"</code>.', hookCommand: `bash ${HOOKS_DIR}/pretooluse-vscode.sh`, hookConfigPath: '<code>~/.copilot/hooks/dollhouse-permissions.json</code> plus <code>chat.hookFilesLocations</code> in VS Code user settings' },
25
+ { id: 'codex', rootKey: 'mcpServers', installClient: 'codex', openClient: 'codex', cli: 'codex', toml: true, tomlPath: '<code>~/.codex/config.toml</code> (Codex uses TOML, not JSON)', hookCommand: `bash ${HOOKS_DIR}/pretooluse-codex.sh`, hookConfigPath: '<code>~/.codex/hooks.json</code> and <code>~/.codex/config.toml</code>' },
26
+ { id: 'gemini', rootKey: 'mcpServers', installClient: 'gemini-cli', openClient: 'gemini-cli', cli: 'gemini', configPath: '<code>~/.gemini/settings.json</code> or <code>.gemini/settings.json</code> in your project', hookCommand: `bash ${HOOKS_DIR}/pretooluse-gemini.sh`, hookConfigPath: '<code>~/.gemini/settings.json</code> or <code>.gemini/settings.json</code> in your project' },
27
+ { id: 'windsurf', rootKey: 'mcpServers', installClient: 'windsurf', openClient: 'windsurf', configPath: '<code>~/.codeium/windsurf/mcp_config.json</code>', hint: 'Or click the MCPs icon in the Cascade panel &gt; Configure.', hookCommand: `bash ${HOOKS_DIR}/pretooluse-windsurf.sh`, hookConfigPath: '<code>~/.codeium/windsurf/hooks.json</code> or <code>.windsurf/hooks.json</code> in your project' },
28
28
  { id: 'cline', rootKey: 'mcpServers', installClient: 'cline', openClient: 'cline', configPath: 'Cline stores MCP servers in <code>cline_mcp_settings.json</code> inside its extension settings. Use Configure Now or open the file directly.' },
29
29
  { id: 'lmstudio', rootKey: 'mcpServers', installClient: 'lmstudio', openClient: 'lmstudio', configPath: '<code>~/.lmstudio/mcp.json</code> (or open via Program tab &gt; Install &gt; Edit mcp.json)', hint: 'Restart LM Studio after saving.' },
30
30
  ];
@@ -888,6 +888,7 @@ codex_hooks = true`;
888
888
  'claude': 'claude-desktop',
889
889
  'claude-code': 'claude-code',
890
890
  'cursor': 'cursor',
891
+ 'cline': 'cline',
891
892
  'windsurf': 'windsurf',
892
893
  'lmstudio': 'lmstudio',
893
894
  'gemini-cli': 'gemini',
@@ -965,32 +966,29 @@ codex_hooks = true`;
965
966
  }
966
967
  };
967
968
 
968
- const PERMISSION_PLATFORM_LABELS = {
969
- 'claude-desktop': 'Claude Desktop',
970
- 'claude-code': 'Claude Code',
971
- cursor: 'Cursor',
972
- vscode: 'VS Code',
973
- codex: 'Codex',
974
- gemini: 'Gemini CLI',
975
- windsurf: 'Windsurf',
976
- cline: 'Cline',
977
- lmstudio: 'LM Studio',
978
- };
979
-
980
- const VERIFIED_PERMISSION_PLATFORMS = {
969
+ const PERMISSION_SUPPORT_MATRIX = {
970
+ 'claude-desktop': {
971
+ label: 'Claude Desktop',
972
+ supportLevel: 'unsupported',
973
+ statusTag: 'coming soon',
974
+ badgeClass: 'unsupported',
975
+ limitation: 'Claude Desktop can host DollhouseMCP, but this release does not ship a native permissions setup flow for it yet.',
976
+ },
981
977
  'claude-code': {
982
978
  label: 'Claude Code',
979
+ supportLevel: 'full_native',
983
980
  statusTag: 'claude code',
981
+ badgeClass: 'verified',
984
982
  configPath: '<code>~/.claude/settings.json</code>',
985
983
  scriptPath: HOOK_BASE_SCRIPT_PATH,
986
984
  settingsBlock: CLAUDE_CODE_HOOK_SETTINGS,
985
+ limitation: 'Claude Code has the full native permission-hook path in this release.',
987
986
  },
988
- };
989
-
990
- const PARTIAL_PERMISSION_PLATFORMS = {
991
987
  gemini: {
992
988
  label: 'Gemini CLI',
989
+ supportLevel: 'partial_native',
993
990
  statusTag: 'allow / deny',
991
+ badgeClass: 'manual',
994
992
  configPath: '<code>~/.gemini/settings.json</code> or <code>.gemini/settings.json</code> in your project',
995
993
  scriptPath: `${HOOKS_DIR}/pretooluse-gemini.sh`,
996
994
  settingsBlock: GEMINI_HOOK_SETTINGS,
@@ -998,7 +996,9 @@ codex_hooks = true`;
998
996
  },
999
997
  cursor: {
1000
998
  label: 'Cursor',
999
+ supportLevel: 'partial_native',
1001
1000
  statusTag: 'native hooks',
1001
+ badgeClass: 'manual',
1002
1002
  configPath: '<code>.cursor/hooks.json</code> in your project, or <code>~/.cursor/hooks.json</code> for all projects',
1003
1003
  scriptPath: `${HOOKS_DIR}/pretooluse-cursor.sh`,
1004
1004
  settingsBlock: CURSOR_HOOK_SETTINGS,
@@ -1006,7 +1006,9 @@ codex_hooks = true`;
1006
1006
  },
1007
1007
  vscode: {
1008
1008
  label: 'VS Code',
1009
+ supportLevel: 'partial_native',
1009
1010
  statusTag: 'native hooks',
1011
+ badgeClass: 'manual',
1010
1012
  configPath: '<code>~/.copilot/hooks/dollhouse-permissions.json</code> and VS Code user settings',
1011
1013
  scriptPath: `${HOOKS_DIR}/pretooluse-vscode.sh`,
1012
1014
  settingsBlock: VSCODE_HOOK_SETTINGS,
@@ -1017,7 +1019,9 @@ codex_hooks = true`;
1017
1019
  },
1018
1020
  windsurf: {
1019
1021
  label: 'Windsurf',
1022
+ supportLevel: 'partial_native',
1020
1023
  statusTag: 'allow / deny',
1024
+ badgeClass: 'manual',
1021
1025
  configPath: '<code>~/.codeium/windsurf/hooks.json</code> or <code>.windsurf/hooks.json</code> in your project',
1022
1026
  scriptPath: `${HOOKS_DIR}/pretooluse-windsurf.sh`,
1023
1027
  settingsBlock: WINDSURF_HOOK_SETTINGS,
@@ -1025,20 +1029,46 @@ codex_hooks = true`;
1025
1029
  },
1026
1030
  codex: {
1027
1031
  label: 'Codex',
1032
+ supportLevel: 'partial_native',
1028
1033
  statusTag: 'bash only',
1034
+ badgeClass: 'manual',
1029
1035
  configPath: '<code>~/.codex/hooks.json</code> and <code>~/.codex/config.toml</code>',
1030
1036
  scriptPath: `${HOOKS_DIR}/pretooluse-codex.sh`,
1031
1037
  settingsBlock: CODEX_HOOK_SETTINGS,
1032
1038
  featureBlock: CODEX_HOOK_FEATURES_TOML,
1033
1039
  limitation: 'Codex currently only supports native PreToolUse hooks for Bash, so this turns on Bash permission guardrails only.',
1034
1040
  },
1041
+ cline: {
1042
+ label: 'Cline',
1043
+ supportLevel: 'mcp_only',
1044
+ statusTag: 'mcp only',
1045
+ badgeClass: 'manual',
1046
+ limitation: 'Cline MCP setup is supported here, but native permission-hook automation is still incomplete in this release.',
1047
+ },
1048
+ lmstudio: {
1049
+ label: 'LM Studio',
1050
+ supportLevel: 'mcp_only',
1051
+ statusTag: 'mcp only',
1052
+ badgeClass: 'manual',
1053
+ limitation: 'LM Studio MCP setup is supported here, but permission enforcement currently relies on LM Studio built-in confirmations or a future fallback adapter.',
1054
+ },
1055
+ };
1056
+
1057
+ const getPermissionSupport = (platformId, detected) => {
1058
+ if (detected?.support) {
1059
+ return {
1060
+ ...PERMISSION_SUPPORT_MATRIX[platformId],
1061
+ supportLevel: detected.support.level || PERMISSION_SUPPORT_MATRIX[platformId]?.supportLevel,
1062
+ };
1063
+ }
1064
+ return PERMISSION_SUPPORT_MATRIX[platformId];
1035
1065
  };
1036
1066
 
1037
- const getVerifiedPermissionStatusCopy = (verified, detected) => {
1067
+ const getFullNativePermissionStatusCopy = (support, detected) => {
1038
1068
  if (detected?.hookInstalled) {
1039
1069
  return {
1040
1070
  tone: 'info',
1041
- titleText: `${verified.label} permission enforcement is enabled.`,
1071
+ titleText: `${support.label} permission enforcement is enabled.`,
1042
1072
  messageText: 'No further changes are needed here unless you want to reinstall the hook settings.',
1043
1073
  };
1044
1074
  }
@@ -1046,44 +1076,60 @@ codex_hooks = true`;
1046
1076
  if (detected?.installed) {
1047
1077
  return {
1048
1078
  tone: 'warning',
1049
- titleText: `${verified.label} is connected for this client.`,
1050
- messageText: `DollhouseMCP is configured as an MCP server. Use Configure Now below to also install the ${verified.label} permission hook.`,
1079
+ titleText: `${support.label} is connected for this client.`,
1080
+ messageText: `DollhouseMCP is configured as an MCP server. Use Configure Now below to also install the ${support.label} permission hook.`,
1051
1081
  };
1052
1082
  }
1053
1083
 
1054
1084
  return {
1055
1085
  tone: 'info',
1056
- titleText: `${verified.label} permissions are not configured yet.`,
1057
- messageText: `First connect DollhouseMCP using Auto-updating or Pinned version, then use Configure Now below to install the ${verified.label} permission hook.`,
1086
+ titleText: `${support.label} permissions are not configured yet.`,
1087
+ messageText: `First connect DollhouseMCP using Auto-updating or Pinned version, then use Configure Now below to install the ${support.label} permission hook.`,
1058
1088
  };
1059
1089
  };
1060
1090
 
1061
- const getPartialPermissionStatusCopy = (partial, detected) => {
1062
- const activationLabel = partial.label === 'Codex' ? 'Bash guardrails' : 'permission hooks';
1091
+ const getPartialPermissionStatusCopy = (support, detected) => {
1092
+ const activationLabel = support.label === 'Codex' ? 'Bash guardrails' : 'permission hooks';
1063
1093
  if (detected?.hookInstalled) {
1064
1094
  return {
1065
1095
  tone: 'info',
1066
- titleText: `${partial.label} ${activationLabel} are enabled.`,
1067
- messageText: partial.limitation,
1096
+ titleText: `${support.label} ${activationLabel} are enabled.`,
1097
+ messageText: support.limitation,
1068
1098
  };
1069
1099
  }
1070
1100
 
1071
1101
  if (detected?.installed) {
1072
1102
  return {
1073
1103
  tone: 'warning',
1074
- titleText: `${partial.label} is connected for this client.`,
1075
- messageText: `DollhouseMCP is configured as an MCP server. Use Configure Now below to turn on ${partial.label}'s native ${activationLabel}.`,
1104
+ titleText: `${support.label} is connected for this client.`,
1105
+ messageText: `DollhouseMCP is configured as an MCP server. Use Configure Now below to turn on ${support.label}'s native ${activationLabel}.`,
1076
1106
  };
1077
1107
  }
1078
1108
 
1079
1109
  return {
1080
1110
  tone: 'info',
1081
- titleText: `${partial.label} ${activationLabel} are not configured yet.`,
1082
- messageText: `First connect DollhouseMCP using Auto-updating or Pinned version, then use Configure Now below to install ${partial.label}'s native ${activationLabel}.`,
1111
+ titleText: `${support.label} ${activationLabel} are not configured yet.`,
1112
+ messageText: `First connect DollhouseMCP using Auto-updating or Pinned version, then use Configure Now below to install ${support.label}'s native ${activationLabel}.`,
1083
1113
  };
1084
1114
  };
1085
1115
 
1086
- const getManualPermissionStatusCopy = (detected) => {
1116
+ const getMcpOnlyPermissionStatusCopy = (support, detected) => {
1117
+ if (detected?.installed) {
1118
+ return {
1119
+ tone: 'warning',
1120
+ titleText: `${support.label} is connected for this client.`,
1121
+ messageText: `${support.limitation} This release keeps that client in the MCP and fallback lane for now.`,
1122
+ };
1123
+ }
1124
+
1125
+ return {
1126
+ tone: 'info',
1127
+ titleText: `${support.label} supports MCP setup in this release.`,
1128
+ messageText: `${support.limitation} Use Auto-updating or Pinned version above to connect DollhouseMCP first.`,
1129
+ };
1130
+ };
1131
+
1132
+ const getManualPermissionStatusCopy = (support, detected) => {
1087
1133
  if (detected?.hookAssetsPrepared) {
1088
1134
  return {
1089
1135
  tone: 'info',
@@ -1106,32 +1152,40 @@ codex_hooks = true`;
1106
1152
  };
1107
1153
  };
1108
1154
 
1109
- const getUnsupportedPermissionStatusCopy = (platformLabel, detected) => ({
1155
+ const getUnsupportedPermissionStatusCopy = (support, detected) => ({
1110
1156
  tone: detected?.installed ? 'warning' : 'neutral',
1111
- titleText: `Permissions & security tools are unavailable for ${platformLabel} right now.`,
1157
+ titleText: `Permissions & security tools are unavailable for ${support.label} right now.`,
1112
1158
  messageText: detected?.installed
1113
1159
  ? 'DollhouseMCP is connected for this client, but this release does not include a supported permissions setup flow here yet.'
1114
- : 'This release does not include a supported permissions setup flow for this client yet.',
1160
+ : support.limitation,
1115
1161
  });
1116
1162
 
1117
1163
  const getPermissionStatusCopy = (platformId, detected) => {
1118
- const verified = VERIFIED_PERMISSION_PLATFORMS[platformId];
1119
- if (verified) {
1120
- return getVerifiedPermissionStatusCopy(verified, detected);
1164
+ const support = getPermissionSupport(platformId, detected);
1165
+ if (!support) {
1166
+ return getUnsupportedPermissionStatusCopy({
1167
+ label: 'this client',
1168
+ limitation: 'This release does not include a supported permissions setup flow for this client yet.',
1169
+ }, detected);
1121
1170
  }
1122
1171
 
1123
- const partial = PARTIAL_PERMISSION_PLATFORMS[platformId];
1124
- if (partial) {
1125
- return getPartialPermissionStatusCopy(partial, detected);
1172
+ if (support.supportLevel === 'full_native') {
1173
+ return getFullNativePermissionStatusCopy(support, detected);
1126
1174
  }
1127
1175
 
1128
- const support = PLATFORMS.find((platform) => platform.id === platformId)?.hookSupport || 'unsupported';
1129
- if (support === 'manual') {
1130
- return getManualPermissionStatusCopy(detected);
1176
+ if (support.supportLevel === 'partial_native') {
1177
+ return getPartialPermissionStatusCopy(support, detected);
1131
1178
  }
1132
1179
 
1133
- const platformLabel = PERMISSION_PLATFORM_LABELS[platformId] || 'this client';
1134
- return getUnsupportedPermissionStatusCopy(platformLabel, detected);
1180
+ if (support.supportLevel === 'mcp_only') {
1181
+ return getMcpOnlyPermissionStatusCopy(support, detected);
1182
+ }
1183
+
1184
+ if (support.supportLevel === 'manual') {
1185
+ return getManualPermissionStatusCopy(support, detected);
1186
+ }
1187
+
1188
+ return getUnsupportedPermissionStatusCopy(support, detected);
1135
1189
  };
1136
1190
 
1137
1191
  const updatePermissionStatus = (panel, platformId, detected) => {
@@ -1418,24 +1472,41 @@ codex_hooks = true`;
1418
1472
  </div>`;
1419
1473
  };
1420
1474
 
1475
+ const renderMcpOnlyPermissionSection = (support) => `<div class="setup-method setup-security-mode" data-setup-modes="permissions" hidden>
1476
+ <h3>Permissions &amp; Security <span class="setup-support-badge setup-support-badge--${support.badgeClass}">${support.statusTag}</span></h3>
1477
+ <div class="setup-permission-status" data-state="info">
1478
+ <strong class="setup-permission-status-title"></strong>
1479
+ <p class="setup-permission-status-msg"></p>
1480
+ </div>
1481
+ <p class="setup-hint">${support.limitation}</p>
1482
+ </div>`;
1483
+
1421
1484
  const renderPermissionSection = (p) => {
1422
- const hookSupport = p.hookSupport || 'unsupported';
1485
+ const support = getPermissionSupport(p.id);
1423
1486
  const configPath = p.hookConfigPath || p.configPath || p.tomlPath || 'this client’s user configuration';
1424
1487
 
1425
- if (hookSupport === 'verified' && VERIFIED_PERMISSION_PLATFORMS[p.id]) {
1426
- return renderVerifiedPermissionSection(p, VERIFIED_PERMISSION_PLATFORMS[p.id]);
1488
+ if (!support) {
1489
+ return '';
1490
+ }
1491
+
1492
+ if (support.supportLevel === 'full_native') {
1493
+ return renderVerifiedPermissionSection(p, support);
1494
+ }
1495
+
1496
+ if (support.supportLevel === 'partial_native') {
1497
+ return renderPartialPermissionSection(p, support);
1427
1498
  }
1428
1499
 
1429
- if (hookSupport === 'partial' && PARTIAL_PERMISSION_PLATFORMS[p.id]) {
1430
- return renderPartialPermissionSection(p, PARTIAL_PERMISSION_PLATFORMS[p.id]);
1500
+ if (support.supportLevel === 'mcp_only') {
1501
+ return renderMcpOnlyPermissionSection(support);
1431
1502
  }
1432
1503
 
1433
- if (hookSupport === 'manual') {
1504
+ if (support.supportLevel === 'manual') {
1434
1505
  const platformName = p.id === 'gemini' ? 'gemini' : p.id;
1435
1506
  const wrapperFilename = `pretooluse-${platformName}.sh`;
1436
1507
  const wrapperScript = buildHookWrapperScript(platformName);
1437
1508
  return `<div class="setup-method setup-security-mode" data-setup-modes="permissions" hidden>
1438
- <h3>Permissions &amp; Security <span class="setup-support-badge setup-support-badge--manual">manual setup</span></h3>
1509
+ <h3>Permissions &amp; Security <span class="setup-support-badge setup-support-badge--${support.badgeClass}">${support.statusTag}</span></h3>
1439
1510
  <div class="setup-permission-status" data-state="info">
1440
1511
  <strong class="setup-permission-status-title"></strong>
1441
1512
  <p class="setup-permission-status-msg"></p>
@@ -1453,7 +1524,7 @@ codex_hooks = true`;
1453
1524
  }
1454
1525
 
1455
1526
  return `<div class="setup-method setup-security-mode" data-setup-modes="permissions" hidden>
1456
- <h3>Permissions &amp; Security <span class="setup-support-badge setup-support-badge--unsupported">coming soon</span></h3>
1527
+ <h3>Permissions &amp; Security <span class="setup-support-badge setup-support-badge--${support.badgeClass}">${support.statusTag}</span></h3>
1457
1528
  <div class="setup-permission-status" data-state="neutral">
1458
1529
  <strong class="setup-permission-status-title"></strong>
1459
1530
  <p class="setup-permission-status-msg"></p>
@@ -1467,7 +1538,7 @@ codex_hooks = true`;
1467
1538
 
1468
1539
  intro.innerHTML = `<div class="setup-permissions-note">
1469
1540
  <strong>Permissions &amp; Security</strong>
1470
- <p>Use this mode to turn on permission enforcement for supported clients. Claude Code is fully guided in this release, and Gemini CLI, Cursor, VS Code, Windsurf, plus Codex have native partial support. Where we have workable manual steps for other clients, they are shown here. Otherwise, the client will be marked as coming soon.</p>
1541
+ <p>Use this mode to turn on permission enforcement for supported clients. Claude Code is fully guided in this release. Gemini CLI, Cursor, VS Code, Windsurf, and Codex have native partial support, while Cline and LM Studio stay in the MCP and fallback lane for now. Other clients will be marked as coming soon.</p>
1471
1542
  </div>`;
1472
1543
  };
1473
1544
 
@@ -1 +1 @@
1
- {"version":3,"file":"permissionRoutes.d.ts","sourceRoot":"","sources":["../../../src/web/routes/permissionRoutes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAgB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAsJ7E;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CAkIrF"}
1
+ {"version":3,"file":"permissionRoutes.d.ts","sourceRoot":"","sources":["../../../src/web/routes/permissionRoutes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAgB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AA+Q7E;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CA0IrF"}
@@ -13,6 +13,8 @@ import { SlidingWindowRateLimiter } from '../../utils/SlidingWindowRateLimiter.j
13
13
  const PERMISSION_ROUTE_RATE_LIMIT_REQUESTS = 120;
14
14
  const PERMISSION_ROUTE_RATE_LIMIT_WINDOW_MS = 60_000;
15
15
  const DECISION_BUFFER_SIZE = 200;
16
+ const CLAUDE_COMPATIBLE_HOOK_PLATFORMS = new Set(['claude_code', 'vscode']);
17
+ const NORMALIZABLE_PERMISSION_DECISIONS = new Set(['allow', 'deny', 'ask']);
16
18
  /** Extract a string field from a record, trying multiple keys in order */
17
19
  function extractString(obj, keys, fallback) {
18
20
  for (const key of keys) {
@@ -48,11 +50,71 @@ function extractReason(result) {
48
50
  }
49
51
  return extractString(result, ['reason', 'message'], '');
50
52
  }
53
+ function shouldNormalizeClaudeHook(platform) {
54
+ return platform !== undefined && CLAUDE_COMPATIBLE_HOOK_PLATFORMS.has(platform);
55
+ }
56
+ function normalizePermissionResponseForPlatform(platform, input, result) {
57
+ if (!shouldNormalizeClaudeHook(platform)) {
58
+ return result;
59
+ }
60
+ const nested = result.hookSpecificOutput;
61
+ if (nested && typeof nested === 'object' && !Array.isArray(nested)) {
62
+ const nestedDecision = nested.permissionDecision;
63
+ if (typeof nestedDecision === 'string') {
64
+ return result;
65
+ }
66
+ }
67
+ const decision = extractDecision(result);
68
+ if (NORMALIZABLE_PERMISSION_DECISIONS.has(decision)) {
69
+ return formatPermissionResponse(decision, platform, input, extractReason(result));
70
+ }
71
+ return formatPermissionResponse('allow', platform, input);
72
+ }
73
+ function buildDecisionDetails(toolName, input, result, platform) {
74
+ const details = [];
75
+ if (platform) {
76
+ details.push({ label: 'Platform', value: platform, monospace: true });
77
+ }
78
+ if (toolName === 'Bash' && typeof input.command === 'string' && input.command !== '') {
79
+ details.push({ label: 'Command', value: input.command, monospace: true });
80
+ }
81
+ const targetDescriptors = [
82
+ { key: 'file_path', label: 'File', monospace: true },
83
+ { key: 'path', label: 'Path', monospace: true },
84
+ { key: 'url', label: 'URL' },
85
+ { key: 'pattern', label: 'Pattern', monospace: true },
86
+ { key: 'query', label: 'Query' },
87
+ { key: 'element_name', label: 'Element', monospace: true },
88
+ { key: 'request_id', label: 'Request', monospace: true },
89
+ ];
90
+ let target;
91
+ let targetLabel;
92
+ for (const descriptor of targetDescriptors) {
93
+ const value = input[descriptor.key];
94
+ if (typeof value !== 'string' || value === '') {
95
+ continue;
96
+ }
97
+ target = value;
98
+ targetLabel = descriptor.label;
99
+ details.push({ label: descriptor.label, value, monospace: descriptor.monospace });
100
+ break;
101
+ }
102
+ const matchedPattern = extractString(result, ['matched_pattern', 'matchedPattern'], '');
103
+ if (matchedPattern !== '') {
104
+ details.push({ label: 'Matched Pattern', value: matchedPattern, monospace: true });
105
+ }
106
+ const policySource = extractString(result, ['policy_source', 'policySource'], '');
107
+ if (policySource !== '') {
108
+ details.push({ label: 'Policy Source', value: policySource, monospace: true });
109
+ }
110
+ return { target, targetLabel, details };
111
+ }
51
112
  function createPermissionDecisionTracker(bufferSize = DECISION_BUFFER_SIZE) {
52
113
  const recentDecisions = [];
53
114
  let decisionCounter = 0;
54
115
  return {
55
- trackDecision(sessionId, toolName, input, result) {
116
+ trackDecision(sessionId, toolName, input, result, platform) {
117
+ const detailState = buildDecisionDetails(toolName, input, result, platform);
56
118
  const entry = {
57
119
  id: `d-${++decisionCounter}`,
58
120
  timestamp: new Date().toISOString(),
@@ -61,6 +123,10 @@ function createPermissionDecisionTracker(bufferSize = DECISION_BUFFER_SIZE) {
61
123
  command: toolName === 'Bash' && typeof input?.command === 'string' ? input.command : undefined,
62
124
  decision: extractDecision(result),
63
125
  reason: extractReason(result),
126
+ platform,
127
+ target: detailState.target,
128
+ targetLabel: detailState.targetLabel,
129
+ details: detailState.details,
64
130
  };
65
131
  recentDecisions.unshift(entry);
66
132
  if (recentDecisions.length > bufferSize) {
@@ -92,6 +158,8 @@ function normalizePolicyElements(elements) {
92
158
  allowRules: mergeRuleArrays(element.allowPatterns, element.allowOperations),
93
159
  confirmRules: mergeRuleArrays(element.confirmPatterns, element.confirmOperations),
94
160
  denyRules: mergeRuleArrays(element.denyPatterns, element.denyOperations),
161
+ invalidGatekeeperPolicy: !!element.invalidGatekeeperPolicy,
162
+ invalidGatekeeperMessage: typeof element.invalidGatekeeperMessage === 'string' ? element.invalidGatekeeperMessage : undefined,
95
163
  }));
96
164
  }
97
165
  function resolveElementName(element) {
@@ -171,11 +239,14 @@ export function registerPermissionRoutes(router, handler) {
171
239
  res.json(formatPermissionResponse('allow', platform, input || {})); // fail open
172
240
  return;
173
241
  }
174
- const decision = extractDecision(opResult.data);
242
+ const rawResult = opResult.data;
243
+ const responseData = normalizePermissionResponseForPlatform(platform, input || {}, rawResult);
244
+ const trackedResult = { ...rawResult, ...responseData };
245
+ const decision = extractDecision(responseData);
175
246
  logger.debug(`[WebUI/Gateway] evaluate_permission: ${tool_name} → ${decision} (${elapsedMs}ms)`);
176
247
  // Track decision for live dashboard feed
177
- decisionTracker.trackDecision(session_id, tool_name, input || {}, opResult.data);
178
- res.json(opResult.data);
248
+ decisionTracker.trackDecision(session_id, tool_name, input || {}, trackedResult, platform);
249
+ res.json(responseData);
179
250
  }
180
251
  catch (err) {
181
252
  const elapsedMs = Date.now() - startMs;
@@ -231,6 +302,7 @@ export function registerPermissionRoutes(router, handler) {
231
302
  hookInstalled: data.hookInstalled,
232
303
  hookHost: data.hookHost,
233
304
  enforcementReady: data.enforcementReady,
305
+ invalidPolicyElementCount: data.invalidPolicyElementCount ?? 0,
234
306
  advisory: data.advisory,
235
307
  recentDecisions: decisionTracker.getRecentDecisions(),
236
308
  });
@@ -241,4 +313,4 @@ export function registerPermissionRoutes(router, handler) {
241
313
  }
242
314
  });
243
315
  }
244
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVybWlzc2lvblJvdXRlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy93ZWIvcm91dGVzL3Blcm1pc3Npb25Sb3V0ZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRztBQUVILE9BQU8sT0FBbUIsTUFBTSxTQUFTLENBQUM7QUFDMUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRS9DLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDhDQUE4QyxDQUFDO0FBRXhGLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBcUJuRixNQUFNLG9DQUFvQyxHQUFHLEdBQUcsQ0FBQztBQUNqRCxNQUFNLHFDQUFxQyxHQUFHLE1BQU0sQ0FBQztBQUNyRCxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQU9qQywwRUFBMEU7QUFDMUUsU0FBUyxhQUFhLENBQUMsR0FBNEIsRUFBRSxJQUFjLEVBQUUsUUFBZ0I7SUFDbkYsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUN2QixNQUFNLEdBQUcsR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN2QixJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVE7WUFBRSxPQUFPLEdBQUcsQ0FBQztJQUMxQyxDQUFDO0lBQ0QsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQztBQUVELFNBQVMsZUFBZSxDQUFDLE1BQStCO0lBQ3RELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQztJQUN6QyxJQUFJLE1BQU0sSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDbkUsTUFBTSxjQUFjLEdBQUksTUFBa0MsQ0FBQyxrQkFBa0IsQ0FBQztRQUM5RSxJQUFJLE9BQU8sY0FBYyxLQUFLLFFBQVE7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USxDQUFDO2dCQUNuRCxzQkFBc0IsRUFBRSxJQUFJLENBQUMsc0JBQXNCO2dCQUNuRCxhQUFhLEVBQUUsSUFBSSxDQUFDLGFBQWE7Z0JBQ2pDLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUTtnQkFDdkIsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLGdCQUFnQjtnQkFDdkMsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRO2dCQUN2QixlQUFlLEVBQUUsZUFBZSxDQUFDLGtCQUFrQixFQUFFO2FBQ3RELENBQUMsQ0FBQztRQUNMLENBQUM7UUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ2IsTUFBTSxDQUFDLEtBQUssQ0FBQywyQ0FBMkMsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUMvRCxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxpQ0FBaUMsRUFBRSxDQUFDLENBQUM7UUFDckUsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUGVybWlzc2lvbiBldmFsdWF0aW9uIEhUVFAgcm91dGVzIGFuZCBkZWNpc2lvbiB0cmFja2luZy5cbiAqXG4gKiBQcm92aWRlczpcbiAqIC0gUE9TVCAvZXZhbHVhdGVfcGVybWlzc2lvbiDigJQgZXZhbHVhdGVzIHRvb2wgcGVybWlzc2lvbnMgdmlhIE1DUC1BUUxcbiAqIC0gR0VUIC9wZXJtaXNzaW9ucy9zdGF0dXMg4oCUIHJldHVybnMgY3VycmVudCBwb2xpY2llcyBhbmQgcmVjZW50IGRlY2lzaW9uc1xuICogLSBEZWNpc2lvbiB0cmFja2luZyByaW5nIGJ1ZmZlciBmb3IgdGhlIGxpdmUgZGFzaGJvYXJkIGZlZWRcbiAqL1xuXG5pbXBvcnQgZXhwcmVzcywgeyBSb3V0ZXIgfSBmcm9tICdleHByZXNzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uLy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgdHlwZSB7IE1DUEFRTEhhbmRsZXIgfSBmcm9tICcuLi8uLi9oYW5kbGVycy9tY3AtYXFsL01DUEFRTEhhbmRsZXIuanMnO1xuaW1wb3J0IHsgZm9ybWF0UGVybWlzc2lvblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vaGFuZGxlcnMvbWNwLWFxbC9ldmFsdWF0ZVBlcm1pc3Npb24uanMnO1xuXG5pbXBvcnQgeyBTbGlkaW5nV2luZG93UmF0ZUxpbWl0ZXIgfSBmcm9tICcuLi8uLi91dGlscy9TbGlkaW5nV2luZG93UmF0ZUxpbWl0ZXIuanMnO1xuXG4vLyDilIDilIAgUGVybWlzc2lvbiBEZWNpc2lvbiBUcmFja2luZyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbi8vIFJpbmcgYnVmZmVyIG9mIHJlY2VudCBwZXJtaXNzaW9uIGRlY2lzaW9ucyBmb3IgdGhlIGxpdmUgZGFzaGJvYXJkIGZlZWQuXG5cbmludGVyZmFjZSBQZXJtaXNzaW9uRGVjaXNpb24ge1xuICBpZDogc3RyaW5nO1xuICB0aW1lc3RhbXA6IHN0cmluZztcbiAgc2Vzc2lvbl9pZD86IHN0cmluZztcbiAgdG9vbF9uYW1lOiBzdHJpbmc7XG4gIGNvbW1hbmQ/OiBzdHJpbmc7XG4gIGRlY2lzaW9uOiBzdHJpbmc7XG4gIHJlYXNvbj86IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIEtub3duUG9saWN5U2Vzc2lvbiB7XG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICBkaXNwbGF5TmFtZTogc3RyaW5nO1xuICBzb3VyY2U6ICdwb2xpY3knO1xufVxuXG5jb25zdCBQRVJNSVNTSU9OX1JPVVRFX1JBVEVfTElNSVRfUkVRVUVTVFMgPSAxMjA7XG5jb25zdCBQRVJNSVNTSU9OX1JPVVRFX1JBVEVfTElNSVRfV0lORE9XX01TID0gNjBfMDAwO1xuY29uc3QgREVDSVNJT05fQlVGRkVSX1NJWkUgPSAyMDA7XG5cbmludGVyZmFjZSBQZXJtaXNzaW9uRGVjaXNpb25UcmFja2VyIHtcbiAgdHJhY2tEZWNpc2lvbihzZXNzaW9uSWQ6IHN0cmluZyB8IHVuZGVmaW5lZCwgdG9vbE5hbWU6IHN0cmluZywgaW5wdXQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogdm9pZDtcbiAgZ2V0UmVjZW50RGVjaXNpb25zKCk6IFBlcm1pc3Npb25EZWNpc2lvbltdO1xufVxuXG4vKiogRXh0cmFjdCBhIHN0cmluZyBmaWVsZCBmcm9tIGEgcmVjb3JkLCB0cnlpbmcgbXVsdGlwbGUga2V5cyBpbiBvcmRlciAqL1xuZnVuY3Rpb24gZXh0cmFjdFN0cmluZyhvYmo6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBrZXlzOiBzdHJpbmdbXSwgZmFsbGJhY2s6IHN0cmluZyk6IHN0cmluZyB7XG4gIGZvciAoY29uc3Qga2V5IG9mIGtleXMpIHtcbiAgICBjb25zdCB2YWwgPSBvYmo/LltrZXldO1xuICAgIGlmICh0eXBlb2YgdmFsID09PSAnc3RyaW5nJykgcmV0dXJuIHZhbDtcbiAgfVxuICByZXR1cm4gZmFsbGJhY2s7XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3REZWNpc2lvbihyZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogc3RyaW5nIHtcbiAgY29uc3QgbmVzdGVkID0gcmVzdWx0Lmhvb2tTcGVjaWZpY091dHB1dDtcbiAgaWYgKG5lc3RlZCAmJiB0eXBlb2YgbmVzdGVkID09PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheShuZXN0ZWQpKSB7XG4gICAgY29uc3QgbmVzdGVkRGVjaXNpb24gPSAobmVzdGVkIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KS5wZXJtaXNzaW9uRGVjaXNpb247XG4gICAgaWYgKHR5cGVvZiBuZXN0ZWREZWNpc2lvbiA9PT0gJ3N0cmluZycpIHJldHVybiBuZXN0ZWREZWNpc2lvbjtcbiAgfVxuXG4gIGlmICh0eXBlb2YgcmVzdWx0LnBlcm1pc3Npb24gPT09ICdzdHJpbmcnKSByZXR1cm4gcmVzdWx0LnBlcm1pc3Npb247XG4gIGlmICh0eXBlb2YgcmVzdWx0LmRlY2lzaW9uID09PSAnc3RyaW5nJykgcmV0dXJuIHJlc3VsdC5kZWNpc2lvbjtcbiAgaWYgKHR5cGVvZiByZXN1bHQuYmVoYXZpb3IgPT09ICdzdHJpbmcnKSByZXR1cm4gcmVzdWx0LmJlaGF2aW9yO1xuICBpZiAodHlwZW9mIHJlc3VsdC5hbGxvd2VkID09PSAnYm9vbGVhbicpIHJldHVybiByZXN1bHQuYWxsb3dlZCA/ICdhbGxvdycgOiAnZGVueSc7XG4gIHJldHVybiAndW5rbm93bic7XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RSZWFzb24ocmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHN0cmluZyB7XG4gIGNvbnN0IG5lc3RlZCA9IHJlc3VsdC5ob29rU3BlY2lmaWNPdXRwdXQ7XG4gIGlmIChuZXN0ZWQgJiYgdHlwZW9mIG5lc3RlZCA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkobmVzdGVkKSkge1xuICAgIGNvbnN0IG5lc3RlZFJlYXNvbiA9IChuZXN0ZWQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLnBlcm1pc3Npb25EZWNpc2lvblJlYXNvbjtcbiAgICBpZiAodHlwZW9mIG5lc3RlZFJlYXNvbiA9PT0gJ3N0cmluZycpIHJldHVybiBuZXN0ZWRSZWFzb247XG4gIH1cblxuICByZXR1cm4gZXh0cmFjdFN0cmluZyhyZXN1bHQsIFsncmVhc29uJywgJ21lc3NhZ2UnXSwgJycpO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVQZXJtaXNzaW9uRGVjaXNpb25UcmFja2VyKGJ1ZmZlclNpemUgPSBERUNJU0lPTl9CVUZGRVJfU0laRSk6IFBlcm1pc3Npb25EZWNpc2lvblRyYWNrZXIge1xuICBjb25zdCByZWNlbnREZWNpc2lvbnM6IFBlcm1pc3Npb25EZWNpc2lvbltdID0gW107XG4gIGxldCBkZWNpc2lvbkNvdW50ZXIgPSAwO1xuXG4gIHJldHVybiB7XG4gICAgdHJhY2tEZWNpc2lvbihzZXNzaW9uSWQ6IHN0cmluZyB8IHVuZGVmaW5lZCwgdG9vbE5hbWU6IHN0cmluZywgaW5wdXQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogdm9pZCB7XG4gICAgICBjb25zdCBlbnRyeTogUGVybWlzc2lvbkRlY2lzaW9uID0ge1xuICAgICAgICBpZDogYGQtJHsrK2RlY2lzaW9uQ291bnRlcn1gLFxuICAgICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgLi4uKHNlc3Npb25JZCA/IHsgc2Vzc2lvbl9pZDogc2Vzc2lvbklkIH0gOiB7fSksXG4gICAgICAgIHRvb2xfbmFtZTogdG9vbE5hbWUsXG4gICAgICAgIGNvbW1hbmQ6IHRvb2xOYW1lID09PSAnQmFzaCcgJiYgdHlwZW9mIGlucHV0Py5jb21tYW5kID09PSAnc3RyaW5nJyA/IGlucHV0LmNvbW1hbmQgOiB1bmRlZmluZWQsXG4gICAgICAgIGRlY2lzaW9uOiBleHRyYWN0RGVjaXNpb24ocmVzdWx0KSxcbiAgICAgICAgcmVhc29uOiBleHRyYWN0UmVhc29uKHJlc3VsdCksXG4gICAgICB9O1xuICAgICAgcmVjZW50RGVjaXNpb25zLnVuc2hpZnQoZW50cnkpO1xuICAgICAgaWYgKHJlY2VudERlY2lzaW9ucy5sZW5ndGggPiBidWZmZXJTaXplKSB7XG4gICAgICAgIHJlY2VudERlY2lzaW9ucy5sZW5ndGggPSBidWZmZXJTaXplO1xuICAgICAgfVxuICAgIH0sXG4gICAgZ2V0UmVjZW50RGVjaXNpb25zKCk6IFBlcm1pc3Npb25EZWNpc2lvbltdIHtcbiAgICAgIHJldHVybiByZWNlbnREZWNpc2lvbnM7XG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWVyZ2VSdWxlQXJyYXlzKC4uLnNvdXJjZXM6IHVua25vd25bXSk6IHN0cmluZ1tdIHtcbiAgY29uc3QgbWVyZ2VkID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGZvciAoY29uc3Qgc291cmNlIG9mIHNvdXJjZXMpIHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoc291cmNlKSkgY29udGludWU7XG4gICAgZm9yIChjb25zdCBlbnRyeSBvZiBzb3VyY2UpIHtcbiAgICAgIGlmICh0eXBlb2YgZW50cnkgPT09ICdzdHJpbmcnICYmIGVudHJ5ICE9PSAnJykge1xuICAgICAgICBtZXJnZWQuYWRkKGVudHJ5KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIEFycmF5LmZyb20obWVyZ2VkKTtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplUG9saWN5RWxlbWVudHMoZWxlbWVudHM6IEFycmF5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pik6IEFycmF5PFJlY29yZDxzdHJpbmcsIHVua25vd24+PiB7XG4gIHJldHVybiBlbGVtZW50cy5tYXAoKGVsZW1lbnQpID0+ICh7XG4gICAgLi4uZWxlbWVudCxcbiAgICBlbGVtZW50X25hbWU6IHJlc29sdmVFbGVtZW50TmFtZShlbGVtZW50KSxcbiAgICBhbGxvd1J1bGVzOiBtZXJnZVJ1bGVBcnJheXMoZWxlbWVudC5hbGxvd1BhdHRlcm5zLCBlbGVtZW50LmFsbG93T3BlcmF0aW9ucyksXG4gICAgY29uZmlybVJ1bGVzOiBtZXJnZVJ1bGVBcnJheXMoZWxlbWVudC5jb25maXJtUGF0dGVybnMsIGVsZW1lbnQuY29uZmlybU9wZXJhdGlvbnMpLFxuICAgIGRlbnlSdWxlczogbWVyZ2VSdWxlQXJyYXlzKGVsZW1lbnQuZGVueVBhdHRlcm5zLCBlbGVtZW50LmRlbnlPcGVyYXRpb25zKSxcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRWxlbWVudE5hbWUoZWxlbWVudDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBzdHJpbmcge1xuICBpZiAodHlwZW9mIGVsZW1lbnQuZWxlbWVudF9uYW1lID09PSAnc3RyaW5nJykgcmV0dXJuIGVsZW1lbnQuZWxlbWVudF9uYW1lO1xuICBpZiAodHlwZW9mIGVsZW1lbnQubmFtZSA9PT0gJ3N0cmluZycpIHJldHVybiBlbGVtZW50Lm5hbWU7XG4gIHJldHVybiAnJztcbn1cblxuLyoqIEhlbHBlciB0byBleHRyYWN0IHNpbmdsZSByZXN1bHQgZnJvbSBNQ1AtQVFMIGJhdGNoIHJlc3BvbnNlICovXG5mdW5jdGlvbiBhc1NpbmdsZVJlc3VsdChyZXN1bHRzOiB1bmtub3duKTogeyBzdWNjZXNzOiBib29sZWFuOyBkYXRhPzogdW5rbm93bjsgZXJyb3I/OiBzdHJpbmcgfSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHJlc3VsdHMpKSByZXR1cm4gcmVzdWx0c1swXSB8fCB7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogJ0VtcHR5IHJlc3VsdCcgfTtcbiAgcmV0dXJuIHJlc3VsdHMgYXMgeyBzdWNjZXNzOiBib29sZWFuOyBkYXRhPzogdW5rbm93bjsgZXJyb3I/OiBzdHJpbmcgfTtcbn1cblxuZnVuY3Rpb24gZXh0cmFjdEtub3duUG9saWN5U2Vzc2lvbnMoZWxlbWVudHM6IEFycmF5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pik6IEtub3duUG9saWN5U2Vzc2lvbltdIHtcbiAgY29uc3Qgc2VlbiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBjb25zdCBrbm93blNlc3Npb25zOiBLbm93blBvbGljeVNlc3Npb25bXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZWxlbWVudCBvZiBlbGVtZW50cykge1xuICAgIGNvbnN0IHNlc3Npb25JZHMgPSBBcnJheS5pc0FycmF5KGVsZW1lbnQuc2Vzc2lvbklkcykgPyBlbGVtZW50LnNlc3Npb25JZHMgOiBbXTtcbiAgICBmb3IgKGNvbnN0IHNlc3Npb25JZCBvZiBzZXNzaW9uSWRzKSB7XG4gICAgICBpZiAodHlwZW9mIHNlc3Npb25JZCAhPT0gJ3N0cmluZycgfHwgc2Vzc2lvbklkID09PSAnJyB8fCBzZWVuLmhhcyhzZXNzaW9uSWQpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBzZWVuLmFkZChzZXNzaW9uSWQpO1xuICAgICAga25vd25TZXNzaW9ucy5wdXNoKHtcbiAgICAgICAgc2Vzc2lvbklkLFxuICAgICAgICBkaXNwbGF5TmFtZTogc2Vzc2lvbklkLFxuICAgICAgICBzb3VyY2U6ICdwb2xpY3knLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGtub3duU2Vzc2lvbnMuc29ydCgoYSwgYikgPT4gYS5zZXNzaW9uSWQubG9jYWxlQ29tcGFyZShiLnNlc3Npb25JZCkpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVyIHBlcm1pc3Npb24tcmVsYXRlZCByb3V0ZXMgb24gYSBnYXRld2F5IHJvdXRlci5cbiAqIE11c3QgYmUgY2FsbGVkIHdpdGggdGhlIE1DUC1BUUwgaGFuZGxlciBmb3IgcG9saWN5IGV2YWx1YXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlclBlcm1pc3Npb25Sb3V0ZXMocm91dGVyOiBSb3V0ZXIsIGhhbmRsZXI6IE1DUEFRTEhhbmRsZXIpOiB2b2lkIHtcbiAgY29uc3QgZGVjaXNpb25UcmFja2VyID0gY3JlYXRlUGVybWlzc2lvbkRlY2lzaW9uVHJhY2tlcigpO1xuICAvKipcbiAgICogUE9TVCAvYXBpL2V2YWx1YXRlX3Blcm1pc3Npb25cbiAgICogUGVybWlzc2lvbiBldmFsdWF0aW9uIGVuZHBvaW50IGZvciBQcmVUb29sVXNlIGhvb2tzLlxuICAgKiBSb3V0ZXMgdGhyb3VnaCBldmFsdWF0ZV9wZXJtaXNzaW9uIE1DUC1BUUwgUkVBRCBvcGVyYXRpb24uXG4gICAqIEZhaWwtb3BlbjogcmV0dXJucyBhbGxvdyBvbiBhbnkgZXJyb3IgdG8gYXZvaWQgYmxvY2tpbmcgdGhlIHVzZXIuXG4gICAqL1xuICBjb25zdCBwZXJtaXNzaW9uTGltaXRlciA9IG5ldyBTbGlkaW5nV2luZG93UmF0ZUxpbWl0ZXIoXG4gICAgUEVSTUlTU0lPTl9ST1VURV9SQVRFX0xJTUlUX1JFUVVFU1RTLFxuICAgIFBFUk1JU1NJT05fUk9VVEVfUkFURV9MSU1JVF9XSU5ET1dfTVMsXG4gICk7XG4gIHJvdXRlci5wb3N0KCcvZXZhbHVhdGVfcGVybWlzc2lvbicsIGV4cHJlc3MuanNvbigpLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICBjb25zdCBib2R5ID0gcmVxLmJvZHkgYXMge1xuICAgICAgdG9vbF9uYW1lPzogc3RyaW5nO1xuICAgICAgaW5wdXQ/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIHBsYXRmb3JtPzogc3RyaW5nO1xuICAgICAgc2Vzc2lvbl9pZD86IHN0cmluZztcbiAgICB9O1xuICAgIGNvbnN0IHBsYXRmb3JtID0gdHlwZW9mIGJvZHkucGxhdGZvcm0gPT09ICdzdHJpbmcnID8gYm9keS5wbGF0Zm9ybS5ub3JtYWxpemUoJ05GQycpIDogJ2NsYXVkZV9jb2RlJztcblxuICAgIGlmICghcGVybWlzc2lvbkxpbWl0ZXIudHJ5QWNxdWlyZSgpKSB7XG4gICAgICByZXMuanNvbihmb3JtYXRQZXJtaXNzaW9uUmVzcG9uc2UoJ2FsbG93JywgcGxhdGZvcm0sIHt9KSk7IC8vIGZhaWwgb3BlbiBvbiByYXRlIGxpbWl0XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVW5pY29kZSBub3JtYWxpemF0aW9uIChORkMpIG9uIHN0cmluZyBpbnB1dHMgdG8gcHJldmVudCBob21vZ3JhcGggYXR0YWNrc1xuICAgIGNvbnN0IHRvb2xfbmFtZSA9IHR5cGVvZiBib2R5LnRvb2xfbmFtZSA9PT0gJ3N0cmluZycgPyBib2R5LnRvb2xfbmFtZS5ub3JtYWxpemUoJ05GQycpIDogdW5kZWZpbmVkO1xuICAgIGNvbnN0IHNlc3Npb25faWQgPSB0eXBlb2YgYm9keS5zZXNzaW9uX2lkID09PSAnc3RyaW5nJyA/IGJvZHkuc2Vzc2lvbl9pZC5ub3JtYWxpemUoJ05GQycpIDogdW5kZWZpbmVkO1xuICAgIGNvbnN0IGlucHV0ID0gYm9keS5pbnB1dDtcblxuICAgIGlmICghdG9vbF9uYW1lKSB7XG4gICAgICByZXMuanNvbihmb3JtYXRQZXJtaXNzaW9uUmVzcG9uc2UoJ2FsbG93JywgcGxhdGZvcm0sIGlucHV0IHx8IHt9KSk7IC8vIGZhaWwgb3BlbiBvbiBiYWQgaW5wdXRcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBzdGFydE1zID0gRGF0ZS5ub3coKTtcbiAgICB0cnkge1xuICAgICAgY29uc3Qgb3BSZXN1bHQgPSBhc1NpbmdsZVJlc3VsdChhd2FpdCBoYW5kbGVyLmhhbmRsZVJlYWQoe1xuICAgICAgICBvcGVyYXRpb246ICdldmFsdWF0ZV9wZXJtaXNzaW9uJyxcbiAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgdG9vbF9uYW1lLFxuICAgICAgICAgIGlucHV0OiBpbnB1dCB8fCB7fSxcbiAgICAgICAgICBwbGF0Zm9ybSxcbiAgICAgICAgICAuLi4oc2Vzc2lvbl9pZCA/IHsgc2Vzc2lvbl9pZCB9IDoge30pLFxuICAgICAgICB9LFxuICAgICAgfSkpO1xuICAgICAgY29uc3QgZWxhcHNlZE1zID0gRGF0ZS5ub3coKSAtIHN0YXJ0TXM7XG5cbiAgICAgIGlmICghb3BSZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICBsb2dnZXIud2FybihgW1dlYlVJL0dhdGV3YXldIGV2YWx1YXRlX3Blcm1pc3Npb24gZmFpbGVkICgke2VsYXBzZWRNc31tcyk6ICR7b3BSZXN1bHQuZXJyb3J9YCk7XG4gICAgICAgIHJlcy5qc29uKGZvcm1hdFBlcm1pc3Npb25SZXNwb25zZSgnYWxsb3cnLCBwbGF0Zm9ybSwgaW5wdXQgfHwge30pKTsgLy8gZmFpbCBvcGVuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGVjaXNpb24gPSBleHRyYWN0RGVjaXNpb24ob3BSZXN1bHQuZGF0YSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik7XG4gICAgICBsb2dnZXIuZGVidWcoYFtXZWJVSS9HYXRld2F5XSBldmFsdWF0ZV9wZXJtaXNzaW9uOiAke3Rvb2xfbmFtZX0g4oaSICR7ZGVjaXNpb259ICgke2VsYXBzZWRNc31tcylgKTtcblxuICAgICAgLy8gVHJhY2sgZGVjaXNpb24gZm9yIGxpdmUgZGFzaGJvYXJkIGZlZWRcbiAgICAgIGRlY2lzaW9uVHJhY2tlci50cmFja0RlY2lzaW9uKHNlc3Npb25faWQsIHRvb2xfbmFtZSwgaW5wdXQgfHwge30sIG9wUmVzdWx0LmRhdGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pO1xuXG4gICAgICByZXMuanNvbihvcFJlc3VsdC5kYXRhKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnN0IGVsYXBzZWRNcyA9IERhdGUubm93KCkgLSBzdGFydE1zO1xuICAgICAgbG9nZ2VyLmVycm9yKGBbV2ViVUkvR2F0ZXdheV0gZXZhbHVhdGVfcGVybWlzc2lvbiBlcnJvciAoJHtlbGFwc2VkTXN9bXMpOmAsIGVycik7XG4gICAgICByZXMuanNvbihmb3JtYXRQZXJtaXNzaW9uUmVzcG9uc2UoJ2FsbG93JywgcGxhdGZvcm0sIGlucHV0IHx8IHt9KSk7IC8vIGZhaWwgb3BlblxuICAgIH1cbiAgfSk7XG5cbiAgLyoqXG4gICAqIEdFVCAvYXBpL3Blcm1pc3Npb25zL3N0YXR1c1xuICAgKiBSZXR1cm5zIGN1cnJlbnQgcGVybWlzc2lvbiBwb2xpY2llcyBhbmQgcmVjZW50IGRlY2lzaW9uc1xuICAgKiBmb3IgdGhlIGxpdmUgcGVybWlzc2lvbnMgZGFzaGJvYXJkLlxuICAgKi9cbiAgcm91dGVyLmdldCgnL3Blcm1pc3Npb25zL3N0YXR1cycsIGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBzZXNzaW9uSWQgPSB0eXBlb2YgcmVxLnF1ZXJ5WydzZXNzaW9uSWQnXSA9PT0gJ3N0cmluZycgJiYgcmVxLnF1ZXJ5WydzZXNzaW9uSWQnXVxuICAgICAgICA/IHJlcS5xdWVyeVsnc2Vzc2lvbklkJ11cbiAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAgIGNvbnN0IG9wUmVzdWx0ID0gYXNTaW5nbGVSZXN1bHQoYXdhaXQgaGFuZGxlci5oYW5kbGVSZWFkKHtcbiAgICAgICAgb3BlcmF0aW9uOiAnZ2V0X2VmZmVjdGl2ZV9jbGlfcG9saWNpZXMnLFxuICAgICAgICBwYXJhbXM6IHtcbiAgICAgICAgICByZXBvcnRpbmdfc2NvcGU6ICdkYXNoYm9hcmQnLFxuICAgICAgICAgIC4uLihzZXNzaW9uSWQgPyB7IHNlc3Npb25faWQ6IHNlc3Npb25JZCB9IDoge30pLFxuICAgICAgICB9LFxuICAgICAgfSkpO1xuXG4gICAgICBpZiAoIW9wUmVzdWx0LnN1Y2Nlc3MpIHtcbiAgICAgICAgcmVzLnN0YXR1cyg1MDApLmpzb24oeyBlcnJvcjogb3BSZXN1bHQuZXJyb3IgfHwgJ0ZhaWxlZCB0byBnZXQgcG9saWNpZXMnIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRhdGEgPSBvcFJlc3VsdC5kYXRhIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgY29uc3QgZWxlbWVudHMgPSBub3JtYWxpemVQb2xpY3lFbGVtZW50cygoZGF0YS5lbGVtZW50cyB8fCBbXSkgYXMgQXJyYXk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+KTtcblxuICAgICAgY29uc3QgZGVueVBhdHRlcm5zID0gKGRhdGEuY29tYmluZWREZW55UGF0dGVybnMgYXMgc3RyaW5nW10gfCB1bmRlZmluZWQpID8/IFtdO1xuICAgICAgY29uc3QgYWxsb3dQYXR0ZXJucyA9IChkYXRhLmNvbWJpbmVkQWxsb3dQYXR0ZXJucyBhcyBzdHJpbmdbXSB8IHVuZGVmaW5lZCkgPz8gW107XG4gICAgICBjb25zdCBjb25maXJtUGF0dGVybnMgPSAoZGF0YS5jb21iaW5lZENvbmZpcm1QYXR0ZXJucyBhcyBzdHJpbmdbXSB8IHVuZGVmaW5lZCkgPz8gW107XG4gICAgICBjb25zdCBkZW55T3BlcmF0aW9ucyA9IChkYXRhLmNvbWJpbmVkRGVueU9wZXJhdGlvbnMgYXMgc3RyaW5nW10gfCB1bmRlZmluZWQpID8/IFtdO1xuICAgICAgY29uc3QgYWxsb3dPcGVyYXRpb25zID0gKGRhdGEuY29tYmluZWRBbGxvd09wZXJhdGlvbnMgYXMgc3RyaW5nW10gfCB1bmRlZmluZWQpID8/IFtdO1xuICAgICAgY29uc3QgY29uZmlybU9wZXJhdGlvbnMgPSAoZGF0YS5jb21iaW5lZENvbmZpcm1PcGVyYXRpb25zIGFzIHN0cmluZ1tdIHwgdW5kZWZpbmVkKSA/PyBbXTtcblxuICAgICAgcmVzLmpzb24oe1xuICAgICAgICAuLi4oc2Vzc2lvbklkID8geyBzZXNzaW9uSWQgfSA6IHt9KSxcbiAgICAgICAgYWN0aXZlRWxlbWVudENvdW50OiBkYXRhLmFjdGl2ZUVsZW1lbnRDb3VudCxcbiAgICAgICAgaGFzQWxsb3dsaXN0OiBkYXRhLmhhc0FsbG93bGlzdCxcbiAgICAgICAgZGVueVBhdHRlcm5zLFxuICAgICAgICBhbGxvd1BhdHRlcm5zLFxuICAgICAgICBjb25maXJtUGF0dGVybnMsXG4gICAgICAgIGRlbnlPcGVyYXRpb25zLFxuICAgICAgICBhbGxvd09wZXJhdGlvbnMsXG4gICAgICAgIGNvbmZpcm1PcGVyYXRpb25zLFxuICAgICAgICBkZW55UnVsZXM6IG1lcmdlUnVsZUFycmF5cyhkZW55UGF0dGVybnMsIGRlbnlPcGVyYXRpb25zKSxcbiAgICAgICAgYWxsb3dSdWxlczogbWVyZ2VSdWxlQXJyYXlzKGFsbG93UGF0dGVybnMsIGFsbG93T3BlcmF0aW9ucyksXG4gICAgICAgIGNvbmZpcm1SdWxlczogbWVyZ2VSdWxlQXJyYXlzKGNvbmZpcm1QYXR0ZXJucywgY29uZmlybU9wZXJhdGlvbnMpLFxuICAgICAgICBlbGVtZW50cyxcbiAgICAgICAga25vd25TZXNzaW9uczogZXh0cmFjdEtub3duUG9saWN5U2Vzc2lvbnMoZWxlbWVudHMpLFxuICAgICAgICBwZXJtaXNzaW9uUHJvbXB0QWN0aXZlOiBkYXRhLnBlcm1pc3Npb25Qcm9tcHRBY3RpdmUsXG4gICAgICAgIGhvb2tJbnN0YWxsZWQ6IGRhdGEuaG9va0luc3RhbGxlZCxcbiAgICAgICAgaG9va0hvc3Q6IGRhdGEuaG9va0hvc3QsXG4gICAgICAgIGVuZm9yY2VtZW50UmVhZHk6IGRhdGEuZW5mb3JjZW1lbnRSZWFkeSxcbiAgICAgICAgYWR2aXNvcnk6IGRhdGEuYWR2aXNvcnksXG4gICAgICAgIHJlY2VudERlY2lzaW9uczogZGVjaXNpb25UcmFja2VyLmdldFJlY2VudERlY2lzaW9ucygpLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ1tXZWJVSS9HYXRld2F5XSBwZXJtaXNzaW9ucy9zdGF0dXMgZXJyb3I6JywgZXJyKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHsgZXJyb3I6ICdGYWlsZWQgdG8gZ2V0IHBlcm1pc3Npb24gc3RhdHVzJyB9KTtcbiAgICB9XG4gIH0pO1xufVxuIl19
316
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVybWlzc2lvblJvdXRlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy93ZWIvcm91dGVzL3Blcm1pc3Npb25Sb3V0ZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRztBQUVILE9BQU8sT0FBbUIsTUFBTSxTQUFTLENBQUM7QUFDMUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRS9DLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDhDQUE4QyxDQUFDO0FBRXhGLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBK0JuRixNQUFNLG9DQUFvQyxHQUFHLEdBQUcsQ0FBQztBQUNqRCxNQUFNLHFDQUFxQyxHQUFHLE1BQU0sQ0FBQztBQUNyRCxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQWFqQyxNQUFNLGdDQUFnQyxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsYUFBYSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7QUFDNUUsTUFBTSxpQ0FBaUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUc1RSwwRUFBMEU7QUFDMUUsU0FBUyxhQUFhLENBQUMsR0FBNEIsRUFBRSxJQUFjLEVBQUUsUUFBZ0I7SUFDbkYsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUN2QixNQUFNLEdBQUcsR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN2QixJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVE7WUFBRSxPQUFPLEdBQUcsQ0FBQztJQUMxQyxDQUFDO0lBQ0QsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQztBQUVELFNBQVMsZUFBZSxDQUFDLE1BQStCO0lBQ3RELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQztJQUN6QyxJQUFJ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TCxDQUFDO1FBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztZQUNiLE1BQU0sQ0FBQyxLQUFLLENBQUMsMkNBQTJDLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDL0QsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsaUNBQWlDLEVBQUUsQ0FBQyxDQUFDO1FBQ3JFLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBlcm1pc3Npb24gZXZhbHVhdGlvbiBIVFRQIHJvdXRlcyBhbmQgZGVjaXNpb24gdHJhY2tpbmcuXG4gKlxuICogUHJvdmlkZXM6XG4gKiAtIFBPU1QgL2V2YWx1YXRlX3Blcm1pc3Npb24g4oCUIGV2YWx1YXRlcyB0b29sIHBlcm1pc3Npb25zIHZpYSBNQ1AtQVFMXG4gKiAtIEdFVCAvcGVybWlzc2lvbnMvc3RhdHVzIOKAlCByZXR1cm5zIGN1cnJlbnQgcG9saWNpZXMgYW5kIHJlY2VudCBkZWNpc2lvbnNcbiAqIC0gRGVjaXNpb24gdHJhY2tpbmcgcmluZyBidWZmZXIgZm9yIHRoZSBsaXZlIGRhc2hib2FyZCBmZWVkXG4gKi9cblxuaW1wb3J0IGV4cHJlc3MsIHsgUm91dGVyIH0gZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi8uLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHR5cGUgeyBNQ1BBUUxIYW5kbGVyIH0gZnJvbSAnLi4vLi4vaGFuZGxlcnMvbWNwLWFxbC9NQ1BBUUxIYW5kbGVyLmpzJztcbmltcG9ydCB7IGZvcm1hdFBlcm1pc3Npb25SZXNwb25zZSB9IGZyb20gJy4uLy4uL2hhbmRsZXJzL21jcC1hcWwvZXZhbHVhdGVQZXJtaXNzaW9uLmpzJztcblxuaW1wb3J0IHsgU2xpZGluZ1dpbmRvd1JhdGVMaW1pdGVyIH0gZnJvbSAnLi4vLi4vdXRpbHMvU2xpZGluZ1dpbmRvd1JhdGVMaW1pdGVyLmpzJztcblxuLy8g4pSA4pSAIFBlcm1pc3Npb24gRGVjaXNpb24gVHJhY2tpbmcg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4vLyBSaW5nIGJ1ZmZlciBvZiByZWNlbnQgcGVybWlzc2lvbiBkZWNpc2lvbnMgZm9yIHRoZSBsaXZlIGRhc2hib2FyZCBmZWVkLlxuXG5pbnRlcmZhY2UgUGVybWlzc2lvbkRlY2lzaW9uIHtcbiAgaWQ6IHN0cmluZztcbiAgdGltZXN0YW1wOiBzdHJpbmc7XG4gIHNlc3Npb25faWQ/OiBzdHJpbmc7XG4gIHRvb2xfbmFtZTogc3RyaW5nO1xuICBjb21tYW5kPzogc3RyaW5nO1xuICBkZWNpc2lvbjogc3RyaW5nO1xuICByZWFzb24/OiBzdHJpbmc7XG4gIHBsYXRmb3JtPzogc3RyaW5nO1xuICB0YXJnZXQ/OiBzdHJpbmc7XG4gIHRhcmdldExhYmVsPzogc3RyaW5nO1xuICBkZXRhaWxzPzogUGVybWlzc2lvbkRlY2lzaW9uRGV0YWlsW107XG59XG5cbmludGVyZmFjZSBQZXJtaXNzaW9uRGVjaXNpb25EZXRhaWwge1xuICBsYWJlbDogc3RyaW5nO1xuICB2YWx1ZTogc3RyaW5nO1xuICBtb25vc3BhY2U/OiBib29sZWFuO1xufVxuXG5pbnRlcmZhY2UgS25vd25Qb2xpY3lTZXNzaW9uIHtcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIGRpc3BsYXlOYW1lOiBzdHJpbmc7XG4gIHNvdXJjZTogJ3BvbGljeSc7XG59XG5cbmNvbnN0IFBFUk1JU1NJT05fUk9VVEVfUkFURV9MSU1JVF9SRVFVRVNUUyA9IDEyMDtcbmNvbnN0IFBFUk1JU1NJT05fUk9VVEVfUkFURV9MSU1JVF9XSU5ET1dfTVMgPSA2MF8wMDA7XG5jb25zdCBERUNJU0lPTl9CVUZGRVJfU0laRSA9IDIwMDtcblxuaW50ZXJmYWNlIFBlcm1pc3Npb25EZWNpc2lvblRyYWNrZXIge1xuICB0cmFja0RlY2lzaW9uKFxuICAgIHNlc3Npb25JZDogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgIHRvb2xOYW1lOiBzdHJpbmcsXG4gICAgaW5wdXQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICAgIHJlc3VsdDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgcGxhdGZvcm06IHN0cmluZyxcbiAgKTogdm9pZDtcbiAgZ2V0UmVjZW50RGVjaXNpb25zKCk6IFBlcm1pc3Npb25EZWNpc2lvbltdO1xufVxuXG5jb25zdCBDTEFVREVfQ09NUEFUSUJMRV9IT09LX1BMQVRGT1JNUyA9IG5ldyBTZXQoWydjbGF1ZGVfY29kZScsICd2c2NvZGUnXSk7XG5jb25zdCBOT1JNQUxJWkFCTEVfUEVSTUlTU0lPTl9ERUNJU0lPTlMgPSBuZXcgU2V0KFsnYWxsb3cnLCAnZGVueScsICdhc2snXSk7XG50eXBlIE5vcm1hbGl6YWJsZVBlcm1pc3Npb25EZWNpc2lvbiA9ICdhbGxvdycgfCAnZGVueScgfCAnYXNrJztcblxuLyoqIEV4dHJhY3QgYSBzdHJpbmcgZmllbGQgZnJvbSBhIHJlY29yZCwgdHJ5aW5nIG11bHRpcGxlIGtleXMgaW4gb3JkZXIgKi9cbmZ1bmN0aW9uIGV4dHJhY3RTdHJpbmcob2JqOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwga2V5czogc3RyaW5nW10sIGZhbGxiYWNrOiBzdHJpbmcpOiBzdHJpbmcge1xuICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgY29uc3QgdmFsID0gb2JqPy5ba2V5XTtcbiAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpIHJldHVybiB2YWw7XG4gIH1cbiAgcmV0dXJuIGZhbGxiYWNrO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0RGVjaXNpb24ocmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHN0cmluZyB7XG4gIGNvbnN0IG5lc3RlZCA9IHJlc3VsdC5ob29rU3BlY2lmaWNPdXRwdXQ7XG4gIGlmIChuZXN0ZWQgJiYgdHlwZW9mIG5lc3RlZCA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkobmVzdGVkKSkge1xuICAgIGNvbnN0IG5lc3RlZERlY2lzaW9uID0gKG5lc3RlZCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikucGVybWlzc2lvbkRlY2lzaW9uO1xuICAgIGlmICh0eXBlb2YgbmVzdGVkRGVjaXNpb24gPT09ICdzdHJpbmcnKSByZXR1cm4gbmVzdGVkRGVjaXNpb247XG4gIH1cblxuICBpZiAodHlwZW9mIHJlc3VsdC5wZXJtaXNzaW9uID09PSAnc3RyaW5nJykgcmV0dXJuIHJlc3VsdC5wZXJtaXNzaW9uO1xuICBpZiAodHlwZW9mIHJlc3VsdC5kZWNpc2lvbiA9PT0gJ3N0cmluZycpIHJldHVybiByZXN1bHQuZGVjaXNpb247XG4gIGlmICh0eXBlb2YgcmVzdWx0LmJlaGF2aW9yID09PSAnc3RyaW5nJykgcmV0dXJuIHJlc3VsdC5iZWhhdmlvcjtcbiAgaWYgKHR5cGVvZiByZXN1bHQuYWxsb3dlZCA9PT0gJ2Jvb2xlYW4nKSByZXR1cm4gcmVzdWx0LmFsbG93ZWQgPyAnYWxsb3cnIDogJ2RlbnknO1xuICByZXR1cm4gJ3Vua25vd24nO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0UmVhc29uKHJlc3VsdDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBzdHJpbmcge1xuICBjb25zdCBuZXN0ZWQgPSByZXN1bHQuaG9va1NwZWNpZmljT3V0cHV0O1xuICBpZiAobmVzdGVkICYmIHR5cGVvZiBuZXN0ZWQgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KG5lc3RlZCkpIHtcbiAgICBjb25zdCBuZXN0ZWRSZWFzb24gPSAobmVzdGVkIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KS5wZXJtaXNzaW9uRGVjaXNpb25SZWFzb247XG4gICAgaWYgKHR5cGVvZiBuZXN0ZWRSZWFzb24gPT09ICdzdHJpbmcnKSByZXR1cm4gbmVzdGVkUmVhc29uO1xuICB9XG5cbiAgcmV0dXJuIGV4dHJhY3RTdHJpbmcocmVzdWx0LCBbJ3JlYXNvbicsICdtZXNzYWdlJ10sICcnKTtcbn1cblxuZnVuY3Rpb24gc2hvdWxkTm9ybWFsaXplQ2xhdWRlSG9vayhwbGF0Zm9ybTogc3RyaW5nIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gIHJldHVybiBwbGF0Zm9ybSAhPT0gdW5kZWZpbmVkICYmIENMQVVERV9DT01QQVRJQkxFX0hPT0tfUExBVEZPUk1TLmhhcyhwbGF0Zm9ybSk7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVBlcm1pc3Npb25SZXNwb25zZUZvclBsYXRmb3JtKFxuICBwbGF0Zm9ybTogc3RyaW5nLFxuICBpbnB1dDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIHJlc3VsdDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGlmICghc2hvdWxkTm9ybWFsaXplQ2xhdWRlSG9vayhwbGF0Zm9ybSkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgY29uc3QgbmVzdGVkID0gcmVzdWx0Lmhvb2tTcGVjaWZpY091dHB1dDtcbiAgaWYgKG5lc3RlZCAmJiB0eXBlb2YgbmVzdGVkID09PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheShuZXN0ZWQpKSB7XG4gICAgY29uc3QgbmVzdGVkRGVjaXNpb24gPSAobmVzdGVkIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KS5wZXJtaXNzaW9uRGVjaXNpb247XG4gICAgaWYgKHR5cGVvZiBuZXN0ZWREZWNpc2lvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgZGVjaXNpb24gPSBleHRyYWN0RGVjaXNpb24ocmVzdWx0KTtcbiAgaWYgKE5PUk1BTElaQUJMRV9QRVJNSVNTSU9OX0RFQ0lTSU9OUy5oYXMoZGVjaXNpb24pKSB7XG4gICAgcmV0dXJuIGZvcm1hdFBlcm1pc3Npb25SZXNwb25zZShcbiAgICAgIGRlY2lzaW9uIGFzIE5vcm1hbGl6YWJsZVBlcm1pc3Npb25EZWNpc2lvbixcbiAgICAgIHBsYXRmb3JtLFxuICAgICAgaW5wdXQsXG4gICAgICBleHRyYWN0UmVhc29uKHJlc3VsdCksXG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiBmb3JtYXRQZXJtaXNzaW9uUmVzcG9uc2UoJ2FsbG93JywgcGxhdGZvcm0sIGlucHV0KTtcbn1cblxuZnVuY3Rpb24gYnVpbGREZWNpc2lvbkRldGFpbHMoXG4gIHRvb2xOYW1lOiBzdHJpbmcsXG4gIGlucHV0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgcGxhdGZvcm06IHN0cmluZyxcbik6IHsgdGFyZ2V0Pzogc3RyaW5nOyB0YXJnZXRMYWJlbD86IHN0cmluZzsgZGV0YWlsczogUGVybWlzc2lvbkRlY2lzaW9uRGV0YWlsW10gfSB7XG4gIGNvbnN0IGRldGFpbHM6IFBlcm1pc3Npb25EZWNpc2lvbkRldGFpbFtdID0gW107XG5cbiAgaWYgKHBsYXRmb3JtKSB7XG4gICAgZGV0YWlscy5wdXNoKHsgbGFiZWw6ICdQbGF0Zm9ybScsIHZhbHVlOiBwbGF0Zm9ybSwgbW9ub3NwYWNlOiB0cnVlIH0pO1xuICB9XG5cbiAgaWYgKHRvb2xOYW1lID09PSAnQmFzaCcgJiYgdHlwZW9mIGlucHV0LmNvbW1hbmQgPT09ICdzdHJpbmcnICYmIGlucHV0LmNvbW1hbmQgIT09ICcnKSB7XG4gICAgZGV0YWlscy5wdXNoKHsgbGFiZWw6ICdDb21tYW5kJywgdmFsdWU6IGlucHV0LmNvbW1hbmQsIG1vbm9zcGFjZTogdHJ1ZSB9KTtcbiAgfVxuXG4gIGNvbnN0IHRhcmdldERlc2NyaXB0b3JzOiBBcnJheTx7IGtleTogc3RyaW5nOyBsYWJlbDogc3RyaW5nOyBtb25vc3BhY2U/OiBib29sZWFuIH0+ID0gW1xuICAgIHsga2V5OiAnZmlsZV9wYXRoJywgbGFiZWw6ICdGaWxlJywgbW9ub3NwYWNlOiB0cnVlIH0sXG4gICAgeyBrZXk6ICdwYXRoJywgbGFiZWw6ICdQYXRoJywgbW9ub3NwYWNlOiB0cnVlIH0sXG4gICAgeyBrZXk6ICd1cmwnLCBsYWJlbDogJ1VSTCcgfSxcbiAgICB7IGtleTogJ3BhdHRlcm4nLCBsYWJlbDogJ1BhdHRlcm4nLCBtb25vc3BhY2U6IHRydWUgfSxcbiAgICB7IGtleTogJ3F1ZXJ5JywgbGFiZWw6ICdRdWVyeScgfSxcbiAgICB7IGtleTogJ2VsZW1lbnRfbmFtZScsIGxhYmVsOiAnRWxlbWVudCcsIG1vbm9zcGFjZTogdHJ1ZSB9LFxuICAgIHsga2V5OiAncmVxdWVzdF9pZCcsIGxhYmVsOiAnUmVxdWVzdCcsIG1vbm9zcGFjZTogdHJ1ZSB9LFxuICBdO1xuXG4gIGxldCB0YXJnZXQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgbGV0IHRhcmdldExhYmVsOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgZm9yIChjb25zdCBkZXNjcmlwdG9yIG9mIHRhcmdldERlc2NyaXB0b3JzKSB7XG4gICAgY29uc3QgdmFsdWUgPSBpbnB1dFtkZXNjcmlwdG9yLmtleV07XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycgfHwgdmFsdWUgPT09ICcnKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICB0YXJnZXQgPSB2YWx1ZTtcbiAgICB0YXJnZXRMYWJlbCA9IGRlc2NyaXB0b3IubGFiZWw7XG4gICAgZGV0YWlscy5wdXNoKHsgbGFiZWw6IGRlc2NyaXB0b3IubGFiZWwsIHZhbHVlLCBtb25vc3BhY2U6IGRlc2NyaXB0b3IubW9ub3NwYWNlIH0pO1xuICAgIGJyZWFrO1xuICB9XG5cbiAgY29uc3QgbWF0Y2hlZFBhdHRlcm4gPSBleHRyYWN0U3RyaW5nKHJlc3VsdCwgWydtYXRjaGVkX3BhdHRlcm4nLCAnbWF0Y2hlZFBhdHRlcm4nXSwgJycpO1xuICBpZiAobWF0Y2hlZFBhdHRlcm4gIT09ICcnKSB7XG4gICAgZGV0YWlscy5wdXNoKHsgbGFiZWw6ICdNYXRjaGVkIFBhdHRlcm4nLCB2YWx1ZTogbWF0Y2hlZFBhdHRlcm4sIG1vbm9zcGFjZTogdHJ1ZSB9KTtcbiAgfVxuXG4gIGNvbnN0IHBvbGljeVNvdXJjZSA9IGV4dHJhY3RTdHJpbmcocmVzdWx0LCBbJ3BvbGljeV9zb3VyY2UnLCAncG9saWN5U291cmNlJ10sICcnKTtcbiAgaWYgKHBvbGljeVNvdXJjZSAhPT0gJycpIHtcbiAgICBkZXRhaWxzLnB1c2goeyBsYWJlbDogJ1BvbGljeSBTb3VyY2UnLCB2YWx1ZTogcG9saWN5U291cmNlLCBtb25vc3BhY2U6IHRydWUgfSk7XG4gIH1cblxuICByZXR1cm4geyB0YXJnZXQsIHRhcmdldExhYmVsLCBkZXRhaWxzIH07XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVBlcm1pc3Npb25EZWNpc2lvblRyYWNrZXIoYnVmZmVyU2l6ZSA9IERFQ0lTSU9OX0JVRkZFUl9TSVpFKTogUGVybWlzc2lvbkRlY2lzaW9uVHJhY2tlciB7XG4gIGNvbnN0IHJlY2VudERlY2lzaW9uczogUGVybWlzc2lvbkRlY2lzaW9uW10gPSBbXTtcbiAgbGV0IGRlY2lzaW9uQ291bnRlciA9IDA7XG5cbiAgcmV0dXJuIHtcbiAgICB0cmFja0RlY2lzaW9uKFxuICAgICAgc2Vzc2lvbklkOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgICB0b29sTmFtZTogc3RyaW5nLFxuICAgICAgaW5wdXQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICAgICAgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICAgIHBsYXRmb3JtOiBzdHJpbmcsXG4gICAgKTogdm9pZCB7XG4gICAgICBjb25zdCBkZXRhaWxTdGF0ZSA9IGJ1aWxkRGVjaXNpb25EZXRhaWxzKHRvb2xOYW1lLCBpbnB1dCwgcmVzdWx0LCBwbGF0Zm9ybSk7XG4gICAgICBjb25zdCBlbnRyeTogUGVybWlzc2lvbkRlY2lzaW9uID0ge1xuICAgICAgICBpZDogYGQtJHsrK2RlY2lzaW9uQ291bnRlcn1gLFxuICAgICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgLi4uKHNlc3Npb25JZCA/IHsgc2Vzc2lvbl9pZDogc2Vzc2lvbklkIH0gOiB7fSksXG4gICAgICAgIHRvb2xfbmFtZTogdG9vbE5hbWUsXG4gICAgICAgIGNvbW1hbmQ6IHRvb2xOYW1lID09PSAnQmFzaCcgJiYgdHlwZW9mIGlucHV0Py5jb21tYW5kID09PSAnc3RyaW5nJyA/IGlucHV0LmNvbW1hbmQgOiB1bmRlZmluZWQsXG4gICAgICAgIGRlY2lzaW9uOiBleHRyYWN0RGVjaXNpb24ocmVzdWx0KSxcbiAgICAgICAgcmVhc29uOiBleHRyYWN0UmVhc29uKHJlc3VsdCksXG4gICAgICAgIHBsYXRmb3JtLFxuICAgICAgICB0YXJnZXQ6IGRldGFpbFN0YXRlLnRhcmdldCxcbiAgICAgICAgdGFyZ2V0TGFiZWw6IGRldGFpbFN0YXRlLnRhcmdldExhYmVsLFxuICAgICAgICBkZXRhaWxzOiBkZXRhaWxTdGF0ZS5kZXRhaWxzLFxuICAgICAgfTtcbiAgICAgIHJlY2VudERlY2lzaW9ucy51bnNoaWZ0KGVudHJ5KTtcbiAgICAgIGlmIChyZWNlbnREZWNpc2lvbnMubGVuZ3RoID4gYnVmZmVyU2l6ZSkge1xuICAgICAgICByZWNlbnREZWNpc2lvbnMubGVuZ3RoID0gYnVmZmVyU2l6ZTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGdldFJlY2VudERlY2lzaW9ucygpOiBQZXJtaXNzaW9uRGVjaXNpb25bXSB7XG4gICAgICByZXR1cm4gcmVjZW50RGVjaXNpb25zO1xuICAgIH0sXG4gIH07XG59XG5cbmZ1bmN0aW9uIG1lcmdlUnVsZUFycmF5cyguLi5zb3VyY2VzOiB1bmtub3duW10pOiBzdHJpbmdbXSB7XG4gIGNvbnN0IG1lcmdlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBmb3IgKGNvbnN0IHNvdXJjZSBvZiBzb3VyY2VzKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHNvdXJjZSkpIGNvbnRpbnVlO1xuICAgIGZvciAoY29uc3QgZW50cnkgb2Ygc291cmNlKSB7XG4gICAgICBpZiAodHlwZW9mIGVudHJ5ID09PSAnc3RyaW5nJyAmJiBlbnRyeSAhPT0gJycpIHtcbiAgICAgICAgbWVyZ2VkLmFkZChlbnRyeSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBBcnJheS5mcm9tKG1lcmdlZCk7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVBvbGljeUVsZW1lbnRzKGVsZW1lbnRzOiBBcnJheTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4pOiBBcnJheTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4ge1xuICByZXR1cm4gZWxlbWVudHMubWFwKChlbGVtZW50KSA9PiAoe1xuICAgIC4uLmVsZW1lbnQsXG4gICAgZWxlbWVudF9uYW1lOiByZXNvbHZlRWxlbWVudE5hbWUoZWxlbWVudCksXG4gICAgYWxsb3dSdWxlczogbWVyZ2VSdWxlQXJyYXlzKGVsZW1lbnQuYWxsb3dQYXR0ZXJucywgZWxlbWVudC5hbGxvd09wZXJhdGlvbnMpLFxuICAgIGNvbmZpcm1SdWxlczogbWVyZ2VSdWxlQXJyYXlzKGVsZW1lbnQuY29uZmlybVBhdHRlcm5zLCBlbGVtZW50LmNvbmZpcm1PcGVyYXRpb25zKSxcbiAgICBkZW55UnVsZXM6IG1lcmdlUnVsZUFycmF5cyhlbGVtZW50LmRlbnlQYXR0ZXJucywgZWxlbWVudC5kZW55T3BlcmF0aW9ucyksXG4gICAgaW52YWxpZEdhdGVrZWVwZXJQb2xpY3k6ICEhZWxlbWVudC5pbnZhbGlkR2F0ZWtlZXBlclBvbGljeSxcbiAgICBpbnZhbGlkR2F0ZWtlZXBlck1lc3NhZ2U6IHR5cGVvZiBlbGVtZW50LmludmFsaWRHYXRla2VlcGVyTWVzc2FnZSA9PT0gJ3N0cmluZycgPyBlbGVtZW50LmludmFsaWRHYXRla2VlcGVyTWVzc2FnZSA6IHVuZGVmaW5lZCxcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRWxlbWVudE5hbWUoZWxlbWVudDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBzdHJpbmcge1xuICBpZiAodHlwZW9mIGVsZW1lbnQuZWxlbWVudF9uYW1lID09PSAnc3RyaW5nJykgcmV0dXJuIGVsZW1lbnQuZWxlbWVudF9uYW1lO1xuICBpZiAodHlwZW9mIGVsZW1lbnQubmFtZSA9PT0gJ3N0cmluZycpIHJldHVybiBlbGVtZW50Lm5hbWU7XG4gIHJldHVybiAnJztcbn1cblxuLyoqIEhlbHBlciB0byBleHRyYWN0IHNpbmdsZSByZXN1bHQgZnJvbSBNQ1AtQVFMIGJhdGNoIHJlc3BvbnNlICovXG5mdW5jdGlvbiBhc1NpbmdsZVJlc3VsdChyZXN1bHRzOiB1bmtub3duKTogeyBzdWNjZXNzOiBib29sZWFuOyBkYXRhPzogdW5rbm93bjsgZXJyb3I/OiBzdHJpbmcgfSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHJlc3VsdHMpKSByZXR1cm4gcmVzdWx0c1swXSB8fCB7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogJ0VtcHR5IHJlc3VsdCcgfTtcbiAgcmV0dXJuIHJlc3VsdHMgYXMgeyBzdWNjZXNzOiBib29sZWFuOyBkYXRhPzogdW5rbm93bjsgZXJyb3I/OiBzdHJpbmcgfTtcbn1cblxuZnVuY3Rpb24gZXh0cmFjdEtub3duUG9saWN5U2Vzc2lvbnMoZWxlbWVudHM6IEFycmF5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pik6IEtub3duUG9saWN5U2Vzc2lvbltdIHtcbiAgY29uc3Qgc2VlbiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBjb25zdCBrbm93blNlc3Npb25zOiBLbm93blBvbGljeVNlc3Npb25bXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZWxlbWVudCBvZiBlbGVtZW50cykge1xuICAgIGNvbnN0IHNlc3Npb25JZHMgPSBBcnJheS5pc0FycmF5KGVsZW1lbnQuc2Vzc2lvbklkcykgPyBlbGVtZW50LnNlc3Npb25JZHMgOiBbXTtcbiAgICBmb3IgKGNvbnN0IHNlc3Npb25JZCBvZiBzZXNzaW9uSWRzKSB7XG4gICAgICBpZiAodHlwZW9mIHNlc3Npb25JZCAhPT0gJ3N0cmluZycgfHwgc2Vzc2lvbklkID09PSAnJyB8fCBzZWVuLmhhcyhzZXNzaW9uSWQpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBzZWVuLmFkZChzZXNzaW9uSWQpO1xuICAgICAga25vd25TZXNzaW9ucy5wdXNoKHtcbiAgICAgICAgc2Vzc2lvbklkLFxuICAgICAgICBkaXNwbGF5TmFtZTogc2Vzc2lvbklkLFxuICAgICAgICBzb3VyY2U6ICdwb2xpY3knLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGtub3duU2Vzc2lvbnMuc29ydCgoYSwgYikgPT4gYS5zZXNzaW9uSWQubG9jYWxlQ29tcGFyZShiLnNlc3Npb25JZCkpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVyIHBlcm1pc3Npb24tcmVsYXRlZCByb3V0ZXMgb24gYSBnYXRld2F5IHJvdXRlci5cbiAqIE11c3QgYmUgY2FsbGVkIHdpdGggdGhlIE1DUC1BUUwgaGFuZGxlciBmb3IgcG9saWN5IGV2YWx1YXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlclBlcm1pc3Npb25Sb3V0ZXMocm91dGVyOiBSb3V0ZXIsIGhhbmRsZXI6IE1DUEFRTEhhbmRsZXIpOiB2b2lkIHtcbiAgY29uc3QgZGVjaXNpb25UcmFja2VyID0gY3JlYXRlUGVybWlzc2lvbkRlY2lzaW9uVHJhY2tlcigpO1xuICAvKipcbiAgICogUE9TVCAvYXBpL2V2YWx1YXRlX3Blcm1pc3Npb25cbiAgICogUGVybWlzc2lvbiBldmFsdWF0aW9uIGVuZHBvaW50IGZvciBQcmVUb29sVXNlIGhvb2tzLlxuICAgKiBSb3V0ZXMgdGhyb3VnaCBldmFsdWF0ZV9wZXJtaXNzaW9uIE1DUC1BUUwgUkVBRCBvcGVyYXRpb24uXG4gICAqIEZhaWwtb3BlbjogcmV0dXJucyBhbGxvdyBvbiBhbnkgZXJyb3IgdG8gYXZvaWQgYmxvY2tpbmcgdGhlIHVzZXIuXG4gICAqL1xuICBjb25zdCBwZXJtaXNzaW9uTGltaXRlciA9IG5ldyBTbGlkaW5nV2luZG93UmF0ZUxpbWl0ZXIoXG4gICAgUEVSTUlTU0lPTl9ST1VURV9SQVRFX0xJTUlUX1JFUVVFU1RTLFxuICAgIFBFUk1JU1NJT05fUk9VVEVfUkFURV9MSU1JVF9XSU5ET1dfTVMsXG4gICk7XG4gIHJvdXRlci5wb3N0KCcvZXZhbHVhdGVfcGVybWlzc2lvbicsIGV4cHJlc3MuanNvbigpLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICBjb25zdCBib2R5ID0gcmVxLmJvZHkgYXMge1xuICAgICAgdG9vbF9uYW1lPzogc3RyaW5nO1xuICAgICAgaW5wdXQ/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIHBsYXRmb3JtPzogc3RyaW5nO1xuICAgICAgc2Vzc2lvbl9pZD86IHN0cmluZztcbiAgICB9O1xuICAgIGNvbnN0IHBsYXRmb3JtID0gdHlwZW9mIGJvZHkucGxhdGZvcm0gPT09ICdzdHJpbmcnID8gYm9keS5wbGF0Zm9ybS5ub3JtYWxpemUoJ05GQycpIDogJ2NsYXVkZV9jb2RlJztcblxuICAgIGlmICghcGVybWlzc2lvbkxpbWl0ZXIudHJ5QWNxdWlyZSgpKSB7XG4gICAgICByZXMuanNvbihmb3JtYXRQZXJtaXNzaW9uUmVzcG9uc2UoJ2FsbG93JywgcGxhdGZvcm0sIHt9KSk7IC8vIGZhaWwgb3BlbiBvbiByYXRlIGxpbWl0XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVW5pY29kZSBub3JtYWxpemF0aW9uIChORkMpIG9uIHN0cmluZyBpbnB1dHMgdG8gcHJldmVudCBob21vZ3JhcGggYXR0YWNrc1xuICAgIGNvbnN0IHRvb2xfbmFtZSA9IHR5cGVvZiBib2R5LnRvb2xfbmFtZSA9PT0gJ3N0cmluZycgPyBib2R5LnRvb2xfbmFtZS5ub3JtYWxpemUoJ05GQycpIDogdW5kZWZpbmVkO1xuICAgIGNvbnN0IHNlc3Npb25faWQgPSB0eXBlb2YgYm9keS5zZXNzaW9uX2lkID09PSAnc3RyaW5nJyA/IGJvZHkuc2Vzc2lvbl9pZC5ub3JtYWxpemUoJ05GQycpIDogdW5kZWZpbmVkO1xuICAgIGNvbnN0IGlucHV0ID0gYm9keS5pbnB1dDtcblxuICAgIGlmICghdG9vbF9uYW1lKSB7XG4gICAgICByZXMuanNvbihmb3JtYXRQZXJtaXNzaW9uUmVzcG9uc2UoJ2FsbG93JywgcGxhdGZvcm0sIGlucHV0IHx8IHt9KSk7IC8vIGZhaWwgb3BlbiBvbiBiYWQgaW5wdXRcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBzdGFydE1zID0gRGF0ZS5ub3coKTtcbiAgICB0cnkge1xuICAgICAgY29uc3Qgb3BSZXN1bHQgPSBhc1NpbmdsZVJlc3VsdChhd2FpdCBoYW5kbGVyLmhhbmRsZVJlYWQoe1xuICAgICAgICBvcGVyYXRpb246ICdldmFsdWF0ZV9wZXJtaXNzaW9uJyxcbiAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgdG9vbF9uYW1lLFxuICAgICAgICAgIGlucHV0OiBpbnB1dCB8fCB7fSxcbiAgICAgICAgICBwbGF0Zm9ybSxcbiAgICAgICAgICAuLi4oc2Vzc2lvbl9pZCA/IHsgc2Vzc2lvbl9pZCB9IDoge30pLFxuICAgICAgICB9LFxuICAgICAgfSkpO1xuICAgICAgY29uc3QgZWxhcHNlZE1zID0gRGF0ZS5ub3coKSAtIHN0YXJ0TXM7XG5cbiAgICAgIGlmICghb3BSZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICBsb2dnZXIud2FybihgW1dlYlVJL0dhdGV3YXldIGV2YWx1YXRlX3Blcm1pc3Npb24gZmFpbGVkICgke2VsYXBzZWRNc31tcyk6ICR7b3BSZXN1bHQuZXJyb3J9YCk7XG4gICAgICAgIHJlcy5qc29uKGZvcm1hdFBlcm1pc3Npb25SZXNwb25zZSgnYWxsb3cnLCBwbGF0Zm9ybSwgaW5wdXQgfHwge30pKTsgLy8gZmFpbCBvcGVuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmF3UmVzdWx0ID0gb3BSZXN1bHQuZGF0YSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIGNvbnN0IHJlc3BvbnNlRGF0YSA9IG5vcm1hbGl6ZVBlcm1pc3Npb25SZXNwb25zZUZvclBsYXRmb3JtKFxuICAgICAgICBwbGF0Zm9ybSxcbiAgICAgICAgaW5wdXQgfHwge30sXG4gICAgICAgIHJhd1Jlc3VsdCxcbiAgICAgICk7XG4gICAgICBjb25zdCB0cmFja2VkUmVzdWx0ID0geyAuLi5yYXdSZXN1bHQsIC4uLnJlc3BvbnNlRGF0YSB9O1xuICAgICAgY29uc3QgZGVjaXNpb24gPSBleHRyYWN0RGVjaXNpb24ocmVzcG9uc2VEYXRhKTtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgW1dlYlVJL0dhdGV3YXldIGV2YWx1YXRlX3Blcm1pc3Npb246ICR7dG9vbF9uYW1lfSDihpIgJHtkZWNpc2lvbn0gKCR7ZWxhcHNlZE1zfW1zKWApO1xuXG4gICAgICAvLyBUcmFjayBkZWNpc2lvbiBmb3IgbGl2ZSBkYXNoYm9hcmQgZmVlZFxuICAgICAgZGVjaXNpb25UcmFja2VyLnRyYWNrRGVjaXNpb24oc2Vzc2lvbl9pZCwgdG9vbF9uYW1lLCBpbnB1dCB8fCB7fSwgdHJhY2tlZFJlc3VsdCwgcGxhdGZvcm0pO1xuXG4gICAgICByZXMuanNvbihyZXNwb25zZURhdGEpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc3QgZWxhcHNlZE1zID0gRGF0ZS5ub3coKSAtIHN0YXJ0TXM7XG4gICAgICBsb2dnZXIuZXJyb3IoYFtXZWJVSS9HYXRld2F5XSBldmFsdWF0ZV9wZXJtaXNzaW9uIGVycm9yICgke2VsYXBzZWRNc31tcyk6YCwgZXJyKTtcbiAgICAgIHJlcy5qc29uKGZvcm1hdFBlcm1pc3Npb25SZXNwb25zZSgnYWxsb3cnLCBwbGF0Zm9ybSwgaW5wdXQgfHwge30pKTsgLy8gZmFpbCBvcGVuXG4gICAgfVxuICB9KTtcblxuICAvKipcbiAgICogR0VUIC9hcGkvcGVybWlzc2lvbnMvc3RhdHVzXG4gICAqIFJldHVybnMgY3VycmVudCBwZXJtaXNzaW9uIHBvbGljaWVzIGFuZCByZWNlbnQgZGVjaXNpb25zXG4gICAqIGZvciB0aGUgbGl2ZSBwZXJtaXNzaW9ucyBkYXNoYm9hcmQuXG4gICAqL1xuICByb3V0ZXIuZ2V0KCcvcGVybWlzc2lvbnMvc3RhdHVzJywgYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHNlc3Npb25JZCA9IHR5cGVvZiByZXEucXVlcnlbJ3Nlc3Npb25JZCddID09PSAnc3RyaW5nJyAmJiByZXEucXVlcnlbJ3Nlc3Npb25JZCddXG4gICAgICAgID8gcmVxLnF1ZXJ5WydzZXNzaW9uSWQnXVxuICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgY29uc3Qgb3BSZXN1bHQgPSBhc1NpbmdsZVJlc3VsdChhd2FpdCBoYW5kbGVyLmhhbmRsZVJlYWQoe1xuICAgICAgICBvcGVyYXRpb246ICdnZXRfZWZmZWN0aXZlX2NsaV9wb2xpY2llcycsXG4gICAgICAgIHBhcmFtczoge1xuICAgICAgICAgIHJlcG9ydGluZ19zY29wZTogJ2Rhc2hib2FyZCcsXG4gICAgICAgICAgLi4uKHNlc3Npb25JZCA/IHsgc2Vzc2lvbl9pZDogc2Vzc2lvbklkIH0gOiB7fSksXG4gICAgICAgIH0sXG4gICAgICB9KSk7XG5cbiAgICAgIGlmICghb3BSZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICByZXMuc3RhdHVzKDUwMCkuanNvbih7IGVycm9yOiBvcFJlc3VsdC5lcnJvciB8fCAnRmFpbGVkIHRvIGdldCBwb2xpY2llcycgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGF0YSA9IG9wUmVzdWx0LmRhdGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICBjb25zdCBlbGVtZW50cyA9IG5vcm1hbGl6ZVBvbGljeUVsZW1lbnRzKChkYXRhLmVsZW1lbnRzIHx8IFtdKSBhcyBBcnJheTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4pO1xuXG4gICAgICBjb25zdCBkZW55UGF0dGVybnMgPSAoZGF0YS5jb21iaW5lZERlbnlQYXR0ZXJucyBhcyBzdHJpbmdbXSB8IHVuZGVmaW5lZCkgPz8gW107XG4gICAgICBjb25zdCBhbGxvd1BhdHRlcm5zID0gKGRhdGEuY29tYmluZWRBbGxvd1BhdHRlcm5zIGFzIHN0cmluZ1tdIHwgdW5kZWZpbmVkKSA/PyBbXTtcbiAgICAgIGNvbnN0IGNvbmZpcm1QYXR0ZXJucyA9IChkYXRhLmNvbWJpbmVkQ29uZmlybVBhdHRlcm5zIGFzIHN0cmluZ1tdIHwgdW5kZWZpbmVkKSA/PyBbXTtcbiAgICAgIGNvbnN0IGRlbnlPcGVyYXRpb25zID0gKGRhdGEuY29tYmluZWREZW55T3BlcmF0aW9ucyBhcyBzdHJpbmdbXSB8IHVuZGVmaW5lZCkgPz8gW107XG4gICAgICBjb25zdCBhbGxvd09wZXJhdGlvbnMgPSAoZGF0YS5jb21iaW5lZEFsbG93T3BlcmF0aW9ucyBhcyBzdHJpbmdbXSB8IHVuZGVmaW5lZCkgPz8gW107XG4gICAgICBjb25zdCBjb25maXJtT3BlcmF0aW9ucyA9IChkYXRhLmNvbWJpbmVkQ29uZmlybU9wZXJhdGlvbnMgYXMgc3RyaW5nW10gfCB1bmRlZmluZWQpID8/IFtdO1xuXG4gICAgICByZXMuanNvbih7XG4gICAgICAgIC4uLihzZXNzaW9uSWQgPyB7IHNlc3Npb25JZCB9IDoge30pLFxuICAgICAgICBhY3RpdmVFbGVtZW50Q291bnQ6IGRhdGEuYWN0aXZlRWxlbWVudENvdW50LFxuICAgICAgICBoYXNBbGxvd2xpc3Q6IGRhdGEuaGFzQWxsb3dsaXN0LFxuICAgICAgICBkZW55UGF0dGVybnMsXG4gICAgICAgIGFsbG93UGF0dGVybnMsXG4gICAgICAgIGNvbmZpcm1QYXR0ZXJucyxcbiAgICAgICAgZGVueU9wZXJhdGlvbnMsXG4gICAgICAgIGFsbG93T3BlcmF0aW9ucyxcbiAgICAgICAgY29uZmlybU9wZXJhdGlvbnMsXG4gICAgICAgIGRlbnlSdWxlczogbWVyZ2VSdWxlQXJyYXlzKGRlbnlQYXR0ZXJucywgZGVueU9wZXJhdGlvbnMpLFxuICAgICAgICBhbGxvd1J1bGVzOiBtZXJnZVJ1bGVBcnJheXMoYWxsb3dQYXR0ZXJucywgYWxsb3dPcGVyYXRpb25zKSxcbiAgICAgICAgY29uZmlybVJ1bGVzOiBtZXJnZVJ1bGVBcnJheXMoY29uZmlybVBhdHRlcm5zLCBjb25maXJtT3BlcmF0aW9ucyksXG4gICAgICAgIGVsZW1lbnRzLFxuICAgICAgICBrbm93blNlc3Npb25zOiBleHRyYWN0S25vd25Qb2xpY3lTZXNzaW9ucyhlbGVtZW50cyksXG4gICAgICAgIHBlcm1pc3Npb25Qcm9tcHRBY3RpdmU6IGRhdGEucGVybWlzc2lvblByb21wdEFjdGl2ZSxcbiAgICAgICAgaG9va0luc3RhbGxlZDogZGF0YS5ob29rSW5zdGFsbGVkLFxuICAgICAgICBob29rSG9zdDogZGF0YS5ob29rSG9zdCxcbiAgICAgICAgZW5mb3JjZW1lbnRSZWFkeTogZGF0YS5lbmZvcmNlbWVudFJlYWR5LFxuICAgICAgICBpbnZhbGlkUG9saWN5RWxlbWVudENvdW50OiBkYXRhLmludmFsaWRQb2xpY3lFbGVtZW50Q291bnQgPz8gMCxcbiAgICAgICAgYWR2aXNvcnk6IGRhdGEuYWR2aXNvcnksXG4gICAgICAgIHJlY2VudERlY2lzaW9uczogZGVjaXNpb25UcmFja2VyLmdldFJlY2VudERlY2lzaW9ucygpLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ1tXZWJVSS9HYXRld2F5XSBwZXJtaXNzaW9ucy9zdGF0dXMgZXJyb3I6JywgZXJyKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHsgZXJyb3I6ICdGYWlsZWQgdG8gZ2V0IHBlcm1pc3Npb24gc3RhdHVzJyB9KTtcbiAgICB9XG4gIH0pO1xufVxuIl19