@dollhousemcp/mcp-server 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1004) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/LICENSE +51 -0
  3. package/README.md +1124 -0
  4. package/data/agents/code-reviewer.md +296 -0
  5. package/data/agents/research-assistant.md +259 -0
  6. package/data/agents/task-manager.md +206 -0
  7. package/data/ensembles/business-advisor.md +354 -0
  8. package/data/ensembles/creative-studio.md +288 -0
  9. package/data/ensembles/development-team.md +292 -0
  10. package/data/ensembles/security-analysis-team.md +438 -0
  11. package/data/memories/conversation-history.md +146 -0
  12. package/data/memories/learning-progress.md +376 -0
  13. package/data/memories/project-context.md +268 -0
  14. package/data/personas/business-consultant.md +50 -0
  15. package/data/personas/creative-writer.md +44 -0
  16. package/data/personas/debug-detective.md +59 -0
  17. package/data/personas/eli5-explainer.md +49 -0
  18. package/data/personas/security-analyst.md +161 -0
  19. package/data/personas/technical-analyst.md +43 -0
  20. package/data/skills/code-review.md +112 -0
  21. package/data/skills/creative-writing.md +174 -0
  22. package/data/skills/data-analysis.md +160 -0
  23. package/data/skills/penetration-testing.md +374 -0
  24. package/data/skills/research.md +181 -0
  25. package/data/skills/threat-modeling.md +469 -0
  26. package/data/skills/translation.md +148 -0
  27. package/data/templates/code-documentation.md +409 -0
  28. package/data/templates/email-professional.md +158 -0
  29. package/data/templates/meeting-notes.md +141 -0
  30. package/data/templates/penetration-test-report.md +608 -0
  31. package/data/templates/project-brief.md +234 -0
  32. package/data/templates/report-executive.md +258 -0
  33. package/data/templates/security-vulnerability-report.md +457 -0
  34. package/data/templates/threat-assessment-report.md +774 -0
  35. package/dist/cache/APICache.d.ts +23 -0
  36. package/dist/cache/APICache.d.ts.map +1 -0
  37. package/dist/cache/APICache.js +42 -0
  38. package/dist/cache/index.d.ts +5 -0
  39. package/dist/cache/index.d.ts.map +1 -0
  40. package/dist/cache/index.js +5 -0
  41. package/dist/collection/CollectionBrowser.d.ts +24 -0
  42. package/dist/collection/CollectionBrowser.d.ts.map +1 -0
  43. package/dist/collection/CollectionBrowser.js +120 -0
  44. package/dist/collection/CollectionSearch.d.ts +18 -0
  45. package/dist/collection/CollectionSearch.d.ts.map +1 -0
  46. package/dist/collection/CollectionSearch.js +48 -0
  47. package/dist/collection/ElementInstaller.d.ts +33 -0
  48. package/dist/collection/ElementInstaller.d.ts.map +1 -0
  49. package/dist/collection/ElementInstaller.js +142 -0
  50. package/dist/collection/GitHubClient.d.ts +22 -0
  51. package/dist/collection/GitHubClient.d.ts.map +1 -0
  52. package/dist/collection/GitHubClient.js +114 -0
  53. package/dist/collection/MarketplaceBrowser.d.ts +24 -0
  54. package/dist/collection/MarketplaceBrowser.d.ts.map +1 -0
  55. package/dist/collection/MarketplaceBrowser.js +115 -0
  56. package/dist/collection/MarketplaceSearch.d.ts +18 -0
  57. package/dist/collection/MarketplaceSearch.d.ts.map +1 -0
  58. package/dist/collection/MarketplaceSearch.js +48 -0
  59. package/dist/collection/PersonaDetails.d.ts +22 -0
  60. package/dist/collection/PersonaDetails.d.ts.map +1 -0
  61. package/dist/collection/PersonaDetails.js +71 -0
  62. package/dist/collection/PersonaInstaller.d.ts +26 -0
  63. package/dist/collection/PersonaInstaller.d.ts.map +1 -0
  64. package/dist/collection/PersonaInstaller.js +103 -0
  65. package/dist/collection/PersonaSubmitter.d.ts +19 -0
  66. package/dist/collection/PersonaSubmitter.d.ts.map +1 -0
  67. package/dist/collection/PersonaSubmitter.js +57 -0
  68. package/dist/collection/index.d.ts +10 -0
  69. package/dist/collection/index.d.ts.map +1 -0
  70. package/dist/collection/index.js +10 -0
  71. package/dist/config/constants.d.ts +25 -0
  72. package/dist/config/constants.d.ts.map +1 -0
  73. package/dist/config/constants.js +34 -0
  74. package/dist/config/index.d.ts +6 -0
  75. package/dist/config/index.d.ts.map +1 -0
  76. package/dist/config/index.js +6 -0
  77. package/dist/config/indicator-config.d.ts +107 -0
  78. package/dist/config/indicator-config.d.ts.map +1 -0
  79. package/dist/config/indicator-config.js +158 -0
  80. package/dist/constants/defaultPersonas.d.ts +10 -0
  81. package/dist/constants/defaultPersonas.d.ts.map +1 -0
  82. package/dist/constants/defaultPersonas.js +18 -0
  83. package/dist/constants/limits.d.ts +10 -0
  84. package/dist/constants/limits.d.ts.map +1 -0
  85. package/dist/constants/limits.js +13 -0
  86. package/dist/elements/BaseElement.d.ts +81 -0
  87. package/dist/elements/BaseElement.d.ts.map +1 -0
  88. package/dist/elements/BaseElement.js +381 -0
  89. package/dist/elements/FeedbackProcessor.d.ts +57 -0
  90. package/dist/elements/FeedbackProcessor.d.ts.map +1 -0
  91. package/dist/elements/FeedbackProcessor.js +418 -0
  92. package/dist/elements/agents/Agent.d.ts +145 -0
  93. package/dist/elements/agents/Agent.d.ts.map +1 -0
  94. package/dist/elements/agents/Agent.js +848 -0
  95. package/dist/elements/agents/AgentManager.d.ts +125 -0
  96. package/dist/elements/agents/AgentManager.d.ts.map +1 -0
  97. package/dist/elements/agents/AgentManager.js +615 -0
  98. package/dist/elements/agents/constants.d.ts +42 -0
  99. package/dist/elements/agents/constants.d.ts.map +1 -0
  100. package/dist/elements/agents/constants.js +45 -0
  101. package/dist/elements/agents/goalTemplates.d.ts +44 -0
  102. package/dist/elements/agents/goalTemplates.d.ts.map +1 -0
  103. package/dist/elements/agents/goalTemplates.js +297 -0
  104. package/dist/elements/agents/index.d.ts +8 -0
  105. package/dist/elements/agents/index.d.ts.map +1 -0
  106. package/dist/elements/agents/index.js +8 -0
  107. package/dist/elements/agents/ruleEngineConfig.d.ts +76 -0
  108. package/dist/elements/agents/ruleEngineConfig.d.ts.map +1 -0
  109. package/dist/elements/agents/ruleEngineConfig.js +143 -0
  110. package/dist/elements/agents/types.d.ts +97 -0
  111. package/dist/elements/agents/types.d.ts.map +1 -0
  112. package/dist/elements/agents/types.js +5 -0
  113. package/dist/elements/ensembles/Ensemble.d.ts +144 -0
  114. package/dist/elements/ensembles/Ensemble.d.ts.map +1 -0
  115. package/dist/elements/ensembles/Ensemble.js +860 -0
  116. package/dist/elements/ensembles/EnsembleManager.d.ts +85 -0
  117. package/dist/elements/ensembles/EnsembleManager.d.ts.map +1 -0
  118. package/dist/elements/ensembles/EnsembleManager.js +378 -0
  119. package/dist/elements/ensembles/constants.d.ts +73 -0
  120. package/dist/elements/ensembles/constants.d.ts.map +1 -0
  121. package/dist/elements/ensembles/constants.js +92 -0
  122. package/dist/elements/ensembles/index.d.ts +8 -0
  123. package/dist/elements/ensembles/index.d.ts.map +1 -0
  124. package/dist/elements/ensembles/index.js +8 -0
  125. package/dist/elements/ensembles/types.d.ts +92 -0
  126. package/dist/elements/ensembles/types.d.ts.map +1 -0
  127. package/dist/elements/ensembles/types.js +8 -0
  128. package/dist/elements/index.d.ts +11 -0
  129. package/dist/elements/index.d.ts.map +1 -0
  130. package/dist/elements/index.js +12 -0
  131. package/dist/elements/memories/Memory.d.ts +110 -0
  132. package/dist/elements/memories/Memory.d.ts.map +1 -0
  133. package/dist/elements/memories/Memory.js +470 -0
  134. package/dist/elements/memories/MemoryManager.d.ts +86 -0
  135. package/dist/elements/memories/MemoryManager.d.ts.map +1 -0
  136. package/dist/elements/memories/MemoryManager.js +435 -0
  137. package/dist/elements/memories/constants.d.ts +42 -0
  138. package/dist/elements/memories/constants.d.ts.map +1 -0
  139. package/dist/elements/memories/constants.js +49 -0
  140. package/dist/elements/memories/index.d.ts +6 -0
  141. package/dist/elements/memories/index.d.ts.map +1 -0
  142. package/dist/elements/memories/index.js +6 -0
  143. package/dist/elements/skills/Skill.d.ts +109 -0
  144. package/dist/elements/skills/Skill.d.ts.map +1 -0
  145. package/dist/elements/skills/Skill.js +381 -0
  146. package/dist/elements/skills/index.d.ts +5 -0
  147. package/dist/elements/skills/index.d.ts.map +1 -0
  148. package/dist/elements/skills/index.js +5 -0
  149. package/dist/elements/templates/Template.d.ts +138 -0
  150. package/dist/elements/templates/Template.d.ts.map +1 -0
  151. package/dist/elements/templates/Template.js +673 -0
  152. package/dist/elements/templates/TemplateManager.d.ts +104 -0
  153. package/dist/elements/templates/TemplateManager.d.ts.map +1 -0
  154. package/dist/elements/templates/TemplateManager.js +501 -0
  155. package/dist/elements/templates/index.d.ts +6 -0
  156. package/dist/elements/templates/index.d.ts.map +1 -0
  157. package/dist/elements/templates/index.js +6 -0
  158. package/dist/errors/SecurityError.d.ts +29 -0
  159. package/dist/errors/SecurityError.d.ts.map +1 -0
  160. package/dist/errors/SecurityError.js +47 -0
  161. package/dist/errors/index.d.ts +2 -0
  162. package/dist/errors/index.d.ts.map +1 -0
  163. package/dist/errors/index.js +2 -0
  164. package/dist/index.barrel.d.ts +21 -0
  165. package/dist/index.barrel.d.ts.map +1 -0
  166. package/dist/index.barrel.js +31 -0
  167. package/dist/index.d.ts +223 -0
  168. package/dist/index.d.ts.map +1 -0
  169. package/dist/index.js +1606 -0
  170. package/dist/marketplace/GitHubClient.d.ts +22 -0
  171. package/dist/marketplace/GitHubClient.d.ts.map +1 -0
  172. package/dist/marketplace/GitHubClient.js +112 -0
  173. package/dist/marketplace/MarketplaceBrowser.d.ts +24 -0
  174. package/dist/marketplace/MarketplaceBrowser.d.ts.map +1 -0
  175. package/dist/marketplace/MarketplaceBrowser.js +115 -0
  176. package/dist/marketplace/MarketplaceSearch.d.ts +18 -0
  177. package/dist/marketplace/MarketplaceSearch.d.ts.map +1 -0
  178. package/dist/marketplace/MarketplaceSearch.js +48 -0
  179. package/dist/marketplace/PersonaDetails.d.ts +22 -0
  180. package/dist/marketplace/PersonaDetails.d.ts.map +1 -0
  181. package/dist/marketplace/PersonaDetails.js +71 -0
  182. package/dist/marketplace/PersonaInstaller.d.ts +25 -0
  183. package/dist/marketplace/PersonaInstaller.d.ts.map +1 -0
  184. package/dist/marketplace/PersonaInstaller.js +100 -0
  185. package/dist/marketplace/PersonaSubmitter.d.ts +19 -0
  186. package/dist/marketplace/PersonaSubmitter.d.ts.map +1 -0
  187. package/dist/marketplace/PersonaSubmitter.js +57 -0
  188. package/dist/marketplace/index.d.ts +10 -0
  189. package/dist/marketplace/index.d.ts.map +1 -0
  190. package/dist/marketplace/index.js +10 -0
  191. package/dist/persona/PersonaElement.d.ts +64 -0
  192. package/dist/persona/PersonaElement.d.ts.map +1 -0
  193. package/dist/persona/PersonaElement.js +223 -0
  194. package/dist/persona/PersonaElementManager.d.ts +97 -0
  195. package/dist/persona/PersonaElementManager.d.ts.map +1 -0
  196. package/dist/persona/PersonaElementManager.js +348 -0
  197. package/dist/persona/PersonaLoader.d.ts +34 -0
  198. package/dist/persona/PersonaLoader.d.ts.map +1 -0
  199. package/dist/persona/PersonaLoader.js +145 -0
  200. package/dist/persona/PersonaManager.d.ts +112 -0
  201. package/dist/persona/PersonaManager.d.ts.map +1 -0
  202. package/dist/persona/PersonaManager.js +341 -0
  203. package/dist/persona/PersonaValidator.d.ts +39 -0
  204. package/dist/persona/PersonaValidator.d.ts.map +1 -0
  205. package/dist/persona/PersonaValidator.js +161 -0
  206. package/dist/persona/export-import/PersonaExporter.d.ts +43 -0
  207. package/dist/persona/export-import/PersonaExporter.d.ts.map +1 -0
  208. package/dist/persona/export-import/PersonaExporter.js +99 -0
  209. package/dist/persona/export-import/PersonaImporter.d.ts +65 -0
  210. package/dist/persona/export-import/PersonaImporter.d.ts.map +1 -0
  211. package/dist/persona/export-import/PersonaImporter.js +315 -0
  212. package/dist/persona/export-import/PersonaSharer.d.ts +60 -0
  213. package/dist/persona/export-import/PersonaSharer.d.ts.map +1 -0
  214. package/dist/persona/export-import/PersonaSharer.js +502 -0
  215. package/dist/persona/export-import/index.d.ts +10 -0
  216. package/dist/persona/export-import/index.d.ts.map +1 -0
  217. package/dist/persona/export-import/index.js +7 -0
  218. package/dist/persona/index.d.ts +7 -0
  219. package/dist/persona/index.d.ts.map +1 -0
  220. package/dist/persona/index.js +7 -0
  221. package/dist/portfolio/MigrationManager.d.ts +44 -0
  222. package/dist/portfolio/MigrationManager.d.ts.map +1 -0
  223. package/dist/portfolio/MigrationManager.js +163 -0
  224. package/dist/portfolio/PortfolioManager.d.ts +54 -0
  225. package/dist/portfolio/PortfolioManager.d.ts.map +1 -0
  226. package/dist/portfolio/PortfolioManager.js +224 -0
  227. package/dist/portfolio/types.d.ts +18 -0
  228. package/dist/portfolio/types.d.ts.map +1 -0
  229. package/dist/portfolio/types.js +13 -0
  230. package/dist/security/InputValidator.d.ts +80 -0
  231. package/dist/security/InputValidator.d.ts.map +1 -0
  232. package/dist/security/InputValidator.js +448 -0
  233. package/dist/security/audit/SecurityAuditor.d.ts +44 -0
  234. package/dist/security/audit/SecurityAuditor.d.ts.map +1 -0
  235. package/dist/security/audit/SecurityAuditor.js +274 -0
  236. package/dist/security/audit/config/suppressions.d.ts +34 -0
  237. package/dist/security/audit/config/suppressions.d.ts.map +1 -0
  238. package/dist/security/audit/config/suppressions.js +575 -0
  239. package/dist/security/audit/index.d.ts +14 -0
  240. package/dist/security/audit/index.d.ts.map +1 -0
  241. package/dist/security/audit/index.js +15 -0
  242. package/dist/security/audit/reporters/ConsoleReporter.d.ts +46 -0
  243. package/dist/security/audit/reporters/ConsoleReporter.d.ts.map +1 -0
  244. package/dist/security/audit/reporters/ConsoleReporter.js +174 -0
  245. package/dist/security/audit/reporters/JsonReporter.d.ts +13 -0
  246. package/dist/security/audit/reporters/JsonReporter.d.ts.map +1 -0
  247. package/dist/security/audit/reporters/JsonReporter.js +25 -0
  248. package/dist/security/audit/reporters/MarkdownReporter.d.ts +13 -0
  249. package/dist/security/audit/reporters/MarkdownReporter.d.ts.map +1 -0
  250. package/dist/security/audit/reporters/MarkdownReporter.js +79 -0
  251. package/dist/security/audit/rules/SecurityRules.d.ts +20 -0
  252. package/dist/security/audit/rules/SecurityRules.d.ts.map +1 -0
  253. package/dist/security/audit/rules/SecurityRules.js +244 -0
  254. package/dist/security/audit/scanners/CodeScanner.d.ts +47 -0
  255. package/dist/security/audit/scanners/CodeScanner.d.ts.map +1 -0
  256. package/dist/security/audit/scanners/CodeScanner.js +174 -0
  257. package/dist/security/audit/scanners/ConfigurationScanner.d.ts +13 -0
  258. package/dist/security/audit/scanners/ConfigurationScanner.d.ts.map +1 -0
  259. package/dist/security/audit/scanners/ConfigurationScanner.js +22 -0
  260. package/dist/security/audit/scanners/DependencyScanner.d.ts +13 -0
  261. package/dist/security/audit/scanners/DependencyScanner.d.ts.map +1 -0
  262. package/dist/security/audit/scanners/DependencyScanner.js +22 -0
  263. package/dist/security/audit/types.d.ts +94 -0
  264. package/dist/security/audit/types.d.ts.map +1 -0
  265. package/dist/security/audit/types.js +6 -0
  266. package/dist/security/commandValidator.d.ts +7 -0
  267. package/dist/security/commandValidator.d.ts.map +1 -0
  268. package/dist/security/commandValidator.js +78 -0
  269. package/dist/security/constants.d.ts +24 -0
  270. package/dist/security/constants.d.ts.map +1 -0
  271. package/dist/security/constants.js +26 -0
  272. package/dist/security/contentValidator.d.ts +47 -0
  273. package/dist/security/contentValidator.d.ts.map +1 -0
  274. package/dist/security/contentValidator.js +301 -0
  275. package/dist/security/errorHandler.d.ts +42 -0
  276. package/dist/security/errorHandler.d.ts.map +1 -0
  277. package/dist/security/errorHandler.js +166 -0
  278. package/dist/security/errors.d.ts +14 -0
  279. package/dist/security/errors.d.ts.map +1 -0
  280. package/dist/security/errors.js +28 -0
  281. package/dist/security/fileLockManager.d.ts +70 -0
  282. package/dist/security/fileLockManager.d.ts.map +1 -0
  283. package/dist/security/fileLockManager.js +187 -0
  284. package/dist/security/index.d.ts +12 -0
  285. package/dist/security/index.d.ts.map +1 -0
  286. package/dist/security/index.js +14 -0
  287. package/dist/security/pathValidator.d.ts +9 -0
  288. package/dist/security/pathValidator.d.ts.map +1 -0
  289. package/dist/security/pathValidator.js +102 -0
  290. package/dist/security/regexValidator.d.ts +59 -0
  291. package/dist/security/regexValidator.d.ts.map +1 -0
  292. package/dist/security/regexValidator.js +214 -0
  293. package/dist/security/secureYamlParser.d.ts +46 -0
  294. package/dist/security/secureYamlParser.d.ts.map +1 -0
  295. package/dist/security/secureYamlParser.js +203 -0
  296. package/dist/security/securityMonitor.d.ts +58 -0
  297. package/dist/security/securityMonitor.d.ts.map +1 -0
  298. package/dist/security/securityMonitor.js +108 -0
  299. package/dist/security/tokenManager.d.ts +85 -0
  300. package/dist/security/tokenManager.d.ts.map +1 -0
  301. package/dist/security/tokenManager.js +286 -0
  302. package/dist/security/validators/unicodeValidator.d.ts +97 -0
  303. package/dist/security/validators/unicodeValidator.d.ts.map +1 -0
  304. package/dist/security/validators/unicodeValidator.js +312 -0
  305. package/dist/security/yamlValidator.d.ts +21 -0
  306. package/dist/security/yamlValidator.d.ts.map +1 -0
  307. package/dist/security/yamlValidator.js +164 -0
  308. package/dist/server/ServerSetup.d.ts +35 -0
  309. package/dist/server/ServerSetup.d.ts.map +1 -0
  310. package/dist/server/ServerSetup.js +116 -0
  311. package/dist/server/index.d.ts +7 -0
  312. package/dist/server/index.d.ts.map +1 -0
  313. package/dist/server/index.js +7 -0
  314. package/dist/server/startup.d.ts +31 -0
  315. package/dist/server/startup.d.ts.map +1 -0
  316. package/dist/server/startup.js +67 -0
  317. package/dist/server/tools/CollectionTools.d.ts +10 -0
  318. package/dist/server/tools/CollectionTools.d.ts.map +1 -0
  319. package/dist/server/tools/CollectionTools.js +96 -0
  320. package/dist/server/tools/ConfigTools.d.ts +10 -0
  321. package/dist/server/tools/ConfigTools.d.ts.map +1 -0
  322. package/dist/server/tools/ConfigTools.js +63 -0
  323. package/dist/server/tools/MarketplaceTools.d.ts +10 -0
  324. package/dist/server/tools/MarketplaceTools.d.ts.map +1 -0
  325. package/dist/server/tools/MarketplaceTools.js +96 -0
  326. package/dist/server/tools/PersonaTools.d.ts +10 -0
  327. package/dist/server/tools/PersonaTools.d.ts.map +1 -0
  328. package/dist/server/tools/PersonaTools.js +257 -0
  329. package/dist/server/tools/ToolRegistry.d.ts +37 -0
  330. package/dist/server/tools/ToolRegistry.d.ts.map +1 -0
  331. package/dist/server/tools/ToolRegistry.js +40 -0
  332. package/dist/server/tools/UpdateTools.d.ts +10 -0
  333. package/dist/server/tools/UpdateTools.d.ts.map +1 -0
  334. package/dist/server/tools/UpdateTools.js +64 -0
  335. package/dist/server/tools/UserTools.d.ts +10 -0
  336. package/dist/server/tools/UserTools.d.ts.map +1 -0
  337. package/dist/server/tools/UserTools.js +51 -0
  338. package/dist/server/tools/index.d.ts +10 -0
  339. package/dist/server/tools/index.d.ts.map +1 -0
  340. package/dist/server/tools/index.js +10 -0
  341. package/dist/server/types.d.ts +34 -0
  342. package/dist/server/types.d.ts.map +1 -0
  343. package/dist/server/types.js +5 -0
  344. package/dist/src/cache/APICache.d.ts +23 -0
  345. package/dist/src/cache/APICache.d.ts.map +1 -0
  346. package/dist/src/cache/APICache.js +42 -0
  347. package/dist/src/cache/index.d.ts +5 -0
  348. package/dist/src/cache/index.d.ts.map +1 -0
  349. package/dist/src/cache/index.js +5 -0
  350. package/dist/src/config/constants.d.ts +25 -0
  351. package/dist/src/config/constants.d.ts.map +1 -0
  352. package/dist/src/config/constants.js +30 -0
  353. package/dist/src/config/index.d.ts +6 -0
  354. package/dist/src/config/index.d.ts.map +1 -0
  355. package/dist/src/config/index.js +6 -0
  356. package/dist/src/config/indicator-config.d.ts +107 -0
  357. package/dist/src/config/indicator-config.d.ts.map +1 -0
  358. package/dist/src/config/indicator-config.js +158 -0
  359. package/dist/src/constants/defaultPersonas.d.ts +10 -0
  360. package/dist/src/constants/defaultPersonas.d.ts.map +1 -0
  361. package/dist/src/constants/defaultPersonas.js +18 -0
  362. package/dist/src/constants/limits.d.ts +10 -0
  363. package/dist/src/constants/limits.d.ts.map +1 -0
  364. package/dist/src/constants/limits.js +13 -0
  365. package/dist/src/errors/SecurityError.d.ts +29 -0
  366. package/dist/src/errors/SecurityError.d.ts.map +1 -0
  367. package/dist/src/errors/SecurityError.js +47 -0
  368. package/dist/src/errors/index.d.ts +2 -0
  369. package/dist/src/errors/index.d.ts.map +1 -0
  370. package/dist/src/errors/index.js +2 -0
  371. package/dist/src/index.barrel.d.ts +21 -0
  372. package/dist/src/index.barrel.d.ts.map +1 -0
  373. package/dist/src/index.barrel.js +31 -0
  374. package/dist/src/index.d.ts +220 -0
  375. package/dist/src/index.d.ts.map +1 -0
  376. package/dist/src/index.js +1559 -0
  377. package/dist/src/marketplace/GitHubClient.d.ts +22 -0
  378. package/dist/src/marketplace/GitHubClient.d.ts.map +1 -0
  379. package/dist/src/marketplace/GitHubClient.js +112 -0
  380. package/dist/src/marketplace/MarketplaceBrowser.d.ts +21 -0
  381. package/dist/src/marketplace/MarketplaceBrowser.d.ts.map +1 -0
  382. package/dist/src/marketplace/MarketplaceBrowser.js +45 -0
  383. package/dist/src/marketplace/MarketplaceSearch.d.ts +18 -0
  384. package/dist/src/marketplace/MarketplaceSearch.d.ts.map +1 -0
  385. package/dist/src/marketplace/MarketplaceSearch.js +36 -0
  386. package/dist/src/marketplace/PersonaDetails.d.ts +22 -0
  387. package/dist/src/marketplace/PersonaDetails.d.ts.map +1 -0
  388. package/dist/src/marketplace/PersonaDetails.js +71 -0
  389. package/dist/src/marketplace/PersonaInstaller.d.ts +25 -0
  390. package/dist/src/marketplace/PersonaInstaller.d.ts.map +1 -0
  391. package/dist/src/marketplace/PersonaInstaller.js +100 -0
  392. package/dist/src/marketplace/PersonaSubmitter.d.ts +19 -0
  393. package/dist/src/marketplace/PersonaSubmitter.d.ts.map +1 -0
  394. package/dist/src/marketplace/PersonaSubmitter.js +57 -0
  395. package/dist/src/marketplace/index.d.ts +10 -0
  396. package/dist/src/marketplace/index.d.ts.map +1 -0
  397. package/dist/src/marketplace/index.js +10 -0
  398. package/dist/src/persona/PersonaLoader.d.ts +33 -0
  399. package/dist/src/persona/PersonaLoader.d.ts.map +1 -0
  400. package/dist/src/persona/PersonaLoader.js +139 -0
  401. package/dist/src/persona/PersonaManager.d.ts +112 -0
  402. package/dist/src/persona/PersonaManager.d.ts.map +1 -0
  403. package/dist/src/persona/PersonaManager.js +341 -0
  404. package/dist/src/persona/PersonaValidator.d.ts +33 -0
  405. package/dist/src/persona/PersonaValidator.d.ts.map +1 -0
  406. package/dist/src/persona/PersonaValidator.js +157 -0
  407. package/dist/src/persona/export-import/PersonaExporter.d.ts +43 -0
  408. package/dist/src/persona/export-import/PersonaExporter.d.ts.map +1 -0
  409. package/dist/src/persona/export-import/PersonaExporter.js +99 -0
  410. package/dist/src/persona/export-import/PersonaImporter.d.ts +65 -0
  411. package/dist/src/persona/export-import/PersonaImporter.d.ts.map +1 -0
  412. package/dist/src/persona/export-import/PersonaImporter.js +313 -0
  413. package/dist/src/persona/export-import/PersonaSharer.d.ts +60 -0
  414. package/dist/src/persona/export-import/PersonaSharer.d.ts.map +1 -0
  415. package/dist/src/persona/export-import/PersonaSharer.js +363 -0
  416. package/dist/src/persona/export-import/index.d.ts +10 -0
  417. package/dist/src/persona/export-import/index.d.ts.map +1 -0
  418. package/dist/src/persona/export-import/index.js +7 -0
  419. package/dist/src/persona/index.d.ts +7 -0
  420. package/dist/src/persona/index.d.ts.map +1 -0
  421. package/dist/src/persona/index.js +7 -0
  422. package/dist/src/security/InputValidator.d.ts +69 -0
  423. package/dist/src/security/InputValidator.d.ts.map +1 -0
  424. package/dist/src/security/InputValidator.js +381 -0
  425. package/dist/src/security/commandValidator.d.ts +7 -0
  426. package/dist/src/security/commandValidator.d.ts.map +1 -0
  427. package/dist/src/security/commandValidator.js +77 -0
  428. package/dist/src/security/constants.d.ts +21 -0
  429. package/dist/src/security/constants.d.ts.map +1 -0
  430. package/dist/src/security/constants.js +23 -0
  431. package/dist/src/security/contentValidator.d.ts +47 -0
  432. package/dist/src/security/contentValidator.d.ts.map +1 -0
  433. package/dist/src/security/contentValidator.js +188 -0
  434. package/dist/src/security/fileLockManager.d.ts +70 -0
  435. package/dist/src/security/fileLockManager.d.ts.map +1 -0
  436. package/dist/src/security/fileLockManager.js +187 -0
  437. package/dist/src/security/index.d.ts +12 -0
  438. package/dist/src/security/index.d.ts.map +1 -0
  439. package/dist/src/security/index.js +14 -0
  440. package/dist/src/security/pathValidator.d.ts +9 -0
  441. package/dist/src/security/pathValidator.d.ts.map +1 -0
  442. package/dist/src/security/pathValidator.js +97 -0
  443. package/dist/src/security/secureYamlParser.d.ts +46 -0
  444. package/dist/src/security/secureYamlParser.d.ts.map +1 -0
  445. package/dist/src/security/secureYamlParser.js +203 -0
  446. package/dist/src/security/securityMonitor.d.ts +58 -0
  447. package/dist/src/security/securityMonitor.d.ts.map +1 -0
  448. package/dist/src/security/securityMonitor.js +108 -0
  449. package/dist/src/security/tokenManager.d.ts +59 -0
  450. package/dist/src/security/tokenManager.d.ts.map +1 -0
  451. package/dist/src/security/tokenManager.js +216 -0
  452. package/dist/src/security/yamlValidator.d.ts +20 -0
  453. package/dist/src/security/yamlValidator.d.ts.map +1 -0
  454. package/dist/src/security/yamlValidator.js +138 -0
  455. package/dist/src/server/ServerSetup.d.ts +31 -0
  456. package/dist/src/server/ServerSetup.d.ts.map +1 -0
  457. package/dist/src/server/ServerSetup.js +79 -0
  458. package/dist/src/server/index.d.ts +7 -0
  459. package/dist/src/server/index.d.ts.map +1 -0
  460. package/dist/src/server/index.js +7 -0
  461. package/dist/src/server/tools/ConfigTools.d.ts +10 -0
  462. package/dist/src/server/tools/ConfigTools.d.ts.map +1 -0
  463. package/dist/src/server/tools/ConfigTools.js +63 -0
  464. package/dist/src/server/tools/MarketplaceTools.d.ts +10 -0
  465. package/dist/src/server/tools/MarketplaceTools.d.ts.map +1 -0
  466. package/dist/src/server/tools/MarketplaceTools.js +92 -0
  467. package/dist/src/server/tools/PersonaTools.d.ts +10 -0
  468. package/dist/src/server/tools/PersonaTools.d.ts.map +1 -0
  469. package/dist/src/server/tools/PersonaTools.js +257 -0
  470. package/dist/src/server/tools/ToolRegistry.d.ts +37 -0
  471. package/dist/src/server/tools/ToolRegistry.d.ts.map +1 -0
  472. package/dist/src/server/tools/ToolRegistry.js +40 -0
  473. package/dist/src/server/tools/UpdateTools.d.ts +10 -0
  474. package/dist/src/server/tools/UpdateTools.d.ts.map +1 -0
  475. package/dist/src/server/tools/UpdateTools.js +64 -0
  476. package/dist/src/server/tools/UserTools.d.ts +10 -0
  477. package/dist/src/server/tools/UserTools.d.ts.map +1 -0
  478. package/dist/src/server/tools/UserTools.js +51 -0
  479. package/dist/src/server/tools/index.d.ts +10 -0
  480. package/dist/src/server/tools/index.d.ts.map +1 -0
  481. package/dist/src/server/tools/index.js +10 -0
  482. package/dist/src/server/types.d.ts +34 -0
  483. package/dist/src/server/types.d.ts.map +1 -0
  484. package/dist/src/server/types.js +5 -0
  485. package/dist/src/tools/debug.d.ts +20 -0
  486. package/dist/src/tools/debug.d.ts.map +1 -0
  487. package/dist/src/tools/debug.js +37 -0
  488. package/dist/src/types/cache.d.ts +8 -0
  489. package/dist/src/types/cache.d.ts.map +1 -0
  490. package/dist/src/types/cache.js +5 -0
  491. package/dist/src/types/index.d.ts +8 -0
  492. package/dist/src/types/index.d.ts.map +1 -0
  493. package/dist/src/types/index.js +8 -0
  494. package/dist/src/types/marketplace.d.ts +23 -0
  495. package/dist/src/types/marketplace.d.ts.map +1 -0
  496. package/dist/src/types/marketplace.js +5 -0
  497. package/dist/src/types/mcp.d.ts +161 -0
  498. package/dist/src/types/mcp.d.ts.map +1 -0
  499. package/dist/src/types/mcp.js +75 -0
  500. package/dist/src/types/persona.d.ts +30 -0
  501. package/dist/src/types/persona.d.ts.map +1 -0
  502. package/dist/src/types/persona.js +5 -0
  503. package/dist/src/update/BackupManager.d.ts +46 -0
  504. package/dist/src/update/BackupManager.d.ts.map +1 -0
  505. package/dist/src/update/BackupManager.js +261 -0
  506. package/dist/src/update/DependencyChecker.d.ts +41 -0
  507. package/dist/src/update/DependencyChecker.d.ts.map +1 -0
  508. package/dist/src/update/DependencyChecker.js +132 -0
  509. package/dist/src/update/RateLimiter.d.ts +80 -0
  510. package/dist/src/update/RateLimiter.d.ts.map +1 -0
  511. package/dist/src/update/RateLimiter.js +172 -0
  512. package/dist/src/update/SignatureVerifier.d.ts +71 -0
  513. package/dist/src/update/SignatureVerifier.d.ts.map +1 -0
  514. package/dist/src/update/SignatureVerifier.js +214 -0
  515. package/dist/src/update/UpdateChecker.d.ts +127 -0
  516. package/dist/src/update/UpdateChecker.d.ts.map +1 -0
  517. package/dist/src/update/UpdateChecker.js +460 -0
  518. package/dist/src/update/UpdateManager.d.ts +41 -0
  519. package/dist/src/update/UpdateManager.d.ts.map +1 -0
  520. package/dist/src/update/UpdateManager.js +260 -0
  521. package/dist/src/update/VersionManager.d.ts +31 -0
  522. package/dist/src/update/VersionManager.d.ts.map +1 -0
  523. package/dist/src/update/VersionManager.js +134 -0
  524. package/dist/src/update/index.d.ts +9 -0
  525. package/dist/src/update/index.d.ts.map +1 -0
  526. package/dist/src/update/index.js +9 -0
  527. package/dist/src/utils/filesystem.d.ts +32 -0
  528. package/dist/src/utils/filesystem.d.ts.map +1 -0
  529. package/dist/src/utils/filesystem.js +73 -0
  530. package/dist/src/utils/git.d.ts +32 -0
  531. package/dist/src/utils/git.d.ts.map +1 -0
  532. package/dist/src/utils/git.js +65 -0
  533. package/dist/src/utils/index.d.ts +7 -0
  534. package/dist/src/utils/index.d.ts.map +1 -0
  535. package/dist/src/utils/index.js +7 -0
  536. package/dist/src/utils/logger.d.ts +45 -0
  537. package/dist/src/utils/logger.d.ts.map +1 -0
  538. package/dist/src/utils/logger.js +91 -0
  539. package/dist/src/utils/version.d.ts +25 -0
  540. package/dist/src/utils/version.d.ts.map +1 -0
  541. package/dist/src/utils/version.js +97 -0
  542. package/dist/test/src/cache/APICache.d.ts +23 -0
  543. package/dist/test/src/cache/APICache.d.ts.map +1 -0
  544. package/dist/test/src/cache/APICache.js +42 -0
  545. package/dist/test/src/cache/index.d.ts +5 -0
  546. package/dist/test/src/cache/index.d.ts.map +1 -0
  547. package/dist/test/src/cache/index.js +5 -0
  548. package/dist/test/src/collection/CollectionBrowser.d.ts +24 -0
  549. package/dist/test/src/collection/CollectionBrowser.d.ts.map +1 -0
  550. package/dist/test/src/collection/CollectionBrowser.js +115 -0
  551. package/dist/test/src/collection/CollectionSearch.d.ts +18 -0
  552. package/dist/test/src/collection/CollectionSearch.d.ts.map +1 -0
  553. package/dist/test/src/collection/CollectionSearch.js +48 -0
  554. package/dist/test/src/collection/GitHubClient.d.ts +22 -0
  555. package/dist/test/src/collection/GitHubClient.d.ts.map +1 -0
  556. package/dist/test/src/collection/GitHubClient.js +114 -0
  557. package/dist/test/src/collection/PersonaDetails.d.ts +22 -0
  558. package/dist/test/src/collection/PersonaDetails.d.ts.map +1 -0
  559. package/dist/test/src/collection/PersonaDetails.js +71 -0
  560. package/dist/test/src/collection/PersonaInstaller.d.ts +26 -0
  561. package/dist/test/src/collection/PersonaInstaller.d.ts.map +1 -0
  562. package/dist/test/src/collection/PersonaInstaller.js +103 -0
  563. package/dist/test/src/collection/PersonaSubmitter.d.ts +19 -0
  564. package/dist/test/src/collection/PersonaSubmitter.d.ts.map +1 -0
  565. package/dist/test/src/collection/PersonaSubmitter.js +57 -0
  566. package/dist/test/src/collection/index.d.ts +10 -0
  567. package/dist/test/src/collection/index.d.ts.map +1 -0
  568. package/dist/test/src/collection/index.js +10 -0
  569. package/dist/test/src/config/constants.d.ts +25 -0
  570. package/dist/test/src/config/constants.d.ts.map +1 -0
  571. package/dist/test/src/config/constants.js +30 -0
  572. package/dist/test/src/config/index.d.ts +6 -0
  573. package/dist/test/src/config/index.d.ts.map +1 -0
  574. package/dist/test/src/config/index.js +6 -0
  575. package/dist/test/src/config/indicator-config.d.ts +107 -0
  576. package/dist/test/src/config/indicator-config.d.ts.map +1 -0
  577. package/dist/test/src/config/indicator-config.js +158 -0
  578. package/dist/test/src/constants/defaultPersonas.d.ts +10 -0
  579. package/dist/test/src/constants/defaultPersonas.d.ts.map +1 -0
  580. package/dist/test/src/constants/defaultPersonas.js +18 -0
  581. package/dist/test/src/constants/limits.d.ts +10 -0
  582. package/dist/test/src/constants/limits.d.ts.map +1 -0
  583. package/dist/test/src/constants/limits.js +13 -0
  584. package/dist/test/src/elements/BaseElement.d.ts +81 -0
  585. package/dist/test/src/elements/BaseElement.d.ts.map +1 -0
  586. package/dist/test/src/elements/BaseElement.js +381 -0
  587. package/dist/test/src/elements/FeedbackProcessor.d.ts +57 -0
  588. package/dist/test/src/elements/FeedbackProcessor.d.ts.map +1 -0
  589. package/dist/test/src/elements/FeedbackProcessor.js +418 -0
  590. package/dist/test/src/elements/agents/Agent.d.ts +145 -0
  591. package/dist/test/src/elements/agents/Agent.d.ts.map +1 -0
  592. package/dist/test/src/elements/agents/Agent.js +848 -0
  593. package/dist/test/src/elements/agents/AgentManager.d.ts +125 -0
  594. package/dist/test/src/elements/agents/AgentManager.d.ts.map +1 -0
  595. package/dist/test/src/elements/agents/AgentManager.js +608 -0
  596. package/dist/test/src/elements/agents/constants.d.ts +42 -0
  597. package/dist/test/src/elements/agents/constants.d.ts.map +1 -0
  598. package/dist/test/src/elements/agents/constants.js +45 -0
  599. package/dist/test/src/elements/agents/goalTemplates.d.ts +44 -0
  600. package/dist/test/src/elements/agents/goalTemplates.d.ts.map +1 -0
  601. package/dist/test/src/elements/agents/goalTemplates.js +297 -0
  602. package/dist/test/src/elements/agents/index.d.ts +8 -0
  603. package/dist/test/src/elements/agents/index.d.ts.map +1 -0
  604. package/dist/test/src/elements/agents/index.js +8 -0
  605. package/dist/test/src/elements/agents/ruleEngineConfig.d.ts +76 -0
  606. package/dist/test/src/elements/agents/ruleEngineConfig.d.ts.map +1 -0
  607. package/dist/test/src/elements/agents/ruleEngineConfig.js +143 -0
  608. package/dist/test/src/elements/agents/types.d.ts +97 -0
  609. package/dist/test/src/elements/agents/types.d.ts.map +1 -0
  610. package/dist/test/src/elements/agents/types.js +5 -0
  611. package/dist/test/src/elements/index.d.ts +6 -0
  612. package/dist/test/src/elements/index.d.ts.map +1 -0
  613. package/dist/test/src/elements/index.js +6 -0
  614. package/dist/test/src/elements/memories/Memory.d.ts +110 -0
  615. package/dist/test/src/elements/memories/Memory.d.ts.map +1 -0
  616. package/dist/test/src/elements/memories/Memory.js +470 -0
  617. package/dist/test/src/elements/memories/MemoryManager.d.ts +86 -0
  618. package/dist/test/src/elements/memories/MemoryManager.d.ts.map +1 -0
  619. package/dist/test/src/elements/memories/MemoryManager.js +435 -0
  620. package/dist/test/src/elements/memories/constants.d.ts +42 -0
  621. package/dist/test/src/elements/memories/constants.d.ts.map +1 -0
  622. package/dist/test/src/elements/memories/constants.js +49 -0
  623. package/dist/test/src/elements/memories/index.d.ts +6 -0
  624. package/dist/test/src/elements/memories/index.d.ts.map +1 -0
  625. package/dist/test/src/elements/memories/index.js +6 -0
  626. package/dist/test/src/elements/skills/Skill.d.ts +109 -0
  627. package/dist/test/src/elements/skills/Skill.d.ts.map +1 -0
  628. package/dist/test/src/elements/skills/Skill.js +381 -0
  629. package/dist/test/src/elements/templates/Template.d.ts +138 -0
  630. package/dist/test/src/elements/templates/Template.d.ts.map +1 -0
  631. package/dist/test/src/elements/templates/Template.js +673 -0
  632. package/dist/test/src/elements/templates/TemplateManager.d.ts +104 -0
  633. package/dist/test/src/elements/templates/TemplateManager.d.ts.map +1 -0
  634. package/dist/test/src/elements/templates/TemplateManager.js +496 -0
  635. package/dist/test/src/elements/templates/index.d.ts +6 -0
  636. package/dist/test/src/elements/templates/index.d.ts.map +1 -0
  637. package/dist/test/src/elements/templates/index.js +6 -0
  638. package/dist/test/src/errors/SecurityError.d.ts +29 -0
  639. package/dist/test/src/errors/SecurityError.d.ts.map +1 -0
  640. package/dist/test/src/errors/SecurityError.js +47 -0
  641. package/dist/test/src/errors/index.d.ts +2 -0
  642. package/dist/test/src/errors/index.d.ts.map +1 -0
  643. package/dist/test/src/errors/index.js +2 -0
  644. package/dist/test/src/index.barrel.d.ts +21 -0
  645. package/dist/test/src/index.barrel.d.ts.map +1 -0
  646. package/dist/test/src/index.barrel.js +31 -0
  647. package/dist/test/src/index.d.ts +223 -0
  648. package/dist/test/src/index.d.ts.map +1 -0
  649. package/dist/test/src/index.js +1594 -0
  650. package/dist/test/src/marketplace/GitHubClient.d.ts +22 -0
  651. package/dist/test/src/marketplace/GitHubClient.d.ts.map +1 -0
  652. package/dist/test/src/marketplace/GitHubClient.js +112 -0
  653. package/dist/test/src/marketplace/MarketplaceBrowser.d.ts +21 -0
  654. package/dist/test/src/marketplace/MarketplaceBrowser.d.ts.map +1 -0
  655. package/dist/test/src/marketplace/MarketplaceBrowser.js +45 -0
  656. package/dist/test/src/marketplace/MarketplaceSearch.d.ts +18 -0
  657. package/dist/test/src/marketplace/MarketplaceSearch.d.ts.map +1 -0
  658. package/dist/test/src/marketplace/MarketplaceSearch.js +36 -0
  659. package/dist/test/src/marketplace/PersonaDetails.d.ts +22 -0
  660. package/dist/test/src/marketplace/PersonaDetails.d.ts.map +1 -0
  661. package/dist/test/src/marketplace/PersonaDetails.js +71 -0
  662. package/dist/test/src/marketplace/PersonaInstaller.d.ts +25 -0
  663. package/dist/test/src/marketplace/PersonaInstaller.d.ts.map +1 -0
  664. package/dist/test/src/marketplace/PersonaInstaller.js +100 -0
  665. package/dist/test/src/marketplace/PersonaSubmitter.d.ts +19 -0
  666. package/dist/test/src/marketplace/PersonaSubmitter.d.ts.map +1 -0
  667. package/dist/test/src/marketplace/PersonaSubmitter.js +57 -0
  668. package/dist/test/src/marketplace/index.d.ts +10 -0
  669. package/dist/test/src/marketplace/index.d.ts.map +1 -0
  670. package/dist/test/src/marketplace/index.js +10 -0
  671. package/dist/test/src/persona/PersonaElement.d.ts +64 -0
  672. package/dist/test/src/persona/PersonaElement.d.ts.map +1 -0
  673. package/dist/test/src/persona/PersonaElement.js +223 -0
  674. package/dist/test/src/persona/PersonaElementManager.d.ts +97 -0
  675. package/dist/test/src/persona/PersonaElementManager.d.ts.map +1 -0
  676. package/dist/test/src/persona/PersonaElementManager.js +342 -0
  677. package/dist/test/src/persona/PersonaLoader.d.ts +34 -0
  678. package/dist/test/src/persona/PersonaLoader.d.ts.map +1 -0
  679. package/dist/test/src/persona/PersonaLoader.js +145 -0
  680. package/dist/test/src/persona/PersonaManager.d.ts +112 -0
  681. package/dist/test/src/persona/PersonaManager.d.ts.map +1 -0
  682. package/dist/test/src/persona/PersonaManager.js +341 -0
  683. package/dist/test/src/persona/PersonaValidator.d.ts +33 -0
  684. package/dist/test/src/persona/PersonaValidator.d.ts.map +1 -0
  685. package/dist/test/src/persona/PersonaValidator.js +157 -0
  686. package/dist/test/src/persona/export-import/PersonaExporter.d.ts +43 -0
  687. package/dist/test/src/persona/export-import/PersonaExporter.d.ts.map +1 -0
  688. package/dist/test/src/persona/export-import/PersonaExporter.js +99 -0
  689. package/dist/test/src/persona/export-import/PersonaImporter.d.ts +65 -0
  690. package/dist/test/src/persona/export-import/PersonaImporter.d.ts.map +1 -0
  691. package/dist/test/src/persona/export-import/PersonaImporter.js +315 -0
  692. package/dist/test/src/persona/export-import/PersonaSharer.d.ts +60 -0
  693. package/dist/test/src/persona/export-import/PersonaSharer.d.ts.map +1 -0
  694. package/dist/test/src/persona/export-import/PersonaSharer.js +502 -0
  695. package/dist/test/src/persona/export-import/index.d.ts +10 -0
  696. package/dist/test/src/persona/export-import/index.d.ts.map +1 -0
  697. package/dist/test/src/persona/export-import/index.js +7 -0
  698. package/dist/test/src/persona/index.d.ts +7 -0
  699. package/dist/test/src/persona/index.d.ts.map +1 -0
  700. package/dist/test/src/persona/index.js +7 -0
  701. package/dist/test/src/portfolio/MigrationManager.d.ts +44 -0
  702. package/dist/test/src/portfolio/MigrationManager.d.ts.map +1 -0
  703. package/dist/test/src/portfolio/MigrationManager.js +163 -0
  704. package/dist/test/src/portfolio/PortfolioManager.d.ts +54 -0
  705. package/dist/test/src/portfolio/PortfolioManager.d.ts.map +1 -0
  706. package/dist/test/src/portfolio/PortfolioManager.js +224 -0
  707. package/dist/test/src/portfolio/types.d.ts +18 -0
  708. package/dist/test/src/portfolio/types.d.ts.map +1 -0
  709. package/dist/test/src/portfolio/types.js +13 -0
  710. package/dist/test/src/security/InputValidator.d.ts +80 -0
  711. package/dist/test/src/security/InputValidator.d.ts.map +1 -0
  712. package/dist/test/src/security/InputValidator.js +436 -0
  713. package/dist/test/src/security/audit/SecurityAuditor.d.ts +44 -0
  714. package/dist/test/src/security/audit/SecurityAuditor.d.ts.map +1 -0
  715. package/dist/test/src/security/audit/SecurityAuditor.js +274 -0
  716. package/dist/test/src/security/audit/config/suppressions.d.ts +34 -0
  717. package/dist/test/src/security/audit/config/suppressions.d.ts.map +1 -0
  718. package/dist/test/src/security/audit/config/suppressions.js +575 -0
  719. package/dist/test/src/security/audit/index.d.ts +14 -0
  720. package/dist/test/src/security/audit/index.d.ts.map +1 -0
  721. package/dist/test/src/security/audit/index.js +15 -0
  722. package/dist/test/src/security/audit/reporters/ConsoleReporter.d.ts +46 -0
  723. package/dist/test/src/security/audit/reporters/ConsoleReporter.d.ts.map +1 -0
  724. package/dist/test/src/security/audit/reporters/ConsoleReporter.js +174 -0
  725. package/dist/test/src/security/audit/reporters/JsonReporter.d.ts +13 -0
  726. package/dist/test/src/security/audit/reporters/JsonReporter.d.ts.map +1 -0
  727. package/dist/test/src/security/audit/reporters/JsonReporter.js +25 -0
  728. package/dist/test/src/security/audit/reporters/MarkdownReporter.d.ts +13 -0
  729. package/dist/test/src/security/audit/reporters/MarkdownReporter.d.ts.map +1 -0
  730. package/dist/test/src/security/audit/reporters/MarkdownReporter.js +79 -0
  731. package/dist/test/src/security/audit/rules/SecurityRules.d.ts +20 -0
  732. package/dist/test/src/security/audit/rules/SecurityRules.d.ts.map +1 -0
  733. package/dist/test/src/security/audit/rules/SecurityRules.js +244 -0
  734. package/dist/test/src/security/audit/scanners/CodeScanner.d.ts +47 -0
  735. package/dist/test/src/security/audit/scanners/CodeScanner.d.ts.map +1 -0
  736. package/dist/test/src/security/audit/scanners/CodeScanner.js +174 -0
  737. package/dist/test/src/security/audit/scanners/ConfigurationScanner.d.ts +13 -0
  738. package/dist/test/src/security/audit/scanners/ConfigurationScanner.d.ts.map +1 -0
  739. package/dist/test/src/security/audit/scanners/ConfigurationScanner.js +22 -0
  740. package/dist/test/src/security/audit/scanners/DependencyScanner.d.ts +13 -0
  741. package/dist/test/src/security/audit/scanners/DependencyScanner.d.ts.map +1 -0
  742. package/dist/test/src/security/audit/scanners/DependencyScanner.js +22 -0
  743. package/dist/test/src/security/audit/types.d.ts +94 -0
  744. package/dist/test/src/security/audit/types.d.ts.map +1 -0
  745. package/dist/test/src/security/audit/types.js +6 -0
  746. package/dist/test/src/security/commandValidator.d.ts +7 -0
  747. package/dist/test/src/security/commandValidator.d.ts.map +1 -0
  748. package/dist/test/src/security/commandValidator.js +78 -0
  749. package/dist/test/src/security/constants.d.ts +24 -0
  750. package/dist/test/src/security/constants.d.ts.map +1 -0
  751. package/dist/test/src/security/constants.js +26 -0
  752. package/dist/test/src/security/contentValidator.d.ts +47 -0
  753. package/dist/test/src/security/contentValidator.d.ts.map +1 -0
  754. package/dist/test/src/security/contentValidator.js +301 -0
  755. package/dist/test/src/security/errors.d.ts +14 -0
  756. package/dist/test/src/security/errors.d.ts.map +1 -0
  757. package/dist/test/src/security/errors.js +28 -0
  758. package/dist/test/src/security/fileLockManager.d.ts +70 -0
  759. package/dist/test/src/security/fileLockManager.d.ts.map +1 -0
  760. package/dist/test/src/security/fileLockManager.js +187 -0
  761. package/dist/test/src/security/index.d.ts +12 -0
  762. package/dist/test/src/security/index.d.ts.map +1 -0
  763. package/dist/test/src/security/index.js +14 -0
  764. package/dist/test/src/security/pathValidator.d.ts +9 -0
  765. package/dist/test/src/security/pathValidator.d.ts.map +1 -0
  766. package/dist/test/src/security/pathValidator.js +98 -0
  767. package/dist/test/src/security/regexValidator.d.ts +59 -0
  768. package/dist/test/src/security/regexValidator.d.ts.map +1 -0
  769. package/dist/test/src/security/regexValidator.js +214 -0
  770. package/dist/test/src/security/secureYamlParser.d.ts +46 -0
  771. package/dist/test/src/security/secureYamlParser.d.ts.map +1 -0
  772. package/dist/test/src/security/secureYamlParser.js +203 -0
  773. package/dist/test/src/security/securityMonitor.d.ts +58 -0
  774. package/dist/test/src/security/securityMonitor.d.ts.map +1 -0
  775. package/dist/test/src/security/securityMonitor.js +108 -0
  776. package/dist/test/src/security/tokenManager.d.ts +85 -0
  777. package/dist/test/src/security/tokenManager.d.ts.map +1 -0
  778. package/dist/test/src/security/tokenManager.js +286 -0
  779. package/dist/test/src/security/validators/unicodeValidator.d.ts +97 -0
  780. package/dist/test/src/security/validators/unicodeValidator.d.ts.map +1 -0
  781. package/dist/test/src/security/validators/unicodeValidator.js +312 -0
  782. package/dist/test/src/security/yamlValidator.d.ts +21 -0
  783. package/dist/test/src/security/yamlValidator.d.ts.map +1 -0
  784. package/dist/test/src/security/yamlValidator.js +164 -0
  785. package/dist/test/src/server/ServerSetup.d.ts +35 -0
  786. package/dist/test/src/server/ServerSetup.d.ts.map +1 -0
  787. package/dist/test/src/server/ServerSetup.js +116 -0
  788. package/dist/test/src/server/index.d.ts +7 -0
  789. package/dist/test/src/server/index.d.ts.map +1 -0
  790. package/dist/test/src/server/index.js +7 -0
  791. package/dist/test/src/server/startup.d.ts +31 -0
  792. package/dist/test/src/server/startup.d.ts.map +1 -0
  793. package/dist/test/src/server/startup.js +67 -0
  794. package/dist/test/src/server/tools/CollectionTools.d.ts +10 -0
  795. package/dist/test/src/server/tools/CollectionTools.d.ts.map +1 -0
  796. package/dist/test/src/server/tools/CollectionTools.js +96 -0
  797. package/dist/test/src/server/tools/ConfigTools.d.ts +10 -0
  798. package/dist/test/src/server/tools/ConfigTools.d.ts.map +1 -0
  799. package/dist/test/src/server/tools/ConfigTools.js +63 -0
  800. package/dist/test/src/server/tools/MarketplaceTools.d.ts +10 -0
  801. package/dist/test/src/server/tools/MarketplaceTools.d.ts.map +1 -0
  802. package/dist/test/src/server/tools/MarketplaceTools.js +92 -0
  803. package/dist/test/src/server/tools/PersonaTools.d.ts +10 -0
  804. package/dist/test/src/server/tools/PersonaTools.d.ts.map +1 -0
  805. package/dist/test/src/server/tools/PersonaTools.js +257 -0
  806. package/dist/test/src/server/tools/ToolRegistry.d.ts +37 -0
  807. package/dist/test/src/server/tools/ToolRegistry.d.ts.map +1 -0
  808. package/dist/test/src/server/tools/ToolRegistry.js +40 -0
  809. package/dist/test/src/server/tools/UpdateTools.d.ts +10 -0
  810. package/dist/test/src/server/tools/UpdateTools.d.ts.map +1 -0
  811. package/dist/test/src/server/tools/UpdateTools.js +64 -0
  812. package/dist/test/src/server/tools/UserTools.d.ts +10 -0
  813. package/dist/test/src/server/tools/UserTools.d.ts.map +1 -0
  814. package/dist/test/src/server/tools/UserTools.js +51 -0
  815. package/dist/test/src/server/tools/index.d.ts +10 -0
  816. package/dist/test/src/server/tools/index.d.ts.map +1 -0
  817. package/dist/test/src/server/tools/index.js +10 -0
  818. package/dist/test/src/server/types.d.ts +34 -0
  819. package/dist/test/src/server/types.d.ts.map +1 -0
  820. package/dist/test/src/server/types.js +5 -0
  821. package/dist/test/src/tools/debug.d.ts +20 -0
  822. package/dist/test/src/tools/debug.d.ts.map +1 -0
  823. package/dist/test/src/tools/debug.js +37 -0
  824. package/dist/test/src/types/cache.d.ts +8 -0
  825. package/dist/test/src/types/cache.d.ts.map +1 -0
  826. package/dist/test/src/types/cache.js +5 -0
  827. package/dist/test/src/types/collection.d.ts +23 -0
  828. package/dist/test/src/types/collection.d.ts.map +1 -0
  829. package/dist/test/src/types/collection.js +5 -0
  830. package/dist/test/src/types/elements/IElement.d.ts +123 -0
  831. package/dist/test/src/types/elements/IElement.d.ts.map +1 -0
  832. package/dist/test/src/types/elements/IElement.js +30 -0
  833. package/dist/test/src/types/elements/IElementManager.d.ts +65 -0
  834. package/dist/test/src/types/elements/IElementManager.d.ts.map +1 -0
  835. package/dist/test/src/types/elements/IElementManager.js +6 -0
  836. package/dist/test/src/types/elements/IRatingManager.d.ts +109 -0
  837. package/dist/test/src/types/elements/IRatingManager.d.ts.map +1 -0
  838. package/dist/test/src/types/elements/IRatingManager.js +6 -0
  839. package/dist/test/src/types/elements/IReferenceResolver.d.ts +52 -0
  840. package/dist/test/src/types/elements/IReferenceResolver.d.ts.map +1 -0
  841. package/dist/test/src/types/elements/IReferenceResolver.js +6 -0
  842. package/dist/test/src/types/elements/RatingBreakdowns.d.ts +49 -0
  843. package/dist/test/src/types/elements/RatingBreakdowns.d.ts.map +1 -0
  844. package/dist/test/src/types/elements/RatingBreakdowns.js +6 -0
  845. package/dist/test/src/types/elements/index.d.ts +9 -0
  846. package/dist/test/src/types/elements/index.d.ts.map +1 -0
  847. package/dist/test/src/types/elements/index.js +11 -0
  848. package/dist/test/src/types/index.d.ts +9 -0
  849. package/dist/test/src/types/index.d.ts.map +1 -0
  850. package/dist/test/src/types/index.js +9 -0
  851. package/dist/test/src/types/marketplace.d.ts +23 -0
  852. package/dist/test/src/types/marketplace.d.ts.map +1 -0
  853. package/dist/test/src/types/marketplace.js +5 -0
  854. package/dist/test/src/types/mcp.d.ts +84 -0
  855. package/dist/test/src/types/mcp.d.ts.map +1 -0
  856. package/dist/test/src/types/mcp.js +80 -0
  857. package/dist/test/src/types/persona.d.ts +30 -0
  858. package/dist/test/src/types/persona.d.ts.map +1 -0
  859. package/dist/test/src/types/persona.js +5 -0
  860. package/dist/test/src/update/BackupManager.d.ts +46 -0
  861. package/dist/test/src/update/BackupManager.d.ts.map +1 -0
  862. package/dist/test/src/update/BackupManager.js +261 -0
  863. package/dist/test/src/update/DependencyChecker.d.ts +41 -0
  864. package/dist/test/src/update/DependencyChecker.d.ts.map +1 -0
  865. package/dist/test/src/update/DependencyChecker.js +132 -0
  866. package/dist/test/src/update/RateLimiter.d.ts +80 -0
  867. package/dist/test/src/update/RateLimiter.d.ts.map +1 -0
  868. package/dist/test/src/update/RateLimiter.js +172 -0
  869. package/dist/test/src/update/SignatureVerifier.d.ts +71 -0
  870. package/dist/test/src/update/SignatureVerifier.d.ts.map +1 -0
  871. package/dist/test/src/update/SignatureVerifier.js +214 -0
  872. package/dist/test/src/update/UpdateChecker.d.ts +127 -0
  873. package/dist/test/src/update/UpdateChecker.d.ts.map +1 -0
  874. package/dist/test/src/update/UpdateChecker.js +469 -0
  875. package/dist/test/src/update/UpdateManager.d.ts +41 -0
  876. package/dist/test/src/update/UpdateManager.d.ts.map +1 -0
  877. package/dist/test/src/update/UpdateManager.js +260 -0
  878. package/dist/test/src/update/VersionManager.d.ts +31 -0
  879. package/dist/test/src/update/VersionManager.d.ts.map +1 -0
  880. package/dist/test/src/update/VersionManager.js +134 -0
  881. package/dist/test/src/update/index.d.ts +9 -0
  882. package/dist/test/src/update/index.d.ts.map +1 -0
  883. package/dist/test/src/update/index.js +9 -0
  884. package/dist/test/src/utils/filesystem.d.ts +29 -0
  885. package/dist/test/src/utils/filesystem.d.ts.map +1 -0
  886. package/dist/test/src/utils/filesystem.js +94 -0
  887. package/dist/test/src/utils/git.d.ts +32 -0
  888. package/dist/test/src/utils/git.d.ts.map +1 -0
  889. package/dist/test/src/utils/git.js +65 -0
  890. package/dist/test/src/utils/index.d.ts +7 -0
  891. package/dist/test/src/utils/index.d.ts.map +1 -0
  892. package/dist/test/src/utils/index.js +7 -0
  893. package/dist/test/src/utils/logger.d.ts +45 -0
  894. package/dist/test/src/utils/logger.d.ts.map +1 -0
  895. package/dist/test/src/utils/logger.js +91 -0
  896. package/dist/test/src/utils/version.d.ts +25 -0
  897. package/dist/test/src/utils/version.d.ts.map +1 -0
  898. package/dist/test/src/utils/version.js +97 -0
  899. package/dist/test/test/__tests__/integration/helpers/file-utils.d.ts +33 -0
  900. package/dist/test/test/__tests__/integration/helpers/file-utils.d.ts.map +1 -0
  901. package/dist/test/test/__tests__/integration/helpers/file-utils.js +83 -0
  902. package/dist/test/test/__tests__/integration/helpers/test-fixtures.d.ts +26 -0
  903. package/dist/test/test/__tests__/integration/helpers/test-fixtures.d.ts.map +1 -0
  904. package/dist/test/test/__tests__/integration/helpers/test-fixtures.js +95 -0
  905. package/dist/test/test/__tests__/integration/helpers/test-server.d.ts +26 -0
  906. package/dist/test/test/__tests__/integration/helpers/test-server.d.ts.map +1 -0
  907. package/dist/test/test/__tests__/integration/helpers/test-server.js +41 -0
  908. package/dist/test/test/__tests__/integration/setup.d.ts +8 -0
  909. package/dist/test/test/__tests__/integration/setup.d.ts.map +1 -0
  910. package/dist/test/test/__tests__/integration/setup.js +31 -0
  911. package/dist/test/test/__tests__/integration/teardown.d.ts +5 -0
  912. package/dist/test/test/__tests__/integration/teardown.d.ts.map +1 -0
  913. package/dist/test/test/__tests__/integration/teardown.js +23 -0
  914. package/dist/test/test/__tests__/security/framework/RapidSecurityTesting.d.ts +34 -0
  915. package/dist/test/test/__tests__/security/framework/RapidSecurityTesting.d.ts.map +1 -0
  916. package/dist/test/test/__tests__/security/framework/RapidSecurityTesting.js +224 -0
  917. package/dist/test/test/__tests__/security/framework/SecurityTestFramework.d.ts +89 -0
  918. package/dist/test/test/__tests__/security/framework/SecurityTestFramework.d.ts.map +1 -0
  919. package/dist/test/test/__tests__/security/framework/SecurityTestFramework.js +543 -0
  920. package/dist/test/test/__tests__/security/index.d.ts +46 -0
  921. package/dist/test/test/__tests__/security/index.d.ts.map +1 -0
  922. package/dist/test/test/__tests__/security/index.js +98 -0
  923. package/dist/test/test/__tests__/security/setup.d.ts +3 -0
  924. package/dist/test/test/__tests__/security/setup.d.ts.map +1 -0
  925. package/dist/test/test/__tests__/security/setup.js +23 -0
  926. package/dist/tools/debug.d.ts +20 -0
  927. package/dist/tools/debug.d.ts.map +1 -0
  928. package/dist/tools/debug.js +37 -0
  929. package/dist/types/cache.d.ts +8 -0
  930. package/dist/types/cache.d.ts.map +1 -0
  931. package/dist/types/cache.js +5 -0
  932. package/dist/types/collection.d.ts +23 -0
  933. package/dist/types/collection.d.ts.map +1 -0
  934. package/dist/types/collection.js +5 -0
  935. package/dist/types/elements/IElement.d.ts +123 -0
  936. package/dist/types/elements/IElement.d.ts.map +1 -0
  937. package/dist/types/elements/IElement.js +30 -0
  938. package/dist/types/elements/IElementManager.d.ts +65 -0
  939. package/dist/types/elements/IElementManager.d.ts.map +1 -0
  940. package/dist/types/elements/IElementManager.js +6 -0
  941. package/dist/types/elements/IRatingManager.d.ts +109 -0
  942. package/dist/types/elements/IRatingManager.d.ts.map +1 -0
  943. package/dist/types/elements/IRatingManager.js +6 -0
  944. package/dist/types/elements/IReferenceResolver.d.ts +52 -0
  945. package/dist/types/elements/IReferenceResolver.d.ts.map +1 -0
  946. package/dist/types/elements/IReferenceResolver.js +6 -0
  947. package/dist/types/elements/RatingBreakdowns.d.ts +49 -0
  948. package/dist/types/elements/RatingBreakdowns.d.ts.map +1 -0
  949. package/dist/types/elements/RatingBreakdowns.js +6 -0
  950. package/dist/types/elements/index.d.ts +9 -0
  951. package/dist/types/elements/index.d.ts.map +1 -0
  952. package/dist/types/elements/index.js +11 -0
  953. package/dist/types/index.d.ts +9 -0
  954. package/dist/types/index.d.ts.map +1 -0
  955. package/dist/types/index.js +9 -0
  956. package/dist/types/marketplace.d.ts +23 -0
  957. package/dist/types/marketplace.d.ts.map +1 -0
  958. package/dist/types/marketplace.js +5 -0
  959. package/dist/types/mcp.d.ts +84 -0
  960. package/dist/types/mcp.d.ts.map +1 -0
  961. package/dist/types/mcp.js +80 -0
  962. package/dist/types/persona.d.ts +30 -0
  963. package/dist/types/persona.d.ts.map +1 -0
  964. package/dist/types/persona.js +5 -0
  965. package/dist/update/BackupManager.d.ts +46 -0
  966. package/dist/update/BackupManager.d.ts.map +1 -0
  967. package/dist/update/BackupManager.js +261 -0
  968. package/dist/update/DependencyChecker.d.ts +41 -0
  969. package/dist/update/DependencyChecker.d.ts.map +1 -0
  970. package/dist/update/DependencyChecker.js +132 -0
  971. package/dist/update/RateLimiter.d.ts +80 -0
  972. package/dist/update/RateLimiter.d.ts.map +1 -0
  973. package/dist/update/RateLimiter.js +172 -0
  974. package/dist/update/SignatureVerifier.d.ts +71 -0
  975. package/dist/update/SignatureVerifier.d.ts.map +1 -0
  976. package/dist/update/SignatureVerifier.js +214 -0
  977. package/dist/update/UpdateChecker.d.ts +127 -0
  978. package/dist/update/UpdateChecker.d.ts.map +1 -0
  979. package/dist/update/UpdateChecker.js +469 -0
  980. package/dist/update/UpdateManager.d.ts +41 -0
  981. package/dist/update/UpdateManager.d.ts.map +1 -0
  982. package/dist/update/UpdateManager.js +260 -0
  983. package/dist/update/VersionManager.d.ts +31 -0
  984. package/dist/update/VersionManager.d.ts.map +1 -0
  985. package/dist/update/VersionManager.js +134 -0
  986. package/dist/update/index.d.ts +9 -0
  987. package/dist/update/index.d.ts.map +1 -0
  988. package/dist/update/index.js +9 -0
  989. package/dist/utils/filesystem.d.ts +29 -0
  990. package/dist/utils/filesystem.d.ts.map +1 -0
  991. package/dist/utils/filesystem.js +94 -0
  992. package/dist/utils/git.d.ts +32 -0
  993. package/dist/utils/git.d.ts.map +1 -0
  994. package/dist/utils/git.js +65 -0
  995. package/dist/utils/index.d.ts +7 -0
  996. package/dist/utils/index.d.ts.map +1 -0
  997. package/dist/utils/index.js +7 -0
  998. package/dist/utils/logger.d.ts +45 -0
  999. package/dist/utils/logger.d.ts.map +1 -0
  1000. package/dist/utils/logger.js +91 -0
  1001. package/dist/utils/version.d.ts +25 -0
  1002. package/dist/utils/version.d.ts.map +1 -0
  1003. package/dist/utils/version.js +97 -0
  1004. package/package.json +128 -0
