@hanzo/browser-extension 1.7.2

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 (134) hide show
  1. package/.github/workflows/docs.yml +44 -0
  2. package/.github/workflows/release.yml +55 -0
  3. package/LICENSE +21 -0
  4. package/README.md +126 -0
  5. package/dist/browser-extension/README.md +43 -0
  6. package/dist/browser-extension/ai-worker.js +30 -0
  7. package/dist/browser-extension/background-firefox.js +617 -0
  8. package/dist/browser-extension/background.js +2737 -0
  9. package/dist/browser-extension/browser-control.js +683 -0
  10. package/dist/browser-extension/cdp-bridge-server.js +444 -0
  11. package/dist/browser-extension/chrome/ai-worker.js +571 -0
  12. package/dist/browser-extension/chrome/background.js +2737 -0
  13. package/dist/browser-extension/chrome/callback.html +17 -0
  14. package/dist/browser-extension/chrome/content-script.js +1270 -0
  15. package/dist/browser-extension/chrome/icon128.png +0 -0
  16. package/dist/browser-extension/chrome/icon16.png +0 -0
  17. package/dist/browser-extension/chrome/icon32.png +0 -0
  18. package/dist/browser-extension/chrome/icon48.png +0 -0
  19. package/dist/browser-extension/chrome/manifest.json +57 -0
  20. package/dist/browser-extension/chrome/popup.css +519 -0
  21. package/dist/browser-extension/chrome/popup.html +242 -0
  22. package/dist/browser-extension/chrome/popup.js +267 -0
  23. package/dist/browser-extension/chrome/sidebar.css +1176 -0
  24. package/dist/browser-extension/chrome/sidebar.html +280 -0
  25. package/dist/browser-extension/chrome/sidebar.js +778 -0
  26. package/dist/browser-extension/cli.js +233 -0
  27. package/dist/browser-extension/content-script.js +1270 -0
  28. package/dist/browser-extension/firefox/ai-worker.js +571 -0
  29. package/dist/browser-extension/firefox/background.js +617 -0
  30. package/dist/browser-extension/firefox/callback.html +17 -0
  31. package/dist/browser-extension/firefox/content-script.js +1270 -0
  32. package/dist/browser-extension/firefox/icon128.png +0 -0
  33. package/dist/browser-extension/firefox/icon16.png +0 -0
  34. package/dist/browser-extension/firefox/icon32.png +0 -0
  35. package/dist/browser-extension/firefox/icon48.png +0 -0
  36. package/dist/browser-extension/firefox/manifest.json +66 -0
  37. package/dist/browser-extension/firefox/popup.css +519 -0
  38. package/dist/browser-extension/firefox/popup.html +242 -0
  39. package/dist/browser-extension/firefox/popup.js +267 -0
  40. package/dist/browser-extension/firefox/sidebar.css +1176 -0
  41. package/dist/browser-extension/firefox/sidebar.html +280 -0
  42. package/dist/browser-extension/firefox/sidebar.js +778 -0
  43. package/dist/browser-extension/hanzo-browser-extension-firefox-1.1.0.zip +0 -0
  44. package/dist/browser-extension/icon128.png +0 -0
  45. package/dist/browser-extension/icon16.png +0 -0
  46. package/dist/browser-extension/icon32.png +0 -0
  47. package/dist/browser-extension/icon48.png +0 -0
  48. package/dist/browser-extension/manifest.json +57 -0
  49. package/dist/browser-extension/package.json +41 -0
  50. package/dist/browser-extension/popup.css +468 -0
  51. package/dist/browser-extension/popup.html +191 -0
  52. package/dist/browser-extension/popup.js +267 -0
  53. package/dist/browser-extension/safari/Info.plist +21 -0
  54. package/dist/browser-extension/safari/ai-worker.js +571 -0
  55. package/dist/browser-extension/safari/background.js +2737 -0
  56. package/dist/browser-extension/safari/callback.html +17 -0
  57. package/dist/browser-extension/safari/content-script.js +1270 -0
  58. package/dist/browser-extension/safari/icon128.png +0 -0
  59. package/dist/browser-extension/safari/icon16.png +0 -0
  60. package/dist/browser-extension/safari/icon32.png +0 -0
  61. package/dist/browser-extension/safari/icon48.png +0 -0
  62. package/dist/browser-extension/safari/popup.css +519 -0
  63. package/dist/browser-extension/safari/popup.html +242 -0
  64. package/dist/browser-extension/safari/popup.js +267 -0
  65. package/dist/browser-extension/safari/sidebar.css +1176 -0
  66. package/dist/browser-extension/safari/sidebar.html +280 -0
  67. package/dist/browser-extension/safari/sidebar.js +778 -0
  68. package/dist/browser-extension/sidebar.css +718 -0
  69. package/dist/browser-extension/sidebar.html +184 -0
  70. package/dist/browser-extension/sidebar.js +778 -0
  71. package/dist/browser-extension/webgpu-ai.js +495 -0
  72. package/dist/cdp-bridge-server.js +411 -0
  73. package/dist/safari/Hanzo AI/Hanzo AI.xcodeproj/project.pbxproj +1047 -0
  74. package/dist/safari/Hanzo AI/Hanzo AI.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  75. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
  76. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/Contents.json +98 -0
  77. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-128@1x.png +0 -0
  78. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-128@2x.png +0 -0
  79. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-16@1x.png +0 -0
  80. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-16@2x.png +0 -0
  81. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-256@1x.png +0 -0
  82. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-256@2x.png +0 -0
  83. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-32@1x.png +0 -0
  84. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-32@2x.png +0 -0
  85. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-512@1x.png +0 -0
  86. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-512@2x.png +0 -0
  87. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/universal-icon-1024@1x.png +0 -0
  88. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/Contents.json +6 -0
  89. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/LargeIcon.imageset/Contents.json +21 -0
  90. package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/LargeIcon.imageset/icon128.png +0 -0
  91. package/dist/safari/Hanzo AI/Shared (App)/Resources/Base.lproj/Main.html +20 -0
  92. package/dist/safari/Hanzo AI/Shared (App)/Resources/Icon.png +0 -0
  93. package/dist/safari/Hanzo AI/Shared (App)/Resources/Script.js +24 -0
  94. package/dist/safari/Hanzo AI/Shared (App)/Resources/Style.css +61 -0
  95. package/dist/safari/Hanzo AI/Shared (App)/ViewController.swift +81 -0
  96. package/dist/safari/Hanzo AI/Shared (Extension)/SafariWebExtensionHandler.swift +42 -0
  97. package/dist/safari/Hanzo AI/iOS (App)/AppDelegate.swift +24 -0
  98. package/dist/safari/Hanzo AI/iOS (App)/Base.lproj/LaunchScreen.storyboard +36 -0
  99. package/dist/safari/Hanzo AI/iOS (App)/Base.lproj/Main.storyboard +38 -0
  100. package/dist/safari/Hanzo AI/iOS (App)/Info.plist +27 -0
  101. package/dist/safari/Hanzo AI/iOS (App)/SceneDelegate.swift +18 -0
  102. package/dist/safari/Hanzo AI/iOS (Extension)/Info.plist +13 -0
  103. package/dist/safari/Hanzo AI/macOS (App)/AppDelegate.swift +21 -0
  104. package/dist/safari/Hanzo AI/macOS (App)/Base.lproj/Main.storyboard +124 -0
  105. package/dist/safari/Hanzo AI/macOS (App)/Info.plist +8 -0
  106. package/dist/safari/Hanzo AI/macOS (Extension)/Info.plist +13 -0
  107. package/docs/_config.yml +13 -0
  108. package/docs/_layouts/default.html +435 -0
  109. package/docs/index.md +54 -0
  110. package/install-extension.sh +75 -0
  111. package/manifest.json +29 -0
  112. package/package.json +32 -0
  113. package/src/ai-worker.js +571 -0
  114. package/src/callback.html +17 -0
  115. package/src/chat-widget.tsx +93 -0
  116. package/src/icon128.png +0 -0
  117. package/src/icon16.png +0 -0
  118. package/src/icon32.png +0 -0
  119. package/src/icon48.png +0 -0
  120. package/src/manifest-firefox.json +66 -0
  121. package/src/manifest.json +57 -0
  122. package/src/package.json +41 -0
  123. package/src/popup.css +519 -0
  124. package/src/popup.html +242 -0
  125. package/src/popup.js +192 -0
  126. package/src/sidebar.css +1176 -0
  127. package/src/sidebar.html +280 -0
  128. package/src/sidebar.js +884 -0
  129. package/src/webgpu.d.ts +131 -0
  130. package/test/claude-integration.test.ts +251 -0
  131. package/test/server-frameworks-edge-cases.test.ts +145 -0
  132. package/test/server-frameworks.test.ts +395 -0
  133. package/test-cdp-connection.js +140 -0
  134. package/tsconfig.json +19 -0
