diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 1459e9ee..3d068995 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -33,7 +33,8 @@ "esbenp.prettier-vscode", "humao.rest-client", "GitHub.copilot", - "runem.lit-plugin" + "runem.lit-plugin", + "ms-playwright.playwright" ] } }, @@ -42,7 +43,7 @@ "forwardPorts": [3000, 3001, 5173], // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "npm install", + "postCreateCommand": "./.devcontainer/postCreateCommand.sh", // Set minimal host requirements for the container. "hostRequirements": { diff --git a/.devcontainer/postCreateCommand.sh b/.devcontainer/postCreateCommand.sh new file mode 100755 index 00000000..a50a9893 --- /dev/null +++ b/.devcontainer/postCreateCommand.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +echo "Installing dependencies..." +npm install + +echo "Installing playwright browsers..." +npx playwright install --with-deps diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 00000000..a1d52131 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,27 @@ +name: Playwright Tests +on: + push: + branches: [main] + pull_request: + branches: [main] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - name: Install dependencies + run: npm ci + - name: Install Playwright Browsers + run: npm run install:playwright + - name: Run Playwright tests + run: npm run test:playwright + - uses: actions/upload-artifact@v3 + if: failure() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/.gitignore b/.gitignore index 84bfa743..0bc8ef4c 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ dist/ # misc TODO +/test-results/ +/playwright-report/ +/playwright/.cache/ diff --git a/package-lock.json b/package-lock.json index ddf7c504..e94c91f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,9 @@ "packages/*" ], "devDependencies": { + "@playwright/test": "^1.39.0", "@tapjs/nock": "^3.1.13", + "@types/node": "^18.15.3", "concurrently": "^8.2.1", "eslint-config-shared": "^1.0.0", "lint-staged": "^14.0.1", @@ -2794,6 +2796,21 @@ "node": ">=14" } }, + "node_modules/@playwright/test": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.39.0.tgz", + "integrity": "sha512-3u1iFqgzl7zr004bGPYiN/5EZpRUSFddQBra8Rqll5N0/vfpqlP9I9EXqAoGacuAbX6c9Ulg/Cjqglp5VkK6UQ==", + "dev": true, + "dependencies": { + "playwright": "1.39.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@react-spring/animated": { "version": "9.7.3", "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", @@ -3611,12 +3628,9 @@ } }, "node_modules/@types/node": { - "version": "20.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", - "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", - "dependencies": { - "undici-types": "~5.25.1" - } + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==" }, "node_modules/@types/node-fetch": { "version": "2.6.6", @@ -10604,6 +10618,50 @@ "node": ">=8" } }, + "node_modules/playwright": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.39.0.tgz", + "integrity": "sha512-naE5QT11uC/Oiq0BwZ50gDmy8c8WLPRTEWuSSFVG2egBka/1qMoSqYQcROMT9zLwJ86oPofcTH2jBY/5wWOgIw==", + "devOptional": true, + "dependencies": { + "playwright-core": "1.39.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.39.0.tgz", + "integrity": "sha512-+k4pdZgs1qiM+OUkSjx96YiKsXsmb59evFoqv8SKO067qBA+Z2s/dCzJij/ZhdQcs2zlTAgRKfeiiLm8PQ2qvw==", + "devOptional": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -12782,11 +12840,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" - }, "node_modules/unique-filename": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", diff --git a/package.json b/package.json index ce15601e..cd563ab3 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "start:search": "npm run dev --workspace=search", "start:indexer": "npm run dev --workspace=indexer", "test": "npm run test -ws --if-present", + "test:playwright": "npx playwright test", "build": "npm run build -ws --if-present", "clean": "npm run clean -ws --if-present", "docker:build": "npm run docker:build -ws --if-present", @@ -19,7 +20,8 @@ "format:check": "prettier --check .", "lint": "eslint .", "lint:fix": "eslint --fix .", - "prepare": "simple-git-hooks || echo 'simple-git-hooks install skipped'" + "prepare": "simple-git-hooks || echo 'simple-git-hooks install skipped'", + "install:playwright": "npx playwright install --with-deps" }, "keywords": [], "author": "Microsoft", @@ -28,7 +30,9 @@ "packages/*" ], "devDependencies": { + "@playwright/test": "^1.39.0", "@tapjs/nock": "^3.1.13", + "@types/node": "^18.15.3", "concurrently": "^8.2.1", "eslint-config-shared": "^1.0.0", "lint-staged": "^14.0.1", diff --git a/packages/chat-component/src/main.ts b/packages/chat-component/src/main.ts index 7e9b01d4..e4fedacf 100644 --- a/packages/chat-component/src/main.ts +++ b/packages/chat-component/src/main.ts @@ -368,6 +368,7 @@ export class ChatComponent extends LitElement { ${citation.ref}. ${citation.text} ${globalConfig.RESET_CHAT_BUTTON_TITLE} @@ -435,6 +437,7 @@ export class ChatComponent extends LitElement { diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 00000000..d5c610b0 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,82 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +const useLocalServer = true; + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './tests', + testMatch: '*.spec.ts', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: useLocalServer ? 'http://localhost:5173' : process.env.WEBAPP_URI, + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + webServer: useLocalServer + ? { + command: 'npm run start:webapp', + url: 'http://localhost:5173', + reuseExistingServer: !process.env.CI, + } + : undefined, +}); diff --git a/tests/e2e/hars/default-chat-response-nostream.har b/tests/e2e/hars/default-chat-response-nostream.har new file mode 100644 index 00000000..e5bf2165 --- /dev/null +++ b/tests/e2e/hars/default-chat-response-nostream.har @@ -0,0 +1,75 @@ +{ + "log": { + "version": "1.2", + "creator": { + "name": "Playwright", + "version": "1.39.0" + }, + "browser": { + "name": "chromium", + "version": "119.0.6045.9" + }, + "entries": [ + { + "startedDateTime": "2023-10-25T00:22:30.306Z", + "time": 260.475, + "request": { + "method": "POST", + "url": "http://localhost:5173/chat", + "httpVersion": "HTTP/2.0", + "cookies": [], + "headers": [ + { "name": ":authority", "value": "http://localhost:5173" }, + { "name": ":method", "value": "POST" }, + { "name": ":path", "value": "/chat" }, + { "name": ":scheme", "value": "https" }, + { "name": "accept", "value": "*/*" }, + { "name": "accept-encoding", "value": "gzip, deflate, br" }, + { "name": "accept-language", "value": "en-US" }, + { "name": "content-length", "value": "438" }, + { "name": "content-type", "value": "application/json" }, + { "name": "origin", "value": "http://localhost:5173" }, + { "name": "sec-fetch-dest", "value": "empty" }, + { "name": "sec-fetch-mode", "value": "cors" }, + { "name": "sec-fetch-site", "value": "cross-site" }, + { + "name": "user-agent", + "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.9 Safari/537.36" + } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1, + "postData": { + "mimeType": "application/json", + "text": "{\"messages\":[{\"content\":\"How to search and book rentals?\",\"role\":\"user\"}],\"context\":{\"retrieval_mode\":\"hybrid\",\"semantic_ranker\":true,\"semantic_captions\":false,\"suggest_followup_questions\":true,\"retrievalMode\":\"hybrid\",\"top\":3,\"useSemanticRanker\":true,\"useSemanticCaptions\":false,\"excludeCategory\":\"\",\"promptTemplate\":\"\",\"promptTemplatePrefix\":\"\",\"promptTemplateSuffix\":\"\",\"suggestFollowupQuestions\":true,\"approach\":\"rrr\"},\"stream\":false}", + "params": [] + } + }, + "response": { + "status": 200, + "statusText": "", + "httpVersion": "HTTP/2.0", + "cookies": [], + "headers": [ + { "name": "access-control-allow-origin", "value": "http://localhost:5173.net" }, + { "name": "content-length", "value": "10389" }, + { "name": "content-type", "value": "application/json; charset=utf-8" }, + { "name": "date", "value": "Wed, 25 Oct 2023 00:22:36 GMT" }, + { "name": "vary", "value": "Origin" } + ], + "content": { + "size": -1, + "mimeType": "application/json; charset=utf-8", + "text": "{\"choices\":[{\"index\":0,\"message\":{\"content\":\"To search and book rentals on Contoso Real Estate, follow these steps:\\n\\n1. Search for Rentals: Enter your destination, check-in and check-out dates, and the number of guests. Apply filters such as price range, property type, and amenities to narrow down your options. [support.md]\\n2. View Listing Details: Click on a listing to view detailed information, including photos, property description, reviews, and host information. [support.md]\\n3. Make a Booking: Click the \\\"Book Now\\\" button on the listing page. Review the booking details, including the total cost and house rules. Confirm your booking by providing payment information. Once the host accepts your booking, you'll receive a confirmation. [support.md]\\n4. Payment: Contoso Real Estate handles the payment process securely. You'll only be charged once your booking is confirmed. [support.md]\\n5. Communication: You can communicate with the host through our messaging system for any questions or special requests. [support.md]\\n\\n<>\\n<>\\n<>\",\"role\":\"assistant\",\"context\":{\"data_points\":[\"support.md: [How to Search and Book Rentals](#how-to-search-and-book-rentals) 2. [How to Cancel a Confirmed Booking](#how-to-cancel-a-confirmed-booking) 3. [How to Contact Customer Support](#how-to-contact-customer-support) 4. [How to Report a Problem with a Listing](#how-to-report-a-problem-with-a-listing) 5. [How to Report a Problem with a Guest or Host](#how-to-report-a-problem-with-a-guest-or-host) 6. [How to Report a Safety Issue](#how-to-report-a-safety-issue) 7. [How to Report a Payment or Refund Issue](#how-to-report-a-payment-or-refund-issue) 8. [Guest or Host Rule Violations](#guest-or-host-rule-violations) 9. [Compensation for Damage](#compensation-for-damage) 10. [Payment Error Resolution](#payment-error-resolution) --- ## 1. How to Search and Book Rentals Contoso Real Estate offers a wide range of rental properties for your stay. Here's how to search and book rentals: 1. **Search for Rentals:** - Enter your destination, check-in and check-out dates, and the number of guests. - Apply filters such as price range, property type, and amenities to narrow down your options.\",\"support.md: **Search for Rentals:** - Enter your destination, check-in and check-out dates, and the number of guests. - Apply filters such as price range, property type, and amenities to narrow down your options. - Browse through the listings to find the perfect place for your stay. 2. **View Listing Details:** - Click on a listing to view detailed information, including photos, property description, reviews, and host information. 3. **Make a Booking:** - Click the \\\"Book Now\\\" button on the listing page. - Review the booking details, including the total cost and house rules. - Confirm your booking by providing payment information. - Once the host accepts your booking, you'll receive a confirmation. 4. **Payment:** - Contoso Real Estate handles the payment process securely. You'll only be charged once your booking is confirmed. 5. **Communication:** - You can communicate with the host through our messaging system for any questions or special requests. --- ## 2. How to Cancel a Confirmed Booking Life happens, and sometimes you need to cancel a confirmed booking. Here's how to do it: 1.\",\"terms-of-service.md: We aim to create a trusted community where hosts can share their spaces and guests can enjoy memorable experiences. ## 2. How to Search and Book Rentals ### 2.1 Creating an Account To search for and book rentals, users must create a Contoso Real Estate account. You must provide accurate and complete information during the registration process. Users are responsible for maintaining the confidentiality of their account credentials. ### 2.2 Browsing and Searching - Users can browse available rentals without an account. - Use our search filters to narrow down rental options based on your preferences. - Click on a rental listing to view details, including pricing, availability, and host information. ### 2.3 Booking a Rental - To book a rental, click the \\\"Book Now\\\" button on the listing page. - Review the booking details, including dates and pricing, before confirming the reservation. - Payment is processed securely through our platform. Guests will receive a booking confirmation email. ### 2.4 Guest Verification - Guests may be required to complete identity verification steps.\"],\"thoughts\":\"Search query:
Search query: \\\"how to search and book rentals\\\"