package/dist/index.js ADDED
@@ -0,0 +1,1606 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
5
+ import * as fs from "fs/promises";
6
+ import * as path from "path";
7
+ import { loadIndicatorConfig, formatIndicator, validateCustomFormat } from './config/indicator-config.js';
8
+ import { SecureYamlParser } from './security/secureYamlParser.js';
9
+ import { SecurityError } from './errors/SecurityError.js';
10
+ import { SecureErrorHandler } from './security/errorHandler.js';
11
+ import { APICache } from './cache/APICache.js';
12
+ import { validateFilename, sanitizeInput, validateContentSize, validateUsername, validateCategory, MCPInputValidator } from './security/InputValidator.js';
13
+ import { SECURITY_LIMITS, VALIDATION_PATTERNS } from './security/constants.js';
14
+ import { ContentValidator } from './security/contentValidator.js';
15
+ import { PathValidator } from './security/pathValidator.js';
16
+ import { FileLockManager } from './security/fileLockManager.js';
17
+ import { generateAnonymousId, generateUniqueId, slugify } from './utils/filesystem.js';
18
+ import { PersonaManager } from './persona/PersonaManager.js';
19
+ import { GitHubClient, CollectionBrowser, CollectionSearch, PersonaDetails, PersonaSubmitter, ElementInstaller } from './collection/index.js';
20
+ import { UpdateManager } from './update/index.js';
21
+ import { ServerSetup } from './server/index.js';
22
+ import { logger } from './utils/logger.js';
23
+ import { PersonaExporter, PersonaImporter, PersonaSharer } from './persona/export-import/index.js';
24
+ import { isDefaultPersona } from './constants/defaultPersonas.js';
25
+ import { PortfolioManager, ElementType } from './portfolio/PortfolioManager.js';
26
+ import { MigrationManager } from './portfolio/MigrationManager.js';
27
+ export class DollhouseMCPServer {
28
+ server;
29
+ personasDir;
30
+ personas = new Map();
31
+ activePersona = null;
32
+ currentUser = null;
33
+ apiCache = new APICache();
34
+ rateLimitTracker = new Map();
35
+ indicatorConfig;
36
+ personaManager;
37
+ githubClient;
38
+ collectionBrowser;
39
+ collectionSearch;
40
+ personaDetails;
41
+ elementInstaller;
42
+ personaSubmitter;
43
+ updateManager;
44
+ serverSetup;
45
+ personaExporter;
46
+ personaImporter;
47
+ personaSharer;
48
+ portfolioManager;
49
+ migrationManager;
50
+ constructor() {
51
+ this.server = new Server({
52
+ name: "dollhousemcp",
53
+ version: "1.0.0",
54
+ }, {
55
+ capabilities: {
56
+ tools: {},
57
+ },
58
+ });
59
+ // Initialize portfolio system
60
+ this.portfolioManager = PortfolioManager.getInstance();
61
+ this.migrationManager = new MigrationManager(this.portfolioManager);
62
+ // Use portfolio personas directory
63
+ this.personasDir = this.portfolioManager.getElementDir(ElementType.PERSONA);
64
+ // Log resolved path for debugging
65
+ logger.info(`Personas directory resolved to: ${this.personasDir}`);
66
+ // Initialize PathValidator with the personas directory
67
+ PathValidator.initialize(this.personasDir);
68
+ // Load user identity from environment variables
69
+ this.currentUser = process.env.DOLLHOUSE_USER || null;
70
+ // Load indicator configuration
71
+ this.indicatorConfig = loadIndicatorConfig();
72
+ // Initialize persona manager
73
+ this.personaManager = new PersonaManager(this.personasDir, this.indicatorConfig);
74
+ // Initialize collection modules
75
+ this.githubClient = new GitHubClient(this.apiCache, this.rateLimitTracker);
76
+ this.collectionBrowser = new CollectionBrowser(this.githubClient);
77
+ this.collectionSearch = new CollectionSearch(this.githubClient);
78
+ this.personaDetails = new PersonaDetails(this.githubClient);
79
+ this.elementInstaller = new ElementInstaller(this.githubClient);
80
+ this.personaSubmitter = new PersonaSubmitter();
81
+ // Initialize update manager
82
+ this.updateManager = new UpdateManager();
83
+ // Initialize export/import/share modules
84
+ this.personaExporter = new PersonaExporter(this.currentUser);
85
+ this.personaImporter = new PersonaImporter(this.personasDir, this.currentUser);
86
+ this.personaSharer = new PersonaSharer(this.githubClient, this.currentUser);
87
+ // Initialize server setup
88
+ this.serverSetup = new ServerSetup();
89
+ this.serverSetup.setupServer(this.server, this);
90
+ // Initialize portfolio and perform migration if needed
91
+ this.initializePortfolio().then(() => {
92
+ this.loadPersonas();
93
+ }).catch(error => {
94
+ logger.error(`Failed to initialize portfolio: ${error}`);
95
+ });
96
+ }
97
+ async initializePortfolio() {
98
+ // Check if migration is needed
99
+ const needsMigration = await this.migrationManager.needsMigration();
100
+ if (needsMigration) {
101
+ logger.info('Legacy personas detected. Starting migration...');
102
+ const result = await this.migrationManager.migrate({ backup: true });
103
+ if (result.success) {
104
+ logger.info(`Successfully migrated ${result.migratedCount} personas`);
105
+ if (result.backedUp && result.backupPath) {
106
+ logger.info(`Backup created at: ${result.backupPath}`);
107
+ }
108
+ }
109
+ else {
110
+ logger.error('Migration completed with errors:');
111
+ result.errors.forEach(err => logger.error(` - ${err}`));
112
+ }
113
+ }
114
+ // Ensure portfolio structure exists
115
+ const portfolioExists = await this.portfolioManager.exists();
116
+ if (!portfolioExists) {
117
+ logger.info('Creating portfolio directory structure...');
118
+ await this.portfolioManager.initialize();
119
+ }
120
+ }
121
+ // Tool handler methods - now public for access from tool modules
122
+ getPersonaIndicator() {
123
+ if (!this.activePersona) {
124
+ return "";
125
+ }
126
+ const persona = this.personas.get(this.activePersona);
127
+ if (!persona) {
128
+ return "";
129
+ }
130
+ return formatIndicator(this.indicatorConfig, {
131
+ name: persona.metadata.name,
132
+ version: persona.metadata.version,
133
+ author: persona.metadata.author,
134
+ category: persona.metadata.category
135
+ });
136
+ }
137
+ async loadPersonas() {
138
+ // Validate the personas directory path
139
+ if (!path.isAbsolute(this.personasDir)) {
140
+ logger.warn(`Personas directory path is not absolute: ${this.personasDir}`);
141
+ }
142
+ try {
143
+ await fs.access(this.personasDir);
144
+ }
145
+ catch (error) {
146
+ // Create personas directory if it doesn't exist
147
+ try {
148
+ await fs.mkdir(this.personasDir, { recursive: true });
149
+ logger.info(`Created personas directory at: ${this.personasDir}`);
150
+ return;
151
+ }
152
+ catch (mkdirError) {
153
+ logger.error(`Failed to create personas directory at ${this.personasDir}: ${mkdirError.message}`);
154
+ throw new Error(`Cannot create personas directory: ${mkdirError.message}`);
155
+ }
156
+ }
157
+ try {
158
+ const files = await fs.readdir(this.personasDir);
159
+ const markdownFiles = files.filter(file => file.endsWith('.md'));
160
+ this.personas.clear();
161
+ for (const file of markdownFiles) {
162
+ try {
163
+ const filePath = path.join(this.personasDir, file);
164
+ const fileContent = await PathValidator.safeReadFile(filePath);
165
+ // Use secure YAML parser
166
+ let parsed;
167
+ try {
168
+ parsed = SecureYamlParser.safeMatter(fileContent);
169
+ }
170
+ catch (error) {
171
+ if (error instanceof SecurityError) {
172
+ logger.warn(`Security threat detected in persona ${file}: ${error.message}`);
173
+ continue;
174
+ }
175
+ throw error;
176
+ }
177
+ const metadata = parsed.data;
178
+ const content = parsed.content;
179
+ if (!metadata.name) {
180
+ metadata.name = path.basename(file, '.md');
181
+ }
182
+ // Generate unique ID if not present
183
+ let uniqueId = metadata.unique_id;
184
+ if (!uniqueId) {
185
+ const authorForId = metadata.author || this.getCurrentUserForAttribution();
186
+ uniqueId = generateUniqueId(metadata.name, authorForId);
187
+ logger.debug(`Generated unique ID for ${metadata.name}: ${uniqueId}`);
188
+ }
189
+ // Set default values for new metadata fields
190
+ if (!metadata.category)
191
+ metadata.category = 'general';
192
+ if (!metadata.age_rating)
193
+ metadata.age_rating = 'all';
194
+ if (!metadata.content_flags)
195
+ metadata.content_flags = [];
196
+ if (metadata.ai_generated === undefined)
197
+ metadata.ai_generated = false;
198
+ if (!metadata.generation_method)
199
+ metadata.generation_method = 'human';
200
+ if (!metadata.price)
201
+ metadata.price = 'free';
202
+ if (!metadata.license)
203
+ metadata.license = 'CC-BY-SA-4.0';
204
+ const persona = {
205
+ metadata,
206
+ content,
207
+ filename: file,
208
+ unique_id: uniqueId,
209
+ };
210
+ this.personas.set(file, persona);
211
+ logger.debug(`Loaded persona: ${metadata.name} (${uniqueId}`);
212
+ }
213
+ catch (error) {
214
+ logger.error(`Error loading persona ${file}: ${error}`);
215
+ }
216
+ }
217
+ }
218
+ catch (error) {
219
+ logger.error(`Error reading personas directory: ${error}`);
220
+ }
221
+ }
222
+ async listPersonas() {
223
+ const personaList = Array.from(this.personas.values()).map(persona => ({
224
+ filename: persona.filename,
225
+ unique_id: persona.unique_id,
226
+ name: persona.metadata.name,
227
+ description: persona.metadata.description,
228
+ triggers: persona.metadata.triggers || [],
229
+ version: persona.metadata.version || "1.0",
230
+ author: persona.metadata.author || "Unknown",
231
+ category: persona.metadata.category || 'general',
232
+ age_rating: persona.metadata.age_rating || 'all',
233
+ price: persona.metadata.price || 'free',
234
+ ai_generated: persona.metadata.ai_generated || false,
235
+ active: this.activePersona === persona.filename,
236
+ }));
237
+ return {
238
+ content: [
239
+ {
240
+ type: "text",
241
+ text: `${this.getPersonaIndicator()}Available Personas (${personaList.length}):\n\n` +
242
+ personaList.map(p => `${p.active ? '🔹 ' : '▫️ '}**${p.name}** (${p.unique_id})\n` +
243
+ ` ${p.description}\n` +
244
+ ` 📁 ${p.category} | 🎭 ${p.author} | 🔖 ${p.price} | ${p.ai_generated ? '🤖 AI' : '👤 Human'}\n` +
245
+ ` Age: ${p.age_rating} | Version: ${p.version}\n` +
246
+ ` Triggers: ${p.triggers.join(', ') || 'None'}\n`).join('\n'),
247
+ },
248
+ ],
249
+ };
250
+ }
251
+ async activatePersona(personaIdentifier) {
252
+ // Enhanced input validation for persona identifier
253
+ const validatedIdentifier = MCPInputValidator.validatePersonaIdentifier(personaIdentifier);
254
+ // Try to find persona by filename first, then by name
255
+ let persona = this.personas.get(validatedIdentifier);
256
+ if (!persona) {
257
+ // Search by name
258
+ persona = Array.from(this.personas.values()).find(p => p.metadata.name.toLowerCase() === validatedIdentifier.toLowerCase());
259
+ }
260
+ if (!persona) {
261
+ throw new McpError(ErrorCode.InvalidParams, `Persona not found: ${personaIdentifier}`);
262
+ }
263
+ this.activePersona = persona.filename;
264
+ return {
265
+ content: [
266
+ {
267
+ type: "text",
268
+ text: `${this.getPersonaIndicator()}Persona Activated: **${persona.metadata.name}**\n\n` +
269
+ `${persona.metadata.description}\n\n` +
270
+ `**Instructions:**\n${persona.content}`,
271
+ },
272
+ ],
273
+ };
274
+ }
275
+ async getActivePersona() {
276
+ if (!this.activePersona) {
277
+ return {
278
+ content: [
279
+ {
280
+ type: "text",
281
+ text: `${this.getPersonaIndicator()}No persona is currently active.`,
282
+ },
283
+ ],
284
+ };
285
+ }
286
+ const persona = this.personas.get(this.activePersona);
287
+ if (!persona) {
288
+ this.activePersona = null;
289
+ return {
290
+ content: [
291
+ {
292
+ type: "text",
293
+ text: `${this.getPersonaIndicator()}Active persona not found. Deactivated.`,
294
+ },
295
+ ],
296
+ };
297
+ }
298
+ return {
299
+ content: [
300
+ {
301
+ type: "text",
302
+ text: `${this.getPersonaIndicator()}Active Persona: **${persona.metadata.name}**\n\n` +
303
+ `${persona.metadata.description}\n\n` +
304
+ `File: ${persona.filename}\n` +
305
+ `Version: ${persona.metadata.version || '1.0'}\n` +
306
+ `Author: ${persona.metadata.author || 'Unknown'}`,
307
+ },
308
+ ],
309
+ };
310
+ }
311
+ async deactivatePersona() {
312
+ const wasActive = this.activePersona !== null;
313
+ const indicator = this.getPersonaIndicator();
314
+ this.activePersona = null;
315
+ return {
316
+ content: [
317
+ {
318
+ type: "text",
319
+ text: wasActive
320
+ ? `${indicator}✅ Persona deactivated. Back to default mode.`
321
+ : "No persona was active.",
322
+ },
323
+ ],
324
+ };
325
+ }
326
+ async getPersonaDetails(personaIdentifier) {
327
+ // Try to find persona by filename first, then by name
328
+ let persona = this.personas.get(personaIdentifier);
329
+ if (!persona) {
330
+ // Search by name
331
+ persona = Array.from(this.personas.values()).find(p => p.metadata.name.toLowerCase() === personaIdentifier.toLowerCase());
332
+ }
333
+ if (!persona) {
334
+ throw new McpError(ErrorCode.InvalidParams, `Persona not found: ${personaIdentifier}`);
335
+ }
336
+ return {
337
+ content: [
338
+ {
339
+ type: "text",
340
+ text: `${this.getPersonaIndicator()}📋 **${persona.metadata.name}** Details\n\n` +
341
+ `**Description:** ${persona.metadata.description}\n` +
342
+ `**File:** ${persona.filename}\n` +
343
+ `**Version:** ${persona.metadata.version || '1.0'}\n` +
344
+ `**Author:** ${persona.metadata.author || 'Unknown'}\n` +
345
+ `**Triggers:** ${persona.metadata.triggers?.join(', ') || 'None'}\n\n` +
346
+ `**Full Content:**\n\`\`\`\n${persona.content}\n\`\`\``,
347
+ },
348
+ ],
349
+ };
350
+ }
351
+ async reloadPersonas() {
352
+ await this.loadPersonas();
353
+ return {
354
+ content: [
355
+ {
356
+ type: "text",
357
+ text: `${this.getPersonaIndicator()}🔄 Reloaded ${this.personas.size} personas from ${this.personasDir}`,
358
+ },
359
+ ],
360
+ };
361
+ }
362
+ // checkRateLimit and fetchFromGitHub are now handled by GitHubClient
363
+ async browseCollection(section, type) {
364
+ try {
365
+ // Enhanced input validation for section and type
366
+ const validatedSection = section ? validateCategory(section) : undefined;
367
+ const validatedType = type ? validateCategory(type) : undefined;
368
+ const result = await this.collectionBrowser.browseCollection(validatedSection, validatedType);
369
+ // Handle sections view
370
+ const items = result.items;
371
+ const categories = result.sections || result.categories;
372
+ const text = this.collectionBrowser.formatBrowseResults(items, categories, validatedSection, validatedType, this.getPersonaIndicator());
373
+ return {
374
+ content: [
375
+ {
376
+ type: "text",
377
+ text: text,
378
+ },
379
+ ],
380
+ };
381
+ }
382
+ catch (error) {
383
+ const sanitized = SecureErrorHandler.sanitizeError(error);
384
+ return {
385
+ content: [
386
+ {
387
+ type: "text",
388
+ text: `${this.getPersonaIndicator()}❌ Collection browsing failed: ${sanitized.message}`,
389
+ },
390
+ ],
391
+ };
392
+ }
393
+ }
394
+ async searchCollection(query) {
395
+ try {
396
+ // Enhanced input validation for search query
397
+ const validatedQuery = MCPInputValidator.validateSearchQuery(query);
398
+ const items = await this.collectionSearch.searchCollection(validatedQuery);
399
+ const text = this.collectionSearch.formatSearchResults(items, validatedQuery, this.getPersonaIndicator());
400
+ return {
401
+ content: [
402
+ {
403
+ type: "text",
404
+ text: text,
405
+ },
406
+ ],
407
+ };
408
+ }
409
+ catch (error) {
410
+ const sanitized = SecureErrorHandler.sanitizeError(error);
411
+ return {
412
+ content: [
413
+ {
414
+ type: "text",
415
+ text: `${this.getPersonaIndicator()}❌ Error searching collection: ${sanitized.message}`,
416
+ },
417
+ ],
418
+ };
419
+ }
420
+ }
421
+ async getCollectionContent(path) {
422
+ try {
423
+ const { metadata, content } = await this.personaDetails.getCollectionContent(path);
424
+ const text = this.personaDetails.formatPersonaDetails(metadata, content, path, this.getPersonaIndicator());
425
+ return {
426
+ content: [
427
+ {
428
+ type: "text",
429
+ text: text,
430
+ },
431
+ ],
432
+ };
433
+ }
434
+ catch (error) {
435
+ const sanitized = SecureErrorHandler.sanitizeError(error);
436
+ return {
437
+ content: [
438
+ {
439
+ type: "text",
440
+ text: `${this.getPersonaIndicator()}❌ Error fetching content: ${sanitized.message}`,
441
+ },
442
+ ],
443
+ };
444
+ }
445
+ }
446
+ async installContent(inputPath) {
447
+ try {
448
+ const result = await this.elementInstaller.installContent(inputPath);
449
+ if (!result.success) {
450
+ return {
451
+ content: [
452
+ {
453
+ type: "text",
454
+ text: `⚠️ ${result.message}`,
455
+ },
456
+ ],
457
+ };
458
+ }
459
+ // If it's a persona, reload personas
460
+ if (result.elementType === ElementType.PERSONA) {
461
+ await this.loadPersonas();
462
+ }
463
+ const text = this.elementInstaller.formatInstallSuccess(result.metadata, result.filename, result.elementType);
464
+ return {
465
+ content: [
466
+ {
467
+ type: "text",
468
+ text: text,
469
+ },
470
+ ],
471
+ };
472
+ }
473
+ catch (error) {
474
+ const sanitized = SecureErrorHandler.sanitizeError(error);
475
+ return {
476
+ content: [
477
+ {
478
+ type: "text",
479
+ text: `${this.getPersonaIndicator()}❌ Error installing AI customization element: ${sanitized.message}`,
480
+ },
481
+ ],
482
+ };
483
+ }
484
+ }
485
+ async submitContent(contentIdentifier) {
486
+ // Find the content in local collection
487
+ let persona = this.personas.get(contentIdentifier);
488
+ if (!persona) {
489
+ // Search by name
490
+ persona = Array.from(this.personas.values()).find(p => p.metadata.name.toLowerCase() === contentIdentifier.toLowerCase());
491
+ }
492
+ if (!persona) {
493
+ return {
494
+ content: [
495
+ {
496
+ type: "text",
497
+ text: `${this.getPersonaIndicator()}❌ Content not found: ${contentIdentifier}`,
498
+ },
499
+ ],
500
+ };
501
+ }
502
+ // Validate persona content before submission
503
+ try {
504
+ // Read the full persona file content
505
+ const fullPath = path.join(this.personasDir, persona.filename);
506
+ const fileContent = await PathValidator.safeReadFile(fullPath);
507
+ // Validate content for security threats
508
+ const contentValidation = ContentValidator.validateAndSanitize(fileContent);
509
+ if (!contentValidation.isValid && contentValidation.severity === 'critical') {
510
+ return {
511
+ content: [
512
+ {
513
+ type: "text",
514
+ text: `${this.getPersonaIndicator()}❌ **Security Validation Failed**\n\n` +
515
+ `This persona contains content that could be used for prompt injection attacks:\n` +
516
+ `• ${contentValidation.detectedPatterns?.join('\n• ')}\n\n` +
517
+ `Please remove these patterns before submitting to the collection.`,
518
+ },
519
+ ],
520
+ };
521
+ }
522
+ // Validate metadata
523
+ const metadataValidation = ContentValidator.validateMetadata(persona.metadata);
524
+ if (!metadataValidation.isValid) {
525
+ return {
526
+ content: [
527
+ {
528
+ type: "text",
529
+ text: `${this.getPersonaIndicator()}⚠️ **Metadata Security Warning**\n\n` +
530
+ `The persona metadata contains potentially problematic content:\n` +
531
+ `• ${metadataValidation.detectedPatterns?.join('\n• ')}\n\n` +
532
+ `Please fix these issues before submitting.`,
533
+ },
534
+ ],
535
+ };
536
+ }
537
+ }
538
+ catch (error) {
539
+ const sanitized = SecureErrorHandler.sanitizeError(error);
540
+ return {
541
+ content: [
542
+ {
543
+ type: "text",
544
+ text: `${this.getPersonaIndicator()}❌ Error validating persona: ${sanitized.message}`,
545
+ },
546
+ ],
547
+ };
548
+ }
549
+ const { githubIssueUrl } = this.personaSubmitter.generateSubmissionIssue(persona);
550
+ const text = this.personaSubmitter.formatSubmissionResponse(persona, githubIssueUrl, this.getPersonaIndicator());
551
+ return {
552
+ content: [
553
+ {
554
+ type: "text",
555
+ text: text,
556
+ },
557
+ ],
558
+ };
559
+ }
560
+ // User identity management
561
+ async setUserIdentity(username, email) {
562
+ try {
563
+ if (!username || username.trim().length === 0) {
564
+ return {
565
+ content: [
566
+ {
567
+ type: "text",
568
+ text: `${this.getPersonaIndicator()}❌ Username cannot be empty`,
569
+ },
570
+ ],
571
+ };
572
+ }
573
+ // Validate and sanitize username
574
+ const validatedUsername = validateUsername(username);
575
+ // Validate email if provided
576
+ let validatedEmail;
577
+ if (email) {
578
+ const sanitizedEmail = sanitizeInput(email, 100);
579
+ if (!VALIDATION_PATTERNS.SAFE_EMAIL.test(sanitizedEmail)) {
580
+ throw new Error('Invalid email format');
581
+ }
582
+ validatedEmail = sanitizedEmail;
583
+ }
584
+ // Set the validated user identity
585
+ this.currentUser = validatedUsername;
586
+ if (validatedEmail) {
587
+ process.env.DOLLHOUSE_EMAIL = validatedEmail;
588
+ }
589
+ return {
590
+ content: [
591
+ {
592
+ type: "text",
593
+ text: `${this.getPersonaIndicator()}✅ **User Identity Set**\n\n` +
594
+ `👤 **Username:** ${validatedUsername}\n` +
595
+ `${validatedEmail ? `📧 **Email:** ${validatedEmail}\n` : ''}` +
596
+ `\n🎯 **Next Steps:**\n` +
597
+ `• New personas you create will be attributed to "${validatedUsername}"\n` +
598
+ `• Set environment variable \`DOLLHOUSE_USER=${validatedUsername}\` to persist this setting\n` +
599
+ `${validatedEmail ? `• Set environment variable \`DOLLHOUSE_EMAIL=${validatedEmail}\` for contact info\n` : ''}` +
600
+ `• Use \`clear_user_identity\` to return to anonymous mode`,
601
+ },
602
+ ],
603
+ };
604
+ }
605
+ catch (error) {
606
+ const sanitized = SecureErrorHandler.sanitizeError(error);
607
+ return {
608
+ content: [
609
+ {
610
+ type: "text",
611
+ text: `${this.getPersonaIndicator()}❌ **Validation Error**\n\n` +
612
+ `${sanitized.message}\n\n` +
613
+ `Please provide a valid username (alphanumeric characters, hyphens, underscores, dots only).`,
614
+ },
615
+ ],
616
+ };
617
+ }
618
+ }
619
+ async getUserIdentity() {
620
+ const email = process.env.DOLLHOUSE_EMAIL;
621
+ if (!this.currentUser) {
622
+ return {
623
+ content: [
624
+ {
625
+ type: "text",
626
+ text: `${this.getPersonaIndicator()}👤 **User Identity: Anonymous**\n\n` +
627
+ `🔒 **Status:** Anonymous mode\n` +
628
+ `📝 **Attribution:** Personas will use anonymous IDs\n\n` +
629
+ `**To set your identity:**\n` +
630
+ `• Use: \`set_user_identity "your-username"\`\n` +
631
+ `• Or set environment variable: \`DOLLHOUSE_USER=your-username\``,
632
+ },
633
+ ],
634
+ };
635
+ }
636
+ return {
637
+ content: [
638
+ {
639
+ type: "text",
640
+ text: `${this.getPersonaIndicator()}👤 **User Identity: ${this.currentUser}**\n\n` +
641
+ `✅ **Status:** Authenticated\n` +
642
+ `👤 **Username:** ${this.currentUser}\n` +
643
+ `${email ? `📧 **Email:** ${email}\n` : ''}` +
644
+ `📝 **Attribution:** New personas will be credited to "${this.currentUser}"\n\n` +
645
+ `**Environment Variables:**\n` +
646
+ `• \`DOLLHOUSE_USER=${this.currentUser}\`\n` +
647
+ `${email ? `• \`DOLLHOUSE_EMAIL=${email}\`\n` : ''}` +
648
+ `\n**Management:**\n` +
649
+ `• Use \`clear_user_identity\` to return to anonymous mode\n` +
650
+ `• Use \`set_user_identity "new-username"\` to change username`,
651
+ },
652
+ ],
653
+ };
654
+ }
655
+ async clearUserIdentity() {
656
+ const wasSet = this.currentUser !== null;
657
+ const previousUser = this.currentUser;
658
+ this.currentUser = null;
659
+ return {
660
+ content: [
661
+ {
662
+ type: "text",
663
+ text: wasSet
664
+ ? `${this.getPersonaIndicator()}✅ **User Identity Cleared**\n\n` +
665
+ `👤 **Previous:** ${previousUser}\n` +
666
+ `🔒 **Current:** Anonymous mode\n\n` +
667
+ `📝 **Effect:** New personas will use anonymous IDs\n\n` +
668
+ `⚠️ **Note:** This only affects the current session.\n` +
669
+ `To persist this change, unset the \`DOLLHOUSE_USER\` environment variable.`
670
+ : `${this.getPersonaIndicator()}ℹ️ **Already in Anonymous Mode**\n\n` +
671
+ `👤 No user identity was set.\n\n` +
672
+ `Use \`set_user_identity "username"\` to set your identity.`,
673
+ },
674
+ ],
675
+ };
676
+ }
677
+ getCurrentUserForAttribution() {
678
+ return this.currentUser || generateAnonymousId();
679
+ }
680
+ // Chat-based persona management tools
681
+ async createPersona(name, description, category, instructions, triggers) {
682
+ try {
683
+ // Validate required fields
684
+ if (!name || !description || !category || !instructions) {
685
+ return {
686
+ content: [
687
+ {
688
+ type: "text",
689
+ text: `${this.getPersonaIndicator()}❌ **Missing Required Fields**\n\n` +
690
+ `Please provide all required fields:\n` +
691
+ `• **name**: Display name for the persona\n` +
692
+ `• **description**: Brief description of what it does\n` +
693
+ `• **category**: creative, professional, educational, gaming, or personal\n` +
694
+ `• **instructions**: The persona's behavioral guidelines\n\n` +
695
+ `**Optional:**\n` +
696
+ `• **triggers**: Comma-separated keywords for activation`,
697
+ },
698
+ ],
699
+ };
700
+ }
701
+ // Sanitize and validate inputs
702
+ const sanitizedName = sanitizeInput(name, 100);
703
+ const sanitizedDescription = sanitizeInput(description, 500);
704
+ const sanitizedInstructions = sanitizeInput(instructions);
705
+ const sanitizedTriggers = triggers ? sanitizeInput(triggers, 200) : '';
706
+ // Validate name length and format
707
+ if (sanitizedName.length < 2) {
708
+ throw new Error('Persona name must be at least 2 characters long');
709
+ }
710
+ // Validate category
711
+ const validatedCategory = validateCategory(category);
712
+ // Validate content sizes
713
+ validateContentSize(sanitizedInstructions, SECURITY_LIMITS.MAX_CONTENT_LENGTH);
714
+ validateContentSize(sanitizedDescription, 2000); // 2KB max for description
715
+ // Validate content for security threats
716
+ const nameValidation = ContentValidator.validateAndSanitize(sanitizedName);
717
+ if (!nameValidation.isValid) {
718
+ throw new Error(`Name contains prohibited content: ${nameValidation.detectedPatterns?.join(', ')}`);
719
+ }
720
+ const descValidation = ContentValidator.validateAndSanitize(sanitizedDescription);
721
+ if (!descValidation.isValid) {
722
+ throw new Error(`Description contains prohibited content: ${descValidation.detectedPatterns?.join(', ')}`);
723
+ }
724
+ const instructionsValidation = ContentValidator.validateAndSanitize(sanitizedInstructions);
725
+ if (!instructionsValidation.isValid && instructionsValidation.severity === 'critical') {
726
+ throw new Error(`Instructions contain security threats: ${instructionsValidation.detectedPatterns?.join(', ')}`);
727
+ }
728
+ // Generate metadata
729
+ const author = this.getCurrentUserForAttribution();
730
+ const uniqueId = generateUniqueId(sanitizedName, this.currentUser || undefined);
731
+ const filename = validateFilename(`${slugify(sanitizedName)}.md`);
732
+ const filePath = path.join(this.personasDir, filename);
733
+ // Check if file already exists
734
+ try {
735
+ await PathValidator.validatePersonaPath(filePath);
736
+ await fs.access(filePath);
737
+ return {
738
+ content: [
739
+ {
740
+ type: "text",
741
+ text: `${this.getPersonaIndicator()}⚠️ **Persona Already Exists**\n\n` +
742
+ `A persona file named "${filename}" already exists.\n` +
743
+ `Use \`edit_persona\` to modify it, or choose a different name.`,
744
+ },
745
+ ],
746
+ };
747
+ }
748
+ catch {
749
+ // File doesn't exist, proceed with creation
750
+ }
751
+ // Parse and sanitize triggers
752
+ const triggerList = sanitizedTriggers ?
753
+ sanitizedTriggers.split(',').map(t => sanitizeInput(t.trim(), 50)).filter(t => t.length > 0) :
754
+ [];
755
+ // Create persona metadata with sanitized values
756
+ const metadata = {
757
+ name: sanitizedName,
758
+ description: sanitizedDescription,
759
+ unique_id: uniqueId,
760
+ author,
761
+ triggers: triggerList,
762
+ version: "1.0",
763
+ category: validatedCategory,
764
+ age_rating: "all",
765
+ content_flags: ["user-created"],
766
+ ai_generated: true,
767
+ generation_method: "Claude",
768
+ price: "free",
769
+ revenue_split: "80/20",
770
+ license: "CC-BY-SA-4.0",
771
+ created_date: new Date().toISOString().slice(0, 10)
772
+ };
773
+ // Create full persona content with sanitized values
774
+ const frontmatter = Object.entries(metadata)
775
+ .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
776
+ .join('\n');
777
+ const personaContent = `---
778
+ ${frontmatter}
779
+ ---
780
+
781
+ # ${sanitizedName}
782
+
783
+ ${sanitizedInstructions}
784
+
785
+ ## Response Style
786
+ - Follow the behavioral guidelines above
787
+ - Maintain consistency with the persona's character
788
+ - Adapt responses to match the intended purpose
789
+
790
+ ## Usage Notes
791
+ - Created via DollhouseMCP chat interface
792
+ - Author: ${author}
793
+ - Version: 1.0`;
794
+ // Validate final content size
795
+ validateContentSize(personaContent, SECURITY_LIMITS.MAX_PERSONA_SIZE_BYTES);
796
+ try {
797
+ // Use file locking to prevent race conditions
798
+ await FileLockManager.withLock(`persona:${sanitizedName}`, async () => {
799
+ // Double-check file doesn't exist (in case of race condition)
800
+ try {
801
+ await fs.access(filePath);
802
+ throw new Error(`Persona file "${filename}" already exists`);
803
+ }
804
+ catch (error) {
805
+ // If error is not ENOENT (file not found), re-throw it
806
+ if (error.code !== 'ENOENT' && error.message?.includes('already exists')) {
807
+ throw error;
808
+ }
809
+ // File doesn't exist, proceed
810
+ }
811
+ // Write the file atomically
812
+ await FileLockManager.atomicWriteFile(filePath, personaContent);
813
+ });
814
+ // Reload personas to include the new one
815
+ await this.loadPersonas();
816
+ return {
817
+ content: [
818
+ {
819
+ type: "text",
820
+ text: `${this.getPersonaIndicator()}✅ **Persona Created Successfully!**\n\n` +
821
+ `🎭 **${sanitizedName}** by ${author}\n` +
822
+ `📁 Category: ${category}\n` +
823
+ `🆔 Unique ID: ${uniqueId}\n` +
824
+ `📄 Saved as: ${filename}\n` +
825
+ `📊 Total personas: ${this.personas.size}\n\n` +
826
+ `🎯 **Ready to use:** \`activate_persona "${sanitizedName}"\`\n` +
827
+ `📤 **Share it:** \`submit_content "${sanitizedName}"\`\n` +
828
+ `✏️ **Edit it:** \`edit_persona "${sanitizedName}" "field" "new value"\``,
829
+ },
830
+ ],
831
+ };
832
+ }
833
+ catch (error) {
834
+ const sanitized = SecureErrorHandler.sanitizeError(error);
835
+ return {
836
+ content: [
837
+ {
838
+ type: "text",
839
+ text: `${this.getPersonaIndicator()}❌ **Error Creating Persona**\n\n` +
840
+ `Failed to write persona file: ${sanitized.message}\n\n` +
841
+ `Please check permissions and try again.`,
842
+ },
843
+ ],
844
+ };
845
+ }
846
+ }
847
+ catch (error) {
848
+ const sanitized = SecureErrorHandler.sanitizeError(error);
849
+ return {
850
+ content: [
851
+ {
852
+ type: "text",
853
+ text: `${this.getPersonaIndicator()}❌ **Validation Error**\n\n` +
854
+ `${sanitized.message}\n\n` +
855
+ `Please fix the issue and try again.`,
856
+ },
857
+ ],
858
+ };
859
+ }
860
+ }
861
+ async editPersona(personaIdentifier, field, value) {
862
+ if (!personaIdentifier || !field || !value) {
863
+ return {
864
+ content: [
865
+ {
866
+ type: "text",
867
+ text: `${this.getPersonaIndicator()}❌ **Missing Parameters**\n\n` +
868
+ `Usage: \`edit_persona "persona_name" "field" "new_value"\`\n\n` +
869
+ `**Editable fields:**\n` +
870
+ `• **name** - Display name\n` +
871
+ `• **description** - Brief description\n` +
872
+ `• **category** - creative, professional, educational, gaming, personal\n` +
873
+ `• **instructions** - Main persona content\n` +
874
+ `• **triggers** - Comma-separated keywords\n` +
875
+ `• **version** - Version number`,
876
+ },
877
+ ],
878
+ };
879
+ }
880
+ // Find the persona
881
+ let persona = this.personas.get(personaIdentifier);
882
+ if (!persona) {
883
+ // Search by name
884
+ persona = Array.from(this.personas.values()).find(p => p.metadata.name.toLowerCase() === personaIdentifier.toLowerCase());
885
+ }
886
+ if (!persona) {
887
+ return {
888
+ content: [
889
+ {
890
+ type: "text",
891
+ text: `${this.getPersonaIndicator()}❌ **Persona Not Found**\n\n` +
892
+ `Could not find persona: "${personaIdentifier}"\n\n` +
893
+ `Use \`list_personas\` to see available personas.`,
894
+ },
895
+ ],
896
+ };
897
+ }
898
+ const validFields = ['name', 'description', 'category', 'instructions', 'triggers', 'version'];
899
+ if (!validFields.includes(field.toLowerCase())) {
900
+ return {
901
+ content: [
902
+ {
903
+ type: "text",
904
+ text: `${this.getPersonaIndicator()}❌ **Invalid Field**\n\n` +
905
+ `Field "${field}" is not editable.\n\n` +
906
+ `**Valid fields:** ${validFields.join(', ')}`,
907
+ },
908
+ ],
909
+ };
910
+ }
911
+ let filePath = path.join(this.personasDir, persona.filename);
912
+ let isDefault = isDefaultPersona(persona.filename);
913
+ try {
914
+ // Read current file
915
+ const fileContent = await PathValidator.safeReadFile(filePath);
916
+ // Use secure YAML parser
917
+ let parsed;
918
+ try {
919
+ parsed = SecureYamlParser.safeMatter(fileContent);
920
+ }
921
+ catch (error) {
922
+ if (error instanceof SecurityError) {
923
+ return {
924
+ content: [
925
+ {
926
+ type: "text",
927
+ text: `${this.getPersonaIndicator()}❌ **Security Error**\n\n` +
928
+ `Cannot edit persona due to security threat: ${error.message}`,
929
+ },
930
+ ],
931
+ };
932
+ }
933
+ throw error;
934
+ }
935
+ // If editing a default persona, create a copy instead
936
+ if (isDefault) {
937
+ // Generate unique ID for the copy
938
+ const author = this.currentUser || generateAnonymousId();
939
+ const uniqueId = generateUniqueId(persona.metadata.name, author);
940
+ const newFilename = `${uniqueId}.md`;
941
+ const newFilePath = path.join(this.personasDir, newFilename);
942
+ // Create copy of the default persona
943
+ const content = await PathValidator.safeReadFile(filePath);
944
+ // Use file locking to prevent race conditions when creating the copy
945
+ await FileLockManager.withLock(`persona:${persona.metadata.name}-copy`, async () => {
946
+ await FileLockManager.atomicWriteFile(newFilePath, content);
947
+ });
948
+ // Update file path to point to the copy
949
+ filePath = newFilePath;
950
+ // Update the unique_id in the metadata
951
+ parsed.data.unique_id = uniqueId;
952
+ parsed.data.author = author;
953
+ }
954
+ // Update the appropriate field
955
+ const normalizedField = field.toLowerCase();
956
+ // Validate the new value for security threats
957
+ const valueValidation = ContentValidator.validateAndSanitize(value);
958
+ if (!valueValidation.isValid && valueValidation.severity === 'critical') {
959
+ return {
960
+ content: [
961
+ {
962
+ type: "text",
963
+ text: `${this.getPersonaIndicator()}❌ **Security Validation Failed**\n\n` +
964
+ `The new value contains prohibited content:\n` +
965
+ `• ${valueValidation.detectedPatterns?.join('\n• ')}\n\n` +
966
+ `Please remove these patterns and try again.`,
967
+ },
968
+ ],
969
+ };
970
+ }
971
+ // Use sanitized value if needed
972
+ let sanitizedValue = valueValidation.sanitizedContent || value;
973
+ // Always remove shell metacharacters from display output
974
+ const displayValue = sanitizedValue.replace(/[;&|`$()]/g, '');
975
+ if (normalizedField === 'instructions') {
976
+ // Update the main content
977
+ parsed.content = sanitizedValue;
978
+ }
979
+ else if (normalizedField === 'triggers') {
980
+ // Parse triggers as comma-separated list
981
+ parsed.data[normalizedField] = sanitizedValue.split(',').map(t => t.trim()).filter(t => t.length > 0);
982
+ }
983
+ else if (normalizedField === 'category') {
984
+ // Validate category
985
+ const validCategories = ['creative', 'professional', 'educational', 'gaming', 'personal'];
986
+ if (!validCategories.includes(sanitizedValue.toLowerCase())) {
987
+ return {
988
+ content: [
989
+ {
990
+ type: "text",
991
+ text: `${this.getPersonaIndicator()}❌ **Invalid Category**\n\n` +
992
+ `Category must be one of: ${validCategories.join(', ')}\n` +
993
+ `You provided: "${sanitizedValue}"`,
994
+ },
995
+ ],
996
+ };
997
+ }
998
+ parsed.data[normalizedField] = sanitizedValue.toLowerCase();
999
+ }
1000
+ else {
1001
+ // Update metadata field
1002
+ // For name field, apply additional sanitization to remove shell metacharacters
1003
+ if (normalizedField === 'name') {
1004
+ parsed.data[normalizedField] = sanitizeInput(sanitizedValue, 100);
1005
+ }
1006
+ else {
1007
+ parsed.data[normalizedField] = sanitizedValue;
1008
+ }
1009
+ }
1010
+ // Update version and modification info
1011
+ if (normalizedField !== 'version') {
1012
+ const currentVersion = parsed.data.version || '1.0';
1013
+ const versionParts = currentVersion.split('.').map(Number);
1014
+ versionParts[1] = (versionParts[1] || 0) + 1;
1015
+ parsed.data.version = versionParts.join('.');
1016
+ }
1017
+ // Regenerate file content
1018
+ // Use secure YAML stringification
1019
+ const secureParser = SecureYamlParser.createSecureMatterParser();
1020
+ const updatedContent = secureParser.stringify(parsed.content, parsed.data);
1021
+ // Use file locking to prevent race conditions
1022
+ await FileLockManager.withLock(`persona:${persona.metadata.name}`, async () => {
1023
+ // Write updated file atomically
1024
+ await FileLockManager.atomicWriteFile(filePath, updatedContent);
1025
+ });
1026
+ // Reload personas
1027
+ await this.loadPersonas();
1028
+ return {
1029
+ content: [
1030
+ {
1031
+ type: "text",
1032
+ text: `${this.getPersonaIndicator()}✅ **Persona Updated Successfully!**\n\n` +
1033
+ (isDefault ? `📋 **Note:** Created a copy of the default persona to preserve the original.\n\n` : '') +
1034
+ `🎭 **${(parsed.data.name || persona.metadata.name || '').replace(/[;&|`$()]/g, '')}**\n` +
1035
+ `📝 **Field Updated:** ${field}\n` +
1036
+ `🔄 **New Value:** ${normalizedField === 'instructions' ? 'Content updated' : displayValue}\n` +
1037
+ `📊 **Version:** ${parsed.data.version}\n` +
1038
+ (isDefault ? `🆔 **New ID:** ${parsed.data.unique_id}\n` : '') +
1039
+ `\n` +
1040
+ `Use \`get_persona_details "${(parsed.data.name || persona.metadata.name || '').replace(/[;&|`$()]/g, '')}"\` to see all changes.`,
1041
+ },
1042
+ ],
1043
+ };
1044
+ }
1045
+ catch (error) {
1046
+ const sanitized = SecureErrorHandler.sanitizeError(error);
1047
+ return {
1048
+ content: [
1049
+ {
1050
+ type: "text",
1051
+ text: `${this.getPersonaIndicator()}❌ **Error Updating Persona**\n\n` +
1052
+ `Failed to update persona: ${sanitized.message}\n\n` +
1053
+ `Please check file permissions and try again.`,
1054
+ },
1055
+ ],
1056
+ };
1057
+ }
1058
+ }
1059
+ async validatePersona(personaIdentifier) {
1060
+ if (!personaIdentifier) {
1061
+ return {
1062
+ content: [
1063
+ {
1064
+ type: "text",
1065
+ text: `${this.getPersonaIndicator()}❌ **Missing Persona Identifier**\n\n` +
1066
+ `Usage: \`validate_persona "persona_name"\`\n\n` +
1067
+ `Use \`list_personas\` to see available personas.`,
1068
+ },
1069
+ ],
1070
+ };
1071
+ }
1072
+ // Find the persona
1073
+ let persona = this.personas.get(personaIdentifier);
1074
+ if (!persona) {
1075
+ // Search by name
1076
+ persona = Array.from(this.personas.values()).find(p => p.metadata.name.toLowerCase() === personaIdentifier.toLowerCase());
1077
+ }
1078
+ if (!persona) {
1079
+ return {
1080
+ content: [
1081
+ {
1082
+ type: "text",
1083
+ text: `${this.getPersonaIndicator()}❌ **Persona Not Found**\n\n` +
1084
+ `Could not find persona: "${personaIdentifier}"\n\n` +
1085
+ `Use \`list_personas\` to see available personas.`,
1086
+ },
1087
+ ],
1088
+ };
1089
+ }
1090
+ // Validation checks
1091
+ const issues = [];
1092
+ const warnings = [];
1093
+ const metadata = persona.metadata;
1094
+ // Required field checks
1095
+ if (!metadata.name || metadata.name.trim().length === 0) {
1096
+ issues.push("Missing or empty 'name' field");
1097
+ }
1098
+ if (!metadata.description || metadata.description.trim().length === 0) {
1099
+ issues.push("Missing or empty 'description' field");
1100
+ }
1101
+ if (!persona.content || persona.content.trim().length < 50) {
1102
+ issues.push("Persona content is too short (minimum 50 characters)");
1103
+ }
1104
+ // Category validation
1105
+ const validCategories = ['creative', 'professional', 'educational', 'gaming', 'personal', 'general'];
1106
+ if (metadata.category && !validCategories.includes(metadata.category)) {
1107
+ issues.push(`Invalid category '${metadata.category}'. Must be one of: ${validCategories.join(', ')}`);
1108
+ }
1109
+ // Age rating validation
1110
+ const validAgeRatings = ['all', '13+', '18+'];
1111
+ if (metadata.age_rating && !validAgeRatings.includes(metadata.age_rating)) {
1112
+ warnings.push(`Invalid age_rating '${metadata.age_rating}'. Should be one of: ${validAgeRatings.join(', ')}`);
1113
+ }
1114
+ // Optional field warnings
1115
+ if (!metadata.triggers || metadata.triggers.length === 0) {
1116
+ warnings.push("No trigger keywords defined - users may have difficulty finding this persona");
1117
+ }
1118
+ if (!metadata.version) {
1119
+ warnings.push("No version specified - defaulting to '1.0'");
1120
+ }
1121
+ if (!metadata.unique_id) {
1122
+ warnings.push("No unique_id - one will be generated automatically");
1123
+ }
1124
+ // Content quality checks
1125
+ if (persona.content.length > 5000) {
1126
+ warnings.push("Persona content is very long - consider breaking it into sections");
1127
+ }
1128
+ if (metadata.name && metadata.name.length > 50) {
1129
+ warnings.push("Persona name is very long - consider shortening for better display");
1130
+ }
1131
+ if (metadata.description && metadata.description.length > 200) {
1132
+ warnings.push("Description is very long - consider keeping it under 200 characters");
1133
+ }
1134
+ // Generate validation report
1135
+ let report = `${this.getPersonaIndicator()}📋 **Validation Report: ${persona.metadata.name}**\n\n`;
1136
+ if (issues.length === 0 && warnings.length === 0) {
1137
+ report += `✅ **All Checks Passed!**\n\n` +
1138
+ `🎭 **Persona:** ${metadata.name}\n` +
1139
+ `📁 **Category:** ${metadata.category || 'general'}\n` +
1140
+ `📊 **Version:** ${metadata.version || '1.0'}\n` +
1141
+ `📝 **Content Length:** ${persona.content.length} characters\n` +
1142
+ `🔗 **Triggers:** ${metadata.triggers?.length || 0} keywords\n\n` +
1143
+ `This persona meets all validation requirements and is ready for use!`;
1144
+ }
1145
+ else {
1146
+ if (issues.length > 0) {
1147
+ report += `❌ **Issues Found (${issues.length}):**\n`;
1148
+ issues.forEach((issue, i) => {
1149
+ report += ` ${i + 1}. ${issue}\n`;
1150
+ });
1151
+ report += '\n';
1152
+ }
1153
+ if (warnings.length > 0) {
1154
+ report += `⚠️ **Warnings (${warnings.length}):**\n`;
1155
+ warnings.forEach((warning, i) => {
1156
+ report += ` ${i + 1}. ${warning}\n`;
1157
+ });
1158
+ report += '\n';
1159
+ }
1160
+ if (issues.length > 0) {
1161
+ report += `**Recommendation:** Fix the issues above before using this persona.\n`;
1162
+ report += `Use \`edit_persona "${persona.metadata.name}" "field" "value"\` to make corrections.`;
1163
+ }
1164
+ else {
1165
+ report += `**Status:** Persona is functional but could be improved.\n`;
1166
+ report += `Address warnings above for optimal performance.`;
1167
+ }
1168
+ }
1169
+ return {
1170
+ content: [
1171
+ {
1172
+ type: "text",
1173
+ text: report,
1174
+ },
1175
+ ],
1176
+ };
1177
+ }
1178
+ // retryNetworkOperation is now handled by UpdateChecker
1179
+ // Auto-update management tools
1180
+ async checkForUpdates() {
1181
+ const { text } = await this.updateManager.checkForUpdates();
1182
+ return {
1183
+ content: [{ type: "text", text: this.getPersonaIndicator() + text }]
1184
+ };
1185
+ }
1186
+ // Update helper methods are now handled by UpdateManager
1187
+ async updateServer(confirm) {
1188
+ if (!confirm) {
1189
+ return {
1190
+ content: [{
1191
+ type: "text",
1192
+ text: this.getPersonaIndicator() +
1193
+ '⚠️ **Update Confirmation Required**\n\n' +
1194
+ 'To proceed with the update, you must confirm:\n' +
1195
+ '`update_server true`\n\n' +
1196
+ '**What will happen:**\n' +
1197
+ '• Backup current version\n' +
1198
+ '• Pull latest changes from GitHub\n' +
1199
+ '• Update dependencies\n' +
1200
+ '• Rebuild TypeScript\n' +
1201
+ '• Restart server (will disconnect temporarily)\n\n' +
1202
+ '**Prerequisites:**\n' +
1203
+ '• Git repository must be clean (no uncommitted changes)\n' +
1204
+ '• Network connection required\n' +
1205
+ '• Sufficient disk space for backup'
1206
+ }]
1207
+ };
1208
+ }
1209
+ const { text } = await this.updateManager.updateServer(confirm, this.getPersonaIndicator());
1210
+ return {
1211
+ content: [{ type: "text", text }]
1212
+ };
1213
+ }
1214
+ // Rollback helper methods are now handled by UpdateManager
1215
+ async rollbackUpdate(confirm) {
1216
+ const { text } = await this.updateManager.rollbackUpdate(confirm, this.getPersonaIndicator());
1217
+ return {
1218
+ content: [{ type: "text", text }]
1219
+ };
1220
+ }
1221
+ // Version and git info methods are now handled by UpdateManager
1222
+ // Status helper methods are now handled by UpdateManager
1223
+ async getServerStatus() {
1224
+ // Add persona information to the status
1225
+ const personaInfo = `
1226
+ **🎭 Persona Information:**
1227
+ • **Total Personas:** ${this.personas.size}
1228
+ • **Active Persona:** ${this.activePersona || 'None'}
1229
+ • **User Identity:** ${this.currentUser || 'Anonymous'}
1230
+ • **Personas Directory:** ${this.personasDir}`;
1231
+ const { text } = await this.updateManager.getServerStatus(this.getPersonaIndicator());
1232
+ // Insert persona info into the status text
1233
+ const updatedText = text.replace('**Available Commands:**', personaInfo + '\n\n**Available Commands:**');
1234
+ return {
1235
+ content: [{ type: "text", text: updatedText }]
1236
+ };
1237
+ }
1238
+ // Version and dependency methods are now handled by UpdateManager
1239
+ /**
1240
+ * Configure indicator settings
1241
+ */
1242
+ async configureIndicator(config) {
1243
+ try {
1244
+ // Update the configuration
1245
+ if (config.enabled !== undefined) {
1246
+ this.indicatorConfig.enabled = config.enabled;
1247
+ }
1248
+ if (config.style !== undefined) {
1249
+ this.indicatorConfig.style = config.style;
1250
+ }
1251
+ if (config.customFormat !== undefined) {
1252
+ // Validate custom format before applying
1253
+ const validation = validateCustomFormat(config.customFormat);
1254
+ if (!validation.valid) {
1255
+ return {
1256
+ content: [
1257
+ {
1258
+ type: "text",
1259
+ text: `${this.getPersonaIndicator()}❌ Invalid custom format: ${validation.error}`
1260
+ }
1261
+ ]
1262
+ };
1263
+ }
1264
+ this.indicatorConfig.customFormat = config.customFormat;
1265
+ }
1266
+ if (config.showVersion !== undefined) {
1267
+ this.indicatorConfig.showVersion = config.showVersion;
1268
+ }
1269
+ if (config.showAuthor !== undefined) {
1270
+ this.indicatorConfig.showAuthor = config.showAuthor;
1271
+ }
1272
+ if (config.showCategory !== undefined) {
1273
+ this.indicatorConfig.showCategory = config.showCategory;
1274
+ }
1275
+ if (config.emoji !== undefined) {
1276
+ this.indicatorConfig.emoji = config.emoji;
1277
+ }
1278
+ if (config.bracketStyle !== undefined) {
1279
+ this.indicatorConfig.bracketStyle = config.bracketStyle;
1280
+ }
1281
+ // Show example of what the indicator would look like
1282
+ let exampleIndicator = "";
1283
+ if (this.activePersona) {
1284
+ const persona = this.personas.get(this.activePersona);
1285
+ if (persona) {
1286
+ exampleIndicator = formatIndicator(this.indicatorConfig, {
1287
+ name: persona.metadata.name,
1288
+ version: persona.metadata.version,
1289
+ author: persona.metadata.author,
1290
+ category: persona.metadata.category
1291
+ });
1292
+ }
1293
+ }
1294
+ else {
1295
+ // Show example with sample data
1296
+ exampleIndicator = formatIndicator(this.indicatorConfig, {
1297
+ name: "Example Persona",
1298
+ version: "1.0",
1299
+ author: "@username",
1300
+ category: "creative"
1301
+ });
1302
+ }
1303
+ return {
1304
+ content: [
1305
+ {
1306
+ type: "text",
1307
+ text: `${this.getPersonaIndicator()}✅ Indicator configuration updated successfully!
1308
+
1309
+ Current settings:
1310
+ - Enabled: ${this.indicatorConfig.enabled}
1311
+ - Style: ${this.indicatorConfig.style}
1312
+ - Show Version: ${this.indicatorConfig.showVersion}
1313
+ - Show Author: ${this.indicatorConfig.showAuthor}
1314
+ - Show Category: ${this.indicatorConfig.showCategory}
1315
+ - Emoji: ${this.indicatorConfig.emoji}
1316
+ - Brackets: ${this.indicatorConfig.bracketStyle}
1317
+ ${this.indicatorConfig.customFormat ? `- Custom Format: ${this.indicatorConfig.customFormat}` : ''}
1318
+
1319
+ Example indicator: ${exampleIndicator || "(none - indicators disabled)"}
1320
+
1321
+ Note: Configuration is temporary for this session. To make permanent, set environment variables:
1322
+ - DOLLHOUSE_INDICATOR_ENABLED=true/false
1323
+ - DOLLHOUSE_INDICATOR_STYLE=full/minimal/compact/custom
1324
+ - DOLLHOUSE_INDICATOR_FORMAT="custom format template"
1325
+ - DOLLHOUSE_INDICATOR_SHOW_VERSION=true/false
1326
+ - DOLLHOUSE_INDICATOR_SHOW_AUTHOR=true/false
1327
+ - DOLLHOUSE_INDICATOR_SHOW_CATEGORY=true/false
1328
+ - DOLLHOUSE_INDICATOR_EMOJI=🎭
1329
+ - DOLLHOUSE_INDICATOR_BRACKETS=square/round/curly/angle/none`
1330
+ }
1331
+ ]
1332
+ };
1333
+ }
1334
+ catch (error) {
1335
+ return {
1336
+ content: [
1337
+ {
1338
+ type: "text",
1339
+ text: `${this.getPersonaIndicator()}❌ Error configuring indicator: ${SecureErrorHandler.sanitizeError(error).message}`
1340
+ }
1341
+ ]
1342
+ };
1343
+ }
1344
+ }
1345
+ /**
1346
+ * Get current indicator configuration
1347
+ */
1348
+ async getIndicatorConfig() {
1349
+ // Show current configuration and example
1350
+ let exampleIndicator = "";
1351
+ if (this.activePersona) {
1352
+ const persona = this.personas.get(this.activePersona);
1353
+ if (persona) {
1354
+ exampleIndicator = formatIndicator(this.indicatorConfig, {
1355
+ name: persona.metadata.name,
1356
+ version: persona.metadata.version,
1357
+ author: persona.metadata.author,
1358
+ category: persona.metadata.category
1359
+ });
1360
+ }
1361
+ }
1362
+ else {
1363
+ // Show example with sample data
1364
+ exampleIndicator = formatIndicator(this.indicatorConfig, {
1365
+ name: "Example Persona",
1366
+ version: "1.0",
1367
+ author: "@username",
1368
+ category: "creative"
1369
+ });
1370
+ }
1371
+ return {
1372
+ content: [
1373
+ {
1374
+ type: "text",
1375
+ text: `${this.getPersonaIndicator()}📊 Current Indicator Configuration:
1376
+
1377
+ Settings:
1378
+ - Enabled: ${this.indicatorConfig.enabled}
1379
+ - Style: ${this.indicatorConfig.style}
1380
+ - Show Version: ${this.indicatorConfig.showVersion}
1381
+ - Show Author: ${this.indicatorConfig.showAuthor}
1382
+ - Show Category: ${this.indicatorConfig.showCategory}
1383
+ - Emoji: ${this.indicatorConfig.emoji}
1384
+ - Brackets: ${this.indicatorConfig.bracketStyle}
1385
+ - Separator: "${this.indicatorConfig.separator}"
1386
+ ${this.indicatorConfig.customFormat ? `- Custom Format: ${this.indicatorConfig.customFormat}` : ''}
1387
+
1388
+ Available styles:
1389
+ - full: [🎭 Persona Name v1.0 by @author]
1390
+ - minimal: 🎭 Persona Name
1391
+ - compact: [Persona Name v1.0]
1392
+ - custom: Use your own format with placeholders
1393
+
1394
+ Example with current settings: ${exampleIndicator || "(none - indicators disabled)"}
1395
+
1396
+ Placeholders for custom format:
1397
+ - {emoji} - The configured emoji
1398
+ - {name} - Persona name
1399
+ - {version} - Persona version
1400
+ - {author} - Persona author
1401
+ - {category} - Persona category`
1402
+ }
1403
+ ]
1404
+ };
1405
+ }
1406
+ /**
1407
+ * Export a single persona
1408
+ */
1409
+ async exportPersona(personaName) {
1410
+ try {
1411
+ // Use a single lookup to avoid race conditions
1412
+ let persona = this.personas.get(personaName);
1413
+ if (!persona) {
1414
+ // Try by filename
1415
+ persona = Array.from(this.personas.values()).find(p => p.filename === personaName);
1416
+ if (!persona) {
1417
+ return {
1418
+ content: [{
1419
+ type: "text",
1420
+ text: `${this.getPersonaIndicator()}❌ Persona not found: ${personaName}`
1421
+ }]
1422
+ };
1423
+ }
1424
+ }
1425
+ const exportData = this.personaExporter.exportPersona(persona);
1426
+ const base64 = this.personaExporter.toBase64(exportData);
1427
+ const result = this.personaExporter.formatExportResult(persona, base64);
1428
+ return {
1429
+ content: [{
1430
+ type: "text",
1431
+ text: `${this.getPersonaIndicator()}${result}`
1432
+ }]
1433
+ };
1434
+ }
1435
+ catch (error) {
1436
+ return {
1437
+ content: [{
1438
+ type: "text",
1439
+ text: `${this.getPersonaIndicator()}❌ Export failed: ${SecureErrorHandler.sanitizeError(error).message}`
1440
+ }]
1441
+ };
1442
+ }
1443
+ }
1444
+ /**
1445
+ * Export all personas
1446
+ */
1447
+ async exportAllPersonas(includeDefaults = true) {
1448
+ try {
1449
+ const personasArray = Array.from(this.personas.values());
1450
+ const bundle = this.personaExporter.exportBundle(personasArray, includeDefaults);
1451
+ const base64 = this.personaExporter.toBase64(bundle);
1452
+ const result = this.personaExporter.formatBundleResult(bundle, base64);
1453
+ return {
1454
+ content: [{
1455
+ type: "text",
1456
+ text: `${this.getPersonaIndicator()}${result}`
1457
+ }]
1458
+ };
1459
+ }
1460
+ catch (error) {
1461
+ return {
1462
+ content: [{
1463
+ type: "text",
1464
+ text: `${this.getPersonaIndicator()}❌ Export failed: ${SecureErrorHandler.sanitizeError(error).message}`
1465
+ }]
1466
+ };
1467
+ }
1468
+ }
1469
+ /**
1470
+ * Import a persona
1471
+ */
1472
+ async importPersona(source, overwrite = false) {
1473
+ try {
1474
+ const result = await this.personaImporter.importPersona(source, this.personas, overwrite);
1475
+ if (result.success) {
1476
+ // Reload personas to include the new one
1477
+ await this.loadPersonas();
1478
+ return {
1479
+ content: [{
1480
+ type: "text",
1481
+ text: `${this.getPersonaIndicator()}✅ ${result.message}\n\nPersona "${result.persona?.metadata.name}" is now available.\nTotal personas: ${this.personas.size}`
1482
+ }]
1483
+ };
1484
+ }
1485
+ else {
1486
+ return {
1487
+ content: [{
1488
+ type: "text",
1489
+ text: `${this.getPersonaIndicator()}❌ ${result.message}`
1490
+ }]
1491
+ };
1492
+ }
1493
+ }
1494
+ catch (error) {
1495
+ return {
1496
+ content: [{
1497
+ type: "text",
1498
+ text: `${this.getPersonaIndicator()}❌ Import failed: ${SecureErrorHandler.sanitizeError(error).message}`
1499
+ }]
1500
+ };
1501
+ }
1502
+ }
1503
+ /**
1504
+ * Share a persona via URL
1505
+ */
1506
+ async sharePersona(personaName, expiryDays = 7) {
1507
+ try {
1508
+ // Enhanced input validation
1509
+ const validatedPersonaName = MCPInputValidator.validatePersonaIdentifier(personaName);
1510
+ const validatedExpiryDays = MCPInputValidator.validateExpiryDays(expiryDays);
1511
+ const persona = this.personas.get(validatedPersonaName);
1512
+ if (!persona) {
1513
+ // Try by filename
1514
+ const byFilename = Array.from(this.personas.values()).find(p => p.filename === validatedPersonaName);
1515
+ if (!byFilename) {
1516
+ return {
1517
+ content: [{
1518
+ type: "text",
1519
+ text: `${this.getPersonaIndicator()}❌ Persona not found: ${validatedPersonaName}`
1520
+ }]
1521
+ };
1522
+ }
1523
+ personaName = byFilename.metadata.name;
1524
+ }
1525
+ const result = await this.personaSharer.sharePersona(this.personas.get(personaName), validatedExpiryDays);
1526
+ return {
1527
+ content: [{
1528
+ type: "text",
1529
+ text: `${this.getPersonaIndicator()}${result.message}`
1530
+ }]
1531
+ };
1532
+ }
1533
+ catch (error) {
1534
+ return {
1535
+ content: [{
1536
+ type: "text",
1537
+ text: `${this.getPersonaIndicator()}❌ Share failed: ${SecureErrorHandler.sanitizeError(error).message}`
1538
+ }]
1539
+ };
1540
+ }
1541
+ }
1542
+ /**
1543
+ * Import from a shared URL
1544
+ */
1545
+ async importFromUrl(url, overwrite = false) {
1546
+ try {
1547
+ // Enhanced input validation for URL
1548
+ const validatedUrl = MCPInputValidator.validateImportUrl(url);
1549
+ const fetchResult = await this.personaSharer.importFromUrl(validatedUrl);
1550
+ if (!fetchResult.success) {
1551
+ return {
1552
+ content: [{
1553
+ type: "text",
1554
+ text: `${this.getPersonaIndicator()}❌ ${fetchResult.message}`
1555
+ }]
1556
+ };
1557
+ }
1558
+ // Import the fetched data
1559
+ const importResult = await this.personaImporter.importPersona(JSON.stringify(fetchResult.data), this.personas, overwrite);
1560
+ if (importResult.success) {
1561
+ // Reload personas
1562
+ await this.loadPersonas();
1563
+ return {
1564
+ content: [{
1565
+ type: "text",
1566
+ text: `${this.getPersonaIndicator()}✅ Successfully imported from URL!\n\n${importResult.message}\nTotal personas: ${this.personas.size}`
1567
+ }]
1568
+ };
1569
+ }
1570
+ else {
1571
+ return {
1572
+ content: [{
1573
+ type: "text",
1574
+ text: `${this.getPersonaIndicator()}❌ ${importResult.message}`
1575
+ }]
1576
+ };
1577
+ }
1578
+ }
1579
+ catch (error) {
1580
+ return {
1581
+ content: [{
1582
+ type: "text",
1583
+ text: `${this.getPersonaIndicator()}❌ Import from URL failed: ${SecureErrorHandler.sanitizeError(error).message}`
1584
+ }]
1585
+ };
1586
+ }
1587
+ }
1588
+ async run() {
1589
+ const transport = new StdioServerTransport();
1590
+ logger.info("Starting DollhouseMCP server...");
1591
+ await this.server.connect(transport);
1592
+ // Mark that MCP is now connected - no more console output allowed
1593
+ logger.setMCPConnected();
1594
+ logger.info("DollhouseMCP server running on stdio");
1595
+ }
1596
+ }
1597
+ // Export is already at class declaration
1598
+ // Only start the server if this file is being run directly (not imported by tests)
1599
+ if (import.meta.url === `file://${process.argv[1]}` && !process.env.JEST_WORKER_ID) {
1600
+ const server = new DollhouseMCPServer();
1601
+ server.run().catch((error) => {
1602
+ logger.error("Fatal error starting server", error);
1603
+ process.exit(1);
1604
+ });
1605
+ }
1606
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUVBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUNuRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUNqRixPQUFPLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3pFLE9BQU8sS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBRzdCLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxlQUFlLEVBQUUsb0JBQW9CLEVBQXdCLE1BQU0sOEJBQThCLENBQUM7QUFDaEksT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDbEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzFELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBSWhFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQWdCLGFBQWEsRUFBRSxtQkFBbUIsRUFBRSxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3pLLE9BQU8sRUFBRSxlQUFlLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUMvRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFNUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxnQkFBZ0IsRUFBRSxPQUFPLEVBQUUsTUFB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RixJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLFVBQVUsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUNuRixNQUFNLE1BQU0sR0FBRyxJQUFJLGtCQUFrQixFQUFFLENBQUM7SUFDeEMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1FBQzNCLE1BQU0sQ0FBQyxLQUFLLENBQUMsNkJBQTZCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDbkQsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsQixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIjIS91c3IvYmluL2VudiBub2RlXG5cbmltcG9ydCB7IFNlcnZlciB9IGZyb20gXCJAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NlcnZlci9pbmRleC5qc1wiO1xuaW1wb3J0IHsgU3RkaW9TZXJ2ZXJUcmFuc3BvcnQgfSBmcm9tIFwiQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zZXJ2ZXIvc3RkaW8uanNcIjtcbmltcG9ydCB7IE1jcEVycm9yLCBFcnJvckNvZGUgfSBmcm9tIFwiQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay90eXBlcy5qc1wiO1xuaW1wb3J0ICogYXMgZnMgZnJvbSBcImZzL3Byb21pc2VzXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSBcInVybFwiO1xuaW1wb3J0IG1hdHRlciBmcm9tIFwiZ3JheS1tYXR0ZXJcIjtcbmltcG9ydCB7IGxvYWRJbmRpY2F0b3JDb25maWcsIGZvcm1hdEluZGljYXRvciwgdmFsaWRhdGVDdXN0b21Gb3JtYXQsIHR5cGUgSW5kaWNhdG9yQ29uZmlnIH0gZnJvbSAnLi9jb25maWcvaW5kaWNhdG9yLWNvbmZpZy5qcyc7XG5pbXBvcnQgeyBTZWN1cmVZYW1sUGFyc2VyIH0gZnJvbSAnLi9zZWN1cml0eS9zZWN1cmVZYW1sUGFyc2VyLmpzJztcbmltcG9ydCB7IFNlY3VyaXR5RXJyb3IgfSBmcm9tICcuL2Vycm9ycy9TZWN1cml0eUVycm9yLmpzJztcbmltcG9ydCB7IFNlY3VyZUVycm9ySGFuZGxlciB9IGZyb20gJy4vc2VjdXJpdHkvZXJyb3JIYW5kbGVyLmpzJztcblxuLy8gSW1wb3J0IG1vZHVsYXJpemVkIGNvbXBvbmVudHNcbmltcG9ydCB7IFBlcnNvbmEsIFBlcnNvbmFNZXRhZGF0YSB9IGZyb20gJy4vdHlwZXMvcGVyc29uYS5qcyc7XG5pbXBvcnQgeyBBUElDYWNoZSB9IGZyb20gJy4vY2FjaGUvQVBJQ2FjaGUuanMnO1xuaW1wb3J0IHsgdmFsaWRhdGVGaWxlbmFtZSwgdmFsaWRhdGVQYXRoLCBzYW5pdGl6ZUlucHV0LCB2YWxpZGF0ZUNvbnRlbnRTaXplLCB2YWxpZGF0ZVVzZXJuYW1lLCB2YWxpZGF0ZUNhdGVnb3J5LCBNQ1BJbnB1dFZhbGlkYXRvciB9IGZyb20gJy4vc2VjdXJpdHkvSW5wdXRWYWxpZGF0b3IuanMnO1xuaW1wb3J0IHsgU0VDVVJJVFlfTElNSVRTLCBWQUxJREFUSU9OX1BBVFRFUk5TIH0gZnJvbSAnLi9zZWN1cml0eS9jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgQ29udGVudFZhbGlkYXRvciB9IGZyb20gJy4vc2VjdXJpdHkvY29udGVudFZhbGlkYXRvci5qcyc7XG5pbXBvcnQgeyBQYXRoVmFsaWRhdG9yIH0gZnJvbSAnLi9zZWN1cml0eS9wYXRoVmFsaWRhdG9yLmpzJztcbmltcG9ydCB7IFlhbWxWYWxpZGF0b3IgfSBmcm9tICcuL3NlY3VyaXR5L3lhbWxWYWxpZGF0b3IuanMnO1xuaW1wb3J0IHsgRmlsZUxvY2tNYW5hZ2VyIH0gZnJvbSAnLi9zZWN1cml0eS9maWxlTG9ja01hbmFnZXIuanMnO1xuaW1wb3J0IHsgZ2VuZXJhdGVBbm9ueW1vdXNJZCwgZ2VuZXJhdGVVbmlxdWVJZCwgc2x1Z2lmeSB9IGZyb20gJy4vdXRpbHMvZmlsZXN5c3RlbS5qcyc7XG5pbXBvcnQgeyBQZXJzb25hTWFuYWdlciB9IGZyb20gJy4vcGVyc29uYS9QZXJzb25hTWFuYWdlci5qcyc7XG5pbXBvcnQgeyBHaXRIdWJDbGllbnQsIENvbGxlY3Rpb25Ccm93c2VyLCBDb2xsZWN0aW9uU2VhcmNoLCBQZXJzb25hRGV0YWlscywgUGVyc29uYVN1Ym1pdHRlciwgRWxlbWVudEluc3RhbGxlciB9IGZyb20gJy4vY29sbGVjdGlvbi9pbmRleC5qcyc7XG5pbXBvcnQgeyBVcGRhdGVNYW5hZ2VyIH0gZnJvbSAnLi91cGRhdGUvaW5kZXguanMnO1xuaW1wb3J0IHsgU2VydmVyU2V0dXAsIElUb29sSGFuZGxlciB9IGZyb20gJy4vc2VydmVyL2luZGV4LmpzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4vdXRpbHMvbG9nZ2VyLmpzJztcbmltcG9ydCB7IFBlcnNvbmFFeHBvcnRlciwgUGVyc29uYUltcG9ydGVyLCBQZXJzb25hU2hhcmVyIH0gZnJvbSAnLi9wZXJzb25hL2V4cG9ydC1pbXBvcnQvaW5kZXguanMnO1xuaW1wb3J0IHsgaXNEZWZhdWx0UGVyc29uYSB9IGZyb20gJy4vY29uc3RhbnRzL2RlZmF1bHRQZXJzb25hcy5qcyc7XG5pbXBvcnQgeyBQb3J0Zm9saW9NYW5hZ2VyLCBFbGVtZW50VHlwZSB9IGZyb20gJy4vcG9ydGZvbGlvL1BvcnRmb2xpb01hbmFnZXIuanMnO1xuaW1wb3J0IHsgTWlncmF0aW9uTWFuYWdlciB9IGZyb20gJy4vcG9ydGZvbGlvL01pZ3JhdGlvbk1hbmFnZXIuanMnO1xuXG5cblxuZXhwb3J0IGNsYXNzIERvbGxob3VzZU1DUFNlcnZlciBpbXBsZW1lbnRzIElUb29sSGFuZGxlciB7XG4gIHByaXZhdGUgc2VydmVyOiBTZXJ2ZXI7XG4gIHByaXZhdGUgcGVyc29uYXNEaXI6IHN0cmluZztcbiAgcHJpdmF0ZSBwZXJzb25hczogTWFwPHN0cmluZywgUGVyc29uYT4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgYWN0aXZlUGVyc29uYTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgY3VycmVudFVzZXI6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGFwaUNhY2hlOiBBUElDYWNoZSA9IG5ldyBBUElDYWNoZSgpO1xuICBwcml2YXRlIHJhdGVMaW1pdFRyYWNrZXIgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyW10+KCk7XG4gIHByaXZhdGUgaW5kaWNhdG9yQ29uZmlnOiBJbmRpY2F0b3JDb25maWc7XG4gIHByaXZhdGUgcGVyc29uYU1hbmFnZXI6IFBlcnNvbmFNYW5hZ2VyO1xuICBwcml2YXRlIGdpdGh1YkNsaWVudDogR2l0SHViQ2xpZW50O1xuICBwcml2YXRlIGNvbGxlY3Rpb25Ccm93c2VyOiBDb2xsZWN0aW9uQnJvd3NlcjtcbiAgcHJpdmF0ZSBjb2xsZWN0aW9uU2VhcmNoOiBDb2xsZWN0aW9uU2VhcmNoO1xuICBwcml2YXRlIHBlcnNvbmFEZXRhaWxzOiBQZXJzb25hRGV0YWlscztcbiAgcHJpdmF0ZSBlbGVtZW50SW5zdGFsbGVyOiBFbGVtZW50SW5zdGFsbGVyO1xuICBwcml2YXRlIHBlcnNvbmFTdWJtaXR0ZXI6IFBlcnNvbmFTdWJtaXR0ZXI7XG4gIHByaXZhdGUgdXBkYXRlTWFuYWdlcjogVXBkYXRlTWFuYWdlcjtcbiAgcHJpdmF0ZSBzZXJ2ZXJTZXR1cDogU2VydmVyU2V0dXA7XG4gIHByaXZhdGUgcGVyc29uYUV4cG9ydGVyOiBQZXJzb25hRXhwb3J0ZXI7XG4gIHByaXZhdGUgcGVyc29uYUltcG9ydGVyOiBQZXJzb25hSW1wb3J0ZXI7XG4gIHByaXZhdGUgcGVyc29uYVNoYXJlcjogUGVyc29uYVNoYXJlcjtcbiAgcHJpdmF0ZSBwb3J0Zm9saW9NYW5hZ2VyOiBQb3J0Zm9saW9NYW5hZ2VyO1xuICBwcml2YXRlIG1pZ3JhdGlvbk1hbmFnZXI6IE1pZ3JhdGlvbk1hbmFnZXI7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5zZXJ2ZXIgPSBuZXcgU2VydmVyKFxuICAgICAge1xuICAgICAgICBuYW1lOiBcImRvbGxob3VzZW1jcFwiLFxuICAgICAgICB2ZXJzaW9uOiBcIjEuMC4wXCIsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBjYXBhYmlsaXRpZXM6IHtcbiAgICAgICAgICB0b29sczoge30sXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgKTtcblxuICAgIC8vIEluaXRpYWxpemUgcG9ydGZvbGlvIHN5c3RlbVxuICAgIHRoaXMucG9ydGZvbGlvTWFuYWdlciA9IFBvcnRmb2xpb01hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcbiAgICB0aGlzLm1pZ3JhdGlvbk1hbmFnZXIgPSBuZXcgTWlncmF0aW9uTWFuYWdlcih0aGlzLnBvcnRmb2xpb01hbmFnZXIpO1xuICAgIFxuICAgIC8vIFVzZSBwb3J0Zm9saW8gcGVyc29uYXMgZGlyZWN0b3J5XG4gICAgdGhpcy5wZXJzb25hc0RpciA9IHRoaXMucG9ydGZvbGlvTWFuYWdlci5nZXRFbGVtZW50RGlyKEVsZW1lbnRUeXBlLlBFUlNPTkEpO1xuICAgIFxuICAgIC8vIExvZyByZXNvbHZlZCBwYXRoIGZvciBkZWJ1Z2dpbmdcbiAgICBsb2dnZXIuaW5mbyhgUGVyc29uYXMgZGlyZWN0b3J5IHJlc29sdmVkIHRvOiAke3RoaXMucGVyc29uYXNEaXJ9YCk7XG4gICAgXG4gICAgLy8gSW5pdGlhbGl6ZSBQYXRoVmFsaWRhdG9yIHdpdGggdGhlIHBlcnNvbmFzIGRpcmVjdG9yeVxuICAgIFBhdGhWYWxpZGF0b3IuaW5pdGlhbGl6ZSh0aGlzLnBlcnNvbmFzRGlyKTtcbiAgICBcbiAgICAvLyBMb2FkIHVzZXIgaWRlbnRpdHkgZnJvbSBlbnZpcm9ubWVudCB2YXJpYWJsZXNcbiAgICB0aGlzLmN1cnJlbnRVc2VyID0gcHJvY2Vzcy5lbnYuRE9MTEhPVVNFX1VTRVIgfHwgbnVsbDtcbiAgICBcbiAgICAvLyBMb2FkIGluZGljYXRvciBjb25maWd1cmF0aW9uXG4gICAgdGhpcy5pbmRpY2F0b3JDb25maWcgPSBsb2FkSW5kaWNhdG9yQ29uZmlnKCk7XG4gICAgXG4gICAgLy8gSW5pdGlhbGl6ZSBwZXJzb25hIG1hbmFnZXJcbiAgICB0aGlzLnBlcnNvbmFNYW5hZ2VyID0gbmV3IFBlcnNvbmFNYW5hZ2VyKHRoaXMucGVyc29uYXNEaXIsIHRoaXMuaW5kaWNhdG9yQ29uZmlnKTtcbiAgICBcbiAgICAvLyBJbml0aWFsaXplIGNvbGxlY3Rpb24gbW9kdWxlc1xuICAgIHRoaXMuZ2l0aHViQ2xpZW50ID0gbmV3IEdpdEh1YkNsaWVudCh0aGlzLmFwaUNhY2hlLCB0aGlzLnJhdGVMaW1pdFRyYWNrZXIpO1xuICAgIHRoaXMuY29sbGVjdGlvbkJyb3dzZXIgPSBuZXcgQ29sbGVjdGlvbkJyb3dzZXIodGhpcy5naXRodWJDbGllbnQpO1xuICAgIHRoaXMuY29sbGVjdGlvblNlYXJjaCA9IG5ldyBDb2xsZWN0aW9uU2VhcmNoKHRoaXMuZ2l0aHViQ2xpZW50KTtcbiAgICB0aGlzLnBlcnNvbmFEZXRhaWxzID0gbmV3IFBlcnNvbmFEZXRhaWxzKHRoaXMuZ2l0aHViQ2xpZW50KTtcbiAgICB0aGlzLmVsZW1lbnRJbnN0YWxsZXIgPSBuZXcgRWxlbWVudEluc3RhbGxlcih0aGlzLmdpdGh1YkNsaWVudCk7XG4gICAgdGhpcy5wZXJzb25hU3VibWl0dGVyID0gbmV3IFBlcnNvbmFTdWJtaXR0ZXIoKTtcbiAgICBcbiAgICAvLyBJbml0aWFsaXplIHVwZGF0ZSBtYW5hZ2VyXG4gICAgdGhpcy51cGRhdGVNYW5hZ2VyID0gbmV3IFVwZGF0ZU1hbmFnZXIoKTtcbiAgICBcbiAgICAvLyBJbml0aWFsaXplIGV4cG9ydC9pbXBvcnQvc2hhcmUgbW9kdWxlc1xuICAgIHRoaXMucGVyc29uYUV4cG9ydGVyID0gbmV3IFBlcnNvbmFFeHBvcnRlcih0aGlzLmN1cnJlbnRVc2VyKTtcbiAgICB0aGlzLnBlcnNvbmFJbXBvcnRlciA9IG5ldyBQZXJzb25hSW1wb3J0ZXIodGhpcy5wZXJzb25hc0RpciwgdGhpcy5jdXJyZW50VXNlcik7XG4gICAgdGhpcy5wZXJzb25hU2hhcmVyID0gbmV3IFBlcnNvbmFTaGFyZXIodGhpcy5naXRodWJDbGllbnQsIHRoaXMuY3VycmVudFVzZXIpO1xuICAgIFxuICAgIC8vIEluaXRpYWxpemUgc2VydmVyIHNldHVwXG4gICAgdGhpcy5zZXJ2ZXJTZXR1cCA9IG5ldyBTZXJ2ZXJTZXR1cCgpO1xuICAgIHRoaXMuc2VydmVyU2V0dXAuc2V0dXBTZXJ2ZXIodGhpcy5zZXJ2ZXIsIHRoaXMpO1xuICAgIFxuICAgIC8vIEluaXRpYWxpemUgcG9ydGZvbGlvIGFuZCBwZXJmb3JtIG1pZ3JhdGlvbiBpZiBuZWVkZWRcbiAgICB0aGlzLmluaXRpYWxpemVQb3J0Zm9saW8oKS50aGVuKCgpID0+IHtcbiAgICAgIHRoaXMubG9hZFBlcnNvbmFzKCk7XG4gICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgbG9nZ2VyLmVycm9yKGBGYWlsZWQgdG8gaW5pdGlhbGl6ZSBwb3J0Zm9saW86ICR7ZXJyb3J9YCk7XG4gICAgfSk7XG4gIH1cbiAgXG4gIHByaXZhdGUgYXN5bmMgaW5pdGlhbGl6ZVBvcnRmb2xpbygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBDaGVjayBpZiBtaWdyYXRpb24gaXMgbmVlZGVkXG4gICAgY29uc3QgbmVlZHNNaWdyYXRpb24gPSBhd2FpdCB0aGlzLm1pZ3JhdGlvbk1hbmFnZXIubmVlZHNNaWdyYXRpb24oKTtcbiAgICBcbiAgICBpZiAobmVlZHNNaWdyYXRpb24pIHtcbiAgICAgIGxvZ2dlci5pbmZvKCdMZWdhY3kgcGVyc29uYXMgZGV0ZWN0ZWQuIFN0YXJ0aW5nIG1pZ3JhdGlvbi4uLicpO1xuICAgICAgXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLm1pZ3JhdGlvbk1hbmFnZXIubWlncmF0ZSh7IGJhY2t1cDogdHJ1ZSB9KTtcbiAgICAgIFxuICAgICAgaWYgKHJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKGBTdWNjZXNzZnVsbHkgbWlncmF0ZWQgJHtyZXN1bHQubWlncmF0ZWRDb3VudH0gcGVyc29uYXNgKTtcbiAgICAgICAgaWYgKHJlc3VsdC5iYWNrZWRVcCAmJiByZXN1bHQuYmFja3VwUGF0aCkge1xuICAgICAgICAgIGxvZ2dlci5pbmZvKGBCYWNrdXAgY3JlYXRlZCBhdDogJHtyZXN1bHQuYmFja3VwUGF0aH1gKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKCdNaWdyYXRpb24gY29tcGxldGVkIHdpdGggZXJyb3JzOicpO1xuICAgICAgICByZXN1bHQuZXJyb3JzLmZvckVhY2goZXJyID0+IGxvZ2dlci5lcnJvcihgICAtICR7ZXJyfWApKTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgLy8gRW5zdXJlIHBvcnRmb2xpbyBzdHJ1Y3R1cmUgZXhpc3RzXG4gICAgY29uc3QgcG9ydGZvbGlvRXhpc3RzID0gYXdhaXQgdGhpcy5wb3J0Zm9saW9NYW5hZ2VyLmV4aXN0cygpO1xuICAgIGlmICghcG9ydGZvbGlvRXhpc3RzKSB7XG4gICAgICBsb2dnZXIuaW5mbygnQ3JlYXRpbmcgcG9ydGZvbGlvIGRpcmVjdG9yeSBzdHJ1Y3R1cmUuLi4nKTtcbiAgICAgIGF3YWl0IHRoaXMucG9ydGZvbGlvTWFuYWdlci5pbml0aWFsaXplKCk7XG4gICAgfVxuICB9XG5cbiAgLy8gVG9vbCBoYW5kbGVyIG1ldGhvZHMgLSBub3cgcHVibGljIGZvciBhY2Nlc3MgZnJvbSB0b29sIG1vZHVsZXNcbiAgXG4gIHByaXZhdGUgZ2V0UGVyc29uYUluZGljYXRvcigpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5hY3RpdmVQZXJzb25hKSB7XG4gICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG5cbiAgICBjb25zdCBwZXJzb25hID0gdGhpcy5wZXJzb25hcy5nZXQodGhpcy5hY3RpdmVQZXJzb25hKTtcbiAgICBpZiAoIXBlcnNvbmEpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBmb3JtYXRJbmRpY2F0b3IodGhpcy5pbmRpY2F0b3JDb25maWcsIHtcbiAgICAgIG5hbWU6IHBlcnNvbmEubWV0YWRhdGEubmFtZSxcbiAgICAgIHZlcnNpb246IHBlcnNvbmEubWV0YWRhdGEudmVyc2lvbixcbiAgICAgIGF1dGhvcjogcGVyc29uYS5tZXRhZGF0YS5hdXRob3IsXG4gICAgICBjYXRlZ29yeTogcGVyc29uYS5tZXRhZGF0YS5jYXRlZ29yeVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBsb2FkUGVyc29uYXMoKSB7XG4gICAgLy8gVmFsaWRhdGUgdGhlIHBlcnNvbmFzIGRpcmVjdG9yeSBwYXRoXG4gICAgaWYgKCFwYXRoLmlzQWJzb2x1dGUodGhpcy5wZXJzb25hc0RpcikpIHtcbiAgICAgIGxvZ2dlci53YXJuKGBQZXJzb25hcyBkaXJlY3RvcnkgcGF0aCBpcyBub3QgYWJzb2x1dGU6ICR7dGhpcy5wZXJzb25hc0Rpcn1gKTtcbiAgICB9XG4gICAgXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGZzLmFjY2Vzcyh0aGlzLnBlcnNvbmFzRGlyKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgLy8gQ3JlYXRlIHBlcnNvbmFzIGRpcmVjdG9yeSBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBmcy5ta2Rpcih0aGlzLnBlcnNvbmFzRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgbG9nZ2VyLmluZm8oYENyZWF0ZWQgcGVyc29uYXMgZGlyZWN0b3J5IGF0OiAke3RoaXMucGVyc29uYXNEaXJ9YCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gY2F0Y2ggKG1rZGlyRXJyb3I6IGFueSkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoYEZhaWxlZCB0byBjcmVhdGUgcGVyc29uYXMgZGlyZWN0b3J5IGF0ICR7dGhpcy5wZXJzb25hc0Rpcn06ICR7bWtkaXJFcnJvci5tZXNzYWdlfWApO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBjcmVhdGUgcGVyc29uYXMgZGlyZWN0b3J5OiAke21rZGlyRXJyb3IubWVzc2FnZX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZmlsZXMgPSBhd2FpdCBmcy5yZWFkZGlyKHRoaXMucGVyc29uYXNEaXIpO1xuICAgICAgY29uc3QgbWFya2Rvd25GaWxlcyA9IGZpbGVzLmZpbHRlcihmaWxlID0+IGZpbGUuZW5kc1dpdGgoJy5tZCcpKTtcblxuICAgICAgdGhpcy5wZXJzb25hcy5jbGVhcigpO1xuXG4gICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgbWFya2Rvd25GaWxlcykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5qb2luKHRoaXMucGVyc29uYXNEaXIsIGZpbGUpO1xuICAgICAgICAgIGNvbnN0IGZpbGVDb250ZW50ID0gYXdhaXQgUGF0aFZhbGlkYXRvci5zYWZlUmVhZEZpbGUoZmlsZVBhdGgpO1xuICAgICAgICAgIFxuICAgICAgICAgIC8vIFVzZSBzZWN1cmUgWUFNTCBwYXJzZXJcbiAgICAgICAgICBsZXQgcGFyc2VkO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBwYXJzZWQgPSBTZWN1cmVZYW1sUGFyc2VyLnNhZmVNYXR0ZXIoZmlsZUNvbnRlbnQpO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBTZWN1cml0eUVycm9yKSB7XG4gICAgICAgICAgICAgIGxvZ2dlci53YXJuKGBTZWN1cml0eSB0aHJlYXQgZGV0ZWN0ZWQgaW4gcGVyc29uYSAke2ZpbGV9OiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgfVxuICAgICAgICAgIFxuICAgICAgICAgIGNvbnN0IG1ldGFkYXRhID0gcGFyc2VkLmRhdGEgYXMgUGVyc29uYU1ldGFkYXRhO1xuICAgICAgICAgIGNvbnN0IGNvbnRlbnQgPSBwYXJzZWQuY29udGVudDtcblxuICAgICAgICAgIGlmICghbWV0YWRhdGEubmFtZSkge1xuICAgICAgICAgICAgbWV0YWRhdGEubmFtZSA9IHBhdGguYmFzZW5hbWUoZmlsZSwgJy5tZCcpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIEdlbmVyYXRlIHVuaXF1ZSBJRCBpZiBub3QgcHJlc2VudFxuICAgICAgICAgIGxldCB1bmlxdWVJZCA9IG1ldGFkYXRhLnVuaXF1ZV9pZDtcbiAgICAgICAgICBpZiAoIXVuaXF1ZUlkKSB7XG4gICAgICAgICAgICBjb25zdCBhdXRob3JGb3JJZCA9IG1ldGFkYXRhLmF1dGhvciB8fCB0aGlzLmdldEN1cnJlbnRVc2VyRm9yQXR0cmlidXRpb24oKTtcbiAgICAgICAgICAgIHVuaXF1ZUlkID0gZ2VuZXJhdGVVbmlxdWVJZChtZXRhZGF0YS5uYW1lLCBhdXRob3JGb3JJZCk7XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoYEdlbmVyYXRlZCB1bmlxdWUgSUQgZm9yICR7bWV0YWRhdGEubmFtZX06ICR7dW5pcXVlSWR9YCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gU2V0IGRlZmF1bHQgdmFsdWVzIGZvciBuZXcgbWV0YWRhdGEgZmllbGRzXG4gICAgICAgICAgaWYgKCFtZXRhZGF0YS5jYXRlZ29yeSkgbWV0YWRhdGEuY2F0ZWdvcnkgPSAnZ2VuZXJhbCc7XG4gICAgICAgICAgaWYgKCFtZXRhZGF0YS5hZ2VfcmF0aW5nKSBtZXRhZGF0YS5hZ2VfcmF0aW5nID0gJ2FsbCc7XG4gICAgICAgICAgaWYgKCFtZXRhZGF0YS5jb250ZW50X2ZsYWdzKSBtZXRhZGF0YS5jb250ZW50X2ZsYWdzID0gW107XG4gICAgICAgICAgaWYgKG1ldGFkYXRhLmFpX2dlbmVyYXRlZCA9PT0gdW5kZWZpbmVkKSBtZXRhZGF0YS5haV9nZW5lcmF0ZWQgPSBmYWxzZTtcbiAgICAgICAgICBpZiAoIW1ldGFkYXRhLmdlbmVyYXRpb25fbWV0aG9kKSBtZXRhZGF0YS5nZW5lcmF0aW9uX21ldGhvZCA9ICdodW1hbic7XG4gICAgICAgICAgaWYgKCFtZXRhZGF0YS5wcmljZSkgbWV0YWRhdGEucHJpY2UgPSAnZnJlZSc7XG4gICAgICAgICAgaWYgKCFtZXRhZGF0YS5saWNlbnNlKSBtZXRhZGF0YS5saWNlbnNlID0gJ0NDLUJZLVNBLTQuMCc7XG5cbiAgICAgICAgICBjb25zdCBwZXJzb25hOiBQZXJzb25hID0ge1xuICAgICAgICAgICAgbWV0YWRhdGEsXG4gICAgICAgICAgICBjb250ZW50LFxuICAgICAgICAgICAgZmlsZW5hbWU6IGZpbGUsXG4gICAgICAgICAgICB1bmlxdWVfaWQ6IHVuaXF1ZUlkLFxuICAgICAgICAgIH07XG5cbiAgICAgICAgICB0aGlzLnBlcnNvbmFzLnNldChmaWxlLCBwZXJzb25hKTtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoYExvYWRlZCBwZXJzb25hOiAke21ldGFkYXRhLm5hbWV9ICgke3VuaXF1ZUlkfWApO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGxvZ2dlci5lcnJvcihgRXJyb3IgbG9hZGluZyBwZXJzb25hICR7ZmlsZX06ICR7ZXJyb3J9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmVycm9yKGBFcnJvciByZWFkaW5nIHBlcnNvbmFzIGRpcmVjdG9yeTogJHtlcnJvcn1gKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBsaXN0UGVyc29uYXMoKSB7XG4gICAgY29uc3QgcGVyc29uYUxpc3QgPSBBcnJheS5mcm9tKHRoaXMucGVyc29uYXMudmFsdWVzKCkpLm1hcChwZXJzb25hID0+ICh7XG4gICAgICBmaWxlbmFtZTogcGVyc29uYS5maWxlbmFtZSxcbiAgICAgIHVuaXF1ZV9pZDogcGVyc29uYS51bmlxdWVfaWQsXG4gICAgICBuYW1lOiBwZXJzb25hLm1ldGFkYXRhLm5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogcGVyc29uYS5tZXRhZGF0YS5kZXNjcmlwdGlvbixcbiAgICAgIHRyaWdnZXJzOiBwZXJzb25hLm1ldGFkYXRhLnRyaWdnZXJzIHx8IFtdLFxuICAgICAgdmVyc2lvbjogcGVyc29uYS5tZXRhZGF0YS52ZXJzaW9uIHx8IFwiMS4wXCIsXG4gICAgICBhdXRob3I6IHBlcnNvbmEubWV0YWRhdGEuYXV0aG9yIHx8IFwiVW5rbm93blwiLFxuICAgICAgY2F0ZWdvcnk6IHBlcnNvbmEubWV0YWRhdGEuY2F0ZWdvcnkgfHwgJ2dlbmVyYWwnLFxuICAgICAgYWdlX3JhdGluZzogcGVyc29uYS5tZXRhZGF0YS5hZ2VfcmF0aW5nIHx8ICdhbGwnLFxuICAgICAgcHJpY2U6IHBlcnNvbmEubWV0YWRhdGEucHJpY2UgfHwgJ2ZyZWUnLFxuICAgICAgYWlfZ2VuZXJhdGVkOiBwZXJzb25hLm1ldGFkYXRhLmFpX2dlbmVyYXRlZCB8fCBmYWxzZSxcbiAgICAgIGFjdGl2ZTogdGhpcy5hY3RpdmVQZXJzb25hID09PSBwZXJzb25hLmZpbGVuYW1lLFxuICAgIH0pKTtcblxuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX1BdmFpbGFibGUgUGVyc29uYXMgKCR7cGVyc29uYUxpc3QubGVuZ3RofSk6XFxuXFxuYCArXG4gICAgICAgICAgICBwZXJzb25hTGlzdC5tYXAocCA9PiBcbiAgICAgICAgICAgICAgYCR7cC5hY3RpdmUgPyAn8J+UuSAnIDogJ+KWq++4jyAnfSoqJHtwLm5hbWV9KiogKCR7cC51bmlxdWVfaWR9KVxcbmAgK1xuICAgICAgICAgICAgICBgICAgJHtwLmRlc2NyaXB0aW9ufVxcbmAgK1xuICAgICAgICAgICAgICBgICAg8J+TgSAke3AuY2F0ZWdvcnl9IHwg8J+OrSAke3AuYXV0aG9yfSB8IPCflJYgJHtwLnByaWNlfSB8ICR7cC5haV9nZW5lcmF0ZWQgPyAn8J+kliBBSScgOiAn8J+RpCBIdW1hbid9XFxuYCArXG4gICAgICAgICAgICAgIGAgICBBZ2U6ICR7cC5hZ2VfcmF0aW5nfSB8IFZlcnNpb246ICR7cC52ZXJzaW9ufVxcbmAgK1xuICAgICAgICAgICAgICBgICAgVHJpZ2dlcnM6ICR7cC50cmlnZ2Vycy5qb2luKCcsICcpIHx8ICdOb25lJ31cXG5gXG4gICAgICAgICAgICApLmpvaW4oJ1xcbicpLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgYWN0aXZhdGVQZXJzb25hKHBlcnNvbmFJZGVudGlmaWVyOiBzdHJpbmcpIHtcbiAgICAvLyBFbmhhbmNlZCBpbnB1dCB2YWxpZGF0aW9uIGZvciBwZXJzb25hIGlkZW50aWZpZXJcbiAgICBjb25zdCB2YWxpZGF0ZWRJZGVudGlmaWVyID0gTUNQSW5wdXRWYWxpZGF0b3IudmFsaWRhdGVQZXJzb25hSWRlbnRpZmllcihwZXJzb25hSWRlbnRpZmllcik7XG4gICAgXG4gICAgLy8gVHJ5IHRvIGZpbmQgcGVyc29uYSBieSBmaWxlbmFtZSBmaXJzdCwgdGhlbiBieSBuYW1lXG4gICAgbGV0IHBlcnNvbmEgPSB0aGlzLnBlcnNvbmFzLmdldCh2YWxpZGF0ZWRJZGVudGlmaWVyKTtcbiAgICBcbiAgICBpZiAoIXBlcnNvbmEpIHtcbiAgICAgIC8vIFNlYXJjaCBieSBuYW1lXG4gICAgICBwZXJzb25hID0gQXJyYXkuZnJvbSh0aGlzLnBlcnNvbmFzLnZhbHVlcygpKS5maW5kKHAgPT4gXG4gICAgICAgIHAubWV0YWRhdGEubmFtZS50b0xvd2VyQ2FzZSgpID09PSB2YWxpZGF0ZWRJZGVudGlmaWVyLnRvTG93ZXJDYXNlKClcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKCFwZXJzb25hKSB7XG4gICAgICB0aHJvdyBuZXcgTWNwRXJyb3IoXG4gICAgICAgIEVycm9yQ29kZS5JbnZhbGlkUGFyYW1zLFxuICAgICAgICBgUGVyc29uYSBub3QgZm91bmQ6ICR7cGVyc29uYUlkZW50aWZpZXJ9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLmFjdGl2ZVBlcnNvbmEgPSBwZXJzb25hLmZpbGVuYW1lO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfVBlcnNvbmEgQWN0aXZhdGVkOiAqKiR7cGVyc29uYS5tZXRhZGF0YS5uYW1lfSoqXFxuXFxuYCArXG4gICAgICAgICAgICBgJHtwZXJzb25hLm1ldGFkYXRhLmRlc2NyaXB0aW9ufVxcblxcbmAgK1xuICAgICAgICAgICAgYCoqSW5zdHJ1Y3Rpb25zOioqXFxuJHtwZXJzb25hLmNvbnRlbnR9YCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGdldEFjdGl2ZVBlcnNvbmEoKSB7XG4gICAgaWYgKCF0aGlzLmFjdGl2ZVBlcnNvbmEpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfU5vIHBlcnNvbmEgaXMgY3VycmVudGx5IGFjdGl2ZS5gLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHBlcnNvbmEgPSB0aGlzLnBlcnNvbmFzLmdldCh0aGlzLmFjdGl2ZVBlcnNvbmEpO1xuICAgIGlmICghcGVyc29uYSkge1xuICAgICAgdGhpcy5hY3RpdmVQZXJzb25hID0gbnVsbDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfUFjdGl2ZSBwZXJzb25hIG5vdCBmb3VuZC4gRGVhY3RpdmF0ZWQuYCxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogW1xuICAgICAgICB7XG4gICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl9QWN0aXZlIFBlcnNvbmE6ICoqJHtwZXJzb25hLm1ldGFkYXRhLm5hbWV9KipcXG5cXG5gICtcbiAgICAgICAgICAgIGAke3BlcnNvbmEubWV0YWRhdGEuZGVzY3JpcHRpb259XFxuXFxuYCArXG4gICAgICAgICAgICBgRmlsZTogJHtwZXJzb25hLmZpbGVuYW1lfVxcbmAgK1xuICAgICAgICAgICAgYFZlcnNpb246ICR7cGVyc29uYS5tZXRhZGF0YS52ZXJzaW9uIHx8ICcxLjAnfVxcbmAgK1xuICAgICAgICAgICAgYEF1dGhvcjogJHtwZXJzb25hLm1ldGFkYXRhLmF1dGhvciB8fCAnVW5rbm93bid9YCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGRlYWN0aXZhdGVQZXJzb25hKCkge1xuICAgIGNvbnN0IHdhc0FjdGl2ZSA9IHRoaXMuYWN0aXZlUGVyc29uYSAhPT0gbnVsbDtcbiAgICBjb25zdCBpbmRpY2F0b3IgPSB0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKTtcbiAgICB0aGlzLmFjdGl2ZVBlcnNvbmEgPSBudWxsO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IHdhc0FjdGl2ZSBcbiAgICAgICAgICAgID8gYCR7aW5kaWNhdG9yfeKchSBQZXJzb25hIGRlYWN0aXZhdGVkLiBCYWNrIHRvIGRlZmF1bHQgbW9kZS5gXG4gICAgICAgICAgICA6IFwiTm8gcGVyc29uYSB3YXMgYWN0aXZlLlwiLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgZ2V0UGVyc29uYURldGFpbHMocGVyc29uYUlkZW50aWZpZXI6IHN0cmluZykge1xuICAgIC8vIFRyeSB0byBmaW5kIHBlcnNvbmEgYnkgZmlsZW5hbWUgZmlyc3QsIHRoZW4gYnkgbmFtZVxuICAgIGxldCBwZXJzb25hID0gdGhpcy5wZXJzb25hcy5nZXQocGVyc29uYUlkZW50aWZpZXIpO1xuICAgIFxuICAgIGlmICghcGVyc29uYSkge1xuICAgICAgLy8gU2VhcmNoIGJ5IG5hbWVcbiAgICAgIHBlcnNvbmEgPSBBcnJheS5mcm9tKHRoaXMucGVyc29uYXMudmFsdWVzKCkpLmZpbmQocCA9PiBcbiAgICAgICAgcC5tZXRhZGF0YS5uYW1lLnRvTG93ZXJDYXNlKCkgPT09IHBlcnNvbmFJZGVudGlmaWVyLnRvTG93ZXJDYXNlKClcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKCFwZXJzb25hKSB7XG4gICAgICB0aHJvdyBuZXcgTWNwRXJyb3IoXG4gICAgICAgIEVycm9yQ29kZS5JbnZhbGlkUGFyYW1zLFxuICAgICAgICBgUGVyc29uYSBub3QgZm91bmQ6ICR7cGVyc29uYUlkZW50aWZpZXJ9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogW1xuICAgICAgICB7XG4gICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl98J+TiyAqKiR7cGVyc29uYS5tZXRhZGF0YS5uYW1lfSoqIERldGFpbHNcXG5cXG5gICtcbiAgICAgICAgICAgIGAqKkRlc2NyaXB0aW9uOioqICR7cGVyc29uYS5tZXRhZGF0YS5kZXNjcmlwdGlvbn1cXG5gICtcbiAgICAgICAgICAgIGAqKkZpbGU6KiogJHtwZXJzb25hLmZpbGVuYW1lfVxcbmAgK1xuICAgICAgICAgICAgYCoqVmVyc2lvbjoqKiAke3BlcnNvbmEubWV0YWRhdGEudmVyc2lvbiB8fCAnMS4wJ31cXG5gICtcbiAgICAgICAgICAgIGAqKkF1dGhvcjoqKiAke3BlcnNvbmEubWV0YWRhdGEuYXV0aG9yIHx8ICdVbmtub3duJ31cXG5gICtcbiAgICAgICAgICAgIGAqKlRyaWdnZXJzOioqICR7cGVyc29uYS5tZXRhZGF0YS50cmlnZ2Vycz8uam9pbignLCAnKSB8fCAnTm9uZSd9XFxuXFxuYCArXG4gICAgICAgICAgICBgKipGdWxsIENvbnRlbnQ6KipcXG5cXGBcXGBcXGBcXG4ke3BlcnNvbmEuY29udGVudH1cXG5cXGBcXGBcXGBgLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgcmVsb2FkUGVyc29uYXMoKSB7XG4gICAgYXdhaXQgdGhpcy5sb2FkUGVyc29uYXMoKTtcbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogW1xuICAgICAgICB7XG4gICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl98J+UhCBSZWxvYWRlZCAke3RoaXMucGVyc29uYXMuc2l6ZX0gcGVyc29uYXMgZnJvbSAke3RoaXMucGVyc29uYXNEaXJ9YCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuXG4gIC8vIGNoZWNrUmF0ZUxpbWl0IGFuZCBmZXRjaEZyb21HaXRIdWIgYXJlIG5vdyBoYW5kbGVkIGJ5IEdpdEh1YkNsaWVudFxuXG4gIGFzeW5jIGJyb3dzZUNvbGxlY3Rpb24oc2VjdGlvbj86IHN0cmluZywgdHlwZT86IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICAvLyBFbmhhbmNlZCBpbnB1dCB2YWxpZGF0aW9uIGZvciBzZWN0aW9uIGFuZCB0eXBlXG4gICAgICBjb25zdCB2YWxpZGF0ZWRTZWN0aW9uID0gc2VjdGlvbiA/IHZhbGlkYXRlQ2F0ZWdvcnkoc2VjdGlvbikgOiB1bmRlZmluZWQ7XG4gICAgICBjb25zdCB2YWxpZGF0ZWRUeXBlID0gdHlwZSA/IHZhbGlkYXRlQ2F0ZWdvcnkodHlwZSkgOiB1bmRlZmluZWQ7XG4gICAgICBcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuY29sbGVjdGlvbkJyb3dzZXIuYnJvd3NlQ29sbGVjdGlvbih2YWxpZGF0ZWRTZWN0aW9uLCB2YWxpZGF0ZWRUeXBlKTtcbiAgICAgIFxuICAgICAgLy8gSGFuZGxlIHNlY3Rpb25zIHZpZXdcbiAgICAgIGNvbnN0IGl0ZW1zID0gcmVzdWx0Lml0ZW1zO1xuICAgICAgY29uc3QgY2F0ZWdvcmllcyA9IHJlc3VsdC5zZWN0aW9ucyB8fCByZXN1bHQuY2F0ZWdvcmllcztcbiAgICAgIFxuICAgICAgY29uc3QgdGV4dCA9IHRoaXMuY29sbGVjdGlvbkJyb3dzZXIuZm9ybWF0QnJvd3NlUmVzdWx0cyhcbiAgICAgICAgaXRlbXMsIFxuICAgICAgICBjYXRlZ29yaWVzLCBcbiAgICAgICAgdmFsaWRhdGVkU2VjdGlvbiwgXG4gICAgICAgIHZhbGlkYXRlZFR5cGUsIFxuICAgICAgICB0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKVxuICAgICAgKTtcbiAgICAgIFxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogdGV4dCxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc3Qgc2FuaXRpemVkID0gU2VjdXJlRXJyb3JIYW5kbGVyLnNhbml0aXplRXJyb3IoZXJyb3IpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94p2MIENvbGxlY3Rpb24gYnJvd3NpbmcgZmFpbGVkOiAke3Nhbml0aXplZC5tZXNzYWdlfWAsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgc2VhcmNoQ29sbGVjdGlvbihxdWVyeTogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIEVuaGFuY2VkIGlucHV0IHZhbGlkYXRpb24gZm9yIHNlYXJjaCBxdWVyeVxuICAgICAgY29uc3QgdmFsaWRhdGVkUXVlcnkgPSBNQ1BJbnB1dFZhbGlkYXRvci52YWxpZGF0ZVNlYXJjaFF1ZXJ5KHF1ZXJ5KTtcbiAgICAgIFxuICAgICAgY29uc3QgaXRlbXMgPSBhd2FpdCB0aGlzLmNvbGxlY3Rpb25TZWFyY2guc2VhcmNoQ29sbGVjdGlvbih2YWxpZGF0ZWRRdWVyeSk7XG4gICAgICBjb25zdCB0ZXh0ID0gdGhpcy5jb2xsZWN0aW9uU2VhcmNoLmZvcm1hdFNlYXJjaFJlc3VsdHMoaXRlbXMsIHZhbGlkYXRlZFF1ZXJ5LCB0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKSk7XG4gICAgICBcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgIHRleHQ6IHRleHQsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnN0IHNhbml0aXplZCA9IFNlY3VyZUVycm9ySGFuZGxlci5zYW5pdGl6ZUVycm9yKGVycm9yKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfeKdjCBFcnJvciBzZWFyY2hpbmcgY29sbGVjdGlvbjogJHtzYW5pdGl6ZWQubWVzc2FnZX1gLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGdldENvbGxlY3Rpb25Db250ZW50KHBhdGg6IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IG1ldGFkYXRhLCBjb250ZW50IH0gPSBhd2FpdCB0aGlzLnBlcnNvbmFEZXRhaWxzLmdldENvbGxlY3Rpb25Db250ZW50KHBhdGgpO1xuICAgICAgY29uc3QgdGV4dCA9IHRoaXMucGVyc29uYURldGFpbHMuZm9ybWF0UGVyc29uYURldGFpbHMobWV0YWRhdGEsIGNvbnRlbnQsIHBhdGgsIHRoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpKTtcbiAgICAgIFxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogdGV4dCxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc3Qgc2FuaXRpemVkID0gU2VjdXJlRXJyb3JIYW5kbGVyLnNhbml0aXplRXJyb3IoZXJyb3IpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94p2MIEVycm9yIGZldGNoaW5nIGNvbnRlbnQ6ICR7c2FuaXRpemVkLm1lc3NhZ2V9YCxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBpbnN0YWxsQ29udGVudChpbnB1dFBhdGg6IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmVsZW1lbnRJbnN0YWxsZXIuaW5zdGFsbENvbnRlbnQoaW5wdXRQYXRoKTtcbiAgICAgIFxuICAgICAgaWYgKCFyZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICAgIHRleHQ6IGDimqDvuI8gJHtyZXN1bHQubWVzc2FnZX1gLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBJZiBpdCdzIGEgcGVyc29uYSwgcmVsb2FkIHBlcnNvbmFzXG4gICAgICBpZiAocmVzdWx0LmVsZW1lbnRUeXBlID09PSBFbGVtZW50VHlwZS5QRVJTT05BKSB7XG4gICAgICAgIGF3YWl0IHRoaXMubG9hZFBlcnNvbmFzKCk7XG4gICAgICB9XG4gICAgICBcbiAgICAgIGNvbnN0IHRleHQgPSB0aGlzLmVsZW1lbnRJbnN0YWxsZXIuZm9ybWF0SW5zdGFsbFN1Y2Nlc3MoXG4gICAgICAgIHJlc3VsdC5tZXRhZGF0YSEsIFxuICAgICAgICByZXN1bHQuZmlsZW5hbWUhLFxuICAgICAgICByZXN1bHQuZWxlbWVudFR5cGUhXG4gICAgICApO1xuICAgICAgXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiB0ZXh0LFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zdCBzYW5pdGl6ZWQgPSBTZWN1cmVFcnJvckhhbmRsZXIuc2FuaXRpemVFcnJvcihlcnJvcik7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3inYwgRXJyb3IgaW5zdGFsbGluZyBBSSBjdXN0b21pemF0aW9uIGVsZW1lbnQ6ICR7c2FuaXRpemVkLm1lc3NhZ2V9YCxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBzdWJtaXRDb250ZW50KGNvbnRlbnRJZGVudGlmaWVyOiBzdHJpbmcpIHtcbiAgICAvLyBGaW5kIHRoZSBjb250ZW50IGluIGxvY2FsIGNvbGxlY3Rpb25cbiAgICBsZXQgcGVyc29uYSA9IHRoaXMucGVyc29uYXMuZ2V0KGNvbnRlbnRJZGVudGlmaWVyKTtcbiAgICBcbiAgICBpZiAoIXBlcnNvbmEpIHtcbiAgICAgIC8vIFNlYXJjaCBieSBuYW1lXG4gICAgICBwZXJzb25hID0gQXJyYXkuZnJvbSh0aGlzLnBlcnNvbmFzLnZhbHVlcygpKS5maW5kKHAgPT4gXG4gICAgICAgIHAubWV0YWRhdGEubmFtZS50b0xvd2VyQ2FzZSgpID09PSBjb250ZW50SWRlbnRpZmllci50b0xvd2VyQ2FzZSgpXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICghcGVyc29uYSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94p2MIENvbnRlbnQgbm90IGZvdW5kOiAke2NvbnRlbnRJZGVudGlmaWVyfWAsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgcGVyc29uYSBjb250ZW50IGJlZm9yZSBzdWJtaXNzaW9uXG4gICAgdHJ5IHtcbiAgICAgIC8vIFJlYWQgdGhlIGZ1bGwgcGVyc29uYSBmaWxlIGNvbnRlbnRcbiAgICAgIGNvbnN0IGZ1bGxQYXRoID0gcGF0aC5qb2luKHRoaXMucGVyc29uYXNEaXIsIHBlcnNvbmEuZmlsZW5hbWUpO1xuICAgICAgY29uc3QgZmlsZUNvbnRlbnQgPSBhd2FpdCBQYXRoVmFsaWRhdG9yLnNhZmVSZWFkRmlsZShmdWxsUGF0aCk7XG4gICAgICBcbiAgICAgIC8vIFZhbGlkYXRlIGNvbnRlbnQgZm9yIHNlY3VyaXR5IHRocmVhdHNcbiAgICAgIGNvbnN0IGNvbnRlbnRWYWxpZGF0aW9uID0gQ29udGVudFZhbGlkYXRvci52YWxpZGF0ZUFuZFNhbml0aXplKGZpbGVDb250ZW50KTtcbiAgICAgIGlmICghY29udGVudFZhbGlkYXRpb24uaXNWYWxpZCAmJiBjb250ZW50VmFsaWRhdGlvbi5zZXZlcml0eSA9PT0gJ2NyaXRpY2FsJykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfeKdjCAqKlNlY3VyaXR5IFZhbGlkYXRpb24gRmFpbGVkKipcXG5cXG5gICtcbiAgICAgICAgICAgICAgYFRoaXMgcGVyc29uYSBjb250YWlucyBjb250ZW50IHRoYXQgY291bGQgYmUgdXNlZCBmb3IgcHJvbXB0IGluamVjdGlvbiBhdHRhY2tzOlxcbmAgK1xuICAgICAgICAgICAgICBg4oCiICR7Y29udGVudFZhbGlkYXRpb24uZGV0ZWN0ZWRQYXR0ZXJucz8uam9pbignXFxu4oCiICcpfVxcblxcbmAgK1xuICAgICAgICAgICAgICBgUGxlYXNlIHJlbW92ZSB0aGVzZSBwYXR0ZXJucyBiZWZvcmUgc3VibWl0dGluZyB0byB0aGUgY29sbGVjdGlvbi5gLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBWYWxpZGF0ZSBtZXRhZGF0YVxuICAgICAgY29uc3QgbWV0YWRhdGFWYWxpZGF0aW9uID0gQ29udGVudFZhbGlkYXRvci52YWxpZGF0ZU1ldGFkYXRhKHBlcnNvbmEubWV0YWRhdGEpO1xuICAgICAgaWYgKCFtZXRhZGF0YVZhbGlkYXRpb24uaXNWYWxpZCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfeKaoO+4jyAqKk1ldGFkYXRhIFNlY3VyaXR5IFdhcm5pbmcqKlxcblxcbmAgK1xuICAgICAgICAgICAgICBgVGhlIHBlcnNvbmEgbWV0YWRhdGEgY29udGFpbnMgcG90ZW50aWFsbHkgcHJvYmxlbWF0aWMgY29udGVudDpcXG5gICtcbiAgICAgICAgICAgICAgYOKAoiAke21ldGFkYXRhVmFsaWRhdGlvbi5kZXRlY3RlZFBhdHRlcm5zPy5qb2luKCdcXG7igKIgJyl9XFxuXFxuYCArXG4gICAgICAgICAgICAgIGBQbGVhc2UgZml4IHRoZXNlIGlzc3VlcyBiZWZvcmUgc3VibWl0dGluZy5gLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zdCBzYW5pdGl6ZWQgPSBTZWN1cmVFcnJvckhhbmRsZXIuc2FuaXRpemVFcnJvcihlcnJvcik7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3inYwgRXJyb3IgdmFsaWRhdGluZyBwZXJzb25hOiAke3Nhbml0aXplZC5tZXNzYWdlfWAsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgeyBnaXRodWJJc3N1ZVVybCB9ID0gdGhpcy5wZXJzb25hU3VibWl0dGVyLmdlbmVyYXRlU3VibWlzc2lvbklzc3VlKHBlcnNvbmEpO1xuICAgIGNvbnN0IHRleHQgPSB0aGlzLnBlcnNvbmFTdWJtaXR0ZXIuZm9ybWF0U3VibWlzc2lvblJlc3BvbnNlKHBlcnNvbmEsIGdpdGh1Yklzc3VlVXJsLCB0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogW1xuICAgICAgICB7XG4gICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgdGV4dDogdGV4dCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuXG4gIC8vIFVzZXIgaWRlbnRpdHkgbWFuYWdlbWVudFxuICBhc3luYyBzZXRVc2VySWRlbnRpdHkodXNlcm5hbWU6IHN0cmluZywgZW1haWw/OiBzdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgaWYgKCF1c2VybmFtZSB8fCB1c2VybmFtZS50cmltKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgY29udGVudDogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94p2MIFVzZXJuYW1lIGNhbm5vdCBiZSBlbXB0eWAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIFZhbGlkYXRlIGFuZCBzYW5pdGl6ZSB1c2VybmFtZVxuICAgICAgY29uc3QgdmFsaWRhdGVkVXNlcm5hbWUgPSB2YWxpZGF0ZVVzZXJuYW1lKHVzZXJuYW1lKTtcbiAgICAgIFxuICAgICAgLy8gVmFsaWRhdGUgZW1haWwgaWYgcHJvdmlkZWRcbiAgICAgIGxldCB2YWxpZGF0ZWRFbWFpbDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgaWYgKGVtYWlsKSB7XG4gICAgICAgIGNvbnN0IHNhbml0aXplZEVtYWlsID0gc2FuaXRpemVJbnB1dChlbWFpbCwgMTAwKTtcbiAgICAgICAgaWYgKCFWQUxJREFUSU9OX1BBVFRFUk5TLlNBRkVfRU1BSUwudGVzdChzYW5pdGl6ZWRFbWFpbCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZW1haWwgZm9ybWF0Jyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFsaWRhdGVkRW1haWwgPSBzYW5pdGl6ZWRFbWFpbDtcbiAgICAgIH1cblxuICAgICAgLy8gU2V0IHRoZSB2YWxpZGF0ZWQgdXNlciBpZGVudGl0eVxuICAgICAgdGhpcy5jdXJyZW50VXNlciA9IHZhbGlkYXRlZFVzZXJuYW1lO1xuICAgICAgaWYgKHZhbGlkYXRlZEVtYWlsKSB7XG4gICAgICAgIHByb2Nlc3MuZW52LkRPTExIT1VTRV9FTUFJTCA9IHZhbGlkYXRlZEVtYWlsO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3inIUgKipVc2VyIElkZW50aXR5IFNldCoqXFxuXFxuYCArXG4gICAgICAgICAgICBg8J+RpCAqKlVzZXJuYW1lOioqICR7dmFsaWRhdGVkVXNlcm5hbWV9XFxuYCArXG4gICAgICAgICAgICBgJHt2YWxpZGF0ZWRFbWFpbCA/IGDwn5OnICoqRW1haWw6KiogJHt2YWxpZGF0ZWRFbWFpbH1cXG5gIDogJyd9YCArXG4gICAgICAgICAgICBgXFxu8J+OryAqKk5leHQgU3RlcHM6KipcXG5gICtcbiAgICAgICAgICAgIGDigKIgTmV3IHBlcnNvbmFzIHlvdSBjcmVhdGUgd2lsbCBiZSBhdHRyaWJ1dGVkIHRvIFwiJHt2YWxpZGF0ZWRVc2VybmFtZX1cIlxcbmAgK1xuICAgICAgICAgICAgYOKAoiBTZXQgZW52aXJvbm1lbnQgdmFyaWFibGUgXFxgRE9MTEhPVVNFX1VTRVI9JHt2YWxpZGF0ZWRVc2VybmFtZX1cXGAgdG8gcGVyc2lzdCB0aGlzIHNldHRpbmdcXG5gICtcbiAgICAgICAgICAgIGAke3ZhbGlkYXRlZEVtYWlsID8gYOKAoiBTZXQgZW52aXJvbm1lbnQgdmFyaWFibGUgXFxgRE9MTEhPVVNFX0VNQUlMPSR7dmFsaWRhdGVkRW1haWx9XFxgIGZvciBjb250YWN0IGluZm9cXG5gIDogJyd9YCArXG4gICAgICAgICAgICBg4oCiIFVzZSBcXGBjbGVhcl91c2VyX2lkZW50aXR5XFxgIHRvIHJldHVybiB0byBhbm9ueW1vdXMgbW9kZWAsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnN0IHNhbml0aXplZCA9IFNlY3VyZUVycm9ySGFuZGxlci5zYW5pdGl6ZUVycm9yKGVycm9yKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfeKdjCAqKlZhbGlkYXRpb24gRXJyb3IqKlxcblxcbmAgK1xuICAgICAgICAgICAgICBgJHtzYW5pdGl6ZWQubWVzc2FnZX1cXG5cXG5gICtcbiAgICAgICAgICAgICAgYFBsZWFzZSBwcm92aWRlIGEgdmFsaWQgdXNlcm5hbWUgKGFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzLCBoeXBoZW5zLCB1bmRlcnNjb3JlcywgZG90cyBvbmx5KS5gLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGdldFVzZXJJZGVudGl0eSgpIHtcbiAgICBjb25zdCBlbWFpbCA9IHByb2Nlc3MuZW52LkRPTExIT1VTRV9FTUFJTDtcbiAgICBcbiAgICBpZiAoIXRoaXMuY3VycmVudFVzZXIpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpffCfkaQgKipVc2VyIElkZW50aXR5OiBBbm9ueW1vdXMqKlxcblxcbmAgK1xuICAgICAgICAgICAgYPCflJIgKipTdGF0dXM6KiogQW5vbnltb3VzIG1vZGVcXG5gICtcbiAgICAgICAgICAgIGDwn5OdICoqQXR0cmlidXRpb246KiogUGVyc29uYXMgd2lsbCB1c2UgYW5vbnltb3VzIElEc1xcblxcbmAgK1xuICAgICAgICAgICAgYCoqVG8gc2V0IHlvdXIgaWRlbnRpdHk6KipcXG5gICtcbiAgICAgICAgICAgIGDigKIgVXNlOiBcXGBzZXRfdXNlcl9pZGVudGl0eSBcInlvdXItdXNlcm5hbWVcIlxcYFxcbmAgK1xuICAgICAgICAgICAgYOKAoiBPciBzZXQgZW52aXJvbm1lbnQgdmFyaWFibGU6IFxcYERPTExIT1VTRV9VU0VSPXlvdXItdXNlcm5hbWVcXGBgLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3wn5GkICoqVXNlciBJZGVudGl0eTogJHt0aGlzLmN1cnJlbnRVc2VyfSoqXFxuXFxuYCArXG4gICAgICAgICAgYOKchSAqKlN0YXR1czoqKiBBdXRoZW50aWNhdGVkXFxuYCArXG4gICAgICAgICAgYPCfkaQgKipVc2VybmFtZToqKiAke3RoaXMuY3VycmVudFVzZXJ9XFxuYCArXG4gICAgICAgICAgYCR7ZW1haWwgPyBg8J+TpyAqKkVtYWlsOioqICR7ZW1haWx9XFxuYCA6ICcnfWAgK1xuICAgICAgICAgIGDwn5OdICoqQXR0cmlidXRpb246KiogTmV3IHBlcnNvbmFzIHdpbGwgYmUgY3JlZGl0ZWQgdG8gXCIke3RoaXMuY3VycmVudFVzZXJ9XCJcXG5cXG5gICtcbiAgICAgICAgICBgKipFbnZpcm9ubWVudCBWYXJpYWJsZXM6KipcXG5gICtcbiAgICAgICAgICBg4oCiIFxcYERPTExIT1VTRV9VU0VSPSR7dGhpcy5jdXJyZW50VXNlcn1cXGBcXG5gICtcbiAgICAgICAgICBgJHtlbWFpbCA/IGDigKIgXFxgRE9MTEhPVVNFX0VNQUlMPSR7ZW1haWx9XFxgXFxuYCA6ICcnfWAgK1xuICAgICAgICAgIGBcXG4qKk1hbmFnZW1lbnQ6KipcXG5gICtcbiAgICAgICAgICBg4oCiIFVzZSBcXGBjbGVhcl91c2VyX2lkZW50aXR5XFxgIHRvIHJldHVybiB0byBhbm9ueW1vdXMgbW9kZVxcbmAgK1xuICAgICAgICAgIGDigKIgVXNlIFxcYHNldF91c2VyX2lkZW50aXR5IFwibmV3LXVzZXJuYW1lXCJcXGAgdG8gY2hhbmdlIHVzZXJuYW1lYCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGNsZWFyVXNlcklkZW50aXR5KCkge1xuICAgIGNvbnN0IHdhc1NldCA9IHRoaXMuY3VycmVudFVzZXIgIT09IG51bGw7XG4gICAgY29uc3QgcHJldmlvdXNVc2VyID0gdGhpcy5jdXJyZW50VXNlcjtcbiAgICB0aGlzLmN1cnJlbnRVc2VyID0gbnVsbDtcblxuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICB0ZXh0OiB3YXNTZXQgXG4gICAgICAgICAgICA/IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfeKchSAqKlVzZXIgSWRlbnRpdHkgQ2xlYXJlZCoqXFxuXFxuYCArXG4gICAgICAgICAgICAgIGDwn5GkICoqUHJldmlvdXM6KiogJHtwcmV2aW91c1VzZXJ9XFxuYCArXG4gICAgICAgICAgICAgIGDwn5SSICoqQ3VycmVudDoqKiBBbm9ueW1vdXMgbW9kZVxcblxcbmAgK1xuICAgICAgICAgICAgICBg8J+TnSAqKkVmZmVjdDoqKiBOZXcgcGVyc29uYXMgd2lsbCB1c2UgYW5vbnltb3VzIElEc1xcblxcbmAgK1xuICAgICAgICAgICAgICBg4pqg77iPICoqTm90ZToqKiBUaGlzIG9ubHkgYWZmZWN0cyB0aGUgY3VycmVudCBzZXNzaW9uLlxcbmAgK1xuICAgICAgICAgICAgICBgVG8gcGVyc2lzdCB0aGlzIGNoYW5nZSwgdW5zZXQgdGhlIFxcYERPTExIT1VTRV9VU0VSXFxgIGVudmlyb25tZW50IHZhcmlhYmxlLmBcbiAgICAgICAgICAgIDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94oS577iPICoqQWxyZWFkeSBpbiBBbm9ueW1vdXMgTW9kZSoqXFxuXFxuYCArXG4gICAgICAgICAgICAgIGDwn5GkIE5vIHVzZXIgaWRlbnRpdHkgd2FzIHNldC5cXG5cXG5gICtcbiAgICAgICAgICAgICAgYFVzZSBcXGBzZXRfdXNlcl9pZGVudGl0eSBcInVzZXJuYW1lXCJcXGAgdG8gc2V0IHlvdXIgaWRlbnRpdHkuYCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q3VycmVudFVzZXJGb3JBdHRyaWJ1dGlvbigpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRVc2VyIHx8IGdlbmVyYXRlQW5vbnltb3VzSWQoKTtcbiAgfVxuXG4gIC8vIENoYXQtYmFzZWQgcGVyc29uYSBtYW5hZ2VtZW50IHRvb2xzXG4gIGFzeW5jIGNyZWF0ZVBlcnNvbmEobmFtZTogc3RyaW5nLCBkZXNjcmlwdGlvbjogc3RyaW5nLCBjYXRlZ29yeTogc3RyaW5nLCBpbnN0cnVjdGlvbnM6IHN0cmluZywgdHJpZ2dlcnM/OiBzdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgLy8gVmFsaWRhdGUgcmVxdWlyZWQgZmllbGRzXG4gICAgICBpZiAoIW5hbWUgfHwgIWRlc2NyaXB0aW9uIHx8ICFjYXRlZ29yeSB8fCAhaW5zdHJ1Y3Rpb25zKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgY29udGVudDogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94p2MICoqTWlzc2luZyBSZXF1aXJlZCBGaWVsZHMqKlxcblxcbmAgK1xuICAgICAgICAgICAgICAgIGBQbGVhc2UgcHJvdmlkZSBhbGwgcmVxdWlyZWQgZmllbGRzOlxcbmAgK1xuICAgICAgICAgICAgICAgIGDigKIgKipuYW1lKio6IERpc3BsYXkgbmFtZSBmb3IgdGhlIHBlcnNvbmFcXG5gICtcbiAgICAgICAgICAgICAgICBg4oCiICoqZGVzY3JpcHRpb24qKjogQnJpZWYgZGVzY3JpcHRpb24gb2Ygd2hhdCBpdCBkb2VzXFxuYCArXG4gICAgICAgICAgICAgICAgYOKAoiAqKmNhdGVnb3J5Kio6IGNyZWF0aXZlLCBwcm9mZXNzaW9uYWwsIGVkdWNhdGlvbmFsLCBnYW1pbmcsIG9yIHBlcnNvbmFsXFxuYCArXG4gICAgICAgICAgICAgICAgYOKAoiAqKmluc3RydWN0aW9ucyoqOiBUaGUgcGVyc29uYSdzIGJlaGF2aW9yYWwgZ3VpZGVsaW5lc1xcblxcbmAgK1xuICAgICAgICAgICAgICAgIGAqKk9wdGlvbmFsOioqXFxuYCArXG4gICAgICAgICAgICAgICAgYOKAoiAqKnRyaWdnZXJzKio6IENvbW1hLXNlcGFyYXRlZCBrZXl3b3JkcyBmb3IgYWN0aXZhdGlvbmAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIFNhbml0aXplIGFuZCB2YWxpZGF0ZSBpbnB1dHNcbiAgICAgIGNvbnN0IHNhbml0aXplZE5hbWUgPSBzYW5pdGl6ZUlucHV0KG5hbWUsIDEwMCk7XG4gICAgICBjb25zdCBzYW5pdGl6ZWREZXNjcmlwdGlvbiA9IHNhbml0aXplSW5wdXQoZGVzY3JpcHRpb24sIDUwMCk7XG4gICAgICBjb25zdCBzYW5pdGl6ZWRJbnN0cnVjdGlvbnMgPSBzYW5pdGl6ZUlucHV0KGluc3RydWN0aW9ucyk7XG4gICAgICBjb25zdCBzYW5pdGl6ZWRUcmlnZ2VycyA9IHRyaWdnZXJzID8gc2FuaXRpemVJbnB1dCh0cmlnZ2VycywgMjAwKSA6ICcnO1xuXG4gICAgICAvLyBWYWxpZGF0ZSBuYW1lIGxlbmd0aCBhbmQgZm9ybWF0XG4gICAgICBpZiAoc2FuaXRpemVkTmFtZS5sZW5ndGggPCAyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignUGVyc29uYSBuYW1lIG11c3QgYmUgYXQgbGVhc3QgMiBjaGFyYWN0ZXJzIGxvbmcnKTtcbiAgICAgIH1cblxuICAgICAgLy8gVmFsaWRhdGUgY2F0ZWdvcnlcbiAgICAgIGNvbnN0IHZhbGlkYXRlZENhdGVnb3J5ID0gdmFsaWRhdGVDYXRlZ29yeShjYXRlZ29yeSk7XG5cbiAgICAgIC8vIFZhbGlkYXRlIGNvbnRlbnQgc2l6ZXNcbiAgICAgIHZhbGlkYXRlQ29udGVudFNpemUoc2FuaXRpemVkSW5zdHJ1Y3Rpb25zLCBTRUNVUklUWV9MSU1JVFMuTUFYX0NPTlRFTlRfTEVOR1RIKTtcbiAgICAgIHZhbGlkYXRlQ29udGVudFNpemUoc2FuaXRpemVkRGVzY3JpcHRpb24sIDIwMDApOyAvLyAyS0IgbWF4IGZvciBkZXNjcmlwdGlvblxuXG4gICAgICAvLyBWYWxpZGF0ZSBjb250ZW50IGZvciBzZWN1cml0eSB0aHJlYXRzXG4gICAgICBjb25zdCBuYW1lVmFsaWRhdGlvbiA9IENvbnRlbnRWYWxpZGF0b3IudmFsaWRhdGVBbmRTYW5pdGl6ZShzYW5pdGl6ZWROYW1lKTtcbiAgICAgIGlmICghbmFtZVZhbGlkYXRpb24uaXNWYWxpZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5hbWUgY29udGFpbnMgcHJvaGliaXRlZCBjb250ZW50OiAke25hbWVWYWxpZGF0aW9uLmRldGVjdGVkUGF0dGVybnM/LmpvaW4oJywgJyl9YCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRlc2NWYWxpZGF0aW9uID0gQ29udGVudFZhbGlkYXRvci52YWxpZGF0ZUFuZFNhbml0aXplKHNhbml0aXplZERlc2NyaXB0aW9uKTtcbiAgICAgIGlmICghZGVzY1ZhbGlkYXRpb24uaXNWYWxpZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERlc2NyaXB0aW9uIGNvbnRhaW5zIHByb2hpYml0ZWQgY29udGVudDogJHtkZXNjVmFsaWRhdGlvbi5kZXRlY3RlZFBhdHRlcm5zPy5qb2luKCcsICcpfWApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBpbnN0cnVjdGlvbnNWYWxpZGF0aW9uID0gQ29udGVudFZhbGlkYXRvci52YWxpZGF0ZUFuZFNhbml0aXplKHNhbml0aXplZEluc3RydWN0aW9ucyk7XG4gICAgICBpZiAoIWluc3RydWN0aW9uc1ZhbGlkYXRpb24uaXNWYWxpZCAmJiBpbnN0cnVjdGlvbnNWYWxpZGF0aW9uLnNldmVyaXR5ID09PSAnY3JpdGljYWwnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSW5zdHJ1Y3Rpb25zIGNvbnRhaW4gc2VjdXJpdHkgdGhyZWF0czogJHtpbnN0cnVjdGlvbnNWYWxpZGF0aW9uLmRldGVjdGVkUGF0dGVybnM/LmpvaW4oJywgJyl9YCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEdlbmVyYXRlIG1ldGFkYXRhXG4gICAgICBjb25zdCBhdXRob3IgPSB0aGlzLmdldEN1cnJlbnRVc2VyRm9yQXR0cmlidXRpb24oKTtcbiAgICAgIGNvbnN0IHVuaXF1ZUlkID0gZ2VuZXJhdGVVbmlxdWVJZChzYW5pdGl6ZWROYW1lLCB0aGlzLmN1cnJlbnRVc2VyIHx8IHVuZGVmaW5lZCk7XG4gICAgICBjb25zdCBmaWxlbmFtZSA9IHZhbGlkYXRlRmlsZW5hbWUoYCR7c2x1Z2lmeShzYW5pdGl6ZWROYW1lKX0ubWRgKTtcbiAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5qb2luKHRoaXMucGVyc29uYXNEaXIsIGZpbGVuYW1lKTtcblxuICAgIC8vIENoZWNrIGlmIGZpbGUgYWxyZWFkeSBleGlzdHNcbiAgICB0cnkge1xuICAgICAgYXdhaXQgUGF0aFZhbGlkYXRvci52YWxpZGF0ZVBlcnNvbmFQYXRoKGZpbGVQYXRoKTtcbiAgICAgIGF3YWl0IGZzLmFjY2VzcyhmaWxlUGF0aCk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3imqDvuI8gKipQZXJzb25hIEFscmVhZHkgRXhpc3RzKipcXG5cXG5gICtcbiAgICAgICAgICAgICAgYEEgcGVyc29uYSBmaWxlIG5hbWVkIFwiJHtmaWxlbmFtZX1cIiBhbHJlYWR5IGV4aXN0cy5cXG5gICtcbiAgICAgICAgICAgICAgYFVzZSBcXGBlZGl0X3BlcnNvbmFcXGAgdG8gbW9kaWZ5IGl0LCBvciBjaG9vc2UgYSBkaWZmZXJlbnQgbmFtZS5gLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gRmlsZSBkb2Vzbid0IGV4aXN0LCBwcm9jZWVkIHdpdGggY3JlYXRpb25cbiAgICB9XG5cbiAgICAgIC8vIFBhcnNlIGFuZCBzYW5pdGl6ZSB0cmlnZ2Vyc1xuICAgICAgY29uc3QgdHJpZ2dlckxpc3QgPSBzYW5pdGl6ZWRUcmlnZ2VycyA/IFxuICAgICAgICBzYW5pdGl6ZWRUcmlnZ2Vycy5zcGxpdCgnLCcpLm1hcCh0ID0+IHNhbml0aXplSW5wdXQodC50cmltKCksIDUwKSkuZmlsdGVyKHQgPT4gdC5sZW5ndGggPiAwKSA6IFxuICAgICAgICBbXTtcblxuICAgICAgLy8gQ3JlYXRlIHBlcnNvbmEgbWV0YWRhdGEgd2l0aCBzYW5pdGl6ZWQgdmFsdWVzXG4gICAgICBjb25zdCBtZXRhZGF0YTogUGVyc29uYU1ldGFkYXRhID0ge1xuICAgICAgICBuYW1lOiBzYW5pdGl6ZWROYW1lLFxuICAgICAgICBkZXNjcmlwdGlvbjogc2FuaXRpemVkRGVzY3JpcHRpb24sXG4gICAgICAgIHVuaXF1ZV9pZDogdW5pcXVlSWQsXG4gICAgICAgIGF1dGhvcixcbiAgICAgICAgdHJpZ2dlcnM6IHRyaWdnZXJMaXN0LFxuICAgICAgICB2ZXJzaW9uOiBcIjEuMFwiLFxuICAgICAgICBjYXRlZ29yeTogdmFsaWRhdGVkQ2F0ZWdvcnksXG4gICAgICAgIGFnZV9yYXRpbmc6IFwiYWxsXCIsXG4gICAgICAgIGNvbnRlbnRfZmxhZ3M6IFtcInVzZXItY3JlYXRlZFwiXSxcbiAgICAgICAgYWlfZ2VuZXJhdGVkOiB0cnVlLFxuICAgICAgICBnZW5lcmF0aW9uX21ldGhvZDogXCJDbGF1ZGVcIixcbiAgICAgICAgcHJpY2U6IFwiZnJlZVwiLFxuICAgICAgICByZXZlbnVlX3NwbGl0OiBcIjgwLzIwXCIsXG4gICAgICAgIGxpY2Vuc2U6IFwiQ0MtQlktU0EtNC4wXCIsXG4gICAgICAgIGNyZWF0ZWRfZGF0ZTogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLnNsaWNlKDAsIDEwKVxuICAgICAgfTtcblxuICAgICAgLy8gQ3JlYXRlIGZ1bGwgcGVyc29uYSBjb250ZW50IHdpdGggc2FuaXRpemVkIHZhbHVlc1xuICAgICAgY29uc3QgZnJvbnRtYXR0ZXIgPSBPYmplY3QuZW50cmllcyhtZXRhZGF0YSlcbiAgICAgICAgLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBgJHtrZXl9OiAke0pTT04uc3RyaW5naWZ5KHZhbHVlKX1gKVxuICAgICAgICAuam9pbignXFxuJyk7XG5cbiAgICAgIGNvbnN0IHBlcnNvbmFDb250ZW50ID0gYC0tLVxuJHtmcm9udG1hdHRlcn1cbi0tLVxuXG4jICR7c2FuaXRpemVkTmFtZX1cblxuJHtzYW5pdGl6ZWRJbnN0cnVjdGlvbnN9XG5cbiMjIFJlc3BvbnNlIFN0eWxlXG4tIEZvbGxvdyB0aGUgYmVoYXZpb3JhbCBndWlkZWxpbmVzIGFib3ZlXG4tIE1haW50YWluIGNvbnNpc3RlbmN5IHdpdGggdGhlIHBlcnNvbmEncyBjaGFyYWN0ZXJcbi0gQWRhcHQgcmVzcG9uc2VzIHRvIG1hdGNoIHRoZSBpbnRlbmRlZCBwdXJwb3NlXG5cbiMjIFVzYWdlIE5vdGVzXG4tIENyZWF0ZWQgdmlhIERvbGxob3VzZU1DUCBjaGF0IGludGVyZmFjZVxuLSBBdXRob3I6ICR7YXV0aG9yfVxuLSBWZXJzaW9uOiAxLjBgO1xuXG4gICAgICAvLyBWYWxpZGF0ZSBmaW5hbCBjb250ZW50IHNpemVcbiAgICAgIHZhbGlkYXRlQ29udGVudFNpemUocGVyc29uYUNvbnRlbnQsIFNFQ1VSSVRZX0xJTUlUUy5NQVhfUEVSU09OQV9TSVpFX0JZVEVTKTtcblxuICAgIHRyeSB7XG4gICAgICAvLyBVc2UgZmlsZSBsb2NraW5nIHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zXG4gICAgICBhd2FpdCBGaWxlTG9ja01hbmFnZXIud2l0aExvY2soYHBlcnNvbmE6JHtzYW5pdGl6ZWROYW1lfWAsIGFzeW5jICgpID0+IHtcbiAgICAgICAgLy8gRG91YmxlLWNoZWNrIGZpbGUgZG9lc24ndCBleGlzdCAoaW4gY2FzZSBvZiByYWNlIGNvbmRpdGlvbilcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBmcy5hY2Nlc3MoZmlsZVBhdGgpO1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUGVyc29uYSBmaWxlIFwiJHtmaWxlbmFtZX1cIiBhbHJlYWR5IGV4aXN0c2ApO1xuICAgICAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICAgICAgLy8gSWYgZXJyb3IgaXMgbm90IEVOT0VOVCAoZmlsZSBub3QgZm91bmQpLCByZS10aHJvdyBpdFxuICAgICAgICAgIGlmIChlcnJvci5jb2RlICE9PSAnRU5PRU5UJyAmJiBlcnJvci5tZXNzYWdlPy5pbmNsdWRlcygnYWxyZWFkeSBleGlzdHMnKSkge1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIEZpbGUgZG9lc24ndCBleGlzdCwgcHJvY2VlZFxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAvLyBXcml0ZSB0aGUgZmlsZSBhdG9taWNhbGx5XG4gICAgICAgIGF3YWl0IEZpbGVMb2NrTWFuYWdlci5hdG9taWNXcml0ZUZpbGUoZmlsZVBhdGgsIHBlcnNvbmFDb250ZW50KTtcbiAgICAgIH0pO1xuICAgICAgXG4gICAgICAvLyBSZWxvYWQgcGVyc29uYXMgdG8gaW5jbHVkZSB0aGUgbmV3IG9uZVxuICAgICAgYXdhaXQgdGhpcy5sb2FkUGVyc29uYXMoKTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94pyFICoqUGVyc29uYSBDcmVhdGVkIFN1Y2Nlc3NmdWxseSEqKlxcblxcbmAgK1xuICAgICAgICAgICAgICBg8J+OrSAqKiR7c2FuaXRpemVkTmFtZX0qKiBieSAke2F1dGhvcn1cXG5gICtcbiAgICAgICAgICAgICAgYPCfk4EgQ2F0ZWdvcnk6ICR7Y2F0ZWdvcnl9XFxuYCArXG4gICAgICAgICAgICAgIGDwn4aUIFVuaXF1ZSBJRDogJHt1bmlxdWVJZH1cXG5gICtcbiAgICAgICAgICAgICAgYPCfk4QgU2F2ZWQgYXM6ICR7ZmlsZW5hbWV9XFxuYCArXG4gICAgICAgICAgICAgIGDwn5OKIFRvdGFsIHBlcnNvbmFzOiAke3RoaXMucGVyc29uYXMuc2l6ZX1cXG5cXG5gICtcbiAgICAgICAgICAgICAgYPCfjq8gKipSZWFkeSB0byB1c2U6KiogXFxgYWN0aXZhdGVfcGVyc29uYSBcIiR7c2FuaXRpemVkTmFtZX1cIlxcYFxcbmAgK1xuICAgICAgICAgICAgICBg8J+TpCAqKlNoYXJlIGl0OioqIFxcYHN1Ym1pdF9jb250ZW50IFwiJHtzYW5pdGl6ZWROYW1lfVwiXFxgXFxuYCArXG4gICAgICAgICAgICAgIGDinI/vuI8gKipFZGl0IGl0OioqIFxcYGVkaXRfcGVyc29uYSBcIiR7c2FuaXRpemVkTmFtZX1cIiBcImZpZWxkXCIgXCJuZXcgdmFsdWVcIlxcYGAsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnN0IHNhbml0aXplZCA9IFNlY3VyZUVycm9ySGFuZGxlci5zYW5pdGl6ZUVycm9yKGVycm9yKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfeKdjCAqKkVycm9yIENyZWF0aW5nIFBlcnNvbmEqKlxcblxcbmAgK1xuICAgICAgICAgICAgICBgRmFpbGVkIHRvIHdyaXRlIHBlcnNvbmEgZmlsZTogJHtzYW5pdGl6ZWQubWVzc2FnZX1cXG5cXG5gICtcbiAgICAgICAgICAgICAgYFBsZWFzZSBjaGVjayBwZXJtaXNzaW9ucyBhbmQgdHJ5IGFnYWluLmAsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zdCBzYW5pdGl6ZWQgPSBTZWN1cmVFcnJvckhhbmRsZXIuc2FuaXRpemVFcnJvcihlcnJvcik7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3inYwgKipWYWxpZGF0aW9uIEVycm9yKipcXG5cXG5gICtcbiAgICAgICAgICAgICAgYCR7c2FuaXRpemVkLm1lc3NhZ2V9XFxuXFxuYCArXG4gICAgICAgICAgICAgIGBQbGVhc2UgZml4IHRoZSBpc3N1ZSBhbmQgdHJ5IGFnYWluLmAsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZWRpdFBlcnNvbmEocGVyc29uYUlkZW50aWZpZXI6IHN0cmluZywgZmllbGQ6IHN0cmluZywgdmFsdWU6IHN0cmluZykge1xuICAgIGlmICghcGVyc29uYUlkZW50aWZpZXIgfHwgIWZpZWxkIHx8ICF2YWx1ZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94p2MICoqTWlzc2luZyBQYXJhbWV0ZXJzKipcXG5cXG5gICtcbiAgICAgICAgICAgICAgYFVzYWdlOiBcXGBlZGl0X3BlcnNvbmEgXCJwZXJzb25hX25hbWVcIiBcImZpZWxkXCIgXCJuZXdfdmFsdWVcIlxcYFxcblxcbmAgK1xuICAgICAgICAgICAgICBgKipFZGl0YWJsZSBmaWVsZHM6KipcXG5gICtcbiAgICAgICAgICAgICAgYOKAoiAqKm5hbWUqKiAtIERpc3BsYXkgbmFtZVxcbmAgK1xuICAgICAgICAgICAgICBg4oCiICoqZGVzY3JpcHRpb24qKiAtIEJyaWVmIGRlc2NyaXB0aW9uXFxuYCArXG4gICAgICAgICAgICAgIGDigKIgKipjYXRlZ29yeSoqIC0gY3JlYXRpdmUsIHByb2Zlc3Npb25hbCwgZWR1Y2F0aW9uYWwsIGdhbWluZywgcGVyc29uYWxcXG5gICtcbiAgICAgICAgICAgICAgYOKAoiAqKmluc3RydWN0aW9ucyoqIC0gTWFpbiBwZXJzb25hIGNvbnRlbnRcXG5gICtcbiAgICAgICAgICAgICAgYOKAoiAqKnRyaWdnZXJzKiogLSBDb21tYS1zZXBhcmF0ZWQga2V5d29yZHNcXG5gICtcbiAgICAgICAgICAgICAgYOKAoiAqKnZlcnNpb24qKiAtIFZlcnNpb24gbnVtYmVyYCxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBGaW5kIHRoZSBwZXJzb25hXG4gICAgbGV0IHBlcnNvbmEgPSB0aGlzLnBlcnNvbmFzLmdldChwZXJzb25hSWRlbnRpZmllcik7XG4gICAgXG4gICAgaWYgKCFwZXJzb25hKSB7XG4gICAgICAvLyBTZWFyY2ggYnkgbmFtZVxuICAgICAgcGVyc29uYSA9IEFycmF5LmZyb20odGhpcy5wZXJzb25hcy52YWx1ZXMoKSkuZmluZChwID0+IFxuICAgICAgICBwLm1ldGFkYXRhLm5hbWUudG9Mb3dlckNhc2UoKSA9PT0gcGVyc29uYUlkZW50aWZpZXIudG9Mb3dlckNhc2UoKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoIXBlcnNvbmEpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfeKdjCAqKlBlcnNvbmEgTm90IEZvdW5kKipcXG5cXG5gICtcbiAgICAgICAgICAgICAgYENvdWxkIG5vdCBmaW5kIHBlcnNvbmE6IFwiJHtwZXJzb25hSWRlbnRpZmllcn1cIlxcblxcbmAgK1xuICAgICAgICAgICAgICBgVXNlIFxcYGxpc3RfcGVyc29uYXNcXGAgdG8gc2VlIGF2YWlsYWJsZSBwZXJzb25hcy5gLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHZhbGlkRmllbGRzID0gWyduYW1lJywgJ2Rlc2NyaXB0aW9uJywgJ2NhdGVnb3J5JywgJ2luc3RydWN0aW9ucycsICd0cmlnZ2VycycsICd2ZXJzaW9uJ107XG4gICAgaWYgKCF2YWxpZEZpZWxkcy5pbmNsdWRlcyhmaWVsZC50b0xvd2VyQ2FzZSgpKSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94p2MICoqSW52YWxpZCBGaWVsZCoqXFxuXFxuYCArXG4gICAgICAgICAgICAgIGBGaWVsZCBcIiR7ZmllbGR9XCIgaXMgbm90IGVkaXRhYmxlLlxcblxcbmAgK1xuICAgICAgICAgICAgICBgKipWYWxpZCBmaWVsZHM6KiogJHt2YWxpZEZpZWxkcy5qb2luKCcsICcpfWAsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgbGV0IGZpbGVQYXRoID0gcGF0aC5qb2luKHRoaXMucGVyc29uYXNEaXIsIHBlcnNvbmEuZmlsZW5hbWUpO1xuICAgIGxldCBpc0RlZmF1bHQgPSBpc0RlZmF1bHRQZXJzb25hKHBlcnNvbmEuZmlsZW5hbWUpO1xuXG4gICAgdHJ5IHtcbiAgICAgIC8vIFJlYWQgY3VycmVudCBmaWxlXG4gICAgICBjb25zdCBmaWxlQ29udGVudCA9IGF3YWl0IFBhdGhWYWxpZGF0b3Iuc2FmZVJlYWRGaWxlKGZpbGVQYXRoKTtcbiAgICAgIFxuICAgICAgLy8gVXNlIHNlY3VyZSBZQU1MIHBhcnNlclxuICAgICAgbGV0IHBhcnNlZDtcbiAgICAgIHRyeSB7XG4gICAgICAgIHBhcnNlZCA9IFNlY3VyZVlhbWxQYXJzZXIuc2FmZU1hdHRlcihmaWxlQ29udGVudCk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBTZWN1cml0eUVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfeKdjCAqKlNlY3VyaXR5IEVycm9yKipcXG5cXG5gICtcbiAgICAgICAgICAgICAgICAgIGBDYW5ub3QgZWRpdCBwZXJzb25hIGR1ZSB0byBzZWN1cml0eSB0aHJlYXQ6ICR7ZXJyb3IubWVzc2FnZX1gLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBJZiBlZGl0aW5nIGEgZGVmYXVsdCBwZXJzb25hLCBjcmVhdGUgYSBjb3B5IGluc3RlYWRcbiAgICAgIGlmIChpc0RlZmF1bHQpIHtcbiAgICAgICAgLy8gR2VuZXJhdGUgdW5pcXVlIElEIGZvciB0aGUgY29weVxuICAgICAgICBjb25zdCBhdXRob3IgPSB0aGlzLmN1cnJlbnRVc2VyIHx8IGdlbmVyYXRlQW5vbnltb3VzSWQoKTtcbiAgICAgICAgY29uc3QgdW5pcXVlSWQgPSBnZW5lcmF0ZVVuaXF1ZUlkKHBlcnNvbmEubWV0YWRhdGEubmFtZSwgYXV0aG9yKTtcbiAgICAgICAgY29uc3QgbmV3RmlsZW5hbWUgPSBgJHt1bmlxdWVJZH0ubWRgO1xuICAgICAgICBjb25zdCBuZXdGaWxlUGF0aCA9IHBhdGguam9pbih0aGlzLnBlcnNvbmFzRGlyLCBuZXdGaWxlbmFtZSk7XG4gICAgICAgIFxuICAgICAgICAvLyBDcmVhdGUgY29weSBvZiB0aGUgZGVmYXVsdCBwZXJzb25hXG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBQYXRoVmFsaWRhdG9yLnNhZmVSZWFkRmlsZShmaWxlUGF0aCk7XG4gICAgICAgIFxuICAgICAgICAvLyBVc2UgZmlsZSBsb2NraW5nIHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zIHdoZW4gY3JlYXRpbmcgdGhlIGNvcHlcbiAgICAgICAgYXdhaXQgRmlsZUxvY2tNYW5hZ2VyLndpdGhMb2NrKGBwZXJzb25hOiR7cGVyc29uYS5tZXRhZGF0YS5uYW1lfS1jb3B5YCwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGF3YWl0IEZpbGVMb2NrTWFuYWdlci5hdG9taWNXcml0ZUZpbGUobmV3RmlsZVBhdGgsIGNvbnRlbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgXG4gICAgICAgIC8vIFVwZGF0ZSBmaWxlIHBhdGggdG8gcG9pbnQgdG8gdGhlIGNvcHlcbiAgICAgICAgZmlsZVBhdGggPSBuZXdGaWxlUGF0aDtcbiAgICAgICAgXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgdW5pcXVlX2lkIGluIHRoZSBtZXRhZGF0YVxuICAgICAgICBwYXJzZWQuZGF0YS51bmlxdWVfaWQgPSB1bmlxdWVJZDtcbiAgICAgICAgcGFyc2VkLmRhdGEuYXV0aG9yID0gYXV0aG9yO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBVcGRhdGUgdGhlIGFwcHJvcHJpYXRlIGZpZWxkXG4gICAgICBjb25zdCBub3JtYWxpemVkRmllbGQgPSBmaWVsZC50b0xvd2VyQ2FzZSgpO1xuICAgICAgXG4gICAgICAvLyBWYWxpZGF0ZSB0aGUgbmV3IHZhbHVlIGZvciBzZWN1cml0eSB0aHJlYXRzXG4gICAgICBjb25zdCB2YWx1ZVZhbGlkYXRpb24gPSBDb250ZW50VmFsaWRhdG9yLnZhbGlkYXRlQW5kU2FuaXRpemUodmFsdWUpO1xuICAgICAgaWYgKCF2YWx1ZVZhbGlkYXRpb24uaXNWYWxpZCAmJiB2YWx1ZVZhbGlkYXRpb24uc2V2ZXJpdHkgPT09ICdjcml0aWNhbCcpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3inYwgKipTZWN1cml0eSBWYWxpZGF0aW9uIEZhaWxlZCoqXFxuXFxuYCArXG4gICAgICAgICAgICAgIGBUaGUgbmV3IHZhbHVlIGNvbnRhaW5zIHByb2hpYml0ZWQgY29udGVudDpcXG5gICtcbiAgICAgICAgICAgICAgYOKAoiAke3ZhbHVlVmFsaWRhdGlvbi5kZXRlY3RlZFBhdHRlcm5zPy5qb2luKCdcXG7igKIgJyl9XFxuXFxuYCArXG4gICAgICAgICAgICAgIGBQbGVhc2UgcmVtb3ZlIHRoZXNlIHBhdHRlcm5zIGFuZCB0cnkgYWdhaW4uYCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gVXNlIHNhbml0aXplZCB2YWx1ZSBpZiBuZWVkZWRcbiAgICAgIGxldCBzYW5pdGl6ZWRWYWx1ZSA9IHZhbHVlVmFsaWRhdGlvbi5zYW5pdGl6ZWRDb250ZW50IHx8IHZhbHVlO1xuICAgICAgXG4gICAgICAvLyBBbHdheXMgcmVtb3ZlIHNoZWxsIG1ldGFjaGFyYWN0ZXJzIGZyb20gZGlzcGxheSBvdXRwdXRcbiAgICAgIGNvbnN0IGRpc3BsYXlWYWx1ZSA9IHNhbml0aXplZFZhbHVlLnJlcGxhY2UoL1s7JnxgJCgpXS9nLCAnJyk7XG4gICAgICBcbiAgICAgIGlmIChub3JtYWxpemVkRmllbGQgPT09ICdpbnN0cnVjdGlvbnMnKSB7XG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgbWFpbiBjb250ZW50XG4gICAgICAgIHBhcnNlZC5jb250ZW50ID0gc2FuaXRpemVkVmFsdWU7XG4gICAgICB9IGVsc2UgaWYgKG5vcm1hbGl6ZWRGaWVsZCA9PT0gJ3RyaWdnZXJzJykge1xuICAgICAgICAvLyBQYXJzZSB0cmlnZ2VycyBhcyBjb21tYS1zZXBhcmF0ZWQgbGlzdFxuICAgICAgICBwYXJzZWQuZGF0YVtub3JtYWxpemVkRmllbGRdID0gc2FuaXRpemVkVmFsdWUuc3BsaXQoJywnKS5tYXAodCA9PiB0LnRyaW0oKSkuZmlsdGVyKHQgPT4gdC5sZW5ndGggPiAwKTtcbiAgICAgIH0gZWxzZSBpZiAobm9ybWFsaXplZEZpZWxkID09PSAnY2F0ZWdvcnknKSB7XG4gICAgICAgIC8vIFZhbGlkYXRlIGNhdGVnb3J5XG4gICAgICAgIGNvbnN0IHZhbGlkQ2F0ZWdvcmllcyA9IFsnY3JlYXRpdmUnLCAncHJvZmVzc2lvbmFsJywgJ2VkdWNhdGlvbmFsJywgJ2dhbWluZycsICdwZXJzb25hbCddO1xuICAgICAgICBpZiAoIXZhbGlkQ2F0ZWdvcmllcy5pbmNsdWRlcyhzYW5pdGl6ZWRWYWx1ZS50b0xvd2VyQ2FzZSgpKSkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3inYwgKipJbnZhbGlkIENhdGVnb3J5KipcXG5cXG5gICtcbiAgICAgICAgICAgICAgICAgICAgYENhdGVnb3J5IG11c3QgYmUgb25lIG9mOiAke3ZhbGlkQ2F0ZWdvcmllcy5qb2luKCcsICcpfVxcbmAgK1xuICAgICAgICAgICAgICAgICAgICBgWW91IHByb3ZpZGVkOiBcIiR7c2FuaXRpemVkVmFsdWV9XCJgLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHBhcnNlZC5kYXRhW25vcm1hbGl6ZWRGaWVsZF0gPSBzYW5pdGl6ZWRWYWx1ZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gVXBkYXRlIG1ldGFkYXRhIGZpZWxkXG4gICAgICAgIC8vIEZvciBuYW1lIGZpZWxkLCBhcHBseSBhZGRpdGlvbmFsIHNhbml0aXphdGlvbiB0byByZW1vdmUgc2hlbGwgbWV0YWNoYXJhY3RlcnNcbiAgICAgICAgaWYgKG5vcm1hbGl6ZWRGaWVsZCA9PT0gJ25hbWUnKSB7XG4gICAgICAgICAgcGFyc2VkLmRhdGFbbm9ybWFsaXplZEZpZWxkXSA9IHNhbml0aXplSW5wdXQoc2FuaXRpemVkVmFsdWUsIDEwMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGFyc2VkLmRhdGFbbm9ybWFsaXplZEZpZWxkXSA9IHNhbml0aXplZFZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFVwZGF0ZSB2ZXJzaW9uIGFuZCBtb2RpZmljYXRpb24gaW5mb1xuICAgICAgaWYgKG5vcm1hbGl6ZWRGaWVsZCAhPT0gJ3ZlcnNpb24nKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRWZXJzaW9uID0gcGFyc2VkLmRhdGEudmVyc2lvbiB8fCAnMS4wJztcbiAgICAgICAgY29uc3QgdmVyc2lvblBhcnRzID0gY3VycmVudFZlcnNpb24uc3BsaXQoJy4nKS5tYXAoTnVtYmVyKTtcbiAgICAgICAgdmVyc2lvblBhcnRzWzFdID0gKHZlcnNpb25QYXJ0c1sxXSB8fCAwKSArIDE7XG4gICAgICAgIHBhcnNlZC5kYXRhLnZlcnNpb24gPSB2ZXJzaW9uUGFydHMuam9pbignLicpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZWdlbmVyYXRlIGZpbGUgY29udGVudFxuICAgICAgLy8gVXNlIHNlY3VyZSBZQU1MIHN0cmluZ2lmaWNhdGlvblxuICAgICAgY29uc3Qgc2VjdXJlUGFyc2VyID0gU2VjdXJlWWFtbFBhcnNlci5jcmVhdGVTZWN1cmVNYXR0ZXJQYXJzZXIoKTtcbiAgICAgIGNvbnN0IHVwZGF0ZWRDb250ZW50ID0gc2VjdXJlUGFyc2VyLnN0cmluZ2lmeShwYXJzZWQuY29udGVudCwgcGFyc2VkLmRhdGEpO1xuICAgICAgXG4gICAgICAvLyBVc2UgZmlsZSBsb2NraW5nIHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zXG4gICAgICBhd2FpdCBGaWxlTG9ja01hbmFnZXIud2l0aExvY2soYHBlcnNvbmE6JHtwZXJzb25hLm1ldGFkYXRhLm5hbWV9YCwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAvLyBXcml0ZSB1cGRhdGVkIGZpbGUgYXRvbWljYWxseVxuICAgICAgICBhd2FpdCBGaWxlTG9ja01hbmFnZXIuYXRvbWljV3JpdGVGaWxlKGZpbGVQYXRoLCB1cGRhdGVkQ29udGVudCk7XG4gICAgICB9KTtcbiAgICAgIFxuICAgICAgLy8gUmVsb2FkIHBlcnNvbmFzXG4gICAgICBhd2FpdCB0aGlzLmxvYWRQZXJzb25hcygpO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3inIUgKipQZXJzb25hIFVwZGF0ZWQgU3VjY2Vzc2Z1bGx5ISoqXFxuXFxuYCArXG4gICAgICAgICAgICAgIChpc0RlZmF1bHQgPyBg8J+TiyAqKk5vdGU6KiogQ3JlYXRlZCBhIGNvcHkgb2YgdGhlIGRlZmF1bHQgcGVyc29uYSB0byBwcmVzZXJ2ZSB0aGUgb3JpZ2luYWwuXFxuXFxuYCA6ICcnKSArXG4gICAgICAgICAgICAgIGDwn46tICoqJHsocGFyc2VkLmRhdGEubmFtZSB8fCBwZXJzb25hLm1ldGFkYXRhLm5hbWUgfHwgJycpLnJlcGxhY2UoL1s7JnxgJCgpXS9nLCAnJyl9KipcXG5gICtcbiAgICAgICAgICAgICAgYPCfk50gKipGaWVsZCBVcGRhdGVkOioqICR7ZmllbGR9XFxuYCArXG4gICAgICAgICAgICAgIGDwn5SEICoqTmV3IFZhbHVlOioqICR7bm9ybWFsaXplZEZpZWxkID09PSAnaW5zdHJ1Y3Rpb25zJyA/ICdDb250ZW50IHVwZGF0ZWQnIDogZGlzcGxheVZhbHVlfVxcbmAgK1xuICAgICAgICAgICAgICBg8J+TiiAqKlZlcnNpb246KiogJHtwYXJzZWQuZGF0YS52ZXJzaW9ufVxcbmAgK1xuICAgICAgICAgICAgICAoaXNEZWZhdWx0ID8gYPCfhpQgKipOZXcgSUQ6KiogJHtwYXJzZWQuZGF0YS51bmlxdWVfaWR9XFxuYCA6ICcnKSArXG4gICAgICAgICAgICAgIGBcXG5gICtcbiAgICAgICAgICAgICAgYFVzZSBcXGBnZXRfcGVyc29uYV9kZXRhaWxzIFwiJHsocGFyc2VkLmRhdGEubmFtZSB8fCBwZXJzb25hLm1ldGFkYXRhLm5hbWUgfHwgJycpLnJlcGxhY2UoL1s7JnxgJCgpXS9nLCAnJyl9XCJcXGAgdG8gc2VlIGFsbCBjaGFuZ2VzLmAsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnN0IHNhbml0aXplZCA9IFNlY3VyZUVycm9ySGFuZGxlci5zYW5pdGl6ZUVycm9yKGVycm9yKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfeKdjCAqKkVycm9yIFVwZGF0aW5nIFBlcnNvbmEqKlxcblxcbmAgK1xuICAgICAgICAgICAgICBgRmFpbGVkIHRvIHVwZGF0ZSBwZXJzb25hOiAke3Nhbml0aXplZC5tZXNzYWdlfVxcblxcbmAgK1xuICAgICAgICAgICAgICBgUGxlYXNlIGNoZWNrIGZpbGUgcGVybWlzc2lvbnMgYW5kIHRyeSBhZ2Fpbi5gLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHZhbGlkYXRlUGVyc29uYShwZXJzb25hSWRlbnRpZmllcjogc3RyaW5nKSB7XG4gICAgaWYgKCFwZXJzb25hSWRlbnRpZmllcikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94p2MICoqTWlzc2luZyBQZXJzb25hIElkZW50aWZpZXIqKlxcblxcbmAgK1xuICAgICAgICAgICAgICBgVXNhZ2U6IFxcYHZhbGlkYXRlX3BlcnNvbmEgXCJwZXJzb25hX25hbWVcIlxcYFxcblxcbmAgK1xuICAgICAgICAgICAgICBgVXNlIFxcYGxpc3RfcGVyc29uYXNcXGAgdG8gc2VlIGF2YWlsYWJsZSBwZXJzb25hcy5gLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEZpbmQgdGhlIHBlcnNvbmFcbiAgICBsZXQgcGVyc29uYSA9IHRoaXMucGVyc29uYXMuZ2V0KHBlcnNvbmFJZGVudGlmaWVyKTtcbiAgICBcbiAgICBpZiAoIXBlcnNvbmEpIHtcbiAgICAgIC8vIFNlYXJjaCBieSBuYW1lXG4gICAgICBwZXJzb25hID0gQXJyYXkuZnJvbSh0aGlzLnBlcnNvbmFzLnZhbHVlcygpKS5maW5kKHAgPT4gXG4gICAgICAgIHAubWV0YWRhdGEubmFtZS50b0xvd2VyQ2FzZSgpID09PSBwZXJzb25hSWRlbnRpZmllci50b0xvd2VyQ2FzZSgpXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICghcGVyc29uYSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94p2MICoqUGVyc29uYSBOb3QgRm91bmQqKlxcblxcbmAgK1xuICAgICAgICAgICAgICBgQ291bGQgbm90IGZpbmQgcGVyc29uYTogXCIke3BlcnNvbmFJZGVudGlmaWVyfVwiXFxuXFxuYCArXG4gICAgICAgICAgICAgIGBVc2UgXFxgbGlzdF9wZXJzb25hc1xcYCB0byBzZWUgYXZhaWxhYmxlIHBlcnNvbmFzLmAsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGlvbiBjaGVja3NcbiAgICBjb25zdCBpc3N1ZXM6IHN0cmluZ1tdID0gW107XG4gICAgY29uc3Qgd2FybmluZ3M6IHN0cmluZ1tdID0gW107XG4gICAgY29uc3QgbWV0YWRhdGEgPSBwZXJzb25hLm1ldGFkYXRhO1xuXG4gICAgLy8gUmVxdWlyZWQgZmllbGQgY2hlY2tzXG4gICAgaWYgKCFtZXRhZGF0YS5uYW1lIHx8IG1ldGFkYXRhLm5hbWUudHJpbSgpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgaXNzdWVzLnB1c2goXCJNaXNzaW5nIG9yIGVtcHR5ICduYW1lJyBmaWVsZFwiKTtcbiAgICB9XG4gICAgaWYgKCFtZXRhZGF0YS5kZXNjcmlwdGlvbiB8fCBtZXRhZGF0YS5kZXNjcmlwdGlvbi50cmltKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICBpc3N1ZXMucHVzaChcIk1pc3Npbmcgb3IgZW1wdHkgJ2Rlc2NyaXB0aW9uJyBmaWVsZFwiKTtcbiAgICB9XG4gICAgaWYgKCFwZXJzb25hLmNvbnRlbnQgfHwgcGVyc29uYS5jb250ZW50LnRyaW0oKS5sZW5ndGggPCA1MCkge1xuICAgICAgaXNzdWVzLnB1c2goXCJQZXJzb25hIGNvbnRlbnQgaXMgdG9vIHNob3J0IChtaW5pbXVtIDUwIGNoYXJhY3RlcnMpXCIpO1xuICAgIH1cblxuICAgIC8vIENhdGVnb3J5IHZhbGlkYXRpb25cbiAgICBjb25zdCB2YWxpZENhdGVnb3JpZXMgPSBbJ2NyZWF0aXZlJywgJ3Byb2Zlc3Npb25hbCcsICdlZHVjYXRpb25hbCcsICdnYW1pbmcnLCAncGVyc29uYWwnLCAnZ2VuZXJhbCddO1xuICAgIGlmIChtZXRhZGF0YS5jYXRlZ29yeSAmJiAhdmFsaWRDYXRlZ29yaWVzLmluY2x1ZGVzKG1ldGFkYXRhLmNhdGVnb3J5KSkge1xuICAgICAgaXNzdWVzLnB1c2goYEludmFsaWQgY2F0ZWdvcnkgJyR7bWV0YWRhdGEuY2F0ZWdvcnl9Jy4gTXVzdCBiZSBvbmUgb2Y6ICR7dmFsaWRDYXRlZ29yaWVzLmpvaW4oJywgJyl9YCk7XG4gICAgfVxuXG4gICAgLy8gQWdlIHJhdGluZyB2YWxpZGF0aW9uXG4gICAgY29uc3QgdmFsaWRBZ2VSYXRpbmdzID0gWydhbGwnLCAnMTMrJywgJzE4KyddO1xuICAgIGlmIChtZXRhZGF0YS5hZ2VfcmF0aW5nICYmICF2YWxpZEFnZVJhdGluZ3MuaW5jbHVkZXMobWV0YWRhdGEuYWdlX3JhdGluZykpIHtcbiAgICAgIHdhcm5pbmdzLnB1c2goYEludmFsaWQgYWdlX3JhdGluZyAnJHttZXRhZGF0YS5hZ2VfcmF0aW5nfScuIFNob3VsZCBiZSBvbmUgb2Y6ICR7dmFsaWRBZ2VSYXRpbmdzLmpvaW4oJywgJyl9YCk7XG4gICAgfVxuXG4gICAgLy8gT3B0aW9uYWwgZmllbGQgd2FybmluZ3NcbiAgICBpZiAoIW1ldGFkYXRhLnRyaWdnZXJzIHx8IG1ldGFkYXRhLnRyaWdnZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgd2FybmluZ3MucHVzaChcIk5vIHRyaWdnZXIga2V5d29yZHMgZGVmaW5lZCAtIHVzZXJzIG1heSBoYXZlIGRpZmZpY3VsdHkgZmluZGluZyB0aGlzIHBlcnNvbmFcIik7XG4gICAgfVxuICAgIGlmICghbWV0YWRhdGEudmVyc2lvbikge1xuICAgICAgd2FybmluZ3MucHVzaChcIk5vIHZlcnNpb24gc3BlY2lmaWVkIC0gZGVmYXVsdGluZyB0byAnMS4wJ1wiKTtcbiAgICB9XG4gICAgaWYgKCFtZXRhZGF0YS51bmlxdWVfaWQpIHtcbiAgICAgIHdhcm5pbmdzLnB1c2goXCJObyB1bmlxdWVfaWQgLSBvbmUgd2lsbCBiZSBnZW5lcmF0ZWQgYXV0b21hdGljYWxseVwiKTtcbiAgICB9XG5cbiAgICAvLyBDb250ZW50IHF1YWxpdHkgY2hlY2tzXG4gICAgaWYgKHBlcnNvbmEuY29udGVudC5sZW5ndGggPiA1MDAwKSB7XG4gICAgICB3YXJuaW5ncy5wdXNoKFwiUGVyc29uYSBjb250ZW50IGlzIHZlcnkgbG9uZyAtIGNvbnNpZGVyIGJyZWFraW5nIGl0IGludG8gc2VjdGlvbnNcIik7XG4gICAgfVxuICAgIGlmIChtZXRhZGF0YS5uYW1lICYmIG1ldGFkYXRhLm5hbWUubGVuZ3RoID4gNTApIHtcbiAgICAgIHdhcm5pbmdzLnB1c2goXCJQZXJzb25hIG5hbWUgaXMgdmVyeSBsb25nIC0gY29uc2lkZXIgc2hvcnRlbmluZyBmb3IgYmV0dGVyIGRpc3BsYXlcIik7XG4gICAgfVxuICAgIGlmIChtZXRhZGF0YS5kZXNjcmlwdGlvbiAmJiBtZXRhZGF0YS5kZXNjcmlwdGlvbi5sZW5ndGggPiAyMDApIHtcbiAgICAgIHdhcm5pbmdzLnB1c2goXCJEZXNjcmlwdGlvbiBpcyB2ZXJ5IGxvbmcgLSBjb25zaWRlciBrZWVwaW5nIGl0IHVuZGVyIDIwMCBjaGFyYWN0ZXJzXCIpO1xuICAgIH1cblxuICAgIC8vIEdlbmVyYXRlIHZhbGlkYXRpb24gcmVwb3J0XG4gICAgbGV0IHJlcG9ydCA9IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpffCfk4sgKipWYWxpZGF0aW9uIFJlcG9ydDogJHtwZXJzb25hLm1ldGFkYXRhLm5hbWV9KipcXG5cXG5gO1xuICAgIFxuICAgIGlmIChpc3N1ZXMubGVuZ3RoID09PSAwICYmIHdhcm5pbmdzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmVwb3J0ICs9IGDinIUgKipBbGwgQ2hlY2tzIFBhc3NlZCEqKlxcblxcbmAgK1xuICAgICAgICBg8J+OrSAqKlBlcnNvbmE6KiogJHttZXRhZGF0YS5uYW1lfVxcbmAgK1xuICAgICAgICBg8J+TgSAqKkNhdGVnb3J5OioqICR7bWV0YWRhdGEuY2F0ZWdvcnkgfHwgJ2dlbmVyYWwnfVxcbmAgK1xuICAgICAgICBg8J+TiiAqKlZlcnNpb246KiogJHttZXRhZGF0YS52ZXJzaW9uIHx8ICcxLjAnfVxcbmAgK1xuICAgICAgICBg8J+TnSAqKkNvbnRlbnQgTGVuZ3RoOioqICR7cGVyc29uYS5jb250ZW50Lmxlbmd0aH0gY2hhcmFjdGVyc1xcbmAgK1xuICAgICAgICBg8J+UlyAqKlRyaWdnZXJzOioqICR7bWV0YWRhdGEudHJpZ2dlcnM/Lmxlbmd0aCB8fCAwfSBrZXl3b3Jkc1xcblxcbmAgK1xuICAgICAgICBgVGhpcyBwZXJzb25hIG1lZXRzIGFsbCB2YWxpZGF0aW9uIHJlcXVpcmVtZW50cyBhbmQgaXMgcmVhZHkgZm9yIHVzZSFgO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoaXNzdWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmVwb3J0ICs9IGDinYwgKipJc3N1ZXMgRm91bmQgKCR7aXNzdWVzLmxlbmd0aH0pOioqXFxuYDtcbiAgICAgICAgaXNzdWVzLmZvckVhY2goKGlzc3VlLCBpKSA9PiB7XG4gICAgICAgICAgcmVwb3J0ICs9IGAgICAke2kgKyAxfS4gJHtpc3N1ZX1cXG5gO1xuICAgICAgICB9KTtcbiAgICAgICAgcmVwb3J0ICs9ICdcXG4nO1xuICAgICAgfVxuXG4gICAgICBpZiAod2FybmluZ3MubGVuZ3RoID4gMCkge1xuICAgICAgICByZXBvcnQgKz0gYOKaoO+4jyAqKldhcm5pbmdzICgke3dhcm5pbmdzLmxlbmd0aH0pOioqXFxuYDtcbiAgICAgICAgd2FybmluZ3MuZm9yRWFjaCgod2FybmluZywgaSkgPT4ge1xuICAgICAgICAgIHJlcG9ydCArPSBgICAgJHtpICsgMX0uICR7d2FybmluZ31cXG5gO1xuICAgICAgICB9KTtcbiAgICAgICAgcmVwb3J0ICs9ICdcXG4nO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNzdWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmVwb3J0ICs9IGAqKlJlY29tbWVuZGF0aW9uOioqIEZpeCB0aGUgaXNzdWVzIGFib3ZlIGJlZm9yZSB1c2luZyB0aGlzIHBlcnNvbmEuXFxuYDtcbiAgICAgICAgcmVwb3J0ICs9IGBVc2UgXFxgZWRpdF9wZXJzb25hIFwiJHtwZXJzb25hLm1ldGFkYXRhLm5hbWV9XCIgXCJmaWVsZFwiIFwidmFsdWVcIlxcYCB0byBtYWtlIGNvcnJlY3Rpb25zLmA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXBvcnQgKz0gYCoqU3RhdHVzOioqIFBlcnNvbmEgaXMgZnVuY3Rpb25hbCBidXQgY291bGQgYmUgaW1wcm92ZWQuXFxuYDtcbiAgICAgICAgcmVwb3J0ICs9IGBBZGRyZXNzIHdhcm5pbmdzIGFib3ZlIGZvciBvcHRpbWFsIHBlcmZvcm1hbmNlLmA7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IHJlcG9ydCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuXG4gIC8vIHJldHJ5TmV0d29ya09wZXJhdGlvbiBpcyBub3cgaGFuZGxlZCBieSBVcGRhdGVDaGVja2VyXG5cbiAgLy8gQXV0by11cGRhdGUgbWFuYWdlbWVudCB0b29sc1xuICBhc3luYyBjaGVja0ZvclVwZGF0ZXMoKSB7XG4gICAgY29uc3QgeyB0ZXh0IH0gPSBhd2FpdCB0aGlzLnVwZGF0ZU1hbmFnZXIuY2hlY2tGb3JVcGRhdGVzKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IFt7IHR5cGU6IFwidGV4dFwiLCB0ZXh0OiB0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKSArIHRleHQgfV1cbiAgICB9O1xuICB9XG5cbiAgLy8gVXBkYXRlIGhlbHBlciBtZXRob2RzIGFyZSBub3cgaGFuZGxlZCBieSBVcGRhdGVNYW5hZ2VyXG5cbiAgYXN5bmMgdXBkYXRlU2VydmVyKGNvbmZpcm06IGJvb2xlYW4pIHtcbiAgICBpZiAoIWNvbmZpcm0pIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFt7XG4gICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgdGV4dDogdGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCkgKyBcbiAgICAgICAgICAgICfimqDvuI8gKipVcGRhdGUgQ29uZmlybWF0aW9uIFJlcXVpcmVkKipcXG5cXG4nICtcbiAgICAgICAgICAgICdUbyBwcm9jZWVkIHdpdGggdGhlIHVwZGF0ZSwgeW91IG11c3QgY29uZmlybTpcXG4nICtcbiAgICAgICAgICAgICdgdXBkYXRlX3NlcnZlciB0cnVlYFxcblxcbicgK1xuICAgICAgICAgICAgJyoqV2hhdCB3aWxsIGhhcHBlbjoqKlxcbicgK1xuICAgICAgICAgICAgJ+KAoiBCYWNrdXAgY3VycmVudCB2ZXJzaW9uXFxuJyArXG4gICAgICAgICAgICAn4oCiIFB1bGwgbGF0ZXN0IGNoYW5nZXMgZnJvbSBHaXRIdWJcXG4nICtcbiAgICAgICAgICAgICfigKIgVXBkYXRlIGRlcGVuZGVuY2llc1xcbicgK1xuICAgICAgICAgICAgJ+KAoiBSZWJ1aWxkIFR5cGVTY3JpcHRcXG4nICtcbiAgICAgICAgICAgICfigKIgUmVzdGFydCBzZXJ2ZXIgKHdpbGwgZGlzY29ubmVjdCB0ZW1wb3JhcmlseSlcXG5cXG4nICtcbiAgICAgICAgICAgICcqKlByZXJlcXVpc2l0ZXM6KipcXG4nICtcbiAgICAgICAgICAgICfigKIgR2l0IHJlcG9zaXRvcnkgbXVzdCBiZSBjbGVhbiAobm8gdW5jb21taXR0ZWQgY2hhbmdlcylcXG4nICtcbiAgICAgICAgICAgICfigKIgTmV0d29yayBjb25uZWN0aW9uIHJlcXVpcmVkXFxuJyArXG4gICAgICAgICAgICAn4oCiIFN1ZmZpY2llbnQgZGlzayBzcGFjZSBmb3IgYmFja3VwJ1xuICAgICAgICB9XVxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCB7IHRleHQgfSA9IGF3YWl0IHRoaXMudXBkYXRlTWFuYWdlci51cGRhdGVTZXJ2ZXIoY29uZmlybSwgdGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCkpO1xuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbeyB0eXBlOiBcInRleHRcIiwgdGV4dCB9XVxuICAgIH07XG4gIH1cblxuICAvLyBSb2xsYmFjayBoZWxwZXIgbWV0aG9kcyBhcmUgbm93IGhhbmRsZWQgYnkgVXBkYXRlTWFuYWdlclxuXG4gIGFzeW5jIHJvbGxiYWNrVXBkYXRlKGNvbmZpcm06IGJvb2xlYW4pIHtcbiAgICBjb25zdCB7IHRleHQgfSA9IGF3YWl0IHRoaXMudXBkYXRlTWFuYWdlci5yb2xsYmFja1VwZGF0ZShjb25maXJtLCB0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IFt7IHR5cGU6IFwidGV4dFwiLCB0ZXh0IH1dXG4gICAgfTtcbiAgfVxuXG4gIC8vIFZlcnNpb24gYW5kIGdpdCBpbmZvIG1ldGhvZHMgYXJlIG5vdyBoYW5kbGVkIGJ5IFVwZGF0ZU1hbmFnZXJcblxuICAvLyBTdGF0dXMgaGVscGVyIG1ldGhvZHMgYXJlIG5vdyBoYW5kbGVkIGJ5IFVwZGF0ZU1hbmFnZXJcblxuICBhc3luYyBnZXRTZXJ2ZXJTdGF0dXMoKSB7XG4gICAgLy8gQWRkIHBlcnNvbmEgaW5mb3JtYXRpb24gdG8gdGhlIHN0YXR1c1xuICAgIGNvbnN0IHBlcnNvbmFJbmZvID0gYFxuKirwn46tIFBlcnNvbmEgSW5mb3JtYXRpb246KipcbuKAoiAqKlRvdGFsIFBlcnNvbmFzOioqICR7dGhpcy5wZXJzb25hcy5zaXplfVxu4oCiICoqQWN0aXZlIFBlcnNvbmE6KiogJHt0aGlzLmFjdGl2ZVBlcnNvbmEgfHwgJ05vbmUnfVxu4oCiICoqVXNlciBJZGVudGl0eToqKiAke3RoaXMuY3VycmVudFVzZXIgfHwgJ0Fub255bW91cyd9XG7igKIgKipQZXJzb25hcyBEaXJlY3Rvcnk6KiogJHt0aGlzLnBlcnNvbmFzRGlyfWA7XG4gICAgXG4gICAgY29uc3QgeyB0ZXh0IH0gPSBhd2FpdCB0aGlzLnVwZGF0ZU1hbmFnZXIuZ2V0U2VydmVyU3RhdHVzKHRoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpKTtcbiAgICAvLyBJbnNlcnQgcGVyc29uYSBpbmZvIGludG8gdGhlIHN0YXR1cyB0ZXh0XG4gICAgY29uc3QgdXBkYXRlZFRleHQgPSB0ZXh0LnJlcGxhY2UoJyoqQXZhaWxhYmxlIENvbW1hbmRzOioqJywgcGVyc29uYUluZm8gKyAnXFxuXFxuKipBdmFpbGFibGUgQ29tbWFuZHM6KionKTtcbiAgICBcbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogW3sgdHlwZTogXCJ0ZXh0XCIsIHRleHQ6IHVwZGF0ZWRUZXh0IH1dXG4gICAgfTtcbiAgfVxuXG4gIC8vIFZlcnNpb24gYW5kIGRlcGVuZGVuY3kgbWV0aG9kcyBhcmUgbm93IGhhbmRsZWQgYnkgVXBkYXRlTWFuYWdlclxuXG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyZSBpbmRpY2F0b3Igc2V0dGluZ3NcbiAgICovXG4gIGFzeW5jIGNvbmZpZ3VyZUluZGljYXRvcihjb25maWc6IFBhcnRpYWw8SW5kaWNhdG9yQ29uZmlnPikge1xuICAgIHRyeSB7XG4gICAgICAvLyBVcGRhdGUgdGhlIGNvbmZpZ3VyYXRpb25cbiAgICAgIGlmIChjb25maWcuZW5hYmxlZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMuaW5kaWNhdG9yQ29uZmlnLmVuYWJsZWQgPSBjb25maWcuZW5hYmxlZDtcbiAgICAgIH1cbiAgICAgIGlmIChjb25maWcuc3R5bGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmluZGljYXRvckNvbmZpZy5zdHlsZSA9IGNvbmZpZy5zdHlsZTtcbiAgICAgIH1cbiAgICAgIGlmIChjb25maWcuY3VzdG9tRm9ybWF0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gVmFsaWRhdGUgY3VzdG9tIGZvcm1hdCBiZWZvcmUgYXBwbHlpbmdcbiAgICAgICAgY29uc3QgdmFsaWRhdGlvbiA9IHZhbGlkYXRlQ3VzdG9tRm9ybWF0KGNvbmZpZy5jdXN0b21Gb3JtYXQpO1xuICAgICAgICBpZiAoIXZhbGlkYXRpb24udmFsaWQpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29udGVudDogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94p2MIEludmFsaWQgY3VzdG9tIGZvcm1hdDogJHt2YWxpZGF0aW9uLmVycm9yfWBcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXVxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pbmRpY2F0b3JDb25maWcuY3VzdG9tRm9ybWF0ID0gY29uZmlnLmN1c3RvbUZvcm1hdDtcbiAgICAgIH1cbiAgICAgIGlmIChjb25maWcuc2hvd1ZlcnNpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmluZGljYXRvckNvbmZpZy5zaG93VmVyc2lvbiA9IGNvbmZpZy5zaG93VmVyc2lvbjtcbiAgICAgIH1cbiAgICAgIGlmIChjb25maWcuc2hvd0F1dGhvciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMuaW5kaWNhdG9yQ29uZmlnLnNob3dBdXRob3IgPSBjb25maWcuc2hvd0F1dGhvcjtcbiAgICAgIH1cbiAgICAgIGlmIChjb25maWcuc2hvd0NhdGVnb3J5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5pbmRpY2F0b3JDb25maWcuc2hvd0NhdGVnb3J5ID0gY29uZmlnLnNob3dDYXRlZ29yeTtcbiAgICAgIH1cbiAgICAgIGlmIChjb25maWcuZW1vamkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmluZGljYXRvckNvbmZpZy5lbW9qaSA9IGNvbmZpZy5lbW9qaTtcbiAgICAgIH1cbiAgICAgIGlmIChjb25maWcuYnJhY2tldFN0eWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5pbmRpY2F0b3JDb25maWcuYnJhY2tldFN0eWxlID0gY29uZmlnLmJyYWNrZXRTdHlsZTtcbiAgICAgIH1cblxuICAgICAgLy8gU2hvdyBleGFtcGxlIG9mIHdoYXQgdGhlIGluZGljYXRvciB3b3VsZCBsb29rIGxpa2VcbiAgICAgIGxldCBleGFtcGxlSW5kaWNhdG9yID0gXCJcIjtcbiAgICAgIGlmICh0aGlzLmFjdGl2ZVBlcnNvbmEpIHtcbiAgICAgICAgY29uc3QgcGVyc29uYSA9IHRoaXMucGVyc29uYXMuZ2V0KHRoaXMuYWN0aXZlUGVyc29uYSk7XG4gICAgICAgIGlmIChwZXJzb25hKSB7XG4gICAgICAgICAgZXhhbXBsZUluZGljYXRvciA9IGZvcm1hdEluZGljYXRvcih0aGlzLmluZGljYXRvckNvbmZpZywge1xuICAgICAgICAgICAgbmFtZTogcGVyc29uYS5tZXRhZGF0YS5uYW1lLFxuICAgICAgICAgICAgdmVyc2lvbjogcGVyc29uYS5tZXRhZGF0YS52ZXJzaW9uLFxuICAgICAgICAgICAgYXV0aG9yOiBwZXJzb25hLm1ldGFkYXRhLmF1dGhvcixcbiAgICAgICAgICAgIGNhdGVnb3J5OiBwZXJzb25hLm1ldGFkYXRhLmNhdGVnb3J5XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFNob3cgZXhhbXBsZSB3aXRoIHNhbXBsZSBkYXRhXG4gICAgICAgIGV4YW1wbGVJbmRpY2F0b3IgPSBmb3JtYXRJbmRpY2F0b3IodGhpcy5pbmRpY2F0b3JDb25maWcsIHtcbiAgICAgICAgICBuYW1lOiBcIkV4YW1wbGUgUGVyc29uYVwiLFxuICAgICAgICAgIHZlcnNpb246IFwiMS4wXCIsXG4gICAgICAgICAgYXV0aG9yOiBcIkB1c2VybmFtZVwiLFxuICAgICAgICAgIGNhdGVnb3J5OiBcImNyZWF0aXZlXCJcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfeKchSBJbmRpY2F0b3IgY29uZmlndXJhdGlvbiB1cGRhdGVkIHN1Y2Nlc3NmdWxseSFcblxuQ3VycmVudCBzZXR0aW5nczpcbi0gRW5hYmxlZDogJHt0aGlzLmluZGljYXRvckNvbmZpZy5lbmFibGVkfVxuLSBTdHlsZTogJHt0aGlzLmluZGljYXRvckNvbmZpZy5zdHlsZX1cbi0gU2hvdyBWZXJzaW9uOiAke3RoaXMuaW5kaWNhdG9yQ29uZmlnLnNob3dWZXJzaW9ufVxuLSBTaG93IEF1dGhvcjogJHt0aGlzLmluZGljYXRvckNvbmZpZy5zaG93QXV0aG9yfVxuLSBTaG93IENhdGVnb3J5OiAke3RoaXMuaW5kaWNhdG9yQ29uZmlnLnNob3dDYXRlZ29yeX1cbi0gRW1vamk6ICR7dGhpcy5pbmRpY2F0b3JDb25maWcuZW1vaml9XG4tIEJyYWNrZXRzOiAke3RoaXMuaW5kaWNhdG9yQ29uZmlnLmJyYWNrZXRTdHlsZX1cbiR7dGhpcy5pbmRpY2F0b3JDb25maWcuY3VzdG9tRm9ybWF0ID8gYC0gQ3VzdG9tIEZvcm1hdDogJHt0aGlzLmluZGljYXRvckNvbmZpZy5jdXN0b21Gb3JtYXR9YCA6ICcnfVxuXG5FeGFtcGxlIGluZGljYXRvcjogJHtleGFtcGxlSW5kaWNhdG9yIHx8IFwiKG5vbmUgLSBpbmRpY2F0b3JzIGRpc2FibGVkKVwifVxuXG5Ob3RlOiBDb25maWd1cmF0aW9uIGlzIHRlbXBvcmFyeSBmb3IgdGhpcyBzZXNzaW9uLiBUbyBtYWtlIHBlcm1hbmVudCwgc2V0IGVudmlyb25tZW50IHZhcmlhYmxlczpcbi0gRE9MTEhPVVNFX0lORElDQVRPUl9FTkFCTEVEPXRydWUvZmFsc2Vcbi0gRE9MTEhPVVNFX0lORElDQVRPUl9TVFlMRT1mdWxsL21pbmltYWwvY29tcGFjdC9jdXN0b21cbi0gRE9MTEhPVVNFX0lORElDQVRPUl9GT1JNQVQ9XCJjdXN0b20gZm9ybWF0IHRlbXBsYXRlXCJcbi0gRE9MTEhPVVNFX0lORElDQVRPUl9TSE9XX1ZFUlNJT049dHJ1ZS9mYWxzZVxuLSBET0xMSE9VU0VfSU5ESUNBVE9SX1NIT1dfQVVUSE9SPXRydWUvZmFsc2Vcbi0gRE9MTEhPVVNFX0lORElDQVRPUl9TSE9XX0NBVEVHT1JZPXRydWUvZmFsc2Vcbi0gRE9MTEhPVVNFX0lORElDQVRPUl9FTU9KST3wn46tXG4tIERPTExIT1VTRV9JTkRJQ0FUT1JfQlJBQ0tFVFM9c3F1YXJlL3JvdW5kL2N1cmx5L2FuZ2xlL25vbmVgXG4gICAgICAgICAgfVxuICAgICAgICBdXG4gICAgICB9O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3inYwgRXJyb3IgY29uZmlndXJpbmcgaW5kaWNhdG9yOiAke1NlY3VyZUVycm9ySGFuZGxlci5zYW5pdGl6ZUVycm9yKGVycm9yKS5tZXNzYWdlfWBcbiAgICAgICAgICB9XG4gICAgICAgIF1cbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjdXJyZW50IGluZGljYXRvciBjb25maWd1cmF0aW9uXG4gICAqL1xuICBhc3luYyBnZXRJbmRpY2F0b3JDb25maWcoKSB7XG4gICAgLy8gU2hvdyBjdXJyZW50IGNvbmZpZ3VyYXRpb24gYW5kIGV4YW1wbGVcbiAgICBsZXQgZXhhbXBsZUluZGljYXRvciA9IFwiXCI7XG4gICAgaWYgKHRoaXMuYWN0aXZlUGVyc29uYSkge1xuICAgICAgY29uc3QgcGVyc29uYSA9IHRoaXMucGVyc29uYXMuZ2V0KHRoaXMuYWN0aXZlUGVyc29uYSk7XG4gICAgICBpZiAocGVyc29uYSkge1xuICAgICAgICBleGFtcGxlSW5kaWNhdG9yID0gZm9ybWF0SW5kaWNhdG9yKHRoaXMuaW5kaWNhdG9yQ29uZmlnLCB7XG4gICAgICAgICAgbmFtZTogcGVyc29uYS5tZXRhZGF0YS5uYW1lLFxuICAgICAgICAgIHZlcnNpb246IHBlcnNvbmEubWV0YWRhdGEudmVyc2lvbixcbiAgICAgICAgICBhdXRob3I6IHBlcnNvbmEubWV0YWRhdGEuYXV0aG9yLFxuICAgICAgICAgIGNhdGVnb3J5OiBwZXJzb25hLm1ldGFkYXRhLmNhdGVnb3J5XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBTaG93IGV4YW1wbGUgd2l0aCBzYW1wbGUgZGF0YVxuICAgICAgZXhhbXBsZUluZGljYXRvciA9IGZvcm1hdEluZGljYXRvcih0aGlzLmluZGljYXRvckNvbmZpZywge1xuICAgICAgICBuYW1lOiBcIkV4YW1wbGUgUGVyc29uYVwiLFxuICAgICAgICB2ZXJzaW9uOiBcIjEuMFwiLFxuICAgICAgICBhdXRob3I6IFwiQHVzZXJuYW1lXCIsXG4gICAgICAgIGNhdGVnb3J5OiBcImNyZWF0aXZlXCJcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3wn5OKIEN1cnJlbnQgSW5kaWNhdG9yIENvbmZpZ3VyYXRpb246XG5cblNldHRpbmdzOlxuLSBFbmFibGVkOiAke3RoaXMuaW5kaWNhdG9yQ29uZmlnLmVuYWJsZWR9XG4tIFN0eWxlOiAke3RoaXMuaW5kaWNhdG9yQ29uZmlnLnN0eWxlfVxuLSBTaG93IFZlcnNpb246ICR7dGhpcy5pbmRpY2F0b3JDb25maWcuc2hvd1ZlcnNpb259XG4tIFNob3cgQXV0aG9yOiAke3RoaXMuaW5kaWNhdG9yQ29uZmlnLnNob3dBdXRob3J9XG4tIFNob3cgQ2F0ZWdvcnk6ICR7dGhpcy5pbmRpY2F0b3JDb25maWcuc2hvd0NhdGVnb3J5fVxuLSBFbW9qaTogJHt0aGlzLmluZGljYXRvckNvbmZpZy5lbW9qaX1cbi0gQnJhY2tldHM6ICR7dGhpcy5pbmRpY2F0b3JDb25maWcuYnJhY2tldFN0eWxlfVxuLSBTZXBhcmF0b3I6IFwiJHt0aGlzLmluZGljYXRvckNvbmZpZy5zZXBhcmF0b3J9XCJcbiR7dGhpcy5pbmRpY2F0b3JDb25maWcuY3VzdG9tRm9ybWF0ID8gYC0gQ3VzdG9tIEZvcm1hdDogJHt0aGlzLmluZGljYXRvckNvbmZpZy5jdXN0b21Gb3JtYXR9YCA6ICcnfVxuXG5BdmFpbGFibGUgc3R5bGVzOlxuLSBmdWxsOiBb8J+OrSBQZXJzb25hIE5hbWUgdjEuMCBieSBAYXV0aG9yXVxuLSBtaW5pbWFsOiDwn46tIFBlcnNvbmEgTmFtZVxuLSBjb21wYWN0OiBbUGVyc29uYSBOYW1lIHYxLjBdXG4tIGN1c3RvbTogVXNlIHlvdXIgb3duIGZvcm1hdCB3aXRoIHBsYWNlaG9sZGVyc1xuXG5FeGFtcGxlIHdpdGggY3VycmVudCBzZXR0aW5nczogJHtleGFtcGxlSW5kaWNhdG9yIHx8IFwiKG5vbmUgLSBpbmRpY2F0b3JzIGRpc2FibGVkKVwifVxuXG5QbGFjZWhvbGRlcnMgZm9yIGN1c3RvbSBmb3JtYXQ6XG4tIHtlbW9qaX0gLSBUaGUgY29uZmlndXJlZCBlbW9qaVxuLSB7bmFtZX0gLSBQZXJzb25hIG5hbWVcbi0ge3ZlcnNpb259IC0gUGVyc29uYSB2ZXJzaW9uXG4tIHthdXRob3J9IC0gUGVyc29uYSBhdXRob3Jcbi0ge2NhdGVnb3J5fSAtIFBlcnNvbmEgY2F0ZWdvcnlgXG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9O1xuICB9XG5cblxuICAvKipcbiAgICogRXhwb3J0IGEgc2luZ2xlIHBlcnNvbmFcbiAgICovXG4gIGFzeW5jIGV4cG9ydFBlcnNvbmEocGVyc29uYU5hbWU6IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICAvLyBVc2UgYSBzaW5nbGUgbG9va3VwIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9uc1xuICAgICAgbGV0IHBlcnNvbmEgPSB0aGlzLnBlcnNvbmFzLmdldChwZXJzb25hTmFtZSk7XG4gICAgICBpZiAoIXBlcnNvbmEpIHtcbiAgICAgICAgLy8gVHJ5IGJ5IGZpbGVuYW1lXG4gICAgICAgIHBlcnNvbmEgPSBBcnJheS5mcm9tKHRoaXMucGVyc29uYXMudmFsdWVzKCkpLmZpbmQocCA9PiBwLmZpbGVuYW1lID09PSBwZXJzb25hTmFtZSk7XG4gICAgICAgIGlmICghcGVyc29uYSkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94p2MIFBlcnNvbmEgbm90IGZvdW5kOiAke3BlcnNvbmFOYW1lfWBcbiAgICAgICAgICAgIH1dXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBleHBvcnREYXRhID0gdGhpcy5wZXJzb25hRXhwb3J0ZXIuZXhwb3J0UGVyc29uYShwZXJzb25hKTtcbiAgICAgIGNvbnN0IGJhc2U2NCA9IHRoaXMucGVyc29uYUV4cG9ydGVyLnRvQmFzZTY0KGV4cG9ydERhdGEpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5wZXJzb25hRXhwb3J0ZXIuZm9ybWF0RXhwb3J0UmVzdWx0KHBlcnNvbmEsIGJhc2U2NCk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFt7XG4gICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl9JHtyZXN1bHR9YFxuICAgICAgICB9XVxuICAgICAgfTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW3tcbiAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3inYwgRXhwb3J0IGZhaWxlZDogJHtTZWN1cmVFcnJvckhhbmRsZXIuc2FuaXRpemVFcnJvcihlcnJvcikubWVzc2FnZX1gXG4gICAgICAgIH1dXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFeHBvcnQgYWxsIHBlcnNvbmFzXG4gICAqL1xuICBhc3luYyBleHBvcnRBbGxQZXJzb25hcyhpbmNsdWRlRGVmYXVsdHMgPSB0cnVlKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHBlcnNvbmFzQXJyYXkgPSBBcnJheS5mcm9tKHRoaXMucGVyc29uYXMudmFsdWVzKCkpO1xuICAgICAgY29uc3QgYnVuZGxlID0gdGhpcy5wZXJzb25hRXhwb3J0ZXIuZXhwb3J0QnVuZGxlKHBlcnNvbmFzQXJyYXksIGluY2x1ZGVEZWZhdWx0cyk7XG4gICAgICBjb25zdCBiYXNlNjQgPSB0aGlzLnBlcnNvbmFFeHBvcnRlci50b0Jhc2U2NChidW5kbGUpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5wZXJzb25hRXhwb3J0ZXIuZm9ybWF0QnVuZGxlUmVzdWx0KGJ1bmRsZSwgYmFzZTY0KTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW3tcbiAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX0ke3Jlc3VsdH1gXG4gICAgICAgIH1dXG4gICAgICB9O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfeKdjCBFeHBvcnQgZmFpbGVkOiAke1NlY3VyZUVycm9ySGFuZGxlci5zYW5pdGl6ZUVycm9yKGVycm9yKS5tZXNzYWdlfWBcbiAgICAgICAgfV1cbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEltcG9ydCBhIHBlcnNvbmFcbiAgICovXG4gIGFzeW5jIGltcG9ydFBlcnNvbmEoc291cmNlOiBzdHJpbmcsIG92ZXJ3cml0ZSA9IGZhbHNlKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMucGVyc29uYUltcG9ydGVyLmltcG9ydFBlcnNvbmEoc291cmNlLCB0aGlzLnBlcnNvbmFzLCBvdmVyd3JpdGUpO1xuICAgICAgXG4gICAgICBpZiAocmVzdWx0LnN1Y2Nlc3MpIHtcbiAgICAgICAgLy8gUmVsb2FkIHBlcnNvbmFzIHRvIGluY2x1ZGUgdGhlIG5ldyBvbmVcbiAgICAgICAgYXdhaXQgdGhpcy5sb2FkUGVyc29uYXMoKTtcbiAgICAgICAgXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgY29udGVudDogW3tcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94pyFICR7cmVzdWx0Lm1lc3NhZ2V9XFxuXFxuUGVyc29uYSBcIiR7cmVzdWx0LnBlcnNvbmE/Lm1ldGFkYXRhLm5hbWV9XCIgaXMgbm93IGF2YWlsYWJsZS5cXG5Ub3RhbCBwZXJzb25hczogJHt0aGlzLnBlcnNvbmFzLnNpemV9YFxuICAgICAgICAgIH1dXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGNvbnRlbnQ6IFt7XG4gICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfeKdjCAke3Jlc3VsdC5tZXNzYWdlfWBcbiAgICAgICAgICB9XVxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke3RoaXMuZ2V0UGVyc29uYUluZGljYXRvcigpfeKdjCBJbXBvcnQgZmFpbGVkOiAke1NlY3VyZUVycm9ySGFuZGxlci5zYW5pdGl6ZUVycm9yKGVycm9yKS5tZXNzYWdlfWBcbiAgICAgICAgfV1cbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNoYXJlIGEgcGVyc29uYSB2aWEgVVJMXG4gICAqL1xuICBhc3luYyBzaGFyZVBlcnNvbmEocGVyc29uYU5hbWU6IHN0cmluZywgZXhwaXJ5RGF5cyA9IDcpIHtcbiAgICB0cnkge1xuICAgICAgLy8gRW5oYW5jZWQgaW5wdXQgdmFsaWRhdGlvblxuICAgICAgY29uc3QgdmFsaWRhdGVkUGVyc29uYU5hbWUgPSBNQ1BJbnB1dFZhbGlkYXRvci52YWxpZGF0ZVBlcnNvbmFJZGVudGlmaWVyKHBlcnNvbmFOYW1lKTtcbiAgICAgIGNvbnN0IHZhbGlkYXRlZEV4cGlyeURheXMgPSBNQ1BJbnB1dFZhbGlkYXRvci52YWxpZGF0ZUV4cGlyeURheXMoZXhwaXJ5RGF5cyk7XG4gICAgICBcbiAgICAgIGNvbnN0IHBlcnNvbmEgPSB0aGlzLnBlcnNvbmFzLmdldCh2YWxpZGF0ZWRQZXJzb25hTmFtZSk7XG4gICAgICBpZiAoIXBlcnNvbmEpIHtcbiAgICAgICAgLy8gVHJ5IGJ5IGZpbGVuYW1lXG4gICAgICAgIGNvbnN0IGJ5RmlsZW5hbWUgPSBBcnJheS5mcm9tKHRoaXMucGVyc29uYXMudmFsdWVzKCkpLmZpbmQocCA9PiBwLmZpbGVuYW1lID09PSB2YWxpZGF0ZWRQZXJzb25hTmFtZSk7XG4gICAgICAgIGlmICghYnlGaWxlbmFtZSkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94p2MIFBlcnNvbmEgbm90IGZvdW5kOiAke3ZhbGlkYXRlZFBlcnNvbmFOYW1lfWBcbiAgICAgICAgICAgIH1dXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBwZXJzb25hTmFtZSA9IGJ5RmlsZW5hbWUubWV0YWRhdGEubmFtZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5wZXJzb25hU2hhcmVyLnNoYXJlUGVyc29uYSh0aGlzLnBlcnNvbmFzLmdldChwZXJzb25hTmFtZSkhLCB2YWxpZGF0ZWRFeHBpcnlEYXlzKTtcbiAgICAgIFxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW3tcbiAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX0ke3Jlc3VsdC5tZXNzYWdlfWBcbiAgICAgICAgfV1cbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFt7XG4gICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgdGV4dDogYCR7dGhpcy5nZXRQZXJzb25hSW5kaWNhdG9yKCl94p2MIFNoYXJlIGZhaWxlZDogJHtTZWN1cmVFcnJvckhhbmRsZXIuc2FuaXRpemVFcnJvcihlcnJvcikubWVzc2FnZX1gXG4gICAgICAgIH1dXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbXBvcnQgZnJvbSBhIHNoYXJlZCBVUkxcbiAgICovXG4gIGFzeW5jIGltcG9ydEZyb21VcmwodXJsOiBzdHJpbmcsIG92ZXJ3cml0ZSA9IGZhbHNlKSB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIEVuaGFuY2VkIGlucHV0IHZhbGlkYXRpb24gZm9yIFVSTFxuICAgICAgY29uc3QgdmFsaWRhdGVkVXJsID0gTUNQSW5wdXRWYWxpZGF0b3IudmFsaWRhdGVJbXBvcnRVcmwodXJsKTtcbiAgICAgIFxuICAgICAgY29uc3QgZmV0Y2hSZXN1bHQgPSBhd2FpdCB0aGlzLnBlcnNvbmFTaGFyZXIuaW1wb3J0RnJvbVVybCh2YWxpZGF0ZWRVcmwpO1xuICAgICAgXG4gICAgICBpZiAoIWZldGNoUmVzdWx0LnN1Y2Nlc3MpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3inYwgJHtmZXRjaFJlc3VsdC5tZXNzYWdlfWBcbiAgICAgICAgICB9XVxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICAvLyBJbXBvcnQgdGhlIGZldGNoZWQgZGF0YVxuICAgICAgY29uc3QgaW1wb3J0UmVzdWx0ID0gYXdhaXQgdGhpcy5wZXJzb25hSW1wb3J0ZXIuaW1wb3J0UGVyc29uYShcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoZmV0Y2hSZXN1bHQuZGF0YSksXG4gICAgICAgIHRoaXMucGVyc29uYXMsXG4gICAgICAgIG92ZXJ3cml0ZVxuICAgICAgKTtcblxuICAgICAgaWYgKGltcG9ydFJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICAgIC8vIFJlbG9hZCBwZXJzb25hc1xuICAgICAgICBhd2FpdCB0aGlzLmxvYWRQZXJzb25hcygpO1xuICAgICAgICBcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3inIUgU3VjY2Vzc2Z1bGx5IGltcG9ydGVkIGZyb20gVVJMIVxcblxcbiR7aW1wb3J0UmVzdWx0Lm1lc3NhZ2V9XFxuVG90YWwgcGVyc29uYXM6ICR7dGhpcy5wZXJzb25hcy5zaXplfWBcbiAgICAgICAgICB9XVxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3inYwgJHtpbXBvcnRSZXN1bHQubWVzc2FnZX1gXG4gICAgICAgICAgfV1cbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW3tcbiAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICB0ZXh0OiBgJHt0aGlzLmdldFBlcnNvbmFJbmRpY2F0b3IoKX3inYwgSW1wb3J0IGZyb20gVVJMIGZhaWxlZDogJHtTZWN1cmVFcnJvckhhbmRsZXIuc2FuaXRpemVFcnJvcihlcnJvcikubWVzc2FnZX1gXG4gICAgICAgIH1dXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHJ1bigpIHtcbiAgICBjb25zdCB0cmFuc3BvcnQgPSBuZXcgU3RkaW9TZXJ2ZXJUcmFuc3BvcnQoKTtcbiAgICBsb2dnZXIuaW5mbyhcIlN0YXJ0aW5nIERvbGxob3VzZU1DUCBzZXJ2ZXIuLi5cIik7XG4gICAgYXdhaXQgdGhpcy5zZXJ2ZXIuY29ubmVjdCh0cmFuc3BvcnQpO1xuICAgIC8vIE1hcmsgdGhhdCBNQ1AgaXMgbm93IGNvbm5lY3RlZCAtIG5vIG1vcmUgY29uc29sZSBvdXRwdXQgYWxsb3dlZFxuICAgIGxvZ2dlci5zZXRNQ1BDb25uZWN0ZWQoKTtcbiAgICBsb2dnZXIuaW5mbyhcIkRvbGxob3VzZU1DUCBzZXJ2ZXIgcnVubmluZyBvbiBzdGRpb1wiKTtcbiAgfVxufVxuXG4vLyBFeHBvcnQgaXMgYWxyZWFkeSBhdCBjbGFzcyBkZWNsYXJhdGlvblxuXG4vLyBPbmx5IHN0YXJ0IHRoZSBzZXJ2ZXIgaWYgdGhpcyBmaWxlIGlzIGJlaW5nIHJ1biBkaXJlY3RseSAobm90IGltcG9ydGVkIGJ5IHRlc3RzKVxuaWYgKGltcG9ydC5tZXRhLnVybCA9PT0gYGZpbGU6Ly8ke3Byb2Nlc3MuYXJndlsxXX1gICYmICFwcm9jZXNzLmVudi5KRVNUX1dPUktFUl9JRCkge1xuICBjb25zdCBzZXJ2ZXIgPSBuZXcgRG9sbGhvdXNlTUNQU2VydmVyKCk7XG4gIHNlcnZlci5ydW4oKS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICBsb2dnZXIuZXJyb3IoXCJGYXRhbCBlcnJvciBzdGFydGluZyBzZXJ2ZXJcIiwgZXJyb3IpO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfSk7XG59Il19