@@ -0,0 +1,242 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Hanzo AI</title>
7
+ <link rel="stylesheet" href="popup.css">
8
+ </head>
9
+ <body>
10
+ <div class="container">
11
+ <header>
12
+ <svg class="logo" viewBox="0 0 67 67" xmlns="http://www.w3.org/2000/svg">
13
+ <path d="M22.21 67V44.6369H0V67H22.21Z" fill="currentColor"/>
14
+ <path d="M66.7038 22.3184H22.2534L0.0878906 44.6367H44.4634L66.7038 22.3184Z" fill="currentColor"/>
15
+ <path d="M22.21 0H0V22.3184H22.21V0Z" fill="currentColor"/>
16
+ <path d="M66.7198 0H44.5098V22.3184H66.7198V0Z" fill="currentColor"/>
17
+ <path d="M66.7198 67V44.6369H44.5098V67H66.7198Z" fill="currentColor"/>
18
+ </svg>
19
+ <h1>Hanzo AI</h1>
20
+ </header>
21
+
22
+ <!-- Login Section -->
23
+ <div id="login-section" class="section">
24
+ <h2>Sign In</h2>
25
+ <p class="subtitle">Connect to your Hanzo AI account</p>
26
+ <button id="login-btn" class="btn btn-primary">Sign in with Hanzo</button>
27
+ <p class="help-text">
28
+ <a href="https://hanzo.id/register" target="_blank">Create account</a> •
29
+ <a href="https://hanzo.id/forgot" target="_blank">Forgot password?</a>
30
+ </p>
31
+ </div>
32
+
33
+ <!-- Main Section (shown after login) -->
34
+ <div id="main-section" class="section hidden">
35
+ <div class="user-info">
36
+ <img id="user-avatar" class="avatar" src="" alt="">
37
+ <div>
38
+ <div id="user-name" class="user-name"></div>
39
+ <div id="user-email" class="user-email"></div>
40
+ </div>
41
+ <button id="logout-btn" class="btn-icon" title="Sign out">
42
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
43
+ <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/>
44
+ </svg>
45
+ </button>
46
+ </div>
47
+
48
+ <div class="divider"></div>
49
+
50
+ <!-- Open Chat Panel -->
51
+ <button id="open-panel" class="btn btn-primary" style="margin-bottom: 16px;">
52
+ <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
53
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
54
+ </svg>
55
+ Open Chat Panel
56
+ </button>
57
+ <button id="open-page-overlay" class="btn btn-secondary" style="margin-bottom: 16px;">
58
+ <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
59
+ <path d="M4 4h16v12H8l-4 4V4z"/>
60
+ </svg>
61
+ Toggle On-Page Overlay
62
+ </button>
63
+
64
+ <!-- Features -->
65
+ <div class="features">
66
+ <div class="feature-toggle">
67
+ <label>
68
+ <input type="checkbox" id="source-maps" checked>
69
+ <span class="toggle"></span>
70
+ <div class="feature-info">
71
+ <strong>Source Maps</strong>
72
+ <small>Click-to-code navigation</small>
73
+ </div>
74
+ </label>
75
+ </div>
76
+
77
+ <div class="feature-toggle">
78
+ <label>
79
+ <input type="checkbox" id="webgpu-ai" checked>
80
+ <span class="toggle"></span>
81
+ <div class="feature-info">
82
+ <strong>WebGPU AI</strong>
83
+ <small>Local AI inference</small>
84
+ </div>
85
+ </label>
86
+ </div>
87
+
88
+ <div class="feature-toggle">
89
+ <label>
90
+ <input type="checkbox" id="browser-control">
91
+ <span class="toggle"></span>
92
+ <div class="feature-info">
93
+ <strong>Browser Control</strong>
94
+ <small>AI browser automation</small>
95
+ </div>
96
+ </label>
97
+ </div>
98
+
99
+ <div class="feature-toggle">
100
+ <label>
101
+ <input type="checkbox" id="tab-filesystem">
102
+ <span class="toggle"></span>
103
+ <div class="feature-info">
104
+ <strong>Tab Filesystem</strong>
105
+ <small>Mount tabs as files</small>
106
+ </div>
107
+ </label>
108
+ </div>
109
+ </div>
110
+
111
+ <div class="divider"></div>
112
+
113
+ <!-- Browser Backend -->
114
+ <div class="setting-group backend-picker">
115
+ <h3>Browser Backend</h3>
116
+ <div class="backend-select-wrapper">
117
+ <select id="browser-backend">
118
+ <option value="auto">Auto (default)</option>
119
+ <option value="this">This Browser</option>
120
+ <option value="firefox">Firefox</option>
121
+ <option value="chrome">Chrome</option>
122
+ <option value="playwright">Playwright Only</option>
123
+ </select>
124
+ </div>
125
+ <div class="backend-status">
126
+ <span class="status-dot" id="bridge-status"></span>
127
+ <span id="bridge-detail" class="status-detail">Checking bridge...</span>
128
+ </div>
129
+ </div>
130
+
131
+ <div class="divider"></div>
132
+
133
+ <!-- Connection Status -->
134
+ <div class="status">
135
+ <div class="status-item">
136
+ <span class="status-dot" id="zap-status"></span>
137
+ <span>ZAP Protocol</span>
138
+ <span id="zap-detail" class="status-detail">Discovering...</span>
139
+ </div>
140
+ <div class="status-item">
141
+ <span class="status-dot" id="mcp-status"></span>
142
+ <span>MCP Server</span>
143
+ <span id="mcp-port" class="status-detail">Fallback</span>
144
+ </div>
145
+ <div class="status-item">
146
+ <span class="status-dot" id="cdp-status"></span>
147
+ <span>CDP Bridge</span>
148
+ <span id="cdp-detail" class="status-detail">Checking...</span>
149
+ </div>
150
+ <div class="status-item">
151
+ <span class="status-dot" id="gpu-status"></span>
152
+ <span>WebGPU</span>
153
+ <span id="gpu-detail" class="status-detail">Checking...</span>
154
+ </div>
155
+ </div>
156
+
157
+ <div class="divider"></div>
158
+
159
+ <!-- Actions -->
160
+ <div class="actions">
161
+ <button id="test-connection" class="btn btn-secondary">Test Connection</button>
162
+ <button id="open-settings" class="btn btn-secondary">Settings</button>
163
+ </div>
164
+
165
+ <!-- Quick Guide -->
166
+ <div class="guide" style="margin-top: 16px;">
167
+ <h3>Quick Guide</h3>
168
+ <p><kbd>Alt</kbd> + <kbd>Click</kbd> any element to navigate to source</p>
169
+ <p><kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>H</kbd> to open Hanzo AI panel</p>
170
+ </div>
171
+ </div>
172
+
173
+ <!-- Settings Section -->
174
+ <div id="settings-section" class="section hidden">
175
+ <div class="settings-header">
176
+ <button id="back-btn" class="btn-icon">
177
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
178
+ <path d="M19 12H5M12 19l-7-7 7-7"/>
179
+ </svg>
180
+ </button>
181
+ <h2>Settings</h2>
182
+ </div>
183
+
184
+ <div class="settings-content">
185
+ <div class="setting-group">
186
+ <h3>Connection</h3>
187
+ <label>
188
+ MCP Port
189
+ <input type="number" id="mcp-port-setting" value="3001" min="1024" max="65535">
190
+ </label>
191
+ <label>
192
+ CDP Bridge Port
193
+ <input type="number" id="cdp-port-setting" value="9223" min="1024" max="65535">
194
+ </label>
195
+ <label>
196
+ ZAP Discovery Ports
197
+ <input type="text" id="zap-ports-setting" value="9999,9998,9997,9996,9995" placeholder="Comma-separated ports">
198
+ </label>
199
+ </div>
200
+
201
+ <div class="setting-group">
202
+ <h3>AI Models</h3>
203
+ <label>
204
+ Local Model Path
205
+ <input type="text" id="model-path" placeholder="/models/browser-control-4bit.bin">
206
+ </label>
207
+ <label>
208
+ Model Quantization
209
+ <select id="model-quant">
210
+ <option value="4bit">4-bit (Fastest)</option>
211
+ <option value="8bit">8-bit (Balanced)</option>
212
+ <option value="fp16">FP16 (Best Quality)</option>
213
+ </select>
214
+ </label>
215
+ </div>
216
+
217
+ <div class="setting-group">
218
+ <h3>Browser Control</h3>
219
+ <label>
220
+ <input type="checkbox" id="safe-mode" checked>
221
+ Safe Mode (require confirmation for actions)
222
+ </label>
223
+ <label>
224
+ Max Workers
225
+ <input type="number" id="max-workers" value="3" min="1" max="10">
226
+ </label>
227
+ </div>
228
+
229
+ <button id="save-settings" class="btn btn-primary">Save Settings</button>
230
+
231
+ <p class="help-text" style="margin-top: 16px;">
232
+ <a href="https://console.hanzo.ai" target="_blank">Console</a> •
233
+ <a href="https://billing.hanzo.ai" target="_blank">Billing</a> •
234
+ <a href="https://docs.hanzo.ai" target="_blank">Docs</a>
235
+ </p>
236
+ </div>
237
+ </div>
238
+ </div>
239
+
240
+ <script src="popup.js"></script>
241
+ </body>
242
+ </html>
@@ -0,0 +1,267 @@
1
+ "use strict";
2
+ (() => {
3
+ // src/popup.ts
4
+ document.addEventListener("DOMContentLoaded", () => {
5
+ const loginSection = document.getElementById("login-section");
6
+ const mainSection = document.getElementById("main-section");
7
+ const settingsSection = document.getElementById("settings-section");
8
+ const loginBtn = document.getElementById("login-btn");
9
+ const logoutBtn = document.getElementById("logout-btn");
10
+ const openPanel = document.getElementById("open-panel");
11
+ const openPageOverlay = document.getElementById("open-page-overlay");
12
+ const zapStatus = document.getElementById("zap-status");
13
+ const zapDetail = document.getElementById("zap-detail");
14
+ const mcpStatus = document.getElementById("mcp-status");
15
+ const mcpPort = document.getElementById("mcp-port");
16
+ const cdpStatus = document.getElementById("cdp-status");
17
+ const cdpDetail = document.getElementById("cdp-detail");
18
+ const gpuStatus = document.getElementById("gpu-status");
19
+ const gpuDetail = document.getElementById("gpu-detail");
20
+ const openSettings = document.getElementById("open-settings");
21
+ const backBtn = document.getElementById("back-btn");
22
+ const saveSettings = document.getElementById("save-settings");
23
+ const testConnection = document.getElementById("test-connection");
24
+ function checkAuth() {
25
+ mainSection.classList.remove("hidden");
26
+ refreshStatus();
27
+ chrome.runtime.sendMessage({ action: "auth.status" }, (response) => {
28
+ if (chrome.runtime.lastError) return;
29
+ if ((response == null ? void 0 : response.success) && response.authenticated) {
30
+ loginSection.classList.add("hidden");
31
+ if (response.user) {
32
+ const avatar = document.getElementById("user-avatar");
33
+ const name = document.getElementById("user-name");
34
+ const email = document.getElementById("user-email");
35
+ avatar.src = response.user.picture || response.user.avatar || "icon48.png";
36
+ name.textContent = response.user.name || response.user.displayName || "Hanzo User";
37
+ email.textContent = response.user.email || "";
38
+ }
39
+ } else {
40
+ loginSection.classList.remove("hidden");
41
+ }
42
+ });
43
+ }
44
+ loginBtn == null ? void 0 : loginBtn.addEventListener("click", () => {
45
+ loginBtn.disabled = true;
46
+ loginBtn.textContent = "Signing in...";
47
+ chrome.runtime.sendMessage({ action: "auth.login" }, (response) => {
48
+ loginBtn.disabled = false;
49
+ loginBtn.innerHTML = '<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4M10 17l5-5-5-5M15 12H3"/></svg> Sign in with Hanzo';
50
+ if (response == null ? void 0 : response.success) {
51
+ checkAuth();
52
+ }
53
+ });
54
+ });
55
+ logoutBtn == null ? void 0 : logoutBtn.addEventListener("click", () => {
56
+ chrome.runtime.sendMessage({ action: "auth.logout" }, () => {
57
+ mainSection.classList.add("hidden");
58
+ loginSection.classList.remove("hidden");
59
+ });
60
+ });
61
+ openPanel == null ? void 0 : openPanel.addEventListener("click", () => {
62
+ if (chrome.sidePanel) {
63
+ chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
64
+ var _a;
65
+ if ((_a = tabs[0]) == null ? void 0 : _a.id) {
66
+ chrome.sidePanel.open({ tabId: tabs[0].id });
67
+ }
68
+ });
69
+ } else {
70
+ window.close();
71
+ }
72
+ });
73
+ function isInjectableTab(tab) {
74
+ if (!tab || !tab.id) return false;
75
+ const url = tab.url || "";
76
+ if (!url) return false;
77
+ if (url.startsWith("chrome://")) return false;
78
+ if (url.startsWith("chrome-extension://")) return false;
79
+ if (url.startsWith("devtools://")) return false;
80
+ if (url.startsWith("edge://")) return false;
81
+ if (url.startsWith("about:")) return false;
82
+ if (url.startsWith("view-source:")) return false;
83
+ if (url.startsWith("moz-extension://")) return false;
84
+ return true;
85
+ }
86
+ openPageOverlay == null ? void 0 : openPageOverlay.addEventListener("click", () => {
87
+ openPageOverlay.textContent = "Opening...";
88
+ openPageOverlay.setAttribute("disabled", "true");
89
+ chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
90
+ const activeTab = tabs[0];
91
+ let targetTab = isInjectableTab(activeTab) ? activeTab : null;
92
+ if (!targetTab) {
93
+ chrome.tabs.query({ currentWindow: true }, (allTabs) => {
94
+ targetTab = allTabs.find((tab) => isInjectableTab(tab)) || null;
95
+ if (!(targetTab == null ? void 0 : targetTab.id)) {
96
+ openPageOverlay.textContent = "No valid page tab";
97
+ setTimeout(() => {
98
+ openPageOverlay.textContent = "Toggle On-Page Overlay";
99
+ openPageOverlay.removeAttribute("disabled");
100
+ }, 1200);
101
+ return;
102
+ }
103
+ chrome.runtime.sendMessage({ action: "page.overlay.toggle", tabId: targetTab.id }, (response) => {
104
+ if (chrome.runtime.lastError || !(response == null ? void 0 : response.success)) {
105
+ openPageOverlay.textContent = "Unavailable on this page";
106
+ } else {
107
+ const opened = !!(response == null ? void 0 : response.open);
108
+ openPageOverlay.textContent = opened ? "Overlay Opened" : "Overlay Hidden";
109
+ }
110
+ setTimeout(() => {
111
+ openPageOverlay.textContent = "Toggle On-Page Overlay";
112
+ openPageOverlay.removeAttribute("disabled");
113
+ }, 900);
114
+ });
115
+ });
116
+ return;
117
+ }
118
+ if (!(targetTab == null ? void 0 : targetTab.id)) {
119
+ openPageOverlay.textContent = "No Active Tab";
120
+ setTimeout(() => {
121
+ openPageOverlay.textContent = "Toggle On-Page Overlay";
122
+ openPageOverlay.removeAttribute("disabled");
123
+ }, 1200);
124
+ return;
125
+ }
126
+ chrome.runtime.sendMessage({ action: "page.overlay.toggle", tabId: targetTab.id }, (response) => {
127
+ if (chrome.runtime.lastError || !(response == null ? void 0 : response.success)) {
128
+ openPageOverlay.textContent = "Unavailable on this page";
129
+ } else {
130
+ const opened = !!(response == null ? void 0 : response.open);
131
+ openPageOverlay.textContent = opened ? "Overlay Opened" : "Overlay Hidden";
132
+ }
133
+ setTimeout(() => {
134
+ openPageOverlay.textContent = "Toggle On-Page Overlay";
135
+ openPageOverlay.removeAttribute("disabled");
136
+ }, 900);
137
+ });
138
+ });
139
+ });
140
+ function refreshStatus() {
141
+ chrome.runtime.sendMessage({ action: "zap.status" }, (response) => {
142
+ var _a, _b;
143
+ if (chrome.runtime.lastError) return;
144
+ if (response == null ? void 0 : response.success) {
145
+ const zap = response.zap;
146
+ if (zap.connected) {
147
+ zapStatus.classList.add("connected");
148
+ zapStatus.classList.remove("disconnected");
149
+ const mcpCount = ((_a = zap.mcps) == null ? void 0 : _a.length) || 0;
150
+ const toolCount = ((_b = zap.mcps) == null ? void 0 : _b.reduce((sum, m) => {
151
+ var _a2;
152
+ return sum + (((_a2 = m.tools) == null ? void 0 : _a2.length) || 0);
153
+ }, 0)) || 0;
154
+ zapDetail.textContent = `${mcpCount} MCP(s), ${toolCount} tools`;
155
+ } else {
156
+ zapStatus.classList.remove("connected");
157
+ zapStatus.classList.add("disconnected");
158
+ zapDetail.textContent = "Not connected";
159
+ }
160
+ }
161
+ });
162
+ chrome.runtime.sendMessage({ action: "runLocalAI", prompt: "" }, (response) => {
163
+ if (chrome.runtime.lastError) return;
164
+ gpuStatus.classList.add((response == null ? void 0 : response.success) ? "connected" : "disconnected");
165
+ gpuStatus.classList.remove((response == null ? void 0 : response.success) ? "disconnected" : "connected");
166
+ gpuDetail.textContent = (response == null ? void 0 : response.success) ? "Available" : "Not available";
167
+ });
168
+ mcpStatus.classList.add("connected");
169
+ mcpPort.textContent = "Fallback";
170
+ cdpStatus.classList.add("connected");
171
+ cdpDetail.textContent = "Active";
172
+ }
173
+ openSettings == null ? void 0 : openSettings.addEventListener("click", () => {
174
+ mainSection.classList.add("hidden");
175
+ settingsSection.classList.remove("hidden");
176
+ loadSettings();
177
+ });
178
+ backBtn == null ? void 0 : backBtn.addEventListener("click", () => {
179
+ settingsSection.classList.add("hidden");
180
+ mainSection.classList.remove("hidden");
181
+ });
182
+ function loadSettings() {
183
+ chrome.storage.local.get(["mcpPort", "cdpPort", "zapPorts"], (result) => {
184
+ const mcpPortInput = document.getElementById("mcp-port-setting");
185
+ const cdpPortInput = document.getElementById("cdp-port-setting");
186
+ const zapPortsInput = document.getElementById("zap-ports-setting");
187
+ if (mcpPortInput) mcpPortInput.value = result.mcpPort || 3001;
188
+ if (cdpPortInput) cdpPortInput.value = result.cdpPort || 9223;
189
+ if (zapPortsInput) zapPortsInput.value = (result.zapPorts || [9999, 9998, 9997, 9996, 9995]).join(",");
190
+ });
191
+ }
192
+ saveSettings == null ? void 0 : saveSettings.addEventListener("click", () => {
193
+ var _a, _b, _c;
194
+ const mcpPortVal = parseInt((_a = document.getElementById("mcp-port-setting")) == null ? void 0 : _a.value) || 3001;
195
+ const cdpPortVal = parseInt((_b = document.getElementById("cdp-port-setting")) == null ? void 0 : _b.value) || 9223;
196
+ const zapPortsVal = (((_c = document.getElementById("zap-ports-setting")) == null ? void 0 : _c.value) || "").split(",").map((p) => parseInt(p.trim())).filter((p) => p > 0 && p < 65536);
197
+ chrome.storage.local.set({
198
+ mcpPort: mcpPortVal,
199
+ cdpPort: cdpPortVal,
200
+ zapPorts: zapPortsVal.length ? zapPortsVal : [9999, 9998, 9997, 9996, 9995]
201
+ }, () => {
202
+ saveSettings.textContent = "Saved!";
203
+ setTimeout(() => {
204
+ saveSettings.textContent = "Save Settings";
205
+ }, 1500);
206
+ });
207
+ });
208
+ testConnection == null ? void 0 : testConnection.addEventListener("click", () => {
209
+ testConnection.textContent = "Testing...";
210
+ testConnection.disabled = true;
211
+ chrome.runtime.sendMessage({ action: "zap.discover" }, () => {
212
+ refreshStatus();
213
+ testConnection.textContent = "Test Connection";
214
+ testConnection.disabled = false;
215
+ });
216
+ });
217
+ ["source-maps", "webgpu-ai", "browser-control", "tab-filesystem"].forEach((id) => {
218
+ const checkbox = document.getElementById(id);
219
+ if (checkbox) {
220
+ chrome.storage.local.get([id], (result) => {
221
+ checkbox.checked = result[id] !== false;
222
+ });
223
+ checkbox.addEventListener("change", () => {
224
+ chrome.storage.local.set({ [id]: checkbox.checked });
225
+ });
226
+ }
227
+ });
228
+ const backendSelect = document.getElementById("browser-backend");
229
+ const bridgeStatus = document.getElementById("bridge-status");
230
+ const bridgeDetail = document.getElementById("bridge-detail");
231
+ function loadBackendPreference() {
232
+ chrome.storage.sync.get(["browserBackend"], (result) => {
233
+ if (backendSelect && result.browserBackend) {
234
+ backendSelect.value = result.browserBackend;
235
+ }
236
+ });
237
+ }
238
+ function refreshBridgeStatus() {
239
+ chrome.runtime.sendMessage({ action: "bridge.status" }, (response) => {
240
+ if (chrome.runtime.lastError) return;
241
+ if ((response == null ? void 0 : response.success) && response.connected) {
242
+ bridgeStatus == null ? void 0 : bridgeStatus.classList.add("connected");
243
+ bridgeStatus == null ? void 0 : bridgeStatus.classList.remove("disconnected");
244
+ const browsers = response.browsers || [];
245
+ bridgeDetail.textContent = browsers.length ? `Connected: ${browsers.join(", ")}` : "Connected";
246
+ } else {
247
+ bridgeStatus == null ? void 0 : bridgeStatus.classList.remove("connected");
248
+ bridgeStatus == null ? void 0 : bridgeStatus.classList.add("disconnected");
249
+ bridgeDetail.textContent = "Not connected";
250
+ }
251
+ });
252
+ }
253
+ backendSelect == null ? void 0 : backendSelect.addEventListener("change", () => {
254
+ const value = backendSelect.value;
255
+ chrome.storage.sync.set({ browserBackend: value });
256
+ chrome.runtime.sendMessage({
257
+ action: "config.save",
258
+ key: "browserBackend",
259
+ value
260
+ });
261
+ });
262
+ loadBackendPreference();
263
+ refreshBridgeStatus();
264
+ checkAuth();
265
+ });
266
+ })();
267
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL3BvcHVwLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvLyBIYW56byBBSSBcdTIwMTQgUG9wdXAgU2NyaXB0XG4vLyBVc2VzIGJhY2tncm91bmQgbWVzc2FnZSBwYXNzaW5nIGZvciBhdXRoIChub3QgZGlyZWN0IHN0b3JhZ2UgYWNjZXNzKS5cblxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHtcbiAgY29uc3QgbG9naW5TZWN0aW9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2xvZ2luLXNlY3Rpb24nKTtcbiAgY29uc3QgbWFpblNlY3Rpb24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbWFpbi1zZWN0aW9uJyk7XG4gIGNvbnN0IHNldHRpbmdzU2VjdGlvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzZXR0aW5ncy1zZWN0aW9uJyk7XG5cbiAgLy8gQXV0aFxuICBjb25zdCBsb2dpbkJ0biA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdsb2dpbi1idG4nKTtcbiAgY29uc3QgbG9nb3V0QnRuID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2xvZ291dC1idG4nKTtcblxuICAvLyBPcGVuIHBhbmVsXG4gIGNvbnN0IG9wZW5QYW5lbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdvcGVuLXBhbmVsJyk7XG4gIGNvbnN0IG9wZW5QYWdlT3ZlcmxheSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdvcGVuLXBhZ2Utb3ZlcmxheScpO1xuXG4gIC8vIFN0YXR1cyBkb3RzXG4gIGNvbnN0IHphcFN0YXR1cyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd6YXAtc3RhdHVzJyk7XG4gIGNvbnN0IHphcERldGFpbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd6YXAtZGV0YWlsJyk7XG4gIGNvbnN0IG1jcFN0YXR1cyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtY3Atc3RhdHVzJyk7XG4gIGNvbnN0IG1jcFBvcnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbWNwLXBvcnQnKTtcbiAgY29uc3QgY2RwU3RhdHVzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2NkcC1zdGF0dXMnKTtcbiAgY29uc3QgY2RwRGV0YWlsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2NkcC1kZXRhaWwnKTtcbiAgY29uc3QgZ3B1U3RhdHVzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2dwdS1zdGF0dXMnKTtcbiAgY29uc3QgZ3B1RGV0YWlsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2dwdS1kZXRhaWwnKTtcblxuICAvLyBTZXR0aW5nc1xuICBjb25zdCBvcGVuU2V0dGluZ3MgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnb3Blbi1zZXR0aW5ncycpO1xuICBjb25zdCBiYWNrQnRuID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2JhY2stYnRuJyk7XG4gIGNvbnN0IHNhdmVTZXR0aW5ncyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzYXZlLXNldHRpbmdzJyk7XG4gIGNvbnN0IHRlc3RDb25uZWN0aW9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3Rlc3QtY29ubmVjdGlvbicpO1xuXG4gIC8vIC0tLSBBdXRoIHZpYSBiYWNrZ3JvdW5kIC0tLVxuICBmdW5jdGlvbiBjaGVja0F1dGgoKSB7XG4gICAgLy8gQWx3YXlzIHNob3cgbWFpbiBzZWN0aW9uIGFuZCBzdGF0dXMgKHRvb2xzIHdvcmsgd2l0aG91dCBsb2dpbilcbiAgICBtYWluU2VjdGlvbi5jbGFzc0xpc3QucmVtb3ZlKCdoaWRkZW4nKTtcbiAgICByZWZyZXNoU3RhdHVzKCk7XG5cbiAgICBjaHJvbWUucnVudGltZS5zZW5kTWVzc2FnZSh7IGFjdGlvbjogJ2F1dGguc3RhdHVzJyB9LCAocmVzcG9uc2UpID0+IHtcbiAgICAgIGlmIChjaHJvbWUucnVudGltZS5sYXN0RXJyb3IpIHJldHVybjtcbiAgICAgIGlmIChyZXNwb25zZT8uc3VjY2VzcyAmJiByZXNwb25zZS5hdXRoZW50aWNhdGVkKSB7XG4gICAgICAgIGxvZ2luU2VjdGlvbi5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKTtcbiAgICAgICAgaWYgKHJlc3BvbnNlLnVzZXIpIHtcbiAgICAgICAgICBjb25zdCBhdmF0YXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndXNlci1hdmF0YXInKTtcbiAgICAgICAgICBjb25zdCBuYW1lID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VzZXItbmFtZScpO1xuICAgICAgICAgIGNvbnN0IGVtYWlsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VzZXItZW1haWwnKTtcbiAgICAgICAgICBhdmF0YXIuc3JjID0gcmVzcG9uc2UudXNlci5waWN0dXJlIHx8IHJlc3BvbnNlLnVzZXIuYXZhdGFyIHx8ICdpY29uNDgucG5nJztcbiAgICAgICAgICBuYW1lLnRleHRDb250ZW50ID0gcmVzcG9uc2UudXNlci5uYW1lIHx8IHJlc3BvbnNlLnVzZXIuZGlzcGxheU5hbWUgfHwgJ0hhbnpvIFVzZXInO1xuICAgICAgICAgIGVtYWlsLnRleHRDb250ZW50ID0gcmVzcG9uc2UudXNlci5lbWFpbCB8fCAnJztcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9naW5TZWN0aW9uLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgbG9naW5CdG4/LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4ge1xuICAgIGxvZ2luQnRuLmRpc2FibGVkID0gdHJ1ZTtcbiAgICBsb2dpbkJ0bi50ZXh0Q29udGVudCA9ICdTaWduaW5nIGluLi4uJztcbiAgICBjaHJvbWUucnVudGltZS5zZW5kTWVzc2FnZSh7IGFjdGlvbjogJ2F1dGgubG9naW4nIH0sIChyZXNwb25zZSkgPT4ge1xuICAgICAgbG9naW5CdG4uZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgIGxvZ2luQnRuLmlubmVySFRNTCA9ICc8c3ZnIGNsYXNzPVwiaWNvblwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiPjxwYXRoIGQ9XCJNMTUgM2g0YTIgMiAwIDAgMSAyIDJ2MTRhMiAyIDAgMCAxLTIgMmgtNE0xMCAxN2w1LTUtNS01TTE1IDEySDNcIi8+PC9zdmc+IFNpZ24gaW4gd2l0aCBIYW56byc7XG4gICAgICBpZiAocmVzcG9uc2U/LnN1Y2Nlc3MpIHtcbiAgICAgICAgY2hlY2tBdXRoKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIGxvZ291dEJ0bj8uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7XG4gICAgY2hyb21lLnJ1bnRpbWUuc2VuZE1lc3NhZ2UoeyBhY3Rpb246ICdhdXRoLmxvZ291dCcgfSwgKCkgPT4ge1xuICAgICAgbWFpblNlY3Rpb24uY2xhc3NMaXN0LmFkZCgnaGlkZGVuJyk7XG4gICAgICBsb2dpblNlY3Rpb24uY2xhc3NMaXN0LnJlbW92ZSgnaGlkZGVuJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIC0tLSBPcGVuIHNpZGUgcGFuZWwgLS0tXG4gIG9wZW5QYW5lbD8uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7XG4gICAgaWYgKGNocm9tZS5zaWRlUGFuZWwpIHtcbiAgICAgIGNocm9tZS50YWJzLnF1ZXJ5KHsgYWN0aXZlOiB0cnVlLCBjdXJyZW50V2luZG93OiB0cnVlIH0sICh0YWJzKSA9PiB7XG4gICAgICAgIGlmICh0YWJzWzBdPy5pZCkge1xuICAgICAgICAgIGNocm9tZS5zaWRlUGFuZWwub3Blbih7IHRhYklkOiB0YWJzWzBdLmlkIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRmlyZWZveDogc2lkZWJhcl9hY3Rpb24gaXMgYXV0b21hdGljXG4gICAgICB3aW5kb3cuY2xvc2UoKTtcbiAgICB9XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGlzSW5qZWN0YWJsZVRhYih0YWI6IGNocm9tZS50YWJzLlRhYiB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICAgIGlmICghdGFiIHx8ICF0YWIuaWQpIHJldHVybiBmYWxzZTtcbiAgICBjb25zdCB1cmwgPSB0YWIudXJsIHx8ICcnO1xuICAgIGlmICghdXJsKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKHVybC5zdGFydHNXaXRoKCdjaHJvbWU6Ly8nKSkgcmV0dXJuIGZhbHNlO1xuICAgIGlmICh1cmwuc3RhcnRzV2l0aCgnY2hyb21lLWV4dGVuc2lvbjovLycpKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKHVybC5zdGFydHNXaXRoKCdkZXZ0b29sczovLycpKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKHVybC5zdGFydHNXaXRoKCdlZGdlOi8vJykpIHJldHVybiBmYWxzZTtcbiAgICBpZiAodXJsLnN0YXJ0c1dpdGgoJ2Fib3V0OicpKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKHVybC5zdGFydHNXaXRoKCd2aWV3LXNvdXJjZTonKSkgcmV0dXJuIGZhbHNlO1xuICAgIGlmICh1cmwuc3RhcnRzV2l0aCgnbW96LWV4dGVuc2lvbjovLycpKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBvcGVuUGFnZU92ZXJsYXk/LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4ge1xuICAgIG9wZW5QYWdlT3ZlcmxheS50ZXh0Q29udGVudCA9ICdPcGVuaW5nLi4uJztcbiAgICBvcGVuUGFnZU92ZXJsYXkuc2V0QXR0cmlidXRlKCdkaXNhYmxlZCcsICd0cnVlJyk7XG5cbiAgICBjaHJvbWUudGFicy5xdWVyeSh7IGFjdGl2ZTogdHJ1ZSwgY3VycmVudFdpbmRvdzogdHJ1ZSB9LCAodGFicykgPT4ge1xuICAgICAgY29uc3QgYWN0aXZlVGFiID0gdGFic1swXTtcbiAgICAgIGxldCB0YXJnZXRUYWIgPSBpc0luamVjdGFibGVUYWIoYWN0aXZlVGFiKSA/IGFjdGl2ZVRhYiA6IG51bGw7XG5cbiAgICAgIGlmICghdGFyZ2V0VGFiKSB7XG4gICAgICAgIGNocm9tZS50YWJzLnF1ZXJ5KHsgY3VycmVudFdpbmRvdzogdHJ1ZSB9LCAoYWxsVGFicykgPT4ge1xuICAgICAgICAgIHRhcmdldFRhYiA9IGFsbFRhYnMuZmluZCgodGFiKSA9PiBpc0luamVjdGFibGVUYWIodGFiKSkgfHwgbnVsbDtcbiAgICAgICAgICBpZiAoIXRhcmdldFRhYj8uaWQpIHtcbiAgICAgICAgICAgIG9wZW5QYWdlT3ZlcmxheS50ZXh0Q29udGVudCA9ICdObyB2YWxpZCBwYWdlIHRhYic7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgb3BlblBhZ2VPdmVybGF5LnRleHRDb250ZW50ID0gJ1RvZ2dsZSBPbi1QYWdlIE92ZXJsYXknO1xuICAgICAgICAgICAgICBvcGVuUGFnZU92ZXJsYXkucmVtb3ZlQXR0cmlidXRlKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgfSwgMTIwMCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY2hyb21lLnJ1bnRpbWUuc2VuZE1lc3NhZ2UoeyBhY3Rpb246ICdwYWdlLm92ZXJsYXkudG9nZ2xlJywgdGFiSWQ6IHRhcmdldFRhYi5pZCB9LCAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChjaHJvbWUucnVudGltZS5sYXN0RXJyb3IgfHwgIXJlc3BvbnNlPy5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgIG9wZW5QYWdlT3ZlcmxheS50ZXh0Q29udGVudCA9ICdVbmF2YWlsYWJsZSBvbiB0aGlzIHBhZ2UnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY29uc3Qgb3BlbmVkID0gISFyZXNwb25zZT8ub3BlbjtcbiAgICAgICAgICAgICAgb3BlblBhZ2VPdmVybGF5LnRleHRDb250ZW50ID0gb3BlbmVkID8gJ092ZXJsYXkgT3BlbmVkJyA6ICdPdmVybGF5IEhpZGRlbic7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgb3BlblBhZ2VPdmVybGF5LnRleHRDb250ZW50ID0gJ1RvZ2dsZSBPbi1QYWdlIE92ZXJsYXknO1xuICAgICAgICAgICAgICBvcGVuUGFnZU92ZXJsYXkucmVtb3ZlQXR0cmlidXRlKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgfSwgOTAwKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKCF0YXJnZXRUYWI/LmlkKSB7XG4gICAgICAgIG9wZW5QYWdlT3ZlcmxheS50ZXh0Q29udGVudCA9ICdObyBBY3RpdmUgVGFiJztcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgb3BlblBhZ2VPdmVybGF5LnRleHRDb250ZW50ID0gJ1RvZ2dsZSBPbi1QYWdlIE92ZXJsYXknO1xuICAgICAgICAgIG9wZW5QYWdlT3ZlcmxheS5yZW1vdmVBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gICAgICAgIH0sIDEyMDApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNocm9tZS5ydW50aW1lLnNlbmRNZXNzYWdlKHsgYWN0aW9uOiAncGFnZS5vdmVybGF5LnRvZ2dsZScsIHRhYklkOiB0YXJnZXRUYWIuaWQgfSwgKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChjaHJvbWUucnVudGltZS5sYXN0RXJyb3IgfHwgIXJlc3BvbnNlPy5zdWNjZXNzKSB7XG4gICAgICAgICAgb3BlblBhZ2VPdmVybGF5LnRleHRDb250ZW50ID0gJ1VuYXZhaWxhYmxlIG9uIHRoaXMgcGFnZSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3Qgb3BlbmVkID0gISFyZXNwb25zZT8ub3BlbjtcbiAgICAgICAgICBvcGVuUGFnZU92ZXJsYXkudGV4dENvbnRlbnQgPSBvcGVuZWQgPyAnT3ZlcmxheSBPcGVuZWQnIDogJ092ZXJsYXkgSGlkZGVuJztcbiAgICAgICAgfVxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICBvcGVuUGFnZU92ZXJsYXkudGV4dENvbnRlbnQgPSAnVG9nZ2xlIE9uLVBhZ2UgT3ZlcmxheSc7XG4gICAgICAgICAgb3BlblBhZ2VPdmVybGF5LnJlbW92ZUF0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgICAgICAgfSwgOTAwKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyAtLS0gU3RhdHVzIC0tLVxuICBmdW5jdGlvbiByZWZyZXNoU3RhdHVzKCkge1xuICAgIC8vIFpBUCBzdGF0dXNcbiAgICBjaHJvbWUucnVudGltZS5zZW5kTWVzc2FnZSh7IGFjdGlvbjogJ3phcC5zdGF0dXMnIH0sIChyZXNwb25zZSkgPT4ge1xuICAgICAgaWYgKGNocm9tZS5ydW50aW1lLmxhc3RFcnJvcikgcmV0dXJuO1xuICAgICAgaWYgKHJlc3BvbnNlPy5zdWNjZXNzKSB7XG4gICAgICAgIGNvbnN0IHphcCA9IHJlc3BvbnNlLnphcDtcbiAgICAgICAgaWYgKHphcC5jb25uZWN0ZWQpIHtcbiAgICAgICAgICB6YXBTdGF0dXMuY2xhc3NMaXN0LmFkZCgnY29ubmVjdGVkJyk7XG4gICAgICAgICAgemFwU3RhdHVzLmNsYXNzTGlzdC5yZW1vdmUoJ2Rpc2Nvbm5lY3RlZCcpO1xuICAgICAgICAgIGNvbnN0IG1jcENvdW50ID0gemFwLm1jcHM/Lmxlbmd0aCB8fCAwO1xuICAgICAgICAgIGNvbnN0IHRvb2xDb3VudCA9IHphcC5tY3BzPy5yZWR1Y2UoKHN1bSwgbSkgPT4gc3VtICsgKG0udG9vbHM/Lmxlbmd0aCB8fCAwKSwgMCkgfHwgMDtcbiAgICAgICAgICB6YXBEZXRhaWwudGV4dENvbnRlbnQgPSBgJHttY3BDb3VudH0gTUNQKHMpLCAke3Rvb2xDb3VudH0gdG9vbHNgO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHphcFN0YXR1cy5jbGFzc0xpc3QucmVtb3ZlKCdjb25uZWN0ZWQnKTtcbiAgICAgICAgICB6YXBTdGF0dXMuY2xhc3NMaXN0LmFkZCgnZGlzY29ubmVjdGVkJyk7XG4gICAgICAgICAgemFwRGV0YWlsLnRleHRDb250ZW50ID0gJ05vdCBjb25uZWN0ZWQnO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBHUFUgc3RhdHVzXG4gICAgY2hyb21lLnJ1bnRpbWUuc2VuZE1lc3NhZ2UoeyBhY3Rpb246ICdydW5Mb2NhbEFJJywgcHJvbXB0OiAnJyB9LCAocmVzcG9uc2UpID0+IHtcbiAgICAgIGlmIChjaHJvbWUucnVudGltZS5sYXN0RXJyb3IpIHJldHVybjtcbiAgICAgIGdwdVN0YXR1cy5jbGFzc0xpc3QuYWRkKHJlc3BvbnNlPy5zdWNjZXNzID8gJ2Nvbm5lY3RlZCcgOiAnZGlzY29ubmVjdGVkJyk7XG4gICAgICBncHVTdGF0dXMuY2xhc3NMaXN0LnJlbW92ZShyZXNwb25zZT8uc3VjY2VzcyA/ICdkaXNjb25uZWN0ZWQnIDogJ2Nvbm5lY3RlZCcpO1xuICAgICAgZ3B1RGV0YWlsLnRleHRDb250ZW50ID0gcmVzcG9uc2U/LnN1Y2Nlc3MgPyAnQXZhaWxhYmxlJyA6ICdOb3QgYXZhaWxhYmxlJztcbiAgICB9KTtcblxuICAgIC8vIE1DUC9DRFAgXHUyMDE0IHNldCBhcyBhY3RpdmUgZm9yIG5vdyAoY2hlY2tlZCB2aWEgWkFQKVxuICAgIG1jcFN0YXR1cy5jbGFzc0xpc3QuYWRkKCdjb25uZWN0ZWQnKTtcbiAgICBtY3BQb3J0LnRleHRDb250ZW50ID0gJ0ZhbGxiYWNrJztcbiAgICBjZHBTdGF0dXMuY2xhc3NMaXN0LmFkZCgnY29ubmVjdGVkJyk7XG4gICAgY2RwRGV0YWlsLnRleHRDb250ZW50ID0gJ0FjdGl2ZSc7XG4gIH1cblxuICAvLyAtLS0gU2V0dGluZ3MgLS0tXG4gIG9wZW5TZXR0aW5ncz8uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7XG4gICAgbWFpblNlY3Rpb24uY2xhc3NMaXN0LmFkZCgnaGlkZGVuJyk7XG4gICAgc2V0dGluZ3NTZWN0aW9uLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpO1xuICAgIGxvYWRTZXR0aW5ncygpO1xuICB9KTtcblxuICBiYWNrQnRuPy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHtcbiAgICBzZXR0aW5nc1NlY3Rpb24uY2xhc3NMaXN0LmFkZCgnaGlkZGVuJyk7XG4gICAgbWFpblNlY3Rpb24uY2xhc3NMaXN0LnJlbW92ZSgnaGlkZGVuJyk7XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGxvYWRTZXR0aW5ncygpIHtcbiAgICBjaHJvbWUuc3RvcmFnZS5sb2NhbC5nZXQoWydtY3BQb3J0JywgJ2NkcFBvcnQnLCAnemFwUG9ydHMnXSwgKHJlc3VsdCkgPT4ge1xuICAgICAgY29uc3QgbWNwUG9ydElucHV0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ21jcC1wb3J0LXNldHRpbmcnKTtcbiAgICAgIGNvbnN0IGNkcFBvcnRJbnB1dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjZHAtcG9ydC1zZXR0aW5nJyk7XG4gICAgICBjb25zdCB6YXBQb3J0c0lucHV0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3phcC1wb3J0cy1zZXR0aW5nJyk7XG5cbiAgICAgIGlmIChtY3BQb3J0SW5wdXQpIG1jcFBvcnRJbnB1dC52YWx1ZSA9IHJlc3VsdC5tY3BQb3J0IHx8IDMwMDE7XG4gICAgICBpZiAoY2RwUG9ydElucHV0KSBjZHBQb3J0SW5wdXQudmFsdWUgPSByZXN1bHQuY2RwUG9ydCB8fCA5MjIzO1xuICAgICAgaWYgKHphcFBvcnRzSW5wdXQpIHphcFBvcnRzSW5wdXQudmFsdWUgPSAocmVzdWx0LnphcFBvcnRzIHx8IFs5OTk5LCA5OTk4LCA5OTk3LCA5OTk2LCA5OTk1XSkuam9pbignLCcpO1xuICAgIH0pO1xuICB9XG5cbiAgc2F2ZVNldHRpbmdzPy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHtcbiAgICBjb25zdCBtY3BQb3J0VmFsID0gcGFyc2VJbnQoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ21jcC1wb3J0LXNldHRpbmcnKT8udmFsdWUpIHx8IDMwMDE7XG4gICAgY29uc3QgY2RwUG9ydFZhbCA9IHBhcnNlSW50KGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjZHAtcG9ydC1zZXR0aW5nJyk/LnZhbHVlKSB8fCA5MjIzO1xuICAgIGNvbnN0IHphcFBvcnRzVmFsID0gKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd6YXAtcG9ydHMtc2V0dGluZycpPy52YWx1ZSB8fCAnJylcbiAgICAgIC5zcGxpdCgnLCcpLm1hcChwID0+IHBhcnNlSW50KHAudHJpbSgpKSkuZmlsdGVyKHAgPT4gcCA+IDAgJiYgcCA8IDY1NTM2KTtcblxuICAgIGNocm9tZS5zdG9yYWdlLmxvY2FsLnNldCh7XG4gICAgICBtY3BQb3J0OiBtY3BQb3J0VmFsLFxuICAgICAgY2RwUG9ydDogY2RwUG9ydFZhbCxcbiAgICAgIHphcFBvcnRzOiB6YXBQb3J0c1ZhbC5sZW5ndGggPyB6YXBQb3J0c1ZhbCA6IFs5OTk5LCA5OTk4LCA5OTk3LCA5OTk2LCA5OTk1XSxcbiAgICB9LCAoKSA9PiB7XG4gICAgICBzYXZlU2V0dGluZ3MudGV4dENvbnRlbnQgPSAnU2F2ZWQhJztcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4geyBzYXZlU2V0dGluZ3MudGV4dENvbnRlbnQgPSAnU2F2ZSBTZXR0aW5ncyc7IH0sIDE1MDApO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyAtLS0gVGVzdCBDb25uZWN0aW9uIC0tLVxuICB0ZXN0Q29ubmVjdGlvbj8uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7XG4gICAgdGVzdENvbm5lY3Rpb24udGV4dENvbnRlbnQgPSAnVGVzdGluZy4uLic7XG4gICAgdGVzdENvbm5lY3Rpb24uZGlzYWJsZWQgPSB0cnVlO1xuXG4gICAgY2hyb21lLnJ1bnRpbWUuc2VuZE1lc3NhZ2UoeyBhY3Rpb246ICd6YXAuZGlzY292ZXInIH0sICgpID0+IHtcbiAgICAgIHJlZnJlc2hTdGF0dXMoKTtcbiAgICAgIHRlc3RDb25uZWN0aW9uLnRleHRDb250ZW50ID0gJ1Rlc3QgQ29ubmVjdGlvbic7XG4gICAgICB0ZXN0Q29ubmVjdGlvbi5kaXNhYmxlZCA9IGZhbHNlO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyBGZWF0dXJlIHRvZ2dsZXNcbiAgWydzb3VyY2UtbWFwcycsICd3ZWJncHUtYWknLCAnYnJvd3Nlci1jb250cm9sJywgJ3RhYi1maWxlc3lzdGVtJ10uZm9yRWFjaChpZCA9PiB7XG4gICAgY29uc3QgY2hlY2tib3ggPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCk7XG4gICAgaWYgKGNoZWNrYm94KSB7XG4gICAgICBjaHJvbWUuc3RvcmFnZS5sb2NhbC5nZXQoW2lkXSwgKHJlc3VsdCkgPT4ge1xuICAgICAgICBjaGVja2JveC5jaGVja2VkID0gcmVzdWx0W2lkXSAhPT0gZmFsc2U7IC8vIGRlZmF1bHQgb25cbiAgICAgIH0pO1xuICAgICAgY2hlY2tib3guYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgKCkgPT4ge1xuICAgICAgICBjaHJvbWUuc3RvcmFnZS5sb2NhbC5zZXQoeyBbaWRdOiBjaGVja2JveC5jaGVja2VkIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICB9KTtcblxuICAvLyAtLS0gQnJvd3NlciBCYWNrZW5kIFBpY2tlciAtLS1cbiAgY29uc3QgYmFja2VuZFNlbGVjdCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdicm93c2VyLWJhY2tlbmQnKSBhcyBIVE1MU2VsZWN0RWxlbWVudCB8IG51bGw7XG4gIGNvbnN0IGJyaWRnZVN0YXR1cyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdicmlkZ2Utc3RhdHVzJyk7XG4gIGNvbnN0IGJyaWRnZURldGFpbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdicmlkZ2UtZGV0YWlsJyk7XG5cbiAgZnVuY3Rpb24gbG9hZEJhY2tlbmRQcmVmZXJlbmNlKCkge1xuICAgIGNocm9tZS5zdG9yYWdlLnN5bmMuZ2V0KFsnYnJvd3NlckJhY2tlbmQnXSwgKHJlc3VsdCkgPT4ge1xuICAgICAgaWYgKGJhY2tlbmRTZWxlY3QgJiYgcmVzdWx0LmJyb3dzZXJCYWNrZW5kKSB7XG4gICAgICAgIGJhY2tlbmRTZWxlY3QudmFsdWUgPSByZXN1bHQuYnJvd3NlckJhY2tlbmQ7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiByZWZyZXNoQnJpZGdlU3RhdHVzKCkge1xuICAgIGNocm9tZS5ydW50aW1lLnNlbmRNZXNzYWdlKHsgYWN0aW9uOiAnYnJpZGdlLnN0YXR1cycgfSwgKHJlc3BvbnNlKSA9PiB7XG4gICAgICBpZiAoY2hyb21lLnJ1bnRpbWUubGFzdEVycm9yKSByZXR1cm47XG4gICAgICBpZiAocmVzcG9uc2U/LnN1Y2Nlc3MgJiYgcmVzcG9uc2UuY29ubmVjdGVkKSB7XG4gICAgICAgIGJyaWRnZVN0YXR1cz8uY2xhc3NMaXN0LmFkZCgnY29ubmVjdGVkJyk7XG4gICAgICAgIGJyaWRnZVN0YXR1cz8uY2xhc3NMaXN0LnJlbW92ZSgnZGlzY29ubmVjdGVkJyk7XG4gICAgICAgIGNvbnN0IGJyb3dzZXJzID0gcmVzcG9uc2UuYnJvd3NlcnMgfHwgW107XG4gICAgICAgIGJyaWRnZURldGFpbC50ZXh0Q29udGVudCA9IGJyb3dzZXJzLmxlbmd0aFxuICAgICAgICAgID8gYENvbm5lY3RlZDogJHticm93c2Vycy5qb2luKCcsICcpfWBcbiAgICAgICAgICA6ICdDb25uZWN0ZWQnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJpZGdlU3RhdHVzPy5jbGFzc0xpc3QucmVtb3ZlKCdjb25uZWN0ZWQnKTtcbiAgICAgICAgYnJpZGdlU3RhdHVzPy5jbGFzc0xpc3QuYWRkKCdkaXNjb25uZWN0ZWQnKTtcbiAgICAgICAgYnJpZGdlRGV0YWlsLnRleHRDb250ZW50ID0gJ05vdCBjb25uZWN0ZWQnO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgYmFja2VuZFNlbGVjdD8uYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgKCkgPT4ge1xuICAgIGNvbnN0IHZhbHVlID0gYmFja2VuZFNlbGVjdC52YWx1ZTtcblxuICAgIC8vIFNhdmUgdG8gY2hyb21lLnN0b3JhZ2Uuc3luYyAoY3Jvc3MtZGV2aWNlKVxuICAgIGNocm9tZS5zdG9yYWdlLnN5bmMuc2V0KHsgYnJvd3NlckJhY2tlbmQ6IHZhbHVlIH0pO1xuXG4gICAgLy8gRm9yd2FyZCB0byBiYWNrZ3JvdW5kIHRvIHBlcnNpc3QgdmlhIENEUCBicmlkZ2UgKyBzeW5jIHRvIElBTVxuICAgIGNocm9tZS5ydW50aW1lLnNlbmRNZXNzYWdlKHtcbiAgICAgIGFjdGlvbjogJ2NvbmZpZy5zYXZlJyxcbiAgICAgIGtleTogJ2Jyb3dzZXJCYWNrZW5kJyxcbiAgICAgIHZhbHVlLFxuICAgIH0pO1xuICB9KTtcblxuICBsb2FkQmFja2VuZFByZWZlcmVuY2UoKTtcbiAgcmVmcmVzaEJyaWRnZVN0YXR1cygpO1xuXG4gIC8vIEluaXRcbiAgY2hlY2tBdXRoKCk7XG59KTtcbiJdLAogICJtYXBwaW5ncyI6ICI7OztBQUdBLFdBQVMsaUJBQWlCLG9CQUFvQixNQUFNO0FBQ2xELFVBQU0sZUFBZSxTQUFTLGVBQWUsZUFBZTtBQUM1RCxVQUFNLGNBQWMsU0FBUyxlQUFlLGNBQWM7QUFDMUQsVUFBTSxrQkFBa0IsU0FBUyxlQUFlLGtCQUFrQjtBQUdsRSxVQUFNLFdBQVcsU0FBUyxlQUFlLFdBQVc7QUFDcEQsVUFBTSxZQUFZLFNBQVMsZUFBZSxZQUFZO0FBR3RELFVBQU0sWUFBWSxTQUFTLGVBQWUsWUFBWTtBQUN0RCxVQUFNLGtCQUFrQixTQUFTLGVBQWUsbUJBQW1CO0FBR25FLFVBQU0sWUFBWSxTQUFTLGVBQWUsWUFBWTtBQUN0RCxVQUFNLFlBQVksU0FBUyxlQUFlLFlBQVk7QUFDdEQsVUFBTSxZQUFZLFNBQVMsZUFBZSxZ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QUUsR0FBRyxDQUFDLFdBQVc7QUFDekMsbUJBQVMsVUFBVSxPQUFPLEVBQUUsTUFBTTtBQUFBLFFBQ3BDLENBQUM7QUFDRCxpQkFBUyxpQkFBaUIsVUFBVSxNQUFNO0FBQ3hDLGlCQUFPLFFBQVEsTUFBTSxJQUFJLEVBQUUsQ0FBQyxFQUFFLEdBQUcsU0FBUyxRQUFRLENBQUM7QUFBQSxRQUNyRCxDQUFDO0FBQUEsTUFDSDtBQUFBLElBQ0YsQ0FBQztBQUdELFVBQU0sZ0JBQWdCLFNBQVMsZUFBZSxpQkFBaUI7QUFDL0QsVUFBTSxlQUFlLFNBQVMsZUFBZSxlQUFlO0FBQzVELFVBQU0sZUFBZSxTQUFTLGVBQWUsZUFBZTtBQUU1RCxhQUFTLHdCQUF3QjtBQUMvQixhQUFPLFFBQVEsS0FBSyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsQ0FBQyxXQUFXO0FBQ3RELFlBQUksaUJBQWlCLE9BQU8sZ0JBQWdCO0FBQzFDLHdCQUFjLFFBQVEsT0FBTztBQUFBLFFBQy9CO0FBQUEsTUFDRixDQUFDO0FBQUEsSUFDSDtBQUVBLGFBQVMsc0JBQXNCO0FBQzdCLGFBQU8sUUFBUSxZQUFZLEVBQUUsUUFBUSxnQkFBZ0IsR0FBRyxDQUFDLGFBQWE7QUFDcEUsWUFBSSxPQUFPLFFBQVEsVUFBVztBQUM5QixhQUFJLHFDQUFVLFlBQVcsU0FBUyxXQUFXO0FBQzNDLHVEQUFjLFVBQVUsSUFBSTtBQUM1Qix1REFBYyxVQUFVLE9BQU87QUFDL0IsZ0JBQU0sV0FBVyxTQUFTLFlBQVksQ0FBQztBQUN2Qyx1QkFBYSxjQUFjLFNBQVMsU0FDaEMsY0FBYyxTQUFTLEtBQUssSUFBSSxDQUFDLEtBQ2pDO0FBQUEsUUFDTixPQUFPO0FBQ0wsdURBQWMsVUFBVSxPQUFPO0FBQy9CLHVEQUFjLFVBQVUsSUFBSTtBQUM1Qix1QkFBYSxjQUFjO0FBQUEsUUFDN0I7QUFBQSxNQUNGLENBQUM7QUFBQSxJQUNIO0FBRUEsbURBQWUsaUJBQWlCLFVBQVUsTUFBTTtBQUM5QyxZQUFNLFFBQVEsY0FBYztBQUc1QixhQUFPLFFBQVEsS0FBSyxJQUFJLEVBQUUsZ0JBQWdCLE1BQU0sQ0FBQztBQUdqRCxhQUFPLFFBQVEsWUFBWTtBQUFBLFFBQ3pCLFFBQVE7QUFBQSxRQUNSLEtBQUs7QUFBQSxRQUNMO0FBQUEsTUFDRixDQUFDO0FBQUEsSUFDSDtBQUVBLDBCQUFzQjtBQUN0Qix3QkFBb0I7QUFHcEIsY0FBVTtBQUFBLEVBQ1osQ0FBQzsiLAogICJuYW1lcyI6IFsiX2EiXQp9Cg==