Conversations:
system: Below is a history of the conversation so far, and a new question asked by the user that needs to be answered by searching in a knowledge base about terms of service, privacy policy, and questions about support requests.
Generate a search query based on the conversation and the new question.
Do not include cited source filenames and document names e.g info.txt or doc.pdf in the search query terms.
Do not include any text inside [] or <<>> in the search query terms.
Do not include any special characters like '+'.
If the question is not in English, translate the question to English before generating the search query.
If you cannot generate a search query, return just the number 0.


assistant: Refund policy

user: can I get refunded if cannot travel?

assistant: Show support for payment errors

user: What happens if a payment error occurs?

user: Generate search query for: How to search and book rentals?

system: Assistant helps the Consto Real Estate company customers with support questions regarding terms of service, privacy policy, and questions about support requests. Be brief in your answers.
Answer ONLY with the facts listed in the list of sources below. If there isn't enough information below, say you don't know. Do not generate answers that don't use the sources below. If asking a clarifying question to the user would help, ask the question.
For tabular information return it as an html table. Do not return markdown format. If the question is not in English, answer in the language used in the question.
Each source has a name followed by colon and the actual information, always include the source name for each fact you use in the response. Use square brackets to reference the source, for example: [info1.txt]. Don't combine sources, list each source separately, for example: [info1.txt][info2.pdf].
Generate 3 very brief follow-up questions that the user would likely ask next.
Enclose the follow-up questions in double angle brackets. Example:
<>
<>
<>

Do no repeat questions that have already been asked.
Make sure the last question ends with \\\">>\\\".



user: How to search and book rentals?

