Spaces:
Running
Running
| <html lang="en"><head><style> | |
| @import url(https://fonts.googleapis.com/css?family=Google+Sans+Text); | |
| html { | |
| font-family: 'Google Sans Text', 'Google Sans'; | |
| font-size: 14px; | |
| color-scheme: light; | |
| background: light-dark(white, black); | |
| color: light-dark(black, white); | |
| } | |
| </style> | |
| <script type="importmap">{"imports":{"@modelcontextprotocol/sdk/":"https://esm.sh/@modelcontextprotocol/sdk/dist/esm/","https://esm.sh/@modelcontextprotocol/sdk@^1.11.0/es2022/":"https://esm.sh/@modelcontextprotocol/sdk@^1.11.0/es2022/dist/esm/","https://esm.sh/@modelcontextprotocol/sdk@^1.11.0/client/index?target=es2022":"https://esm.sh/@modelcontextprotocol/sdk@^1.11.0/dist/esm/client/index?target=es2022","https://esm.sh/@modelcontextprotocol/sdk@^1.11.0/types?target=es2022":"https://esm.sh/@modelcontextprotocol/sdk@^1.11.0/dist/esm/types?target=es2022","react":"https://esm.sh/react@^19.1.0","react-dom/":"https://esm.sh/react-dom@^19.1.0/","react/":"https://esm.sh/react@^19.1.0/","@/index":"data:application/javascript;base64,aW1wb3J0IHsganN4IGFzIF9qc3ggfSBmcm9tICJyZWFjdC9qc3gtcnVudGltZSI7CmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7CmltcG9ydCBSZWFjdERPTSBmcm9tICdyZWFjdC1kb20vY2xpZW50JzsKaW1wb3J0IHsgQXBwIH0gZnJvbSAnQC9BcHAnOwpjb25zdCByb290RWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdyb290Jyk7CmlmICghcm9vdEVsZW1lbnQpIHsKICAgIHRocm93IG5ldyBFcnJvcigiQ291bGQgbm90IGZpbmQgcm9vdCBlbGVtZW50IHRvIG1vdW50IHRvIik7Cn0KY29uc3Qgcm9vdCA9IFJlYWN0RE9NLmNyZWF0ZVJvb3Qocm9vdEVsZW1lbnQpOwpyb290LnJlbmRlcihfanN4KFJlYWN0LlN0cmljdE1vZGUsIHsgY2hpbGRyZW46IF9qc3goQXBwLCB7fSkgfSkpOwo=","@":"data:application/javascript;base64,aW1wb3J0IHsganN4IGFzIF9qc3ggfSBmcm9tICJyZWFjdC9qc3gtcnVudGltZSI7CmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7CmltcG9ydCBSZWFjdERPTSBmcm9tICdyZWFjdC1kb20vY2xpZW50JzsKaW1wb3J0IHsgQXBwIH0gZnJvbSAnQC9BcHAnOwpjb25zdCByb290RWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdyb290Jyk7CmlmICghcm9vdEVsZW1lbnQpIHsKICAgIHRocm93IG5ldyBFcnJvcigiQ291bGQgbm90IGZpbmQgcm9vdCBlbGVtZW50IHRvIG1vdW50IHRvIik7Cn0KY29uc3Qgcm9vdCA9IFJlYWN0RE9NLmNyZWF0ZVJvb3Qocm9vdEVsZW1lbnQpOwpyb290LnJlbmRlcihfanN4KFJlYWN0LlN0cmljdE1vZGUsIHsgY2hpbGRyZW46IF9qc3goQXBwLCB7fSkgfSkpOwo=","@/types":"data:application/javascript;base64,ZXhwb3J0IHZhciBNZXNzYWdlVHlwZTsKKGZ1bmN0aW9uIChNZXNzYWdlVHlwZSkgewogICAgTWVzc2FnZVR5cGVbIlVTRVJfTUVTU0FHRSJdID0gIlVTRVJfTUVTU0FHRSI7CiAgICBNZXNzYWdlVHlwZVsiU1lTVEVNX01FU1NBR0UiXSA9ICJTWVNURU1fTUVTU0FHRSI7Cn0pKE1lc3NhZ2VUeXBlIHx8IChNZXNzYWdlVHlwZSA9IHt9KSk7Ci8vIFAyUCBEYXRhIFByb3RvY29sCmV4cG9ydCB2YXIgUHJvdG9jb2xUeXBlOwooZnVuY3Rpb24gKFByb3RvY29sVHlwZSkgewogICAgUHJvdG9jb2xUeXBlWyJIQU5EU0hBS0UiXSA9ICJIQU5EU0hBS0UiOwogICAgUHJvdG9jb2xUeXBlWyJDSEFUX01FU1NBR0UiXSA9ICJDSEFUX01FU1NBR0UiOwogICAgUHJvdG9jb2xUeXBlWyJQQVJUSUNJUEFOVF9VUERBVEUiXSA9ICJQQVJUSUNJUEFOVF9VUERBVEUiOwogICAgUHJvdG9jb2xUeXBlWyJXRUxDT01FX0lORk8iXSA9ICJXRUxDT01FX0lORk8iOwp9KShQcm90b2NvbFR5cGUgfHwgKFByb3RvY29sVHlwZSA9IHt9KSk7Cg==","@/components/icons":"data:application/javascript;base64,aW1wb3J0IHsganN4IGFzIF9qc3ggfSBmcm9tICJyZWFjdC9qc3gtcnVudGltZSI7CmV4cG9ydCBjb25zdCBTZW5kSWNvbiA9ICgpID0+IChfanN4KCJzdmciLCB7IHhtbG5zOiAiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciLCB2aWV3Qm94OiAiMCAwIDI0IDI0IiwgZmlsbDogImN1cnJlbnRDb2xvciIsIGNsYXNzTmFtZTogInctNiBoLTYiLCBjaGlsZHJlbjogX2pzeCgicGF0aCIsIHsgZDogIk0zLjQ3OCAyLjQwNGEuNzUuNzUgMCAwIDAtLjkyNi45NDFsMi40MzIgNy45MDVIMTMuNWEuNzUuNzUgMCAwIDEgMCAxLjVINC45ODRsLTIuNDMyIDcuOTA1YS43NS43NSAwIDAgMCAuOTI2Ljk0IDYwLjUxOSA2MC41MTkgMCAwIDAgMTguNDQ1LTguOTg2Ljc1Ljc1IDAgMCAwIDAtMS4yMThBNjAuNTE3IDYwLjUxNyAwIDAgMCAzLjQ3OCAyLjQwNFoiIH0pIH0pKTsKZXhwb3J0IGNvbnN0IFVzZXJzSWNvbiA9ICgpID0+IChfanN4KCJzdmciLCB7IHhtbG5zOiAiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciLCBmaWxsOiAibm9uZSIsIHZpZXdCb3g6ICIwIDAgMjQgMjQiLCBzdHJva2VXaWR0aDogMS41LCBzdHJva2U6ICJjdXJyZW50Q29sb3IiLCBjbGFzc05hbWU6ICJ3LTYgaC02IiwgY2hpbGRyZW46IF9qc3goInBhdGgiLCB7IHN0cm9rZUxpbmVjYXA6ICJyb3VuZCIsIHN0cm9rZUxpbmVqb2luOiAicm91bmQiLCBkOiAiTTE4IDE4LjcyYTkuMDk0IDkuMDk0IDAgMCAwIDMuNzQxLS40NzkgMyAzIDAgMCAwLTQuNjgyLTIuNzJtLTcuNS0yLjk2MmEzLjc1IDMuNzUgMCAxIDAtNy41IDAgMy43NSAzLjc1IDAgMCAwIDcuNSAwWk0xMC41IDEuNWE5IDkgMCAxIDEtMTggMCA5IDkgMCAwIDEgMTggMFoiIH0pIH0pKTsKZXhwb3J0IGNvbnN0IFBsdXNJY29uID0gKCkgPT4gKF9qc3goInN2ZyIsIHsgeG1sbnM6ICJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIsIGZpbGw6ICJub25lIiwgdmlld0JveDogIjAgMCAyNCAyNCIsIHN0cm9rZVdpZHRoOiAxLjUsIHN0cm9rZTogImN1cnJlbnRDb2xvciIsIGNsYXNzTmFtZTogInctNiBoLTYiLCBjaGlsZHJlbjogX2pzeCgicGF0aCIsIHsgc3Ryb2tlTGluZWNhcDogInJvdW5kIiwgc3Ryb2tlTGluZWpvaW46ICJyb3VuZCIsIGQ6ICJNMTIgNC41djE1bTcuNS03LjVoLTE1IiB9KSB9KSk7CmV4cG9ydCBjb25zdCBMaW5rSWNvbiA9ICgpID0+IChfanN4KCJzdmciLCB7IHhtbG5zOiAiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciLCBmaWxsOiAibm9uZSIsIHZpZXdCb3g6ICIwIDAgMjQgMjQiLCBzdHJva2VXaWR0aDogMS41LCBzdHJva2U6ICJjdXJyZW50Q29sb3IiLCBjbGFzc05hbWU6ICJ3LTYgaC02IiwgY2hpbGRyZW46IF9qc3goInBhdGgiLCB7IHN0cm9rZUxpbmVjYXA6ICJyb3VuZCIsIHN0cm9rZUxpbmVqb2luOiAicm91bmQiLCBkOiAiTTEzLjE5IDguNjg4YTQuNSA0LjUgMCAwIDEgMS4yNDIgNy4yNDRsLTQuNSA0LjVhNC41IDQuNSAwIDAgMS02LjM2NC02LjM2NGwxLjc1Ny0xLjc1N20xMy4zNS0uNjIyIDEuNzU3LTEuNzU3YTQuNSA0LjUgMCAwIDAtNi4zNjQtNi4zNjRsLTQuNSA0LjVhNC41IDQuNSAwIDAgMCAxLjI0MiA3LjI0NCIgfSkgfSkpOwpleHBvcnQgY29uc3QgTG9nb3V0SWNvbiA9ICgpID0+IChfanN4KCJzdmciLCB7IHhtbG5zOiAiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciLCBmaWxsOiAibm9uZSIsIHZpZXdCb3g6ICIwIDAgMjQgMjQiLCBzdHJva2VXaWR0aDogMS41LCBzdHJva2U6ICJjdXJyZW50Q29sb3IiLCBjbGFzc05hbWU6ICJ3LTYgaC02IiwgY2hpbGRyZW46IF9qc3goInBhdGgiLCB7IHN0cm9rZUxpbmVjYXA6ICJyb3VuZCIsIHN0cm9rZUxpbmVqb2luOiAicm91bmQiLCBkOiAiTTE1Ljc1IDlWNS4yNUEyLjI1IDIuMjUgMCAwIDAgMTMuNSAzaC02YTIuMjUgMi4yNSAwIDAgMC0yLjI1IDIuMjV2MTMuNUEyLjI1IDIuMjUgMCAwIDAgNy41IDIxaDZhMi4yNSAyLjI1IDAgMCAwIDIuMjUtMi4yNVYxNW0zIDAgMy0zbTAgMC0zLTNtMyAzSDkiIH0pIH0pKTsKZXhwb3J0IGNvbnN0IENvcHlJY29uID0gKCkgPT4gKF9qc3goInN2ZyIsIHsgeG1sbnM6ICJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIsIGNsYXNzTmFtZTogImgtNSB3LTUiLCBmaWxsOiAibm9uZSIsIHZpZXdCb3g6ICIwIDAgMjQgMjQiLCBzdHJva2U6ICJjdXJyZW50Q29sb3IiLCBjaGlsZHJlbjogX2pzeCgicGF0aCIsIHsgc3Ryb2tlTGluZWNhcDogInJvdW5kIiwgc3Ryb2tlTGluZWpvaW46ICJyb3VuZCIsIHN0cm9rZVdpZHRoOiAyLCBkOiAiTTggMTZINmEyIDIgMCAwMS0yLTJWNmEyIDIgMCAwMTItMmg4YTIgMiAwIDAxMiAydjJtLTYgMTJoOGEyIDIgMCAwMDItMnYtOGEyIDIgMCAwMC0yLTJoLThhMiAyIDAgMDAtMiAydjhhMiAyIDAgMDAyIDJ6IiB9KSB9KSk7Cg==","@/App":"data:application/javascript;base64,aW1wb3J0IHsganN4IGFzIF9qc3gsIGpzeHMgYXMgX2pzeHMgfSBmcm9tICJyZWFjdC9qc3gtcnVudGltZSI7CmltcG9ydCB7IHVzZVN0YXRlLCB1c2VFZmZlY3QsIHVzZVJlZiwgdXNlQ2FsbGJhY2sgfSBmcm9tICdyZWFjdCc7CmltcG9ydCB7IE1lc3NhZ2VUeXBlLCBQcm90b2NvbFR5cGUgfSBmcm9tICdAL3R5cGVzJzsKaW1wb3J0IHsgU2VuZEljb24sIFVzZXJzSWNvbiwgUGx1c0ljb24sIExpbmtJY29uLCBMb2dvdXRJY29uLCBDb3B5SWNvbiB9IGZyb20gJ0AvY29tcG9uZW50cy9pY29ucyc7CmNvbnN0IGNyZWF0ZVN5c3RlbU1lc3NhZ2UgPSAoY29udGVudCkgPT4gKHsKICAgIGlkOiBgc3lzLSR7RGF0ZS5ub3coKX1gLAogICAgdHlwZTogTWVzc2FnZVR5cGUuU1lTVEVNX01FU1NBR0UsCiAgICBjb250ZW50LAogICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvTG9jYWxlVGltZVN0cmluZyhbXSwgeyBob3VyOiAnMi1kaWdpdCcsIG1pbnV0ZTogJzItZGlnaXQnIH0pLAp9KTsKY29uc3QgR2xhc3NQYW5lbCA9ICh7IGNoaWxkcmVuLCBjbGFzc05hbWUgfSkgPT4gKF9qc3goImRpdiIsIHsgY2xhc3NOYW1lOiBgYmctd2hpdGUvMTAgYmFja2Ryb3AtYmx1ci14bCBib3JkZXIgYm9yZGVyLXdoaXRlLzIwIHJvdW5kZWQtMnhsIHNoYWRvdy1sZyAke2NsYXNzTmFtZX1gLCBjaGlsZHJlbjogY2hpbGRyZW4gfSkpOwpleHBvcnQgY29uc3QgQXBwID0gKCkgPT4gewogICAgY29uc3QgW3ZpZXcsIHNldFZpZXddID0gdXNlU3RhdGUoJ1NFVFVQJyk7CiAgICBjb25zdCBbdXNlcm5hbWUsIHNldFVzZXJuYW1lXSA9IHVzZVN0YXRlKCcnKTsKICAgIGNvbnN0IFtteUlkLCBzZXRNeUlkXSA9IHVzZVN0YXRlKCcnKTsKICAgIGNvbnN0IFtpc0hvc3QsIHNldElzSG9zdF0gPSB1c2VTdGF0ZShmYWxzZSk7CiAgICBjb25zdCBbcGFydGljaXBhbnRzLCBzZXRQYXJ0aWNpcGFudHNdID0gdXNlU3RhdGUoW10pOwogICAgY29uc3QgW21lc3NhZ2VzLCBzZXRNZXNzYWdlc10gPSB1c2VTdGF0ZShbXSk7CiAgICBjb25zdCBbbWVzc2FnZUlucHV0LCBzZXRNZXNzYWdlSW5wdXRdID0gdXNlU3RhdGUoJycpOwogICAgY29uc3QgW3Jvb21Ub0pvaW4sIHNldFJvb21Ub0pvaW5dID0gdXNlU3RhdGUoJycpOwogICAgY29uc3QgW2Vycm9yLCBzZXRFcnJvcl0gPSB1c2VTdGF0ZSgnJyk7CiAgICBjb25zdCBwZWVyUmVmID0gdXNlUmVmKG51bGwpOwogICAgY29uc3QgY29ubmVjdGlvbnNSZWYgPSB1c2VSZWYobmV3IE1hcCgpKTsKICAgIGNvbnN0IGNoYXRDb250YWluZXJSZWYgPSB1c2VSZWYobnVsbCk7CiAgICBjb25zdCByZXNldFN0YXRlID0gdXNlQ2FsbGJhY2soKCkgPT4gewogICAgICAgIGNvbm5lY3Rpb25zUmVmLmN1cnJlbnQuZm9yRWFjaChjb25uID0+IGNvbm4uY2xvc2UoKSk7CiAgICAgICAgY29ubmVjdGlvbnNSZWYuY3VycmVudC5jbGVhcigpOwogICAgICAgIHBlZXJSZWYuY3VycmVudD8uZGVzdHJveSgpOwogICAgICAgIHBlZXJSZWYuY3VycmVudCA9IG51bGw7CiAgICAgICAgc2V0SXNIb3N0KGZhbHNlKTsKICAgICAgICBzZXRQYXJ0aWNpcGFudHMoW10pOwogICAgICAgIHNldE1lc3NhZ2VzKFtdKTsKICAgICAgICBzZXRFcnJvcignJyk7CiAgICAgICAgc2V0Um9vbVRvSm9pbignJyk7CiAgICAgICAgc2V0VmlldygnTE9CQlknKTsKICAgIH0sIFtdKTsKICAgIGNvbnN0IGJyb2FkY2FzdCA9IHVzZUNhbGxiYWNrKChkYXRhLCBleGNsdWRlSWQpID0+IHsKICAgICAgICBjb25uZWN0aW9uc1JlZi5jdXJyZW50LmZvckVhY2goKGNvbm4sIGlkKSA9PiB7CiAgICAgICAgICAgIGlmIChpZCAhPT0gZXhjbHVkZUlkICYmIGNvbm4ub3BlbikgewogICAgICAgICAgICAgICAgY29ubi5zZW5kKGRhdGEpOwogICAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICB9LCBbXSk7CiAgICBjb25zdCB1cGRhdGVBbmRCcm9hZGNhc3RQYXJ0aWNpcGFudHMgPSB1c2VDYWxsYmFjaygobmV3UGFydGljaXBhbnRzLCBtZXNzYWdlLCBleGNsdWRlSWQpID0+IHsKICAgICAgICBzZXRQYXJ0aWNpcGFudHMobmV3UGFydGljaXBhbnRzKTsKICAgICAgICBpZiAobWVzc2FnZSkgewogICAgICAgICAgICBzZXRNZXNzYWdlcyhwcmV2ID0+IFsuLi5wcmV2LCBjcmVhdGVTeXN0ZW1NZXNzYWdlKG1lc3NhZ2UpXSk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHVwZGF0ZVBheWxvYWQgPSB7CiAgICAgICAgICAgIHR5cGU6IFByb3RvY29sVHlwZS5QQVJUSUNJUEFOVF9VUERBVEUsCiAgICAgICAgICAgIHBheWxvYWQ6IHsgcGFydGljaXBhbnRzOiBuZXdQYXJ0aWNpcGFudHMgfQogICAgICAgIH07CiAgICAgICAgYnJvYWRjYXN0KHVwZGF0ZVBheWxvYWQsIGV4Y2x1ZGVJZCk7CiAgICB9LCBbYnJvYWRjYXN0XSk7CiAgICBjb25zdCBoYW5kbGVJbmNvbWluZ0RhdGEgPSB1c2VDYWxsYmFjaygoY29ubiwgZGF0YSkgPT4gewogICAgICAgIHN3aXRjaCAoZGF0YS50eXBlKSB7CiAgICAgICAgICAgIGNhc2UgUHJvdG9jb2xUeXBlLkhBTkRTSEFLRToKICAgICAgICAgICAgICAgIGlmIChpc0hvc3QpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdQYXJ0aWNpcGFudCA9IHsgaWQ6IGNvbm4ucGVlciwgbmFtZTogZGF0YS5wYXlsb2FkLm5hbWUgfTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50UGFydGljaXBhbnRzID0gWy4uLnBhcnRpY2lwYW50cywgbmV3UGFydGljaXBhbnRdOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHdlbGNvbWVQYXlsb2FkID0gewogICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBQcm90b2NvbFR5cGUuV0VMQ09NRV9JTkZPLAogICAgICAgICAgICAgICAgICAgICAgICBwYXlsb2FkOiB7IHBhcnRpY2lwYW50czogY3VycmVudFBhcnRpY2lwYW50cywgaGlzdG9yeTogbWVzc2FnZXMgfQogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgY29ubi5zZW5kKHdlbGNvbWVQYXlsb2FkKTsKICAgICAgICAgICAgICAgICAgICB1cGRhdGVBbmRCcm9hZGNhc3RQYXJ0aWNpcGFudHMoY3VycmVudFBhcnRpY2lwYW50cywgYCR7bmV3UGFydGljaXBhbnQubmFtZX0gaGFzIGpvaW5lZCB0aGUgY2hhdC5gLCBjb25uLnBlZXIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgUHJvdG9jb2xUeXBlLldFTENPTUVfSU5GTzoKICAgICAgICAgICAgICAgIHNldFBhcnRpY2lwYW50cyhkYXRhLnBheWxvYWQucGFydGljaXBhbnRzKTsKICAgICAgICAgICAgICAgIGNvbnN0IHdlbGNvbWVIaXN0b3J5ID0gWy4uLmRhdGEucGF5bG9hZC5oaXN0b3J5LCBjcmVhdGVTeXN0ZW1NZXNzYWdlKCdXZWxjb21lISBZb3UgaGF2ZSBqb2luZWQgdGhlIHJvb20uJyldOwogICAgICAgICAgICAgICAgc2V0TWVzc2FnZXMod2VsY29tZUhpc3RvcnkpOwogICAgICAgICAgICAgICAgc2V0VmlldygnQ0hBVCcpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgUHJvdG9jb2xUeXBlLlBBUlRJQ0lQQU5UX1VQREFURToKICAgICAgICAgICAgICAgIHNldFBhcnRpY2lwYW50cyhkYXRhLnBheWxvYWQucGFydGljaXBhbnRzKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIFByb3RvY29sVHlwZS5DSEFUX01FU1NBR0U6CiAgICAgICAgICAgICAgICBjb25zdCBzZW5kZXIgPSBwYXJ0aWNpcGFudHMuZmluZChwID0+IHAuaWQgPT09IGNvbm4ucGVlcik7CiAgICAgICAgICAgICAgICBpZiAoc2VuZGVyKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV3TWVzc2FnZSA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IGBtc2ctJHtjb25uLnBlZXJ9LSR7RGF0ZS5ub3coKX1gLAogICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBNZXNzYWdlVHlwZS5VU0VSX01FU1NBR0UsCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRlcjogc2VuZGVyLAogICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50OiBkYXRhLnBheWxvYWQuY29udGVudCwKICAgICAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvTG9jYWxlVGltZVN0cmluZyhbXSwgeyBob3VyOiAnMi1kaWdpdCcsIG1pbnV0ZTogJzItZGlnaXQnIH0pLAogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgc2V0TWVzc2FnZXMocHJldiA9PiBbLi4ucHJldiwgbmV3TWVzc2FnZV0pOwogICAgICAgICAgICAgICAgICAgIGlmIChpc0hvc3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmUtYnJvYWRjYXN0IG1lc3NhZ2UgZnJvbSBhIHBlZXIgdG8gYWxsIG90aGVyIHBlZXJzCiAgICAgICAgICAgICAgICAgICAgICAgIGJyb2FkY2FzdCh7IHR5cGU6IFByb3RvY29sVHlwZS5DSEFUX01FU1NBR0UsIHBheWxvYWQ6IHsgY29udGVudDogZGF0YS5wYXlsb2FkLmNvbnRlbnQgfSB9LCBjb25uLnBlZXIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgIH0sIFtpc0hvc3QsIGJyb2FkY2FzdCwgbWVzc2FnZXMsIHBhcnRpY2lwYW50cywgdXBkYXRlQW5kQnJvYWRjYXN0UGFydGljaXBhbnRzXSk7CiAgICBjb25zdCBzZXR1cENvbm5lY3Rpb25MaXN0ZW5lcnMgPSB1c2VDYWxsYmFjaygoY29ubikgPT4gewogICAgICAgIGNvbm4ub24oJ29wZW4nLCAoKSA9PiB7CiAgICAgICAgICAgIGNvbm5lY3Rpb25zUmVmLmN1cnJlbnQuc2V0KGNvbm4ucGVlciwgY29ubik7CiAgICAgICAgICAgIGlmICghaXNIb3N0KSB7IC8vIENsaWVudCBzZW5kcyBoYW5kc2hha2UKICAgICAgICAgICAgICAgIGNvbnN0IGhhbmRzaGFrZSA9IHsgdHlwZTogUHJvdG9jb2xUeXBlLkhBTkRTSEFLRSwgcGF5bG9hZDogeyBuYW1lOiB1c2VybmFtZSB9IH07CiAgICAgICAgICAgICAgICBjb25uLnNlbmQoaGFuZHNoYWtlKTsKICAgICAgICAgICAgfQogICAgICAgIH0pOwogICAgICAgIGNvbm4ub24oJ2RhdGEnLCAoZGF0YSkgPT4gaGFuZGxlSW5jb21pbmdEYXRhKGNvbm4sIGRhdGEpKTsKICAgICAgICBjb25uLm9uKCdjbG9zZScsICgpID0+IHsKICAgICAgICAgICAgY29ubmVjdGlvbnNSZWYuY3VycmVudC5kZWxldGUoY29ubi5wZWVyKTsKICAgICAgICAgICAgaWYgKGlzSG9zdCkgewogICAgICAgICAgICAgICAgY29uc3QgbGVhdmluZ1BhcnRpY2lwYW50ID0gcGFydGljaXBhbnRzLmZpbmQocCA9PiBwLmlkID09PSBjb25uLnBlZXIpOwogICAgICAgICAgICAgICAgY29uc3QgdXBkYXRlZFBhcnRpY2lwYW50cyA9IHBhcnRpY2lwYW50cy5maWx0ZXIocCA9PiBwLmlkICE9PSBjb25uLnBlZXIpOwogICAgICAgICAgICAgICAgdXBkYXRlQW5kQnJvYWRjYXN0UGFydGljaXBhbnRzKHVwZGF0ZWRQYXJ0aWNpcGFudHMsIGxlYXZpbmdQYXJ0aWNpcGFudCA/IGAke2xlYXZpbmdQYXJ0aWNpcGFudC5uYW1lfSBoYXMgbGVmdCB0aGUgY2hhdC5gIDogJ0EgcGFydGljaXBhbnQgaGFzIGxlZnQgdGhlIGNoYXQuJyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgY29ubmVjdGlvbiB0aGF0IGNsb3NlZCB3YXMgdGhlIGhvc3QKICAgICAgICAgICAgICAgIGlmIChjb25uLnBlZXIgPT09IHJvb21Ub0pvaW4pIHsKICAgICAgICAgICAgICAgICAgICBzZXRNZXNzYWdlcyhwcmV2ID0+IFsuLi5wcmV2LCBjcmVhdGVTeXN0ZW1NZXNzYWdlKGBDb25uZWN0aW9uIHRvIHRoZSBob3N0IGxvc3QuIFlvdSBoYXZlIGJlZW4gZGlzY29ubmVjdGVkLmApXSk7CiAgICAgICAgICAgICAgICAgICAgc2V0RXJyb3IoJ0Rpc2Nvbm5lY3RlZCBmcm9tIGhvc3QuJyk7CiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChyZXNldFN0YXRlLCAzMDAwKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0pOwogICAgICAgIGNvbm4ub24oJ2Vycm9yJywgKGVycikgPT4gewogICAgICAgICAgICBjb25zb2xlLmVycm9yKCdDb25uZWN0aW9uIGVycm9yOicsIGVycik7CiAgICAgICAgICAgIHNldEVycm9yKGBDb25uZWN0aW9uIGVycm9yIHdpdGggJHtjb25uLnBlZXJ9LmApOwogICAgICAgICAgICBjb25uZWN0aW9uc1JlZi5jdXJyZW50LmRlbGV0ZShjb25uLnBlZXIpOwogICAgICAgIH0pOwogICAgfSwgW2hhbmRsZUluY29taW5nRGF0YSwgaXNIb3N0LCBwYXJ0aWNpcGFudHMsIHVzZXJuYW1lLCByZXNldFN0YXRlLCB1cGRhdGVBbmRCcm9hZGNhc3RQYXJ0aWNpcGFudHMsIHJvb21Ub0pvaW5dKTsKICAgIGNvbnN0IGluaXRpYWxpemVQZWVyID0gdXNlQ2FsbGJhY2soKCkgPT4gewogICAgICAgIGlmIChwZWVyUmVmLmN1cnJlbnQpIHsKICAgICAgICAgICAgcGVlclJlZi5jdXJyZW50LmRlc3Ryb3koKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgY29uc3QgcGVlciA9IG5ldyBQZWVyKCk7CiAgICAgICAgICAgIHBlZXJSZWYuY3VycmVudCA9IHBlZXI7CiAgICAgICAgICAgIHBlZXIub24oJ29wZW4nLCAoaWQpID0+IHsKICAgICAgICAgICAgICAgIHNldE15SWQoaWQpOwogICAgICAgICAgICAgICAgaWYgKGlzSG9zdCkgewogICAgICAgICAgICAgICAgICAgIHNldFBhcnRpY2lwYW50cyhwcmV2ID0+IHByZXYubWFwKHAgPT4gcC5pZCA9PT0gJ2hvc3QtcGVuZGluZycgPyB7IC4uLnAsIGlkIH0gOiBwKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBwZWVyLm9uKCdjb25uZWN0aW9uJywgKGNvbm4pID0+IHsKICAgICAgICAgICAgICAgIGlmIChpc0hvc3QpIHsKICAgICAgICAgICAgICAgICAgICBzZXR1cENvbm5lY3Rpb25MaXN0ZW5lcnMoY29ubik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1JlamVjdGluZyBpbmNvbWluZyBjb25uZWN0aW9uIGFzIG5vdCBhIGhvc3QuJyk7CiAgICAgICAgICAgICAgICAgICAgY29ubi5vbignb3BlbicsICgpID0+IGNvbm4uY2xvc2UoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBwZWVyLm9uKCdlcnJvcicsIChlcnIpID0+IHsKICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1BlZXJKUyBlcnJvcjonLCBlcnIpOwogICAgICAgICAgICAgICAgaWYgKGVyci50eXBlID09PSAncGVlci11bmF2YWlsYWJsZScpIHsKICAgICAgICAgICAgICAgICAgICBzZXRFcnJvcihgQ291bGQgbm90IGNvbm5lY3QgdG8gcm9vbS4gUGxlYXNlIGNoZWNrIHRoZSBJRCBhbmQgdHJ5IGFnYWluLmApOwogICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQocmVzZXRTdGF0ZSwgMzAwMCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBzZXRFcnJvcignQSBQMlAgZXJyb3Igb2NjdXJyZWQuIFBsZWFzZSB0cnkgYWdhaW4uJyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzZXRWaWV3KCdMT0JCWScpOwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgcGVlci5vbignZGlzY29ubmVjdGVkJywgKCkgPT4gewogICAgICAgICAgICAgICAgc2V0RXJyb3IoJ0Rpc2Nvbm5lY3RlZCBmcm9tIFAyUCBzZXJ2ZXIuIEF0dGVtcHRpbmcgdG8gcmVjb25uZWN0Li4uJyk7CiAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgIHBlZXIucmVjb25uZWN0KCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjYXRjaCAoZSkgewogICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoIlJlY29ubmVjdCBmYWlsZWQiLCBlKTsKICAgICAgICAgICAgICAgICAgICByZXNldFN0YXRlKCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICAvLyBJZiBjbGllbnQsIGNvbm5lY3QgdG8gaG9zdAogICAgICAgICAgICBpZiAoIWlzSG9zdCAmJiByb29tVG9Kb2luKSB7CiAgICAgICAgICAgICAgICBjb25zdCBjb25uID0gcGVlci5jb25uZWN0KHJvb21Ub0pvaW4sIHsgcmVsaWFibGU6IHRydWUgfSk7CiAgICAgICAgICAgICAgICBzZXR1cENvbm5lY3Rpb25MaXN0ZW5lcnMoY29ubik7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY2F0Y2ggKGUpIHsKICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGluaXRpYWxpemUgUGVlckpTOicsIGUpOwogICAgICAgICAgICBzZXRFcnJvcignQ291bGQgbm90IGluaXRpYWxpemUgUDJQIGVuZ2luZS4gWW91ciBicm93c2VyIG1pZ2h0IG5vdCBzdXBwb3J0IFdlYlJUQy4gUGxlYXNlIHJlZnJlc2guJyk7CiAgICAgICAgICAgIHNldFZpZXcoJ0xPQkJZJyk7CiAgICAgICAgfQogICAgfSwgW2lzSG9zdCwgcm9vbVRvSm9pbiwgc2V0dXBDb25uZWN0aW9uTGlzdGVuZXJzLCByZXNldFN0YXRlXSk7CiAgICB1c2VFZmZlY3QoKCkgPT4gewogICAgICAgIGNvbnN0IHNhdmVkTmFtZSA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdwMnAtdXNlcm5hbWUnKTsKICAgICAgICBpZiAoc2F2ZWROYW1lKSB7CiAgICAgICAgICAgIHNldFVzZXJuYW1lKHNhdmVkTmFtZSk7CiAgICAgICAgICAgIHNldFZpZXcoJ0xPQkJZJyk7CiAgICAgICAgfQogICAgfSwgW10pOwogICAgdXNlRWZmZWN0KCgpID0+IHsKICAgICAgICBpZiAoY2hhdENvbnRhaW5lclJlZi5jdXJyZW50KSB7CiAgICAgICAgICAgIGNoYXRDb250YWluZXJSZWYuY3VycmVudC5zY3JvbGxUb3AgPSBjaGF0Q29udGFpbmVyUmVmLmN1cnJlbnQuc2Nyb2xsSGVpZ2h0OwogICAgICAgIH0KICAgIH0sIFttZXNzYWdlc10pOwogICAgY29uc3QgaGFuZGxlTmFtZVN1Ym1pdCA9IChlKSA9PiB7CiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgIGlmICh1c2VybmFtZS50cmltKCkpIHsKICAgICAgICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ3AycC11c2VybmFtZScsIHVzZXJuYW1lLnRyaW0oKSk7CiAgICAgICAgICAgIHNldFZpZXcoJ0xPQkJZJyk7CiAgICAgICAgfQogICAgfTsKICAgIGNvbnN0IGNyZWF0ZVJvb20gPSAoKSA9PiB7CiAgICAgICAgc2V0SXNIb3N0KHRydWUpOwogICAgICAgIHNldFBhcnRpY2lwYW50cyhbeyBpZDogJ2hvc3QtcGVuZGluZycsIG5hbWU6IHVzZXJuYW1lIH1dKTsKICAgICAgICBzZXRWaWV3KCdDSEFUJyk7CiAgICAgICAgc2V0Um9vbVRvSm9pbignJyk7CiAgICB9OwogICAgY29uc3Qgam9pblJvb20gPSAoKSA9PiB7CiAgICAgICAgaWYgKCFyb29tVG9Kb2luLnRyaW0oKSkKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIHNldElzSG9zdChmYWxzZSk7CiAgICAgICAgc2V0VmlldygnQ0hBVCcpOwogICAgfTsKICAgIHVzZUVmZmVjdCgoKSA9PiB7CiAgICAgICAgaWYgKHZpZXcgPT09ICdDSEFUJykgewogICAgICAgICAgICBpbml0aWFsaXplUGVlcigpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgaWYgKHBlZXJSZWYuY3VycmVudCkgewogICAgICAgICAgICAgICAgcGVlclJlZi5jdXJyZW50LmRlc3Ryb3koKTsKICAgICAgICAgICAgICAgIHBlZXJSZWYuY3VycmVudCA9IG51bGw7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuICgpID0+IHsKICAgICAgICAgICAgaWYgKHBlZXJSZWYuY3VycmVudCkgewogICAgICAgICAgICAgICAgcGVlclJlZi5jdXJyZW50LmRlc3Ryb3koKTsKICAgICAgICAgICAgICAgIHBlZXJSZWYuY3VycmVudCA9IG51bGw7CiAgICAgICAgICAgIH0KICAgICAgICB9OwogICAgfSwgW3ZpZXcsIGluaXRpYWxpemVQZWVyXSk7CiAgICBjb25zdCBoYW5kbGVTZW5kTWVzc2FnZSA9IChlKSA9PiB7CiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgIGlmICghbWVzc2FnZUlucHV0LnRyaW0oKSkKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIGNvbnN0IG1lID0gcGFydGljaXBhbnRzLmZpbmQocCA9PiBwLmlkID09PSBteUlkKSB8fCB7IGlkOiBteUlkLCBuYW1lOiB1c2VybmFtZSB9OwogICAgICAgIGNvbnN0IG5ld01lc3NhZ2UgPSB7CiAgICAgICAgICAgIGlkOiBgbXNnLSR7bXlJZH0tJHtEYXRlLm5vdygpfWAsCiAgICAgICAgICAgIHR5cGU6IE1lc3NhZ2VUeXBlLlVTRVJfTUVTU0FHRSwKICAgICAgICAgICAgc2VuZGVyOiBtZSwKICAgICAgICAgICAgY29udGVudDogbWVzc2FnZUlucHV0LAogICAgICAgICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCkudG9Mb2NhbGVUaW1lU3RyaW5nKFtdLCB7IGhvdXI6ICcyLWRpZ2l0JywgbWludXRlOiAnMi1kaWdpdCcgfSksCiAgICAgICAgfTsKICAgICAgICBzZXRNZXNzYWdlcyhwcmV2ID0+IFsuLi5wcmV2LCBuZXdNZXNzYWdlXSk7CiAgICAgICAgY29uc3QgcGF5bG9hZCA9IHsKICAgICAgICAgICAgdHlwZTogUHJvdG9jb2xUeXBlLkNIQVRfTUVTU0FHRSwKICAgICAgICAgICAgcGF5bG9hZDogeyBjb250ZW50OiBtZXNzYWdlSW5wdXQgfSwKICAgICAgICB9OwogICAgICAgIGJyb2FkY2FzdChwYXlsb2FkKTsKICAgICAgICBzZXRNZXNzYWdlSW5wdXQoJycpOwogICAgfTsKICAgIGNvbnN0IGNvcHlUb0NsaXBib2FyZCA9ICgpID0+IHsKICAgICAgICBpZiAobXlJZCkgewogICAgICAgICAgICBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dChteUlkKTsKICAgICAgICB9CiAgICB9OwogICAgaWYgKHZpZXcgPT09ICdTRVRVUCcpIHsKICAgICAgICByZXR1cm4gKF9qc3goImRpdiIsIHsgY2xhc3NOYW1lOiAiaC1zY3JlZW4gdy1zY3JlZW4gZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcC00IiwgY2hpbGRyZW46IF9qc3hzKEdsYXNzUGFuZWwsIHsgY2xhc3NOYW1lOiAidy1mdWxsIG1heC13LW1kIHAtOCB0ZXh0LWNlbnRlciIsIGNoaWxkcmVuOiBbX2pzeCgiaDEiLCB7IGNsYXNzTmFtZTogInRleHQtM3hsIGZvbnQtYm9sZCBtYi0yIiwgY2hpbGRyZW46ICJXZWxjb21lIHRvIFAyUCBDaGF0IiB9KSwgX2pzeCgicCIsIHsgY2xhc3NOYW1lOiAidGV4dC13aGl0ZS83MCBtYi02IiwgY2hpbGRyZW46ICJQbGVhc2Ugc2V0IHlvdXIgZGlzcGxheSBuYW1lIHRvIGJlZ2luLiIgfSksIF9qc3hzKCJmb3JtIiwgeyBvblN1Ym1pdDogaGFuZGxlTmFtZVN1Ym1pdCwgY2xhc3NOYW1lOiAiZmxleCBmbGV4LWNvbCBzcGFjZS15LTQiLCBjaGlsZHJlbjogW19qc3goImlucHV0IiwgeyB0eXBlOiAidGV4dCIsIHZhbHVlOiB1c2VybmFtZSwgb25DaGFuZ2U6IChlKSA9PiBzZXRVc2VybmFtZShlLnRhcmdldC52YWx1ZSksIHBsYWNlaG9sZGVyOiAiRW50ZXIgeW91ciBuYW1lIiwgY2xhc3NOYW1lOiAiYmctYmxhY2svMjAgdGV4dC1sZyB0ZXh0LWNlbnRlciByb3VuZGVkLWxnIHB4LTQgcHktMyBmb2N1czpyaW5nLTIgZm9jdXM6cmluZy1waW5rLTUwMCBmb2N1czpvdXRsaW5lLW5vbmUgdHJhbnNpdGlvbiIsIGF1dG9Gb2N1czogdHJ1ZSB9KSwgX2pzeCgiYnV0dG9uIiwgeyB0eXBlOiAic3VibWl0IiwgZGlzYWJsZWQ6ICF1c2VybmFtZS50cmltKCksIGNsYXNzTmFtZTogImJnLXBpbmstNTAwIGhvdmVyOmJnLXBpbmstNjAwIGRpc2FibGVkOmJnLWdyYXktNTAwIGRpc2FibGVkOmN1cnNvci1ub3QtYWxsb3dlZCB0ZXh0LXdoaXRlIGZvbnQtYm9sZCBweS0zIHJvdW5kZWQtbGcgdHJhbnNpdGlvbi1hbGwgdGV4dC1sZyIsIGNoaWxkcmVuOiAiRW50ZXIgQ2hhdCIgfSldIH0pXSB9KSB9KSk7CiAgICB9CiAgICBpZiAodmlldyA9PT0gJ0xPQkJZJykgewogICAgICAgIHJldHVybiAoX2pzeCgiZGl2IiwgeyBjbGFzc05hbWU6ICJoLXNjcmVlbiB3LXNjcmVlbiBmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBwLTQiLCBjaGlsZHJlbjogX2pzeHMoR2xhc3NQYW5lbCwgeyBjbGFzc05hbWU6ICJ3LWZ1bGwgbWF4LXctbWQgcC04IiwgY2hpbGRyZW46IFtfanN4cygiZGl2IiwgeyBjbGFzc05hbWU6ICJmbGV4IGp1c3RpZnktYmV0d2VlbiBpdGVtcy1zdGFydCIsIGNoaWxkcmVuOiBbX2pzeHMoImRpdiIsIHsgY2hpbGRyZW46IFtfanN4KCJoMSIsIHsgY2xhc3NOYW1lOiAidGV4dC0zeGwgZm9udC1ib2xkIiwgY2hpbGRyZW46ICJMb2JieSIgfSksIF9qc3hzKCJwIiwgeyBjbGFzc05hbWU6ICJ0ZXh0LXdoaXRlLzcwIiwgY2hpbGRyZW46IFsiV2VsY29tZSwgIiwgX2pzeCgic3BhbiIsIHsgY2xhc3NOYW1lOiAiZm9udC1ib2xkIHRleHQtcGluay00MDAiLCBjaGlsZHJlbjogdXNlcm5hbWUgfSksICIhIl0gfSldIH0pLCBfanN4KCJidXR0b24iLCB7IG9uQ2xpY2s6ICgpID0+IHsgc2V0VXNlcm5hbWUoJycpOyBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbSgncDJwLXVzZXJuYW1lJyk7IHNldFZpZXcoJ1NFVFVQJyk7IH0sIGNsYXNzTmFtZTogInRleHQtd2hpdGUvNTAgaG92ZXI6dGV4dC13aGl0ZSB0cmFuc2l0aW9uIiwgdGl0bGU6ICJDaGFuZ2UgTmFtZSIsIGNoaWxkcmVuOiBfanN4KExvZ291dEljb24sIHt9KSB9KV0gfSksIF9qc3hzKCJkaXYiLCB7IGNsYXNzTmFtZTogIm10LTggc3BhY2UteS02IiwgY2hpbGRyZW46IFtfanN4KCJkaXYiLCB7IGNsYXNzTmFtZTogInRleHQtY2VudGVyIiwgY2hpbGRyZW46IF9qc3hzKCJidXR0b24iLCB7IG9uQ2xpY2s6IGNyZWF0ZVJvb20sIGNsYXNzTmFtZTogInctZnVsbCBiZy1pbmRpZ28tNTAwIGhvdmVyOmJnLWluZGlnby02MDAgdGV4dC13aGl0ZSBmb250LWJvbGQgcHktMyBweC00IHJvdW5kZWQtbGcgdHJhbnNpdGlvbi1hbGwgdGV4dC1sZyBmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBzcGFjZS14LTIiLCBjaGlsZHJlbjogW19qc3goUGx1c0ljb24sIHt9KSwgX2pzeCgic3BhbiIsIHsgY2hpbGRyZW46ICJDcmVhdGUgTmV3IFJvb20iIH0pXSB9KSB9KSwgX2pzeHMoImRpdiIsIHsgY2xhc3NOYW1lOiAiZmxleCBpdGVtcy1jZW50ZXIgc3BhY2UteC0yIiwgY2hpbGRyZW46IFtfanN4KCJociIsIHsgY2xhc3NOYW1lOiAiZmxleC1ncm93IGJvcmRlci13aGl0ZS8yMCIgfSksIF9qc3goInNwYW4iLCB7IGNsYXNzTmFtZTogInRleHQtd2hpdGUvNTAiLCBjaGlsZHJlbjogIk9SIiB9KSwgX2pzeCgiaHIiLCB7IGNsYXNzTmFtZTogImZsZXgtZ3JvdyBib3JkZXItd2hpdGUvMjAiIH0pXSB9KSwgX2pzeCgiZm9ybSIsIHsgb25TdWJtaXQ6IChlKSA9PiB7IGUucHJldmVudERlZmF1bHQoKTsgam9pblJvb20oKTsgfSwgY2hpbGRyZW46IF9qc3hzKCJkaXYiLCB7IGNsYXNzTmFtZTogInNwYWNlLXktMyIsIGNoaWxkcmVuOiBbX2pzeCgiaW5wdXQiLCB7IHR5cGU6ICJ0ZXh0IiwgdmFsdWU6IHJvb21Ub0pvaW4sIG9uQ2hhbmdlOiAoZSkgPT4gc2V0Um9vbVRvSm9pbihlLnRhcmdldC52YWx1ZSksIHBsYWNlaG9sZGVyOiAiRW50ZXIgUm9vbSBJRCB0byBqb2luIiwgY2xhc3NOYW1lOiAidy1mdWxsIGJnLWJsYWNrLzIwIHJvdW5kZWQtbGcgcHgtNCBweS0zIGZvY3VzOnJpbmctMiBmb2N1czpyaW5nLXBpbmstNTAwIGZvY3VzOm91dGxpbmUtbm9uZSB0cmFuc2l0aW9uIiB9KSwgX2pzeHMoImJ1dHRvbiIsIHsgdHlwZTogInN1Ym1pdCIsIGRpc2FibGVkOiAhcm9vbVRvSm9pbi50cmltKCksIGNsYXNzTmFtZTogInctZnVsbCBiZy1waW5rLTUwMCBob3ZlcjpiZy1waW5rLTYwMCBkaXNhYmxlZDpiZy1ncmF5LTUwMCBkaXNhYmxlZDpjdXJzb3Itbm90LWFsbG93ZWQgdGV4dC13aGl0ZSBmb250LWJvbGQgcHktMyBweC00IHJvdW5kZWQtbGcgdHJhbnNpdGlvbi1hbGwgZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgc3BhY2UteC0yIiwgY2hpbGRyZW46IFtfanN4KExpbmtJY29uLCB7fSksIF9qc3goInNwYW4iLCB7IGNoaWxkcmVuOiAiSm9pbiBSb29tIiB9KV0gfSldIH0pIH0pXSB9KSwgZXJyb3IgJiYgX2pzeCgicCIsIHsgY2xhc3NOYW1lOiAidGV4dC1yZWQtNDAwIG10LTQgdGV4dC1jZW50ZXIiLCBjaGlsZHJlbjogZXJyb3IgfSldIH0pIH0pKTsKICAgIH0KICAgIGNvbnN0IENoYXRCdWJibGUgPSAoeyBtc2cgfSkgPT4gewogICAgICAgIGlmIChtc2cudHlwZSA9PT0gTWVzc2FnZVR5cGUuU1lTVEVNX01FU1NBR0UpIHsKICAgICAgICAgICAgcmV0dXJuIF9qc3goImRpdiIsIHsgY2xhc3NOYW1lOiAidGV4dC1jZW50ZXIgdGV4dC1zbSB0ZXh0LXdoaXRlLzUwIGl0YWxpYyBweS0yIiwgY2hpbGRyZW46IG1zZy5jb250ZW50IH0pOwogICAgICAgIH0KICAgICAgICBjb25zdCBpc01lID0gbXNnLnNlbmRlci5pZCA9PT0gbXlJZDsKICAgICAgICByZXR1cm4gKF9qc3hzKCJkaXYiLCB7IGNsYXNzTmFtZTogYGZsZXggZ2FwLTMgJHtpc01lID8gJ2p1c3RpZnktZW5kJyA6ICdqdXN0aWZ5LXN0YXJ0J31gLCBjaGlsZHJlbjogWyFpc01lICYmIF9qc3goImRpdiIsIHsgY2xhc3NOYW1lOiAidy0xMCBoLTEwIHJvdW5kZWQtZnVsbCBiZy13aGl0ZS8yMCBmbGV4LXNocmluay0wIGZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIGZvbnQtYm9sZCB0ZXh0LXBpbmstMzAwIiwgY2hpbGRyZW46IG1zZy5zZW5kZXIubmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSB9KSwgX2pzeHMoImRpdiIsIHsgY2hpbGRyZW46IFtfanN4cygiZGl2IiwgeyBjbGFzc05hbWU6IGBmbGV4IGl0ZW1zLWJhc2VsaW5lIGdhcC0yICR7aXNNZSA/ICdqdXN0aWZ5LWVuZCcgOiAnanVzdGlmeS1zdGFydCd9YCwgY2hpbGRyZW46IFshaXNNZSAmJiBfanN4KCJzcGFuIiwgeyBjbGFzc05hbWU6ICJmb250LWJvbGQgdGV4dC1zbSIsIGNoaWxkcmVuOiBtc2cuc2VuZGVyLm5hbWUgfSksIF9qc3goInNwYW4iLCB7IGNsYXNzTmFtZTogInRleHQteHMgdGV4dC13aGl0ZS81MCIsIGNoaWxkcmVuOiBtc2cudGltZXN0YW1wIH0pXSB9KSwgX2pzeCgiZGl2IiwgeyBjbGFzc05hbWU6IGBtdC0xIG1heC13LXhzIG1kOm1heC13LW1kIGxnOm1heC13LWxnIHB4LTQgcHktMyByb3VuZGVkLTJ4bCBicmVhay13b3JkcyAke2lzTWUgPyAnYmctcGluay01MDAgcm91bmRlZC1ici1ub25lJyA6ICdiZy13aGl0ZS8yMCByb3VuZGVkLWJsLW5vbmUnfWAsIGNoaWxkcmVuOiBtc2cuY29udGVudCB9KV0gfSldIH0pKTsKICAgIH07CiAgICByZXR1cm4gKF9qc3hzKCJkaXYiLCB7IGNsYXNzTmFtZTogImgtc2NyZWVuIHctc2NyZWVuIGZsZXggcC00IHNwYWNlLXgtNCIsIGNoaWxkcmVuOiBbX2pzeCgiYXNpZGUiLCB7IGNsYXNzTmFtZTogInctZnVsbCBtYXgtdy14cyBmbGV4LXNocmluay0wIiwgY2hpbGRyZW46IF9qc3hzKEdsYXNzUGFuZWwsIHsgY2xhc3NOYW1lOiAicC02IGgtZnVsbCBmbGV4IGZsZXgtY29sIiwgY2hpbGRyZW46IFtfanN4cygiaDIiLCB7IGNsYXNzTmFtZTogInRleHQteGwgZm9udC1ib2xkIGZsZXggaXRlbXMtY2VudGVyIGdhcC0zIiwgY2hpbGRyZW46IFtfanN4KFVzZXJzSWNvbiwge30pLCAiIFBhcnRpY2lwYW50cyAoIiwgcGFydGljaXBhbnRzLmxlbmd0aCwgIikiXSB9KSwgX2pzeCgidWwiLCB7IGNsYXNzTmFtZTogIm10LTQgc3BhY2UteS0zIGZsZXgtZ3JvdyBvdmVyZmxvdy15LWF1dG8iLCBjaGlsZHJlbjogcGFydGljaXBhbnRzLm1hcChwID0+IChfanN4cygibGkiLCB7IGNsYXNzTmFtZTogYGZsZXggaXRlbXMtY2VudGVyIGdhcC0zIHAtMiByb3VuZGVkLWxnICR7cC5pZCA9PT0gbXlJZCA/ICdiZy13aGl0ZS8yMCcgOiAnJ31gLCBjaGlsZHJlbjogW19qc3goImRpdiIsIHsgY2xhc3NOYW1lOiBgdy0zIGgtMyByb3VuZGVkLWZ1bGwgJHtwLmlkID09PSBteUlkIHx8IChpc0hvc3QgJiYgcC5pZCA9PT0gJ2hvc3QtcGVuZGluZycpID8gJ2JnLWdyZWVuLTQwMCcgOiAnYmctZ3JheS00MDAnfWAgfSksIF9qc3hzKCJzcGFuIiwgeyBjbGFzc05hbWU6ICJmb250LW1lZGl1bSB0cnVuY2F0ZSIsIGNoaWxkcmVuOiBbcC5uYW1lLCAiICIsIHAuaWQgPT09IG15SWQgJiYgJyhZb3UpJ10gfSksIGlzSG9zdCAmJiAocC5pZCA9PT0gbXlJZCB8fCBwLmlkID09PSAnaG9zdC1wZW5kaW5nJykgJiYgX2pzeCgic3BhbiIsIHsgY2xhc3NOYW1lOiAidGV4dC14cyBiZy1waW5rLTUwMCBweC0yIHB5LTAuNSByb3VuZGVkLWZ1bGwgbWwtYXV0byIsIGNoaWxkcmVuOiAiSG9zdCIgfSldIH0sIHAuaWQpKSkgfSksIGlzSG9zdCAmJiBteUlkICYmIChfanN4cygiZGl2IiwgeyBjbGFzc05hbWU6ICJtdC00IHB0LTQgYm9yZGVyLXQgYm9yZGVyLXdoaXRlLzIwIiwgY2hpbGRyZW46IFtfanN4KCJsYWJlbCIsIHsgY2xhc3NOYW1lOiAidGV4dC1zbSBmb250LXNlbWlib2xkIHRleHQtd2hpdGUvNzAiLCBjaGlsZHJlbjogIlJvb20gSUQgKFNoYXJlIHdpdGggb3RoZXJzKSIgfSksIF9qc3hzKCJkaXYiLCB7IGNsYXNzTmFtZTogImZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktYmV0d2VlbiBiZy1ibGFjay8zMCBwLTIgbXQtMiByb3VuZGVkLW1kIiwgY2hpbGRyZW46IFtfanN4KCJzcGFuIiwgeyBjbGFzc05hbWU6ICJmb250LW1vbm8gdGV4dC1waW5rLTMwMCB0ZXh0LXNtIHRydW5jYXRlIiwgY2hpbGRyZW46IG15SWQgfSksIF9qc3goImJ1dHRvbiIsIHsgb25DbGljazogY29weVRvQ2xpcGJvYXJkLCBjbGFzc05hbWU6ICJ0ZXh0LXdoaXRlLzYwIGhvdmVyOnRleHQtd2hpdGUgdHJhbnNpdGlvbi1jb2xvcnMgcC0xIiwgdGl0bGU6ICJDb3B5IElEIiwgY2hpbGRyZW46IF9qc3goQ29weUljb24sIHt9KSB9KV0gfSldIH0pKSwgX2pzeHMoImJ1dHRvbiIsIHsgb25DbGljazogcmVzZXRTdGF0ZSwgY2xhc3NOYW1lOiAibXQtNCB3LWZ1bGwgdGV4dC1jZW50ZXIgYmctcmVkLTUwMC81MCBob3ZlcjpiZy1yZWQtNTAwLzgwIHAtMiByb3VuZGVkLWxnIHRyYW5zaXRpb24tY29sb3JzIGZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIGdhcC0yIiwgY2hpbGRyZW46IFtfanN4KExvZ291dEljb24sIHt9KSwgIiBMZWF2ZSBSb29tIl0gfSldIH0pIH0pLCBfanN4KCJtYWluIiwgeyBjbGFzc05hbWU6ICJmbGV4LTEgZmxleCBmbGV4LWNvbCIsIGNoaWxkcmVuOiBfanN4cyhHbGFzc1BhbmVsLCB7IGNsYXNzTmFtZTogImZsZXgtMSBmbGV4IGZsZXgtY29sIGgtZnVsbCIsIGNoaWxkcmVuOiBbX2pzeCgiaGVhZGVyIiwgeyBjbGFzc05hbWU6ICJmbGV4LXNocmluay0wIHAtNCBib3JkZXItYiBib3JkZXItd2hpdGUvMjAiLCBjaGlsZHJlbjogX2pzeCgiaDIiLCB7IGNsYXNzTmFtZTogInRleHQtbGcgZm9udC1zZW1pYm9sZCIsIGNoaWxkcmVuOiAiQ2hhdCBSb29tIiB9KSB9KSwgX2pzeHMoImRpdiIsIHsgcmVmOiBjaGF0Q29udGFpbmVyUmVmLCBjbGFzc05hbWU6ICJmbGV4LTEgcC02IG92ZXJmbG93LXktYXV0byBzcGFjZS15LTYiLCBjaGlsZHJlbjogW21lc3NhZ2VzLmxlbmd0aCA9PT0gMCAmJiAhaXNIb3N0ICYmIF9qc3goImRpdiIsIHsgY2xhc3NOYW1lOiAidGV4dC1jZW50ZXIgdGV4dC13aGl0ZS81MCIsIGNoaWxkcmVuOiAiQ29ubmVjdGluZyB0byBob3N0Li4uIiB9KSwgbWVzc2FnZXMubGVuZ3RoID09PSAwICYmIGlzSG9zdCAmJiBfanN4KCJkaXYiLCB7IGNsYXNzTmFtZTogInRleHQtY2VudGVyIHRleHQtd2hpdGUvNTAiLCBjaGlsZHJlbjogIldhaXRpbmcgZm9yIHBhcnRpY2lwYW50cy4uLiIgfSksIG1lc3NhZ2VzLm1hcChtc2cgPT4gX2pzeChDaGF0QnViYmxlLCB7IG1zZzogbXNnIH0sIG1zZy5pZCkpXSB9KSwgX2pzeCgiZm9vdGVyIiwgeyBjbGFzc05hbWU6ICJmbGV4LXNocmluay0wIHAtNCIsIGNoaWxkcmVuOiBfanN4cygiZm9ybSIsIHsgb25TdWJtaXQ6IGhhbmRsZVNlbmRNZXNzYWdlLCBjbGFzc05hbWU6ICJmbGV4IGl0ZW1zLWNlbnRlciBzcGFjZS14LTQiLCBjaGlsZHJlbjogW19qc3goImlucHV0IiwgeyB0eXBlOiAidGV4dCIsIHZhbHVlOiBtZXNzYWdlSW5wdXQsIG9uQ2hhbmdlOiAoZSkgPT4gc2V0TWVzc2FnZUlucHV0KGUudGFyZ2V0LnZhbHVlKSwgcGxhY2Vob2xkZXI6ICJUeXBlIGEgbWVzc2FnZS4uLiIsIGNsYXNzTmFtZTogImZsZXgtZ3JvdyBiZy1ibGFjay8zMCBiYWNrZHJvcC1ibHVyLXNtIGJvcmRlciBib3JkZXItdHJhbnNwYXJlbnQgcm91bmRlZC1mdWxsIHB4LTUgcHktMyBmb2N1czpyaW5nLTIgZm9jdXM6cmluZy1waW5rLTUwMCBmb2N1czpvdXRsaW5lLW5vbmUgdHJhbnNpdGlvbiIgfSksIF9qc3goImJ1dHRvbiIsIHsgdHlwZTogInN1Ym1pdCIsIGRpc2FibGVkOiAhbWVzc2FnZUlucHV0LnRyaW0oKSwgY2xhc3NOYW1lOiAiYmctcGluay01MDAgaG92ZXI6YmctcGluay02MDAgZGlzYWJsZWQ6YmctZ3JheS02MDAvNTAgZGlzYWJsZWQ6Y3Vyc29yLW5vdC1hbGxvd2VkIHRleHQtd2hpdGUgcm91bmRlZC1mdWxsIHAtMyB0cmFuc2l0aW9uLWNvbG9ycyBmbGV4LXNocmluay0wIiwgY2hpbGRyZW46IF9qc3goU2VuZEljb24sIHt9KSB9KV0gfSkgfSldIH0pIH0pXSB9KSk7Cn07Cg=="}}</script> | |
| <script> | |
| window.APPLET_FILES = ["index.tsx","metadata.json","index.html","types.ts","components/icons.tsx","App.tsx"]; | |
| </script> | |
| <script type="module"> | |
| window.API_KEY = 'GEMINI_API_KEY'; | |
| window.GEMINI_API_KEY = 'GEMINI_API_KEY'; | |
| window.process = window.process || {}; | |
| window.process.env = window.process.env || {}; | |
| window.process.env.API_KEY = window.API_KEY; | |
| window.process.env.GEMINI_API_KEY = window.GEMINI_API_KEY; | |
| (() => { | |
| const bootstrapChannel = new Promise((resolve) => { | |
| window.addEventListener('message', (event) => { | |
| if (event.origin !== 'https://aistudio.google.com') { | |
| return; | |
| } | |
| if (event.data.type === 'bootstrap') { | |
| resolve({ | |
| port: event.ports[0], | |
| urlPatterns: | |
| event.data.urlPatterns.map((pattern) => new RegExp(pattern)), | |
| }); | |
| } | |
| }); | |
| }); | |
| window.aistudio = window.aistudio || { | |
| getHostUrl: async function() { | |
| const hostPort = (await bootstrapChannel).port; | |
| return new Promise((resolve) => { | |
| const channel = new MessageChannel(); | |
| hostPort.postMessage( | |
| {type: 'get_host_url'}, | |
| [channel.port2]); | |
| const port = channel.port1; | |
| port.onmessage = (message) => { | |
| resolve(message.data.url); | |
| }; | |
| }); | |
| }, | |
| }; | |
| const nativeFetch = window.fetch; | |
| /** | |
| * @param {string | URL | Request} resource The resource of the fetch request. | |
| * @param {RequestInit} options The options of the fetch request. | |
| * @return {Promise!} The promise of the fetch request. | |
| */ | |
| async function fetch(resource, options) { | |
| const config = await bootstrapChannel; | |
| const request = new Request(resource, options); | |
| if (!config.urlPatterns.some((pattern) => request.url.match(pattern))) { | |
| return nativeFetch(resource, options); | |
| } | |
| const hostPort = config.port; | |
| const channel = new MessageChannel(); | |
| const port = channel.port1; | |
| let bodyBytes; | |
| const transfer = [channel.port2]; | |
| const parts = []; | |
| const buffer = await request.arrayBuffer(); | |
| if (buffer.byteLength) { | |
| bodyBytes = buffer; | |
| transfer.push(bodyBytes); | |
| } | |
| hostPort.postMessage( | |
| { | |
| type: 'fetch', | |
| url: request.url, | |
| method: request.method, | |
| headers: [...request.headers.entries()], | |
| body: bodyBytes, | |
| }, | |
| transfer); | |
| let streamController; | |
| const body = new ReadableStream({ | |
| start(controller) { | |
| streamController = controller; | |
| }, | |
| }); | |
| let resolveReceive; | |
| const receivePromise = new Promise((resolve) => { | |
| resolveReceive = resolve; | |
| }); | |
| port.onmessage = (message) => { | |
| switch (message.data.type) { | |
| case 'response': | |
| resolveReceive(new Response(body, { | |
| status: message.data.status, | |
| statusText: message.data.statusText, | |
| headers: new Headers(message.data.headers), | |
| })); | |
| break; | |
| case 'body': | |
| streamController.enqueue(message.data.data); | |
| break; | |
| case 'body_done': | |
| streamController.close(); | |
| break; | |
| } | |
| }; | |
| return receivePromise; | |
| } | |
| Object.defineProperty(window, 'fetch', { | |
| get: function() { | |
| return fetch; | |
| }, | |
| }); | |
| const originalWebSocket = window.WebSocket; | |
| class ProxiedWebSocket extends EventTarget { | |
| /** | |
| * @param {string} url The url of the websocket. | |
| * @param {Object!} protocols The protocols of the websocket. | |
| */ | |
| constructor(url, protocols) { | |
| super(); | |
| this.url = url; | |
| this.protocols = protocols; | |
| this.open(); | |
| } | |
| /** Opens the websocket. */ | |
| async open() { | |
| const hostPort = (await bootstrapChannel).port; | |
| const channel = new MessageChannel(); | |
| hostPort.postMessage( | |
| {type: 'websocket_open', url: this.url, protocols: this.protocols}, | |
| [channel.port2]); | |
| this.port = channel.port1; | |
| this.port.onmessage = (message) => { | |
| if (message.data.type === 'close') { | |
| const event = new CloseEvent('close', { | |
| code: message.data.code, | |
| reason: message.data.reason, | |
| wasClean: message.data.wasClean, | |
| }); | |
| if (this.onclose) { | |
| this.onclose(event); | |
| } | |
| this.dispatchEvent(event); | |
| return; | |
| } else if (message.data.type === 'open') { | |
| const event = new Event('open'); | |
| if (this.onopen) { | |
| this.onopen(event); | |
| } | |
| this.dispatchEvent(event); | |
| return; | |
| } else if (message.data.type === 'message') { | |
| let data = message.data.data; | |
| if (message.data.messageType === 'text' || message.data.messageType === 'message') { | |
| data = new TextDecoder().decode(data); | |
| } | |
| const event = new MessageEvent('message', { | |
| data, | |
| type: message.data.messageType, | |
| }); | |
| if (this.onmessage) { | |
| this.onmessage(event); | |
| } | |
| this.dispatchEvent(event); | |
| return; | |
| } else if (message.data.type === 'error') { | |
| const event = new ErrorEvent('error', { | |
| message: message.data.message, | |
| }); | |
| if (this.onerror) { | |
| this.onerror(event); | |
| } | |
| this.dispatchEvent(event); | |
| return; | |
| } | |
| console.error('received unknown message in frame', event.data); | |
| }; | |
| } | |
| /** | |
| * @param {string|ArrayBuffer!} data The data to send. | |
| */ | |
| send(data) { | |
| if (typeof data === 'string') { | |
| this.port.postMessage({type: 'send', data}); | |
| } else { | |
| this.port.postMessage({type: 'send', data}, [data.buffer]); | |
| } | |
| } | |
| /** | |
| * @param {number} code The code of the close event. | |
| * @param {string} reason The reason of the close event. | |
| */ | |
| close(code, reason) { | |
| this.port.postMessage({type: 'close', code, reason}); | |
| } | |
| } | |
| /** | |
| * @param {string} url The url of the websocket. | |
| * @param {Object!} protocols The protocols of the websocket. | |
| * @return {WebSocket!} The websocket. | |
| */ | |
| function createWebSocket(url, protocols) { | |
| // This should come from the bootstrap channel, but we want this to | |
| // work for the synchronous constructor here. | |
| if (url.startsWith('wss://generativelanguage.googleapis.com/')) { | |
| return Reflect.construct(ProxiedWebSocket, [url, protocols]); | |
| } | |
| return Reflect.construct(originalWebSocket, [url, protocols]); | |
| } | |
| Object.defineProperty(window, 'WebSocket', { | |
| get: function() { | |
| return createWebSocket; | |
| }, | |
| }); | |
| async function instrumentErrorReporting() { | |
| const errors = []; | |
| let hostPort; | |
| function reportError(message) { | |
| if (!hostPort) { | |
| errors.push(message); | |
| } else { | |
| hostPort.postMessage({type: 'error', message: message}, message); | |
| } | |
| } | |
| function serialize(args) { | |
| return args.map((a) => { | |
| if (a instanceof Error || a instanceof ErrorEvent) { | |
| return a.message; | |
| } | |
| if(a instanceof CloseEvent) { | |
| return {code: a.code, reason: a.reason, wasClean: a.wasClean}; | |
| } | |
| if( a instanceof Map) { | |
| return JSON.parse(JSON.stringify([...a.entries()])); | |
| } | |
| if( a instanceof Set) { | |
| return JSON.parse(JSON.stringify([...a.values()])); | |
| } | |
| if (a instanceof Object) { | |
| return JSON.parse(JSON.stringify(a)); | |
| } | |
| return a; | |
| }); | |
| } | |
| const originalConsole = window.console; | |
| const originalConsoleLog = window.console.log; | |
| const originalConsoleError = window.console.error; | |
| const originalConsoleWarn = window.console.warn; | |
| const originalConsoleDebug = window.console.debug; | |
| window.console = { | |
| ...originalConsole, | |
| log: (message, ...args) => { | |
| originalConsoleLog.apply(window.console, [message, ...args]); | |
| const combined = serialize([message, ...args]); | |
| reportError({type: 'console_log', message: combined }); | |
| }, | |
| debug: (message, ...args) => { | |
| originalConsoleDebug.apply(window.console, [message, ...args]); | |
| const combined = serialize([message, ...args]); | |
| reportError({type: 'console_debug', message: combined }); | |
| }, | |
| error: (message, ...args) => { | |
| originalConsoleError.apply(window.console, [message, ...args]); | |
| const combined = serialize([message, ...args]); | |
| reportError({type: 'console_error', message: combined }); | |
| }, | |
| warn: (message, ...args) => { | |
| originalConsoleWarn.apply(window.console, [message, ...args]); | |
| const combined = serialize([message, ...args]); | |
| reportError({type: 'console_warn', message: combined }); | |
| }, | |
| }; | |
| window.onerror = (message, source, lineno, colno, error) => { | |
| reportError({type: 'error', message: serialize([message]), source, lineno, colno, error}); | |
| }; | |
| window.onunhandledrejection = (event) => { | |
| reportError({type: 'unhandledrejection', message: serialize([event.reason])}); | |
| }; | |
| window.alert = (message) => { | |
| reportError({type: 'alert', message: serialize([message]) }); | |
| }; | |
| hostPort = (await bootstrapChannel).port; | |
| for(const error of errors) { | |
| hostPort.postMessage({type: 'error', message: error}); | |
| } | |
| } | |
| const availableFiles = new Set(window.APPLET_FILES || []); | |
| instrumentErrorReporting(); | |
| window.addEventListener('hashchange', async (e) =>{ | |
| const config = await bootstrapChannel; | |
| const hostPort = config.port; | |
| hostPort.postMessage({type: 'hashchange', hash: window.location.hash}); | |
| }); | |
| })(); | |
| // # sourceURL=iframe_shim.js | |
| </script> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>P2P K-Style Messenger</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://unpkg.com/peerjs@1.5.2/dist/peerjs.min.js"></script> | |
| <style> | |
| /* Custom scrollbar for a more polished look */ | |
| ::-webkit-scrollbar { | |
| width: 8px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: rgba(255, 255, 255, 0.1); | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: rgba(255, 255, 255, 0.25); | |
| border-radius: 4px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: rgba(255, 255, 255, 0.4); | |
| } | |
| </style> | |
| <style>*, ::before, ::after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/* ! tailwindcss v3.4.16 | MIT License | https://tailwindcss.com */*,::after,::before{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}::after,::before{--tw-content:''}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.mb-2{margin-bottom:0.5rem}.mb-6{margin-bottom:1.5rem}.flex{display:flex}.h-screen{height:100vh}.w-full{width:100%}.w-screen{width:100vw}.max-w-md{max-width:28rem}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.space-y-4 > :not([hidden]) ~ :not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.rounded-2xl{border-radius:1rem}.rounded-lg{border-radius:0.5rem}.border{border-width:1px}.border-white\/20{border-color:rgb(255 255 255 / 0.2)}.bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1))}.bg-black\/20{background-color:rgb(0 0 0 / 0.2)}.bg-pink-500{--tw-bg-opacity:1;background-color:rgb(236 72 153 / var(--tw-bg-opacity, 1))}.bg-white\/10{background-color:rgb(255 255 255 / 0.1)}.bg-gradient-to-br{background-image:linear-gradient(to bottom right, var(--tw-gradient-stops))}.from-indigo-900{--tw-gradient-from:#312e81 var(--tw-gradient-from-position);--tw-gradient-to:rgb(49 46 129 / 0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.via-purple-900{--tw-gradient-to:rgb(88 28 135 / 0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), #581c87 var(--tw-gradient-via-position), var(--tw-gradient-to)}.to-pink-900{--tw-gradient-to:#831843 var(--tw-gradient-to-position)}.p-4{padding:1rem}.p-8{padding:2rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-top:0.75rem;padding-bottom:0.75rem}.text-center{text-align:center}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.font-bold{font-weight:700}.text-white{--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-white\/70{color:rgb(255 255 255 / 0.7)}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.shadow-lg{--tw-shadow:0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}.backdrop-blur-xl{--tw-backdrop-blur:blur(24px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color, background-color, border-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-text-decoration-color, -webkit-backdrop-filter;transition-property:color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;transition-property:color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-text-decoration-color, -webkit-backdrop-filter;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms}.hover\:bg-pink-600:hover{--tw-bg-opacity:1;background-color:rgb(219 39 119 / var(--tw-bg-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)}.focus\:ring-pink-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(236 72 153 / var(--tw-ring-opacity, 1))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-gray-500:disabled{--tw-bg-opacity:1;background-color:rgb(107 114 128 / var(--tw-bg-opacity, 1))}</style></head> | |
| <body class="bg-gray-900 text-white antialiased bg-gradient-to-br from-indigo-900 via-purple-900 to-pink-900"> | |
| <div id="root"><div class="h-screen w-screen flex items-center justify-center p-4"><div class="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl shadow-lg w-full max-w-md p-8 text-center"><h1 class="text-3xl font-bold mb-2">Welcome to P2P Chat</h1><p class="text-white/70 mb-6">Please set your display name to begin.</p><form class="flex flex-col space-y-4"><input placeholder="Enter your name" class="bg-black/20 text-lg text-center rounded-lg px-4 py-3 focus:ring-2 focus:ring-pink-500 focus:outline-none transition" type="text" value=""><button type="submit" disabled="" class="bg-pink-500 hover:bg-pink-600 disabled:bg-gray-500 disabled:cursor-not-allowed text-white font-bold py-3 rounded-lg transition-all text-lg">Enter Chat</button></form></div></div></div> | |
| <base href="https://ai.studio"> | |
| <script type="module">import '@/index';</script> | |
| </body></html> |