Sources:
support.md: [How to Search and Book Rentals](#how-to-search-and-book-rentals) 2. [How to Cancel a Confirmed Booking](#how-to-cancel-a-confirmed-booking) 3. [How to Contact Customer Support](#how-to-contact-customer-support) 4. [How to Report a Problem with a Listing](#how-to-report-a-problem-with-a-listing) 5. [How to Report a Problem with a Guest or Host](#how-to-report-a-problem-with-a-guest-or-host) 6. [How to Report a Safety Issue](#how-to-report-a-safety-issue) 7. [How to Report a Payment or Refund Issue](#how-to-report-a-payment-or-refund-issue) 8. [Guest or Host Rule Violations](#guest-or-host-rule-violations) 9. [Compensation for Damage](#compensation-for-damage) 10. [Payment Error Resolution](#payment-error-resolution) --- ## 1. How to Search and Book Rentals Contoso Real Estate offers a wide range of rental properties for your stay. Here's how to search and book rentals: 1. **Search for Rentals:** - Enter your destination, check-in and check-out dates, and the number of guests. - Apply filters such as price range, property type, and amenities to narrow down your options.
support.md: **Search for Rentals:** - Enter your destination, check-in and check-out dates, and the number of guests. - Apply filters such as price range, property type, and amenities to narrow down your options. - Browse through the listings to find the perfect place for your stay. 2. **View Listing Details:** - Click on a listing to view detailed information, including photos, property description, reviews, and host information. 3. **Make a Booking:** - Click the \\\"Book Now\\\" button on the listing page. - Review the booking details, including the total cost and house rules. - Confirm your booking by providing payment information. - Once the host accepts your booking, you'll receive a confirmation. 4. **Payment:** - Contoso Real Estate handles the payment process securely. You'll only be charged once your booking is confirmed. 5. **Communication:** - You can communicate with the host through our messaging system for any questions or special requests. --- ## 2. How to Cancel a Confirmed Booking Life happens, and sometimes you need to cancel a confirmed booking. Here's how to do it: 1.
terms-of-service.md: We aim to create a trusted community where hosts can share their spaces and guests can enjoy memorable experiences. ## 2. How to Search and Book Rentals ### 2.1 Creating an Account To search for and book rentals, users must create a Contoso Real Estate account. You must provide accurate and complete information during the registration process. Users are responsible for maintaining the confidentiality of their account credentials. ### 2.2 Browsing and Searching - Users can browse available rentals without an account. - Use our search filters to narrow down rental options based on your preferences. - Click on a rental listing to view details, including pricing, availability, and host information. ### 2.3 Booking a Rental - To book a rental, click the \\\"Book Now\\\" button on the listing page. - Review the booking details, including dates and pricing, before confirming the reservation. - Payment is processed securely through our platform. Guests will receive a booking confirmation email. ### 2.4 Guest Verification - Guests may be required to complete identity verification steps.\"}}}],\"object\":\"chat.completion\"}" + }, + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 260.475 } + } + ] + } +} diff --git a/tests/e2e/hars/default-chat-response-stream.har b/tests/e2e/hars/default-chat-response-stream.har new file mode 100644 index 00000000..48cffc47 --- /dev/null +++ b/tests/e2e/hars/default-chat-response-stream.har @@ -0,0 +1,75 @@ +{ + "log": { + "version": "1.2", + "creator": { + "name": "Playwright", + "version": "1.39.0" + }, + "browser": { + "name": "chromium", + "version": "119.0.6045.9" + }, + "entries": [ + { + "startedDateTime": "2023-10-25T00:27:07.983Z", + "time": 4348.057, + "request": { + "method": "POST", + "url": "http://localhost:5173/chat", + "httpVersion": "HTTP/2.0", + "cookies": [], + "headers": [ + { "name": ":authority", "value": "http://localhost:5173" }, + { "name": ":method", "value": "POST" }, + { "name": ":path", "value": "/chat" }, + { "name": ":scheme", "value": "http" }, + { "name": "accept", "value": "*/*" }, + { "name": "accept-encoding", "value": "gzip, deflate, br" }, + { "name": "accept-language", "value": "en-US" }, + { "name": "content-length", "value": "437" }, + { "name": "content-type", "value": "application/json" }, + { "name": "origin", "value": "http://localhost:5173" }, + { "name": "sec-fetch-dest", "value": "empty" }, + { "name": "sec-fetch-mode", "value": "cors" }, + { "name": "sec-fetch-site", "value": "cross-site" }, + { + "name": "user-agent", + "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.9 Safari/537.36" + } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1, + "postData": { + "mimeType": "application/json", + "text": "{\"messages\":[{\"content\":\"How to search and book rentals?\",\"role\":\"user\"}],\"context\":{\"retrieval_mode\":\"hybrid\",\"semantic_ranker\":true,\"semantic_captions\":false,\"suggest_followup_questions\":true,\"retrievalMode\":\"hybrid\",\"top\":3,\"useSemanticRanker\":true,\"useSemanticCaptions\":false,\"excludeCategory\":\"\",\"promptTemplate\":\"\",\"promptTemplatePrefix\":\"\",\"promptTemplateSuffix\":\"\",\"suggestFollowupQuestions\":true,\"approach\":\"rrr\"},\"stream\":true}", + "params": [] + } + }, + "response": { + "status": 200, + "statusText": "", + "httpVersion": "HTTP/2.0", + "cookies": [], + "headers": [ + { "name": "access-control-allow-origin", "value": "http://localhost:5173" }, + { "name": "content-type", "value": "application/x-ndjson" }, + { "name": "date", "value": "Wed, 25 Oct 2023 00:27:10 GMT" }, + { "name": "vary", "value": "Origin" } + ], + "content": { + "size": -1, + "mimeType": "application/x-ndjson", + "text": "eyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7ImRhdGFfcG9pbnRzIjpbInN1cHBvcnQubWQ6ICBbSG93IHRvIFNlYXJjaCBhbmQgQm9vayBSZW50YWxzXSgjaG93LXRvLXNlYXJjaC1hbmQtYm9vay1yZW50YWxzKSAyLiBbSG93IHRvIENhbmNlbCBhIENvbmZpcm1lZCBCb29raW5nXSgjaG93LXRvLWNhbmNlbC1hLWNvbmZpcm1lZC1ib29raW5nKSAzLiBbSG93IHRvIENvbnRhY3QgQ3VzdG9tZXIgU3VwcG9ydF0oI2hvdy10by1jb250YWN0LWN1c3RvbWVyLXN1cHBvcnQpIDQuIFtIb3cgdG8gUmVwb3J0IGEgUHJvYmxlbSB3aXRoIGEgTGlzdGluZ10oI2hvdy10by1yZXBvcnQtYS1wcm9ibGVtLXdpdGgtYS1saXN0aW5nKSA1LiBbSG93IHRvIFJlcG9ydCBhIFByb2JsZW0gd2l0aCBhIEd1ZXN0IG9yIEhvc3RdKCNob3ctdG8tcmVwb3J0LWEtcHJvYmxlbS13aXRoLWEtZ3Vlc3Qtb3ItaG9zdCkgNi4gW0hvdyB0byBSZXBvcnQgYSBTYWZldHkgSXNzdWVdKCNob3ctdG8tcmVwb3J0LWEtc2FmZXR5LWlzc3VlKSA3LiBbSG93IHRvIFJlcG9ydCBhIFBheW1lbnQgb3IgUmVmdW5kIElzc3VlXSgjaG93LXRvLXJlcG9ydC1hLXBheW1lbnQtb3ItcmVmdW5kLWlzc3VlKSA4LiBbR3Vlc3Qgb3IgSG9zdCBSdWxlIFZpb2xhdGlvbnNdKCNndWVzdC1vci1ob3N0LXJ1bGUtdmlvbGF0aW9ucykgOS4gW0NvbXBlbnNhdGlvbiBmb3IgRGFtYWdlXSgjY29tcGVuc2F0aW9uLWZvci1kYW1hZ2UpIDEwLiBbUGF5bWVudCBFcnJvciBSZXNvbHV0aW9uXSgjcGF5bWVudC1lcnJvci1yZXNvbHV0aW9uKSAtLS0gIyMgMS4gSG93IHRvIFNlYXJjaCBhbmQgQm9vayBSZW50YWxzIENvbnRvc28gUmVhbCBFc3RhdGUgb2ZmZXJzIGEgd2lkZSByYW5nZSBvZiByZW50YWwgcHJvcGVydGllcyBmb3IgeW91ciBzdGF5LiBIZXJlJ3MgaG93IHRvIHNlYXJjaCBhbmQgYm9vayByZW50YWxzOiAxLiAqKlNlYXJjaCBmb3IgUmVudGFsczoqKiAgICAtIEVudGVyIHlvdXIgZGVzdGluYXRpb24sIGNoZWNrLWluIGFuZCBjaGVjay1vdXQgZGF0ZXMsIGFuZCB0aGUgbnVtYmVyIG9mIGd1ZXN0cy4gICAgLSBBcHBseSBmaWx0ZXJzIHN1Y2ggYXMgcHJpY2UgcmFuZ2UsIHByb3BlcnR5IHR5cGUsIGFuZCBhbWVuaXRpZXMgdG8gbmFycm93IGRvd24geW91ciBvcHRpb25zLiIsInRlcm1zLW9mLXNlcnZpY2UubWQ6ICBXZSBhaW0gdG8gY3JlYXRlIGEgdHJ1c3RlZCBjb21tdW5pdHkgd2hlcmUgaG9zdHMgY2FuIHNoYXJlIHRoZWlyIHNwYWNlcyBhbmQgZ3Vlc3RzIGNhbiBlbmpveSBtZW1vcmFibGUgZXhwZXJpZW5jZXMuICMjIDIuIEhvdyB0byBTZWFyY2ggYW5kIEJvb2sgUmVudGFscyAjIyMgMi4xIENyZWF0aW5nIGFuIEFjY291bnQgVG8gc2VhcmNoIGZvciBhbmQgYm9vayByZW50YWxzLCB1c2VycyBtdXN0IGNyZWF0ZSBhIENvbnRvc28gUmVhbCBFc3RhdGUgYWNjb3VudC4gWW91IG11c3QgcHJvdmlkZSBhY2N1cmF0ZSBhbmQgY29tcGxldGUgaW5mb3JtYXRpb24gZHVyaW5nIHRoZSByZWdpc3RyYXRpb24gcHJvY2Vzcy4gVXNlcnMgYXJlIHJlc3BvbnNpYmxlIGZvciBtYWludGFpbmluZyB0aGUgY29uZmlkZW50aWFsaXR5IG9mIHRoZWlyIGFjY291bnQgY3JlZGVudGlhbHMuICMjIyAyLjIgQnJvd3NpbmcgYW5kIFNlYXJjaGluZyAtIFVzZXJzIGNhbiBicm93c2UgYXZhaWxhYmxlIHJlbnRhbHMgd2l0aG91dCBhbiBhY2NvdW50LiAtIFVzZSBvdXIgc2VhcmNoIGZpbHRlcnMgdG8gbmFycm93IGRvd24gcmVudGFsIG9wdGlvbnMgYmFzZWQgb24geW91ciBwcmVmZXJlbmNlcy4gLSBDbGljayBvbiBhIHJlbnRhbCBsaXN0aW5nIHRvIHZpZXcgZGV0YWlscywgaW5jbHVkaW5nIHByaWNpbmcsIGF2YWlsYWJpbGl0eSwgYW5kIGhvc3QgaW5mb3JtYXRpb24uICMjIyAyLjMgQm9va2luZyBhIFJlbnRhbCAtIFRvIGJvb2sgYSByZW50YWwsIGNsaWNrIHRoZSBcIkJvb2sgTm93XCIgYnV0dG9uIG9uIHRoZSBsaXN0aW5nIHBhZ2UuIC0gUmV2aWV3IHRoZSBib29raW5nIGRldGFpbHMsIGluY2x1ZGluZyBkYXRlcyBhbmQgcHJpY2luZywgYmVmb3JlIGNvbmZpcm1pbmcgdGhlIHJlc2VydmF0aW9uLiAtIFBheW1lbnQgaXMgcHJvY2Vzc2VkIHNlY3VyZWx5IHRocm91Z2ggb3VyIHBsYXRmb3JtLiBHdWVzdHMgd2lsbCByZWNlaXZlIGEgYm9va2luZyBjb25maXJtYXRpb24gZW1haWwuICMjIyAyLjQgR3Vlc3QgVmVyaWZpY2F0aW9uIC0gR3Vlc3RzIG1heSBiZSByZXF1aXJlZCB0byBjb21wbGV0ZSBpZGVudGl0eSB2ZXJpZmljYXRpb24gc3RlcHMuIiwic3VwcG9ydC5tZDogICoqU2VhcmNoIGZvciBSZW50YWxzOioqICAgIC0gRW50ZXIgeW91ciBkZXN0aW5hdGlvbiwgY2hlY2staW4gYW5kIGNoZWNrLW91dCBkYXRlcywgYW5kIHRoZSBudW1iZXIgb2YgZ3Vlc3RzLiAgICAtIEFwcGx5IGZpbHRlcnMgc3VjaCBhcyBwcmljZSByYW5nZSwgcHJvcGVydHkgdHlwZSwgYW5kIGFtZW5pdGllcyB0byBuYXJyb3cgZG93biB5b3VyIG9wdGlvbnMuICAgIC0gQnJvd3NlIHRocm91Z2ggdGhlIGxpc3RpbmdzIHRvIGZpbmQgdGhlIHBlcmZlY3QgcGxhY2UgZm9yIHlvdXIgc3RheS4gMi4gKipWaWV3IExpc3RpbmcgRGV0YWlsczoqKiAgICAtIENsaWNrIG9uIGEgbGlzdGluZyB0byB2aWV3IGRldGFpbGVkIGluZm9ybWF0aW9uLCBpbmNsdWRpbmcgcGhvdG9zLCBwcm9wZXJ0eSBkZXNjcmlwdGlvbiwgcmV2aWV3cywgYW5kIGhvc3QgaW5mb3JtYXRpb24uIDMuICoqTWFrZSBhIEJvb2tpbmc6KiogICAgLSBDbGljayB0aGUgXCJCb29rIE5vd1wiIGJ1dHRvbiBvbiB0aGUgbGlzdGluZyBwYWdlLiAgICAtIFJldmlldyB0aGUgYm9va2luZyBkZXRhaWxzLCBpbmNsdWRpbmcgdGhlIHRvdGFsIGNvc3QgYW5kIGhvdXNlIHJ1bGVzLiAgICAtIENvbmZpcm0geW91ciBib29raW5nIGJ5IHByb3ZpZGluZyBwYXltZW50IGluZm9ybWF0aW9uLiAgICAtIE9uY2UgdGhlIGhvc3QgYWNjZXB0cyB5b3VyIGJvb2tpbmcsIHlvdSdsbCByZWNlaXZlIGEgY29uZmlybWF0aW9uLiA0LiAqKlBheW1lbnQ6KiogICAgLSBDb250b3NvIFJlYWwgRXN0YXRlIGhhbmRsZXMgdGhlIHBheW1lbnQgcHJvY2VzcyBzZWN1cmVseS4gWW91J2xsIG9ubHkgYmUgY2hhcmdlZCBvbmNlIHlvdXIgYm9va2luZyBpcyBjb25maXJtZWQuIDUuICoqQ29tbXVuaWNhdGlvbjoqKiAgICAtIFlvdSBjYW4gY29tbXVuaWNhdGUgd2l0aCB0aGUgaG9zdCB0aHJvdWdoIG91ciBtZXNzYWdpbmcgc3lzdGVtIGZvciBhbnkgcXVlc3Rpb25zIG9yIHNwZWNpYWwgcmVxdWVzdHMuIC0tLSAjIyAyLiBIb3cgdG8gQ2FuY2VsIGEgQ29uZmlybWVkIEJvb2tpbmcgTGlmZSBoYXBwZW5zLCBhbmQgc29tZXRpbWVzIHlvdSBuZWVkIHRvIGNhbmNlbCBhIGNvbmZpcm1lZCBib29raW5nLiBIZXJlJ3MgaG93IHRvIGRvIGl0OiAxLiJdLCJ0aG91Z2h0cyI6IlNlYXJjaCBxdWVyeTo8YnI+U2VhcmNoIGFuZCBib29rIHJlbnRhbHMgcHJvY2Vzczxicj48YnI+Q29udmVyc2F0aW9uczo8YnI+c3lzdGVtOiBCZWxvdyBpcyBhIGhpc3Rvcnkgb2YgdGhlIGNvbnZlcnNhdGlvbiBzbyBmYXIsIGFuZCBhIG5ldyBxdWVzdGlvbiBhc2tlZCBieSB0aGUgdXNlciB0aGF0IG5lZWRzIHRvIGJlIGFuc3dlcmVkIGJ5IHNlYXJjaGluZyBpbiBhIGtub3dsZWRnZSBiYXNlIGFib3V0IHRlcm1zIG9mIHNlcnZpY2UsIHByaXZhY3kgcG9saWN5LCBhbmQgcXVlc3Rpb25zIGFib3V0IHN1cHBvcnQgcmVxdWVzdHMuPGJyPkdlbmVyYXRlIGEgc2VhcmNoIHF1ZXJ5IGJhc2VkIG9uIHRoZSBjb252ZXJzYXRpb24gYW5kIHRoZSBuZXcgcXVlc3Rpb24uPGJyPkRvIG5vdCBpbmNsdWRlIGNpdGVkIHNvdXJjZSBmaWxlbmFtZXMgYW5kIGRvY3VtZW50IG5hbWVzIGUuZyBpbmZvLnR4dCBvciBkb2MucGRmIGluIHRoZSBzZWFyY2ggcXVlcnkgdGVybXMuPGJyPkRvIG5vdCBpbmNsdWRlIGFueSB0ZXh0IGluc2lkZSBbXSBvciA8PD4+IGluIHRoZSBzZWFyY2ggcXVlcnkgdGVybXMuPGJyPkRvIG5vdCBpbmNsdWRlIGFueSBzcGVjaWFsIGNoYXJhY3RlcnMgbGlrZSAnKycuPGJyPklmIHRoZSBxdWVzdGlvbiBpcyBub3QgaW4gRW5nbGlzaCwgdHJhbnNsYXRlIHRoZSBxdWVzdGlvbiB0byBFbmdsaXNoIGJlZm9yZSBnZW5lcmF0aW5nIHRoZSBzZWFyY2ggcXVlcnkuPGJyPklmIHlvdSBjYW5ub3QgZ2VuZXJhdGUgYSBzZWFyY2ggcXVlcnksIHJldHVybiBqdXN0IHRoZSBudW1iZXIgMC48YnI+PGJyPjxicj51c2VyOiBXaGF0IGhhcHBlbnMgaWYgYSBwYXltZW50IGVycm9yIG9jY3Vycz88YnI+PGJyPmFzc2lzdGFudDogU2hvdyBzdXBwb3J0IGZvciBwYXltZW50IGVycm9yczxicj48YnI+dXNlcjogY2FuIEkgZ2V0IHJlZnVuZGVkIGlmIGNhbm5vdCB0cmF2ZWw/PGJyPjxicj5hc3Npc3RhbnQ6IFJlZnVuZCBwb2xpY3k8YnI+PGJyPnVzZXI6IEdlbmVyYXRlIHNlYXJjaCBxdWVyeSBmb3I6IEhvdyB0byBzZWFyY2ggYW5kIGJvb2sgcmVudGFscz88YnI+PGJyPnN5c3RlbTogQXNzaXN0YW50IGhlbHBzIHRoZSBDb25zdG8gUmVhbCBFc3RhdGUgY29tcGFueSBjdXN0b21lcnMgd2l0aCBzdXBwb3J0IHF1ZXN0aW9ucyByZWdhcmRpbmcgdGVybXMgb2Ygc2VydmljZSwgcHJpdmFjeSBwb2xpY3ksIGFuZCBxdWVzdGlvbnMgYWJvdXQgc3VwcG9ydCByZXF1ZXN0cy4gQmUgYnJpZWYgaW4geW91ciBhbnN3ZXJzLjxicj5BbnN3ZXIgT05MWSB3aXRoIHRoZSBmYWN0cyBsaXN0ZWQgaW4gdGhlIGxpc3Qgb2Ygc291cmNlcyBiZWxvdy4gSWYgdGhlcmUgaXNuJ3QgZW5vdWdoIGluZm9ybWF0aW9uIGJlbG93LCBzYXkgeW91IGRvbid0IGtub3cuIERvIG5vdCBnZW5lcmF0ZSBhbnN3ZXJzIHRoYXQgZG9uJ3QgdXNlIHRoZSBzb3VyY2VzIGJlbG93LiBJZiBhc2tpbmcgYSBjbGFyaWZ5aW5nIHF1ZXN0aW9uIHRvIHRoZSB1c2VyIHdvdWxkIGhlbHAsIGFzayB0aGUgcXVlc3Rpb24uPGJyPkZvciB0YWJ1bGFyIGluZm9ybWF0aW9uIHJldHVybiBpdCBhcyBhbiBodG1sIHRhYmxlLiBEbyBub3QgcmV0dXJuIG1hcmtkb3duIGZvcm1hdC4gSWYgdGhlIHF1ZXN0aW9uIGlzIG5vdCBpbiBFbmdsaXNoLCBhbnN3ZXIgaW4gdGhlIGxhbmd1YWdlIHVzZWQgaW4gdGhlIHF1ZXN0aW9uLjxicj5FYWNoIHNvdXJjZSBoYXMgYSBuYW1lIGZvbGxvd2VkIGJ5IGNvbG9uIGFuZCB0aGUgYWN0dWFsIGluZm9ybWF0aW9uLCBhbHdheXMgaW5jbHVkZSB0aGUgc291cmNlIG5hbWUgZm9yIGVhY2ggZmFjdCB5b3UgdXNlIGluIHRoZSByZXNwb25zZS4gVXNlIHNxdWFyZSBicmFja2V0cyB0byByZWZlcmVuY2UgdGhlIHNvdXJjZSwgZm9yIGV4YW1wbGU6IFtpbmZvMS50eHRdLiBEb24ndCBjb21iaW5lIHNvdXJjZXMsIGxpc3QgZWFjaCBzb3VyY2Ugc2VwYXJhdGVseSwgZm9yIGV4YW1wbGU6IFtpbmZvMS50eHRdW2luZm8yLnBkZl0uPGJyPkdlbmVyYXRlIDMgdmVyeSBicmllZiBmb2xsb3ctdXAgcXVlc3Rpb25zIHRoYXQgdGhlIHVzZXIgd291bGQgbGlrZWx5IGFzayBuZXh0Ljxicj5FbmNsb3NlIHRoZSBmb2xsb3ctdXAgcXVlc3Rpb25zIGluIGRvdWJsZSBhbmdsZSBicmFja2V0cy4gRXhhbXBsZTo8YnI+PDxBbSBJIGFsbG93ZWQgdG8gaW52aXRlIGZyaWVuZHMgZm9yIGEgcGFydHk/Pj48YnI+PDxIb3cgY2FuIEkgYXNrIGZvciBhIHJlZnVuZD8+Pjxicj48PFdoYXQgSWYgSSBicmVhayBzb21ldGhpbmc/Pj48YnI+PGJyPkRvIG5vIHJlcGVhdCBxdWVzdGlvbnMgdGhhdCBoYXZlIGFscmVhZHkgYmVlbiBhc2tlZC48YnI+TWFrZSBzdXJlIHRoZSBsYXN0IHF1ZXN0aW9uIGVuZHMgd2l0aCBcIj4+XCIuPGJyPjxicj48YnI+PGJyPnVzZXI6IEhvdyB0byBzZWFyY2ggYW5kIGJvb2sgcmVudGFscz88YnI+PGJyPlNvdXJjZXM6PGJyPnN1cHBvcnQubWQ6ICBbSG93IHRvIFNlYXJjaCBhbmQgQm9vayBSZW50YWxzXSgjaG93LXRvLXNlYXJjaC1hbmQtYm9vay1yZW50YWxzKSAyLiBbSG93IHRvIENhbmNlbCBhIENvbmZpcm1lZCBCb29raW5nXSgjaG93LXRvLWNhbmNlbC1hLWNvbmZpcm1lZC1ib29raW5nKSAzLiBbSG93IHRvIENvbnRhY3QgQ3VzdG9tZXIgU3VwcG9ydF0oI2hvdy10by1jb250YWN0LWN1c3RvbWVyLXN1cHBvcnQpIDQuIFtIb3cgdG8gUmVwb3J0IGEgUHJvYmxlbSB3aXRoIGEgTGlzdGluZ10oI2hvdy10by1yZXBvcnQtYS1wcm9ibGVtLXdpdGgtYS1saXN0aW5nKSA1LiBbSG93IHRvIFJlcG9ydCBhIFByb2JsZW0gd2l0aCBhIEd1ZXN0IG9yIEhvc3RdKCNob3ctdG8tcmVwb3J0LWEtcHJvYmxlbS13aXRoLWEtZ3Vlc3Qtb3ItaG9zdCkgNi4gW0hvdyB0byBSZXBvcnQgYSBTYWZldHkgSXNzdWVdKCNob3ctdG8tcmVwb3J0LWEtc2FmZXR5LWlzc3VlKSA3LiBbSG93IHRvIFJlcG9ydCBhIFBheW1lbnQgb3IgUmVmdW5kIElzc3VlXSgjaG93LXRvLXJlcG9ydC1hLXBheW1lbnQtb3ItcmVmdW5kLWlzc3VlKSA4LiBbR3Vlc3Qgb3IgSG9zdCBSdWxlIFZpb2xhdGlvbnNdKCNndWVzdC1vci1ob3N0LXJ1bGUtdmlvbGF0aW9ucykgOS4gW0NvbXBlbnNhdGlvbiBmb3IgRGFtYWdlXSgjY29tcGVuc2F0aW9uLWZvci1kYW1hZ2UpIDEwLiBbUGF5bWVudCBFcnJvciBSZXNvbHV0aW9uXSgjcGF5bWVudC1lcnJvci1yZXNvbHV0aW9uKSAtLS0gIyMgMS4gSG93IHRvIFNlYXJjaCBhbmQgQm9vayBSZW50YWxzIENvbnRvc28gUmVhbCBFc3RhdGUgb2ZmZXJzIGEgd2lkZSByYW5nZSBvZiByZW50YWwgcHJvcGVydGllcyBmb3IgeW91ciBzdGF5LiBIZXJlJ3MgaG93IHRvIHNlYXJjaCBhbmQgYm9vayByZW50YWxzOiAxLiAqKlNlYXJjaCBmb3IgUmVudGFsczoqKiAgICAtIEVudGVyIHlvdXIgZGVzdGluYXRpb24sIGNoZWNrLWluIGFuZCBjaGVjay1vdXQgZGF0ZXMsIGFuZCB0aGUgbnVtYmVyIG9mIGd1ZXN0cy4gICAgLSBBcHBseSBmaWx0ZXJzIHN1Y2ggYXMgcHJpY2UgcmFuZ2UsIHByb3BlcnR5IHR5cGUsIGFuZCBhbWVuaXRpZXMgdG8gbmFycm93IGRvd24geW91ciBvcHRpb25zLjxicj50ZXJtcy1vZi1zZXJ2aWNlLm1kOiAgV2UgYWltIHRvIGNyZWF0ZSBhIHRydXN0ZWQgY29tbXVuaXR5IHdoZXJlIGhvc3RzIGNhbiBzaGFyZSB0aGVpciBzcGFjZXMgYW5kIGd1ZXN0cyBjYW4gZW5qb3kgbWVtb3JhYmxlIGV4cGVyaWVuY2VzLiAjIyAyLiBIb3cgdG8gU2VhcmNoIGFuZCBCb29rIFJlbnRhbHMgIyMjIDIuMSBDcmVhdGluZyBhbiBBY2NvdW50IFRvIHNlYXJjaCBmb3IgYW5kIGJvb2sgcmVudGFscywgdXNlcnMgbXVzdCBjcmVhdGUgYSBDb250b3NvIFJlYWwgRXN0YXRlIGFjY291bnQuIFlvdSBtdXN0IHByb3ZpZGUgYWNjdXJhdGUgYW5kIGNvbXBsZXRlIGluZm9ybWF0aW9uIGR1cmluZyB0aGUgcmVnaXN0cmF0aW9uIHByb2Nlc3MuIFVzZXJzIGFyZSByZXNwb25zaWJsZSBmb3IgbWFpbnRhaW5pbmcgdGhlIGNvbmZpZGVudGlhbGl0eSBvZiB0aGVpciBhY2NvdW50IGNyZWRlbnRpYWxzLiAjIyMgMi4yIEJyb3dzaW5nIGFuZCBTZWFyY2hpbmcgLSBVc2VycyBjYW4gYnJvd3NlIGF2YWlsYWJsZSByZW50YWxzIHdpdGhvdXQgYW4gYWNjb3VudC4gLSBVc2Ugb3VyIHNlYXJjaCBmaWx0ZXJzIHRvIG5hcnJvdyBkb3duIHJlbnRhbCBvcHRpb25zIGJhc2VkIG9uIHlvdXIgcHJlZmVyZW5jZXMuIC0gQ2xpY2sgb24gYSByZW50YWwgbGlzdGluZyB0byB2aWV3IGRldGFpbHMsIGluY2x1ZGluZyBwcmljaW5nLCBhdmFpbGFiaWxpdHksIGFuZCBob3N0IGluZm9ybWF0aW9uLiAjIyMgMi4zIEJvb2tpbmcgYSBSZW50YWwgLSBUbyBib29rIGEgcmVudGFsLCBjbGljayB0aGUgXCJCb29rIE5vd1wiIGJ1dHRvbiBvbiB0aGUgbGlzdGluZyBwYWdlLiAtIFJldmlldyB0aGUgYm9va2luZyBkZXRhaWxzLCBpbmNsdWRpbmcgZGF0ZXMgYW5kIHByaWNpbmcsIGJlZm9yZSBjb25maXJtaW5nIHRoZSByZXNlcnZhdGlvbi4gLSBQYXltZW50IGlzIHByb2Nlc3NlZCBzZWN1cmVseSB0aHJvdWdoIG91ciBwbGF0Zm9ybS4gR3Vlc3RzIHdpbGwgcmVjZWl2ZSBhIGJvb2tpbmcgY29uZmlybWF0aW9uIGVtYWlsLiAjIyMgMi40IEd1ZXN0IFZlcmlmaWNhdGlvbiAtIEd1ZXN0cyBtYXkgYmUgcmVxdWlyZWQgdG8gY29tcGxldGUgaWRlbnRpdHkgdmVyaWZpY2F0aW9uIHN0ZXBzLjxicj5zdXBwb3J0Lm1kOiAgKipTZWFyY2ggZm9yIFJlbnRhbHM6KiogICAgLSBFbnRlciB5b3VyIGRlc3RpbmF0aW9uLCBjaGVjay1pbiBhbmQgY2hlY2stb3V0IGRhdGVzLCBhbmQgdGhlIG51bWJlciBvZiBndWVzdHMuICAgIC0gQXBwbHkgZmlsdGVycyBzdWNoIGFzIHByaWNlIHJhbmdlLCBwcm9wZXJ0eSB0eXBlLCBhbmQgYW1lbml0aWVzIHRvIG5hcnJvdyBkb3duIHlvdXIgb3B0aW9ucy4gICAgLSBCcm93c2UgdGhyb3VnaCB0aGUgbGlzdGluZ3MgdG8gZmluZCB0aGUgcGVyZmVjdCBwbGFjZSBmb3IgeW91ciBzdGF5LiAyLiAqKlZpZXcgTGlzdGluZyBEZXRhaWxzOioqICAgIC0gQ2xpY2sgb24gYSBsaXN0aW5nIHRvIHZpZXcgZGV0YWlsZWQgaW5mb3JtYXRpb24sIGluY2x1ZGluZyBwaG90b3MsIHByb3BlcnR5IGRlc2NyaXB0aW9uLCByZXZpZXdzLCBhbmQgaG9zdCBpbmZvcm1hdGlvbi4gMy4gKipNYWtlIGEgQm9va2luZzoqKiAgICAtIENsaWNrIHRoZSBcIkJvb2sgTm93XCIgYnV0dG9uIG9uIHRoZSBsaXN0aW5nIHBhZ2UuICAgIC0gUmV2aWV3IHRoZSBib29raW5nIGRldGFpbHMsIGluY2x1ZGluZyB0aGUgdG90YWwgY29zdCBhbmQgaG91c2UgcnVsZXMuICAgIC0gQ29uZmlybSB5b3VyIGJvb2tpbmcgYnkgcHJvdmlkaW5nIHBheW1lbnQgaW5mb3JtYXRpb24uICAgIC0gT25jZSB0aGUgaG9zdCBhY2NlcHRzIHlvdXIgYm9va2luZywgeW91J2xsIHJlY2VpdmUgYSBjb25maXJtYXRpb24uIDQuICoqUGF5bWVudDoqKiAgICAtIENvbnRvc28gUmVhbCBFc3RhdGUgaGFuZGxlcyB0aGUgcGF5bWVudCBwcm9jZXNzIHNlY3VyZWx5LiBZb3UnbGwgb25seSBiZSBjaGFyZ2VkIG9uY2UgeW91ciBib29raW5nIGlzIGNvbmZpcm1lZC4gNS4gKipDb21tdW5pY2F0aW9uOioqICAgIC0gWW91IGNhbiBjb21tdW5pY2F0ZSB3aXRoIHRoZSBob3N0IHRocm91Z2ggb3VyIG1lc3NhZ2luZyBzeXN0ZW0gZm9yIGFueSBxdWVzdGlvbnMgb3Igc3BlY2lhbCByZXF1ZXN0cy4gLS0tICMjIDIuIEhvdyB0byBDYW5jZWwgYSBDb25maXJtZWQgQm9va2luZyBMaWZlIGhhcHBlbnMsIGFuZCBzb21ldGltZXMgeW91IG5lZWQgdG8gY2FuY2VsIGEgY29uZmlybWVkIGJvb2tpbmcuIEhlcmUncyBob3cgdG8gZG8gaXQ6IDEuIn19LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiJUbyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBzZWFyY2giLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgYW5kIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGJvb2siLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgcmVudGFscyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiB3aXRoIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIENvbnQiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiJvc28iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgUmVhbCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBFc3RhdGUiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIsIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGZvbGxvdyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiB0aGVzZSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBzdGVwcyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IjpcbiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IjEiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIuIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIFNlYXJjaCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBmb3IiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgUmVudGFscyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IjpcbiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiAgIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIC0iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgRW50ZXIiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgeW91ciIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBkZXN0aW5hdGlvbiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiwiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgY2hlY2siLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiItaW4iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgYW5kIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGNoZWNrIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiLW91dCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBkYXRlcyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiwiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgYW5kIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIHRoZSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBudW1iZXIiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgb2YiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgZ3Vlc3RzIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiLlxuIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiICAiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgLSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBBcHBseSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBmaWx0ZXJzIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIHN1Y2giLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgYXMiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgcHJpY2UiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgcmFuZ2UiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIsIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIHByb3BlcnR5Iiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIHR5cGUiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIsIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGFuZCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBhbWVuaXRpZXMiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgdG8iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgbmFycm93Iiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGRvd24iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgeW91ciIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBvcHRpb25zIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiLlxuIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiMiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6Ii4iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgVmlldyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBMaXN0aW5nIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIERldGFpbHMiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiI6XG4iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgICIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiAtIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIENsaWNrIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIG9uIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGEiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgbGlzdGluZyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiB0byIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiB2aWV3Iiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGRldGFpbGVkIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGluZm9ybWF0aW9uIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiLCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBpbmNsdWRpbmciLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgcGhvdG9zIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiLCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBwcm9wZXJ0eSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBkZXNjcmlwdGlvbiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiwiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgcmV2aWV3cyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiwiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgYW5kIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGhvc3QiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgaW5mb3JtYXRpb24iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIuXG4iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIzIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiLiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBNYWtlIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGEiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgQm9va2luZyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IjpcbiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiAgIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIC0iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgQ2xpY2siLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgdGhlIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIFwiIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiQm9vayIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBOb3ciLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiJcIiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBidXR0b24iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgb24iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgdGhlIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGxpc3RpbmciLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgcGFnZSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6Ii5cbiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiAgIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIC0iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgUmV2aWV3Iiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIHRoZSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBib29raW5nIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGRldGFpbHMiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIsIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGluY2x1ZGluZyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiB0aGUiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgdG90YWwiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgY29zdCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBhbmQiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgaG91c2UiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgcnVsZXMiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIuXG4iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgICIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiAtIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIENvbmZpcm0iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgeW91ciIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBib29raW5nIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGJ5Iiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIHByb3ZpZGluZyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBwYXltZW50Iiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGluZm9ybWF0aW9uIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiLlxuIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiICAiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgLSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBPbmNlIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIHRoZSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBob3N0Iiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGFjY2VwdHMiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgeW91ciIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBib29raW5nIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiLCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiB5b3UiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiInbGwiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgcmVjZWl2ZSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBhIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGNvbmZpcm1hdGlvbiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6Ii5cbiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IjQiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIuIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIFBheW1lbnQiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiI6XG4iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgICIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiAtIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIENvbnQiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiJvc28iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgUmVhbCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBFc3RhdGUiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgaGFuZGxlcyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiB0aGUiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgcGF5bWVudCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBwcm9jZXNzIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIHNlY3VyZWx5Iiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiLiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBZb3UiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiInbGwiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgb25seSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBiZSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBjaGFyZ2VkIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIG9uY2UiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgeW91ciIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBib29raW5nIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGlzIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGNvbmZpcm1lZCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6Ii5cbiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IjUiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIuIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIENvbW11bmljYXRpb24iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiI6XG4iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgICIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiAtIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIFlvdSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBjYW4iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgY29tbXVuaWNhdGUiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgd2l0aCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiB0aGUiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgaG9zdCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiB0aHJvdWdoIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIG91ciIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBtZXNzYWdpbmciLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgc3lzdGVtIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIGZvciIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBhbnkiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgcXVlc3Rpb25zIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIG9yIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIHNwZWNpYWwiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgcmVxdWVzdHMiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIuIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIFsiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiJzdXBwb3J0Iiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiLm1kIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiXVxuXG4iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiI8PCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IkhvdyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBjYW4iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgSSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBjYW5jZWwiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgYSIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBjb25maXJtZWQiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgYm9va2luZyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6Ij8+Iiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiPlxuIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiPDwiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiJXaGF0Iiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIHBheW1lbnQiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgbWV0aG9kcyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBhcmUiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgYWNjZXB0ZWQiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiI/PiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6Ij5cbiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6Ijw8Iiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiQ2FuIiwicm9sZSI6ImFzc2lzdGFudCIsImNvbnRleHQiOnt9fSwiZmluaXNoX3JlYXNvbiI6bnVsbH1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQp7ImNob2ljZXMiOlt7ImluZGV4IjowLCJkZWx0YSI6eyJjb250ZW50IjoiIEkiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgY29udGFjdCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiB0aGUiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgaG9zdCIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiBiZWZvcmUiLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiIgYm9va2luZyIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6Ij8iLCJyb2xlIjoiYXNzaXN0YW50IiwiY29udGV4dCI6e319LCJmaW5pc2hfcmVhc29uIjpudWxsfV0sIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbi5jaHVuayJ9CnsiY2hvaWNlcyI6W3siaW5kZXgiOjAsImRlbHRhIjp7ImNvbnRlbnQiOiI+PiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOm51bGx9XSwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIn0KeyJjaG9pY2VzIjpbeyJpbmRleCI6MCwiZGVsdGEiOnsiY29udGVudCI6IiIsInJvbGUiOiJhc3Npc3RhbnQiLCJjb250ZXh0Ijp7fX0sImZpbmlzaF9yZWFzb24iOiJzdG9wIn1dLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsifQo=", + "encoding": "base64" + }, + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 4348.057 } + } + ] + } +} diff --git a/tests/e2e/webapp.spec.ts b/tests/e2e/webapp.spec.ts new file mode 100644 index 00000000..0b23b067 --- /dev/null +++ b/tests/e2e/webapp.spec.ts @@ -0,0 +1,173 @@ +import { test, expect } from '@playwright/test'; + +test.describe('default', () => { + test('chat interation', async ({ page }) => { + await page.goto('/'); + + const defaultQuestions = page.getByTestId('default-question'); + + // expect there to be at least 3 default question buttons on page load + await test.step('Get default questions', async () => { + await expect(defaultQuestions).toHaveCount(3); + }); + + const chatInput = page.getByTestId('question-input'); + const firstQuestionButton = defaultQuestions.nth(0); + const firstQuestionText = ((await firstQuestionButton.textContent()) ?? '').replace('Ask now', '').trim(); + + // should not have any text at the start + await test.step('Use default question', async () => { + await expect(chatInput).toHaveValue(''); + + await firstQuestionButton.click(); + await expect(chatInput).toHaveValue(firstQuestionText); + }); + + const userMessage = page.locator('.chat__txt.user-message'); + + // Set to replay the response for a local route (will not be used for the official) + await page.routeFromHAR('./tests/e2e/hars/default-chat-response-stream.har', { + url: '/chat', + update: false, + }); + + const showThoughtProcess = page.getByTestId('chat-show-thought-process'); + await test.step('Get answer', async () => { + await expect(showThoughtProcess).not.toBeVisible(); + + await page.getByTestId('submit-question-button').click(); + + // wait for the thought process button to be enabled. + await expect(showThoughtProcess).toBeEnabled({ timeout: 30_000 }); + + await expect(userMessage).toHaveCount(1); + await expect(userMessage.nth(0)).toHaveText(firstQuestionText); + + await expect(defaultQuestions).toHaveCount(0); + }); + + // make sure the response is formatted as list items + await test.step('response formatting', async () => { + await expect(page.locator('.items__listItem--step')).not.toHaveCount(0); + }); + + await test.step('Reset chat', async () => { + await page.getByTestId('chat-reset-button').click(); + await expect(userMessage).toHaveCount(0); + await expect(defaultQuestions).toHaveCount(3); + }); + }); + + test('waiting for response', async ({ page }) => { + await page.goto('/'); + await page.getByTestId('default-question').nth(0).click(); + + await page.route('/chat', (route) => + route.fulfill({ + status: -1, + }), + ); + + await expect(page.locator('.loading-skeleton')).not.toBeVisible(); + await page.getByTestId('submit-question-button').click(); + await expect(page.locator('.loading-skeleton')).toBeVisible(); + await expect(page.getByTestId('question-input')).not.toBeEnabled(); + }); + + test('show error on failure', async ({ page }) => { + await page.goto('/'); + await page.getByTestId('default-question').nth(0).click(); + + await page.route('/chat', (route) => route.abort()); + await page.route('**/chat', (route) => route.abort()); + + await page.getByTestId('submit-question-button').click(); + await expect(page.locator('.chat__txt.error')).toBeVisible(); + }); +}); + +test.describe('generate answer', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/'); + await page.getByTestId('default-question').nth(0).click(); + + await page.routeFromHAR('./tests/e2e/hars/default-chat-response-stream.har', { + url: '/chat', + update: false, + }); + + await page.getByTestId('submit-question-button').click(); + // wait for the thought process button to be enabled. + await expect(page.getByTestId('chat-show-thought-process')).toBeEnabled({ timeout: 30_000 }); + }); + + test('show thought process', async ({ page }) => { + const showThoughtProcess = page.getByTestId('chat-show-thought-process'); + const thoughtProcessAside = page.getByTestId('aside-thought-process'); + + await test.step('show/hide aside', async () => { + await expect(thoughtProcessAside).not.toBeVisible(); + await showThoughtProcess.click(); + await expect(thoughtProcessAside).toBeVisible(); + + await page.getByTestId('chat-hide-thought-process').click(); + await expect(thoughtProcessAside).not.toBeVisible(); + }); + + await test.step('Reset chat', async () => { + await showThoughtProcess.click(); + await expect(thoughtProcessAside).toBeVisible(); + await page.getByTestId('chat-reset-button').click(); + await expect(thoughtProcessAside).not.toBeVisible(); + }); + }); + + test('citation', async ({ page }) => { + const citations = page.getByTestId('citation'); + await expect(citations).toHaveCount(1); + + await expect(citations.nth(0)).toBeEnabled(); + await expect(citations.nth(0)).toContainText('support.md'); + expect(await citations.nth(0).getAttribute('href')).toContain('/content/support.md'); + }); +}); + +test.describe('developer settings', () => { + test('default settings', async ({ page }) => { + await page.goto('/'); + await page.getByTestId('button__developer-settings').click(); + + await expect(page.getByLabel('Override prompt template')).toBeVisible(); + await expect(page.getByLabel('Retrieve this many search results:')).toBeVisible(); + await expect(page.locator('label').filter({ hasText: 'Use semantic ranker' }).locator('i')).toBeChecked(); + await expect(page.locator('label').filter({ hasText: 'contextual summaries' }).locator('i')).not.toBeChecked(); + await expect(page.locator('label').filter({ hasText: 'follow-up questions' }).locator('i')).toBeChecked(); + await expect(page.locator('label').filter({ hasText: 'Stream chat' }).locator('i')).toBeChecked(); + await expect(page.getByLabel('Retrieval mode')).toContainText('Vectors + Text (Hybrid)'); + }); + + test('handle no stream parsing', async ({ page }) => { + await page.goto('/'); + await page.getByTestId('default-question').nth(0).click(); + + await page.routeFromHAR('./tests/e2e/hars/default-chat-response-nostream.har', { + url: '/chat', + update: false, + }); + + await page.getByTestId('button__developer-settings').click(); + const streamSetting = page.locator('label').filter({ hasText: 'Stream chat' }).locator('i'); + + await expect(streamSetting).toBeChecked(); + await streamSetting.click(); + await expect(streamSetting).not.toBeChecked(); + + await page.locator('button').filter({ hasText: 'Close' }).click(); + + await page.getByTestId('submit-question-button').click(); + // wait for the thought process button to be enabled. + await expect(page.getByTestId('chat-show-thought-process')).toBeEnabled({ timeout: 30_000 }); + + await expect(page.locator('.items__listItem--step')).not.toHaveCount(0); + }); +});