From 698bc9488ea2cd1a9ea1032b98c43189b885bfda Mon Sep 17 00:00:00 2001 From: lua-stefan-kruger Date: Sat, 26 Sep 2026 10:24:14 +0100 Subject: [PATCH 1/3] EM-WS8: headless hardening + standalone MCP server (1.6.0) - mcp/lua-platform: bundle @modelcontextprotocol/sdk and every other npm dependency into dist/server.js (createRequire banner for CJS deps), so the server runs with no node_modules (marketplace install, Job-tier image). tests/standalone-bundle.test.mjs copies the bundle + package.json into an empty temp dir and lists the five tools over stdio. - lib/tokenizer.mjs: replace the start-anchored regex with a shell lexer. Production verbs are found in any simple command of a &&/;/||/pipe chain, groups, $()/backticks/<(), bash -c/eval/ssh/| sh strings and heredocs, behind env-assignment prefixes and wrappers, via npx lua / npx lua-cli / pnpm exec / yarn / node .../lua-cli, and at any binary path; shell variables in the binary/verb position are blocked; unclosable input falls back to a textual search. LUA_DEPLOY_CONFIRMED=1 counts only as the first word of the same simple command, binary spelled bare, outside pipes/groups/substitutions. Closes the five Job-tier audit bypasses and the marketplace `templates`/`agent-template` and upper-case alias gaps. - LUA_PLUGIN_HEADLESS=1 (lib/headless.mjs): hooks name no slash command; check-lua-auth emits a neutral note instead of "run /lua-auth"; confirm-deploy treats the prefix as void and blocks every production verb; post-deploy-smoke sends no production ping. - docs/JOB_TIER.md "Running in the Lua Job tier"; SECURITY.md, READMEs, CHANGELOG; version 1.5.0 -> 1.6.0. Co-Authored-By: Claude Opus 5.5 --- .claude-plugin/marketplace.json | 2 +- README.md | 4 +- docs/JOB_TIER.md | 133 ++++ .../.claude-plugin/plugin.json | 2 +- plugins/lua-agent-builder/CHANGELOG.md | 91 +++ plugins/lua-agent-builder/README.md | 5 +- plugins/lua-agent-builder/SECURITY.md | 7 +- .../hooks/block-auto-deploy.mjs | 11 +- .../hooks/check-lua-auth.mjs | 23 +- .../hooks/check-lua-version.mjs | 18 +- .../hooks/confirm-deploy.mjs | 36 +- .../hooks/detect-project.mjs | 10 +- .../hooks/post-deploy-smoke.mjs | 10 +- plugins/lua-agent-builder/lib/headless.mjs | 33 + .../lua-agent-builder/lib/hook-runtime.mjs | 4 +- plugins/lua-agent-builder/lib/tokenizer.mjs | 678 ++++++++++++++++-- .../mcp/lua-platform/README.md | 9 +- .../mcp/lua-platform/dist/server.js | 9 +- .../mcp/lua-platform/package-lock.json | 4 +- .../mcp/lua-platform/package.json | 2 +- .../mcp/lua-platform/scripts/bundle.mjs | 27 +- .../mcp/lua-platform/src/api-client.mjs | 2 +- .../mcp/lua-platform/src/server.mjs | 6 +- .../tests/standalone-bundle.test.mjs | 131 ++++ plugins/lua-agent-builder/package-lock.json | 4 +- plugins/lua-agent-builder/package.json | 2 +- .../hooks/confirm-deploy.integration.test.mjs | 20 + .../test/hooks/headless.test.mjs | 172 +++++ .../test/lib/tokenizer-hardening.test.mjs | 352 +++++++++ 29 files changed, 1712 insertions(+), 95 deletions(-) create mode 100644 docs/JOB_TIER.md create mode 100644 plugins/lua-agent-builder/lib/headless.mjs create mode 100644 plugins/lua-agent-builder/mcp/lua-platform/tests/standalone-bundle.test.mjs create mode 100644 plugins/lua-agent-builder/test/hooks/headless.test.mjs create mode 100644 plugins/lua-agent-builder/test/lib/tokenizer-hardening.test.mjs diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 8a4eb32..5a42d58 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "name": "lua-agent-builder", "source": "./plugins/lua-agent-builder", "description": "Build, test, and deploy Lua AI agents from inside Claude Code", - "version": "1.5.0", + "version": "1.6.0", "homepage": "https://github.com/lua-ai-global/claude-code-lua-plugin#readme", "repository": "https://github.com/lua-ai-global/claude-code-lua-plugin.git", "license": "MIT", diff --git a/README.md b/README.md index 032c3b2..2fa3cf7 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ A [Claude Code](https://code.claude.com) marketplace + plugin for building, test πŸ“– **[User Guide β†’](./docs/USER_GUIDE.md)** β€” installation, walkthroughs, every slash command, hooks, MCP tools, safety model, troubleshooting. +πŸ€– **[Running in the Lua Job tier β†’](./docs/JOB_TIER.md)** β€” headless use (`LUA_PLUGIN_HEADLESS=1`, `claude -p`): inline playbooks, `--mcp-config`, and why the Lua-API proxy, not the hooks, is the boundary. + lua-cli is a TypeScript SDK/CLI. It has nothing to do with the Lua programming language. ## Install @@ -21,7 +23,7 @@ Then `/lua-auth`: an existing credential is kept; a new login runs `lua auth con | Plugin | Description | |---|---| -| [`lua-agent-builder`](./plugins/lua-agent-builder/) | 21 slash commands, 5 subagents, 10 hooks, a 6-file knowledge base verified against lua-cli source (3.33.0 base; 1.3.0 added per-step model classes and the workflow autonomy envelope from lua-cli 3.36.0, 1.4.0 the Job-tier billing rules and the lua-cli 3.37.0 cost read-outs, 1.5.0 log drains and the `lua logs` read window from lua-cli 3.38.0, read from `main`), a local read-only platform MCP server and the public docs MCP | +| [`lua-agent-builder`](./plugins/lua-agent-builder/) | 21 slash commands, 5 subagents, 10 hooks, a 6-file knowledge base verified against lua-cli source (3.33.0 base; 1.3.0 added per-step model classes and the workflow autonomy envelope from lua-cli 3.36.0, 1.4.0 the Job-tier billing rules and the lua-cli 3.37.0 cost read-outs, 1.5.0 log drains and the `lua logs` read window from lua-cli 3.38.0, read from `main`; 1.6.0 headless mode and a hardened production-gate parser), a local read-only platform MCP server and the public docs MCP | ## Quick walkthrough diff --git a/docs/JOB_TIER.md b/docs/JOB_TIER.md new file mode 100644 index 0000000..b2f237e --- /dev/null +++ b/docs/JOB_TIER.md @@ -0,0 +1,133 @@ +# Running in the Lua Job tier (headless) + +This page is for the people who run `lua-agent-builder` **unattended**: inside `claude -p` on a Lua workflow Job step, or in any CI-style harness where no one answers a prompt. It covers what changes when the plugin knows it is headless, what still works, and where the real security boundary sits. It applies from plugin **1.6.0**. + +> lua-cli is a TypeScript SDK/CLI; it is unrelated to the Lua programming language. + +## 1. Turn on headless mode + +Set **`LUA_PLUGIN_HEADLESS=1`** in the environment of the `claude` process. `true`, `yes` and `on` are accepted too. + +With it set, the hooks behave as follows: + +| Hook | Interactive (default) | Headless | +|---|---|---| +| `check-lua-auth` (SessionStart) | A failed probe says "not authenticated … run `/lua-auth`" | One neutral note: authentication *could not be confirmed*, behind a Lua-API proxy that often means only that the probe route is refused, carry on. It names no slash command. | +| `check-lua-version` (SessionStart) | Points at `/lua-doctor` / `/lua-update` / `npm i -g` | The same finding with no fix-it instruction. The image owns the lua-cli version, not the run. | +| `detect-project` (SessionStart) | "… Run /lua-doctor or /lua-test to begin." | "βœ“ Lua agent project detected: ``." | +| `confirm-deploy` (PreToolUse) | Bare production verbs are blocked. `LUA_DEPLOY_CONFIRMED=1 lua …` is allowed. | **Every** production verb is blocked, prefixed or not (`DEPLOY_DENIED_HEADLESS`). The prefix means "a person confirmed this deploy"; headless, the model would be confirming to itself. | +| `block-auto-deploy` (PreToolUse) | Blocks `--auto-deploy`, points at `/lua-deploy` | Blocks it, and tells the model to push without the flag | +| `post-deploy-smoke` (PostToolUse) | Sends a production `lua chat` ping after a deploy | Never runs. A headless deploy should be impossible, and more production traffic is the wrong response if one happens. | + +Nothing that is blocked interactively is allowed headless. The only differences are wording, the void prefix, and the skipped smoke ping. + +## 2. Load the plugin, and pass MCP servers explicitly + +```bash +LUA_PLUGIN_HEADLESS=1 LUA_TELEMETRY=false \ +claude -p "$STEP_PROMPT" \ + --plugin-dir /opt/claude-code-lua-plugin/plugins/lua-agent-builder \ + --setting-sources '' \ + --strict-mcp-config \ + --mcp-config "$MCP_CONFIG_JSON" \ + --settings "$INLINE_SETTINGS_JSON" \ + --disallowedTools Agent +``` + +- **`--strict-mcp-config` drops the plugin's own `.mcp.json`.** Skills, subagent files and hooks still load, but `lua-platform` and `lua-docs` do not. If you want them, pass them in `--mcp-config`: + + ```json + { + "mcpServers": { + "lua-docs": { "type": "http", "url": "https://docs.heylua.ai/mcp" }, + "lua-platform": { + "command": "node", + "args": ["/opt/claude-code-lua-plugin/plugins/lua-agent-builder/mcp/lua-platform/dist/server.js"] + } + } + } + ``` + + Tool names then follow the plain spelling (`mcp__lua-platform__get_agent`), not the `mcp__plugin_lua-agent-builder_…` one. +- **`lua-platform` is self-contained since 1.6.0.** `dist/server.js` bundles `@modelcontextprotocol/sdk` and every other dependency, so baking the plugin into an image needs no `npm ci`. Up to 1.5.0 it failed with `ERR_MODULE_NOT_FOUND` (seen as `lua-platform CONNECTION_CLOSED`). `mcp/lua-platform/tests/standalone-bundle.test.mjs` keeps it that way. + - It honours `LUA_API_URL` and `LUA_API_KEY`, so behind a proxy it needs no real credential. + - `list_agents` / `get_agent` shell out to `lua agents --json --ci`. The other three tools are GET-only. + - It is optional: every reference to its tools has a `lua status` / `lua logs` fallback. + - A harness that can only emit `{type: "http"}` servers cannot pass it. Leave it out rather than work around that. +- **`--setting-sources ''`** keeps the user and project `~/.claude` agents, skills and settings out of the run. +- `LUA_TELEMETRY=false` stops lua-cli's PostHog calls. lua-cli's npm-registry version check (3 s, silent on failure) still runs on every command. + +## 3. The Agent tool is denied: run the playbooks inline + +The Job-tier harness denies the `Agent` tool. Every slash command that hands work to a subagent cannot complete headless: `/lua-new`, `/lua-qa`, `/lua-deploy`, `/lua-architect`, and the `/lua-test` β†’ `lua-debug` failure hand-off. + +The subagent files are plain Markdown playbooks. Point the step prompt at them as instructions for the main model: + +| Need | Read inline | +|---|---| +| Scaffold, register, compile and test one primitive | `${CLAUDE_PLUGIN_ROOT}/agents/lua-skill-builder.md` | +| Diagnose a failing `lua compile --ci` / `lua test --ci` / `lua push` | `${CLAUDE_PLUGIN_ROOT}/agents/lua-debug.md` | +| A conversational QA pass with a triage report | `${CLAUDE_PLUGIN_ROOT}/agents/lua-qa.md`. Its sandbox chats run real tools against the agent's live Data and connections, so use read-only cases only. | + +`lua-deploy-pilot.md` has no headless use, because nothing goes live from a headless run. + +`AskUserQuestion` is refused in `-p` mode. The slash commands built around it do not work headless: `/lua-auth`, `/lua-doctor`, `/lua-update`, `/lua-init`, `/lua-sync`, `/lua-template`, `/lua-env`, `/lua-drains`, `/lua-logs` without arguments, and `/lua-version create` without a message. + +The following work inline with their arguments given up front: +- `lua push --ci --force`; +- `lua test --ci …` with the input JSON in the prompt; +- `lua chat --ci -e sandbox -m "" -t `; +- `lua workflows run` (offline); +- `lua version list|show|diff`; +- `lua version create --ci -m ""`. + +## 4. The proxy is the boundary. Hooks are belts. + +`confirm-deploy` got much harder to slip past in 1.6.0. +- It lexes the whole command and finds a production verb: + - anywhere in a `&&` / `;` / `||` / pipe chain; + - in a `( )` or `{ }` group; + - in `$( )`, backticks or `<( )`; + - in a string run by `bash -c` / `eval` / `ssh` / `… | sh`, or in a heredoc fed to a shell; + - behind `FOO=1` prefixes, `sudo` / `env` / `timeout`, `npx lua`, `npx lua-cli`, `pnpm exec lua` or `node …/lua-cli/…`, and at a binary path. +- A shell variable in the binary or verb position is blocked. +- The confirmation prefix counts only as the first word of the exact simple command that runs the verb. + +It is still a **belt**: +- A turn that can run a shell can always build a command the classifier cannot see: `echo | base64 -d | sh`, a script file written first, an `npm run` script, a `node` program that assembles the string, or a raw HTTP call. +- The Job tier also runs in `bypassPermissions` (the coding turn needs a shell), where permission **allow** rules have no effect. + +So: + +1. **The Lua-API proxy decides what reaches production.** It must refuse: + - deploy, promote and activate routes; + - workflow and job version bodies with `activate: true`; + - the live `PATCH …/sub-agent` and MCP upserts that `lua push all` issues. + + It must also pin the credential to the target agent. +2. **Inline `--settings` should carry deny rows, not the plugin's permission template.** Deny rows still apply under `bypassPermissions`. The template's allow list admits the `LUA_DEPLOY_CONFIRMED=1` forms, which is right for a person and wrong for a headless run. Suggested rows: + + ``` + Bash(*lua deploy*) Bash(*lua * deploy*) Bash(*version promote*) + Bash(*workflows deploy*) Bash(*workflows activate*) Bash(*mcp activate*) + Bash(*publish*) Bash(*--auto-deploy*) Bash(*--auto-push*) + Bash(*LUA_DEPLOY_CONFIRMED*) Bash(*lua push agent*) Bash(*lua env*) + Bash(*lua auth*) Bash(*npm install -g*) + ``` + +3. **Allow `GET /agents/self-serve/models` through the proxy.** It is the `check-lua-auth` probe (`lua models list --json --ci`). If the proxy refuses it, the headless hook emits its neutral note and the run carries on, but the note is noise. + - Do not disable hooks with `--settings '{"disableAllHooks": true}'` to silence it. That also removes the `confirm-deploy` belt. + +## 5. Environment hygiene + +`lua chat -e sandbox` uploads the invoking process's **entire environment** as the sandbox skill version's `env` (see [SECURITY.md](../plugins/lua-agent-builder/SECURITY.md), "Known platform-side exposure"). Keep the `claude` child environment minimal: the proxy URL, the proxy-scoped key, `PATH`, `HOME`, `LUA_PLUGIN_HEADLESS` and `LUA_TELEMETRY`. Nothing else. + +## 6. Checklist + +- [ ] `LUA_PLUGIN_HEADLESS=1` and `LUA_TELEMETRY=false` are set on the `claude` process. +- [ ] The plugin is baked from this repository's `plugins/lua-agent-builder` at a pinned commit (1.6.0 or later), with no `npm ci` needed. +- [ ] `--strict-mcp-config` is set, plus `--mcp-config` for whichever of `lua-docs` / `lua-platform` you want. +- [ ] `--disallowedTools Agent` is set, and the step prompts point at `agents/*.md` as inline playbooks. +- [ ] Inline `--settings` carries the deny rows above. +- [ ] The proxy refuses every go-live route and body, allows `GET /agents/self-serve/models`, and pins the target agent. +- [ ] The child environment is scrubbed. diff --git a/plugins/lua-agent-builder/.claude-plugin/plugin.json b/plugins/lua-agent-builder/.claude-plugin/plugin.json index 1270bf5..f80bf15 100644 --- a/plugins/lua-agent-builder/.claude-plugin/plugin.json +++ b/plugins/lua-agent-builder/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "lua-agent-builder", - "version": "1.5.0", + "version": "1.6.0", "description": "Build, test, and deploy Lua AI agents from inside Claude Code", "author": { "name": "Lua AI", diff --git a/plugins/lua-agent-builder/CHANGELOG.md b/plugins/lua-agent-builder/CHANGELOG.md index 5045edc..784749e 100644 --- a/plugins/lua-agent-builder/CHANGELOG.md +++ b/plugins/lua-agent-builder/CHANGELOG.md @@ -2,6 +2,97 @@ All notable changes to the `lua-agent-builder` plugin. Versions follow the tag `release-prod.yml` cuts from `package.json` (`v`). lua-cli is a TypeScript SDK/CLI; it is unrelated to the Lua programming language. +## 1.6.0 β€” 2026-09-26 + +**Headless hardening and a standalone MCP server (EM-WS8).** Three findings from the Lua Job-tier audit, where the plugin runs unattended inside `claude -p`: +- the `lua-platform` MCP server could not start without an `npm ci` nobody runs; +- the `confirm-deploy` parser was a start-anchored regex with five known bypasses; +- the hooks steered an unattended model into interactive flows that cannot complete. + +The lua-cli pin is unchanged (3.38.0). + +### `lua-platform` runs with no `node_modules` + +- `mcp/lua-platform/scripts/bundle.mjs` no longer marks `@modelcontextprotocol/sdk` external. `dist/server.js` now inlines every npm dependency from the committed lockfile: 106 KB β†’ 529 KB, against a 5 MB budget. + - Before this, a marketplace install, or the plugin baked into an image, died with `ERR_MODULE_NOT_FOUND`, which Claude Code reports as `lua-platform CONNECTION_CLOSED`. The plugin ships no `node_modules`, and `.mcp.json` launches `dist/server.js` directly. + - A `createRequire` banner gives the ESM bundle a real `require` for any CommonJS dependency. +- New `tests/standalone-bundle.test.mjs`: + - copies the bundle into an empty temp directory, asserting no `node_modules` exists anywhere above it; + - spawns it with `NODE_PATH` removed and runs `initialize` β†’ `tools/list` over stdio; + - asserts the five tools, and that `serverInfo.version` equals `package.json`, which catches a version bump that forgot to rebuild `dist/`. + - Against the 1.5.0 bundle it fails with `ERR_MODULE_NOT_FOUND`, as intended. + +### `confirm-deploy`: the parser reads the whole command + +`lib/tokenizer.mjs` used to test one regex anchored at the start of the string. These all ran a production verb straight past it: +- `cd x && lua deploy …` +- `true; lua version promote 3` +- `FOO=1 lua deploy all` +- `/usr/local/bin/lua deploy all` +- `npx lua deploy all` + +It now lexes the command the way a POSIX shell does (quotes, escapes, `&& || ; | |& &`, newlines, `( )` and `{ }` groups, redirections, heredocs) and checks **every simple command**: + +- **The binary is found at any word position, by basename.** That covers: + - `./node_modules/.bin/lua`, `C:/…/npm/lua.cmd`, and `"lua"` or `l\ua` spellings; + - env-assignment prefixes, and the `sudo` / `env` / `command` / `exec` / `timeout N` wrappers; + - launchers: `npx lua`, `npx lua-cli`, `npx -y lua-cli@3.38.0`, `pnpm exec lua`, `pnpm dlx lua-cli`, `yarn lua`, `npm exec -- lua`, `bunx lua-cli`; + - `node [opts] …/lua-cli/dist/index.js` and a directly executed `…/lua-cli/dist/index.js`. + - A bare `lua-cli` at the head is still unclassified, as in 1.5.0: it is not an installed binary. +- **Options between the binary and the verb are skipped**, both as boolean flags and as `--flag value` pairs. `lua --ci deploy`, `lua workflows -v 3 deploy x`. +- **Substitutions are parsed recursively.** That covers `$( )`, backticks and `<( )`, including inside double quotes. +- **Strings run by another shell are parsed too.** That covers `bash -c` / `sh -lc` / `eval` / `ssh host "…"` / `watch` / `npx -c`, `… | sh`, heredocs and here-strings fed to a shell, and `alias` / `trap` bodies. + - Inline interpreter code (`node -e`, `python3 -c`, `perl -e`) is searched as text. +- **A shell variable in the binary or verb position is blocked**, because it cannot be resolved: `L=lua; $L deploy all`, `lua $VERB all`, `… | xargs lua`. The label is `lua `. +- **Input the lexer cannot close** (an unterminated quote or substitution) falls back to an unanchored textual search, reported as unprefixed. +- **Alias gaps closed**, from lua-cli `aliases.ts`: + - `marketplace.noun` maps `templates`, `agent-template` and `agent-templates` to `template`; + - `normalizeArg` lower-cases action words, so `lua workflows DEPLOY x` is live. Matching is now case-insensitive. +- **`LUA_DEPLOY_CONFIRMED=1` counts only in its canonical shape.** It must be the first word of the very simple command that runs the verb (optionally after `env`), with the binary spelled bare, outside any pipe, group, substitution or wrapper string. + - Each verb in a chain needs its own prefix, and one unprefixed verb blocks the whole command. + - Blocked: `export LUA_DEPLOY_CONFIRMED=1; lua deploy all`, `LUA_DEPLOY_CONFIRMED=1 true && lua deploy all`, `LUA_DEPLOY_CONFIRMED=1 npx lua deploy all`, `FOO=1 LUA_DEPLOY_CONFIRMED=1 lua deploy all`. + - Allowed: `cd agent && LUA_DEPLOY_CONFIRMED=1 lua deploy skill …`, and redirections such as `> deploy.log 2>&1`. + - Every form `/lua-deploy`, the deploy pilot and `/lua-template` emit is unchanged and still allowed. +- **Text that only *mentions* a verb stays unclassified**: `git commit -m "lua deploy all"`, `grep -r "lua deploy" .`, `lua chat … -m "please lua deploy all"`, and a heredoc written to a file. +- `classifyProductionCommand` keeps its `{ label, slash, prefixed }` shape, and `PRODUCTION_COMMANDS` keeps `label` / `slash` / `re`, now with a `seq` token table. `lex()` and `UNRESOLVED_LABEL` are new exports. +- The `DEPLOY_DENIED_BARE` text now explains where the prefix counts. +- New `test/lib/tokenizer-hardening.test.mjs`, about 170 cases: + - every audit bypass and its neighbours; + - the prefix rule in both directions; + - false-positive guards; + - the fail-closed fallbacks; + - the lexer. +- The spawned `confirm-deploy` integration test gains the chain cases. + +This is still a belt, not a sandbox. A command assembled at runtime (`base64 -d | sh`, a script file, an npm script, a raw HTTP call) is out of any static classifier's reach. `SECURITY.md` now says so, and names the Lua-API proxy as the boundary for unattended runs. + +### Headless mode: `LUA_PLUGIN_HEADLESS=1` + +New `lib/headless.mjs`. With `LUA_PLUGIN_HEADLESS=1` (or `true` / `yes` / `on`): + +- **`check-lua-auth`**: every failure (exit 9, exit 11, other, timeout) becomes one neutral note. Authentication could not be confirmed; behind a Lua-API proxy that often means only that the probe route (`GET /agents/self-serve/models`) is refused; carry on. The note never says "run /lua-auth", which led the model into an `AskUserQuestion` flow that cannot complete in `-p` mode. +- **`check-lua-version` and `detect-project`**: the same findings, with no `/lua-doctor`, `/lua-update` or `npm i -g` instruction. +- **`confirm-deploy`**: the `LUA_DEPLOY_CONFIRMED=1` prefix is **void**, and every production verb is blocked with `DEPLOY_DENIED_HEADLESS`. The prefix means a person confirmed; headless, the model would be confirming to itself. `block-auto-deploy` loses its slash pointer as well. +- **`post-deploy-smoke`**: never sends its production `lua chat` ping. +- **`lib/hook-runtime.mjs`**: the too-old-Node message drops "re-run /lua-doctor". +- Interactive behaviour and text are unchanged. New `test/hooks/headless.test.mjs` asserts: + - no headless message matches `/lua-…`; + - nothing blocked interactively is allowed headless; + - a spawned headless `confirm-deploy` exits 2 on a prefixed deploy. + +### Docs + +- New **`docs/JOB_TIER.md`, "Running in the Lua Job tier"**. It covers: + - what headless mode changes; + - `--strict-mcp-config` dropping plugin MCP servers, so pass `lua-docs` (http) and `lua-platform` (stdio) through `--mcp-config`; + - the denied `Agent` tool, so read `agents/lua-skill-builder.md`, `lua-debug.md` and `lua-qa.md` inline as playbooks; + - which slashes work with full arguments and which need `AskUserQuestion`; + - the proxy as the boundary, with suggested inline deny rows because allow rules do nothing under `bypassPermissions`; + - allowing `GET /agents/self-serve/models` rather than disabling hooks; + - `LUA_TELEMETRY=false`, and environment scrubbing. +- Also updated: `SECURITY.md` (the gate row, the MCP bundle, the headless row), both READMEs, and the MCP README's build section. +- Bump 1.5.0 β†’ 1.6.0 everywhere `lint-release-version` checks, plus both lockfiles. `dist/server.js` is rebuilt. + ## 1.5.0 β€” 2026-09-22 **Log drains, and a `lua logs` that reads a window instead of a page.** Two shipped CLI surfaces reach the plugin: the whole `lua drains` command β€” the rules that copy an organization's agent log records to a destination the customer owns β€” and the `lua logs` read window `--since` / `--until` / `--environment` / `--follow`, with all **18** log sources finally reachable through `--type`. Everything below was read from lua-core-services `main`: `packages/lua-cli/src/cli/command-definitions.ts` (the `drains` and `logs` declarations), `src/commands/drains.ts`, `src/commands/drains.mutations.ts`, `src/commands/logs.ts`, `src/api/drains.api.service.ts`, `src/utils/aliases.ts` (`drains.action`, `logs.type`), `@lua/shared-types` `log-drain.types.ts` / `vm-execution-log.types.ts` and `@lua/shared-observability` `drain-scrubber.ts` β€” never from the public docs, which agree with all of it and are cited only as a destination for the user. [PRO-1896] diff --git a/plugins/lua-agent-builder/README.md b/plugins/lua-agent-builder/README.md index 506edb8..ba0ac0b 100644 --- a/plugins/lua-agent-builder/README.md +++ b/plugins/lua-agent-builder/README.md @@ -62,7 +62,8 @@ plugins/lua-agent-builder/ ## Safety model -- **Production gate** β€” every verb that changes what runs in production is blocked by the `confirm-deploy` hook (on every Bash call) unless it carries the `LUA_DEPLOY_CONFIRMED=1` prefix, which only the deploy flow emits after your single confirmation: `lua deploy`, `lua skills|webhooks|jobs|preprocessors|postprocessors deploy`, `lua persona production deploy`, `lua workflows deploy|activate`, `lua version promote`, `lua mcp activate`, `lua marketplace template publish|apply` β€” in every spelling lua-cli accepts (its `publish`/`on`/`enable`/`submit`/`rollout`/`prod` aliases and the `heylua`/`lua-ai` binaries). A hook block wins over any allow rule. The permission template allows the literal prefixed forms and carries no deny/ask rule for the bare verbs, because Claude Code evaluates deny/ask past a leading env assignment and such a rule would block the confirmed form too. `lib/tokenizer.mjs` is the one classifier; `test/lib/permissions-mirror.test.mjs` fails if the layers drift. +- **Production gate** β€” every verb that changes what runs in production is blocked by the `confirm-deploy` hook (on every Bash call) unless it carries the `LUA_DEPLOY_CONFIRMED=1` prefix, which only the deploy flow emits after your single confirmation: `lua deploy`, `lua skills|webhooks|jobs|preprocessors|postprocessors deploy`, `lua persona production deploy`, `lua workflows deploy|activate`, `lua version promote`, `lua mcp activate`, `lua marketplace template publish|apply` β€” in every spelling lua-cli accepts (its `publish`/`on`/`enable`/`submit`/`rollout`/`prod` aliases and the `heylua`/`lua-ai` binaries). A hook block wins over any allow rule. The permission template allows the literal prefixed forms and carries no deny/ask rule for the bare verbs, because Claude Code evaluates deny/ask past a leading env assignment and such a rule would block the confirmed form too. `lib/tokenizer.mjs` is the one classifier; `test/lib/permissions-mirror.test.mjs` fails if the layers drift. Since 1.6.0 the classifier reads the whole command β€” chains, groups, substitutions, `bash -c` strings, env prefixes, `npx`/`pnpm exec`/`node` launchers and binary paths β€” and honours the prefix only on the simple command that runs the verb. +- **Headless mode** β€” `LUA_PLUGIN_HEADLESS=1` (for `claude -p` in the Lua Job tier or CI): no hook message points at a slash command, the `LUA_DEPLOY_CONFIRMED=1` prefix is void (every production verb is blocked) and the post-deploy smoke ping is skipped. See [Running in the Lua Job tier](../../docs/JOB_TIER.md). - **`--auto-deploy`** is denied and blocked unconditionally. - **Log drains** (⏳ lua-cli 3.38.0) are ORGANIZATION configuration, not a deploy: `lua drains list|status|deliveries|test` are allowed, and `create|update|delete|verify|pause|resume|rotate-secret` sit in the `ask` tier β€” that prompt is `/lua-drains`'s single confirmation. They are deliberately **not** in `lib/tokenizer.mjs`: none of them changes what runs in production, and `LUA_DEPLOY_CONFIRMED=1` would be the wrong sentence for a log-shipping change. No secret ever reaches a command line β€” a header value is prompted or read from an environment variable (`--header-from-env NAME=ENV_VAR`), and the HMAC signing secret is minted server-side and printed exactly once. - **Credential isolation** β€” `lua auth configure|key|logout` are denied for the model; login happens in your terminal. @@ -70,7 +71,7 @@ plugins/lua-agent-builder/ ## MCP servers -- `lua-platform` (local, `mcp/lua-platform/dist/server.js`): five read-only tools β€” `list_agents`, `get_agent`, `list_primitive_versions`, `get_deployment_status`, `tail_logs` β€” over the same lua-api routes lua-cli uses, with lua-cli's credential resolution (env β†’ `.env` β†’ renewable session β†’ credentials file). +- `lua-platform` (local, `mcp/lua-platform/dist/server.js`, one self-contained bundle β€” no `node_modules` needed at runtime): five read-only tools β€” `list_agents`, `get_agent`, `list_primitive_versions`, `get_deployment_status`, `tail_logs` β€” over the same lua-api routes lua-cli uses, with lua-cli's credential resolution (env β†’ `.env` β†’ renewable session β†’ credentials file). - `lua-docs` (remote, `https://docs.heylua.ai/mcp`): the public docs search (`search_lua_cli`, `query_docs_filesystem_lua_cli`). - Claude Code names a plugin's MCP tools `mcp__plugin_lua-agent-builder___`; the subagents, slashes and the permission template use that form (the plain `mcp__lua-platform__…` spelling only exists for a server you register yourself with `claude mcp add`). diff --git a/plugins/lua-agent-builder/SECURITY.md b/plugins/lua-agent-builder/SECURITY.md index 17e0be1..11a6350 100644 --- a/plugins/lua-agent-builder/SECURITY.md +++ b/plugins/lua-agent-builder/SECURITY.md @@ -11,7 +11,7 @@ We aim to acknowledge within 2 business days and ship a fix within 30 days for h This plugin's surface includes: - **Hooks** (`hooks/*.mjs`) β€” run as subprocesses of Claude Code on `SessionStart`, `UserPromptSubmit`, and `Pre/PostToolUse(Bash)` events. -- **MCP servers** β€” `mcp/lua-platform/dist/server.js`, a local stdio server exposing 5 read-only tools; it talks to `https://api.heylua.ai` over HTTPS with the user's lua-cli credential (and, for a session login, refreshes the stored refresh token at Google's securetoken endpoint exactly like lua-cli does). `lua-docs` is the public remote MCP at `https://docs.heylua.ai/mcp` (read-only docs search). +- **MCP servers** β€” `mcp/lua-platform/dist/server.js`, a local stdio server exposing 5 read-only tools (a single self-contained bundle since 1.6.0 β€” its npm dependencies, `@modelcontextprotocol/sdk` included, are inlined at build time from the lockfile); it talks to `https://api.heylua.ai` over HTTPS with the user's lua-cli credential (and, for a session login, refreshes the stored refresh token at Google's securetoken endpoint exactly like lua-cli does). `lua-docs` is the public remote MCP at `https://docs.heylua.ai/mcp` (read-only docs search). - **Slash commands and subagents** (`commands/*.md`, `agents/*.md`) β€” Markdown prompts that Claude reads and executes. - **Permission rules** (`lib/permissions-template.json`) β€” merged into the user's `.claude/settings.json` by `/lua-doctor` Step 5 with consent. @@ -32,10 +32,11 @@ Out of scope: | Contract | Where enforced | |---|---| -| Production gate: `lua deploy`, `lua skills\|webhooks\|jobs\|preprocessors\|postprocessors deploy`, `lua persona production deploy`, `lua workflows deploy\|activate`, `lua version promote`, `lua mcp activate`, `lua marketplace template publish\|apply` are blocked in bare form; only the `LUA_DEPLOY_CONFIRMED=1`-prefixed form emitted after the user's confirmation runs. The gate covers every spelling lua-cli accepts: the action aliases from its `aliases.ts` (`publish`β†’deploy, `on`/`enable`β†’activate, `submit`/`publish_version`β†’template publish, `deploy`/`fleet-apply`/`rollout`β†’template apply, `prod`/`prd`/`live`β†’production) and all three installed binaries (`lua`, `heylua`, `lua-ai`) | **The hook is the gate.** `hooks/confirm-deploy.mjs` runs on **every** Bash call (no `if` glob to drift), classifies with `lib/tokenizer.mjs` (the single source of truth) and exits 2 on a bare verb β€” a hook block takes precedence over any allow rule, including a broad `Bash(lua *)` in the user's own settings. Wrappers and pipes are refused even with the prefix. `lib/permissions-template.json` allows the literal prefixed forms (so the confirmed command runs without a second prompt) and deliberately has **no** deny/ask rule for the bare verbs: Claude Code evaluates deny/ask rules past a leading env assignment (code.claude.com/docs/en/permissions: "A deny or ask rule matches past any leading assignment"), so a `Bash(lua deploy*)` deny would also block the confirmed form and make every deploy impossible β€” verified live on 2026-09-12. A bare verb that reaches the permission layer falls to Claude Code's default prompt (a denial in `-p` mode). `heylua`/`lua-ai` are denied wholesale. `test/lib/permissions-mirror.test.mjs` and `scripts/lint-permissions.mjs` fail if a deny/ask rule would shadow a confirmed form or an allow rule admits a bare one | +| Production gate: `lua deploy`, `lua skills\|webhooks\|jobs\|preprocessors\|postprocessors deploy`, `lua persona production deploy`, `lua workflows deploy\|activate`, `lua version promote`, `lua mcp activate`, `lua marketplace template publish\|apply` are blocked in bare form; only the `LUA_DEPLOY_CONFIRMED=1`-prefixed form emitted after the user's confirmation runs. The gate covers every spelling lua-cli accepts: the action aliases from its `aliases.ts` (`publish`β†’deploy, `on`/`enable`β†’activate, `submit`/`publish_version`β†’template publish, `deploy`/`fleet-apply`/`rollout`β†’template apply, `prod`/`prd`/`live`β†’production) and all three installed binaries (`lua`, `heylua`, `lua-ai`) | **The hook is the gate.** `hooks/confirm-deploy.mjs` runs on **every** Bash call (no `if` glob to drift), classifies with `lib/tokenizer.mjs` (the single source of truth) and exits 2 on a bare verb β€” a hook block takes precedence over any allow rule, including a broad `Bash(lua *)` in the user's own settings. Since 1.6.0 the classifier lexes the whole command, so a verb is found anywhere in a `&&`/`;`/`||`/pipe chain, in a `( )`/`{ }` group, in `$( )`/backticks/`<( )`, in a string handed to `bash -c`/`eval`/`ssh`/`… | sh` or a heredoc fed to a shell, behind env-assignment prefixes and `sudo`/`env`/`timeout` wrappers, through `npx lua`, `npx lua-cli`, `pnpm exec lua`, `yarn lua`, `node …/lua-cli/…`, and at any binary path; a shell variable in the binary or verb position is blocked. The prefix counts only as the first word of the very simple command that runs the verb, with the binary spelled bare β€” never through a pipe, group, substitution, wrapper string or launcher β€” and each verb in a chain needs its own. With `LUA_PLUGIN_HEADLESS=1` the prefix is void and every production verb is blocked (docs/JOB_TIER.md). The hook is still a belt against a model, not a sandbox: a command assembled at runtime (`base64 -d \| sh`, a script file, an npm script, a raw HTTP call) is out of its reach β€” in unattended runs the Lua-API proxy is the boundary. `lib/permissions-template.json` allows the literal prefixed forms (so the confirmed command runs without a second prompt) and deliberately has **no** deny/ask rule for the bare verbs: Claude Code evaluates deny/ask rules past a leading env assignment (code.claude.com/docs/en/permissions: "A deny or ask rule matches past any leading assignment"), so a `Bash(lua deploy*)` deny would also block the confirmed form and make every deploy impossible β€” verified live on 2026-09-12. A bare verb that reaches the permission layer falls to Claude Code's default prompt (a denial in `-p` mode). `heylua`/`lua-ai` are denied wholesale. `test/lib/permissions-mirror.test.mjs` and `scripts/lint-permissions.mjs` fail if a deny/ask rule would shadow a confirmed form or an allow rule admits a bare one | | `--auto-deploy` is never allowed | deny list (`Bash(lua * --auto-deploy*)` matches prefixed or not) + `hooks/block-auto-deploy.mjs` + `hooks/confirm-deploy.mjs` | | Single-permission contract: each slash asks at most one prompt. For workflow run-control verbs (`lua workflows start\|approve\|signal\|resume\|retry-step\|resolve-step\|raise-budget\|cancel\|deactivate\|export\|schedules\|goals`) that single prompt is the **Bash permission prompt** from the `ask` tier, which shows the exact command; `/lua-workflow` does not add an AskUserQuestion on top. `/lua-env` (`lua env *`; listings are masked by the CLI, set values are never echoed by the slash) and `/lua-integrations` (connect/update/disconnect/convert, webhook and MCP toggles) rely on the same `ask`-tier prompt | `scripts/lint-single-permission.mjs`; `ask` tier of `lib/permissions-template.json` | -| Post-deploy smoke check fires after every verb that makes something live (`SMOKE_LABELS` in `lib/tokenizer.mjs`: deploy spellings, `persona production deploy`, `workflows deploy`, `version promote`, `mcp activate`) | `hooks/post-deploy-smoke.mjs` (PostToolUse on every Bash call) | +| Post-deploy smoke check fires after every verb that makes something live (`SMOKE_LABELS` in `lib/tokenizer.mjs`: deploy spellings, `persona production deploy`, `workflows deploy`, `version promote`, `mcp activate`); never in headless mode, which sends no production ping | `hooks/post-deploy-smoke.mjs` (PostToolUse on every Bash call) | +| Headless mode (`LUA_PLUGIN_HEADLESS=1`): no hook message points at a slash command (they need AskUserQuestion or the Agent tool), and nothing blocked interactively is allowed | `lib/headless.mjs`; `test/hooks/headless.test.mjs` | | Credential isolation: account details, one-time codes and credentials never enter the conversation | `commands/lua-auth.md` sends login to a private terminal; `hooks/block-auth-configure.mjs`; `lua auth configure\|key\|logout` denied in `lib/permissions-template.json` | | Read-only MCP: no tool mutates platform state | `mcp/lua-platform/src/tools/*` (GET routes and `lua agents --json` only) | diff --git a/plugins/lua-agent-builder/hooks/block-auto-deploy.mjs b/plugins/lua-agent-builder/hooks/block-auto-deploy.mjs index 7e5c46e..33adbe5 100644 --- a/plugins/lua-agent-builder/hooks/block-auto-deploy.mjs +++ b/plugins/lua-agent-builder/hooks/block-auto-deploy.mjs @@ -7,11 +7,13 @@ import { runHook, checkNodeVersion, isMainScript } from '../lib/hook-runtime.mjs'; import { hasAutoDeploy } from '../lib/tokenizer.mjs'; +import { isHeadless } from '../lib/headless.mjs'; /** * @param {{tool_input?: {command?: string}}|null} input + * @param {Record} [env] β€” defaults to process.env (headless switch) */ -export function decide(input) { +export function decide(input, env = process.env) { const command = input?.tool_input?.command ?? ''; if (hasAutoDeploy(command)) { @@ -19,8 +21,11 @@ export function decide(input) { block: true, reason: 'DEPLOY_DENIED_AUTO: --auto-deploy is never the right choice from inside Claude Code. ' + - 'Use /lua-deploy instead β€” it spawns the deploy-pilot subagent which gates each step ' + - 'with the Β§3.7 single-permission contract.', + (isHeadless(env) + ? 'This is a headless run (LUA_PLUGIN_HEADLESS=1): push without that flag and report what you ' + + 'staged; nothing goes live from this session.' + : 'Use /lua-deploy instead β€” it spawns the deploy-pilot subagent which gates each step ' + + 'with the Β§3.7 single-permission contract.'), }; } diff --git a/plugins/lua-agent-builder/hooks/check-lua-auth.mjs b/plugins/lua-agent-builder/hooks/check-lua-auth.mjs index 9586004..e244d26 100644 --- a/plugins/lua-agent-builder/hooks/check-lua-auth.mjs +++ b/plugins/lua-agent-builder/hooks/check-lua-auth.mjs @@ -17,9 +17,17 @@ // were signed out. lua-cli's exit-code classes (3.33.0) tell the outcomes // apart: 0 ok Β· 9 auth Β· 10 forbidden (a typed key scoped too narrowly for // the catalog route β€” still a valid login) Β· 11 Lua API unavailable. +// +// Headless (LUA_PLUGIN_HEADLESS=1, 1.6.0): every failure becomes one neutral +// note that names no slash command. In the Lua Job tier the credential is the +// pod's, lua-cli talks to a Lua-API proxy, and a proxy that refuses +// `GET /agents/self-serve/models` makes this probe fail with a perfectly good +// credential β€” "run /lua-auth" would send the model into an AskUserQuestion +// flow that cannot complete in `claude -p`. import { runHook, checkNodeVersion, isMainScript } from '../lib/hook-runtime.mjs'; import { spawnLua } from '../lib/lua-cli.mjs'; +import { isHeadless, HEADLESS_NOTE } from '../lib/headless.mjs'; export const AUTH_PROBE_ARGS = ['models', 'list', '--json', '--ci']; const AUTH_PROBE_TIMEOUT_MS = 15_000; @@ -29,8 +37,9 @@ const AUTH_PROBE_TIMEOUT_MS = 15_000; * Result of `lua --version` (must succeed before auth probe makes sense). * @param {{exitCode: number|null, stdout?: string, stderr?: string, timedOut?: boolean}} authResult * Result of `lua models list --json --ci`. + * @param {Record} [env] β€” defaults to process.env (headless switch) */ -export function decide(versionResult, authResult) { +export function decide(versionResult, authResult, env = process.env) { // If lua-cli isn't installed, check-lua-version already warned the user. // Don't double-warn here. if (versionResult.exitCode !== 0) return null; @@ -39,6 +48,18 @@ export function decide(versionResult, authResult) { // away from the catalog route β€” still authenticated for its own agents. if (authResult.exitCode === 0 || authResult.exitCode === 10) return null; + if (isHeadless(env)) { + const outcome = authResult.timedOut || authResult.exitCode === null + ? `did not answer within ${AUTH_PROBE_TIMEOUT_MS / 1000}s` + : `exited ${authResult.exitCode}`; + return { + warn: + `β„Ή Lua authentication could not be confirmed at session start (\`lua models list\` ${outcome}). ` + + 'Behind a Lua-API proxy this often means only that the probe route is not allowed; lua-cli commands ' + + 'that need the platform may still work, and any that fail will say why. ' + HEADLESS_NOTE, + }; + } + // A slow probe is not a missing credential. if (authResult.timedOut || authResult.exitCode === null) { return { diff --git a/plugins/lua-agent-builder/hooks/check-lua-version.mjs b/plugins/lua-agent-builder/hooks/check-lua-version.mjs index aa740ec..0d1062b 100644 --- a/plugins/lua-agent-builder/hooks/check-lua-version.mjs +++ b/plugins/lua-agent-builder/hooks/check-lua-version.mjs @@ -5,6 +5,7 @@ import { runHook, checkNodeVersion, isMainScript } from '../lib/hook-runtime.mjs'; import { spawnLua } from '../lib/lua-cli.mjs'; +import { isHeadless, HEADLESS_NOTE } from '../lib/headless.mjs'; // Pinned minimum lua-cli version. The plugin's commands, agents and knowledge // files describe the lua-cli 3.38.0 surface: the 3.33.0 base (workflows, @@ -62,25 +63,34 @@ export function compareSemver(a, b) { * Returns null (allow silently), or { warn } to print a warning. * * @param {{stdout: string, exitCode: number|null}} versionResult + * @param {Record} [env] β€” defaults to process.env. Headless + * (LUA_PLUGIN_HEADLESS=1): the same findings, but no /lua-doctor or /lua-update + * pointer and no install instruction β€” the image, not the run, owns lua-cli. */ -export function decide(versionResult) { +export function decide(versionResult, env = process.env) { + const headless = isHeadless(env); if (versionResult.exitCode !== 0) { return { - warn: 'Could not detect lua-cli version. Run /lua-doctor to install.', + warn: headless + ? `Could not detect lua-cli (\`lua --version\` failed). ${HEADLESS_NOTE}` + : 'Could not detect lua-cli version. Run /lua-doctor to install.', }; } const installed = parseSemver(versionResult.stdout); if (!installed) { return { - warn: `Couldn't parse lua --version output: "${versionResult.stdout.trim()}". Run /lua-doctor.`, + warn: `Couldn't parse lua --version output: "${versionResult.stdout.trim()}". ` + + (headless ? HEADLESS_NOTE : 'Run /lua-doctor.'), }; } const minimum = parseSemver(PINNED_MIN_LUA_CLI); if (compareSemver(installed, minimum) < 0) { return { - warn: `Lua plugin requires lua-cli β‰₯${PINNED_MIN_LUA_CLI} (you have ${installed.join('.')}) β€” run /lua-update or: npm i -g lua-cli@latest. The plugin will continue to work with degraded functionality until you do (lua drains, and the lua logs --since/--until/--environment/--follow options, do not exist below ${PINNED_MIN_LUA_CLI}).`, + warn: headless + ? `lua-cli ${installed.join('.')} is older than the plugin's minimum ${PINNED_MIN_LUA_CLI}: lua drains, and the lua logs --since/--until/--environment/--follow options, do not exist on it. ${HEADLESS_NOTE}` + : `Lua plugin requires lua-cli β‰₯${PINNED_MIN_LUA_CLI} (you have ${installed.join('.')}) β€” run /lua-update or: npm i -g lua-cli@latest. The plugin will continue to work with degraded functionality until you do (lua drains, and the lua logs --since/--until/--environment/--follow options, do not exist below ${PINNED_MIN_LUA_CLI}).`, }; } diff --git a/plugins/lua-agent-builder/hooks/confirm-deploy.mjs b/plugins/lua-agent-builder/hooks/confirm-deploy.mjs index d8ad899..2081092 100644 --- a/plugins/lua-agent-builder/hooks/confirm-deploy.mjs +++ b/plugins/lua-agent-builder/hooks/confirm-deploy.mjs @@ -16,18 +16,36 @@ // therefore lists only the prefixed forms (allow) and nothing for the bare // forms; an exit-2 block from this hook takes precedence over any allow rule, // including a broad `Bash(lua *)` in the user's own settings. +// +// 1.6.0 (EM-WS8): the classifier reads the whole command β€” every simple +// command in a `&&`/`;`/`||`/pipe chain, subshells, substitutions, strings run +// by another shell, env-assignment prefixes, launchers (`npx lua`, `npx +// lua-cli`, `pnpm exec lua`, `node …/lua`) and binary paths β€” and accepts +// the prefix only on the very simple command that runs the verb. Headless +// (LUA_PLUGIN_HEADLESS=1) the prefix is void: nobody is there to confirm, so +// every production verb is blocked and the block names no slash command. +// It remains a belt; in the Lua Job tier the Lua-API proxy is the boundary. import { runHook, checkNodeVersion, isMainScript } from '../lib/hook-runtime.mjs'; import { classifyProductionCommand, hasAutoDeploy } from '../lib/tokenizer.mjs'; +import { isHeadless } from '../lib/headless.mjs'; + +const HEADLESS_REASON = + 'This is a headless run (LUA_PLUGIN_HEADLESS=1): nothing here can confirm a production change, so the ' + + 'LUA_DEPLOY_CONFIRMED=1 prefix is not accepted and no deploy, promote, activation or template release ' + + 'runs from this session. Stage the change (lua push, lua version create) and report it; it is made live ' + + 'outside the run. Do not retry with another spelling.'; /** * Pure function β€” exported so tests can import and call directly without * the side effects of running as a script (per tech spec Β§17.1.1). * * @param {{tool_input?: {command?: string}}|null} input + * @param {Record} [env] β€” defaults to process.env (headless switch) */ -export function decide(input) { +export function decide(input, env = process.env) { const command = input?.tool_input?.command ?? ''; + const headless = isHeadless(env); if (hasAutoDeploy(command)) { return { @@ -35,13 +53,23 @@ export function decide(input) { reason: 'DEPLOY_DENIED_AUTO: --auto-deploy is never appropriate from inside Claude Code ' + '(a granular push would publish as a side effect; lua-cli ignores it for `push all` anyway). ' + - 'Use /lua-deploy instead β€” it spawns the deploy-pilot subagent which gates each step.', + (headless + ? HEADLESS_REASON + : 'Use /lua-deploy instead β€” it spawns the deploy-pilot subagent which gates each step.'), }; } const classified = classifyProductionCommand(command); if (!classified) return null; // Not a production verb β€” allow + + if (headless) { + return { + block: true, + reason: `DEPLOY_DENIED_HEADLESS: \`${classified.label}\` changes what runs in production. ${HEADLESS_REASON}`, + }; + } + if (classified.prefixed) return null; // User-authorised via the slash flow β€” allow return { @@ -49,7 +77,9 @@ export function decide(input) { reason: `DEPLOY_DENIED_BARE: \`${classified.label}\` changes what runs in production and is blocked without the ` + `LUA_DEPLOY_CONFIRMED=1 prefix. Use ${classified.slash} (it collects your single confirmation per the Β§3.7 ` + - 'contract, then emits the prefixed form). Shell wrappers and pipes are refused even with the prefix.', + 'contract, then emits the prefixed form). The prefix counts only as the first word of the simple command ' + + 'that runs the verb, with the binary spelled `lua` β€” not in a pipe, subshell, `$(…)`, `bash -c` string, ' + + 'or through npx/pnpm/node/a path, and it confirms only that one command in a chain.', }; } diff --git a/plugins/lua-agent-builder/hooks/detect-project.mjs b/plugins/lua-agent-builder/hooks/detect-project.mjs index a6b41f5..e37bf38 100644 --- a/plugins/lua-agent-builder/hooks/detect-project.mjs +++ b/plugins/lua-agent-builder/hooks/detect-project.mjs @@ -13,6 +13,7 @@ import { existsSync, readFileSync } from 'node:fs'; import { join } from 'node:path'; import { runHook, checkNodeVersion, isMainScript } from '../lib/hook-runtime.mjs'; +import { isHeadless } from '../lib/headless.mjs'; /** * Pure decision function. Reads from disk synchronously β€” file existence @@ -25,7 +26,9 @@ import { runHook, checkNodeVersion, isMainScript } from '../lib/hook-runtime.mjs * Test injection point retained as `opts.cwd` for backward compat. * * @param {{cwd?: string}|null} input β€” Claude Code hook payload - * @param {{cwd?: string}} [opts] β€” test override; takes precedence over input.cwd + * @param {{cwd?: string, env?: Record}} [opts] β€” test override; + * `cwd` takes precedence over input.cwd; `env` defaults to process.env (headless switch: + * no "run /lua-doctor" pointer when LUA_PLUGIN_HEADLESS=1) */ export function decide(input, opts = {}) { const cwd = opts.cwd ?? input?.cwd ?? process.cwd(); @@ -48,10 +51,9 @@ export function decide(input, opts = {}) { // Permission denied, etc. β€” print a generic message and move on. } + const detected = agentId ? `βœ“ Lua agent project detected: ${agentId}.` : 'βœ“ Lua agent project detected.'; return { - warn: agentId - ? `βœ“ Lua agent project detected: ${agentId}. Run /lua-doctor or /lua-test to begin.` - : 'βœ“ Lua agent project detected. Run /lua-doctor or /lua-test to begin.', + warn: isHeadless(opts.env ?? process.env) ? detected : `${detected} Run /lua-doctor or /lua-test to begin.`, }; } diff --git a/plugins/lua-agent-builder/hooks/post-deploy-smoke.mjs b/plugins/lua-agent-builder/hooks/post-deploy-smoke.mjs index 8e29219..49288bc 100644 --- a/plugins/lua-agent-builder/hooks/post-deploy-smoke.mjs +++ b/plugins/lua-agent-builder/hooks/post-deploy-smoke.mjs @@ -14,6 +14,7 @@ import { runHook, checkNodeVersion, isMainScript } from '../lib/hook-runtime.mjs'; import { classifyProductionCommand, SMOKE_LABELS } from '../lib/tokenizer.mjs'; +import { isHeadless } from '../lib/headless.mjs'; /** How far back the post-deploy log scan looks, in both spellings. */ const SMOKE_WINDOW = '1m'; @@ -21,12 +22,17 @@ const SMOKE_WINDOW_MS = 60_000; /** * @param {{tool_input?: {command?: string}, tool_response?: {success?: boolean}}|null} input - * @param {{spawnLuaFn?: Function}} [opts] β€” injectable for tests + * @param {{spawnLuaFn?: Function, env?: Record}} [opts] β€” injectable for tests */ export async function decide( input, - { spawnLuaFn } = {} + { spawnLuaFn, env = process.env } = {} ) { + // Headless (LUA_PLUGIN_HEADLESS=1): never send a production `lua chat` ping + // from an unattended run. confirm-deploy blocks every production verb there, + // so reaching this point would itself be a finding for the harness, not + // something to probe with more production traffic. + if (isHeadless(env)) return null; const command = input?.tool_input?.command ?? ''; const classified = classifyProductionCommand(command); if (!classified || !SMOKE_LABELS.has(classified.label)) return null; diff --git a/plugins/lua-agent-builder/lib/headless.mjs b/plugins/lua-agent-builder/lib/headless.mjs new file mode 100644 index 0000000..cc34804 --- /dev/null +++ b/plugins/lua-agent-builder/lib/headless.mjs @@ -0,0 +1,33 @@ +// Headless mode (EM-WS8, 1.6.0). See docs/JOB_TIER.md at the repository root. +// +// `LUA_PLUGIN_HEADLESS=1` tells the hooks that no human is in the loop β€” the +// plugin runs inside `claude -p` in the Lua Job tier (or any other +// unattended harness). In that mode: +// +// * no hook message points at a slash command. The slashes that fix things +// (/lua-auth, /lua-doctor, /lua-update, /lua-deploy, /lua-template) all +// need AskUserQuestion or the Agent tool, both unavailable headless, and a +// message naming them steers the model into a flow that cannot complete; +// * confirm-deploy treats the LUA_DEPLOY_CONFIRMED=1 prefix as VOID. The +// prefix means "a person confirmed this deploy"; headless, the model would +// be confirming to itself. Every production verb is blocked (fail closed); +// production changes are made outside the run; +// * post-deploy-smoke never sends its production `lua chat` ping. +// +// Blocking behaviour is otherwise identical: every command that is blocked +// interactively is blocked headless too. + +const TRUTHY = new Set(['1', 'true', 'yes', 'on']); + +/** + * @param {Record} [env] + * @returns {boolean} + */ +export function isHeadless(env = process.env) { + return TRUTHY.has(String(env?.LUA_PLUGIN_HEADLESS ?? '').trim().toLowerCase()); +} + +/** The sentence every headless message ends with instead of a slash command. */ +export const HEADLESS_NOTE = + 'This is a headless run (LUA_PLUGIN_HEADLESS=1): there is no one to answer a prompt, so do not start ' + + 'an interactive sign-in, install or deploy flow β€” continue with the task, or report the problem in your result.'; diff --git a/plugins/lua-agent-builder/lib/hook-runtime.mjs b/plugins/lua-agent-builder/lib/hook-runtime.mjs index 770408c..edb1e60 100644 --- a/plugins/lua-agent-builder/lib/hook-runtime.mjs +++ b/plugins/lua-agent-builder/lib/hook-runtime.mjs @@ -6,6 +6,7 @@ import { fileURLToPath } from 'node:url'; import { resolve } from 'node:path'; +import { isHeadless } from './headless.mjs'; const REQUIRED_NODE_MAJOR = 18; @@ -23,7 +24,8 @@ export function checkNodeVersion() { if (major < REQUIRED_NODE_MAJOR) { log.toClaudeCode( `LUA_NODE_VERSION_TOO_OLD: This plugin requires Node β‰₯${REQUIRED_NODE_MAJOR}. ` + - `You have ${process.versions.node}. Update Node and re-run /lua-doctor.` + `You have ${process.versions.node}. ` + + (isHeadless() ? 'The plugin hooks are inactive in this run.' : 'Update Node and re-run /lua-doctor.') ); exit(0); // Fail-open per Β§6.1 } diff --git a/plugins/lua-agent-builder/lib/tokenizer.mjs b/plugins/lua-agent-builder/lib/tokenizer.mjs index 2433888..b099960 100644 --- a/plugins/lua-agent-builder/lib/tokenizer.mjs +++ b/plugins/lua-agent-builder/lib/tokenizer.mjs @@ -1,8 +1,7 @@ -// Per tech spec Β§17.4 / feature doc Β§6.5. +// Per tech spec Β§17.4 / feature doc Β§6.5, hardened in 1.6.0 (EM-WS8). // Parses bash command strings to detect production-affecting lua-cli // invocations and the LUA_DEPLOY_CONFIRMED=1 prefix that signals -// user-authorised intent. Refuses shell wrappers and pipes β€” these can't be -// safely classified, so they're denied even with the right env var. +// user-authorised intent. // // THIS FILE IS THE SINGLE SOURCE OF TRUTH for "what changes production". // hooks/confirm-deploy.mjs and hooks/post-deploy-smoke.mjs classify with it @@ -15,11 +14,13 @@ // // The gated set is every lua-cli verb that changes what runs in production // (verified against packages/lua-cli/src/cli/command-definitions.ts and -// src/utils/aliases.ts, lua-cli 3.33.0), INCLUDING the action aliases the CLI -// resolves at runtime (aliases.ts: `publish` β†’ deploy, `on`/`enable` β†’ -// activate, `submit`/`publish_version` β†’ template publish, `deploy`/ -// `fleet-apply`/`rollout` β†’ template apply, `prod`/`prd`/`live` β†’ -// production) and the three installed binaries (`lua`, `heylua`, `lua-ai`). +// src/utils/aliases.ts), INCLUDING the action aliases the CLI resolves at +// runtime (aliases.ts: `publish` β†’ deploy, `on`/`enable` β†’ activate, +// `submit`/`publish_version` β†’ template publish, `deploy`/`fleet-apply`/ +// `rollout` β†’ template apply, `prod`/`prd`/`live` β†’ production, +// `templates`/`agent-template(s)` β†’ template) and the three installed +// binaries (`lua`, `heylua`, `lua-ai`). `normalizeArg` lower-cases every +// action word, so matching is case-insensitive. // // lua deploy per-primitive publish (skill, webhook, trigger, job, pre/postprocessor, persona, all) // lua skills|webhooks|jobs|preprocessors|postprocessors deploy|publish the same publish, older spelling @@ -34,34 +35,120 @@ // `lua push … --auto-deploy` publishes as a side effect of a push and is // never allowed, prefix or not (lua-cli ignores it for `push all`, but a // granular push would deploy). +// +// ── How a command is read (1.6.0) ───────────────────────────────────────── +// Up to 1.5.0 this was a regex anchored at the start of the string, so +// `cd x && lua deploy all`, `true; lua version promote 3`, `FOO=1 lua deploy +// all`, `/usr/local/bin/lua deploy all` and `npx lua deploy all` all passed +// (Job-tier audit, finding 3). The classifier now LEXES the command the way a +// POSIX shell would β€” quotes, escapes, `&& || ; | |& &`, newlines, `( )` and +// `{ }` groups, redirections, heredocs β€” and inspects EVERY simple command: +// +// * the lua binary is found at any word position, by basename +// (`/usr/local/bin/lua`, `./node_modules/.bin/heylua`, `lua.cmd`), so +// env-assignment prefixes, `sudo`/`env`/`command`/`exec`/`timeout N`/… +// wrappers and launchers (`npx lua`, `npx lua-cli`, `npx -y lua-cli@3`, +// `pnpm exec lua`, `pnpm dlx lua-cli`, `yarn lua`, `npm exec -- lua`, +// `bunx lua`) are all seen through; +// * `node [opts] ` counts when the path is a lua-cli entry point +// (`…/lua-cli/dist/index.js`, `…/bin/lua`); +// * option tokens between the binary and the verb are skipped (both as +// boolean flags and as `--flag value` pairs); +// * a shell variable in the binary or verb position (`$L deploy all`, +// `lua $VERB skill`) cannot be resolved and is blocked (fail closed); +// * `$(…)`, backticks and `<(…)` are parsed recursively, also inside +// double quotes; a string handed to a shell (`bash -c`, `sh -c`, `eval`, +// `ssh host "…"`, `watch`, `npx -c`, `… | sh`, a heredoc or here-string +// fed to a shell, `trap`, `alias`) is parsed recursively too; inline code +// for `node -e` / `python -c` / `perl -e` is searched textually; +// * input the lexer cannot close (an unterminated quote or substitution) +// falls back to an unanchored textual search. +// +// The LUA_DEPLOY_CONFIRMED=1 allowance survives ONLY in its canonical shape: +// `[env ]LUA_DEPLOY_CONFIRMED=1 lua|heylua|lua-ai …` as ONE simple +// command β€” the assignment is the first word of the very simple command that +// runs the verb, the binary is spelled bare, and the command is not part of a +// pipeline, a `( )`/`{ }` group, a substitution or a string run by another +// shell. `export LUA_DEPLOY_CONFIRMED=1; lua deploy all`, +// `LUA_DEPLOY_CONFIRMED=1 true && lua deploy all` and +// `LUA_DEPLOY_CONFIRMED=1 npx lua deploy all` are all blocked. In a chain, +// every production verb needs its own prefix; one unprefixed verb blocks the +// whole command. +// +// This is a belt, not the boundary. A determined caller can always build the +// command at runtime (`base64 -d | sh`, a script file, an npm script, a raw +// HTTP call). In the Lua Job tier the Lua-API proxy is the boundary; see +// docs/JOB_TIER.md. -const PREFIX = /^(?:env\s+)?LUA_DEPLOY_CONFIRMED=1\s+/; -const WRAPPER_HEAD = /^(bash|sh|zsh)\s/; const BIN = '(?:lua|heylua|lua-ai)'; -const rule = (label, body, slash) => ({ label, re: new RegExp(`^${BIN}\\s+${body}`), slash }); +/** Binaries lua-cli installs (package.json `bin`). */ +const BINARIES = new Set(['lua', 'heylua', 'lua-ai']); +/** Also accepted after a launcher (`npx lua-cli …`) or as a node entry point. */ +const PACKAGES = new Set([...BINARIES, 'lua-cli']); + +/** Commands that take ANOTHER command as argv (the verb can follow them). */ +const WRAPPERS = new Set([ + 'env', 'command', 'exec', 'builtin', 'nohup', 'time', 'nice', 'ionice', 'timeout', 'sudo', 'doas', + 'xargs', 'stdbuf', 'setsid', 'caffeinate', 'unbuffer', 'chronic', 'npx', 'pnpx', 'bunx', 'npm', + 'pnpm', 'yarn', 'bun', 'run', 'exec', 'dlx', 'x', '!', '{', 'then', 'do', 'else', 'if', 'while', 'until', +]); + +/** Commands that run a STRING as shell code (their string arguments are parsed recursively). */ +const SCRIPT_RUNNERS = new Set([ + 'sh', 'bash', 'zsh', 'dash', 'ksh', 'mksh', 'ash', 'fish', 'busybox', 'pwsh', 'powershell', 'cmd', + 'eval', 'ssh', 'su', 'runuser', 'script', 'flock', 'watch', 'parallel', 'npx', 'npm', 'concurrently', + 'nodemon', 'entr', 'trap', 'at', 'batch', +]); + +/** Interpreters whose inline code (`-e`, `-c`, `-p`, …) is searched textually. */ +const INLINE_CODE = new Set(['node', 'nodejs', 'bun', 'deno', 'python', 'python3', 'perl', 'ruby', 'php']); + +/** `node`-like launchers that take a script path as their first positional. */ +const NODE_LIKE = new Set(['node', 'nodejs', 'bun', 'tsx', 'ts-node']); + +/** Node options that consume the following word. */ +const NODE_VALUE_FLAGS = new Set(['-r', '--require', '--import', '--loader', '--experimental-loader', '--env-file', '--title', '--inspect-port']); + +const MAX_DEPTH = 6; + +const rule = (label, seq, slash) => ({ + label, + seq, + slash, + re: new RegExp(`^${BIN}\\s+${seq.map((alts) => `(?:${alts.join('|')})`).join('\\s+')}(?![\\w-])`, 'i'), +}); + +const DEPLOY = ['deploy', 'publish']; +const ACTIVATE = ['activate', 'on', 'enable']; +const PROD_ENV = ['production', 'prod', 'prd', 'live']; +const TEMPLATE = ['template', 'templates', 'agent-template', 'agent-templates']; /** - * Ordered list of gated command shapes. Each entry: the regex that matches - * the command (after any prefix is stripped; anchored at the binary), a short - * label, and the slash command that collects the user's confirmation. + * Ordered list of gated command shapes. Each entry: the positional token + * sequence (each position lists every spelling the CLI accepts), the + * equivalent binary-anchored regex, a short label, and the slash command that + * collects the user's confirmation. */ export const PRODUCTION_COMMANDS = [ - rule('lua deploy', 'deploy\\b', '/lua-deploy'), - rule('lua skills deploy', 'skills\\s+(?:deploy|publish)\\b', '/lua-deploy'), - rule('lua webhooks deploy', 'webhooks\\s+(?:deploy|publish)\\b', '/lua-deploy'), - rule('lua jobs deploy', 'jobs\\s+(?:deploy|publish)\\b', '/lua-deploy'), - rule('lua preprocessors deploy', 'preprocessors\\s+(?:deploy|publish)\\b', '/lua-deploy'), - rule('lua postprocessors deploy', 'postprocessors\\s+(?:deploy|publish)\\b', '/lua-deploy'), - rule('lua persona production deploy', 'persona\\s+(?:production|prod|prd|live)\\s+(?:deploy|publish)\\b', '/lua-deploy'), - rule('lua workflows deploy', 'workflows\\s+(?:deploy|publish)\\b', '/lua-deploy'), - rule('lua workflows activate', 'workflows\\s+(?:activate|on|enable)\\b', '/lua-deploy'), - rule('lua version promote', 'version\\s+promote\\b', '/lua-deploy'), - rule('lua mcp activate', 'mcp\\s+(?:activate|on|enable)\\b', '/lua-deploy'), - rule('lua marketplace template publish', 'marketplace\\s+template\\s+(?:publish|publish_version|submit)\\b', '/lua-template'), - rule('lua marketplace template apply', 'marketplace\\s+template\\s+(?:apply|deploy|fleet-apply|rollout)\\b', '/lua-template'), + rule('lua deploy', [['deploy']], '/lua-deploy'), + rule('lua skills deploy', [['skills'], DEPLOY], '/lua-deploy'), + rule('lua webhooks deploy', [['webhooks'], DEPLOY], '/lua-deploy'), + rule('lua jobs deploy', [['jobs'], DEPLOY], '/lua-deploy'), + rule('lua preprocessors deploy', [['preprocessors'], DEPLOY], '/lua-deploy'), + rule('lua postprocessors deploy', [['postprocessors'], DEPLOY], '/lua-deploy'), + rule('lua persona production deploy', [['persona'], PROD_ENV, DEPLOY], '/lua-deploy'), + rule('lua workflows deploy', [['workflows'], DEPLOY], '/lua-deploy'), + rule('lua workflows activate', [['workflows'], ACTIVATE], '/lua-deploy'), + rule('lua version promote', [['version'], ['promote']], '/lua-deploy'), + rule('lua mcp activate', [['mcp'], ACTIVATE], '/lua-deploy'), + rule('lua marketplace template publish', [['marketplace'], TEMPLATE, ['publish', 'publish_version', 'submit']], '/lua-template'), + rule('lua marketplace template apply', [['marketplace'], TEMPLATE, ['apply', 'deploy', 'fleet-apply', 'rollout']], '/lua-template'), ]; +/** Label for a lua invocation whose verb is a shell variable (cannot be resolved statically). */ +export const UNRESOLVED_LABEL = 'lua '; + /** Labels whose success should trigger the post-deploy smoke check (something now runs live). */ export const SMOKE_LABELS = new Set([ 'lua deploy', 'lua skills deploy', 'lua webhooks deploy', 'lua jobs deploy', 'lua preprocessors deploy', @@ -69,35 +156,534 @@ export const SMOKE_LABELS = new Set([ 'lua mcp activate', ]); +// Unanchored textual patterns β€” the fallback for input the lexer cannot close +// and for inline interpreter code. `lua-cli/` covers a node entry point. +const RAW_PATTERNS = PRODUCTION_COMMANDS.map((e) => ({ + entry: e, + re: new RegExp( + `(? `(?:${alts.join('|')})`).join('\\s+(?:-{1,2}[\\w-]+(?:=\\S*)?\\s+)*') + + '(?![\\w-])', + 'i', + ), +})); + +// ── Lexer ────────────────────────────────────────────────────────────────── + +/** + * @typedef {{text: string, quoted: boolean, dynamic: boolean}} Word + * @typedef {{words: Word[], sep: string|null, grouped: boolean, pipeline: boolean, pipeId: number, + * heredocs: string[], herestrings: string[]}} Segment + */ + +const newSegment = () => ({ words: [], sep: null, grouped: false, pipeline: false, pipeId: 0, heredocs: [], herestrings: [] }); + +/** Index of the `)` closing the `(` at `start`, honouring quotes and nesting; -1 if none. */ +function findClose(src, start) { + let depth = 0; + for (let i = start; i < src.length; i++) { + const c = src[i]; + if (c === '\\') { i++; continue; } + if (c === "'") { + const j = src.indexOf("'", i + 1); + if (j < 0) return -1; + i = j; + continue; + } + if (c === '"') { + let j = i + 1; + while (j < src.length && src[j] !== '"') j += src[j] === '\\' ? 2 : 1; + if (j >= src.length) return -1; + i = j; + continue; + } + if (c === '(') depth++; + else if (c === ')' && --depth === 0) return i; + } + return -1; +} + +/** Index of the next unescaped backtick after `start`; -1 if none. */ +function findBacktick(src, start) { + for (let i = start + 1; i < src.length; i++) { + if (src[i] === '\\') { i++; continue; } + if (src[i] === '`') return i; + } + return -1; +} + /** - * Classify a command. Returns null for commands that are not gated, or - * `{ label, slash, prefixed }` for a production-affecting lua-cli verb. - * Shell wrappers and pipes are reported as unsafe (`prefixed: false`) even - * when the env var is present, because the real command can't be seen. + * Split a shell command into simple commands. Collects command-substitution + * bodies (`$(…)`, backticks, `<(…)`) in `subs` for recursive inspection and + * sets `opaque` when something could not be closed. + * + * @param {string} src + * @returns {{segments: Segment[], subs: string[], opaque: boolean}} + */ +export function lex(src) { + /** @type {Segment[]} */ + const segments = []; + const subs = []; + let opaque = false; + let seg = newSegment(); + /** @type {Word|null} */ + let word = null; + let depth = 0; + let redirTarget = null; // null | 'file' | 'herestring' + /** @type {{delim: string, strip: boolean, seg: Segment}[]} */ + let pendingHeredocs = []; + const n = src.length; + let i = 0; + + const startWord = () => { if (!word) word = { text: '', quoted: false, dynamic: false }; return word; }; + const endWord = () => { + if (!word) return; + if (redirTarget === 'herestring') seg.herestrings.push(word.text); + if (redirTarget) redirTarget = null; + else if (!word.quoted && (word.text === '{' || word.text === '}')) { + // Brace group: `{ cmd; }` runs in the current shell but is still a group. + depth = Math.max(0, depth + (word.text === '{' ? 1 : -1)); + if (word.text === '{') seg.grouped = true; + } else seg.words.push(word); + word = null; + }; + const endSegment = (sep) => { + endWord(); + if (seg.words.length || seg.heredocs.length || seg.herestrings.length) { + seg.sep = sep; + if (depth > 0) seg.grouped = true; + segments.push(seg); + } else if ((sep === '|' || sep === '|&') && segments.length) { + segments[segments.length - 1].sep = sep; + } + seg = newSegment(); + }; + const takeSubstitution = (open) => { + // `open` indexes the `(` of `$(`, `<(` or `>(`. + const close = findClose(src, open); + if (close < 0) { opaque = true; subs.push(src.slice(open + 1)); return n; } + subs.push(src.slice(open + 1, close)); + return close + 1; + }; + const readHeredocBodies = () => { + for (const h of pendingHeredocs) { + const lines = []; + let found = false; + while (i < n) { + let end = src.indexOf('\n', i); + if (end < 0) end = n; + const line = src.slice(i, end); + i = end + 1; + if ((h.strip ? line.replace(/^\t+/, '') : line) === h.delim) { found = true; break; } + lines.push(line); + } + h.seg.heredocs.push(lines.join('\n')); + if (!found) i = n; + } + pendingHeredocs = []; + }; + + while (i < n) { + const c = src[i]; + const next = src[i + 1]; + + if (c === '\\') { + if (next === '\n') { i += 2; continue; } + const w = startWord(); + w.quoted = true; + if (next !== undefined) w.text += next; + i += 2; + continue; + } + if (c === "'") { + const w = startWord(); + w.quoted = true; + const j = src.indexOf("'", i + 1); + if (j < 0) { opaque = true; w.text += src.slice(i + 1); i = n; continue; } + w.text += src.slice(i + 1, j); + i = j + 1; + continue; + } + if (c === '"') { + const w = startWord(); + w.quoted = true; + let j = i + 1; + let closed = false; + while (j < n) { + const d = src[j]; + if (d === '"') { closed = true; break; } + if (d === '\\') { + const e = src[j + 1]; + if (e === '\n') { j += 2; continue; } + if (e !== undefined && '$`"\\'.includes(e)) { w.text += e; j += 2; continue; } + w.text += d; + j++; + continue; + } + if (d === '$' && src[j + 1] === '(') { w.dynamic = true; w.text += '$(…)'; j = takeSubstitution(j + 1); continue; } + if (d === '`') { + const k = findBacktick(src, j); + w.dynamic = true; + if (k < 0) { opaque = true; subs.push(src.slice(j + 1)); j = n; break; } + subs.push(src.slice(j + 1, k)); + w.text += '`…`'; + j = k + 1; + continue; + } + if (d === '$' && /[A-Za-z_{0-9@*#?$!-]/.test(src[j + 1] ?? '')) w.dynamic = true; + w.text += d; + j++; + } + if (!closed) opaque = true; + i = j + 1; + continue; + } + if (c === '`') { + const w = startWord(); + w.dynamic = true; + const k = findBacktick(src, i); + if (k < 0) { opaque = true; subs.push(src.slice(i + 1)); i = n; continue; } + subs.push(src.slice(i + 1, k)); + w.text += '`…`'; + i = k + 1; + continue; + } + if (c === '$') { + const w = startWord(); + if (next === '(') { w.dynamic = true; w.text += '$(…)'; i = takeSubstitution(i + 1); continue; } + if (next === "'") { + // ANSI-C quoting ($'\x6cua') can spell anything β€” treat as unresolvable. + w.dynamic = true; + w.quoted = true; + let j = i + 2; + while (j < n && src[j] !== "'") j += src[j] === '\\' ? 2 : 1; + if (j >= n) opaque = true; + w.text += src.slice(i, j + 1); + i = j + 1; + continue; + } + if (next === '"') { i++; continue; } // $"…" locale string = "…" + if (/[A-Za-z_{0-9@*#?$!-]/.test(next ?? '')) w.dynamic = true; + w.text += '$'; + i++; + continue; + } + if (c === ' ' || c === '\t' || c === '\r') { endWord(); i++; continue; } + if (c === '\n') { + endWord(); + i++; + if (pendingHeredocs.length) readHeredocBodies(); + endSegment(';'); + continue; + } + if (c === '#' && !word) { + while (i < n && src[i] !== '\n') i++; + continue; + } + if (c === ';') { endSegment(';'); i += next === ';' ? 2 : 1; continue; } + if (c === '&') { + if (next === '&') { endSegment('&&'); i += 2; continue; } + if (next === '>') { + endWord(); + i += src[i + 2] === '>' ? 3 : 2; + redirTarget = 'file'; + continue; + } + endSegment('&'); + i++; + continue; + } + if (c === '|') { + if (next === '|') { endSegment('||'); i += 2; continue; } + if (next === '&') { endSegment('|&'); i += 2; continue; } + endSegment('|'); + i++; + continue; + } + if (c === '(') { + if (word && word.text.endsWith('=')) { + // Array assignment `a=(x y)` β€” keep it as one word. + const close = findClose(src, i); + if (close < 0) { opaque = true; i = n; continue; } + word.text += src.slice(i, close + 1); + i = close + 1; + continue; + } + endWord(); + if (next === ')' && seg.words.length) { i += 2; continue; } // `name()` function definition + endSegment(';'); + depth++; + i++; + continue; + } + if (c === ')') { + endWord(); + if (seg.words.length) { seg.grouped = true; } + endSegment(')'); + depth = Math.max(0, depth - 1); + i++; + continue; + } + if (c === '<' || c === '>') { + if (next === '(') { + // Process substitution <(…) / >(…) is a word that runs a command. + const w = startWord(); + w.dynamic = true; + w.text += `${c}(…)`; + i = takeSubstitution(i + 1); + continue; + } + if (word && !word.quoted && !word.dynamic && /^\d+$/.test(word.text)) word = null; // fd number + else endWord(); + if (src.startsWith('<<<', i)) { i += 3; redirTarget = 'herestring'; continue; } + if (src.startsWith('<<', i)) { + i += 2; + const strip = src[i] === '-'; + if (strip) i++; + while (src[i] === ' ' || src[i] === '\t') i++; + let delim = ''; + while (i < n && !/[\s;&|<>()]/.test(src[i])) { + if (src[i] !== "'" && src[i] !== '"' && src[i] !== '\\') delim += src[i]; + i++; + } + pendingHeredocs.push({ delim, strip, seg }); + continue; + } + i++; + if ('>&|'.includes(src[i] ?? '') && !(c === '<' && src[i] === '|')) i++; + if (src[i - 1] === '&') { + let consumed = false; + while (i < n && /[\d-]/.test(src[i])) { i++; consumed = true; } + if (consumed) continue; + } + redirTarget = 'file'; + continue; + } + startWord().text += c; + i++; + } + if (pendingHeredocs.length) readHeredocBodies(); + endSegment(null); + + let pipeId = 0; + for (let k = 0; k < segments.length; k++) { + segments[k].pipeId = pipeId; + const piped = segments[k].sep === '|' || segments[k].sep === '|&'; + if (piped) { + segments[k].pipeline = true; + if (segments[k + 1]) segments[k + 1].pipeline = true; + } else { + pipeId++; + } + } + return { segments, subs, opaque }; +} + +// ── Classification ───────────────────────────────────────────────────────── + +/** Command name as the shell would resolve it: basename, no `@version`, no Windows extension, lower-cased. */ +function commandName(text) { + let b = text.split(/[\\/]/).pop() ?? ''; + const at = b.indexOf('@', 1); + if (at > 0) b = b.slice(0, at); + return b.replace(/\.(?:cmd|exe|bat|ps1)$/i, '').toLowerCase(); +} + +const isFlag = (w) => w.text.length > 1 && w.text.startsWith('-'); +const isAssignment = (w) => !w.quoted && /^[A-Za-z_][A-Za-z0-9_]*=/.test(w.text); +const isPrefixWord = (w) => !!w && !w.quoted && !w.dynamic && w.text === 'LUA_DEPLOY_CONFIRMED=1'; + +/** True when every word before `j` is an assignment, a wrapper/launcher, an option or a bare number. */ +function isCommandPosition(words, j) { + for (let k = 0; k < j; k++) { + const w = words[k]; + if (isAssignment(w) || isFlag(w) || /^\d+[smhd]?$/.test(w.text) || WRAPPERS.has(commandName(w.text))) continue; + return false; + } + return true; +} + +/** Does `path` (the script handed to node) point at a lua-cli entry point? */ +function isLuaEntryPoint(path) { + const base = commandName(path).replace(/\.(?:m|c)?js$/i, ''); + if (PACKAGES.has(base)) return true; + return /(?:^|[\\/])(?:lua-cli|heylua|lua-ai)(?:[\\/]|$)/i.test(path); +} + +/** + * If a lua-cli invocation starts at word `j`, return the index of its first + * argument (and whether the binary itself was a shell variable); else null. + */ +function invocationAt(words, j) { + const w = words[j]; + if (w.dynamic) { + return isCommandPosition(words, j) ? { start: j + 1, dynamicHead: true } : null; + } + const name = commandName(w.text); + if (BINARIES.has(name)) return { start: j + 1, dynamicHead: false }; + // `lua-cli` is the package name, not an installed binary: gated after a + // launcher (`npx lua-cli`), or as a path to the package. + if (name === 'lua-cli' && (j > 0 || /[\\/]/.test(w.text))) return { start: j + 1, dynamicHead: false }; + // The entry point run directly through its shebang: `/opt/lua-cli/dist/index.js deploy`. + if (/(?:^|[\\/])(?:lua-cli|heylua|lua-ai)[\\/].*\.[mc]?js$/i.test(w.text)) return { start: j + 1, dynamicHead: false }; + if (NODE_LIKE.has(name)) { + let k = j + 1; + while (k < words.length && isFlag(words[k])) { + if (NODE_VALUE_FLAGS.has(words[k].text)) k++; + k++; + } + if (k < words.length && !words[k].dynamic && isLuaEntryPoint(words[k].text)) { + return { start: k + 1, dynamicHead: false }; + } + } + return null; +} + +/** + * Match the arguments after a lua binary against the gated shapes. Options + * are skipped twice over β€” once as boolean flags, once as `--flag value` + * pairs β€” so neither reading hides a verb. + * + * @param {Word[]} args + * @param {boolean} allowDynamic a `$VAR` token may stand in for a verb + * @returns {{label: string, slash: string, dynamic: boolean}|null} + */ +function matchArgs(args, allowDynamic) { + const loose = []; // flags dropped, their values kept + const strict = []; // flags and the word after a value-less `--flag` dropped + let pendingValue = false; + for (const a of args) { + if (a.text === '--') { pendingValue = false; continue; } + if (isFlag(a)) { pendingValue = !a.text.includes('='); continue; } + loose.push(a); + if (pendingValue) pendingValue = false; + else strict.push(a); + } + let dynamicHit = null; + for (const positional of [loose, strict]) { + for (const entry of PRODUCTION_COMMANDS) { + let ok = true; + let usedDynamic = false; + for (let p = 0; p < entry.seq.length; p++) { + const tok = positional[p]; + if (!tok) { ok = false; break; } + if (tok.dynamic) { + if (!allowDynamic) { ok = false; break; } + usedDynamic = true; + continue; + } + if (!entry.seq[p].includes(tok.text.toLowerCase())) { ok = false; break; } + } + if (!ok) continue; + if (!usedDynamic) return { label: entry.label, slash: entry.slash, dynamic: false }; + dynamicHit ??= { label: UNRESOLVED_LABEL, slash: '/lua-deploy', dynamic: true }; + } + } + return dynamicHit; +} + +/** Unanchored textual search, for text the lexer cannot structure. */ +function rawSearch(text, hits) { + for (const { entry, re } of RAW_PATTERNS) { + if (re.test(text)) hits.push({ label: entry.label, slash: entry.slash, prefixed: false }); + } +} + +/** + * @param {Segment} seg + * @param {{nested: boolean, depth: number}} ctx + * @param {boolean} pipedIntoRunner another stage of this pipeline runs its input as code + * @param {Array<{label: string, slash: string, prefixed: boolean}>} hits + */ +function analyzeSegment(seg, ctx, pipedIntoRunner, hits) { + const words = seg.words; + const names = words.map((w) => (w.dynamic ? '' : commandName(w.text))); + const runsStrings = pipedIntoRunner || names.some((nm) => SCRIPT_RUNNERS.has(nm)); + const inlineCode = names.some((nm) => INLINE_CODE.has(nm)); + const nested = { nested: true, depth: ctx.depth + 1 }; + + words.forEach((w, k) => { + if (k === 0) return; + if (runsStrings && /[\s;&|`$()]/.test(w.text)) analyzeScript(w.text, nested, hits); + if (inlineCode) rawSearch(w.text, hits); + if (names[0] === 'alias' || names[0] === 'trap') { + const eq = w.text.indexOf('='); + if (eq > 0) analyzeScript(w.text.slice(eq + 1), nested, hits); + } + }); + for (const body of [...seg.heredocs, ...seg.herestrings]) { + if (runsStrings || inlineCode || names.some((nm) => nm === 'source' || nm === '.')) { + analyzeScript(body, nested, hits); + if (inlineCode) rawSearch(body, hits); + } + } + + for (let j = 0; j < words.length; j++) { + const inv = invocationAt(words, j); + if (!inv) continue; + const args = words.slice(inv.start); + // `… | xargs lua` or `lua` with nothing but a variable after it: the verb + // arrives at runtime and cannot be classified. + const fedByXargs = names.slice(0, j).includes('xargs'); + let match = matchArgs(args, !inv.dynamicHead); + if (!match && fedByXargs && !inv.dynamicHead) { + match = { label: UNRESOLVED_LABEL, slash: '/lua-deploy', dynamic: true }; + } + if (!match) continue; + const canonicalPrefix = + !inv.dynamicHead && + BINARIES.has(words[j].text) && + ((j === 1 && isPrefixWord(words[0])) || + (j === 2 && words[0].text === 'env' && !words[0].quoted && isPrefixWord(words[1]))); + const prefixed = + canonicalPrefix && !match.dynamic && !ctx.nested && !seg.pipeline && !seg.grouped; + hits.push({ label: match.label, slash: match.slash, prefixed }); + } +} + +/** + * @param {string} src + * @param {{nested: boolean, depth: number}} ctx + * @param {Array<{label: string, slash: string, prefixed: boolean}>} hits + */ +function analyzeScript(src, ctx, hits) { + if (ctx.depth > MAX_DEPTH) { rawSearch(src, hits); return; } + const { segments, subs, opaque } = lex(src); + if (opaque) rawSearch(src, hits); + + // A pipeline stage that runs its stdin as code (`… | sh`, `… | xargs sh -c`) + // turns every string in the pipeline into code. + const runnerPipes = new Set( + segments + .filter((s) => s.pipeline && s.words.some((w) => !w.dynamic && SCRIPT_RUNNERS.has(commandName(w.text)))) + .map((s) => s.pipeId), + ); + for (const seg of segments) analyzeSegment(seg, ctx, runnerPipes.has(seg.pipeId), hits); + for (const sub of subs) analyzeScript(sub, { nested: true, depth: ctx.depth + 1 }, hits); +} + +/** + * Classify a command. Returns null for commands that run no gated verb, or + * `{ label, slash, prefixed }` for a production-affecting lua-cli verb. When a + * command runs several gated verbs, the first one WITHOUT a valid prefix is + * returned (so one unconfirmed verb blocks the whole chain); `prefixed` is + * true only when every gated verb in it carries the canonical prefix. * * @param {unknown} command * @returns {{label: string, slash: string, prefixed: boolean}|null} */ export function classifyProductionCommand(command) { if (typeof command !== 'string') return null; - const trimmed = command.trimStart(); - const unsafe = trimmed.includes('|') || WRAPPER_HEAD.test(trimmed); - const hasPrefix = PREFIX.test(trimmed); - const body = hasPrefix ? trimmed.replace(PREFIX, '') : trimmed; - // Inside a wrapper/pipe the verb may sit anywhere β€” search, don't anchor. - const haystack = unsafe ? trimmed : body; - for (const entry of PRODUCTION_COMMANDS) { - const anchored = unsafe ? new RegExp(entry.re.source.replace(/^\^/, '(? !h.prefixed) ?? hits[0]; + return { label, slash, prefixed }; } /** - * True iff the command is a gated production verb carrying the - * LUA_DEPLOY_CONFIRMED=1 prefix, with no wrapper or pipe. + * True iff the command runs a gated production verb and every such verb + * carries the LUA_DEPLOY_CONFIRMED=1 prefix in its canonical shape. * * @param {unknown} command * @returns {boolean} diff --git a/plugins/lua-agent-builder/mcp/lua-platform/README.md b/plugins/lua-agent-builder/mcp/lua-platform/README.md index e4d124e..7543e8b 100644 --- a/plugins/lua-agent-builder/mcp/lua-platform/README.md +++ b/plugins/lua-agent-builder/mcp/lua-platform/README.md @@ -77,8 +77,13 @@ npm run build # esbuild β†’ dist/server.js npm test ``` -Output: `dist/server.js` (single bundled file, `@modelcontextprotocol/sdk` -external). The plugin's `.mcp.json` launches it via +Output: `dist/server.js` β€” a single self-contained file. Since 1.6.0 every npm +dependency, `@modelcontextprotocol/sdk` included, is bundled from the +lockfile, so the server runs with no `node_modules` anywhere (a marketplace +install, or the plugin baked into a Lua Job-tier image). +`tests/standalone-bundle.test.mjs` copies the bundle into an empty temp +directory and lists the tools over stdio to keep it that way; rebuild after +any change to `src/` or a dependency bump and commit `dist/`. The plugin's `.mcp.json` launches it via `node ${CLAUDE_PLUGIN_ROOT}/mcp/lua-platform/dist/server.js`; the built file is committed so marketplace installs (which copy the repo verbatim) work without a build step. diff --git a/plugins/lua-agent-builder/mcp/lua-platform/dist/server.js b/plugins/lua-agent-builder/mcp/lua-platform/dist/server.js index ca3ef57..1897652 100644 --- a/plugins/lua-agent-builder/mcp/lua-platform/dist/server.js +++ b/plugins/lua-agent-builder/mcp/lua-platform/dist/server.js @@ -1,3 +1,6 @@ -var ie=Object.defineProperty;var ae=(e,t)=>{for(var r in t)ie(e,r,{get:t[r],enumerable:!0})};import{Server as $e}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Oe}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as Ue,ListToolsRequestSchema as Ne}from"@modelcontextprotocol/sdk/types.js";var K={};ae(K,{getAgent:()=>W,getDeploymentStatus:()=>te,listAgents:()=>G,listPrimitiveVersions:()=>Q,tailLogs:()=>re});import{spawn as le}from"node:child_process";var ce=6e4;function pe(e,{spawnFn:t=le,timeoutMs:r=ce,label:s="lua"}={}){return new Promise((o,i)=>{let a=t("lua",e,{shell:process.platform==="win32",windowsHide:!0,env:{...process.env,LUA_NO_BANNER:"1",LUA_NO_HINTS:"1"}}),n="",l="";a.stdout.on("data",m=>{n+=m.toString("utf8")}),a.stderr.on("data",m=>{l+=m.toString("utf8")});let c=setTimeout(()=>{a.kill("SIGTERM"),i(new Error(`${s}: 'lua ${e.join(" ")}' timed out after ${r}ms`))},r);a.on("exit",m=>{clearTimeout(c),m!==0?i(new Error(`'lua ${e.join(" ")}' exited ${m}: ${l.trim()}`)):o(n)}),a.on("error",m=>{clearTimeout(c),i(m)})})}function ue(e){let t=e,r=Array.isArray(t)?t:t?.agents??t?.orgs??[];return r.length>0&&r[0]&&Array.isArray(r[0].agents)?r.flatMap(o=>(o.agents??[]).map(i=>({id:i.agentId??i.id??i._id,name:i.name??null,orgId:o.orgId??o.id??o._id??null,orgName:o.name??o.registeredName??null,visibility:i.visibility??null}))):r.map(o=>({id:o.agentId??o.id??o._id,name:o.name??null,orgId:o.orgId??null,orgName:o.orgName??null,visibility:o.visibility??null}))}async function T({spawnFn:e,label:t="list_agents"}={}){let r=await pe(["agents","--json","--ci"],{spawnFn:e,label:t}),s;try{s=JSON.parse(r)}catch(o){throw new Error(`${t}: could not parse 'lua agents --json' output: ${o.message}`)}return ue(s)}var G={spec:{name:"list_agents",description:"List all Lua agents the authenticated credential can reach. Returns a compact array of {id, name, orgId, orgName, visibility} flattened across all organisations. Same data as `lua agents --json` \u2014 it resolves every organisation, so on accounts with many orgs this takes 20 s or more; prefer get_agent when you already know the id.",inputSchema:{type:"object",properties:{},required:[]}},async handler(e,t={}){let r=await T({spawnFn:t.spawnFn,label:"list_agents"});return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}};var W={spec:{name:"get_agent",description:"Look up one Lua agent by ID and return {id, name, orgId, orgName, visibility}. For what is live use get_deployment_status / list_primitive_versions; for logs use tail_logs.",inputSchema:{type:"object",properties:{agentId:{type:"string",description:"Agent ID (the `id` field from list_agents; also `agent.agentId` in lua.skill.yaml)"}},required:["agentId"]}},async handler({agentId:e},t={}){if(!e)throw new Error("agentId is required");let s=(await T({spawnFn:t.spawnFn,label:"get_agent"})).find(o=>o.id===e)??null;if(!s)throw new Error(`get_agent: no agent with id "${e}" found in the authenticated credential's accessible orgs. Run list_agents to see available agents.`);return{content:[{type:"text",text:JSON.stringify(s,null,2)}]}}};import{readFile as j,readdir as de,stat as me}from"node:fs/promises";import{join as R,dirname as fe}from"node:path";import{homedir as ge}from"node:os";var he="https://api.heylua.ai",we="https://securetoken.googleapis.com/v1/token",ve=15e3,ye=6e4,_e=["TOKEN_EXPIRED","USER_DISABLED","USER_NOT_FOUND","INVALID_REFRESH_TOKEN","INVALID_GRANT_TYPE","MISSING_REFRESH_TOKEN"],X=new Map;function Ee(e){for(let t of e.split(/\r?\n/)){let r=t.match(/^\s*(?:export\s+)?LUA_API_KEY\s*=\s*(.*)$/);if(!r)continue;let s=r[1].trim(),o=s.match(/^(['"`])(.*?)\1(?:\s+#.*)?\s*$/);return o?s=o[2]:s=s.replace(/\s+#.*$/,"").trim(),s||null}return null}async function Se({sessionsDir:e,apiUrl:t}){let r;try{r=await de(e)}catch{return null}let s=[];for(let o of r){if(!o.endsWith(".json")||o.startsWith("."))continue;let i=R(e,o);try{let a=JSON.parse(await j(i,"utf8"));if(a?.kind!=="firebase-session"||a?.version!==1||typeof a.refreshToken!="string"||!a.refreshToken||typeof a.firebaseWebApiKey!="string"||!a.firebaseWebApiKey||a.apiUrl!==t)continue;let{mtimeMs:n}=await me(i);s.push({path:i,session:a,mtimeMs:n})}catch{}}return s.length===0?null:(s.sort((o,i)=>i.mtimeMs-o.mtimeMs),{path:s[0].path,session:s[0].session})}async function Ae({path:e,session:t,fetchFn:r=globalThis.fetch,now:s=Date.now}){let o=X.get(e);if(o&&o.expiresAt-s()>ye)return o.idToken;let i=new AbortController,a=setTimeout(()=>i.abort(),ve),n;try{n=await r(`${we}?key=${encodeURIComponent(t.firebaseWebApiKey)}`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:t.refreshToken}).toString(),signal:i.signal})}catch(p){throw new Error(`MCP_AUTH_UNAVAILABLE: could not refresh the lua-cli session (${p?.name==="AbortError"?"timed out":p.message}). Check your network, or set LUA_API_KEY to bypass the session.`)}finally{clearTimeout(a)}if(!n.ok){let p=n.statusText??String(n.status);try{let d=(await n.json())?.error?.message;typeof d=="string"&&d&&(p=d.split(":")[0].trim())}catch{}let g=n.status<500&&_e.find(u=>p.toUpperCase().includes(u));throw g?new Error(`MCP_AUTH_STALE: your lua-cli session was signed out (${g}). Signing out of the Lua dashboard, desktop or mobile app also ends CLI sessions. Run \`lua auth configure\` in a terminal to sign in again.`):new Error(`MCP_AUTH_UNAVAILABLE: lua-cli session refresh failed (${n.status} ${p}). Retry in a moment.`)}let l=await n.json(),c=l?.id_token,m=Number(l?.expires_in);if(typeof c!="string"||!c||!Number.isFinite(m)||m<=0)throw new Error("MCP_AUTH_UNAVAILABLE: the session refresh returned an invalid token. Run `lua auth configure` again.");return X.set(e,{idToken:c,expiresAt:s()+m*1e3}),c}async function z({env:e=process.env,credentialsPath:t=e.LUA_CREDENTIALS_PATH??R(ge(),".lua-cli","credentials"),sessionsDir:r=e.LUA_SESSIONS_DIR??R(fe(t),"sessions"),cwd:s=process.cwd(),apiUrl:o=e.LUA_API_URL||he,fetchFn:i=globalThis.fetch,now:a=Date.now}={}){if(e.LUA_API_KEY&&e.LUA_API_KEY.trim())return e.LUA_API_KEY.trim();try{let l=Ee(await j(R(s,".env"),"utf8"));if(l)return l}catch{}let n=await Se({sessionsDir:r,apiUrl:o});if(n)return Ae({...n,fetchFn:i,now:a});try{let l=(await j(t,"utf8")).trim();if(l){if(l.startsWith("{"))try{let c=JSON.parse(l);if(c?.apiKey)return c.apiKey}catch{}return l}}catch{}throw new Error("MCP_AUTH_STALE: No lua-cli credentials found in LUA_API_KEY, .env, ~/.lua-cli/sessions, or ~/.lua-cli/credentials. Run `lua auth configure` in a terminal (or /lua-auth in Claude Code).")}var be="https://api.heylua.ai",ke=1e4,Ge=Object.freeze({skills:"automations:read",webhooks:"automations:read",jobs:"automations:read",triggers:"automations:read",preprocessors:"automations:read",postprocessors:"automations:read",workflows:"workflows:read",persona:"agents:read",logs:"knowledge:read"}),Ie="skills/webhooks/jobs/triggers/preprocessors/postprocessors need automations:read, workflows need workflows:read, persona needs agents:read, logs need knowledge:read";async function v(e,{method:t="GET",body:r,query:s,fetchFn:o=globalThis.fetch,baseUrl:i=process.env.LUA_API_URL||be,timeoutMs:a=ke}={}){let n=await z(),l=new URL(i.replace(/\/$/,"")+e);if(s)for(let[p,g]of Object.entries(s))l.searchParams.set(p,String(g));let c=new AbortController,m=setTimeout(()=>c.abort(),a);try{let p=await o(l.toString(),{method:t,headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json","X-Lua-Client":"claude-plugin/1.5.0"},body:r?JSON.stringify(r):void 0,signal:c.signal});if(p.status===401)throw new Error("MCP_AUTH_STALE: lua-api returned 401. The credential is missing, expired, or the session was signed out (signing out of the Lua dashboard or apps also ends CLI sessions). Run `lua auth configure` in a terminal, or re-run /lua-doctor.");if(p.status===403)throw new Error(`MCP_FORBIDDEN: lua-api returned 403 for ${e}. The credential cannot access this agent or org, or it lacks the route scope (${Ie} \u2014 typed keys are scoped to the agents and role chosen at \`lua auth configure\`). Re-run /lua-doctor or check the LUA_API_KEY env var.`);if(!p.ok){let g=await p.text(),u=g;try{let d=JSON.parse(g);u=d?.error?.message??d?.message??g;let h=d?.error?.code;typeof h=="string"&&h&&!String(u).includes(h)&&(u=`${h}: ${u}`)}catch{}throw new Error(`lua-api ${p.status}: ${u}`)}return await p.json()}catch(p){throw p.name==="AbortError"?new Error(`MCP_TIMEOUT: ${e} did not respond in ${a}ms`):p}finally{clearTimeout(m)}}var V={skill:e=>e?.skills??[],webhook:e=>e?.data?.webhooks??[],job:e=>e?.data?.jobs??[],trigger:e=>e?.data?.triggers??[],preprocessor:e=>e?.data?.preprocessors??[],postprocessor:e=>e?.data?.postprocessors??[],workflow:e=>e?.data?.workflows??[]},D={skill:e=>e?.versions??[],webhook:e=>e?.data?.versions??[],job:e=>Array.isArray(e?.data)?e.data:[],trigger:e=>e?.data?.versions??[],preprocessor:e=>e?.data?.versions??[],postprocessor:e=>e?.data?.versions??[],workflow:e=>Array.isArray(e?.data)?e.data:[],persona:e=>e?.versions??[]},_={skill:"skills",webhook:"webhooks",job:"jobs",trigger:"triggers",preprocessor:"preprocessors",postprocessor:"postprocessors",workflow:"workflows"};function L(e,t){let r=V[e];if(!r)throw new Error(`extractList: unknown primitive type "${e}". Valid: ${Object.keys(V).join(", ")}`);return r(t)}function E(e,t){let r=D[e];if(!r)throw new Error(`extractVersions: unknown primitive type "${e}". Valid: ${Object.keys(D).join(", ")}`);return r(t)}function S(e){let t=e?.data?.activeVersionId;return typeof t=="string"&&t?t:null}function A(e,t,r){if(!t||typeof t!="object")return!1;switch(e){case"skill":case"persona":return t.isCurrent===!0;case"job":case"workflow":return t.active===!0;case"webhook":case"trigger":case"preprocessor":case"postprocessor":{if(t.isActive===!0)return!0;let s=S(r),o=t.versionId??t.id??null;return!!s&&o===s}default:return!1}}function b(e){if(!e||typeof e!="object")return null;let t=e.createdAt??e.createdDate??null;return t==null?null:typeof t=="number"?Number.isFinite(t)?new Date(t).toISOString():null:String(t)}function x(e){return!e||typeof e!="object"?null:e.versionId??e.id??null}var Xe=Object.keys(V),Z=Object.keys(D);var F=new Set(Z),Q={spec:{name:"list_primitive_versions",description:"List the server-side versions of one primitive (skill, webhook, job, trigger, preprocessor, postprocessor, workflow) or the agent persona. Returns { activeVersionId, versions: [{version, versionId, active, createdAt}] } \u2014 `active` is the version currently live. `versionId` is null for types whose versions route carries no per-entry id: skill, persona and webhook (the webhook route exposes the row id only under a misnamed `webhookId` key). For those, identify a version by `version`; for webhooks the live row id is the top-level `activeVersionId`. `activeVersionId` is populated only for webhook, trigger, preprocessor and postprocessor envelopes and is null for skill, job, workflow and persona.",inputSchema:{type:"object",properties:{agentId:{type:"string"},type:{type:"string",enum:[...F]},name:{type:"string",description:"Primitive name as written in lua.skill.yaml (omit for persona \u2014 an agent has only one)"}},required:["agentId","type"]}},async handler({agentId:e,type:t,name:r},s={}){if(!e||!t)throw new Error("agentId and type are required");if(!F.has(t))throw new Error(`Invalid type: ${t}. Valid: ${[...F].join(", ")}`);if(t!=="persona"&&!r)throw new Error("name is required for all types except persona");let o;if(t==="persona")o=`/developer/agents/${encodeURIComponent(e)}/persona/versions`;else{let c=await Te({agentId:e,type:t,name:r,fetchFn:s.fetchFn});o=`/developer/${_[t]}/${encodeURIComponent(e)}/${encodeURIComponent(c)}/versions`}let i=await v(o,{fetchFn:s.fetchFn}),n=E(t,i).map(c=>({version:c.version,versionId:x(c),active:A(t,c,i),createdAt:b(c)})),l={agentId:e,type:t,name:t==="persona"?null:r,activeVersionId:S(i),versions:n};return{content:[{type:"text",text:JSON.stringify(l,null,2)}]}}};async function Te({agentId:e,type:t,name:r,fetchFn:s}){let o=`/developer/${_[t]}/${encodeURIComponent(e)}`,i=await v(o,{fetchFn:s}),a=L(t,i),n=a.find(c=>c.name===r);if(!n){let c=a.map(m=>m.name).filter(Boolean).join(", ")||"(none)";throw new Error(`list_primitive_versions: no ${t} named "${r}" on agent ${e}. Available: ${c}`)}let l=n.id??n._id;if(!l)throw new Error(`list_primitive_versions: ${t} "${r}" exists but has no id field`);return l}var $=["skill","webhook","job","trigger","preprocessor","postprocessor","workflow"],ee=5,Re=45e3,te={spec:{name:"get_deployment_status",description:'What is live right now for an agent: for every skill, webhook, job, trigger, preprocessor, postprocessor and workflow the active (deployed) version, plus the active persona version. Composed from the per-type lua-api version routes (list calls in parallel, then per-item version lookups in chunks of 5). Bounded by a 45 s wall-clock budget: if exceeded, remaining items are listed with `error: "skipped: \u2026"` and the result carries `partial: true` + `partialReason`. Inside a project, `lua status --json` additionally compares local vs deployed.',inputSchema:{type:"object",properties:{agentId:{type:"string"}},required:["agentId"]}},async handler({agentId:e},t={}){if(!e)throw new Error("agentId is required");let r=encodeURIComponent(e),s=Number.isFinite(t.budgetMs)?t.budgetMs:Re,o=Date.now(),i=()=>Date.now()-o>s,a=u=>v(u,{fetchFn:t.fetchFn}),n={agentId:e,persona:null,primitives:{}};for(let u of $)n.primitives[u]=[];let[l,...c]=await Promise.allSettled([a(`/developer/agents/${r}/persona/versions`),...$.map(u=>a(`/developer/${_[u]}/${r}`))]);if(l.status==="fulfilled"){let u=l.value,d=E("persona",u),h=d.find(y=>A("persona",y,u))??null;n.persona={activeVersion:h?.version??null,activeVersionCreatedAt:b(h),versionCount:d.length}}else n.persona={error:l.reason?.message??String(l.reason)};let m=!1,p=0,g=0;for(let u=0;u<$.length;u++){let d=$[u],h=_[d],y=c[u];if(y.status!=="fulfilled"){n.primitives[d]={error:y.reason?.message??String(y.reason)};continue}let O=L(d,y.value).map(f=>({p:f,primId:f.id??f._id,name:f.name??f.id??f._id})).filter(f=>f.primId);g+=O.length;for(let f=0;fa(`/developer/${h}/${r}/${encodeURIComponent(w)}/versions`)))).forEach((w,U)=>{let{p:I,primId:q,name:B}=k[U];if(w.status!=="fulfilled"){n.primitives[d].push({name:B,id:q,error:w.reason?.message??String(w.reason)});return}let N=w.value,J=E(d,N),C=J.find(ne=>A(d,ne,N))??null,P={name:B,id:q,activeVersion:C?.version??null,activeVersionId:x(C)??S(N),activeVersionCreatedAt:b(C),versionCount:J.length};typeof I.active=="boolean"&&(P.enabled=I.active),d==="workflow"&&typeof I.dynamic=="boolean"&&(P.dynamic=I.dynamic),n.primitives[d].push(P)})}}return p>0&&(n.partial=!0,n.partialReason=`Wall-clock budget of ${s}ms exceeded after ${Date.now()-o}ms; ${p} of ${g} version lookups were not issued (entries carry error: "skipped: \u2026").`),{content:[{type:"text",text:JSON.stringify(n,null,2)}]}}};var Le=["skill","job","webhook","trigger","preprocessor","postprocessor","user_message","agent_response","agent_error","runtime","mcp","rag","device","device-trigger","model-resolver","workflow-step","workflow-script","workflow"],H=["error","warn","info","debug","start","complete"],M=new Set(["all",...Le]),xe=new Set(H),re={spec:{name:"tail_logs",description:"Fetch recent execution logs for an agent (same data as `lua logs --json`). Returns { logs: LogEntry[], pagination }. Each LogEntry has `subType` (error | warn | info | debug | start | complete), `message`, `timestamp`, and `metadata.logSource` / `metadata.primitiveName` \u2014 there is NO `level` field. Filter by source (`type`), primitive (`name`) and/or severity (`logType`, which filters on `subType`).",inputSchema:{type:"object",properties:{agentId:{type:"string"},type:{type:"string",enum:[...M],default:"all",description:"Log source filter (maps to lua-api `logSource`). `all` = no filter."},name:{type:"string",description:"Filter by primitive name (optional; maps to `primitiveName`)"},logType:{type:"string",enum:H,description:"Filter by LogEntry `subType` (optional; maps to lua-api `logType`). Omit for every severity. e.g. `error` to see only failures."},limit:{type:"number",default:50,minimum:1,maximum:100},page:{type:"number",minimum:1,description:"Page number for pagination (optional)"}},required:["agentId"]}},async handler({agentId:e,type:t="all",name:r,logType:s,limit:o=50,page:i},a={}){if(!e)throw new Error("agentId is required");if(!M.has(t))throw new Error(`Invalid type: ${t}. Valid: ${[...M].join(", ")}`);if(s!==void 0&&!xe.has(s))throw new Error(`Invalid logType: ${s}. Valid: ${H.join(", ")}`);if(o>100)throw new Error(`Invalid limit: ${o}. lua-api caps logs at 100 entries per call.`);let n={limit:o};t!=="all"&&(n.logSource=t),r&&(n.primitiveName=r),s&&(n.logType=s),i&&(n.page=i);let l=await v(`/developer/agents/${encodeURIComponent(e)}/logs`,{query:n,fetchFn:a.fetchFn});return{content:[{type:"text",text:JSON.stringify(l,null,2)}]}}};var oe=Object.values(K),Y=new $e({name:"lua-platform",version:"1.5.0"},{capabilities:{tools:{}}});Y.setRequestHandler(Ne,async()=>({tools:oe.map(e=>e.spec)}));Y.setRequestHandler(Ue,async e=>{let t=oe.find(r=>r.spec.name===e.params.name);if(!t)throw new Error(`Unknown tool: ${e.params.name}`);try{return await t.handler(e.params.arguments??{})}catch(r){return{content:[{type:"text",text:`Error: ${r.message}`}],isError:!0}}});function se(e){process.stderr.write(JSON.stringify(e)+` -`,()=>process.exit(1))}process.on("uncaughtException",e=>{se({event:"mcp_server_crash",kind:"uncaughtException",message:e?.message,stack:e?.stack,plugin_version:"1.5.0",lua_cli_version:process.env.LUA_CLI_VERSION??null,platform:process.platform,ts:new Date().toISOString()})});process.on("unhandledRejection",e=>{se({event:"mcp_server_crash",kind:"unhandledRejection",reason:String(e),stack:e?.stack,plugin_version:"1.5.0",lua_cli_version:process.env.LUA_CLI_VERSION??null,platform:process.platform,ts:new Date().toISOString()})});await Y.connect(new Oe); -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3NlcnZlci5tanMiLCAiLi4vc3JjL3Rvb2xzL2luZGV4Lm1qcyIsICIuLi9zcmMvcnVuLWx1YS5tanMiLCAiLi4vc3JjL3Rvb2xzL2xpc3QtYWdlbnRzLm1qcyIsICIuLi9zcmMvdG9vbHMvZ2V0LWFnZW50Lm1qcyIsICIuLi9zcmMvYXV0aC5tanMiLCAiLi4vc3JjL2FwaS1jbGllbnQubWpzIiwgIi4uL3NyYy9yZXNwb25zZS1zaGFwZXMubWpzIiwgIi4uL3NyYy90b29scy9saXN0LXByaW1pdGl2ZS12ZXJzaW9ucy5tanMiLCAiLi4vc3JjL3Rvb2xzL2dldC1kZXBsb3ltZW50LXN0YXR1cy5tanMiLCAiLi4vc3JjL3Rvb2xzL3RhaWwtbG9ncy5tanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8vIE1DUCBzdGRpbyBzZXJ2ZXIgYm9vdHN0cmFwLiBQZXIgdGVjaCBzcGVjIFx1MDBBNzguMS5cblxuaW1wb3J0IHsgU2VydmVyIH0gZnJvbSAnQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zZXJ2ZXIvaW5kZXguanMnO1xuaW1wb3J0IHsgU3RkaW9TZXJ2ZXJUcmFuc3BvcnQgfSBmcm9tICdAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NlcnZlci9zdGRpby5qcyc7XG5pbXBvcnQge1xuICBDYWxsVG9vbFJlcXVlc3RTY2hlbWEsXG4gIExpc3RUb29sc1JlcXVlc3RTY2hlbWEsXG59IGZyb20gJ0Btb2RlbGNvbnRleHRwcm90b2NvbC9zZGsvdHlwZXMuanMnO1xuaW1wb3J0ICogYXMgdG9vbHMgZnJvbSAnLi90b29scy9pbmRleC5tanMnO1xuXG5jb25zdCBUT09MX1JFR0lTVFJZID0gT2JqZWN0LnZhbHVlcyh0b29scyk7XG5cbmNvbnN0IHNlcnZlciA9IG5ldyBTZXJ2ZXIoXG4gIHsgbmFtZTogJ2x1YS1wbGF0Zm9ybScsIHZlcnNpb246ICcxLjUuMCcgfSxcbiAgeyBjYXBhYmlsaXRpZXM6IHsgdG9vbHM6IHt9IH0gfVxuKTtcblxuc2VydmVyLnNldFJlcXVlc3RIYW5kbGVyKExpc3RUb29sc1JlcXVlc3RTY2hlbWEsIGFzeW5jICgpID0+ICh7XG4gIHRvb2xzOiBUT09MX1JFR0lTVFJZLm1hcCgodCkgPT4gdC5zcGVjKSxcbn0pKTtcblxuc2VydmVyLnNldFJlcXVlc3RIYW5kbGVyKENhbGxUb29sUmVxdWVzdFNjaGVtYSwgYXN5bmMgKHJlcSkgPT4ge1xuICBjb25zdCB0b29sID0gVE9PTF9SRUdJU1RSWS5maW5kKCh0KSA9PiB0LnNwZWMubmFtZSA9PT0gcmVxLnBhcmFtcy5uYW1lKTtcbiAgaWYgKCF0b29sKSB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdG9vbDogJHtyZXEucGFyYW1zLm5hbWV9YCk7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHRvb2wuaGFuZGxlcihyZXEucGFyYW1zLmFyZ3VtZW50cyA/PyB7fSk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbeyB0eXBlOiAndGV4dCcsIHRleHQ6IGBFcnJvcjogJHtlcnIubWVzc2FnZX1gIH1dLFxuICAgICAgaXNFcnJvcjogdHJ1ZSxcbiAgICB9O1xuICB9XG59KTtcblxuLy8gXHUwMEE3MTkuNiBjcmFzaCByZXBvcnRpbmcgXHUyMDE0IG11c3QgbGFuZCBCRUZPUkUgcHJvY2VzcyBleGl0IHNvIHRoZSBldmVudCByZWFjaGVzXG4vLyB0ZWxlbWV0cnkuIFdpbmRvd3MgY2FuIGRyb3AgdGhlIGxhc3Qgc3RkZXJyIHdyaXRlIGlmIHByb2Nlc3MuZXhpdCBmaXJlc1xuLy8gc3luY2hyb25vdXNseSBhZnRlciBpdDsgc2FtZSBidWcgY2xhc3MgYXMgbGliL2hvb2stcnVudGltZS5tanMncyBleGl0KCkuXG4vLyBFeGl0IG9ubHkgaW5zaWRlIHRoZSB3cml0ZSBjYWxsYmFjayBzbyB0aGUgZmx1c2ggY29tcGxldGVzLlxuZnVuY3Rpb24gcmVwb3J0Q3Jhc2hBbmRFeGl0KHBheWxvYWQpIHtcbiAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkgKyAnXFxuJywgKCkgPT4gcHJvY2Vzcy5leGl0KDEpKTtcbn1cblxucHJvY2Vzcy5vbigndW5jYXVnaHRFeGNlcHRpb24nLCAoZXJyKSA9PiB7XG4gIHJlcG9ydENyYXNoQW5kRXhpdCh7XG4gICAgZXZlbnQ6ICdtY3Bfc2VydmVyX2NyYXNoJyxcbiAgICBraW5kOiAndW5jYXVnaHRFeGNlcHRpb24nLFxuICAgIG1lc3NhZ2U6IGVycj8ubWVzc2FnZSxcbiAgICBzdGFjazogZXJyPy5zdGFjayxcbiAgICBwbHVnaW5fdmVyc2lvbjogJzEuNS4wJyxcbiAgICBsdWFfY2xpX3ZlcnNpb246IHByb2Nlc3MuZW52LkxVQV9DTElfVkVSU0lPTiA/PyBudWxsLFxuICAgIHBsYXRmb3JtOiBwcm9jZXNzLnBsYXRmb3JtLFxuICAgIHRzOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gIH0pO1xufSk7XG5cbnByb2Nlc3Mub24oJ3VuaGFuZGxlZFJlamVjdGlvbicsIChyZWFzb24pID0+IHtcbiAgcmVwb3J0Q3Jhc2hBbmRFeGl0KHtcbiAgICBldmVudDogJ21jcF9zZXJ2ZXJfY3Jhc2gnLFxuICAgIGtpbmQ6ICd1bmhhbmRsZWRSZWplY3Rpb24nLFxuICAgIHJlYXNvbjogU3RyaW5nKHJlYXNvbiksXG4gICAgc3RhY2s6IC8qKiBAdHlwZSB7YW55fSAqLyAocmVhc29uKT8uc3RhY2ssXG4gICAgcGx1Z2luX3ZlcnNpb246ICcxLjUuMCcsXG4gICAgbHVhX2NsaV92ZXJzaW9uOiBwcm9jZXNzLmVudi5MVUFfQ0xJX1ZFUlNJT04gPz8gbnVsbCxcbiAgICBwbGF0Zm9ybTogcHJvY2Vzcy5wbGF0Zm9ybSxcbiAgICB0czogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICB9KTtcbn0pO1xuXG5hd2FpdCBzZXJ2ZXIuY29ubmVjdChuZXcgU3RkaW9TZXJ2ZXJUcmFuc3BvcnQoKSk7XG4iLCAiZXhwb3J0IHsgbGlzdEFnZW50cyB9IGZyb20gJy4vbGlzdC1hZ2VudHMubWpzJztcbmV4cG9ydCB7IGdldEFnZW50IH0gZnJvbSAnLi9nZXQtYWdlbnQubWpzJztcbmV4cG9ydCB7IGxpc3RQcmltaXRpdmVWZXJzaW9ucyB9IGZyb20gJy4vbGlzdC1wcmltaXRpdmUtdmVyc2lvbnMubWpzJztcbmV4cG9ydCB7IGdldERlcGxveW1lbnRTdGF0dXMgfSBmcm9tICcuL2dldC1kZXBsb3ltZW50LXN0YXR1cy5tanMnO1xuZXhwb3J0IHsgdGFpbExvZ3MgfSBmcm9tICcuL3RhaWwtbG9ncy5tanMnO1xuLy8gY2hlY2tfZHJpZnQgcmVtb3ZlZCBpbiB2MS4yNSBcdTIwMTQgdXNlIEJhc2gobHVhIHN5bmMgLS1jaGVjaykgZGlyZWN0bHkuIFRoZVxuLy8gTUNQIHNlcnZlciBpcyBsb2NhbCBhbmQgc28gaXMgdGhlIENMSTsgcmVpbXBsZW1lbnRpbmcgZHJpZnQgZGV0ZWN0aW9uXG4vLyBzZXJ2ZXItc2lkZSBvciBpbiB0aGUgTUNQIHdvdWxkIGR1cGxpY2F0ZSBsb2dpYyB0aGF0IGx1YS1jbGkgYWxyZWFkeSBvd25zLlxuIiwgIi8vIFNoYXJlZCBzdWJwcm9jZXNzIGhlbHBlciBmb3IgdG9vbHMgdGhhdCBzaGVsbCBvdXQgdG8gdGhlIGx1YS1jbGkgYmluYXJ5LlxuLy9cbi8vIFdoeSBzaGVsbCBvdXQgYXQgYWxsOiB0aGVyZSBpcyBubyBcImxpc3QgZXZlcnkgYWdlbnQgdGhpcyBjcmVkZW50aWFsIGNhblxuLy8gcmVhY2hcIiBSRVNUIHJvdXRlIFx1MjAxNCBgbHVhIGFnZW50cyAtLWpzb25gIGFscmVhZHkgZG9lcyB0aGUgY3JlZGVudGlhbC10by1cbi8vIGF1dGhvcml6YXRpb24tcHJvamVjdGlvbiByZXNvbHV0aW9uIChQUk8tMTcxMikgZm9yIGV2ZXJ5IGNyZWRlbnRpYWwgY2xhc3Ncbi8vIChBUEkga2V5LCB0eXBlZCBzY29wZWQga2V5LCByZW5ld2FibGUgc2Vzc2lvbikuIFJlaW1wbGVtZW50aW5nIHRoYXQgaW4gdGhlXG4vLyBNQ1Agd291bGQgZHVwbGljYXRlIGxvZ2ljIGx1YS1jbGkgb3ducy5cblxuaW1wb3J0IHsgc3Bhd24gfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnO1xuXG4vLyBgbHVhIGFnZW50c2Agd2Fsa3MgZXZlcnkgb3JnYW5pc2F0aW9uIHRoZSBjcmVkZW50aWFsIGNhbiBzZWUgYW5kLCBmb3IgYVxuLy8gc2Vzc2lvbiBsb2dpbiwgcmVmcmVzaGVzIHRoZSBzZXNzaW9uIGZpcnN0LiBNZWFzdXJlZCAyMDI2LTA5LTEyIG9uIGFcbi8vIDE0NC1vcmcgYWNjb3VudDogMThcdTIwMTMyNSBzLiBUaGUgYnVkZ2V0IG11c3QgY292ZXIgdGhhdC5cbmNvbnN0IERFRkFVTFRfVElNRU9VVF9NUyA9IDYwXzAwMDtcblxuLyoqXG4gKiBSdW4gYGx1YSA8YXJncz5gIGFuZCByZXNvbHZlIHdpdGggaXRzIHN0ZG91dC5cbiAqXG4gKiBPbiBXaW5kb3dzIHRoZSBucG0gYmluIGlzIGEgYGx1YS5jbWRgIHNoaW0sIHdoaWNoIE5vZGUgKFx1MjI2NTE4LjIwIC8gXHUyMjY1MjAuMTIpXG4gKiByZWZ1c2VzIHRvIHNwYXduIHdpdGhvdXQgYSBzaGVsbDsgdGhlIGFyZ3MgYXJlIGZpeGVkIGxpdGVyYWxzIChubyB1c2VyXG4gKiBpbnB1dCksIHNvIGBzaGVsbDogdHJ1ZWAgdGhlcmUgaXMgc2FmZS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBhcmdzXG4gKiBAcGFyYW0ge3tzcGF3bkZuPzogdHlwZW9mIHNwYXduLCB0aW1lb3V0TXM/OiBudW1iZXIsIGxhYmVsPzogc3RyaW5nfX0gW29wdHNdXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuTHVhKGFyZ3MsIHsgc3Bhd25GbiA9IHNwYXduLCB0aW1lb3V0TXMgPSBERUZBVUxUX1RJTUVPVVRfTVMsIGxhYmVsID0gJ2x1YScgfSA9IHt9KSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgY2hpbGQgPSBzcGF3bkZuKCdsdWEnLCBhcmdzLCB7XG4gICAgICBzaGVsbDogcHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJyxcbiAgICAgIHdpbmRvd3NIaWRlOiB0cnVlLFxuICAgICAgZW52OiB7IC4uLnByb2Nlc3MuZW52LCBMVUFfTk9fQkFOTkVSOiAnMScsIExVQV9OT19ISU5UUzogJzEnIH0sXG4gICAgfSk7XG4gICAgbGV0IHN0ZG91dCA9ICcnO1xuICAgIGxldCBzdGRlcnIgPSAnJztcbiAgICBjaGlsZC5zdGRvdXQub24oJ2RhdGEnLCAoZCkgPT4geyBzdGRvdXQgKz0gZC50b1N0cmluZygndXRmOCcpOyB9KTtcbiAgICBjaGlsZC5zdGRlcnIub24oJ2RhdGEnLCAoZCkgPT4geyBzdGRlcnIgKz0gZC50b1N0cmluZygndXRmOCcpOyB9KTtcblxuICAgIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBjaGlsZC5raWxsKCdTSUdURVJNJyk7XG4gICAgICByZWplY3QobmV3IEVycm9yKGAke2xhYmVsfTogJ2x1YSAke2FyZ3Muam9pbignICcpfScgdGltZWQgb3V0IGFmdGVyICR7dGltZW91dE1zfW1zYCkpO1xuICAgIH0sIHRpbWVvdXRNcyk7XG5cbiAgICBjaGlsZC5vbignZXhpdCcsIChjb2RlKSA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgaWYgKGNvZGUgIT09IDApIHJlamVjdChuZXcgRXJyb3IoYCdsdWEgJHthcmdzLmpvaW4oJyAnKX0nIGV4aXRlZCAke2NvZGV9OiAke3N0ZGVyci50cmltKCl9YCkpO1xuICAgICAgZWxzZSByZXNvbHZlKHN0ZG91dCk7XG4gICAgfSk7XG4gICAgY2hpbGQub24oJ2Vycm9yJywgKGVycikgPT4ge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIHJlamVjdChlcnIpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuLyoqXG4gKiBGbGF0dGVuIGBsdWEgYWdlbnRzIC0tanNvbmAgb3V0cHV0IChsdWEtY2xpIFx1MjI2NSAzLjI4OiBhbiBhcnJheSBvZlxuICogQ3JlZGVudGlhbE9yZ2FuaXphdGlvbiByb3dzIFx1MjAxNCBgeyBvcmdJZCwgbmFtZT8sIGFyY2hpdmVkLCBkaXNjb3ZlcmVkVmlhLFxuICogYWdlbnRzOiBbeyBhZ2VudElkLCBuYW1lPywgdmlzaWJpbGl0eSwgZGlzcGxheVJvbGVzIH1dIH1gLCBzZWVcbiAqIHBhY2thZ2VzL2x1YS1jbGkvc3JjL3NlcnZpY2VzL2NyZWRlbnRpYWwtb3BlcmF0aW9uYWwtY29udGV4dC50cykgaW50byBhXG4gKiBjb21wYWN0IGFnZW50IGxpc3QuIE9sZGVyIGZsYXQgc2hhcGVzIGFyZSB0b2xlcmF0ZWQgZm9yIGZvcndhcmQtY29tcGF0LlxuICpcbiAqIEBwYXJhbSB7dW5rbm93bn0gcGFyc2VkXG4gKiBAcmV0dXJucyB7QXJyYXk8e2lkOiBzdHJpbmcsIG5hbWU6IHN0cmluZ3xudWxsLCBvcmdJZDogc3RyaW5nfG51bGwsIG9yZ05hbWU6IHN0cmluZ3xudWxsLCB2aXNpYmlsaXR5OiBzdHJpbmd8bnVsbH0+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gZmxhdHRlbkFnZW50cyhwYXJzZWQpIHtcbiAgY29uc3Qgb2JqID0gLyoqIEB0eXBlIHthbnl9ICovIChwYXJzZWQpO1xuICBjb25zdCBlbnRyaWVzID0gQXJyYXkuaXNBcnJheShvYmopID8gb2JqIDogKG9iaj8uYWdlbnRzID8/IG9iaj8ub3JncyA/PyBbXSk7XG4gIGNvbnN0IGxvb2tzTGlrZU9yZ3MgPSBlbnRyaWVzLmxlbmd0aCA+IDAgJiYgZW50cmllc1swXSAmJiBBcnJheS5pc0FycmF5KGVudHJpZXNbMF0uYWdlbnRzKTtcblxuICBpZiAobG9va3NMaWtlT3Jncykge1xuICAgIHJldHVybiBlbnRyaWVzLmZsYXRNYXAoKG9yZykgPT4gKG9yZy5hZ2VudHMgPz8gW10pLm1hcCgoYSkgPT4gKHtcbiAgICAgIGlkOiBhLmFnZW50SWQgPz8gYS5pZCA/PyBhLl9pZCxcbiAgICAgIG5hbWU6IGEubmFtZSA/PyBudWxsLFxuICAgICAgb3JnSWQ6IG9yZy5vcmdJZCA/PyBvcmcuaWQgPz8gb3JnLl9pZCA/PyBudWxsLFxuICAgICAgb3JnTmFtZTogb3JnLm5hbWUgPz8gb3JnLnJlZ2lzdGVyZWROYW1lID8/IG51bGwsXG4gICAgICB2aXNpYmlsaXR5OiBhLnZpc2liaWxpdHkgPz8gbnVsbCxcbiAgICB9KSkpO1xuICB9XG4gIHJldHVybiBlbnRyaWVzLm1hcCgoYSkgPT4gKHtcbiAgICBpZDogYS5hZ2VudElkID8/IGEuaWQgPz8gYS5faWQsXG4gICAgbmFtZTogYS5uYW1lID8/IG51bGwsXG4gICAgb3JnSWQ6IGEub3JnSWQgPz8gbnVsbCxcbiAgICBvcmdOYW1lOiBhLm9yZ05hbWUgPz8gbnVsbCxcbiAgICB2aXNpYmlsaXR5OiBhLnZpc2liaWxpdHkgPz8gbnVsbCxcbiAgfSkpO1xufVxuXG4vKipcbiAqIFJ1biBgbHVhIGFnZW50cyAtLWpzb24gLS1jaWAgYW5kIHJldHVybiB0aGUgZmxhdHRlbmVkIGFnZW50IGxpc3QuXG4gKlxuICogQHBhcmFtIHt7c3Bhd25Gbj86IHR5cGVvZiBzcGF3biwgbGFiZWw/OiBzdHJpbmd9fSBbb3B0c11cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxpc3RBZ2VudHNWaWFDbGkoeyBzcGF3bkZuLCBsYWJlbCA9ICdsaXN0X2FnZW50cycgfSA9IHt9KSB7XG4gIGNvbnN0IHN0ZG91dCA9IGF3YWl0IHJ1bkx1YShbJ2FnZW50cycsICctLWpzb24nLCAnLS1jaSddLCB7IHNwYXduRm4sIGxhYmVsIH0pO1xuICBsZXQgcGFyc2VkO1xuICB0cnkge1xuICAgIHBhcnNlZCA9IEpTT04ucGFyc2Uoc3Rkb3V0KTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke2xhYmVsfTogY291bGQgbm90IHBhcnNlICdsdWEgYWdlbnRzIC0tanNvbicgb3V0cHV0OiAke2Vyci5tZXNzYWdlfWApO1xuICB9XG4gIHJldHVybiBmbGF0dGVuQWdlbnRzKHBhcnNlZCk7XG59XG4iLCAiaW1wb3J0IHsgbGlzdEFnZW50c1ZpYUNsaSB9IGZyb20gJy4uL3J1bi1sdWEubWpzJztcblxuLy8gU2hlbGxzIG91dCB0byBgbHVhIGFnZW50cyAtLWpzb24gLS1jaWAgKHNlZSBydW4tbHVhLm1qcyBmb3Igd2h5KS4gVGhlIENMSVxuLy8gZW1pdHMgb25lIHJvdyBwZXIgb3JnYW5pc2F0aW9uIHdpdGggYSBuZXN0ZWQgYGFnZW50c2AgYXJyYXk7IHdlIGZsYXR0ZW4uXG5cbmV4cG9ydCBjb25zdCBsaXN0QWdlbnRzID0ge1xuICBzcGVjOiB7XG4gICAgbmFtZTogJ2xpc3RfYWdlbnRzJyxcbiAgICBkZXNjcmlwdGlvbjogJ0xpc3QgYWxsIEx1YSBhZ2VudHMgdGhlIGF1dGhlbnRpY2F0ZWQgY3JlZGVudGlhbCBjYW4gcmVhY2guIFJldHVybnMgYSBjb21wYWN0IGFycmF5IG9mIHtpZCwgbmFtZSwgb3JnSWQsIG9yZ05hbWUsIHZpc2liaWxpdHl9IGZsYXR0ZW5lZCBhY3Jvc3MgYWxsIG9yZ2FuaXNhdGlvbnMuIFNhbWUgZGF0YSBhcyBgbHVhIGFnZW50cyAtLWpzb25gIFx1MjAxNCBpdCByZXNvbHZlcyBldmVyeSBvcmdhbmlzYXRpb24sIHNvIG9uIGFjY291bnRzIHdpdGggbWFueSBvcmdzIHRoaXMgdGFrZXMgMjAgcyBvciBtb3JlOyBwcmVmZXIgZ2V0X2FnZW50IHdoZW4geW91IGFscmVhZHkga25vdyB0aGUgaWQuJyxcbiAgICBpbnB1dFNjaGVtYToge1xuICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICBwcm9wZXJ0aWVzOiB7fSxcbiAgICAgIHJlcXVpcmVkOiBbXSxcbiAgICB9LFxuICB9LFxuICBhc3luYyBoYW5kbGVyKF9hcmdzLCBkZXBzID0ge30pIHtcbiAgICBjb25zdCBjb21wYWN0ID0gYXdhaXQgbGlzdEFnZW50c1ZpYUNsaSh7IHNwYXduRm46IGRlcHMuc3Bhd25GbiwgbGFiZWw6ICdsaXN0X2FnZW50cycgfSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IFt7IHR5cGU6ICd0ZXh0JywgdGV4dDogSlNPTi5zdHJpbmdpZnkoY29tcGFjdCwgbnVsbCwgMikgfV0sXG4gICAgfTtcbiAgfSxcbn07XG4iLCAiaW1wb3J0IHsgbGlzdEFnZW50c1ZpYUNsaSB9IGZyb20gJy4uL3J1bi1sdWEubWpzJztcblxuLy8gVGhlcmUgaXMgbm8gY29uc29saWRhdGVkIGBHRVQgL2RldmVsb3Blci9hZ2VudHMvOmFnZW50SWRgIHJvdXRlLCBhbmQgdGhlXG4vLyBwdWJsaWMgYC9wdWJsaWMvYWdlbnRzLzphZ2VudElkYCByb3V0ZSBpcyBvcmlnaW4tZ3VhcmRlZCAoYnJvd3NlciBvbmx5KS5cbi8vIFRoZSBhZ2VudCdzIGlkZW50aXR5IChpZCwgbmFtZSwgb3JnLCB2aXNpYmlsaXR5KSBJUyBpbiBgbHVhIGFnZW50cyAtLWpzb25gLFxuLy8gc28gd2Ugc2hlbGwgb3V0IGFuZCBmaWx0ZXIgXHUyMDE0IHNhbWUgcGF0aCBhcyBsaXN0X2FnZW50cy4gUGVyc29uYSwgbW9kZWwgYW5kXG4vLyBlbnYgbGl2ZSBiZWhpbmQgc2VwYXJhdGUgcGVyLXJlc291cmNlIHJvdXRlczsgdXNlIHRoZSBkZWRpY2F0ZWQgdG9vbHMgKG9yXG4vLyBgbHVhIHN0YXR1cyAtLWpzb25gIGluc2lkZSB0aGUgcHJvamVjdCkgZm9yIHRob3NlLlxuXG5leHBvcnQgY29uc3QgZ2V0QWdlbnQgPSB7XG4gIHNwZWM6IHtcbiAgICBuYW1lOiAnZ2V0X2FnZW50JyxcbiAgICBkZXNjcmlwdGlvbjogJ0xvb2sgdXAgb25lIEx1YSBhZ2VudCBieSBJRCBhbmQgcmV0dXJuIHtpZCwgbmFtZSwgb3JnSWQsIG9yZ05hbWUsIHZpc2liaWxpdHl9LiBGb3Igd2hhdCBpcyBsaXZlIHVzZSBnZXRfZGVwbG95bWVudF9zdGF0dXMgLyBsaXN0X3ByaW1pdGl2ZV92ZXJzaW9uczsgZm9yIGxvZ3MgdXNlIHRhaWxfbG9ncy4nLFxuICAgIGlucHV0U2NoZW1hOiB7XG4gICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgYWdlbnRJZDogeyB0eXBlOiAnc3RyaW5nJywgZGVzY3JpcHRpb246ICdBZ2VudCBJRCAodGhlIGBpZGAgZmllbGQgZnJvbSBsaXN0X2FnZW50czsgYWxzbyBgYWdlbnQuYWdlbnRJZGAgaW4gbHVhLnNraWxsLnlhbWwpJyB9LFxuICAgICAgfSxcbiAgICAgIHJlcXVpcmVkOiBbJ2FnZW50SWQnXSxcbiAgICB9LFxuICB9LFxuICBhc3luYyBoYW5kbGVyKHsgYWdlbnRJZCB9LCBkZXBzID0ge30pIHtcbiAgICBpZiAoIWFnZW50SWQpIHRocm93IG5ldyBFcnJvcignYWdlbnRJZCBpcyByZXF1aXJlZCcpO1xuICAgIGNvbnN0IGFnZW50cyA9IGF3YWl0IGxpc3RBZ2VudHNWaWFDbGkoeyBzcGF3bkZuOiBkZXBzLnNwYXduRm4sIGxhYmVsOiAnZ2V0X2FnZW50JyB9KTtcbiAgICBjb25zdCBtYXRjaCA9IGFnZW50cy5maW5kKChhKSA9PiBhLmlkID09PSBhZ2VudElkKSA/PyBudWxsO1xuXG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBnZXRfYWdlbnQ6IG5vIGFnZW50IHdpdGggaWQgXCIke2FnZW50SWR9XCIgZm91bmQgaW4gdGhlIGF1dGhlbnRpY2F0ZWQgY3JlZGVudGlhbCdzIGFjY2Vzc2libGUgb3Jncy4gUnVuIGxpc3RfYWdlbnRzIHRvIHNlZSBhdmFpbGFibGUgYWdlbnRzLmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbeyB0eXBlOiAndGV4dCcsIHRleHQ6IEpTT04uc3RyaW5naWZ5KG1hdGNoLCBudWxsLCAyKSB9XSxcbiAgICB9O1xuICB9LFxufTtcbiIsICIvLyBDcmVkZW50aWFsIHJlc29sdXRpb24gZm9yIHRoZSBNQ1Agc2VydmVyLiBSZXNvbHZlZCBvbiBFVkVSWSBjYWxsLCBub3QgYXRcbi8vIHNlcnZlciBzdGFydHVwIFx1MjAxNCBzdXBwb3J0cyB0aGUgZmxvdyB3aGVyZSBhIHVzZXIgcmUtcnVucyBgbHVhIGF1dGggY29uZmlndXJlYFxuLy8gbWlkLXNlc3Npb24uXG4vL1xuLy8gVGhlIGNoYWluIE1VU1QgbWF0Y2ggbHVhLWNsaSdzIGByZXNvbHZlUmVxdWVzdENyZWRlbnRpYWwoKWBcbi8vIChwYWNrYWdlcy9sdWEtY2xpL3NyYy9zZXJ2aWNlcy9yZXF1ZXN0LWNyZWRlbnRpYWwudHMsIGx1YS1jbGkgMy4zMy4wKTpcbi8vXG4vLyAgIDEuIExVQV9BUElfS0VZIGluIHRoZSBwcm9jZXNzIGVudmlyb25tZW50LiBsdWEtY2xpIGxvYWRzIGAuLy5lbnZgIGludG9cbi8vICAgICAgcHJvY2Vzcy5lbnYgZmlyc3QgKGBpbXBvcnQgJ2RvdGVudi9jb25maWcnYCksIHNvIGEgYC5lbnZgIHZhbHVlIGluIHRoZVxuLy8gICAgICB3b3JraW5nIGRpcmVjdG9yeSBpcyBwYXJ0IG9mIHRoaXMgdGllciBcdTIwMTQgaXQgYmVhdHMgYSBzdG9yZWQgc2Vzc2lvbi5cbi8vICAgMi4gVGhlIHJlbmV3YWJsZSBmaXJzdC1wYXJ0eSBzZXNzaW9uIGBsdWEgYXV0aCBjb25maWd1cmVgIChlbWFpbCArIE9UUClcbi8vICAgICAgd3JpdGVzIHRvIH4vLmx1YS1jbGkvc2Vzc2lvbnMvPGVudi1oYXNoPi5qc29uLiBUaGlzIGlzIHRoZSBERUZBVUxUXG4vLyAgICAgIGxvZ2luIHNpbmNlIGx1YS1jbGkgMy4yOSBhbmQgaXQgREVMRVRFUyB+Ly5sdWEtY2xpL2NyZWRlbnRpYWxzLCBzbyBhblxuLy8gICAgICBNQ1Agc2VydmVyIHRoYXQgb25seSByZWFkIHRoZSBjcmVkZW50aWFscyBmaWxlIGZhaWxlZCBmb3IgZXZlcnlcbi8vICAgICAgc2Vzc2lvbiB1c2VyLiBUaGUgZmlsZSBob2xkcyBhIEZpcmViYXNlIHJlZnJlc2ggdG9rZW47IHRoZSBiZWFyZXIgaXNcbi8vICAgICAgYSBzaG9ydC1saXZlZCBJRCB0b2tlbiBvYnRhaW5lZCBmcm9tIEdvb2dsZSdzIHNlY3VyZXRva2VuIGVuZHBvaW50LlxuLy8gICAzLiB+Ly5sdWEtY2xpL2NyZWRlbnRpYWxzIFx1MjAxNCBhIHBsYWluLXRleHQgQVBJIGtleSAodHlwZWQgYGFwaV88dXVpZD4uPDQzPmBcbi8vICAgICAgb3IgbGVnYWN5KSwgd3JpdHRlbiB3aGVuIHRoZSB1c2VyIHBpY2tzIHRoZSBBUEkta2V5IG9wdGlvbiBvZlxuLy8gICAgICBgbHVhIGF1dGggY29uZmlndXJlYC5cbi8vXG4vLyBUaGlzIGZpbGUgZGVsaWJlcmF0ZWx5IGR1cGxpY2F0ZXMgbGliL2NyZWRlbnRpYWxzLm1qcyBiZWNhdXNlIHRoZSBNQ1Bcbi8vIHNlcnZlciBpcyBhIHNlcGFyYXRlIG5wbSBwYWNrYWdlIGFuZCBjYW4ndCByZWFjaCBpbnRvIHRoZSBwbHVnaW4ncyBsaWIvLlxuXG5pbXBvcnQgeyByZWFkRmlsZSwgcmVhZGRpciwgc3RhdCB9IGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnO1xuaW1wb3J0IHsgam9pbiwgZGlybmFtZSB9IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBob21lZGlyIH0gZnJvbSAnbm9kZTpvcyc7XG5cbmNvbnN0IERFRkFVTFRfQVBJX1VSTCA9ICdodHRwczovL2FwaS5oZXlsdWEuYWknO1xuY29uc3QgRklSRUJBU0VfUkVGUkVTSF9VUkwgPSAnaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGVhcGlzLmNvbS92MS90b2tlbic7XG5jb25zdCBSRUZSRVNIX1RJTUVPVVRfTVMgPSAxNV8wMDA7XG5jb25zdCBSRUZSRVNIX1NLRVdfTVMgPSA2MF8wMDA7XG5cbi8vIEdvb2dsZSdzIHZlcmRpY3RzIHRoYXQgdGhlIHN0b3JlZCByZWZyZXNoIHRva2VuIGNhbiBuZXZlciB3b3JrIGFnYWluLlxuLy8gTWlycm9ycyBsdWEtY2xpJ3MgUkVKRUNURURfUkVGUkVTSF9SRUFTT05TIChzZXJ2aWNlcy9maXJlYmFzZS1zZXNzaW9uLnRzKS5cbmNvbnN0IFJFSkVDVEVEX1JFRlJFU0hfUkVBU09OUyA9IFtcbiAgJ1RPS0VOX0VYUElSRUQnLFxuICAnVVNFUl9ESVNBQkxFRCcsXG4gICdVU0VSX05PVF9GT1VORCcsXG4gICdJTlZBTElEX1JFRlJFU0hfVE9LRU4nLFxuICAnSU5WQUxJRF9HUkFOVF9UWVBFJyxcbiAgJ01JU1NJTkdfUkVGUkVTSF9UT0tFTicsXG5dO1xuXG4vLyBJbi1wcm9jZXNzIGNhY2hlIG9mIHJlZnJlc2hlZCBJRCB0b2tlbnMsIGtleWVkIGJ5IHNlc3Npb24gZmlsZSBwYXRoLlxuY29uc3QgdG9rZW5DYWNoZSA9IG5ldyBNYXAoKTtcblxuLyoqIEV4cG9ydGVkIGZvciB0ZXN0cy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGVhclRva2VuQ2FjaGUoKSB7XG4gIHRva2VuQ2FjaGUuY2xlYXIoKTtcbn1cblxuLyoqXG4gKiBQYXJzZSBhIGRvdGVudi1zdHlsZSBmaWxlIGZvciBMVUFfQVBJX0tFWSB0aGUgd2F5IGRvdGVudiBkb2VzOiBvcHRpb25hbFxuICogYGV4cG9ydCBgIHByZWZpeCwgc3Vycm91bmRpbmcgc2luZ2xlL2RvdWJsZSBxdW90ZXMgc3RyaXBwZWQsIGEgdHJhaWxpbmdcbiAqIGAgIyBjb21tZW50YCBkcm9wcGVkIGZyb20gdW5xdW90ZWQgdmFsdWVzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBjb250ZW50XG4gKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZURvdGVudkFwaUtleShjb250ZW50KSB7XG4gIGZvciAoY29uc3QgcmF3TGluZSBvZiBjb250ZW50LnNwbGl0KC9cXHI/XFxuLykpIHtcbiAgICBjb25zdCBtID0gcmF3TGluZS5tYXRjaCgvXlxccyooPzpleHBvcnRcXHMrKT9MVUFfQVBJX0tFWVxccyo9XFxzKiguKikkLyk7XG4gICAgaWYgKCFtKSBjb250aW51ZTtcbiAgICBsZXQgdmFsdWUgPSBtWzFdLnRyaW0oKTtcbiAgICBjb25zdCBxdW90ZWQgPSB2YWx1ZS5tYXRjaCgvXihbJ1wiYF0pKC4qPylcXDEoPzpcXHMrIy4qKT9cXHMqJC8pO1xuICAgIGlmIChxdW90ZWQpIHZhbHVlID0gcXVvdGVkWzJdO1xuICAgIGVsc2UgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKC9cXHMrIy4qJC8sICcnKS50cmltKCk7XG4gICAgcmV0dXJuIHZhbHVlIHx8IG51bGw7XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogTG9jYXRlIHRoZSBsdWEtY2xpIHNlc3Npb24gZmlsZSBmb3IgdGhlIEFQSSBiYXNlIFVSTCBpbiB1c2UuIGx1YS1jbGkgbmFtZXNcbiAqIHRoZSBmaWxlIGJ5IGEgaGFzaCBvZiAoYXBpVXJsLCBhdXRoVXJsLCBmaXJlYmFzZVdlYkFwaUtleSk7IHJhdGhlciB0aGFuXG4gKiByZWNvbXB1dGUgaXQgd2Ugc2NhbiB0aGUgZGlyZWN0b3J5IGZvciBhIGBmaXJlYmFzZS1zZXNzaW9uYCByZWNvcmQgd2hvc2VcbiAqIGBhcGlVcmxgIG1hdGNoZXMsIG5ld2VzdCBmaXJzdC5cbiAqXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx7cGF0aDogc3RyaW5nLCBzZXNzaW9uOiBvYmplY3R9fG51bGw+fVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmluZFNlc3Npb25GaWxlKHsgc2Vzc2lvbnNEaXIsIGFwaVVybCB9KSB7XG4gIGxldCBuYW1lcztcbiAgdHJ5IHtcbiAgICBuYW1lcyA9IGF3YWl0IHJlYWRkaXIoc2Vzc2lvbnNEaXIpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBjb25zdCBjYW5kaWRhdGVzID0gW107XG4gIGZvciAoY29uc3QgbmFtZSBvZiBuYW1lcykge1xuICAgIGlmICghbmFtZS5lbmRzV2l0aCgnLmpzb24nKSB8fCBuYW1lLnN0YXJ0c1dpdGgoJy4nKSkgY29udGludWU7XG4gICAgY29uc3QgcGF0aCA9IGpvaW4oc2Vzc2lvbnNEaXIsIG5hbWUpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBzZXNzaW9uID0gSlNPTi5wYXJzZShhd2FpdCByZWFkRmlsZShwYXRoLCAndXRmOCcpKTtcbiAgICAgIGlmIChzZXNzaW9uPy5raW5kICE9PSAnZmlyZWJhc2Utc2Vzc2lvbicgfHwgc2Vzc2lvbj8udmVyc2lvbiAhPT0gMSkgY29udGludWU7XG4gICAgICBpZiAodHlwZW9mIHNlc3Npb24ucmVmcmVzaFRva2VuICE9PSAnc3RyaW5nJyB8fCAhc2Vzc2lvbi5yZWZyZXNoVG9rZW4pIGNvbnRpbnVlO1xuICAgICAgaWYgKHR5cGVvZiBzZXNzaW9uLmZpcmViYXNlV2ViQXBpS2V5ICE9PSAnc3RyaW5nJyB8fCAhc2Vzc2lvbi5maXJlYmFzZVdlYkFwaUtleSkgY29udGludWU7XG4gICAgICBpZiAoc2Vzc2lvbi5hcGlVcmwgIT09IGFwaVVybCkgY29udGludWU7XG4gICAgICBjb25zdCB7IG10aW1lTXMgfSA9IGF3YWl0IHN0YXQocGF0aCk7XG4gICAgICBjYW5kaWRhdGVzLnB1c2goeyBwYXRoLCBzZXNzaW9uLCBtdGltZU1zIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gdW5yZWFkYWJsZSAvIG1hbGZvcm1lZCBcdTIwMTQgc2tpcCwgbHVhLWNsaSB3aWxsIGNvbXBsYWluIG9uIGl0cyBvd25cbiAgICB9XG4gIH1cbiAgaWYgKGNhbmRpZGF0ZXMubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcbiAgY2FuZGlkYXRlcy5zb3J0KChhLCBiKSA9PiBiLm10aW1lTXMgLSBhLm10aW1lTXMpO1xuICByZXR1cm4geyBwYXRoOiBjYW5kaWRhdGVzWzBdLnBhdGgsIHNlc3Npb246IGNhbmRpZGF0ZXNbMF0uc2Vzc2lvbiB9O1xufVxuXG4vKipcbiAqIEV4Y2hhbmdlIHRoZSBzdG9yZWQgcmVmcmVzaCB0b2tlbiBmb3IgYSBGaXJlYmFzZSBJRCB0b2tlbiAodGhlIGJlYXJlclxuICogbHVhLWFwaSBhY2NlcHRzKS4gQ2FjaGVkIGluLXByb2Nlc3MgdW50aWwgNjAgcyBiZWZvcmUgZXhwaXJ5LiBUaGUgc2Vzc2lvblxuICogZmlsZSBpcyBuZXZlciB3cml0dGVuOiBsdWEtY2xpIG93bnMgaXQuXG4gKlxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gYmVhcmVyIHRva2VuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWZyZXNoU2Vzc2lvbkJlYXJlcih7IHBhdGgsIHNlc3Npb24sIGZldGNoRm4gPSBnbG9iYWxUaGlzLmZldGNoLCBub3cgPSBEYXRlLm5vdyB9KSB7XG4gIGNvbnN0IGNhY2hlZCA9IHRva2VuQ2FjaGUuZ2V0KHBhdGgpO1xuICBpZiAoY2FjaGVkICYmIGNhY2hlZC5leHBpcmVzQXQgLSBub3coKSA+IFJFRlJFU0hfU0tFV19NUykgcmV0dXJuIGNhY2hlZC5pZFRva2VuO1xuXG4gIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiBjb250cm9sbGVyLmFib3J0KCksIFJFRlJFU0hfVElNRU9VVF9NUyk7XG4gIGxldCByZXM7XG4gIHRyeSB7XG4gICAgcmVzID0gYXdhaXQgZmV0Y2hGbihgJHtGSVJFQkFTRV9SRUZSRVNIX1VSTH0/a2V5PSR7ZW5jb2RlVVJJQ29tcG9uZW50KHNlc3Npb24uZmlyZWJhc2VXZWJBcGlLZXkpfWAsIHtcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcgfSxcbiAgICAgIGJvZHk6IG5ldyBVUkxTZWFyY2hQYXJhbXMoeyBncmFudF90eXBlOiAncmVmcmVzaF90b2tlbicsIHJlZnJlc2hfdG9rZW46IHNlc3Npb24ucmVmcmVzaFRva2VuIH0pLnRvU3RyaW5nKCksXG4gICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgIH0pO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgTUNQX0FVVEhfVU5BVkFJTEFCTEU6IGNvdWxkIG5vdCByZWZyZXNoIHRoZSBsdWEtY2xpIHNlc3Npb24gKCR7ZXJyPy5uYW1lID09PSAnQWJvcnRFcnJvcicgPyAndGltZWQgb3V0JyA6IGVyci5tZXNzYWdlfSkuIGAgK1xuICAgICAgJ0NoZWNrIHlvdXIgbmV0d29yaywgb3Igc2V0IExVQV9BUElfS0VZIHRvIGJ5cGFzcyB0aGUgc2Vzc2lvbi4nXG4gICAgKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICB9XG5cbiAgaWYgKCFyZXMub2spIHtcbiAgICBsZXQgcmVhc29uID0gcmVzLnN0YXR1c1RleHQgPz8gU3RyaW5nKHJlcy5zdGF0dXMpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVzLmpzb24oKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBib2R5Py5lcnJvcj8ubWVzc2FnZTtcbiAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycgJiYgbWVzc2FnZSkgcmVhc29uID0gbWVzc2FnZS5zcGxpdCgnOicpWzBdLnRyaW0oKTtcbiAgICB9IGNhdGNoIHsgLyoga2VlcCBzdGF0dXNUZXh0ICovIH1cbiAgICBjb25zdCByZWplY3RlZCA9IHJlcy5zdGF0dXMgPCA1MDAgJiYgUkVKRUNURURfUkVGUkVTSF9SRUFTT05TLmZpbmQoKHIpID0+IHJlYXNvbi50b1VwcGVyQ2FzZSgpLmluY2x1ZGVzKHIpKTtcbiAgICBpZiAocmVqZWN0ZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYE1DUF9BVVRIX1NUQUxFOiB5b3VyIGx1YS1jbGkgc2Vzc2lvbiB3YXMgc2lnbmVkIG91dCAoJHtyZWplY3RlZH0pLiBgICtcbiAgICAgICAgJ1NpZ25pbmcgb3V0IG9mIHRoZSBMdWEgZGFzaGJvYXJkLCBkZXNrdG9wIG9yIG1vYmlsZSBhcHAgYWxzbyBlbmRzIENMSSBzZXNzaW9ucy4gJyArXG4gICAgICAgICdSdW4gYGx1YSBhdXRoIGNvbmZpZ3VyZWAgaW4gYSB0ZXJtaW5hbCB0byBzaWduIGluIGFnYWluLidcbiAgICAgICk7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgTUNQX0FVVEhfVU5BVkFJTEFCTEU6IGx1YS1jbGkgc2Vzc2lvbiByZWZyZXNoIGZhaWxlZCAoJHtyZXMuc3RhdHVzfSAke3JlYXNvbn0pLiBSZXRyeSBpbiBhIG1vbWVudC5gKTtcbiAgfVxuXG4gIGNvbnN0IGJvZHkgPSBhd2FpdCByZXMuanNvbigpO1xuICBjb25zdCBpZFRva2VuID0gYm9keT8uaWRfdG9rZW47XG4gIGNvbnN0IGV4cGlyZXNJbiA9IE51bWJlcihib2R5Py5leHBpcmVzX2luKTtcbiAgaWYgKHR5cGVvZiBpZFRva2VuICE9PSAnc3RyaW5nJyB8fCAhaWRUb2tlbiB8fCAhTnVtYmVyLmlzRmluaXRlKGV4cGlyZXNJbikgfHwgZXhwaXJlc0luIDw9IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01DUF9BVVRIX1VOQVZBSUxBQkxFOiB0aGUgc2Vzc2lvbiByZWZyZXNoIHJldHVybmVkIGFuIGludmFsaWQgdG9rZW4uIFJ1biBgbHVhIGF1dGggY29uZmlndXJlYCBhZ2Fpbi4nKTtcbiAgfVxuICB0b2tlbkNhY2hlLnNldChwYXRoLCB7IGlkVG9rZW4sIGV4cGlyZXNBdDogbm93KCkgKyBleHBpcmVzSW4gKiAxMDAwIH0pO1xuICByZXR1cm4gaWRUb2tlbjtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBiZWFyZXIgdG9rZW4gZXZlcnkgbHVhLWFwaSByZXF1ZXN0IHNob3VsZCBjYXJyeS5cbiAqXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fVxuICogQHRocm93cyB7RXJyb3J9IE1DUF9BVVRIX1NUQUxFIHdoZW4gbm8gY3JlZGVudGlhbCByZXNvbHZlcyBmcm9tIGFueSB0aWVyXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlQXBpS2V5KHtcbiAgZW52ID0gcHJvY2Vzcy5lbnYsXG4gIGNyZWRlbnRpYWxzUGF0aCA9IGVudi5MVUFfQ1JFREVOVElBTFNfUEFUSCA/PyBqb2luKGhvbWVkaXIoKSwgJy5sdWEtY2xpJywgJ2NyZWRlbnRpYWxzJyksXG4gIHNlc3Npb25zRGlyID0gZW52LkxVQV9TRVNTSU9OU19ESVIgPz8gam9pbihkaXJuYW1lKGNyZWRlbnRpYWxzUGF0aCksICdzZXNzaW9ucycpLFxuICBjd2QgPSBwcm9jZXNzLmN3ZCgpLFxuICBhcGlVcmwgPSBlbnYuTFVBX0FQSV9VUkwgfHwgREVGQVVMVF9BUElfVVJMLFxuICBmZXRjaEZuID0gZ2xvYmFsVGhpcy5mZXRjaCxcbiAgbm93ID0gRGF0ZS5ub3csXG59ID0ge30pIHtcbiAgLy8gVGllciAxYTogcHJvY2VzcyBlbnZpcm9ubWVudFxuICBpZiAoZW52LkxVQV9BUElfS0VZICYmIGVudi5MVUFfQVBJX0tFWS50cmltKCkpIHJldHVybiBlbnYuTFVBX0FQSV9LRVkudHJpbSgpO1xuXG4gIC8vIFRpZXIgMWI6IC5lbnYgaW4gdGhlIHdvcmtpbmcgZGlyZWN0b3J5IChsdWEtY2xpIGxvYWRzIGl0IGludG8gcHJvY2Vzcy5lbnZcbiAgLy8gYmVmb3JlIHJlYWRpbmcgTFVBX0FQSV9LRVksIHNvIGl0IHJhbmtzIGFib3ZlIHRoZSBzdG9yZWQgc2Vzc2lvbilcbiAgdHJ5IHtcbiAgICBjb25zdCBmcm9tRG90ZW52ID0gcGFyc2VEb3RlbnZBcGlLZXkoYXdhaXQgcmVhZEZpbGUoam9pbihjd2QsICcuZW52JyksICd1dGY4JykpO1xuICAgIGlmIChmcm9tRG90ZW52KSByZXR1cm4gZnJvbURvdGVudjtcbiAgfSBjYXRjaCB7IC8qIG5vIC5lbnYgXHUyMDE0IGZhbGwgdGhyb3VnaCAqLyB9XG5cbiAgLy8gVGllciAyOiByZW5ld2FibGUgZmlyc3QtcGFydHkgc2Vzc2lvblxuICBjb25zdCBmb3VuZCA9IGF3YWl0IGZpbmRTZXNzaW9uRmlsZSh7IHNlc3Npb25zRGlyLCBhcGlVcmwgfSk7XG4gIGlmIChmb3VuZCkgcmV0dXJuIHJlZnJlc2hTZXNzaW9uQmVhcmVyKHsgLi4uZm91bmQsIGZldGNoRm4sIG5vdyB9KTtcblxuICAvLyBUaWVyIDM6IH4vLmx1YS1jbGkvY3JlZGVudGlhbHMgKHBsYWluIHRleHQgQVBJIGtleSlcbiAgdHJ5IHtcbiAgICBjb25zdCByYXcgPSAoYXdhaXQgcmVhZEZpbGUoY3JlZGVudGlhbHNQYXRoLCAndXRmOCcpKS50cmltKCk7XG4gICAgaWYgKHJhdykge1xuICAgICAgaWYgKHJhdy5zdGFydHNXaXRoKCd7JykpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKHJhdyk7XG4gICAgICAgICAgaWYgKHBhcnNlZD8uYXBpS2V5KSByZXR1cm4gcGFyc2VkLmFwaUtleTtcbiAgICAgICAgfSBjYXRjaCB7IC8qIG5vdCBKU09OIGRlc3BpdGUgbGVhZGluZyBicmFjZSAqLyB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmF3O1xuICAgIH1cbiAgfSBjYXRjaCB7IC8qIG1pc3NpbmcgLyB1bnJlYWRhYmxlIFx1MjAxNCBmYWxsIHRocm91Z2ggKi8gfVxuXG4gIHRocm93IG5ldyBFcnJvcihcbiAgICAnTUNQX0FVVEhfU1RBTEU6IE5vIGx1YS1jbGkgY3JlZGVudGlhbHMgZm91bmQgaW4gTFVBX0FQSV9LRVksIC5lbnYsIH4vLmx1YS1jbGkvc2Vzc2lvbnMsIG9yIH4vLmx1YS1jbGkvY3JlZGVudGlhbHMuICcgK1xuICAgICdSdW4gYGx1YSBhdXRoIGNvbmZpZ3VyZWAgaW4gYSB0ZXJtaW5hbCAob3IgL2x1YS1hdXRoIGluIENsYXVkZSBDb2RlKS4nXG4gICk7XG59XG4iLCAiLy8gVGhpbiBIVFRQIHdyYXBwZXIgYXJvdW5kIGx1YS1hcGkuIFBlciB0ZWNoIHNwZWMgXHUwMEE3OC5cbi8vXG4vLyBXZSBkbyBOT1QgaW1wb3J0IGx1YS1jbGkncyBIdHRwQ2xpZW50IGNsYXNzZXMgYXQgcnVudGltZSAod291bGQgZm9yY2Vcbi8vIHRoZSBlbnRpcmUgbHVhLWNsaSBwYWNrYWdlIHRvIGJlIGJ1bmRsZWQpLiBJbnN0ZWFkLCB0aGlzIG1pbmltYWwgY2xpZW50XG4vLyBoaXRzIHRoZSBzYW1lIFJFU1QgZW5kcG9pbnRzIGx1YS1jbGkgZG9lcy4gRXZlcnkgcm91dGUsIHF1ZXJ5IHBhcmFtZXRlclxuLy8gYW5kIGVudmVsb3BlIHVzZWQgYnkgdGhlIHRvb2xzIGlzIHZlcmlmaWVkIGFnYWluc3QgcGFja2FnZXMvbHVhLWFwaVxuLy8gKGNvbnRyb2xsZXJzL2RldmVsb3Blci8qKiwgZHRvLyoqKSBcdTIwMTQgc2VlIHJlc3BvbnNlLXNoYXBlcy5tanMuXG5cbmltcG9ydCB7IHJlc29sdmVBcGlLZXkgfSBmcm9tICcuL2F1dGgubWpzJztcblxuY29uc3QgREVGQVVMVF9CQVNFX1VSTCA9ICdodHRwczovL2FwaS5oZXlsdWEuYWknO1xuY29uc3QgREVGQVVMVF9USU1FT1VUX01TID0gMTBfMDAwO1xuXG4vLyBTY29wZSBlYWNoIHJvdXRlIGZhbWlseSB0aGUgdG9vbHMgY2FsbCBhY3R1YWxseSByZXF1aXJlcyBcdTIwMTQgcmVhZCBmcm9tIHRoZVxuLy8gYEBSZXF1aXJlU2NvcGUoLi4uKWAgZGVjb3JhdG9yIG9uIGV2ZXJ5IEdFVCB0aGUgdG9vbHMgaGl0LCB1bmRlclxuLy8gbHVhLWNvcmUtc2VydmljZXMgcGFja2FnZXMvbHVhLWFwaS9zcmMvY29udHJvbGxlcnMvZGV2ZWxvcGVyLzpcbi8vICAgc2tpbGxzL2Jhc2UuY29udHJvbGxlci50cywgd2ViaG9va3MvYmFzZS5jb250cm9sbGVyLnRzLFxuLy8gICBqb2JzL2Jhc2UuY29udHJvbGxlci50cywgdHJpZ2dlcnMvYmFzZS5jb250cm9sbGVyLnRzLFxuLy8gICBwcmVwcm9jZXNzb3JzL2Jhc2UuY29udHJvbGxlci50cywgcG9zdHByb2Nlc3NvcnMvYmFzZS5jb250cm9sbGVyLnRzXG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdTIxOTIgJ2F1dG9tYXRpb25zOnJlYWQnIChsaXN0ICsgOmlkL3ZlcnNpb25zKVxuLy8gICB3b3JrZmxvd3MvYmFzZS5jb250cm9sbGVyLnRzICAgXHUyMTkyICd3b3JrZmxvd3M6cmVhZCcgICAoR0VUIDphZ2VudElkLCBHRVQgOmFnZW50SWQvOndvcmtmbG93SWQvdmVyc2lvbnMpXG4vLyAgIHBlcnNvbmEvYmFzZS5jb250cm9sbGVyLnRzICAgICBcdTIxOTIgJ2FnZW50czpyZWFkJyAgICAgIChHRVQgOmFnZW50SWQvcGVyc29uYS92ZXJzaW9ucylcbi8vICAgYmFzZS5jb250cm9sbGVyLnRzICAgICAgICAgICAgIFx1MjE5MiAna25vd2xlZGdlOnJlYWQnICAgKEdFVCBhZ2VudHMvOmFnZW50SWQvbG9ncylcbi8vIFdvcmtmbG93cyBhcmUgTk9UIHVuZGVyIGF1dG9tYXRpb25zOnJlYWQgXHUyMDE0IHRoZXkgaGF2ZSB0aGVpciBvd24gc2NvcGUgcGFpclxuLy8gKHdvcmtmbG93czpyZWFkIC8gd29ya2Zsb3dzOndyaXRlKS5cbmV4cG9ydCBjb25zdCBST1VURV9TQ09QRVMgPSBPYmplY3QuZnJlZXplKHtcbiAgc2tpbGxzOiAnYXV0b21hdGlvbnM6cmVhZCcsXG4gIHdlYmhvb2tzOiAnYXV0b21hdGlvbnM6cmVhZCcsXG4gIGpvYnM6ICdhdXRvbWF0aW9uczpyZWFkJyxcbiAgdHJpZ2dlcnM6ICdhdXRvbWF0aW9uczpyZWFkJyxcbiAgcHJlcHJvY2Vzc29yczogJ2F1dG9tYXRpb25zOnJlYWQnLFxuICBwb3N0cHJvY2Vzc29yczogJ2F1dG9tYXRpb25zOnJlYWQnLFxuICB3b3JrZmxvd3M6ICd3b3JrZmxvd3M6cmVhZCcsXG4gIHBlcnNvbmE6ICdhZ2VudHM6cmVhZCcsXG4gIGxvZ3M6ICdrbm93bGVkZ2U6cmVhZCcsXG59KTtcblxuY29uc3QgUk9VVEVfU0NPUEVfU1VNTUFSWSA9XG4gICdza2lsbHMvd2ViaG9va3Mvam9icy90cmlnZ2Vycy9wcmVwcm9jZXNzb3JzL3Bvc3Rwcm9jZXNzb3JzIG5lZWQgYXV0b21hdGlvbnM6cmVhZCwgd29ya2Zsb3dzIG5lZWQgJyArXG4gICd3b3JrZmxvd3M6cmVhZCwgcGVyc29uYSBuZWVkcyBhZ2VudHM6cmVhZCwgbG9ncyBuZWVkIGtub3dsZWRnZTpyZWFkJztcblxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCAtIEFQSSBwYXRoICh3aXRoIGxlYWRpbmcgc2xhc2gpXG4gKiBAcGFyYW0ge3ttZXRob2Q/OiBzdHJpbmcsIGJvZHk/OiBvYmplY3QsIHF1ZXJ5PzogUmVjb3JkPHN0cmluZyxzdHJpbmd8bnVtYmVyPiwgZmV0Y2hGbj86IHR5cGVvZiBmZXRjaCwgYmFzZVVybD86IHN0cmluZywgdGltZW91dE1zPzogbnVtYmVyfX0gW29wdHNdXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhcGlSZXF1ZXN0KHBhdGgsIHtcbiAgbWV0aG9kID0gJ0dFVCcsXG4gIGJvZHksXG4gIHF1ZXJ5LFxuICBmZXRjaEZuID0gZ2xvYmFsVGhpcy5mZXRjaCxcbiAgYmFzZVVybCA9IHByb2Nlc3MuZW52LkxVQV9BUElfVVJMIHx8IERFRkFVTFRfQkFTRV9VUkwsXG4gIHRpbWVvdXRNcyA9IERFRkFVTFRfVElNRU9VVF9NUyxcbn0gPSB7fSkge1xuICBjb25zdCBhcGlLZXkgPSBhd2FpdCByZXNvbHZlQXBpS2V5KCk7XG4gIC8vIEpvaW4gYnkgc3RyaW5nIGNvbmNhdGVuYXRpb24sIE5PVCBgbmV3IFVSTChwYXRoLCBiYXNlVXJsKWA6IHRoZSBXSEFUV0dcbiAgLy8gcmVzb2x2ZXIgdHJlYXRzIGEgbGVhZGluZy1zbGFzaCBwYXRoIGFzIGhvc3QtYWJzb2x1dGUgYW5kIHdvdWxkIGRyb3AgYW55XG4gIC8vIHBhdGggcHJlZml4IG9uIExVQV9BUElfVVJMIChodHRwczovL2hvc3QvYXBpICsgL2RldmVsb3Blci94IFx1MjE5MlxuICAvLyBodHRwczovL2hvc3QvZGV2ZWxvcGVyL3gpLiBgcGF0aGAgYWx3YXlzIHN0YXJ0cyB3aXRoICcvJywgc28gc3RyaXAgb25lXG4gIC8vIHRyYWlsaW5nIHNsYXNoIGZyb20gdGhlIGJhc2UgYW5kIGNvbmNhdGVuYXRlLlxuICBjb25zdCB1cmwgPSBuZXcgVVJMKGJhc2VVcmwucmVwbGFjZSgvXFwvJC8sICcnKSArIHBhdGgpO1xuICBpZiAocXVlcnkpIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKHF1ZXJ5KSkgdXJsLnNlYXJjaFBhcmFtcy5zZXQoaywgU3RyaW5nKHYpKTtcblxuICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4gY29udHJvbGxlci5hYm9ydCgpLCB0aW1lb3V0TXMpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgZmV0Y2hGbih1cmwudG9TdHJpbmcoKSwge1xuICAgICAgbWV0aG9kLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnQXV0aG9yaXphdGlvbic6IGBCZWFyZXIgJHthcGlLZXl9YCxcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgJ1gtTHVhLUNsaWVudCc6ICdjbGF1ZGUtcGx1Z2luLzEuNS4wJyxcbiAgICAgIH0sXG4gICAgICBib2R5OiBib2R5ID8gSlNPTi5zdHJpbmdpZnkoYm9keSkgOiB1bmRlZmluZWQsXG4gICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgIH0pO1xuXG4gICAgaWYgKHJlcy5zdGF0dXMgPT09IDQwMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnTUNQX0FVVEhfU1RBTEU6IGx1YS1hcGkgcmV0dXJuZWQgNDAxLiBUaGUgY3JlZGVudGlhbCBpcyBtaXNzaW5nLCBleHBpcmVkLCBvciB0aGUgc2Vzc2lvbiB3YXMgc2lnbmVkIG91dCAnICtcbiAgICAgICAgJyhzaWduaW5nIG91dCBvZiB0aGUgTHVhIGRhc2hib2FyZCBvciBhcHBzIGFsc28gZW5kcyBDTEkgc2Vzc2lvbnMpLiBSdW4gYGx1YSBhdXRoIGNvbmZpZ3VyZWAgaW4gYSB0ZXJtaW5hbCwgJyArXG4gICAgICAgICdvciByZS1ydW4gL2x1YS1kb2N0b3IuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHJlcy5zdGF0dXMgPT09IDQwMykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgTUNQX0ZPUkJJRERFTjogbHVhLWFwaSByZXR1cm5lZCA0MDMgZm9yICR7cGF0aH0uIFRoZSBjcmVkZW50aWFsIGNhbm5vdCBhY2Nlc3MgdGhpcyBhZ2VudCBvciBvcmcsIG9yIGl0IGxhY2tzIGAgK1xuICAgICAgICBgdGhlIHJvdXRlIHNjb3BlICgke1JPVVRFX1NDT1BFX1NVTU1BUll9IFx1MjAxNCB0eXBlZCBrZXlzIGFyZSBzY29wZWQgdG8gdGhlIGFnZW50cyBhbmQgcm9sZSBjaG9zZW4gYXQgYCArXG4gICAgICAgICdgbHVhIGF1dGggY29uZmlndXJlYCkuIFJlLXJ1biAvbHVhLWRvY3RvciBvciBjaGVjayB0aGUgTFVBX0FQSV9LRVkgZW52IHZhci4nXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIXJlcy5vaykge1xuICAgICAgLy8gVHJ5IHRvIHBhcnNlIGx1YS1hcGkncyBzdHJ1Y3R1cmVkIGVycm9yIGVudmVsb3BlOlxuICAgICAgLy8gICB7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogeyBtZXNzYWdlLCBzdGF0dXNDb2RlLCBjb2RlPywgLi4uIH0gfVxuICAgICAgLy8gRmFsbHMgYmFjayB0byByYXcgdGV4dCBvbiBwYXJzZSBmYWlsdXJlIChlLmcuIHByb3h5IDUwMiB3aXRoIEhUTUwgYm9keSkuXG4gICAgICBjb25zdCByYXcgPSBhd2FpdCByZXMudGV4dCgpO1xuICAgICAgbGV0IGZyaWVuZGx5TXNnID0gcmF3O1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShyYXcpO1xuICAgICAgICBmcmllbmRseU1zZyA9IHBhcnNlZD8uZXJyb3I/Lm1lc3NhZ2UgPz8gcGFyc2VkPy5tZXNzYWdlID8/IHJhdztcbiAgICAgICAgY29uc3QgY29kZSA9IHBhcnNlZD8uZXJyb3I/LmNvZGU7XG4gICAgICAgIGlmICh0eXBlb2YgY29kZSA9PT0gJ3N0cmluZycgJiYgY29kZSAmJiAhU3RyaW5nKGZyaWVuZGx5TXNnKS5pbmNsdWRlcyhjb2RlKSkgZnJpZW5kbHlNc2cgPSBgJHtjb2RlfTogJHtmcmllbmRseU1zZ31gO1xuICAgICAgfSBjYXRjaCB7IC8qIG5vdCBKU09OOyByYXcgaXMgZmluZSAqLyB9XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGx1YS1hcGkgJHtyZXMuc3RhdHVzfTogJHtmcmllbmRseU1zZ31gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXdhaXQgcmVzLmpzb24oKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaWYgKGVyci5uYW1lID09PSAnQWJvcnRFcnJvcicpIHRocm93IG5ldyBFcnJvcihgTUNQX1RJTUVPVVQ6ICR7cGF0aH0gZGlkIG5vdCByZXNwb25kIGluICR7dGltZW91dE1zfW1zYCk7XG4gICAgdGhyb3cgZXJyO1xuICB9IGZpbmFsbHkge1xuICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gIH1cbn1cbiIsICIvLyBQZXItdHlwZSByZXNwb25zZS1zaGFwZSBleHRyYWN0b3JzLlxuLy9cbi8vIGx1YS1hcGkncyBkZXZlbG9wZXIgZW5kcG9pbnRzIGhhdmUgSU5DT05TSVNURU5UIHJlc3BvbnNlIHNoYXBlcyBhY3Jvc3Ncbi8vIHByaW1pdGl2ZSB0eXBlcy4gVmVyaWZpZWQgYWdhaW5zdCBwYWNrYWdlcy9sdWEtYXBpL3NyYy9kdG8vKi5kdG8udHMgYW5kXG4vLyBwYWNrYWdlcy9sdWEtYXBpL3NyYy9jb250cm9sbGVycy9kZXZlbG9wZXIvKiovYmFzZS5jb250cm9sbGVyLnRzLCBwbHVzXG4vLyBwYWNrYWdlcy9sdWEtY2xpL3NyYy9pbnRlcmZhY2VzL3dvcmtmbG93cy50cyAobHVhLWNsaSAzLjMzLjApOlxuLy9cbi8vICAgU2tpbGxzICAgICAgICAgR0VUIC9kZXZlbG9wZXIvc2tpbGxzLzphZ2VudElkICAgICAgICAgICAgICAgICAgICAgIFx1MjE5MiB7IHNraWxsczogU2tpbGxEdG9bXSB9XG4vLyAgICAgICAgICAgICAgICAgIEdFVCAvZGV2ZWxvcGVyL3NraWxscy86YWdlbnRJZC86c2tpbGxJZC92ZXJzaW9ucyAgICBcdTIxOTIgeyB2ZXJzaW9uczogW3sgdmVyc2lvbiwgY3JlYXRlZERhdGUsIGlzQ3VycmVudCwgLi4uIH1dIH1cbi8vICAgV2ViaG9va3MgICAgICAgR0VUIC9kZXZlbG9wZXIvd2ViaG9va3MvOmFnZW50SWQgICAgICAgICAgICAgICAgICAgIFx1MjE5MiB7IHN1Y2Nlc3MsIGRhdGE6IHsgd2ViaG9va3MgfSB9XG4vLyAgICAgICAgICAgICAgICAgIEdFVCAuLi4vOndlYmhvb2tJZC92ZXJzaW9ucyAgICAgICAgICAgICAgICAgICAgICAgICBcdTIxOTIgeyBzdWNjZXNzLCBkYXRhOiB7IHZlcnNpb25zOiBbeyB2ZXJzaW9uLCB3ZWJob29rSWQsIGNyZWF0ZWRBdCwgaXNBY3RpdmUgfV0sIGFjdGl2ZVZlcnNpb25JZD8gfSB9XG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2aWNlcy9kZXZlbG9wZXIud2ViaG9vay5zZXJ2aWNlLnRzIHNldHMgYHdlYmhvb2tJZDogdi5pZGAgXHUyMDE0IHRoZVxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyc2lvbiBST1cgaWQgdW5kZXIgYSBtaXNuYW1lZCBrZXk7IHRoZXJlIGlzIG5vIHZlcnNpb25JZC9pZCwgc29cbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcnNpb25JZCgpIGlzIG51bGwgYW5kIHRoZSBlbnZlbG9wZSdzIGFjdGl2ZVZlcnNpb25JZCBpcyB0aGUgb25seSBpZClcbi8vICAgSm9icyAgICAgICAgICAgR0VUIC9kZXZlbG9wZXIvam9icy86YWdlbnRJZCAgICAgICAgICAgICAgICAgICAgICAgIFx1MjE5MiB7IHN1Y2Nlc3MsIGRhdGE6IHsgam9icyB9IH1cbi8vICAgICAgICAgICAgICAgICAgR0VUIC4uLi86am9iSWQvdmVyc2lvbnMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFx1MjE5MiB7IHN1Y2Nlc3MsIGRhdGE6IEpvYlZlcnNpb25EdG9bXSB9ICAgXHUyMTkwIGFycmF5IHVuZGVyIGRhdGE7IGBhY3RpdmVgXG4vLyAgIFRyaWdnZXJzICAgICAgIEdFVCAvZGV2ZWxvcGVyL3RyaWdnZXJzLzphZ2VudElkICAgICAgICAgICAgICAgICAgICBcdTIxOTIgeyBzdWNjZXNzLCBkYXRhOiB7IHRyaWdnZXJzIH0gfVxuLy8gICAgICAgICAgICAgICAgICBHRVQgLi4uLzp0cmlnZ2VySWQvdmVyc2lvbnMgICAgICAgICAgICAgICAgICAgICAgICAgXHUyMTkyIHsgc3VjY2VzcywgZGF0YTogeyB2ZXJzaW9uczogW3sgdmVyc2lvbiwgdmVyc2lvbklkLCBjcmVhdGVkQXQsIGlzQWN0aXZlIH1dLCBhY3RpdmVWZXJzaW9uSWQ/IH0gfVxuLy8gICBQcmVwcm9jZXNzb3JzICBHRVQgL2RldmVsb3Blci9wcmVwcm9jZXNzb3JzLzphZ2VudElkICAgICAgICAgICAgICAgXHUyMTkyIHsgc3VjY2VzcywgZGF0YTogeyBwcmVwcm9jZXNzb3JzIH0gfVxuLy8gICAgICAgICAgICAgICAgICBHRVQgLi4uLzpwcmVwcm9jZXNzb3JJZC92ZXJzaW9ucyAgICAgICAgICAgICAgICAgICAgXHUyMTkyIHsgc3VjY2VzcywgZGF0YTogeyB2ZXJzaW9uczogW3sgdmVyc2lvbklkLCB2ZXJzaW9uLCBpc0FjdGl2ZSwgY3JlYXRlZEF0IH1dLCBhY3RpdmVWZXJzaW9uSWQ/IH0gfVxuLy8gICBQb3N0cHJvY2Vzc29ycyBHRVQgL2RldmVsb3Blci9wb3N0cHJvY2Vzc29ycy86YWdlbnRJZCAgICAgICAgICAgICAgXHUyMTkyIHsgc3VjY2VzcywgZGF0YTogeyBwb3N0cHJvY2Vzc29ycyB9IH1cbi8vICAgICAgICAgICAgICAgICAgR0VUIC4uLi86cG9zdHByb2Nlc3NvcklkL3ZlcnNpb25zICAgICAgICAgICAgICAgICAgIFx1MjE5MiBzYW1lIGZhbWlseSBhcyBwcmVwcm9jZXNzb3JzXG4vLyAgIFdvcmtmbG93cyAgICAgIEdFVCAvZGV2ZWxvcGVyL3dvcmtmbG93cy86YWdlbnRJZCAgICAgICAgICAgICAgICAgICBcdTIxOTIgeyBzdWNjZXNzLCBkYXRhOiB7IHdvcmtmbG93cyB9IH0gICAoY29kZS9zY3JpcHQgcHJvamVjdGVkIG91dClcbi8vICAgICAgICAgICAgICAgICAgR0VUIC4uLi86d29ya2Zsb3dJZC92ZXJzaW9ucyAgICAgICAgICAgICAgICAgICAgICAgIFx1MjE5MiB7IHN1Y2Nlc3MsIGRhdGE6IFdvcmtmbG93VmVyc2lvbltdIH0gICBcdTIxOTAgYXJyYXkgdW5kZXIgZGF0YTsgYGFjdGl2ZWBcbi8vICAgUGVyc29uYSAgICAgICAgR0VUIC9kZXZlbG9wZXIvYWdlbnRzLzphZ2VudElkL3BlcnNvbmEvdmVyc2lvbnMgICAgIFx1MjE5MiB7IHN0YXR1cywgbWVzc2FnZSwgdmVyc2lvbnM6IFt7IHZlcnNpb246IG51bWJlciwgY3JlYXRlZERhdGU6IG51bWJlciwgaXNDdXJyZW50LCBwZXJzb25hIH1dIH1cbi8vXG4vLyBObyB2ZXJzaW9uIERUTyBjYXJyaWVzIGBkZXBsb3llZEF0YCBvciBgc291cmNlSGFzaGAuIFRoZSBcImxpdmVcIiBmbGFnIGlzXG4vLyBgaXNDdXJyZW50YCAoc2tpbGwsIHBlcnNvbmEpLCBgYWN0aXZlYCAoam9iLCB3b3JrZmxvdykgb3IgYGlzQWN0aXZlYCAvXG4vLyBgYWN0aXZlVmVyc2lvbklkYCAod2ViaG9vaywgdHJpZ2dlciwgcHJlL3Bvc3Rwcm9jZXNzb3IpLiBDcmVhdGlvbiB0aW1lIGlzXG4vLyBgY3JlYXRlZEF0YCAoSVNPIHN0cmluZykgZXZlcnl3aGVyZSBleGNlcHQgc2tpbGwvcGVyc29uYSAoYGNyZWF0ZWREYXRlYDtcbi8vIHBlcnNvbmEncyBpcyBhbiBlcG9jaC1tcyBudW1iZXIpLlxuXG5jb25zdCBMSVNUX0VYVFJBQ1RPUlMgPSB7XG4gIHNraWxsOiAgICAgICAgIChyKSA9PiByPy5za2lsbHMgPz8gW10sXG4gIHdlYmhvb2s6ICAgICAgIChyKSA9PiByPy5kYXRhPy53ZWJob29rcyA/PyBbXSxcbiAgam9iOiAgICAgICAgICAgKHIpID0+IHI/LmRhdGE/LmpvYnMgPz8gW10sXG4gIHRyaWdnZXI6ICAgICAgIChyKSA9PiByPy5kYXRhPy50cmlnZ2VycyA/PyBbXSxcbiAgcHJlcHJvY2Vzc29yOiAgKHIpID0+IHI/LmRhdGE/LnByZXByb2Nlc3NvcnMgPz8gW10sXG4gIHBvc3Rwcm9jZXNzb3I6IChyKSA9PiByPy5kYXRhPy5wb3N0cHJvY2Vzc29ycyA/PyBbXSxcbiAgd29ya2Zsb3c6ICAgICAgKHIpID0+IHI/LmRhdGE/LndvcmtmbG93cyA/PyBbXSxcbn07XG5cbmNvbnN0IFZFUlNJT05TX0VYVFJBQ1RPUlMgPSB7XG4gIHNraWxsOiAgICAgICAgIChyKSA9PiByPy52ZXJzaW9ucyA/PyBbXSxcbiAgd2ViaG9vazogICAgICAgKHIpID0+IHI/LmRhdGE/LnZlcnNpb25zID8/IFtdLFxuICBqb2I6ICAgICAgICAgICAocikgPT4gKEFycmF5LmlzQXJyYXkocj8uZGF0YSkgPyByLmRhdGEgOiBbXSksXG4gIHRyaWdnZXI6ICAgICAgIChyKSA9PiByPy5kYXRhPy52ZXJzaW9ucyA/PyBbXSxcbiAgcHJlcHJvY2Vzc29yOiAgKHIpID0+IHI/LmRhdGE/LnZlcnNpb25zID8/IFtdLFxuICBwb3N0cHJvY2Vzc29yOiAocikgPT4gcj8uZGF0YT8udmVyc2lvbnMgPz8gW10sXG4gIHdvcmtmbG93OiAgICAgIChyKSA9PiAoQXJyYXkuaXNBcnJheShyPy5kYXRhKSA/IHIuZGF0YSA6IFtdKSxcbiAgcGVyc29uYTogICAgICAgKHIpID0+IHI/LnZlcnNpb25zID8/IFtdLFxufTtcblxuLyoqIFVSTCBwYXRoIHNlZ21lbnQgdW5kZXIgL2RldmVsb3Blci8gZm9yIGVhY2ggbGlzdGFibGUgdHlwZS4gKi9cbmV4cG9ydCBjb25zdCBMSVNUX1BBVEhTID0ge1xuICBza2lsbDogJ3NraWxscycsXG4gIHdlYmhvb2s6ICd3ZWJob29rcycsXG4gIGpvYjogJ2pvYnMnLFxuICB0cmlnZ2VyOiAndHJpZ2dlcnMnLFxuICBwcmVwcm9jZXNzb3I6ICdwcmVwcm9jZXNzb3JzJyxcbiAgcG9zdHByb2Nlc3NvcjogJ3Bvc3Rwcm9jZXNzb3JzJyxcbiAgd29ya2Zsb3c6ICd3b3JrZmxvd3MnLFxufTtcblxuLyoqXG4gKiBFeHRyYWN0IGEgbGlzdCBvZiBwcmltaXRpdmVzIGZyb20gYSBsaXN0LWVuZHBvaW50IHJlc3BvbnNlLlxuICogQHRocm93cyBpZiB0aGUgdHlwZSBpcyB1bmtub3duLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdExpc3QodHlwZSwgcmVzcG9uc2UpIHtcbiAgY29uc3QgZm4gPSBMSVNUX0VYVFJBQ1RPUlNbdHlwZV07XG4gIGlmICghZm4pIHRocm93IG5ldyBFcnJvcihgZXh0cmFjdExpc3Q6IHVua25vd24gcHJpbWl0aXZlIHR5cGUgXCIke3R5cGV9XCIuIFZhbGlkOiAke09iamVjdC5rZXlzKExJU1RfRVhUUkFDVE9SUykuam9pbignLCAnKX1gKTtcbiAgcmV0dXJuIGZuKHJlc3BvbnNlKTtcbn1cblxuLyoqXG4gKiBFeHRyYWN0IGEgbGlzdCBvZiB2ZXJzaW9ucyBmcm9tIGEgdmVyc2lvbnMtZW5kcG9pbnQgcmVzcG9uc2UuXG4gKiBAdGhyb3dzIGlmIHRoZSB0eXBlIGlzIHVua25vd24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0VmVyc2lvbnModHlwZSwgcmVzcG9uc2UpIHtcbiAgY29uc3QgZm4gPSBWRVJTSU9OU19FWFRSQUNUT1JTW3R5cGVdO1xuICBpZiAoIWZuKSB0aHJvdyBuZXcgRXJyb3IoYGV4dHJhY3RWZXJzaW9uczogdW5rbm93biBwcmltaXRpdmUgdHlwZSBcIiR7dHlwZX1cIi4gVmFsaWQ6ICR7T2JqZWN0LmtleXMoVkVSU0lPTlNfRVhUUkFDVE9SUykuam9pbignLCAnKX1gKTtcbiAgcmV0dXJuIGZuKHJlc3BvbnNlKTtcbn1cblxuLyoqXG4gKiBUaGUgYGFjdGl2ZVZlcnNpb25JZGAgYSB2ZXJzaW9ucyBlbnZlbG9wZSBtYXkgY2FycnkgYmVzaWRlIGl0cyBhcnJheVxuICogKHdlYmhvb2ssIHRyaWdnZXIsIHByZS9wb3N0cHJvY2Vzc29yKS4gTnVsbCBmb3IgdGhlIG90aGVyIGZhbWlsaWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdEFjdGl2ZVZlcnNpb25JZChyZXNwb25zZSkge1xuICBjb25zdCBpZCA9IHJlc3BvbnNlPy5kYXRhPy5hY3RpdmVWZXJzaW9uSWQ7XG4gIHJldHVybiB0eXBlb2YgaWQgPT09ICdzdHJpbmcnICYmIGlkID8gaWQgOiBudWxsO1xufVxuXG4vKipcbiAqIElzIHRoaXMgdmVyc2lvbiB0aGUgb25lIHRoYXQgaXMgbGl2ZT8gRWFjaCBmYW1pbHkgc3BlbGxzIGl0IGRpZmZlcmVudGx5LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlXG4gKiBAcGFyYW0ge29iamVjdH0gdmVyc2lvbiAtIG9uZSBlbGVtZW50IG9mIGV4dHJhY3RWZXJzaW9ucygpXG4gKiBAcGFyYW0ge29iamVjdH0gW3Jlc3BvbnNlXSAtIHRoZSB2ZXJzaW9ucyBlbnZlbG9wZSAoZm9yIGFjdGl2ZVZlcnNpb25JZClcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQWN0aXZlVmVyc2lvbih0eXBlLCB2ZXJzaW9uLCByZXNwb25zZSkge1xuICBpZiAoIXZlcnNpb24gfHwgdHlwZW9mIHZlcnNpb24gIT09ICdvYmplY3QnKSByZXR1cm4gZmFsc2U7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgJ3NraWxsJzpcbiAgICBjYXNlICdwZXJzb25hJzpcbiAgICAgIHJldHVybiB2ZXJzaW9uLmlzQ3VycmVudCA9PT0gdHJ1ZTtcbiAgICBjYXNlICdqb2InOlxuICAgIGNhc2UgJ3dvcmtmbG93JzpcbiAgICAgIHJldHVybiB2ZXJzaW9uLmFjdGl2ZSA9PT0gdHJ1ZTtcbiAgICBjYXNlICd3ZWJob29rJzpcbiAgICBjYXNlICd0cmlnZ2VyJzpcbiAgICBjYXNlICdwcmVwcm9jZXNzb3InOlxuICAgIGNhc2UgJ3Bvc3Rwcm9jZXNzb3InOiB7XG4gICAgICBpZiAodmVyc2lvbi5pc0FjdGl2ZSA9PT0gdHJ1ZSkgcmV0dXJuIHRydWU7XG4gICAgICBjb25zdCBhY3RpdmVJZCA9IGV4dHJhY3RBY3RpdmVWZXJzaW9uSWQocmVzcG9uc2UpO1xuICAgICAgY29uc3Qgb3duSWQgPSB2ZXJzaW9uLnZlcnNpb25JZCA/PyB2ZXJzaW9uLmlkID8/IG51bGw7XG4gICAgICByZXR1cm4gISFhY3RpdmVJZCAmJiBvd25JZCA9PT0gYWN0aXZlSWQ7XG4gICAgfVxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLyoqXG4gKiBJU08tODYwMSBjcmVhdGlvbiB0aW1lIG9mIGEgdmVyc2lvbiwgb3IgbnVsbC4gTm9ybWFsaXNlcyBza2lsbC9wZXJzb25hJ3NcbiAqIGBjcmVhdGVkRGF0ZWAgKHBlcnNvbmE6IGVwb2NoIG1zKSBvbnRvIHRoZSBgY3JlYXRlZEF0YCBuYW1lLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmVyc2lvbkNyZWF0ZWRBdCh2ZXJzaW9uKSB7XG4gIGlmICghdmVyc2lvbiB8fCB0eXBlb2YgdmVyc2lvbiAhPT0gJ29iamVjdCcpIHJldHVybiBudWxsO1xuICBjb25zdCByYXcgPSB2ZXJzaW9uLmNyZWF0ZWRBdCA/PyB2ZXJzaW9uLmNyZWF0ZWREYXRlID8/IG51bGw7XG4gIGlmIChyYXcgPT0gbnVsbCkgcmV0dXJuIG51bGw7XG4gIGlmICh0eXBlb2YgcmF3ID09PSAnbnVtYmVyJykgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShyYXcpID8gbmV3IERhdGUocmF3KS50b0lTT1N0cmluZygpIDogbnVsbDtcbiAgcmV0dXJuIFN0cmluZyhyYXcpO1xufVxuXG4vKiogSWRlbnRpZmllciBvZiBhIHZlcnNpb24gcm93ICh0aGUgc2xvdCBsdWEtYXBpIGtleXMgYGFjdGl2ZVZlcnNpb25JZGAgb24pLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZlcnNpb25JZCh2ZXJzaW9uKSB7XG4gIGlmICghdmVyc2lvbiB8fCB0eXBlb2YgdmVyc2lvbiAhPT0gJ29iamVjdCcpIHJldHVybiBudWxsO1xuICByZXR1cm4gdmVyc2lvbi52ZXJzaW9uSWQgPz8gdmVyc2lvbi5pZCA/PyBudWxsO1xufVxuXG5leHBvcnQgY29uc3QgU1VQUE9SVEVEX0xJU1RfVFlQRVMgPSBPYmplY3Qua2V5cyhMSVNUX0VYVFJBQ1RPUlMpO1xuZXhwb3J0IGNvbnN0IFNVUFBPUlRFRF9WRVJTSU9OX1RZUEVTID0gT2JqZWN0LmtleXMoVkVSU0lPTlNfRVhUUkFDVE9SUyk7XG4iLCAiaW1wb3J0IHsgYXBpUmVxdWVzdCB9IGZyb20gJy4uL2FwaS1jbGllbnQubWpzJztcbmltcG9ydCB7XG4gIGV4dHJhY3RMaXN0LFxuICBleHRyYWN0VmVyc2lvbnMsXG4gIGV4dHJhY3RBY3RpdmVWZXJzaW9uSWQsXG4gIGlzQWN0aXZlVmVyc2lvbixcbiAgdmVyc2lvbkNyZWF0ZWRBdCxcbiAgdmVyc2lvbklkLFxuICBMSVNUX1BBVEhTLFxuICBTVVBQT1JURURfVkVSU0lPTl9UWVBFUyxcbn0gZnJvbSAnLi4vcmVzcG9uc2Utc2hhcGVzLm1qcyc7XG5cbmNvbnN0IFZBTElEX1RZUEVTID0gbmV3IFNldChTVVBQT1JURURfVkVSU0lPTl9UWVBFUyk7XG5cbmV4cG9ydCBjb25zdCBsaXN0UHJpbWl0aXZlVmVyc2lvbnMgPSB7XG4gIHNwZWM6IHtcbiAgICBuYW1lOiAnbGlzdF9wcmltaXRpdmVfdmVyc2lvbnMnLFxuICAgIC8vIFdoaWNoIGZhbWlsaWVzIGNhcnJ5IGEgcGVyLWVudHJ5IGlkIFx1MjAxNCB2ZXJpZmllZCBpbiBsdWEtYXBpJ3Mgc2VydmljZVxuICAgIC8vIG1hcHBlcnMgKHBhY2thZ2VzL2x1YS1hcGkvc3JjL3NlcnZpY2VzLyk6XG4gICAgLy8gICBkZXZlbG9wZXIudHJpZ2dlci5zZXJ2aWNlLnRzIGdldFRyaWdnZXJWZXJzaW9ucyAgICAgICAgICAgIFx1MjE5MiB7IHZlcnNpb24sIHZlcnNpb25JZDogdi5pZCwgY3JlYXRlZEF0LCBpc0FjdGl2ZSB9XG4gICAgLy8gICBkZXZlbG9wZXIucHJlcHJvY2Vzc29yLnNlcnZpY2UudHMgZ2V0UHJlUHJvY2Vzc29yVmVyc2lvbnMgIFx1MjE5MiB7IHZlcnNpb25JZDogdi5pZCwgdmVyc2lvbiwgaXNBY3RpdmUsIGNyZWF0ZWRBdCB9XG4gICAgLy8gICBkZXZlbG9wZXIucG9zdHByb2Nlc3Nvci5zZXJ2aWNlLnRzIGdldFBvc3RQcm9jZXNzb3JWZXJzaW9uc1x1MjE5MiBzYW1lIGFzIHByZXByb2Nlc3NvclxuICAgIC8vICAgZGV2ZWxvcGVyLndvcmtmbG93LnNlcnZpY2UudHMgdG9WZXJzaW9uRHRvICAgICAgICAgICAgICAgICBcdTIxOTIgeyBpZCwgdmVyc2lvbiwgYWN0aXZlLCAuLi4gfVxuICAgIC8vICAgZHRvL2pvYi5kdG8udHMgSm9iVmVyc2lvbkR0byAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdTIxOTIgeyBpZCwgdmVyc2lvbiwgYWN0aXZlLCAuLi4gfVxuICAgIC8vICAgZGV2ZWxvcGVyLndlYmhvb2suc2VydmljZS50cyBnZXRXZWJob29rVmVyc2lvbnMgICAgICAgICAgICBcdTIxOTIgeyB2ZXJzaW9uLCB3ZWJob29rSWQ6IHYuaWQsIGNyZWF0ZWRBdCwgaXNBY3RpdmUgfVxuICAgIC8vICAgICAgIChOTyB2ZXJzaW9uSWQvaWQga2V5IFx1MjAxNCB0aGUgcm93IGlkIGlzIHN0YXNoZWQgdW5kZXIgdGhlIG1pc25hbWVkXG4gICAgLy8gICAgICAgIGB3ZWJob29rSWRgLCB3aGljaCB3ZSBkZWxpYmVyYXRlbHkgZG8gbm90IHJlYWQgYXMgYSB2ZXJzaW9uIGlkKVxuICAgIC8vICAgZHRvL3NraWxsLmR0by50cyBTa2lsbFZlcnNpb25EdG8gICAgICAgICAgICAgICAgICAgICAgICAgICBcdTIxOTIgeyB2ZXJzaW9uLCBjcmVhdGVkRGF0ZSwgY3JlYXRlZEJ5LCBpc0N1cnJlbnQgfSAobm8gaWQpXG4gICAgLy8gICBwZXJzb25hL2Jhc2UuY29udHJvbGxlci50cyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFx1MjE5MiB7IHZlcnNpb246IG51bWJlciwgY3JlYXRlZERhdGUsIGlzQ3VycmVudCwgcGVyc29uYSB9IChubyBpZClcbiAgICBkZXNjcmlwdGlvbjogJ0xpc3QgdGhlIHNlcnZlci1zaWRlIHZlcnNpb25zIG9mIG9uZSBwcmltaXRpdmUgKHNraWxsLCB3ZWJob29rLCBqb2IsIHRyaWdnZXIsIHByZXByb2Nlc3NvciwgcG9zdHByb2Nlc3Nvciwgd29ya2Zsb3cpIG9yIHRoZSBhZ2VudCBwZXJzb25hLiBSZXR1cm5zIHsgYWN0aXZlVmVyc2lvbklkLCB2ZXJzaW9uczogW3t2ZXJzaW9uLCB2ZXJzaW9uSWQsIGFjdGl2ZSwgY3JlYXRlZEF0fV0gfSBcdTIwMTQgYGFjdGl2ZWAgaXMgdGhlIHZlcnNpb24gY3VycmVudGx5IGxpdmUuIGB2ZXJzaW9uSWRgIGlzIG51bGwgZm9yIHR5cGVzIHdob3NlIHZlcnNpb25zIHJvdXRlIGNhcnJpZXMgbm8gcGVyLWVudHJ5IGlkOiBza2lsbCwgcGVyc29uYSBhbmQgd2ViaG9vayAodGhlIHdlYmhvb2sgcm91dGUgZXhwb3NlcyB0aGUgcm93IGlkIG9ubHkgdW5kZXIgYSBtaXNuYW1lZCBgd2ViaG9va0lkYCBrZXkpLiBGb3IgdGhvc2UsIGlkZW50aWZ5IGEgdmVyc2lvbiBieSBgdmVyc2lvbmA7IGZvciB3ZWJob29rcyB0aGUgbGl2ZSByb3cgaWQgaXMgdGhlIHRvcC1sZXZlbCBgYWN0aXZlVmVyc2lvbklkYC4gYGFjdGl2ZVZlcnNpb25JZGAgaXMgcG9wdWxhdGVkIG9ubHkgZm9yIHdlYmhvb2ssIHRyaWdnZXIsIHByZXByb2Nlc3NvciBhbmQgcG9zdHByb2Nlc3NvciBlbnZlbG9wZXMgYW5kIGlzIG51bGwgZm9yIHNraWxsLCBqb2IsIHdvcmtmbG93IGFuZCBwZXJzb25hLicsXG4gICAgaW5wdXRTY2hlbWE6IHtcbiAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICBhZ2VudElkOiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gICAgICAgIHR5cGU6IHsgdHlwZTogJ3N0cmluZycsIGVudW06IFsuLi5WQUxJRF9UWVBFU10gfSxcbiAgICAgICAgbmFtZTogeyB0eXBlOiAnc3RyaW5nJywgZGVzY3JpcHRpb246ICdQcmltaXRpdmUgbmFtZSBhcyB3cml0dGVuIGluIGx1YS5za2lsbC55YW1sIChvbWl0IGZvciBwZXJzb25hIFx1MjAxNCBhbiBhZ2VudCBoYXMgb25seSBvbmUpJyB9LFxuICAgICAgfSxcbiAgICAgIHJlcXVpcmVkOiBbJ2FnZW50SWQnLCAndHlwZSddLFxuICAgIH0sXG4gIH0sXG4gIGFzeW5jIGhhbmRsZXIoeyBhZ2VudElkLCB0eXBlLCBuYW1lIH0sIGRlcHMgPSB7fSkge1xuICAgIGlmICghYWdlbnRJZCB8fCAhdHlwZSkgdGhyb3cgbmV3IEVycm9yKCdhZ2VudElkIGFuZCB0eXBlIGFyZSByZXF1aXJlZCcpO1xuICAgIGlmICghVkFMSURfVFlQRVMuaGFzKHR5cGUpKSB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgdHlwZTogJHt0eXBlfS4gVmFsaWQ6ICR7Wy4uLlZBTElEX1RZUEVTXS5qb2luKCcsICcpfWApO1xuICAgIGlmICh0eXBlICE9PSAncGVyc29uYScgJiYgIW5hbWUpIHRocm93IG5ldyBFcnJvcignbmFtZSBpcyByZXF1aXJlZCBmb3IgYWxsIHR5cGVzIGV4Y2VwdCBwZXJzb25hJyk7XG5cbiAgICAvLyBWZXJzaW9ucyBsaXZlIHVuZGVyIC9kZXZlbG9wZXIvPHBsdXJhbD4vOmFnZW50SWQvOmlkL3ZlcnNpb25zLCBFWENFUFRcbiAgICAvLyBwZXJzb25hIHdoaWNoIGxpdmVzIHVuZGVyIC9kZXZlbG9wZXIvYWdlbnRzLzphZ2VudElkL3BlcnNvbmEvdmVyc2lvbnNcbiAgICAvLyAobm8gOmlkKS4gVGhlIDppZCBzbG90IGlzIHRoZSBzZXJ2ZXIgaWQgKHNraWxsSWQgLyB3ZWJob29rSWQgLyAuLi4pLFxuICAgIC8vIG5ldmVyIHRoZSBuYW1lIFx1MjAxNCBzbyByZXNvbHZlIG5hbWUgXHUyMTkyIGlkIGJ5IGxpc3RpbmcgZmlyc3QuXG4gICAgbGV0IHBhdGg7XG4gICAgaWYgKHR5cGUgPT09ICdwZXJzb25hJykge1xuICAgICAgcGF0aCA9IGAvZGV2ZWxvcGVyL2FnZW50cy8ke2VuY29kZVVSSUNvbXBvbmVudChhZ2VudElkKX0vcGVyc29uYS92ZXJzaW9uc2A7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGlkID0gYXdhaXQgcmVzb2x2ZU5hbWVUb0lkKHsgYWdlbnRJZCwgdHlwZSwgbmFtZSwgZmV0Y2hGbjogZGVwcy5mZXRjaEZuIH0pO1xuICAgICAgcGF0aCA9IGAvZGV2ZWxvcGVyLyR7TElTVF9QQVRIU1t0eXBlXX0vJHtlbmNvZGVVUklDb21wb25lbnQoYWdlbnRJZCl9LyR7ZW5jb2RlVVJJQ29tcG9uZW50KGlkKX0vdmVyc2lvbnNgO1xuICAgIH1cblxuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBhcGlSZXF1ZXN0KHBhdGgsIHsgZmV0Y2hGbjogZGVwcy5mZXRjaEZuIH0pO1xuICAgIGNvbnN0IHZlcnNpb25zID0gZXh0cmFjdFZlcnNpb25zKHR5cGUsIGRhdGEpO1xuICAgIGNvbnN0IGNvbXBhY3QgPSB2ZXJzaW9ucy5tYXAoKHYpID0+ICh7XG4gICAgICB2ZXJzaW9uOiB2LnZlcnNpb24sXG4gICAgICB2ZXJzaW9uSWQ6IHZlcnNpb25JZCh2KSxcbiAgICAgIGFjdGl2ZTogaXNBY3RpdmVWZXJzaW9uKHR5cGUsIHYsIGRhdGEpLFxuICAgICAgY3JlYXRlZEF0OiB2ZXJzaW9uQ3JlYXRlZEF0KHYpLFxuICAgIH0pKTtcbiAgICBjb25zdCByZXN1bHQgPSB7IGFnZW50SWQsIHR5cGUsIG5hbWU6IHR5cGUgPT09ICdwZXJzb25hJyA/IG51bGwgOiBuYW1lLCBhY3RpdmVWZXJzaW9uSWQ6IGV4dHJhY3RBY3RpdmVWZXJzaW9uSWQoZGF0YSksIHZlcnNpb25zOiBjb21wYWN0IH07XG4gICAgcmV0dXJuIHsgY29udGVudDogW3sgdHlwZTogJ3RleHQnLCB0ZXh0OiBKU09OLnN0cmluZ2lmeShyZXN1bHQsIG51bGwsIDIpIH1dIH07XG4gIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlTmFtZVRvSWQoeyBhZ2VudElkLCB0eXBlLCBuYW1lLCBmZXRjaEZuIH0pIHtcbiAgY29uc3QgbGlzdFBhdGggPSBgL2RldmVsb3Blci8ke0xJU1RfUEFUSFNbdHlwZV19LyR7ZW5jb2RlVVJJQ29tcG9uZW50KGFnZW50SWQpfWA7XG4gIGNvbnN0IGxpc3RSZXNwb25zZSA9IGF3YWl0IGFwaVJlcXVlc3QobGlzdFBhdGgsIHsgZmV0Y2hGbiB9KTtcbiAgY29uc3QgaXRlbXMgPSBleHRyYWN0TGlzdCh0eXBlLCBsaXN0UmVzcG9uc2UpO1xuICBjb25zdCBtYXRjaCA9IGl0ZW1zLmZpbmQoKHApID0+IHAubmFtZSA9PT0gbmFtZSk7XG4gIGlmICghbWF0Y2gpIHtcbiAgICBjb25zdCBhdmFpbGFibGUgPSBpdGVtcy5tYXAoKHApID0+IHAubmFtZSkuZmlsdGVyKEJvb2xlYW4pLmpvaW4oJywgJykgfHwgJyhub25lKSc7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBsaXN0X3ByaW1pdGl2ZV92ZXJzaW9uczogbm8gJHt0eXBlfSBuYW1lZCBcIiR7bmFtZX1cIiBvbiBhZ2VudCAke2FnZW50SWR9LiBBdmFpbGFibGU6ICR7YXZhaWxhYmxlfWApO1xuICB9XG4gIGNvbnN0IGlkID0gbWF0Y2guaWQgPz8gbWF0Y2guX2lkO1xuICBpZiAoIWlkKSB0aHJvdyBuZXcgRXJyb3IoYGxpc3RfcHJpbWl0aXZlX3ZlcnNpb25zOiAke3R5cGV9IFwiJHtuYW1lfVwiIGV4aXN0cyBidXQgaGFzIG5vIGlkIGZpZWxkYCk7XG4gIHJldHVybiBpZDtcbn1cbiIsICJpbXBvcnQgeyBhcGlSZXF1ZXN0IH0gZnJvbSAnLi4vYXBpLWNsaWVudC5tanMnO1xuaW1wb3J0IHtcbiAgZXh0cmFjdExpc3QsXG4gIGV4dHJhY3RWZXJzaW9ucyxcbiAgZXh0cmFjdEFjdGl2ZVZlcnNpb25JZCxcbiAgaXNBY3RpdmVWZXJzaW9uLFxuICB2ZXJzaW9uQ3JlYXRlZEF0LFxuICB2ZXJzaW9uSWQsXG4gIExJU1RfUEFUSFMsXG59IGZyb20gJy4uL3Jlc3BvbnNlLXNoYXBlcy5tanMnO1xuXG4vLyBDb21wb3NlcyBcIndoYXQgaXMgbGl2ZVwiIGZyb20gdGhlIHBlci10eXBlIGx1YS1hcGkgbGlzdCArIHZlcnNpb25zIHJvdXRlcy5cbi8vIFRoZXJlIGlzIG5vIHNpbmdsZSBgL2FnZW50cy86aWQvcHJvZHVjdGlvbmAgcm91dGU7IGBsdWEgc3RhdHVzIC0tanNvbmBcbi8vIGdpdmVzIHRoZSBzYW1lIHBpY3R1cmUgZm9yIHRoZSBDVVJSRU5UIHByb2plY3QgKGxvY2FsIHZzIGRlcGxveWVkKSBhbmQgaXNcbi8vIHRoZSBiZXR0ZXIgdG9vbCB3aGVuIGEgbHVhLnNraWxsLnlhbWwgaXMgYXQgaGFuZC4gVGhpcyB0b29sIHdvcmtzIGZvciBhbnlcbi8vIGFnZW50IHRoZSBjcmVkZW50aWFsIGNhbiByZWFjaCwgcHJvamVjdCBvciBub3QuXG4vL1xuLy8gUGVyLXR5cGUgZW52ZWxvcGUgaGFuZGxpbmcgbGl2ZXMgaW4gcmVzcG9uc2Utc2hhcGVzLm1qcy5cbi8vXG4vLyBSZXF1ZXN0IGZhbi1vdXQgKDEgKyA3ICsgTiB2ZXJzaW9uIGxvb2t1cHMpIGlzIHBhcmFsbGVsaXNlZCBpbiB0d28gcGhhc2VzOlxuLy8gICAxLiB0aGUgcGVyc29uYSBjYWxsIGFuZCB0aGUgc2V2ZW4gbGlzdCBjYWxscyBydW4gdG9nZXRoZXI7XG4vLyAgIDIuIHBlciB0eXBlLCBpdGVtIHZlcnNpb24gbG9va3VwcyBydW4gaW4gY2h1bmtzIG9mIFZFUlNJT05TX0NIVU5LX1NJWkUuXG4vLyBPdXRwdXQgb3JkZXIgaXMgZGV0ZXJtaW5pc3RpYyByZWdhcmRsZXNzIG9mIGNvbXBsZXRpb24gb3JkZXI6IHR5cGVzIGluXG4vLyBQUklNSVRJVkVfVFlQRVMgb3JkZXIsIGl0ZW1zIGluIHRoZSBvcmRlciB0aGUgbGlzdCByb3V0ZSByZXR1cm5lZCB0aGVtLlxuLy8gQSB3YWxsLWNsb2NrIGJ1ZGdldCAoQlVER0VUX01TLCBpbmplY3RhYmxlIGFzIGRlcHMuYnVkZ2V0TXMpIHN0b3BzIE5FV1xuLy8gcmVxdWVzdHMgb25jZSBleGNlZWRlZDsgYWxyZWFkeS1pc3N1ZWQgcmVxdWVzdHMgc3RpbGwgY29tcGxldGUuIEl0ZW1zIHRoYXRcbi8vIGNvdWxkIG5vdCBiZSBsb29rZWQgdXAgYXJlIHN0aWxsIGxpc3RlZCwgd2l0aCBgZXJyb3I6IFwic2tpcHBlZDogXHUyMDI2XCJgLCBhbmRcbi8vIHRoZSByZXN1bHQgY2FycmllcyBgcGFydGlhbDogdHJ1ZWAgKyBgcGFydGlhbFJlYXNvbmAuXG5cbmNvbnN0IFBSSU1JVElWRV9UWVBFUyA9IFsnc2tpbGwnLCAnd2ViaG9vaycsICdqb2InLCAndHJpZ2dlcicsICdwcmVwcm9jZXNzb3InLCAncG9zdHByb2Nlc3NvcicsICd3b3JrZmxvdyddO1xuY29uc3QgVkVSU0lPTlNfQ0hVTktfU0laRSA9IDU7XG5jb25zdCBERUZBVUxUX0JVREdFVF9NUyA9IDQ1XzAwMDtcblxuZXhwb3J0IGNvbnN0IGdldERlcGxveW1lbnRTdGF0dXMgPSB7XG4gIHNwZWM6IHtcbiAgICBuYW1lOiAnZ2V0X2RlcGxveW1lbnRfc3RhdHVzJyxcbiAgICBkZXNjcmlwdGlvbjogJ1doYXQgaXMgbGl2ZSByaWdodCBub3cgZm9yIGFuIGFnZW50OiBmb3IgZXZlcnkgc2tpbGwsIHdlYmhvb2ssIGpvYiwgdHJpZ2dlciwgcHJlcHJvY2Vzc29yLCBwb3N0cHJvY2Vzc29yIGFuZCB3b3JrZmxvdyB0aGUgYWN0aXZlIChkZXBsb3llZCkgdmVyc2lvbiwgcGx1cyB0aGUgYWN0aXZlIHBlcnNvbmEgdmVyc2lvbi4gQ29tcG9zZWQgZnJvbSB0aGUgcGVyLXR5cGUgbHVhLWFwaSB2ZXJzaW9uIHJvdXRlcyAobGlzdCBjYWxscyBpbiBwYXJhbGxlbCwgdGhlbiBwZXItaXRlbSB2ZXJzaW9uIGxvb2t1cHMgaW4gY2h1bmtzIG9mIDUpLiBCb3VuZGVkIGJ5IGEgNDUgcyB3YWxsLWNsb2NrIGJ1ZGdldDogaWYgZXhjZWVkZWQsIHJlbWFpbmluZyBpdGVtcyBhcmUgbGlzdGVkIHdpdGggYGVycm9yOiBcInNraXBwZWQ6IFx1MjAyNlwiYCBhbmQgdGhlIHJlc3VsdCBjYXJyaWVzIGBwYXJ0aWFsOiB0cnVlYCArIGBwYXJ0aWFsUmVhc29uYC4gSW5zaWRlIGEgcHJvamVjdCwgYGx1YSBzdGF0dXMgLS1qc29uYCBhZGRpdGlvbmFsbHkgY29tcGFyZXMgbG9jYWwgdnMgZGVwbG95ZWQuJyxcbiAgICBpbnB1dFNjaGVtYToge1xuICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIGFnZW50SWQ6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgIH0sXG4gICAgICByZXF1aXJlZDogWydhZ2VudElkJ10sXG4gICAgfSxcbiAgfSxcbiAgYXN5bmMgaGFuZGxlcih7IGFnZW50SWQgfSwgZGVwcyA9IHt9KSB7XG4gICAgaWYgKCFhZ2VudElkKSB0aHJvdyBuZXcgRXJyb3IoJ2FnZW50SWQgaXMgcmVxdWlyZWQnKTtcbiAgICBjb25zdCBpZCA9IGVuY29kZVVSSUNvbXBvbmVudChhZ2VudElkKTtcbiAgICBjb25zdCBidWRnZXRNcyA9IE51bWJlci5pc0Zpbml0ZShkZXBzLmJ1ZGdldE1zKSA/IGRlcHMuYnVkZ2V0TXMgOiBERUZBVUxUX0JVREdFVF9NUztcbiAgICBjb25zdCBzdGFydGVkQXQgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IG92ZXJCdWRnZXQgPSAoKSA9PiBEYXRlLm5vdygpIC0gc3RhcnRlZEF0ID4gYnVkZ2V0TXM7XG4gICAgY29uc3QgZ2V0ID0gKHBhdGgpID0+IGFwaVJlcXVlc3QocGF0aCwgeyBmZXRjaEZuOiBkZXBzLmZldGNoRm4gfSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSB7IGFnZW50SWQsIHBlcnNvbmE6IG51bGwsIHByaW1pdGl2ZXM6IHt9IH07XG4gICAgLy8gU2VlZCBrZXlzIHVwIGZyb250IHNvIHRoZSBvdXRwdXQga2V5IG9yZGVyIG5ldmVyIGRlcGVuZHMgb24gdGltaW5nLlxuICAgIGZvciAoY29uc3QgdHlwZSBvZiBQUklNSVRJVkVfVFlQRVMpIHJlc3VsdC5wcmltaXRpdmVzW3R5cGVdID0gW107XG5cbiAgICAvLyBQaGFzZSAxOiBwZXJzb25hICsgZXZlcnkgbGlzdCByb3V0ZSwgYWxsIGluIGZsaWdodCBhdCBvbmNlLlxuICAgIC8vIFBlcnNvbmE6IG9uZSBwZXIgYWdlbnQsIHZlcnNpb25zIHVuZGVyIC9kZXZlbG9wZXIvYWdlbnRzLzphZ2VudElkL3BlcnNvbmEvdmVyc2lvbnMuXG4gICAgY29uc3QgW3BlcnNvbmFPdXRjb21lLCAuLi5saXN0T3V0Y29tZXNdID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFtcbiAgICAgIGdldChgL2RldmVsb3Blci9hZ2VudHMvJHtpZH0vcGVyc29uYS92ZXJzaW9uc2ApLFxuICAgICAgLi4uUFJJTUlUSVZFX1RZUEVTLm1hcCgodHlwZSkgPT4gZ2V0KGAvZGV2ZWxvcGVyLyR7TElTVF9QQVRIU1t0eXBlXX0vJHtpZH1gKSksXG4gICAgXSk7XG5cbiAgICBpZiAocGVyc29uYU91dGNvbWUuc3RhdHVzID09PSAnZnVsZmlsbGVkJykge1xuICAgICAgY29uc3QgcGVyc29uYVJlc3BvbnNlID0gcGVyc29uYU91dGNvbWUudmFsdWU7XG4gICAgICBjb25zdCB2ZXJzaW9ucyA9IGV4dHJhY3RWZXJzaW9ucygncGVyc29uYScsIHBlcnNvbmFSZXNwb25zZSk7XG4gICAgICBjb25zdCBhY3RpdmUgPSB2ZXJzaW9ucy5maW5kKCh2KSA9PiBpc0FjdGl2ZVZlcnNpb24oJ3BlcnNvbmEnLCB2LCBwZXJzb25hUmVzcG9uc2UpKSA/PyBudWxsO1xuICAgICAgcmVzdWx0LnBlcnNvbmEgPSB7XG4gICAgICAgIGFjdGl2ZVZlcnNpb246IGFjdGl2ZT8udmVyc2lvbiA/PyBudWxsLFxuICAgICAgICBhY3RpdmVWZXJzaW9uQ3JlYXRlZEF0OiB2ZXJzaW9uQ3JlYXRlZEF0KGFjdGl2ZSksXG4gICAgICAgIHZlcnNpb25Db3VudDogdmVyc2lvbnMubGVuZ3RoLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0LnBlcnNvbmEgPSB7IGVycm9yOiBwZXJzb25hT3V0Y29tZS5yZWFzb24/Lm1lc3NhZ2UgPz8gU3RyaW5nKHBlcnNvbmFPdXRjb21lLnJlYXNvbikgfTtcbiAgICB9XG5cbiAgICAvLyBQaGFzZSAyOiBwZXIgdHlwZSwgcmVzb2x2ZSBlYWNoIGl0ZW0ncyB2ZXJzaW9ucyBpbiBjaHVua3MuIFR5cGVzIGFyZVxuICAgIC8vIHZpc2l0ZWQgc2VxdWVudGlhbGx5IChjYW5vbmljYWwgb3JkZXIpOyB3aXRoaW4gYSB0eXBlIHVwIHRvXG4gICAgLy8gVkVSU0lPTlNfQ0hVTktfU0laRSBsb29rdXBzIGFyZSBpbiBmbGlnaHQgdG9nZXRoZXIuXG4gICAgbGV0IGJ1ZGdldEV4aGF1c3RlZCA9IGZhbHNlO1xuICAgIGxldCBza2lwcGVkID0gMDtcbiAgICBsZXQgdG90YWwgPSAwO1xuXG4gICAgZm9yIChsZXQgdCA9IDA7IHQgPCBQUklNSVRJVkVfVFlQRVMubGVuZ3RoOyB0KyspIHtcbiAgICAgIGNvbnN0IHR5cGUgPSBQUklNSVRJVkVfVFlQRVNbdF07XG4gICAgICBjb25zdCBwYXRoID0gTElTVF9QQVRIU1t0eXBlXTtcbiAgICAgIGNvbnN0IG91dGNvbWUgPSBsaXN0T3V0Y29tZXNbdF07XG4gICAgICBpZiAob3V0Y29tZS5zdGF0dXMgIT09ICdmdWxmaWxsZWQnKSB7XG4gICAgICAgIHJlc3VsdC5wcmltaXRpdmVzW3R5cGVdID0geyBlcnJvcjogb3V0Y29tZS5yZWFzb24/Lm1lc3NhZ2UgPz8gU3RyaW5nKG91dGNvbWUucmVhc29uKSB9O1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gVGhlIFVSTCBzbG90IGlzIHRoZSBzZXJ2ZXIgaWQgKDpza2lsbElkIC8gOndlYmhvb2tJZCAvIC4uLiksIG5ldmVyXG4gICAgICAvLyB0aGUgbmFtZS4gSXRlbXMgd2l0aG91dCBhbiBpZCBhcmUgZHJvcHBlZCwgYXMgYmVmb3JlLlxuICAgICAgY29uc3QgdGFyZ2V0cyA9IGV4dHJhY3RMaXN0KHR5cGUsIG91dGNvbWUudmFsdWUpXG4gICAgICAgIC5tYXAoKHApID0+ICh7IHAsIHByaW1JZDogcC5pZCA/PyBwLl9pZCwgbmFtZTogcC5uYW1lID8/IHAuaWQgPz8gcC5faWQgfSkpXG4gICAgICAgIC5maWx0ZXIoKHRndCkgPT4gdGd0LnByaW1JZCk7XG4gICAgICB0b3RhbCArPSB0YXJnZXRzLmxlbmd0aDtcblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0YXJnZXRzLmxlbmd0aDsgaSArPSBWRVJTSU9OU19DSFVOS19TSVpFKSB7XG4gICAgICAgIGNvbnN0IGNodW5rID0gdGFyZ2V0cy5zbGljZShpLCBpICsgVkVSU0lPTlNfQ0hVTktfU0laRSk7XG5cbiAgICAgICAgaWYgKGJ1ZGdldEV4aGF1c3RlZCB8fCBvdmVyQnVkZ2V0KCkpIHtcbiAgICAgICAgICBidWRnZXRFeGhhdXN0ZWQgPSB0cnVlO1xuICAgICAgICAgIHNraXBwZWQgKz0gY2h1bmsubGVuZ3RoO1xuICAgICAgICAgIGZvciAoY29uc3QgeyBuYW1lLCBwcmltSWQgfSBvZiBjaHVuaykge1xuICAgICAgICAgICAgcmVzdWx0LnByaW1pdGl2ZXNbdHlwZV0ucHVzaCh7XG4gICAgICAgICAgICAgIG5hbWUsIGlkOiBwcmltSWQsXG4gICAgICAgICAgICAgIGVycm9yOiBgc2tpcHBlZDogd2FsbC1jbG9jayBidWRnZXQgb2YgJHtidWRnZXRNc31tcyBleGhhdXN0ZWQgYmVmb3JlIHRoaXMgdmVyc2lvbiBsb29rdXAgd2FzIGlzc3VlZGAsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBvdXRjb21lcyA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcbiAgICAgICAgICBjaHVuay5tYXAoKHsgcHJpbUlkIH0pID0+IGdldChgL2RldmVsb3Blci8ke3BhdGh9LyR7aWR9LyR7ZW5jb2RlVVJJQ29tcG9uZW50KHByaW1JZCl9L3ZlcnNpb25zYCkpXG4gICAgICAgICk7XG5cbiAgICAgICAgb3V0Y29tZXMuZm9yRWFjaCgodm8sIGopID0+IHtcbiAgICAgICAgICBjb25zdCB7IHAsIHByaW1JZCwgbmFtZSB9ID0gY2h1bmtbal07XG4gICAgICAgICAgaWYgKHZvLnN0YXR1cyAhPT0gJ2Z1bGZpbGxlZCcpIHtcbiAgICAgICAgICAgIHJlc3VsdC5wcmltaXRpdmVzW3R5cGVdLnB1c2goeyBuYW1lLCBpZDogcHJpbUlkLCBlcnJvcjogdm8ucmVhc29uPy5tZXNzYWdlID8/IFN0cmluZyh2by5yZWFzb24pIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCB2ZXJzaW9uc1Jlc3BvbnNlID0gdm8udmFsdWU7XG4gICAgICAgICAgY29uc3QgdmVyc2lvbnMgPSBleHRyYWN0VmVyc2lvbnModHlwZSwgdmVyc2lvbnNSZXNwb25zZSk7XG4gICAgICAgICAgY29uc3QgYWN0aXZlID0gdmVyc2lvbnMuZmluZCgodikgPT4gaXNBY3RpdmVWZXJzaW9uKHR5cGUsIHYsIHZlcnNpb25zUmVzcG9uc2UpKSA/PyBudWxsO1xuXG4gICAgICAgICAgY29uc3QgZW50cnkgPSB7XG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgaWQ6IHByaW1JZCxcbiAgICAgICAgICAgIGFjdGl2ZVZlcnNpb246IGFjdGl2ZT8udmVyc2lvbiA/PyBudWxsLFxuICAgICAgICAgICAgYWN0aXZlVmVyc2lvbklkOiB2ZXJzaW9uSWQoYWN0aXZlKSA/PyBleHRyYWN0QWN0aXZlVmVyc2lvbklkKHZlcnNpb25zUmVzcG9uc2UpLFxuICAgICAgICAgICAgYWN0aXZlVmVyc2lvbkNyZWF0ZWRBdDogdmVyc2lvbkNyZWF0ZWRBdChhY3RpdmUpLFxuICAgICAgICAgICAgdmVyc2lvbkNvdW50OiB2ZXJzaW9ucy5sZW5ndGgsXG4gICAgICAgICAgfTtcbiAgICAgICAgICAvLyBSZWNvcmRzIHRoYXQgY2FycnkgdGhlaXIgb3duIGVuYWJsZWQvZGlzYWJsZWQgc3dpdGNoLlxuICAgICAgICAgIGlmICh0eXBlb2YgcC5hY3RpdmUgPT09ICdib29sZWFuJykgZW50cnkuZW5hYmxlZCA9IHAuYWN0aXZlO1xuICAgICAgICAgIGlmICh0eXBlID09PSAnd29ya2Zsb3cnICYmIHR5cGVvZiBwLmR5bmFtaWMgPT09ICdib29sZWFuJykgZW50cnkuZHluYW1pYyA9IHAuZHluYW1pYztcbiAgICAgICAgICByZXN1bHQucHJpbWl0aXZlc1t0eXBlXS5wdXNoKGVudHJ5KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHNraXBwZWQgPiAwKSB7XG4gICAgICByZXN1bHQucGFydGlhbCA9IHRydWU7XG4gICAgICByZXN1bHQucGFydGlhbFJlYXNvbiA9XG4gICAgICAgIGBXYWxsLWNsb2NrIGJ1ZGdldCBvZiAke2J1ZGdldE1zfW1zIGV4Y2VlZGVkIGFmdGVyICR7RGF0ZS5ub3coKSAtIHN0YXJ0ZWRBdH1tczsgYCArXG4gICAgICAgIGAke3NraXBwZWR9IG9mICR7dG90YWx9IHZlcnNpb24gbG9va3VwcyB3ZXJlIG5vdCBpc3N1ZWQgKGVudHJpZXMgY2FycnkgZXJyb3I6IFwic2tpcHBlZDogXHUyMDI2XCIpLmA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IFt7IHR5cGU6ICd0ZXh0JywgdGV4dDogSlNPTi5zdHJpbmdpZnkocmVzdWx0LCBudWxsLCAyKSB9XSxcbiAgICB9O1xuICB9LFxufTtcbiIsICJpbXBvcnQgeyBhcGlSZXF1ZXN0IH0gZnJvbSAnLi4vYXBpLWNsaWVudC5tanMnO1xuXG4vLyBUaGUgYGxvZ1NvdXJjZWAgZW51bSBsdWEtYXBpIGFjY2VwdHMgXHUyMDE0IEFHRU5UX0xPR19TT1VSQ0VTIGluXG4vLyBwYWNrYWdlcy9zaGFyZWQtdHlwZXMvc3JjL3ZtLWV4ZWN1dGlvbi1sb2cudHlwZXMudHMgKHRoZSBzaW5nbGUgc291cmNlIG9mXG4vLyB0cnV0aCBldmVyeSBzZXJ2aWNlIGltcG9ydHMpLiBgYWxsYCBpcyB0aGUgTUNQLXNpZGUgc2VudGluZWwgZm9yIFwibm9cbi8vIGZpbHRlclwiLiBOb3RlOiBgbHVhIGxvZ3MgLS10eXBlYCBhY2NlcHRzIGEgbmFycm93ZXIgbGlzdCBhbmQgbm8gYG1hc3RyYWAuXG5leHBvcnQgY29uc3QgTE9HX1NPVVJDRVMgPSBbXG4gICdza2lsbCcsICdqb2InLCAnd2ViaG9vaycsICd0cmlnZ2VyJywgJ3ByZXByb2Nlc3NvcicsICdwb3N0cHJvY2Vzc29yJyxcbiAgJ3VzZXJfbWVzc2FnZScsICdhZ2VudF9yZXNwb25zZScsICdhZ2VudF9lcnJvcicsICdydW50aW1lJywgJ21jcCcsICdyYWcnLFxuICAnZGV2aWNlJywgJ2RldmljZS10cmlnZ2VyJywgJ21vZGVsLXJlc29sdmVyJyxcbiAgJ3dvcmtmbG93LXN0ZXAnLCAnd29ya2Zsb3ctc2NyaXB0JywgJ3dvcmtmbG93Jyxcbl07XG5cbi8vIFRoZSBgbG9nVHlwZWAgcXVlcnkgcGFyYW0gXHUyMDE0IEdFVCAvZGV2ZWxvcGVyL2FnZW50cy86YWdlbnRJZC9sb2dzIHJlYWRzIGl0XG4vLyAoY29udHJvbGxlcnMvZGV2ZWxvcGVyL2Jhc2UuY29udHJvbGxlci50cykgYW5kIGRldmVsb3Blci5zZXJ2aWNlLnRzXG4vLyBnZXRBZ2VudExvZ3MgYXBwbGllcyBpdCB2ZXJiYXRpbSBhcyBgZmlsdGVyLnN1YlR5cGUgPSBsb2dUeXBlYC4gVGhlXG4vLyBhY2NlcHRlZCB2YWx1ZXMgYXJlIHRoZXJlZm9yZSB0aGUgVm1FeGVjdXRpb25Mb2cgYHN1YlR5cGVgIGVudW0gaW5cbi8vIHBhY2thZ2VzL3NoYXJlZC1zY2hlbWFzL3NyYy92bUV4ZWN1dGlvbkxvZ3Muc2NoZW1hLnRzOlxuLy8gICBlbnVtOiBbJ3N0YXJ0JywgJ2NvbXBsZXRlJywgJ2Vycm9yJywgJ2RlYnVnJywgJ3dhcm4nLCAnaW5mbyddXG4vLyAobWlycm9yZWQgYnkgbHVhLWNsaSdzIExvZ0VudHJ5LnN1YlR5cGUgaW4gc3JjL2ludGVyZmFjZXMvbG9ncy50cykuIEFueVxuLy8gb3RoZXIgc3RyaW5nIGlzIG5vdCByZWplY3RlZCBzZXJ2ZXItc2lkZSBcdTIwMTQgaXQgc2ltcGx5IG1hdGNoZXMgbm90aGluZy5cbmV4cG9ydCBjb25zdCBMT0dfVFlQRVMgPSBbJ2Vycm9yJywgJ3dhcm4nLCAnaW5mbycsICdkZWJ1ZycsICdzdGFydCcsICdjb21wbGV0ZSddO1xuXG5jb25zdCBWQUxJRF9UWVBFUyA9IG5ldyBTZXQoWydhbGwnLCAuLi5MT0dfU09VUkNFU10pO1xuY29uc3QgVkFMSURfTE9HX1RZUEVTID0gbmV3IFNldChMT0dfVFlQRVMpO1xuXG5leHBvcnQgY29uc3QgdGFpbExvZ3MgPSB7XG4gIHNwZWM6IHtcbiAgICBuYW1lOiAndGFpbF9sb2dzJyxcbiAgICBkZXNjcmlwdGlvbjogJ0ZldGNoIHJlY2VudCBleGVjdXRpb24gbG9ncyBmb3IgYW4gYWdlbnQgKHNhbWUgZGF0YSBhcyBgbHVhIGxvZ3MgLS1qc29uYCkuIFJldHVybnMgeyBsb2dzOiBMb2dFbnRyeVtdLCBwYWdpbmF0aW9uIH0uIEVhY2ggTG9nRW50cnkgaGFzIGBzdWJUeXBlYCAoZXJyb3IgfCB3YXJuIHwgaW5mbyB8IGRlYnVnIHwgc3RhcnQgfCBjb21wbGV0ZSksIGBtZXNzYWdlYCwgYHRpbWVzdGFtcGAsIGFuZCBgbWV0YWRhdGEubG9nU291cmNlYCAvIGBtZXRhZGF0YS5wcmltaXRpdmVOYW1lYCBcdTIwMTQgdGhlcmUgaXMgTk8gYGxldmVsYCBmaWVsZC4gRmlsdGVyIGJ5IHNvdXJjZSAoYHR5cGVgKSwgcHJpbWl0aXZlIChgbmFtZWApIGFuZC9vciBzZXZlcml0eSAoYGxvZ1R5cGVgLCB3aGljaCBmaWx0ZXJzIG9uIGBzdWJUeXBlYCkuJyxcbiAgICBpbnB1dFNjaGVtYToge1xuICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIGFnZW50SWQ6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICAgdHlwZToge1xuICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgIGVudW06IFsuLi5WQUxJRF9UWVBFU10sXG4gICAgICAgICAgZGVmYXVsdDogJ2FsbCcsXG4gICAgICAgICAgZGVzY3JpcHRpb246ICdMb2cgc291cmNlIGZpbHRlciAobWFwcyB0byBsdWEtYXBpIGBsb2dTb3VyY2VgKS4gYGFsbGAgPSBubyBmaWx0ZXIuJyxcbiAgICAgICAgfSxcbiAgICAgICAgbmFtZTogeyB0eXBlOiAnc3RyaW5nJywgZGVzY3JpcHRpb246ICdGaWx0ZXIgYnkgcHJpbWl0aXZlIG5hbWUgKG9wdGlvbmFsOyBtYXBzIHRvIGBwcmltaXRpdmVOYW1lYCknIH0sXG4gICAgICAgIGxvZ1R5cGU6IHtcbiAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICBlbnVtOiBMT0dfVFlQRVMsXG4gICAgICAgICAgZGVzY3JpcHRpb246ICdGaWx0ZXIgYnkgTG9nRW50cnkgYHN1YlR5cGVgIChvcHRpb25hbDsgbWFwcyB0byBsdWEtYXBpIGBsb2dUeXBlYCkuIE9taXQgZm9yIGV2ZXJ5IHNldmVyaXR5LiBlLmcuIGBlcnJvcmAgdG8gc2VlIG9ubHkgZmFpbHVyZXMuJyxcbiAgICAgICAgfSxcbiAgICAgICAgLy8gbHVhLWFwaSBjYXBzIGxpbWl0IGF0IDEwMCBzZXJ2ZXItc2lkZSAoTWF0aC5taW4oMTAwLCAuLi4pIGluXG4gICAgICAgIC8vIGNvbnRyb2xsZXJzL2RldmVsb3Blci9iYXNlLmNvbnRyb2xsZXIudHMpLiBNYXRjaCB0aGUgc2VydmVyIGNhcCBzb1xuICAgICAgICAvLyB0aGUgdG9vbCdzIGNvbnRyYWN0IGlzIGhvbmVzdC5cbiAgICAgICAgbGltaXQ6IHsgdHlwZTogJ251bWJlcicsIGRlZmF1bHQ6IDUwLCBtaW5pbXVtOiAxLCBtYXhpbXVtOiAxMDAgfSxcbiAgICAgICAgcGFnZTogeyB0eXBlOiAnbnVtYmVyJywgbWluaW11bTogMSwgZGVzY3JpcHRpb246ICdQYWdlIG51bWJlciBmb3IgcGFnaW5hdGlvbiAob3B0aW9uYWwpJyB9LFxuICAgICAgfSxcbiAgICAgIHJlcXVpcmVkOiBbJ2FnZW50SWQnXSxcbiAgICB9LFxuICB9LFxuICBhc3luYyBoYW5kbGVyKHsgYWdlbnRJZCwgdHlwZSA9ICdhbGwnLCBuYW1lLCBsb2dUeXBlLCBsaW1pdCA9IDUwLCBwYWdlIH0sIGRlcHMgPSB7fSkge1xuICAgIGlmICghYWdlbnRJZCkgdGhyb3cgbmV3IEVycm9yKCdhZ2VudElkIGlzIHJlcXVpcmVkJyk7XG4gICAgaWYgKCFWQUxJRF9UWVBFUy5oYXModHlwZSkpIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB0eXBlOiAke3R5cGV9LiBWYWxpZDogJHtbLi4uVkFMSURfVFlQRVNdLmpvaW4oJywgJyl9YCk7XG4gICAgaWYgKGxvZ1R5cGUgIT09IHVuZGVmaW5lZCAmJiAhVkFMSURfTE9HX1RZUEVTLmhhcyhsb2dUeXBlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGxvZ1R5cGU6ICR7bG9nVHlwZX0uIFZhbGlkOiAke0xPR19UWVBFUy5qb2luKCcsICcpfWApO1xuICAgIH1cbiAgICAvLyBEZWZlbnNpdmUgY2FwIG1hdGNoaW5nIHRoZSBzZXJ2ZXItc2lkZSBsaW1pdDsgcmVqZWN0cyBsb3VkIHJhdGhlclxuICAgIC8vIHRoYW4gc2lsZW50bHkgdHJ1bmNhdGluZy5cbiAgICBpZiAobGltaXQgPiAxMDApIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBsaW1pdDogJHtsaW1pdH0uIGx1YS1hcGkgY2FwcyBsb2dzIGF0IDEwMCBlbnRyaWVzIHBlciBjYWxsLmApO1xuICAgIC8vIFJvdXRlOiBHRVQgL2RldmVsb3Blci9hZ2VudHMvOmFnZW50SWQvbG9ncyAoY29udHJvbGxlcnMvZGV2ZWxvcGVyL2Jhc2UuY29udHJvbGxlci50cykuXG4gICAgLy8gUXVlcnkgcGFyYW1zIHRoZSBzZXJ2ZXIgcmVhZHM6IHBhZ2UsIGxpbWl0LCBzb3J0QnksIHNvcnRPcmRlciwgbG9nU291cmNlLFxuICAgIC8vIHByaW1pdGl2ZUlkLCBwcmltaXRpdmVOYW1lLCB0b29sSWQsIHRvb2xOYW1lLCBsb2dUeXBlLCB1c2VySWQuIFRoZVxuICAgIC8vIHR5cGUgZmlsdGVyIGlzIGBsb2dTb3VyY2VgIFx1MjAxNCBhIGBwcmltaXRpdmVUeXBlYCBwYXJhbSBpcyBzaWxlbnRseSBpZ25vcmVkLlxuICAgIGNvbnN0IHF1ZXJ5ID0geyBsaW1pdCB9O1xuICAgIGlmICh0eXBlICE9PSAnYWxsJykgcXVlcnkubG9nU291cmNlID0gdHlwZTtcbiAgICBpZiAobmFtZSkgcXVlcnkucHJpbWl0aXZlTmFtZSA9IG5hbWU7XG4gICAgaWYgKGxvZ1R5cGUpIHF1ZXJ5LmxvZ1R5cGUgPSBsb2dUeXBlO1xuICAgIGlmIChwYWdlKSBxdWVyeS5wYWdlID0gcGFnZTtcbiAgICBjb25zdCBkYXRhID0gYXdhaXQgYXBpUmVxdWVzdChcbiAgICAgIGAvZGV2ZWxvcGVyL2FnZW50cy8ke2VuY29kZVVSSUNvbXBvbmVudChhZ2VudElkKX0vbG9nc2AsXG4gICAgICB7IHF1ZXJ5LCBmZXRjaEZuOiBkZXBzLmZldGNoRm4gfVxuICAgICk7XG4gICAgcmV0dXJuIHsgY29udGVudDogW3sgdHlwZTogJ3RleHQnLCB0ZXh0OiBKU09OLnN0cmluZ2lmeShkYXRhLCBudWxsLCAyKSB9XSB9O1xuICB9LFxufTtcbiJdLAogICJtYXBwaW5ncyI6ICI2RkFFQSxPQUFTLFVBQUFBLE9BQWMsNENBQ3ZCLE9BQVMsd0JBQUFDLE9BQTRCLDRDQUNy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Q0FBTyxFQUFJO0FBQUEsRUFBTSxJQUFNLFFBQVEsS0FBSyxDQUFDLENBQUMsQ0FDNUUsQ0FFQSxRQUFRLEdBQUcsb0JBQXNCRixHQUFRLENBQ3ZDQyxHQUFtQixDQUNqQixNQUFPLG1CQUNQLEtBQU0sb0JBQ04sUUFBU0QsR0FBSyxRQUNkLE1BQU9BLEdBQUssTUFDWixlQUFnQixRQUNoQixnQkFBaUIsUUFBUSxJQUFJLGlCQUFtQixLQUNoRCxTQUFVLFFBQVEsU0FDbEIsR0FBSSxJQUFJLEtBQUssRUFBRSxZQUFZLENBQzdCLENBQUMsQ0FDSCxDQUFDLEVBRUQsUUFBUSxHQUFHLHFCQUF1QkcsR0FBVyxDQUMzQ0YsR0FBbUIsQ0FDakIsTUFBTyxtQkFDUCxLQUFNLHFCQUNOLE9BQVEsT0FBT0UsQ0FBTSxFQUNyQixNQUEyQkEsR0FBUyxNQUNwQyxlQUFnQixRQUNoQixnQkFBaUIsUUFBUSxJQUFJLGlCQUFtQixLQUNoRCxTQUFVLFFBQVEsU0FDbEIsR0FBSSxJQUFJLEtBQUssRUFBRSxZQUFZLENBQzdCLENBQUMsQ0FDSCxDQUFDLEVBRUQsTUFBTVYsRUFBTyxRQUFRLElBQUlXLEVBQXNCIiwKICAibmFtZXMiOiBbIlNlcnZlciIsICJTdGRpb1NlcnZlclRyYW5zcG9ydCIsICJDYWxsVG9vbFJlcXVlc3RTY2hlbWEiLCAiTGlzdFRvb2xzUmVxdWVzdFNjaGVtYSIsICJ0b29sc19leHBvcnRzIiwgIl9fZXhwb3J0IiwgImdldEFnZW50IiwgImdldERlcGxveW1lbnRTdGF0dXMiLCAibGlzdEFnZW50cyIsICJsaXN0UHJpbWl0aXZlVmVyc2lvbnMiLCAidGFpbExvZ3MiLCAic3Bhd24iLCAiREVGQVVMVF9USU1FT1VUX01TIiwgInJ1bkx1YSIsICJhcmdzIiwgInNwYXduRm4iLCAidGltZW91dE1zIiwgImxhYmVsIiwgInJlc29sdmUiLCAicmVqZWN0IiwgImNoaWxkIiwgInN0ZG91dCIsICJzdGRlcnIiLCAiZCIsICJ0aW1lciIsICJjb2RlIiwgImVyciIsICJmbGF0dGVuQWdlbnRzIiwgInBhcnNlZCIsICJvYmoiLCAiZW50cmllcyIsICJvcmciLCAiYSIsICJsaXN0QWdlbnRzVmlhQ2xpIiwgImxpc3RBZ2VudHMiLCAiX2FyZ3MiLCAiZGVwcyIsICJjb21wYWN0IiwgImxpc3RBZ2VudHNWaWFDbGkiLCAiZ2V0QWdlbnQiLCAiYWdlbnRJZCIsICJkZXBzIiwgIm1hdGNoIiwgImxpc3RBZ2VudHNWaWFDbGkiLCAiYSIsICJyZWFkRmlsZSIsICJyZWFkZGlyIiwgInN0YXQiLCAiam9pbiIsICJkaXJuYW1lIiwgImhvbWVkaXIiLCAiREVGQVVMVF9BUElfVVJMIiwgIkZJUkVCQVNFX1JFRlJFU0hfVVJMIiwgIlJFRlJFU0hfVElNRU9VVF9NUyIsICJSRUZSRVNIX1NLRVdfTVMiLCAiUkVKRUNURURfUkVGUkVTSF9SRUFTT05TIiwgInRva2VuQ2FjaGUiLCAicGFyc2VEb3RlbnZBcGlLZXkiLCAiY29udGVudCIsICJyYXdMaW5lIiwgIm0iLCAidmFsdWUiLCAicXVvdGVkIiwgImZpbmRTZXNzaW9uRmlsZSIsICJzZXNzaW9uc0RpciIsICJhcGlVcmwiLCAibmFtZXMiLCAicmVhZGRpciIsICJjYW5kaWRhdGVzIiwgIm5hbWUiLCAicGF0aCIsICJqb2luIiwgInNlc3Npb24iLCAicmVhZEZpbGUiLCAibXRpbWVNcyIsICJzdGF0IiwgImEiLCAiYiIsICJyZWZyZXNoU2Vzc2lvbkJlYXJlciIsICJmZXRjaEZuIiwgIm5vdyIsICJjYWNoZWQiLCAidG9rZW5DYWNoZSIsICJSRUZSRVNIX1NLRVdfTVMiLCAiY29udHJvbGxlciIsICJ0aW1lciIsICJSRUZSRVNIX1RJTUVPVVRfTVMiLCAicmVzIiwgIkZJUkVCQVNFX1JFRlJFU0hfVVJMIiwgImVyciIsICJyZWFzb24iLCAibWVzc2FnZSIsICJyZWplY3RlZCIsICJSRUpFQ1RFRF9SRUZSRVNIX1JFQVNPTlMiLCAiciIsICJib2R5IiwgImlkVG9rZW4iLCAiZXhwaXJlc0luIiwgInJlc29sdmVBcGlLZXkiLCAiZW52IiwgImNyZWRlbnRpYWxzUGF0aCIsICJob21lZGlyIiwgImRpcm5hbWUiLCAiY3dkIiwgIkRFRkFVTFRfQVBJX1VSTCIsICJmcm9tRG90ZW52IiwgImZvdW5kIiwgInJhdyIsICJwYXJzZWQiLCAiREVGQVVMVF9CQVNFX1VSTCIsICJERUZBVUxUX1RJTUVPVVRfTVMiLCAiUk9VVEVfU0NPUEVTIiwgIlJPVVRFX1NDT1BFX1NVTU1BUlkiLCAiYXBpUmVxdWVzdCIsICJwYXRoIiwgIm1ldGhvZCIsICJib2R5IiwgInF1ZXJ5IiwgImZldGNoRm4iLCAiYmFzZVVybCIsICJ0aW1lb3V0TXMiLCAiYXBpS2V5IiwgInJlc29sdmVBcGlLZXkiLCAidXJsIiwgImsiLCAidiIsICJjb250cm9sbGVyIiwgInRpbWVyIiwgInJlcyIsICJyYXciLCAiZnJpZW5kbHlNc2ciLCAicGFyc2VkIiwgImNvZGUiLCAiZXJyIiwgIkxJU1RfRVhUUkFDVE9SUyIsICJyIiwgIlZFUlNJT05TX0VYVFJBQ1RPUlMiLCAiTElTVF9QQVRIUyIsICJleHRyYWN0TGlzdCIsICJ0eXBlIiwgInJlc3BvbnNlIiwgImZuIiwgImV4dHJhY3RWZXJzaW9ucyIsICJleHRyYWN0QWN0aXZlVmVyc2lvbklkIiwgImlkIiwgImlzQWN0aXZlVmVyc2lvbiIsICJ2ZXJzaW9uIiwgImFjdGl2ZUlkIiwgIm93bklkIiwgInZlcnNpb25DcmVhdGVkQXQiLCAicmF3IiwgInZlcnNpb25JZCIsICJTVVBQT1JURURfTElTVF9UWVBFUyIsICJTVVBQT1JURURfVkVSU0lPTl9UWVBFUyIsICJWQUxJRF9UWVBFUyIsICJTVVBQT1JURURfVkVSU0lPTl9UWVBFUyIsICJsaXN0UHJpbWl0aXZlVmVyc2lvbnMiLCAiYWdlbnRJZCIsICJ0eXBlIiwgIm5hbWUiLCAiZGVwcyIsICJwYXRoIiwgImlkIiwgInJlc29sdmVOYW1lVG9JZCIsICJMSVNUX1BBVEhTIiwgImRhdGEiLCAiYXBpUmVxdWVzdCIsICJjb21wYWN0IiwgImV4dHJhY3RWZXJzaW9ucyIsICJ2IiwgInZlcnNpb25JZCIsICJpc0FjdGl2ZVZlcnNpb24iLCAidmVyc2lvbkNyZWF0ZWRBdCIsICJyZXN1bHQiLCAiZXh0cmFjdEFjdGl2ZVZlcnNpb25JZCIsICJmZXRjaEZuIiwgImxpc3RQYXRoIiwgImxpc3RSZXNwb25zZSIsICJpdGVtcyIsICJleHRyYWN0TGlzdCIsICJtYXRjaCIsICJwIiwgImF2YWlsYWJsZSIsICJQUklNSVRJVkVfVFlQRVMiLCAiVkVSU0lPTlNfQ0hVTktfU0laRSIsICJERUZBVUxUX0JVREdFVF9NUyIsICJnZXREZXBsb3ltZW50U3RhdHVzIiwgImFnZW50SWQiLCAiZGVwcyIsICJpZCIsICJidWRnZXRNcyIsICJzdGFydGVkQXQiLCAib3ZlckJ1ZGdldCIsICJnZXQiLCAicGF0aCIsICJhcGlSZXF1ZXN0IiwgInJlc3VsdCIsICJ0eXBlIiwgInBlcnNvbmFPdXRjb21lIiwgImxpc3RPdXRjb21lcyIsICJMSVNUX1BBVEhTIiwgInBlcnNvbmFSZXNwb25zZSIsICJ2ZXJzaW9ucyIsICJleHRyYWN0VmVyc2lvbnMiLCAiYWN0aXZlIiwgInYiLCAiaXNBY3RpdmVWZXJzaW9uIiwgInZlcnNpb25DcmVhdGVkQXQiLCAiYnVkZ2V0RXhoYXVzdGVkIiwgInNraXBwZWQiLCAidG90YWwiLCAidCIsICJvdXRjb21lIiwgInRhcmdldHMiLCAiZXh0cmFjdExpc3QiLCAicCIsICJ0Z3QiLCAiaSIsICJjaHVuayIsICJuYW1lIiwgInByaW1JZCIsICJ2byIsICJqIiwgInZlcnNpb25zUmVzcG9uc2UiLCAiZW50cnkiLCAidmVyc2lvbklkIiwgImV4dHJhY3RBY3RpdmVWZXJzaW9uSWQiLCAiTE9HX1NPVVJDRVMiLCAiTE9HX1RZUEVTIiwgIlZBTElEX1RZUEVTIiwgIlZBTElEX0xPR19UWVBFUyIsICJ0YWlsTG9ncyIsICJhZ2VudElkIiwgInR5cGUiLCAibmFtZSIsICJsb2dUeXBlIiwgImxpbWl0IiwgInBhZ2UiLCAiZGVwcyIsICJxdWVyeSIsICJkYXRhIiwgImFwaVJlcXVlc3QiLCAiVE9PTF9SRUdJU1RSWSIsICJ0b29sc19leHBvcnRzIiwgInNlcnZlciIsICJTZXJ2ZXIiLCAiTGlzdFRvb2xzUmVxdWVzdFNjaGVtYSIsICJ0IiwgIkNhbGxUb29sUmVxdWVzdFNjaGVtYSIsICJyZXEiLCAidG9vbCIsICJlcnIiLCAicmVwb3J0Q3Jhc2hBbmRFeGl0IiwgInBheWxvYWQiLCAicmVhc29uIiwgIlN0ZGlvU2VydmVyVHJhbnNwb3J0Il0KfQo= +import { createRequire as __luaCreateRequire } from 'node:module'; const require = __luaCreateRequire(import.meta.url); +var mr=Object.defineProperty;var Nt=(r,e)=>{for(var t in e)mr(r,t,{get:e[t],enumerable:!0})};var i={};Nt(i,{BRAND:()=>Dr,DIRTY:()=>Q,EMPTY_PATH:()=>vr,INVALID:()=>g,NEVER:()=>Ts,OK:()=>E,ParseStatus:()=>R,Schema:()=>v,ZodAny:()=>G,ZodArray:()=>J,ZodBigInt:()=>te,ZodBoolean:()=>re,ZodBranded:()=>Ce,ZodCatch:()=>he,ZodDate:()=>se,ZodDefault:()=>pe,ZodDiscriminatedUnion:()=>Ue,ZodEffects:()=>L,ZodEnum:()=>de,ZodError:()=>I,ZodFirstPartyTypeKind:()=>_,ZodFunction:()=>De,ZodIntersection:()=>oe,ZodIssueCode:()=>u,ZodLazy:()=>ce,ZodLiteral:()=>le,ZodMap:()=>we,ZodNaN:()=>Se,ZodNativeEnum:()=>ue,ZodNever:()=>P,ZodNull:()=>ae,ZodNullable:()=>D,ZodNumber:()=>ee,ZodObject:()=>A,ZodOptional:()=>j,ZodParsedType:()=>h,ZodPipeline:()=>Ie,ZodPromise:()=>X,ZodReadonly:()=>fe,ZodRecord:()=>qe,ZodSchema:()=>v,ZodSet:()=>ke,ZodString:()=>K,ZodSymbol:()=>xe,ZodTransformer:()=>L,ZodTuple:()=>q,ZodType:()=>v,ZodUndefined:()=>ne,ZodUnion:()=>ie,ZodUnknown:()=>B,ZodVoid:()=>be,addIssueToContext:()=>p,any:()=>Kr,array:()=>es,bigint:()=>zr,boolean:()=>Ft,coerce:()=>Ss,custom:()=>qt,date:()=>Br,datetimeRegex:()=>Vt,defaultErrorMap:()=>H,discriminatedUnion:()=>ns,effect:()=>gs,enum:()=>hs,function:()=>ds,getErrorMap:()=>_e,getParsedType:()=>U,instanceof:()=>Fr,intersection:()=>as,isAborted:()=>Me,isAsync:()=>ye,isDirty:()=>Ve,isValid:()=>Y,late:()=>Zr,lazy:()=>us,literal:()=>ps,makeIssue:()=>Ee,map:()=>cs,nan:()=>Hr,nativeEnum:()=>fs,never:()=>Xr,null:()=>Yr,nullable:()=>ys,number:()=>Zt,object:()=>ts,objectUtil:()=>ut,oboolean:()=>ks,onumber:()=>ws,optional:()=>_s,ostring:()=>bs,pipeline:()=>xs,preprocess:()=>vs,promise:()=>ms,quotelessJson:()=>gr,record:()=>os,set:()=>ls,setErrorMap:()=>yr,strictObject:()=>rs,string:()=>Dt,symbol:()=>Jr,transformer:()=>gs,tuple:()=>is,undefined:()=>Wr,union:()=>ss,unknown:()=>Gr,util:()=>b,void:()=>Qr});var b;(function(r){r.assertEqual=n=>{};function e(n){}r.assertIs=e;function t(n){throw new Error}r.assertNever=t,r.arrayToEnum=n=>{let a={};for(let c of n)a[c]=c;return a},r.getValidEnumValues=n=>{let a=r.objectKeys(n).filter(o=>typeof n[n[o]]!="number"),c={};for(let o of a)c[o]=n[o];return r.objectValues(c)},r.objectValues=n=>r.objectKeys(n).map(function(a){return n[a]}),r.objectKeys=typeof Object.keys=="function"?n=>Object.keys(n):n=>{let a=[];for(let c in n)Object.prototype.hasOwnProperty.call(n,c)&&a.push(c);return a},r.find=(n,a)=>{for(let c of n)if(a(c))return c},r.isInteger=typeof Number.isInteger=="function"?n=>Number.isInteger(n):n=>typeof n=="number"&&Number.isFinite(n)&&Math.floor(n)===n;function s(n,a=" | "){return n.map(c=>typeof c=="string"?`'${c}'`:c).join(a)}r.joinValues=s,r.jsonStringifyReplacer=(n,a)=>typeof a=="bigint"?a.toString():a})(b||(b={}));var ut;(function(r){r.mergeShapes=(e,t)=>({...e,...t})})(ut||(ut={}));var h=b.arrayToEnum(["string","nan","number","integer","float","boolean","date","bigint","symbol","function","undefined","null","array","object","unknown","promise","void","never","map","set"]),U=r=>{switch(typeof r){case"undefined":return h.undefined;case"string":return h.string;case"number":return Number.isNaN(r)?h.nan:h.number;case"boolean":return h.boolean;case"function":return h.function;case"bigint":return h.bigint;case"symbol":return h.symbol;case"object":return Array.isArray(r)?h.array:r===null?h.null:r.then&&typeof r.then=="function"&&r.catch&&typeof r.catch=="function"?h.promise:typeof Map<"u"&&r instanceof Map?h.map:typeof Set<"u"&&r instanceof Set?h.set:typeof Date<"u"&&r instanceof Date?h.date:h.object;default:return h.unknown}};var u=b.arrayToEnum(["invalid_type","invalid_literal","custom","invalid_union","invalid_union_discriminator","invalid_enum_value","unrecognized_keys","invalid_arguments","invalid_return_type","invalid_date","invalid_string","too_small","too_big","invalid_intersection_types","not_multiple_of","not_finite"]),gr=r=>JSON.stringify(r,null,2).replace(/"([^"]+)":/g,"$1:"),I=class r extends Error{get errors(){return this.issues}constructor(e){super(),this.issues=[],this.addIssue=s=>{this.issues=[...this.issues,s]},this.addIssues=(s=[])=>{this.issues=[...this.issues,...s]};let t=new.target.prototype;Object.setPrototypeOf?Object.setPrototypeOf(this,t):this.__proto__=t,this.name="ZodError",this.issues=e}format(e){let t=e||function(a){return a.message},s={_errors:[]},n=a=>{for(let c of a.issues)if(c.code==="invalid_union")c.unionErrors.map(n);else if(c.code==="invalid_return_type")n(c.returnTypeError);else if(c.code==="invalid_arguments")n(c.argumentsError);else if(c.path.length===0)s._errors.push(t(c));else{let o=s,l=0;for(;lt.message){let t={},s=[];for(let n of this.issues)if(n.path.length>0){let a=n.path[0];t[a]=t[a]||[],t[a].push(e(n))}else s.push(e(n));return{formErrors:s,fieldErrors:t}}get formErrors(){return this.flatten()}};I.create=r=>new I(r);var _r=(r,e)=>{let t;switch(r.code){case u.invalid_type:r.received===h.undefined?t="Required":t=`Expected ${r.expected}, received ${r.received}`;break;case u.invalid_literal:t=`Invalid literal value, expected ${JSON.stringify(r.expected,b.jsonStringifyReplacer)}`;break;case u.unrecognized_keys:t=`Unrecognized key(s) in object: ${b.joinValues(r.keys,", ")}`;break;case u.invalid_union:t="Invalid input";break;case u.invalid_union_discriminator:t=`Invalid discriminator value. Expected ${b.joinValues(r.options)}`;break;case u.invalid_enum_value:t=`Invalid enum value. Expected ${b.joinValues(r.options)}, received '${r.received}'`;break;case u.invalid_arguments:t="Invalid function arguments";break;case u.invalid_return_type:t="Invalid function return type";break;case u.invalid_date:t="Invalid date";break;case u.invalid_string:typeof r.validation=="object"?"includes"in r.validation?(t=`Invalid input: must include "${r.validation.includes}"`,typeof r.validation.position=="number"&&(t=`${t} at one or more positions greater than or equal to ${r.validation.position}`)):"startsWith"in r.validation?t=`Invalid input: must start with "${r.validation.startsWith}"`:"endsWith"in r.validation?t=`Invalid input: must end with "${r.validation.endsWith}"`:b.assertNever(r.validation):r.validation!=="regex"?t=`Invalid ${r.validation}`:t="Invalid";break;case u.too_small:r.type==="array"?t=`Array must contain ${r.exact?"exactly":r.inclusive?"at least":"more than"} ${r.minimum} element(s)`:r.type==="string"?t=`String must contain ${r.exact?"exactly":r.inclusive?"at least":"over"} ${r.minimum} character(s)`:r.type==="number"?t=`Number must be ${r.exact?"exactly equal to ":r.inclusive?"greater than or equal to ":"greater than "}${r.minimum}`:r.type==="bigint"?t=`Number must be ${r.exact?"exactly equal to ":r.inclusive?"greater than or equal to ":"greater than "}${r.minimum}`:r.type==="date"?t=`Date must be ${r.exact?"exactly equal to ":r.inclusive?"greater than or equal to ":"greater than "}${new Date(Number(r.minimum))}`:t="Invalid input";break;case u.too_big:r.type==="array"?t=`Array must contain ${r.exact?"exactly":r.inclusive?"at most":"less than"} ${r.maximum} element(s)`:r.type==="string"?t=`String must contain ${r.exact?"exactly":r.inclusive?"at most":"under"} ${r.maximum} character(s)`:r.type==="number"?t=`Number must be ${r.exact?"exactly":r.inclusive?"less than or equal to":"less than"} ${r.maximum}`:r.type==="bigint"?t=`BigInt must be ${r.exact?"exactly":r.inclusive?"less than or equal to":"less than"} ${r.maximum}`:r.type==="date"?t=`Date must be ${r.exact?"exactly":r.inclusive?"smaller than or equal to":"smaller than"} ${new Date(Number(r.maximum))}`:t="Invalid input";break;case u.custom:t="Invalid input";break;case u.invalid_intersection_types:t="Intersection results could not be merged";break;case u.not_multiple_of:t=`Number must be a multiple of ${r.multipleOf}`;break;case u.not_finite:t="Number must be finite";break;default:t=e.defaultError,b.assertNever(r)}return{message:t}},H=_r;var jt=H;function yr(r){jt=r}function _e(){return jt}var Ee=r=>{let{data:e,path:t,errorMaps:s,issueData:n}=r,a=[...t,...n.path||[]],c={...n,path:a};if(n.message!==void 0)return{...n,path:a,message:n.message};let o="",l=s.filter(d=>!!d).slice().reverse();for(let d of l)o=d(c,{data:e,defaultError:o}).message;return{...n,path:a,message:o}},vr=[];function p(r,e){let t=_e(),s=Ee({issueData:e,data:r.data,path:r.path,errorMaps:[r.common.contextualErrorMap,r.schemaErrorMap,t,t===H?void 0:H].filter(n=>!!n)});r.common.issues.push(s)}var R=class r{constructor(){this.value="valid"}dirty(){this.value==="valid"&&(this.value="dirty")}abort(){this.value!=="aborted"&&(this.value="aborted")}static mergeArray(e,t){let s=[];for(let n of t){if(n.status==="aborted")return g;n.status==="dirty"&&e.dirty(),s.push(n.value)}return{status:e.value,value:s}}static async mergeObjectAsync(e,t){let s=[];for(let n of t){let a=await n.key,c=await n.value;s.push({key:a,value:c})}return r.mergeObjectSync(e,s)}static mergeObjectSync(e,t){let s={};for(let n of t){let{key:a,value:c}=n;if(a.status==="aborted"||c.status==="aborted")return g;a.status==="dirty"&&e.dirty(),c.status==="dirty"&&e.dirty(),a.value!=="__proto__"&&(typeof c.value<"u"||n.alwaysSet)&&(s[a.value]=c.value)}return{status:e.value,value:s}}},g=Object.freeze({status:"aborted"}),Q=r=>({status:"dirty",value:r}),E=r=>({status:"valid",value:r}),Me=r=>r.status==="aborted",Ve=r=>r.status==="dirty",Y=r=>r.status==="valid",ye=r=>typeof Promise<"u"&&r instanceof Promise;var m;(function(r){r.errToObj=e=>typeof e=="string"?{message:e}:e||{},r.toString=e=>typeof e=="string"?e:e?.message})(m||(m={}));var $=class{constructor(e,t,s,n){this._cachedPath=[],this.parent=e,this.data=t,this._path=s,this._key=n}get path(){return this._cachedPath.length||(Array.isArray(this._key)?this._cachedPath.push(...this._path,...this._key):this._cachedPath.push(...this._path,this._key)),this._cachedPath}},$t=(r,e)=>{if(Y(e))return{success:!0,data:e.value};if(!r.common.issues.length)throw new Error("Validation failed but no issues detected.");return{success:!1,get error(){if(this._error)return this._error;let t=new I(r.common.issues);return this._error=t,this._error}}};function y(r){if(!r)return{};let{errorMap:e,invalid_type_error:t,required_error:s,description:n}=r;if(e&&(t||s))throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`);return e?{errorMap:e,description:n}:{errorMap:(c,o)=>{let{message:l}=r;return c.code==="invalid_enum_value"?{message:l??o.defaultError}:typeof o.data>"u"?{message:l??s??o.defaultError}:c.code!=="invalid_type"?{message:o.defaultError}:{message:l??t??o.defaultError}},description:n}}var v=class{get description(){return this._def.description}_getType(e){return U(e.data)}_getOrReturnCtx(e,t){return t||{common:e.parent.common,data:e.data,parsedType:U(e.data),schemaErrorMap:this._def.errorMap,path:e.path,parent:e.parent}}_processInputParams(e){return{status:new R,ctx:{common:e.parent.common,data:e.data,parsedType:U(e.data),schemaErrorMap:this._def.errorMap,path:e.path,parent:e.parent}}}_parseSync(e){let t=this._parse(e);if(ye(t))throw new Error("Synchronous parse encountered promise.");return t}_parseAsync(e){let t=this._parse(e);return Promise.resolve(t)}parse(e,t){let s=this.safeParse(e,t);if(s.success)return s.data;throw s.error}safeParse(e,t){let s={common:{issues:[],async:t?.async??!1,contextualErrorMap:t?.errorMap},path:t?.path||[],schemaErrorMap:this._def.errorMap,parent:null,data:e,parsedType:U(e)},n=this._parseSync({data:e,path:s.path,parent:s});return $t(s,n)}"~validate"(e){let t={common:{issues:[],async:!!this["~standard"].async},path:[],schemaErrorMap:this._def.errorMap,parent:null,data:e,parsedType:U(e)};if(!this["~standard"].async)try{let s=this._parseSync({data:e,path:[],parent:t});return Y(s)?{value:s.value}:{issues:t.common.issues}}catch(s){s?.message?.toLowerCase()?.includes("encountered")&&(this["~standard"].async=!0),t.common={issues:[],async:!0}}return this._parseAsync({data:e,path:[],parent:t}).then(s=>Y(s)?{value:s.value}:{issues:t.common.issues})}async parseAsync(e,t){let s=await this.safeParseAsync(e,t);if(s.success)return s.data;throw s.error}async safeParseAsync(e,t){let s={common:{issues:[],contextualErrorMap:t?.errorMap,async:!0},path:t?.path||[],schemaErrorMap:this._def.errorMap,parent:null,data:e,parsedType:U(e)},n=this._parse({data:e,path:s.path,parent:s}),a=await(ye(n)?n:Promise.resolve(n));return $t(s,a)}refine(e,t){let s=n=>typeof t=="string"||typeof t>"u"?{message:t}:typeof t=="function"?t(n):t;return this._refinement((n,a)=>{let c=e(n),o=()=>a.addIssue({code:u.custom,...s(n)});return typeof Promise<"u"&&c instanceof Promise?c.then(l=>l?!0:(o(),!1)):c?!0:(o(),!1)})}refinement(e,t){return this._refinement((s,n)=>e(s)?!0:(n.addIssue(typeof t=="function"?t(s,n):t),!1))}_refinement(e){return new L({schema:this,typeName:_.ZodEffects,effect:{type:"refinement",refinement:e}})}superRefine(e){return this._refinement(e)}constructor(e){this.spa=this.safeParseAsync,this._def=e,this.parse=this.parse.bind(this),this.safeParse=this.safeParse.bind(this),this.parseAsync=this.parseAsync.bind(this),this.safeParseAsync=this.safeParseAsync.bind(this),this.spa=this.spa.bind(this),this.refine=this.refine.bind(this),this.refinement=this.refinement.bind(this),this.superRefine=this.superRefine.bind(this),this.optional=this.optional.bind(this),this.nullable=this.nullable.bind(this),this.nullish=this.nullish.bind(this),this.array=this.array.bind(this),this.promise=this.promise.bind(this),this.or=this.or.bind(this),this.and=this.and.bind(this),this.transform=this.transform.bind(this),this.brand=this.brand.bind(this),this.default=this.default.bind(this),this.catch=this.catch.bind(this),this.describe=this.describe.bind(this),this.pipe=this.pipe.bind(this),this.readonly=this.readonly.bind(this),this.isNullable=this.isNullable.bind(this),this.isOptional=this.isOptional.bind(this),this["~standard"]={version:1,vendor:"zod",validate:t=>this["~validate"](t)}}optional(){return j.create(this,this._def)}nullable(){return D.create(this,this._def)}nullish(){return this.nullable().optional()}array(){return J.create(this)}promise(){return X.create(this,this._def)}or(e){return ie.create([this,e],this._def)}and(e){return oe.create(this,e,this._def)}transform(e){return new L({...y(this._def),schema:this,typeName:_.ZodEffects,effect:{type:"transform",transform:e}})}default(e){let t=typeof e=="function"?e:()=>e;return new pe({...y(this._def),innerType:this,defaultValue:t,typeName:_.ZodDefault})}brand(){return new Ce({typeName:_.ZodBranded,type:this,...y(this._def)})}catch(e){let t=typeof e=="function"?e:()=>e;return new he({...y(this._def),innerType:this,catchValue:t,typeName:_.ZodCatch})}describe(e){let t=this.constructor;return new t({...this._def,description:e})}pipe(e){return Ie.create(this,e)}readonly(){return fe.create(this)}isOptional(){return this.safeParse(void 0).success}isNullable(){return this.safeParse(null).success}},xr=/^c[^\s-]{8,}$/i,br=/^[0-9a-z]+$/,wr=/^[0-9A-HJKMNP-TV-Z]{26}$/i,kr=/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i,Sr=/^[a-z0-9_-]{21}$/i,Tr=/^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/,Rr=/^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/,Er=/^(?!\.)(?!.*\.\.)([A-Z0-9_'+\-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i,Cr="^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$",pt,Ir=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,Ar=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(3[0-2]|[12]?[0-9])$/,Or=/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/,Nr=/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,jr=/^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/,$r=/^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/,Pt="((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))",Lr=new RegExp(`^${Pt}$`);function Mt(r){let e="[0-5]\\d";r.precision?e=`${e}\\.\\d{${r.precision}}`:r.precision==null&&(e=`${e}(\\.\\d+)?`);let t=r.precision?"+":"?";return`([01]\\d|2[0-3]):[0-5]\\d(:${e})${t}`}function Pr(r){return new RegExp(`^${Mt(r)}$`)}function Vt(r){let e=`${Pt}T${Mt(r)}`,t=[];return t.push(r.local?"Z?":"Z"),r.offset&&t.push("([+-]\\d{2}:?\\d{2})"),e=`${e}(${t.join("|")})`,new RegExp(`^${e}$`)}function Mr(r,e){return!!((e==="v4"||!e)&&Ir.test(r)||(e==="v6"||!e)&&Or.test(r))}function Vr(r,e){if(!Tr.test(r))return!1;try{let[t]=r.split(".");if(!t)return!1;let s=t.replace(/-/g,"+").replace(/_/g,"/").padEnd(t.length+(4-t.length%4)%4,"="),n=JSON.parse(atob(s));return!(typeof n!="object"||n===null||"typ"in n&&n?.typ!=="JWT"||!n.alg||e&&n.alg!==e)}catch{return!1}}function Ur(r,e){return!!((e==="v4"||!e)&&Ar.test(r)||(e==="v6"||!e)&&Nr.test(r))}var K=class r extends v{_parse(e){if(this._def.coerce&&(e.data=String(e.data)),this._getType(e)!==h.string){let a=this._getOrReturnCtx(e);return p(a,{code:u.invalid_type,expected:h.string,received:a.parsedType}),g}let s=new R,n;for(let a of this._def.checks)if(a.kind==="min")e.data.lengtha.value&&(n=this._getOrReturnCtx(e,n),p(n,{code:u.too_big,maximum:a.value,type:"string",inclusive:!0,exact:!1,message:a.message}),s.dirty());else if(a.kind==="length"){let c=e.data.length>a.value,o=e.data.lengthe.test(n),{validation:t,code:u.invalid_string,...m.errToObj(s)})}_addCheck(e){return new r({...this._def,checks:[...this._def.checks,e]})}email(e){return this._addCheck({kind:"email",...m.errToObj(e)})}url(e){return this._addCheck({kind:"url",...m.errToObj(e)})}emoji(e){return this._addCheck({kind:"emoji",...m.errToObj(e)})}uuid(e){return this._addCheck({kind:"uuid",...m.errToObj(e)})}nanoid(e){return this._addCheck({kind:"nanoid",...m.errToObj(e)})}cuid(e){return this._addCheck({kind:"cuid",...m.errToObj(e)})}cuid2(e){return this._addCheck({kind:"cuid2",...m.errToObj(e)})}ulid(e){return this._addCheck({kind:"ulid",...m.errToObj(e)})}base64(e){return this._addCheck({kind:"base64",...m.errToObj(e)})}base64url(e){return this._addCheck({kind:"base64url",...m.errToObj(e)})}jwt(e){return this._addCheck({kind:"jwt",...m.errToObj(e)})}ip(e){return this._addCheck({kind:"ip",...m.errToObj(e)})}cidr(e){return this._addCheck({kind:"cidr",...m.errToObj(e)})}datetime(e){return typeof e=="string"?this._addCheck({kind:"datetime",precision:null,offset:!1,local:!1,message:e}):this._addCheck({kind:"datetime",precision:typeof e?.precision>"u"?null:e?.precision,offset:e?.offset??!1,local:e?.local??!1,...m.errToObj(e?.message)})}date(e){return this._addCheck({kind:"date",message:e})}time(e){return typeof e=="string"?this._addCheck({kind:"time",precision:null,message:e}):this._addCheck({kind:"time",precision:typeof e?.precision>"u"?null:e?.precision,...m.errToObj(e?.message)})}duration(e){return this._addCheck({kind:"duration",...m.errToObj(e)})}regex(e,t){return this._addCheck({kind:"regex",regex:e,...m.errToObj(t)})}includes(e,t){return this._addCheck({kind:"includes",value:e,position:t?.position,...m.errToObj(t?.message)})}startsWith(e,t){return this._addCheck({kind:"startsWith",value:e,...m.errToObj(t)})}endsWith(e,t){return this._addCheck({kind:"endsWith",value:e,...m.errToObj(t)})}min(e,t){return this._addCheck({kind:"min",value:e,...m.errToObj(t)})}max(e,t){return this._addCheck({kind:"max",value:e,...m.errToObj(t)})}length(e,t){return this._addCheck({kind:"length",value:e,...m.errToObj(t)})}nonempty(e){return this.min(1,m.errToObj(e))}trim(){return new r({...this._def,checks:[...this._def.checks,{kind:"trim"}]})}toLowerCase(){return new r({...this._def,checks:[...this._def.checks,{kind:"toLowerCase"}]})}toUpperCase(){return new r({...this._def,checks:[...this._def.checks,{kind:"toUpperCase"}]})}get isDatetime(){return!!this._def.checks.find(e=>e.kind==="datetime")}get isDate(){return!!this._def.checks.find(e=>e.kind==="date")}get isTime(){return!!this._def.checks.find(e=>e.kind==="time")}get isDuration(){return!!this._def.checks.find(e=>e.kind==="duration")}get isEmail(){return!!this._def.checks.find(e=>e.kind==="email")}get isURL(){return!!this._def.checks.find(e=>e.kind==="url")}get isEmoji(){return!!this._def.checks.find(e=>e.kind==="emoji")}get isUUID(){return!!this._def.checks.find(e=>e.kind==="uuid")}get isNANOID(){return!!this._def.checks.find(e=>e.kind==="nanoid")}get isCUID(){return!!this._def.checks.find(e=>e.kind==="cuid")}get isCUID2(){return!!this._def.checks.find(e=>e.kind==="cuid2")}get isULID(){return!!this._def.checks.find(e=>e.kind==="ulid")}get isIP(){return!!this._def.checks.find(e=>e.kind==="ip")}get isCIDR(){return!!this._def.checks.find(e=>e.kind==="cidr")}get isBase64(){return!!this._def.checks.find(e=>e.kind==="base64")}get isBase64url(){return!!this._def.checks.find(e=>e.kind==="base64url")}get minLength(){let e=null;for(let t of this._def.checks)t.kind==="min"&&(e===null||t.value>e)&&(e=t.value);return e}get maxLength(){let e=null;for(let t of this._def.checks)t.kind==="max"&&(e===null||t.valuenew K({checks:[],typeName:_.ZodString,coerce:r?.coerce??!1,...y(r)});function qr(r,e){let t=(r.toString().split(".")[1]||"").length,s=(e.toString().split(".")[1]||"").length,n=t>s?t:s,a=Number.parseInt(r.toFixed(n).replace(".","")),c=Number.parseInt(e.toFixed(n).replace(".",""));return a%c/10**n}var ee=class r extends v{constructor(){super(...arguments),this.min=this.gte,this.max=this.lte,this.step=this.multipleOf}_parse(e){if(this._def.coerce&&(e.data=Number(e.data)),this._getType(e)!==h.number){let a=this._getOrReturnCtx(e);return p(a,{code:u.invalid_type,expected:h.number,received:a.parsedType}),g}let s,n=new R;for(let a of this._def.checks)a.kind==="int"?b.isInteger(e.data)||(s=this._getOrReturnCtx(e,s),p(s,{code:u.invalid_type,expected:"integer",received:"float",message:a.message}),n.dirty()):a.kind==="min"?(a.inclusive?e.dataa.value:e.data>=a.value)&&(s=this._getOrReturnCtx(e,s),p(s,{code:u.too_big,maximum:a.value,type:"number",inclusive:a.inclusive,exact:!1,message:a.message}),n.dirty()):a.kind==="multipleOf"?qr(e.data,a.value)!==0&&(s=this._getOrReturnCtx(e,s),p(s,{code:u.not_multiple_of,multipleOf:a.value,message:a.message}),n.dirty()):a.kind==="finite"?Number.isFinite(e.data)||(s=this._getOrReturnCtx(e,s),p(s,{code:u.not_finite,message:a.message}),n.dirty()):b.assertNever(a);return{status:n.value,value:e.data}}gte(e,t){return this.setLimit("min",e,!0,m.toString(t))}gt(e,t){return this.setLimit("min",e,!1,m.toString(t))}lte(e,t){return this.setLimit("max",e,!0,m.toString(t))}lt(e,t){return this.setLimit("max",e,!1,m.toString(t))}setLimit(e,t,s,n){return new r({...this._def,checks:[...this._def.checks,{kind:e,value:t,inclusive:s,message:m.toString(n)}]})}_addCheck(e){return new r({...this._def,checks:[...this._def.checks,e]})}int(e){return this._addCheck({kind:"int",message:m.toString(e)})}positive(e){return this._addCheck({kind:"min",value:0,inclusive:!1,message:m.toString(e)})}negative(e){return this._addCheck({kind:"max",value:0,inclusive:!1,message:m.toString(e)})}nonpositive(e){return this._addCheck({kind:"max",value:0,inclusive:!0,message:m.toString(e)})}nonnegative(e){return this._addCheck({kind:"min",value:0,inclusive:!0,message:m.toString(e)})}multipleOf(e,t){return this._addCheck({kind:"multipleOf",value:e,message:m.toString(t)})}finite(e){return this._addCheck({kind:"finite",message:m.toString(e)})}safe(e){return this._addCheck({kind:"min",inclusive:!0,value:Number.MIN_SAFE_INTEGER,message:m.toString(e)})._addCheck({kind:"max",inclusive:!0,value:Number.MAX_SAFE_INTEGER,message:m.toString(e)})}get minValue(){let e=null;for(let t of this._def.checks)t.kind==="min"&&(e===null||t.value>e)&&(e=t.value);return e}get maxValue(){let e=null;for(let t of this._def.checks)t.kind==="max"&&(e===null||t.valuee.kind==="int"||e.kind==="multipleOf"&&b.isInteger(e.value))}get isFinite(){let e=null,t=null;for(let s of this._def.checks){if(s.kind==="finite"||s.kind==="int"||s.kind==="multipleOf")return!0;s.kind==="min"?(t===null||s.value>t)&&(t=s.value):s.kind==="max"&&(e===null||s.valuenew ee({checks:[],typeName:_.ZodNumber,coerce:r?.coerce||!1,...y(r)});var te=class r extends v{constructor(){super(...arguments),this.min=this.gte,this.max=this.lte}_parse(e){if(this._def.coerce)try{e.data=BigInt(e.data)}catch{return this._getInvalidInput(e)}if(this._getType(e)!==h.bigint)return this._getInvalidInput(e);let s,n=new R;for(let a of this._def.checks)a.kind==="min"?(a.inclusive?e.dataa.value:e.data>=a.value)&&(s=this._getOrReturnCtx(e,s),p(s,{code:u.too_big,type:"bigint",maximum:a.value,inclusive:a.inclusive,message:a.message}),n.dirty()):a.kind==="multipleOf"?e.data%a.value!==BigInt(0)&&(s=this._getOrReturnCtx(e,s),p(s,{code:u.not_multiple_of,multipleOf:a.value,message:a.message}),n.dirty()):b.assertNever(a);return{status:n.value,value:e.data}}_getInvalidInput(e){let t=this._getOrReturnCtx(e);return p(t,{code:u.invalid_type,expected:h.bigint,received:t.parsedType}),g}gte(e,t){return this.setLimit("min",e,!0,m.toString(t))}gt(e,t){return this.setLimit("min",e,!1,m.toString(t))}lte(e,t){return this.setLimit("max",e,!0,m.toString(t))}lt(e,t){return this.setLimit("max",e,!1,m.toString(t))}setLimit(e,t,s,n){return new r({...this._def,checks:[...this._def.checks,{kind:e,value:t,inclusive:s,message:m.toString(n)}]})}_addCheck(e){return new r({...this._def,checks:[...this._def.checks,e]})}positive(e){return this._addCheck({kind:"min",value:BigInt(0),inclusive:!1,message:m.toString(e)})}negative(e){return this._addCheck({kind:"max",value:BigInt(0),inclusive:!1,message:m.toString(e)})}nonpositive(e){return this._addCheck({kind:"max",value:BigInt(0),inclusive:!0,message:m.toString(e)})}nonnegative(e){return this._addCheck({kind:"min",value:BigInt(0),inclusive:!0,message:m.toString(e)})}multipleOf(e,t){return this._addCheck({kind:"multipleOf",value:e,message:m.toString(t)})}get minValue(){let e=null;for(let t of this._def.checks)t.kind==="min"&&(e===null||t.value>e)&&(e=t.value);return e}get maxValue(){let e=null;for(let t of this._def.checks)t.kind==="max"&&(e===null||t.valuenew te({checks:[],typeName:_.ZodBigInt,coerce:r?.coerce??!1,...y(r)});var re=class extends v{_parse(e){if(this._def.coerce&&(e.data=!!e.data),this._getType(e)!==h.boolean){let s=this._getOrReturnCtx(e);return p(s,{code:u.invalid_type,expected:h.boolean,received:s.parsedType}),g}return E(e.data)}};re.create=r=>new re({typeName:_.ZodBoolean,coerce:r?.coerce||!1,...y(r)});var se=class r extends v{_parse(e){if(this._def.coerce&&(e.data=new Date(e.data)),this._getType(e)!==h.date){let a=this._getOrReturnCtx(e);return p(a,{code:u.invalid_type,expected:h.date,received:a.parsedType}),g}if(Number.isNaN(e.data.getTime())){let a=this._getOrReturnCtx(e);return p(a,{code:u.invalid_date}),g}let s=new R,n;for(let a of this._def.checks)a.kind==="min"?e.data.getTime()a.value&&(n=this._getOrReturnCtx(e,n),p(n,{code:u.too_big,message:a.message,inclusive:!0,exact:!1,maximum:a.value,type:"date"}),s.dirty()):b.assertNever(a);return{status:s.value,value:new Date(e.data.getTime())}}_addCheck(e){return new r({...this._def,checks:[...this._def.checks,e]})}min(e,t){return this._addCheck({kind:"min",value:e.getTime(),message:m.toString(t)})}max(e,t){return this._addCheck({kind:"max",value:e.getTime(),message:m.toString(t)})}get minDate(){let e=null;for(let t of this._def.checks)t.kind==="min"&&(e===null||t.value>e)&&(e=t.value);return e!=null?new Date(e):null}get maxDate(){let e=null;for(let t of this._def.checks)t.kind==="max"&&(e===null||t.valuenew se({checks:[],coerce:r?.coerce||!1,typeName:_.ZodDate,...y(r)});var xe=class extends v{_parse(e){if(this._getType(e)!==h.symbol){let s=this._getOrReturnCtx(e);return p(s,{code:u.invalid_type,expected:h.symbol,received:s.parsedType}),g}return E(e.data)}};xe.create=r=>new xe({typeName:_.ZodSymbol,...y(r)});var ne=class extends v{_parse(e){if(this._getType(e)!==h.undefined){let s=this._getOrReturnCtx(e);return p(s,{code:u.invalid_type,expected:h.undefined,received:s.parsedType}),g}return E(e.data)}};ne.create=r=>new ne({typeName:_.ZodUndefined,...y(r)});var ae=class extends v{_parse(e){if(this._getType(e)!==h.null){let s=this._getOrReturnCtx(e);return p(s,{code:u.invalid_type,expected:h.null,received:s.parsedType}),g}return E(e.data)}};ae.create=r=>new ae({typeName:_.ZodNull,...y(r)});var G=class extends v{constructor(){super(...arguments),this._any=!0}_parse(e){return E(e.data)}};G.create=r=>new G({typeName:_.ZodAny,...y(r)});var B=class extends v{constructor(){super(...arguments),this._unknown=!0}_parse(e){return E(e.data)}};B.create=r=>new B({typeName:_.ZodUnknown,...y(r)});var P=class extends v{_parse(e){let t=this._getOrReturnCtx(e);return p(t,{code:u.invalid_type,expected:h.never,received:t.parsedType}),g}};P.create=r=>new P({typeName:_.ZodNever,...y(r)});var be=class extends v{_parse(e){if(this._getType(e)!==h.undefined){let s=this._getOrReturnCtx(e);return p(s,{code:u.invalid_type,expected:h.void,received:s.parsedType}),g}return E(e.data)}};be.create=r=>new be({typeName:_.ZodVoid,...y(r)});var J=class r extends v{_parse(e){let{ctx:t,status:s}=this._processInputParams(e),n=this._def;if(t.parsedType!==h.array)return p(t,{code:u.invalid_type,expected:h.array,received:t.parsedType}),g;if(n.exactLength!==null){let c=t.data.length>n.exactLength.value,o=t.data.lengthn.maxLength.value&&(p(t,{code:u.too_big,maximum:n.maxLength.value,type:"array",inclusive:!0,exact:!1,message:n.maxLength.message}),s.dirty()),t.common.async)return Promise.all([...t.data].map((c,o)=>n.type._parseAsync(new $(t,c,t.path,o)))).then(c=>R.mergeArray(s,c));let a=[...t.data].map((c,o)=>n.type._parseSync(new $(t,c,t.path,o)));return R.mergeArray(s,a)}get element(){return this._def.type}min(e,t){return new r({...this._def,minLength:{value:e,message:m.toString(t)}})}max(e,t){return new r({...this._def,maxLength:{value:e,message:m.toString(t)}})}length(e,t){return new r({...this._def,exactLength:{value:e,message:m.toString(t)}})}nonempty(e){return this.min(1,e)}};J.create=(r,e)=>new J({type:r,minLength:null,maxLength:null,exactLength:null,typeName:_.ZodArray,...y(e)});function ve(r){if(r instanceof A){let e={};for(let t in r.shape){let s=r.shape[t];e[t]=j.create(ve(s))}return new A({...r._def,shape:()=>e})}else return r instanceof J?new J({...r._def,type:ve(r.element)}):r instanceof j?j.create(ve(r.unwrap())):r instanceof D?D.create(ve(r.unwrap())):r instanceof q?q.create(r.items.map(e=>ve(e))):r}var A=class r extends v{constructor(){super(...arguments),this._cached=null,this.nonstrict=this.passthrough,this.augment=this.extend}_getCached(){if(this._cached!==null)return this._cached;let e=this._def.shape(),t=b.objectKeys(e);return this._cached={shape:e,keys:t},this._cached}_parse(e){if(this._getType(e)!==h.object){let d=this._getOrReturnCtx(e);return p(d,{code:u.invalid_type,expected:h.object,received:d.parsedType}),g}let{status:s,ctx:n}=this._processInputParams(e),{shape:a,keys:c}=this._getCached(),o=[];if(!(this._def.catchall instanceof P&&this._def.unknownKeys==="strip"))for(let d in n.data)c.includes(d)||o.push(d);let l=[];for(let d of c){let f=a[d],x=n.data[d];l.push({key:{status:"valid",value:d},value:f._parse(new $(n,x,n.path,d)),alwaysSet:d in n.data})}if(this._def.catchall instanceof P){let d=this._def.unknownKeys;if(d==="passthrough")for(let f of o)l.push({key:{status:"valid",value:f},value:{status:"valid",value:n.data[f]}});else if(d==="strict")o.length>0&&(p(n,{code:u.unrecognized_keys,keys:o}),s.dirty());else if(d!=="strip")throw new Error("Internal ZodObject error: invalid unknownKeys value.")}else{let d=this._def.catchall;for(let f of o){let x=n.data[f];l.push({key:{status:"valid",value:f},value:d._parse(new $(n,x,n.path,f)),alwaysSet:f in n.data})}}return n.common.async?Promise.resolve().then(async()=>{let d=[];for(let f of l){let x=await f.key,S=await f.value;d.push({key:x,value:S,alwaysSet:f.alwaysSet})}return d}).then(d=>R.mergeObjectSync(s,d)):R.mergeObjectSync(s,l)}get shape(){return this._def.shape()}strict(e){return m.errToObj,new r({...this._def,unknownKeys:"strict",...e!==void 0?{errorMap:(t,s)=>{let n=this._def.errorMap?.(t,s).message??s.defaultError;return t.code==="unrecognized_keys"?{message:m.errToObj(e).message??n}:{message:n}}}:{}})}strip(){return new r({...this._def,unknownKeys:"strip"})}passthrough(){return new r({...this._def,unknownKeys:"passthrough"})}extend(e){return new r({...this._def,shape:()=>({...this._def.shape(),...e})})}merge(e){return new r({unknownKeys:e._def.unknownKeys,catchall:e._def.catchall,shape:()=>({...this._def.shape(),...e._def.shape()}),typeName:_.ZodObject})}setKey(e,t){return this.augment({[e]:t})}catchall(e){return new r({...this._def,catchall:e})}pick(e){let t={};for(let s of b.objectKeys(e))e[s]&&this.shape[s]&&(t[s]=this.shape[s]);return new r({...this._def,shape:()=>t})}omit(e){let t={};for(let s of b.objectKeys(this.shape))e[s]||(t[s]=this.shape[s]);return new r({...this._def,shape:()=>t})}deepPartial(){return ve(this)}partial(e){let t={};for(let s of b.objectKeys(this.shape)){let n=this.shape[s];e&&!e[s]?t[s]=n:t[s]=n.optional()}return new r({...this._def,shape:()=>t})}required(e){let t={};for(let s of b.objectKeys(this.shape))if(e&&!e[s])t[s]=this.shape[s];else{let a=this.shape[s];for(;a instanceof j;)a=a._def.innerType;t[s]=a}return new r({...this._def,shape:()=>t})}keyof(){return Ut(b.objectKeys(this.shape))}};A.create=(r,e)=>new A({shape:()=>r,unknownKeys:"strip",catchall:P.create(),typeName:_.ZodObject,...y(e)});A.strictCreate=(r,e)=>new A({shape:()=>r,unknownKeys:"strict",catchall:P.create(),typeName:_.ZodObject,...y(e)});A.lazycreate=(r,e)=>new A({shape:r,unknownKeys:"strip",catchall:P.create(),typeName:_.ZodObject,...y(e)});var ie=class extends v{_parse(e){let{ctx:t}=this._processInputParams(e),s=this._def.options;function n(a){for(let o of a)if(o.result.status==="valid")return o.result;for(let o of a)if(o.result.status==="dirty")return t.common.issues.push(...o.ctx.common.issues),o.result;let c=a.map(o=>new I(o.ctx.common.issues));return p(t,{code:u.invalid_union,unionErrors:c}),g}if(t.common.async)return Promise.all(s.map(async a=>{let c={...t,common:{...t.common,issues:[]},parent:null};return{result:await a._parseAsync({data:t.data,path:t.path,parent:c}),ctx:c}})).then(n);{let a,c=[];for(let l of s){let d={...t,common:{...t.common,issues:[]},parent:null},f=l._parseSync({data:t.data,path:t.path,parent:d});if(f.status==="valid")return f;f.status==="dirty"&&!a&&(a={result:f,ctx:d}),d.common.issues.length&&c.push(d.common.issues)}if(a)return t.common.issues.push(...a.ctx.common.issues),a.result;let o=c.map(l=>new I(l));return p(t,{code:u.invalid_union,unionErrors:o}),g}}get options(){return this._def.options}};ie.create=(r,e)=>new ie({options:r,typeName:_.ZodUnion,...y(e)});var z=r=>r instanceof ce?z(r.schema):r instanceof L?z(r.innerType()):r instanceof le?[r.value]:r instanceof de?r.options:r instanceof ue?b.objectValues(r.enum):r instanceof pe?z(r._def.innerType):r instanceof ne?[void 0]:r instanceof ae?[null]:r instanceof j?[void 0,...z(r.unwrap())]:r instanceof D?[null,...z(r.unwrap())]:r instanceof Ce||r instanceof fe?z(r.unwrap()):r instanceof he?z(r._def.innerType):[],Ue=class r extends v{_parse(e){let{ctx:t}=this._processInputParams(e);if(t.parsedType!==h.object)return p(t,{code:u.invalid_type,expected:h.object,received:t.parsedType}),g;let s=this.discriminator,n=t.data[s],a=this.optionsMap.get(n);return a?t.common.async?a._parseAsync({data:t.data,path:t.path,parent:t}):a._parseSync({data:t.data,path:t.path,parent:t}):(p(t,{code:u.invalid_union_discriminator,options:Array.from(this.optionsMap.keys()),path:[s]}),g)}get discriminator(){return this._def.discriminator}get options(){return this._def.options}get optionsMap(){return this._def.optionsMap}static create(e,t,s){let n=new Map;for(let a of t){let c=z(a.shape[e]);if(!c.length)throw new Error(`A discriminator value for key \`${e}\` could not be extracted from all schema options`);for(let o of c){if(n.has(o))throw new Error(`Discriminator property ${String(e)} has duplicate value ${String(o)}`);n.set(o,a)}}return new r({typeName:_.ZodDiscriminatedUnion,discriminator:e,options:t,optionsMap:n,...y(s)})}};function ht(r,e){let t=U(r),s=U(e);if(r===e)return{valid:!0,data:r};if(t===h.object&&s===h.object){let n=b.objectKeys(e),a=b.objectKeys(r).filter(o=>n.indexOf(o)!==-1),c={...r,...e};for(let o of a){let l=ht(r[o],e[o]);if(!l.valid)return{valid:!1};c[o]=l.data}return{valid:!0,data:c}}else if(t===h.array&&s===h.array){if(r.length!==e.length)return{valid:!1};let n=[];for(let a=0;a{if(Me(a)||Me(c))return g;let o=ht(a.value,c.value);return o.valid?((Ve(a)||Ve(c))&&t.dirty(),{status:t.value,value:o.data}):(p(s,{code:u.invalid_intersection_types}),g)};return s.common.async?Promise.all([this._def.left._parseAsync({data:s.data,path:s.path,parent:s}),this._def.right._parseAsync({data:s.data,path:s.path,parent:s})]).then(([a,c])=>n(a,c)):n(this._def.left._parseSync({data:s.data,path:s.path,parent:s}),this._def.right._parseSync({data:s.data,path:s.path,parent:s}))}};oe.create=(r,e,t)=>new oe({left:r,right:e,typeName:_.ZodIntersection,...y(t)});var q=class r extends v{_parse(e){let{status:t,ctx:s}=this._processInputParams(e);if(s.parsedType!==h.array)return p(s,{code:u.invalid_type,expected:h.array,received:s.parsedType}),g;if(s.data.lengththis._def.items.length&&(p(s,{code:u.too_big,maximum:this._def.items.length,inclusive:!0,exact:!1,type:"array"}),t.dirty());let a=[...s.data].map((c,o)=>{let l=this._def.items[o]||this._def.rest;return l?l._parse(new $(s,c,s.path,o)):null}).filter(c=>!!c);return s.common.async?Promise.all(a).then(c=>R.mergeArray(t,c)):R.mergeArray(t,a)}get items(){return this._def.items}rest(e){return new r({...this._def,rest:e})}};q.create=(r,e)=>{if(!Array.isArray(r))throw new Error("You must pass an array of schemas to z.tuple([ ... ])");return new q({items:r,typeName:_.ZodTuple,rest:null,...y(e)})};var qe=class r extends v{get keySchema(){return this._def.keyType}get valueSchema(){return this._def.valueType}_parse(e){let{status:t,ctx:s}=this._processInputParams(e);if(s.parsedType!==h.object)return p(s,{code:u.invalid_type,expected:h.object,received:s.parsedType}),g;let n=[],a=this._def.keyType,c=this._def.valueType;for(let o in s.data)n.push({key:a._parse(new $(s,o,s.path,o)),value:c._parse(new $(s,s.data[o],s.path,o)),alwaysSet:o in s.data});return s.common.async?R.mergeObjectAsync(t,n):R.mergeObjectSync(t,n)}get element(){return this._def.valueType}static create(e,t,s){return t instanceof v?new r({keyType:e,valueType:t,typeName:_.ZodRecord,...y(s)}):new r({keyType:K.create(),valueType:e,typeName:_.ZodRecord,...y(t)})}},we=class extends v{get keySchema(){return this._def.keyType}get valueSchema(){return this._def.valueType}_parse(e){let{status:t,ctx:s}=this._processInputParams(e);if(s.parsedType!==h.map)return p(s,{code:u.invalid_type,expected:h.map,received:s.parsedType}),g;let n=this._def.keyType,a=this._def.valueType,c=[...s.data.entries()].map(([o,l],d)=>({key:n._parse(new $(s,o,s.path,[d,"key"])),value:a._parse(new $(s,l,s.path,[d,"value"]))}));if(s.common.async){let o=new Map;return Promise.resolve().then(async()=>{for(let l of c){let d=await l.key,f=await l.value;if(d.status==="aborted"||f.status==="aborted")return g;(d.status==="dirty"||f.status==="dirty")&&t.dirty(),o.set(d.value,f.value)}return{status:t.value,value:o}})}else{let o=new Map;for(let l of c){let d=l.key,f=l.value;if(d.status==="aborted"||f.status==="aborted")return g;(d.status==="dirty"||f.status==="dirty")&&t.dirty(),o.set(d.value,f.value)}return{status:t.value,value:o}}}};we.create=(r,e,t)=>new we({valueType:e,keyType:r,typeName:_.ZodMap,...y(t)});var ke=class r extends v{_parse(e){let{status:t,ctx:s}=this._processInputParams(e);if(s.parsedType!==h.set)return p(s,{code:u.invalid_type,expected:h.set,received:s.parsedType}),g;let n=this._def;n.minSize!==null&&s.data.sizen.maxSize.value&&(p(s,{code:u.too_big,maximum:n.maxSize.value,type:"set",inclusive:!0,exact:!1,message:n.maxSize.message}),t.dirty());let a=this._def.valueType;function c(l){let d=new Set;for(let f of l){if(f.status==="aborted")return g;f.status==="dirty"&&t.dirty(),d.add(f.value)}return{status:t.value,value:d}}let o=[...s.data.values()].map((l,d)=>a._parse(new $(s,l,s.path,d)));return s.common.async?Promise.all(o).then(l=>c(l)):c(o)}min(e,t){return new r({...this._def,minSize:{value:e,message:m.toString(t)}})}max(e,t){return new r({...this._def,maxSize:{value:e,message:m.toString(t)}})}size(e,t){return this.min(e,t).max(e,t)}nonempty(e){return this.min(1,e)}};ke.create=(r,e)=>new ke({valueType:r,minSize:null,maxSize:null,typeName:_.ZodSet,...y(e)});var De=class r extends v{constructor(){super(...arguments),this.validate=this.implement}_parse(e){let{ctx:t}=this._processInputParams(e);if(t.parsedType!==h.function)return p(t,{code:u.invalid_type,expected:h.function,received:t.parsedType}),g;function s(o,l){return Ee({data:o,path:t.path,errorMaps:[t.common.contextualErrorMap,t.schemaErrorMap,_e(),H].filter(d=>!!d),issueData:{code:u.invalid_arguments,argumentsError:l}})}function n(o,l){return Ee({data:o,path:t.path,errorMaps:[t.common.contextualErrorMap,t.schemaErrorMap,_e(),H].filter(d=>!!d),issueData:{code:u.invalid_return_type,returnTypeError:l}})}let a={errorMap:t.common.contextualErrorMap},c=t.data;if(this._def.returns instanceof X){let o=this;return E(async function(...l){let d=new I([]),f=await o._def.args.parseAsync(l,a).catch(w=>{throw d.addIssue(s(l,w)),d}),x=await Reflect.apply(c,this,f);return await o._def.returns._def.type.parseAsync(x,a).catch(w=>{throw d.addIssue(n(x,w)),d})})}else{let o=this;return E(function(...l){let d=o._def.args.safeParse(l,a);if(!d.success)throw new I([s(l,d.error)]);let f=Reflect.apply(c,this,d.data),x=o._def.returns.safeParse(f,a);if(!x.success)throw new I([n(f,x.error)]);return x.data})}}parameters(){return this._def.args}returnType(){return this._def.returns}args(...e){return new r({...this._def,args:q.create(e).rest(B.create())})}returns(e){return new r({...this._def,returns:e})}implement(e){return this.parse(e)}strictImplement(e){return this.parse(e)}static create(e,t,s){return new r({args:e||q.create([]).rest(B.create()),returns:t||B.create(),typeName:_.ZodFunction,...y(s)})}},ce=class extends v{get schema(){return this._def.getter()}_parse(e){let{ctx:t}=this._processInputParams(e);return this._def.getter()._parse({data:t.data,path:t.path,parent:t})}};ce.create=(r,e)=>new ce({getter:r,typeName:_.ZodLazy,...y(e)});var le=class extends v{_parse(e){if(e.data!==this._def.value){let t=this._getOrReturnCtx(e);return p(t,{received:t.data,code:u.invalid_literal,expected:this._def.value}),g}return{status:"valid",value:e.data}}get value(){return this._def.value}};le.create=(r,e)=>new le({value:r,typeName:_.ZodLiteral,...y(e)});function Ut(r,e){return new de({values:r,typeName:_.ZodEnum,...y(e)})}var de=class r extends v{_parse(e){if(typeof e.data!="string"){let t=this._getOrReturnCtx(e),s=this._def.values;return p(t,{expected:b.joinValues(s),received:t.parsedType,code:u.invalid_type}),g}if(this._cache||(this._cache=new Set(this._def.values)),!this._cache.has(e.data)){let t=this._getOrReturnCtx(e),s=this._def.values;return p(t,{received:t.data,code:u.invalid_enum_value,options:s}),g}return E(e.data)}get options(){return this._def.values}get enum(){let e={};for(let t of this._def.values)e[t]=t;return e}get Values(){let e={};for(let t of this._def.values)e[t]=t;return e}get Enum(){let e={};for(let t of this._def.values)e[t]=t;return e}extract(e,t=this._def){return r.create(e,{...this._def,...t})}exclude(e,t=this._def){return r.create(this.options.filter(s=>!e.includes(s)),{...this._def,...t})}};de.create=Ut;var ue=class extends v{_parse(e){let t=b.getValidEnumValues(this._def.values),s=this._getOrReturnCtx(e);if(s.parsedType!==h.string&&s.parsedType!==h.number){let n=b.objectValues(t);return p(s,{expected:b.joinValues(n),received:s.parsedType,code:u.invalid_type}),g}if(this._cache||(this._cache=new Set(b.getValidEnumValues(this._def.values))),!this._cache.has(e.data)){let n=b.objectValues(t);return p(s,{received:s.data,code:u.invalid_enum_value,options:n}),g}return E(e.data)}get enum(){return this._def.values}};ue.create=(r,e)=>new ue({values:r,typeName:_.ZodNativeEnum,...y(e)});var X=class extends v{unwrap(){return this._def.type}_parse(e){let{ctx:t}=this._processInputParams(e);if(t.parsedType!==h.promise&&t.common.async===!1)return p(t,{code:u.invalid_type,expected:h.promise,received:t.parsedType}),g;let s=t.parsedType===h.promise?t.data:Promise.resolve(t.data);return E(s.then(n=>this._def.type.parseAsync(n,{path:t.path,errorMap:t.common.contextualErrorMap})))}};X.create=(r,e)=>new X({type:r,typeName:_.ZodPromise,...y(e)});var L=class extends v{innerType(){return this._def.schema}sourceType(){return this._def.schema._def.typeName===_.ZodEffects?this._def.schema.sourceType():this._def.schema}_parse(e){let{status:t,ctx:s}=this._processInputParams(e),n=this._def.effect||null,a={addIssue:c=>{p(s,c),c.fatal?t.abort():t.dirty()},get path(){return s.path}};if(a.addIssue=a.addIssue.bind(a),n.type==="preprocess"){let c=n.transform(s.data,a);if(s.common.async)return Promise.resolve(c).then(async o=>{if(t.value==="aborted")return g;let l=await this._def.schema._parseAsync({data:o,path:s.path,parent:s});return l.status==="aborted"?g:l.status==="dirty"?Q(l.value):t.value==="dirty"?Q(l.value):l});{if(t.value==="aborted")return g;let o=this._def.schema._parseSync({data:c,path:s.path,parent:s});return o.status==="aborted"?g:o.status==="dirty"?Q(o.value):t.value==="dirty"?Q(o.value):o}}if(n.type==="refinement"){let c=o=>{let l=n.refinement(o,a);if(s.common.async)return Promise.resolve(l);if(l instanceof Promise)throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead.");return o};if(s.common.async===!1){let o=this._def.schema._parseSync({data:s.data,path:s.path,parent:s});return o.status==="aborted"?g:(o.status==="dirty"&&t.dirty(),c(o.value),{status:t.value,value:o.value})}else return this._def.schema._parseAsync({data:s.data,path:s.path,parent:s}).then(o=>o.status==="aborted"?g:(o.status==="dirty"&&t.dirty(),c(o.value).then(()=>({status:t.value,value:o.value}))))}if(n.type==="transform")if(s.common.async===!1){let c=this._def.schema._parseSync({data:s.data,path:s.path,parent:s});if(!Y(c))return g;let o=n.transform(c.value,a);if(o instanceof Promise)throw new Error("Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.");return{status:t.value,value:o}}else return this._def.schema._parseAsync({data:s.data,path:s.path,parent:s}).then(c=>Y(c)?Promise.resolve(n.transform(c.value,a)).then(o=>({status:t.value,value:o})):g);b.assertNever(n)}};L.create=(r,e,t)=>new L({schema:r,typeName:_.ZodEffects,effect:e,...y(t)});L.createWithPreprocess=(r,e,t)=>new L({schema:e,effect:{type:"preprocess",transform:r},typeName:_.ZodEffects,...y(t)});var j=class extends v{_parse(e){return this._getType(e)===h.undefined?E(void 0):this._def.innerType._parse(e)}unwrap(){return this._def.innerType}};j.create=(r,e)=>new j({innerType:r,typeName:_.ZodOptional,...y(e)});var D=class extends v{_parse(e){return this._getType(e)===h.null?E(null):this._def.innerType._parse(e)}unwrap(){return this._def.innerType}};D.create=(r,e)=>new D({innerType:r,typeName:_.ZodNullable,...y(e)});var pe=class extends v{_parse(e){let{ctx:t}=this._processInputParams(e),s=t.data;return t.parsedType===h.undefined&&(s=this._def.defaultValue()),this._def.innerType._parse({data:s,path:t.path,parent:t})}removeDefault(){return this._def.innerType}};pe.create=(r,e)=>new pe({innerType:r,typeName:_.ZodDefault,defaultValue:typeof e.default=="function"?e.default:()=>e.default,...y(e)});var he=class extends v{_parse(e){let{ctx:t}=this._processInputParams(e),s={...t,common:{...t.common,issues:[]}},n=this._def.innerType._parse({data:s.data,path:s.path,parent:{...s}});return ye(n)?n.then(a=>({status:"valid",value:a.status==="valid"?a.value:this._def.catchValue({get error(){return new I(s.common.issues)},input:s.data})})):{status:"valid",value:n.status==="valid"?n.value:this._def.catchValue({get error(){return new I(s.common.issues)},input:s.data})}}removeCatch(){return this._def.innerType}};he.create=(r,e)=>new he({innerType:r,typeName:_.ZodCatch,catchValue:typeof e.catch=="function"?e.catch:()=>e.catch,...y(e)});var Se=class extends v{_parse(e){if(this._getType(e)!==h.nan){let s=this._getOrReturnCtx(e);return p(s,{code:u.invalid_type,expected:h.nan,received:s.parsedType}),g}return{status:"valid",value:e.data}}};Se.create=r=>new Se({typeName:_.ZodNaN,...y(r)});var Dr=Symbol("zod_brand"),Ce=class extends v{_parse(e){let{ctx:t}=this._processInputParams(e),s=t.data;return this._def.type._parse({data:s,path:t.path,parent:t})}unwrap(){return this._def.type}},Ie=class r extends v{_parse(e){let{status:t,ctx:s}=this._processInputParams(e);if(s.common.async)return(async()=>{let a=await this._def.in._parseAsync({data:s.data,path:s.path,parent:s});return a.status==="aborted"?g:a.status==="dirty"?(t.dirty(),Q(a.value)):this._def.out._parseAsync({data:a.value,path:s.path,parent:s})})();{let n=this._def.in._parseSync({data:s.data,path:s.path,parent:s});return n.status==="aborted"?g:n.status==="dirty"?(t.dirty(),{status:"dirty",value:n.value}):this._def.out._parseSync({data:n.value,path:s.path,parent:s})}}static create(e,t){return new r({in:e,out:t,typeName:_.ZodPipeline})}},fe=class extends v{_parse(e){let t=this._def.innerType._parse(e),s=n=>(Y(n)&&(n.value=Object.freeze(n.value)),n);return ye(t)?t.then(n=>s(n)):s(t)}unwrap(){return this._def.innerType}};fe.create=(r,e)=>new fe({innerType:r,typeName:_.ZodReadonly,...y(e)});function Lt(r,e){let t=typeof r=="function"?r(e):typeof r=="string"?{message:r}:r;return typeof t=="string"?{message:t}:t}function qt(r,e={},t){return r?G.create().superRefine((s,n)=>{let a=r(s);if(a instanceof Promise)return a.then(c=>{if(!c){let o=Lt(e,s),l=o.fatal??t??!0;n.addIssue({code:"custom",...o,fatal:l})}});if(!a){let c=Lt(e,s),o=c.fatal??t??!0;n.addIssue({code:"custom",...c,fatal:o})}}):G.create()}var Zr={object:A.lazycreate},_;(function(r){r.ZodString="ZodString",r.ZodNumber="ZodNumber",r.ZodNaN="ZodNaN",r.ZodBigInt="ZodBigInt",r.ZodBoolean="ZodBoolean",r.ZodDate="ZodDate",r.ZodSymbol="ZodSymbol",r.ZodUndefined="ZodUndefined",r.ZodNull="ZodNull",r.ZodAny="ZodAny",r.ZodUnknown="ZodUnknown",r.ZodNever="ZodNever",r.ZodVoid="ZodVoid",r.ZodArray="ZodArray",r.ZodObject="ZodObject",r.ZodUnion="ZodUnion",r.ZodDiscriminatedUnion="ZodDiscriminatedUnion",r.ZodIntersection="ZodIntersection",r.ZodTuple="ZodTuple",r.ZodRecord="ZodRecord",r.ZodMap="ZodMap",r.ZodSet="ZodSet",r.ZodFunction="ZodFunction",r.ZodLazy="ZodLazy",r.ZodLiteral="ZodLiteral",r.ZodEnum="ZodEnum",r.ZodEffects="ZodEffects",r.ZodNativeEnum="ZodNativeEnum",r.ZodOptional="ZodOptional",r.ZodNullable="ZodNullable",r.ZodDefault="ZodDefault",r.ZodCatch="ZodCatch",r.ZodPromise="ZodPromise",r.ZodBranded="ZodBranded",r.ZodPipeline="ZodPipeline",r.ZodReadonly="ZodReadonly"})(_||(_={}));var Fr=(r,e={message:`Input not instance of ${r.name}`})=>qt(t=>t instanceof r,e),Dt=K.create,Zt=ee.create,Hr=Se.create,zr=te.create,Ft=re.create,Br=se.create,Jr=xe.create,Wr=ne.create,Yr=ae.create,Kr=G.create,Gr=B.create,Xr=P.create,Qr=be.create,es=J.create,ts=A.create,rs=A.strictCreate,ss=ie.create,ns=Ue.create,as=oe.create,is=q.create,os=qe.create,cs=we.create,ls=ke.create,ds=De.create,us=ce.create,ps=le.create,hs=de.create,fs=ue.create,ms=X.create,gs=L.create,_s=j.create,ys=D.create,vs=L.createWithPreprocess,xs=Ie.create,bs=()=>Dt().optional(),ws=()=>Zt().optional(),ks=()=>Ft().optional(),Ss={string:r=>K.create({...r,coerce:!0}),number:r=>ee.create({...r,coerce:!0}),boolean:r=>re.create({...r,coerce:!0}),bigint:r=>te.create({...r,coerce:!0}),date:r=>se.create({...r,coerce:!0})};var Ts=g;var ft="2024-11-05",Ht=[ft,"2024-10-07"],Ze="2.0",zt=i.union([i.string(),i.number().int()]),Bt=i.string(),M=i.object({_meta:i.optional(i.object({progressToken:i.optional(zt)}).passthrough())}).passthrough(),N=i.object({method:i.string(),params:i.optional(M)}),Ae=i.object({_meta:i.optional(i.object({}).passthrough())}).passthrough(),Z=i.object({method:i.string(),params:i.optional(Ae)}),V=i.object({_meta:i.optional(i.object({}).passthrough())}).passthrough(),Fe=i.union([i.string(),i.number().int()]),Rs=i.object({jsonrpc:i.literal(Ze),id:Fe}).merge(N).strict(),Es=i.object({jsonrpc:i.literal(Ze)}).merge(Z).strict(),Cs=i.object({jsonrpc:i.literal(Ze),id:Fe,result:V}).strict(),me;(function(r){r[r.ConnectionClosed=-1]="ConnectionClosed",r[r.RequestTimeout=-2]="RequestTimeout",r[r.ParseError=-32700]="ParseError",r[r.InvalidRequest=-32600]="InvalidRequest",r[r.MethodNotFound=-32601]="MethodNotFound",r[r.InvalidParams=-32602]="InvalidParams",r[r.InternalError=-32603]="InternalError"})(me||(me={}));var Is=i.object({jsonrpc:i.literal(Ze),id:Fe,error:i.object({code:i.number().int(),message:i.string(),data:i.optional(i.unknown())})}).strict(),Jt=i.union([Rs,Es,Cs,Is]),He=V.strict(),ze=Z.extend({method:i.literal("notifications/cancelled"),params:Ae.extend({requestId:Fe,reason:i.string().optional()})}),Wt=i.object({name:i.string(),version:i.string()}).passthrough(),As=i.object({experimental:i.optional(i.object({}).passthrough()),sampling:i.optional(i.object({}).passthrough()),roots:i.optional(i.object({listChanged:i.optional(i.boolean())}).passthrough())}).passthrough(),mt=N.extend({method:i.literal("initialize"),params:M.extend({protocolVersion:i.string(),capabilities:As,clientInfo:Wt})}),Os=i.object({experimental:i.optional(i.object({}).passthrough()),logging:i.optional(i.object({}).passthrough()),prompts:i.optional(i.object({listChanged:i.optional(i.boolean())}).passthrough()),resources:i.optional(i.object({subscribe:i.optional(i.boolean()),listChanged:i.optional(i.boolean())}).passthrough()),tools:i.optional(i.object({listChanged:i.optional(i.boolean())}).passthrough())}).passthrough(),Ns=V.extend({protocolVersion:i.string(),capabilities:Os,serverInfo:Wt}),gt=Z.extend({method:i.literal("notifications/initialized")}),Be=N.extend({method:i.literal("ping")}),js=i.object({progress:i.number(),total:i.optional(i.number())}).passthrough(),Je=Z.extend({method:i.literal("notifications/progress"),params:Ae.merge(js).extend({progressToken:zt})}),We=N.extend({params:M.extend({cursor:i.optional(Bt)}).optional()}),Ye=V.extend({nextCursor:i.optional(Bt)}),Yt=i.object({uri:i.string(),mimeType:i.optional(i.string())}).passthrough(),Kt=Yt.extend({text:i.string()}),Gt=Yt.extend({blob:i.string().base64()}),$s=i.object({uri:i.string(),name:i.string(),description:i.optional(i.string()),mimeType:i.optional(i.string())}).passthrough(),Ls=i.object({uriTemplate:i.string(),name:i.string(),description:i.optional(i.string()),mimeType:i.optional(i.string())}).passthrough(),Ps=We.extend({method:i.literal("resources/list")}),Ms=Ye.extend({resources:i.array($s)}),Vs=We.extend({method:i.literal("resources/templates/list")}),Us=Ye.extend({resourceTemplates:i.array(Ls)}),qs=N.extend({method:i.literal("resources/read"),params:M.extend({uri:i.string()})}),Ds=V.extend({contents:i.array(i.union([Kt,Gt]))}),Zs=Z.extend({method:i.literal("notifications/resources/list_changed")}),Fs=N.extend({method:i.literal("resources/subscribe"),params:M.extend({uri:i.string()})}),Hs=N.extend({method:i.literal("resources/unsubscribe"),params:M.extend({uri:i.string()})}),zs=Z.extend({method:i.literal("notifications/resources/updated"),params:Ae.extend({uri:i.string()})}),Bs=i.object({name:i.string(),description:i.optional(i.string()),required:i.optional(i.boolean())}).passthrough(),Js=i.object({name:i.string(),description:i.optional(i.string()),arguments:i.optional(i.array(Bs))}).passthrough(),Ws=We.extend({method:i.literal("prompts/list")}),Ys=Ye.extend({prompts:i.array(Js)}),Ks=N.extend({method:i.literal("prompts/get"),params:M.extend({name:i.string(),arguments:i.optional(i.record(i.string()))})}),Ke=i.object({type:i.literal("text"),text:i.string()}).passthrough(),Ge=i.object({type:i.literal("image"),data:i.string().base64(),mimeType:i.string()}).passthrough(),Xt=i.object({type:i.literal("resource"),resource:i.union([Kt,Gt])}).passthrough(),Gs=i.object({role:i.enum(["user","assistant"]),content:i.union([Ke,Ge,Xt])}).passthrough(),Xs=V.extend({description:i.optional(i.string()),messages:i.array(Gs)}),Qs=Z.extend({method:i.literal("notifications/prompts/list_changed")}),en=i.object({name:i.string(),description:i.optional(i.string()),inputSchema:i.object({type:i.literal("object"),properties:i.optional(i.object({}).passthrough())}).passthrough()}).passthrough(),_t=We.extend({method:i.literal("tools/list")}),tn=Ye.extend({tools:i.array(en)}),Qt=V.extend({content:i.array(i.union([Ke,Ge,Xt])),isError:i.boolean().default(!1).optional()}),_a=Qt.or(V.extend({toolResult:i.unknown()})),yt=N.extend({method:i.literal("tools/call"),params:M.extend({name:i.string(),arguments:i.optional(i.record(i.unknown()))})}),rn=Z.extend({method:i.literal("notifications/tools/list_changed")}),er=i.enum(["debug","info","notice","warning","error","critical","alert","emergency"]),sn=N.extend({method:i.literal("logging/setLevel"),params:M.extend({level:er})}),nn=Z.extend({method:i.literal("notifications/message"),params:Ae.extend({level:er,logger:i.optional(i.string()),data:i.unknown()})}),an=i.object({name:i.string().optional()}).passthrough(),on=i.object({hints:i.optional(i.array(an)),costPriority:i.optional(i.number().min(0).max(1)),speedPriority:i.optional(i.number().min(0).max(1)),intelligencePriority:i.optional(i.number().min(0).max(1))}).passthrough(),cn=i.object({role:i.enum(["user","assistant"]),content:i.union([Ke,Ge])}).passthrough(),ln=N.extend({method:i.literal("sampling/createMessage"),params:M.extend({messages:i.array(cn),systemPrompt:i.optional(i.string()),includeContext:i.optional(i.enum(["none","thisServer","allServers"])),temperature:i.optional(i.number()),maxTokens:i.number().int(),stopSequences:i.optional(i.array(i.string())),metadata:i.optional(i.object({}).passthrough()),modelPreferences:i.optional(on)})}),vt=V.extend({model:i.string(),stopReason:i.optional(i.enum(["endTurn","stopSequence","maxTokens"]).or(i.string())),role:i.enum(["user","assistant"]),content:i.discriminatedUnion("type",[Ke,Ge])}),dn=i.object({type:i.literal("ref/resource"),uri:i.string()}).passthrough(),un=i.object({type:i.literal("ref/prompt"),name:i.string()}).passthrough(),pn=N.extend({method:i.literal("completion/complete"),params:M.extend({ref:i.union([un,dn]),argument:i.object({name:i.string(),value:i.string()}).passthrough()})}),hn=V.extend({completion:i.object({values:i.array(i.string()).max(100),total:i.optional(i.number().int()),hasMore:i.optional(i.boolean())}).passthrough()}),fn=i.object({uri:i.string().startsWith("file://"),name:i.optional(i.string())}).passthrough(),mn=N.extend({method:i.literal("roots/list")}),xt=V.extend({roots:i.array(fn)}),gn=Z.extend({method:i.literal("notifications/roots/list_changed")}),ya=i.union([Be,mt,pn,sn,Ks,Ws,Ps,Vs,qs,Fs,Hs,yt,_t]),va=i.union([ze,Je,gt,gn]),xa=i.union([He,vt,xt]),ba=i.union([Be,ln,mn]),wa=i.union([ze,Je,nn,zs,Zs,rn,Qs]),ka=i.union([He,Ns,hn,Xs,Ys,Ms,Us,Ds,Qt,tn]),Te=class extends Error{constructor(e,t,s){super(`MCP error ${e}: ${t}`),this.code=e,this.data=s}};var _n=6e4,Xe=class{constructor(e){this._options=e,this._requestMessageId=0,this._requestHandlers=new Map,this._requestHandlerAbortControllers=new Map,this._notificationHandlers=new Map,this._responseHandlers=new Map,this._progressHandlers=new Map,this.setNotificationHandler(ze,t=>{let s=this._requestHandlerAbortControllers.get(t.params.requestId);s?.abort(t.params.reason)}),this.setNotificationHandler(Je,t=>{this._onprogress(t)}),this.setRequestHandler(Be,t=>({}))}async connect(e){this._transport=e,this._transport.onclose=()=>{this._onclose()},this._transport.onerror=t=>{this._onerror(t)},this._transport.onmessage=t=>{"method"in t?"id"in t?this._onrequest(t):this._onnotification(t):this._onresponse(t)},await this._transport.start()}_onclose(){var e;let t=this._responseHandlers;this._responseHandlers=new Map,this._progressHandlers.clear(),this._transport=void 0,(e=this.onclose)===null||e===void 0||e.call(this);let s=new Te(me.ConnectionClosed,"Connection closed");for(let n of t.values())n(s)}_onerror(e){var t;(t=this.onerror)===null||t===void 0||t.call(this,e)}_onnotification(e){var t;let s=(t=this._notificationHandlers.get(e.method))!==null&&t!==void 0?t:this.fallbackNotificationHandler;s!==void 0&&Promise.resolve().then(()=>s(e)).catch(n=>this._onerror(new Error(`Uncaught error in notification handler: ${n}`)))}_onrequest(e){var t,s;let n=(t=this._requestHandlers.get(e.method))!==null&&t!==void 0?t:this.fallbackRequestHandler;if(n===void 0){(s=this._transport)===null||s===void 0||s.send({jsonrpc:"2.0",id:e.id,error:{code:me.MethodNotFound,message:"Method not found"}}).catch(c=>this._onerror(new Error(`Failed to send an error response: ${c}`)));return}let a=new AbortController;this._requestHandlerAbortControllers.set(e.id,a),Promise.resolve().then(()=>n(e,{signal:a.signal})).then(c=>{var o;if(!a.signal.aborted)return(o=this._transport)===null||o===void 0?void 0:o.send({result:c,jsonrpc:"2.0",id:e.id})},c=>{var o,l;if(!a.signal.aborted)return(o=this._transport)===null||o===void 0?void 0:o.send({jsonrpc:"2.0",id:e.id,error:{code:Number.isSafeInteger(c.code)?c.code:me.InternalError,message:(l=c.message)!==null&&l!==void 0?l:"Internal error"}})}).catch(c=>this._onerror(new Error(`Failed to send response: ${c}`))).finally(()=>{this._requestHandlerAbortControllers.delete(e.id)})}_onprogress(e){let{progress:t,total:s,progressToken:n}=e.params,a=this._progressHandlers.get(Number(n));if(a===void 0){this._onerror(new Error(`Received a progress notification for an unknown token: ${JSON.stringify(e)}`));return}a({progress:t,total:s})}_onresponse(e){let t=e.id,s=this._responseHandlers.get(Number(t));if(s===void 0){this._onerror(new Error(`Received a response for an unknown message ID: ${JSON.stringify(e)}`));return}if(this._responseHandlers.delete(Number(t)),this._progressHandlers.delete(Number(t)),"result"in e)s(e);else{let n=new Te(e.error.code,e.error.message,e.error.data);s(n)}}get transport(){return this._transport}async close(){var e;await((e=this._transport)===null||e===void 0?void 0:e.close())}request(e,t,s){return new Promise((n,a)=>{var c,o,l,d;if(!this._transport){a(new Error("Not connected"));return}((c=this._options)===null||c===void 0?void 0:c.enforceStrictCapabilities)===!0&&this.assertCapabilityForMethod(e.method),(o=s?.signal)===null||o===void 0||o.throwIfAborted();let f=this._requestMessageId++,x={...e,jsonrpc:"2.0",id:f};s?.onprogress&&(this._progressHandlers.set(f,s.onprogress),x.params={...e.params,_meta:{progressToken:f}});let S;this._responseHandlers.set(f,T=>{var C;if(S!==void 0&&clearTimeout(S),!(!((C=s?.signal)===null||C===void 0)&&C.aborted)){if(T instanceof Error)return a(T);try{let F=t.parse(T.result);n(F)}catch(F){a(F)}}});let w=T=>{var C;this._responseHandlers.delete(f),this._progressHandlers.delete(f),(C=this._transport)===null||C===void 0||C.send({jsonrpc:"2.0",method:"cancelled",params:{requestId:f,reason:String(T)}}).catch(F=>this._onerror(new Error(`Failed to send cancellation: ${F}`))),a(T)};(l=s?.signal)===null||l===void 0||l.addEventListener("abort",()=>{var T;S!==void 0&&clearTimeout(S),w((T=s?.signal)===null||T===void 0?void 0:T.reason)});let k=(d=s?.timeout)!==null&&d!==void 0?d:_n;S=setTimeout(()=>w(new Te(me.RequestTimeout,"Request timed out",{timeout:k})),k),this._transport.send(x).catch(T=>{S!==void 0&&clearTimeout(S),a(T)})})}async notification(e){if(!this._transport)throw new Error("Not connected");this.assertNotificationCapability(e.method);let t={...e,jsonrpc:"2.0"};await this._transport.send(t)}setRequestHandler(e,t){let s=e.shape.method.value;this.assertRequestHandlerCapability(s),this._requestHandlers.set(s,(n,a)=>Promise.resolve(t(e.parse(n),a)))}removeRequestHandler(e){this._requestHandlers.delete(e)}setNotificationHandler(e,t){this._notificationHandlers.set(e.shape.method.value,s=>Promise.resolve(t(e.parse(s))))}removeNotificationHandler(e){this._notificationHandlers.delete(e)}};var Qe=class extends Xe{constructor(e,t){super(t),this._serverInfo=e,this._capabilities=t.capabilities,this.setRequestHandler(mt,s=>this._oninitialize(s)),this.setNotificationHandler(gt,()=>{var s;return(s=this.oninitialized)===null||s===void 0?void 0:s.call(this)})}assertCapabilityForMethod(e){var t,s;switch(e){case"sampling/createMessage":if(!(!((t=this._clientCapabilities)===null||t===void 0)&&t.sampling))throw new Error(`Client does not support sampling (required for ${e})`);break;case"roots/list":if(!(!((s=this._clientCapabilities)===null||s===void 0)&&s.roots))throw new Error(`Client does not support listing roots (required for ${e})`);break;case"ping":break}}assertNotificationCapability(e){switch(e){case"notifications/message":if(!this._capabilities.logging)throw new Error(`Server does not support logging (required for ${e})`);break;case"notifications/resources/updated":case"notifications/resources/list_changed":if(!this._capabilities.resources)throw new Error(`Server does not support notifying about resources (required for ${e})`);break;case"notifications/tools/list_changed":if(!this._capabilities.tools)throw new Error(`Server does not support notifying of tool list changes (required for ${e})`);break;case"notifications/prompts/list_changed":if(!this._capabilities.prompts)throw new Error(`Server does not support notifying of prompt list changes (required for ${e})`);break;case"notifications/cancelled":break;case"notifications/progress":break}}assertRequestHandlerCapability(e){switch(e){case"sampling/createMessage":if(!this._capabilities.sampling)throw new Error(`Server does not support sampling (required for ${e})`);break;case"logging/setLevel":if(!this._capabilities.logging)throw new Error(`Server does not support logging (required for ${e})`);break;case"prompts/get":case"prompts/list":if(!this._capabilities.prompts)throw new Error(`Server does not support prompts (required for ${e})`);break;case"resources/list":case"resources/templates/list":case"resources/read":if(!this._capabilities.resources)throw new Error(`Server does not support resources (required for ${e})`);break;case"tools/call":case"tools/list":if(!this._capabilities.tools)throw new Error(`Server does not support tools (required for ${e})`);break;case"ping":case"initialize":break}}async _oninitialize(e){let t=e.params.protocolVersion;return this._clientCapabilities=e.params.capabilities,this._clientVersion=e.params.clientInfo,{protocolVersion:Ht.includes(t)?t:ft,capabilities:this.getCapabilities(),serverInfo:this._serverInfo}}getClientCapabilities(){return this._clientCapabilities}getClientVersion(){return this._clientVersion}getCapabilities(){return this._capabilities}async ping(){return this.request({method:"ping"},He)}async createMessage(e,t){return this.request({method:"sampling/createMessage",params:e},vt,t)}async listRoots(e,t){return this.request({method:"roots/list",params:e},xt,t)}async sendLoggingMessage(e){return this.notification({method:"notifications/message",params:e})}async sendResourceUpdated(e){return this.notification({method:"notifications/resources/updated",params:e})}async sendResourceListChanged(){return this.notification({method:"notifications/resources/list_changed"})}async sendToolListChanged(){return this.notification({method:"notifications/tools/list_changed"})}async sendPromptListChanged(){return this.notification({method:"notifications/prompts/list_changed"})}};import rr from"node:process";var et=class{append(e){this._buffer=this._buffer?Buffer.concat([this._buffer,e]):e}readMessage(){if(!this._buffer)return null;let e=this._buffer.indexOf(` +`);if(e===-1)return null;let t=this._buffer.toString("utf8",0,e);return this._buffer=this._buffer.subarray(e+1),yn(t)}clear(){this._buffer=void 0}};function yn(r){return Jt.parse(JSON.parse(r))}function tr(r){return JSON.stringify(r)+` +`}var tt=class{constructor(e=rr.stdin,t=rr.stdout){this._stdin=e,this._stdout=t,this._readBuffer=new et,this._started=!1,this._ondata=s=>{this._readBuffer.append(s),this.processReadBuffer()},this._onerror=s=>{var n;(n=this.onerror)===null||n===void 0||n.call(this,s)}}async start(){if(this._started)throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror)}processReadBuffer(){for(var e,t;;)try{let s=this._readBuffer.readMessage();if(s===null)break;(e=this.onmessage)===null||e===void 0||e.call(this,s)}catch(s){(t=this.onerror)===null||t===void 0||t.call(this,s)}}async close(){var e;this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._readBuffer.clear(),(e=this.onclose)===null||e===void 0||e.call(this)}send(e){return new Promise(t=>{let s=tr(e);this._stdout.write(s)?t():this._stdout.once("drain",t)})}};var Et={};Nt(Et,{getAgent:()=>nr,getDeploymentStatus:()=>dr,listAgents:()=>sr,listPrimitiveVersions:()=>cr,tailLogs:()=>ur});import{spawn as vn}from"node:child_process";var xn=6e4;function bn(r,{spawnFn:e=vn,timeoutMs:t=xn,label:s="lua"}={}){return new Promise((n,a)=>{let c=e("lua",r,{shell:process.platform==="win32",windowsHide:!0,env:{...process.env,LUA_NO_BANNER:"1",LUA_NO_HINTS:"1"}}),o="",l="";c.stdout.on("data",f=>{o+=f.toString("utf8")}),c.stderr.on("data",f=>{l+=f.toString("utf8")});let d=setTimeout(()=>{c.kill("SIGTERM"),a(new Error(`${s}: 'lua ${r.join(" ")}' timed out after ${t}ms`))},t);c.on("exit",f=>{clearTimeout(d),f!==0?a(new Error(`'lua ${r.join(" ")}' exited ${f}: ${l.trim()}`)):n(o)}),c.on("error",f=>{clearTimeout(d),a(f)})})}function wn(r){let e=r,t=Array.isArray(e)?e:e?.agents??e?.orgs??[];return t.length>0&&t[0]&&Array.isArray(t[0].agents)?t.flatMap(n=>(n.agents??[]).map(a=>({id:a.agentId??a.id??a._id,name:a.name??null,orgId:n.orgId??n.id??n._id??null,orgName:n.name??n.registeredName??null,visibility:a.visibility??null}))):t.map(n=>({id:n.agentId??n.id??n._id,name:n.name??null,orgId:n.orgId??null,orgName:n.orgName??null,visibility:n.visibility??null}))}async function rt({spawnFn:r,label:e="list_agents"}={}){let t=await bn(["agents","--json","--ci"],{spawnFn:r,label:e}),s;try{s=JSON.parse(t)}catch(n){throw new Error(`${e}: could not parse 'lua agents --json' output: ${n.message}`)}return wn(s)}var sr={spec:{name:"list_agents",description:"List all Lua agents the authenticated credential can reach. Returns a compact array of {id, name, orgId, orgName, visibility} flattened across all organisations. Same data as `lua agents --json` \u2014 it resolves every organisation, so on accounts with many orgs this takes 20 s or more; prefer get_agent when you already know the id.",inputSchema:{type:"object",properties:{},required:[]}},async handler(r,e={}){let t=await rt({spawnFn:e.spawnFn,label:"list_agents"});return{content:[{type:"text",text:JSON.stringify(t,null,2)}]}}};var nr={spec:{name:"get_agent",description:"Look up one Lua agent by ID and return {id, name, orgId, orgName, visibility}. For what is live use get_deployment_status / list_primitive_versions; for logs use tail_logs.",inputSchema:{type:"object",properties:{agentId:{type:"string",description:"Agent ID (the `id` field from list_agents; also `agent.agentId` in lua.skill.yaml)"}},required:["agentId"]}},async handler({agentId:r},e={}){if(!r)throw new Error("agentId is required");let s=(await rt({spawnFn:e.spawnFn,label:"get_agent"})).find(n=>n.id===r)??null;if(!s)throw new Error(`get_agent: no agent with id "${r}" found in the authenticated credential's accessible orgs. Run list_agents to see available agents.`);return{content:[{type:"text",text:JSON.stringify(s,null,2)}]}}};import{readFile as bt,readdir as kn,stat as Sn}from"node:fs/promises";import{join as st,dirname as Tn}from"node:path";import{homedir as Rn}from"node:os";var En="https://api.heylua.ai",Cn="https://securetoken.googleapis.com/v1/token",In=15e3,An=6e4,On=["TOKEN_EXPIRED","USER_DISABLED","USER_NOT_FOUND","INVALID_REFRESH_TOKEN","INVALID_GRANT_TYPE","MISSING_REFRESH_TOKEN"],ar=new Map;function Nn(r){for(let e of r.split(/\r?\n/)){let t=e.match(/^\s*(?:export\s+)?LUA_API_KEY\s*=\s*(.*)$/);if(!t)continue;let s=t[1].trim(),n=s.match(/^(['"`])(.*?)\1(?:\s+#.*)?\s*$/);return n?s=n[2]:s=s.replace(/\s+#.*$/,"").trim(),s||null}return null}async function jn({sessionsDir:r,apiUrl:e}){let t;try{t=await kn(r)}catch{return null}let s=[];for(let n of t){if(!n.endsWith(".json")||n.startsWith("."))continue;let a=st(r,n);try{let c=JSON.parse(await bt(a,"utf8"));if(c?.kind!=="firebase-session"||c?.version!==1||typeof c.refreshToken!="string"||!c.refreshToken||typeof c.firebaseWebApiKey!="string"||!c.firebaseWebApiKey||c.apiUrl!==e)continue;let{mtimeMs:o}=await Sn(a);s.push({path:a,session:c,mtimeMs:o})}catch{}}return s.length===0?null:(s.sort((n,a)=>a.mtimeMs-n.mtimeMs),{path:s[0].path,session:s[0].session})}async function $n({path:r,session:e,fetchFn:t=globalThis.fetch,now:s=Date.now}){let n=ar.get(r);if(n&&n.expiresAt-s()>An)return n.idToken;let a=new AbortController,c=setTimeout(()=>a.abort(),In),o;try{o=await t(`${Cn}?key=${encodeURIComponent(e.firebaseWebApiKey)}`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:e.refreshToken}).toString(),signal:a.signal})}catch(x){throw new Error(`MCP_AUTH_UNAVAILABLE: could not refresh the lua-cli session (${x?.name==="AbortError"?"timed out":x.message}). Check your network, or set LUA_API_KEY to bypass the session.`)}finally{clearTimeout(c)}if(!o.ok){let x=o.statusText??String(o.status);try{let k=(await o.json())?.error?.message;typeof k=="string"&&k&&(x=k.split(":")[0].trim())}catch{}let S=o.status<500&&On.find(w=>x.toUpperCase().includes(w));throw S?new Error(`MCP_AUTH_STALE: your lua-cli session was signed out (${S}). Signing out of the Lua dashboard, desktop or mobile app also ends CLI sessions. Run \`lua auth configure\` in a terminal to sign in again.`):new Error(`MCP_AUTH_UNAVAILABLE: lua-cli session refresh failed (${o.status} ${x}). Retry in a moment.`)}let l=await o.json(),d=l?.id_token,f=Number(l?.expires_in);if(typeof d!="string"||!d||!Number.isFinite(f)||f<=0)throw new Error("MCP_AUTH_UNAVAILABLE: the session refresh returned an invalid token. Run `lua auth configure` again.");return ar.set(r,{idToken:d,expiresAt:s()+f*1e3}),d}async function ir({env:r=process.env,credentialsPath:e=r.LUA_CREDENTIALS_PATH??st(Rn(),".lua-cli","credentials"),sessionsDir:t=r.LUA_SESSIONS_DIR??st(Tn(e),"sessions"),cwd:s=process.cwd(),apiUrl:n=r.LUA_API_URL||En,fetchFn:a=globalThis.fetch,now:c=Date.now}={}){if(r.LUA_API_KEY&&r.LUA_API_KEY.trim())return r.LUA_API_KEY.trim();try{let l=Nn(await bt(st(s,".env"),"utf8"));if(l)return l}catch{}let o=await jn({sessionsDir:t,apiUrl:n});if(o)return $n({...o,fetchFn:a,now:c});try{let l=(await bt(e,"utf8")).trim();if(l){if(l.startsWith("{"))try{let d=JSON.parse(l);if(d?.apiKey)return d.apiKey}catch{}return l}}catch{}throw new Error("MCP_AUTH_STALE: No lua-cli credentials found in LUA_API_KEY, .env, ~/.lua-cli/sessions, or ~/.lua-cli/credentials. Run `lua auth configure` in a terminal (or /lua-auth in Claude Code).")}var Ln="https://api.heylua.ai",Pn=1e4,Ba=Object.freeze({skills:"automations:read",webhooks:"automations:read",jobs:"automations:read",triggers:"automations:read",preprocessors:"automations:read",postprocessors:"automations:read",workflows:"workflows:read",persona:"agents:read",logs:"knowledge:read"}),Mn="skills/webhooks/jobs/triggers/preprocessors/postprocessors need automations:read, workflows need workflows:read, persona needs agents:read, logs need knowledge:read";async function ge(r,{method:e="GET",body:t,query:s,fetchFn:n=globalThis.fetch,baseUrl:a=process.env.LUA_API_URL||Ln,timeoutMs:c=Pn}={}){let o=await ir(),l=new URL(a.replace(/\/$/,"")+r);if(s)for(let[x,S]of Object.entries(s))l.searchParams.set(x,String(S));let d=new AbortController,f=setTimeout(()=>d.abort(),c);try{let x=await n(l.toString(),{method:e,headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json","X-Lua-Client":"claude-plugin/1.6.0"},body:t?JSON.stringify(t):void 0,signal:d.signal});if(x.status===401)throw new Error("MCP_AUTH_STALE: lua-api returned 401. The credential is missing, expired, or the session was signed out (signing out of the Lua dashboard or apps also ends CLI sessions). Run `lua auth configure` in a terminal, or re-run /lua-doctor.");if(x.status===403)throw new Error(`MCP_FORBIDDEN: lua-api returned 403 for ${r}. The credential cannot access this agent or org, or it lacks the route scope (${Mn} \u2014 typed keys are scoped to the agents and role chosen at \`lua auth configure\`). Re-run /lua-doctor or check the LUA_API_KEY env var.`);if(!x.ok){let S=await x.text(),w=S;try{let k=JSON.parse(S);w=k?.error?.message??k?.message??S;let T=k?.error?.code;typeof T=="string"&&T&&!String(w).includes(T)&&(w=`${T}: ${w}`)}catch{}throw new Error(`lua-api ${x.status}: ${w}`)}return await x.json()}catch(x){throw x.name==="AbortError"?new Error(`MCP_TIMEOUT: ${r} did not respond in ${c}ms`):x}finally{clearTimeout(f)}}var wt={skill:r=>r?.skills??[],webhook:r=>r?.data?.webhooks??[],job:r=>r?.data?.jobs??[],trigger:r=>r?.data?.triggers??[],preprocessor:r=>r?.data?.preprocessors??[],postprocessor:r=>r?.data?.postprocessors??[],workflow:r=>r?.data?.workflows??[]},kt={skill:r=>r?.versions??[],webhook:r=>r?.data?.versions??[],job:r=>Array.isArray(r?.data)?r.data:[],trigger:r=>r?.data?.versions??[],preprocessor:r=>r?.data?.versions??[],postprocessor:r=>r?.data?.versions??[],workflow:r=>Array.isArray(r?.data)?r.data:[],persona:r=>r?.versions??[]},Re={skill:"skills",webhook:"webhooks",job:"jobs",trigger:"triggers",preprocessor:"preprocessors",postprocessor:"postprocessors",workflow:"workflows"};function nt(r,e){let t=wt[r];if(!t)throw new Error(`extractList: unknown primitive type "${r}". Valid: ${Object.keys(wt).join(", ")}`);return t(e)}function Oe(r,e){let t=kt[r];if(!t)throw new Error(`extractVersions: unknown primitive type "${r}". Valid: ${Object.keys(kt).join(", ")}`);return t(e)}function Ne(r){let e=r?.data?.activeVersionId;return typeof e=="string"&&e?e:null}function je(r,e,t){if(!e||typeof e!="object")return!1;switch(r){case"skill":case"persona":return e.isCurrent===!0;case"job":case"workflow":return e.active===!0;case"webhook":case"trigger":case"preprocessor":case"postprocessor":{if(e.isActive===!0)return!0;let s=Ne(t),n=e.versionId??e.id??null;return!!s&&n===s}default:return!1}}function $e(r){if(!r||typeof r!="object")return null;let e=r.createdAt??r.createdDate??null;return e==null?null:typeof e=="number"?Number.isFinite(e)?new Date(e).toISOString():null:String(e)}function at(r){return!r||typeof r!="object"?null:r.versionId??r.id??null}var Wa=Object.keys(wt),or=Object.keys(kt);var St=new Set(or),cr={spec:{name:"list_primitive_versions",description:"List the server-side versions of one primitive (skill, webhook, job, trigger, preprocessor, postprocessor, workflow) or the agent persona. Returns { activeVersionId, versions: [{version, versionId, active, createdAt}] } \u2014 `active` is the version currently live. `versionId` is null for types whose versions route carries no per-entry id: skill, persona and webhook (the webhook route exposes the row id only under a misnamed `webhookId` key). For those, identify a version by `version`; for webhooks the live row id is the top-level `activeVersionId`. `activeVersionId` is populated only for webhook, trigger, preprocessor and postprocessor envelopes and is null for skill, job, workflow and persona.",inputSchema:{type:"object",properties:{agentId:{type:"string"},type:{type:"string",enum:[...St]},name:{type:"string",description:"Primitive name as written in lua.skill.yaml (omit for persona \u2014 an agent has only one)"}},required:["agentId","type"]}},async handler({agentId:r,type:e,name:t},s={}){if(!r||!e)throw new Error("agentId and type are required");if(!St.has(e))throw new Error(`Invalid type: ${e}. Valid: ${[...St].join(", ")}`);if(e!=="persona"&&!t)throw new Error("name is required for all types except persona");let n;if(e==="persona")n=`/developer/agents/${encodeURIComponent(r)}/persona/versions`;else{let d=await Vn({agentId:r,type:e,name:t,fetchFn:s.fetchFn});n=`/developer/${Re[e]}/${encodeURIComponent(r)}/${encodeURIComponent(d)}/versions`}let a=await ge(n,{fetchFn:s.fetchFn}),o=Oe(e,a).map(d=>({version:d.version,versionId:at(d),active:je(e,d,a),createdAt:$e(d)})),l={agentId:r,type:e,name:e==="persona"?null:t,activeVersionId:Ne(a),versions:o};return{content:[{type:"text",text:JSON.stringify(l,null,2)}]}}};async function Vn({agentId:r,type:e,name:t,fetchFn:s}){let n=`/developer/${Re[e]}/${encodeURIComponent(r)}`,a=await ge(n,{fetchFn:s}),c=nt(e,a),o=c.find(d=>d.name===t);if(!o){let d=c.map(f=>f.name).filter(Boolean).join(", ")||"(none)";throw new Error(`list_primitive_versions: no ${e} named "${t}" on agent ${r}. Available: ${d}`)}let l=o.id??o._id;if(!l)throw new Error(`list_primitive_versions: ${e} "${t}" exists but has no id field`);return l}var it=["skill","webhook","job","trigger","preprocessor","postprocessor","workflow"],lr=5,Un=45e3,dr={spec:{name:"get_deployment_status",description:'What is live right now for an agent: for every skill, webhook, job, trigger, preprocessor, postprocessor and workflow the active (deployed) version, plus the active persona version. Composed from the per-type lua-api version routes (list calls in parallel, then per-item version lookups in chunks of 5). Bounded by a 45 s wall-clock budget: if exceeded, remaining items are listed with `error: "skipped: \u2026"` and the result carries `partial: true` + `partialReason`. Inside a project, `lua status --json` additionally compares local vs deployed.',inputSchema:{type:"object",properties:{agentId:{type:"string"}},required:["agentId"]}},async handler({agentId:r},e={}){if(!r)throw new Error("agentId is required");let t=encodeURIComponent(r),s=Number.isFinite(e.budgetMs)?e.budgetMs:Un,n=Date.now(),a=()=>Date.now()-n>s,c=w=>ge(w,{fetchFn:e.fetchFn}),o={agentId:r,persona:null,primitives:{}};for(let w of it)o.primitives[w]=[];let[l,...d]=await Promise.allSettled([c(`/developer/agents/${t}/persona/versions`),...it.map(w=>c(`/developer/${Re[w]}/${t}`))]);if(l.status==="fulfilled"){let w=l.value,k=Oe("persona",w),T=k.find(C=>je("persona",C,w))??null;o.persona={activeVersion:T?.version??null,activeVersionCreatedAt:$e(T),versionCount:k.length}}else o.persona={error:l.reason?.message??String(l.reason)};let f=!1,x=0,S=0;for(let w=0;w({p:O,primId:O.id??O._id,name:O.name??O.id??O._id})).filter(O=>O.primId);S+=F.length;for(let O=0;Oc(`/developer/${T}/${t}/${encodeURIComponent(W)}/versions`)))).forEach((W,ot)=>{let{p:Pe,primId:It,name:At}=Le[ot];if(W.status!=="fulfilled"){o.primitives[k].push({name:At,id:It,error:W.reason?.message??String(W.reason)});return}let ct=W.value,Ot=Oe(k,ct),lt=Ot.find(fr=>je(k,fr,ct))??null,dt={name:At,id:It,activeVersion:lt?.version??null,activeVersionId:at(lt)??Ne(ct),activeVersionCreatedAt:$e(lt),versionCount:Ot.length};typeof Pe.active=="boolean"&&(dt.enabled=Pe.active),k==="workflow"&&typeof Pe.dynamic=="boolean"&&(dt.dynamic=Pe.dynamic),o.primitives[k].push(dt)})}}return x>0&&(o.partial=!0,o.partialReason=`Wall-clock budget of ${s}ms exceeded after ${Date.now()-n}ms; ${x} of ${S} version lookups were not issued (entries carry error: "skipped: \u2026").`),{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}};var qn=["skill","job","webhook","trigger","preprocessor","postprocessor","user_message","agent_response","agent_error","runtime","mcp","rag","device","device-trigger","model-resolver","workflow-step","workflow-script","workflow"],Rt=["error","warn","info","debug","start","complete"],Tt=new Set(["all",...qn]),Dn=new Set(Rt),ur={spec:{name:"tail_logs",description:"Fetch recent execution logs for an agent (same data as `lua logs --json`). Returns { logs: LogEntry[], pagination }. Each LogEntry has `subType` (error | warn | info | debug | start | complete), `message`, `timestamp`, and `metadata.logSource` / `metadata.primitiveName` \u2014 there is NO `level` field. Filter by source (`type`), primitive (`name`) and/or severity (`logType`, which filters on `subType`).",inputSchema:{type:"object",properties:{agentId:{type:"string"},type:{type:"string",enum:[...Tt],default:"all",description:"Log source filter (maps to lua-api `logSource`). `all` = no filter."},name:{type:"string",description:"Filter by primitive name (optional; maps to `primitiveName`)"},logType:{type:"string",enum:Rt,description:"Filter by LogEntry `subType` (optional; maps to lua-api `logType`). Omit for every severity. e.g. `error` to see only failures."},limit:{type:"number",default:50,minimum:1,maximum:100},page:{type:"number",minimum:1,description:"Page number for pagination (optional)"}},required:["agentId"]}},async handler({agentId:r,type:e="all",name:t,logType:s,limit:n=50,page:a},c={}){if(!r)throw new Error("agentId is required");if(!Tt.has(e))throw new Error(`Invalid type: ${e}. Valid: ${[...Tt].join(", ")}`);if(s!==void 0&&!Dn.has(s))throw new Error(`Invalid logType: ${s}. Valid: ${Rt.join(", ")}`);if(n>100)throw new Error(`Invalid limit: ${n}. lua-api caps logs at 100 entries per call.`);let o={limit:n};e!=="all"&&(o.logSource=e),t&&(o.primitiveName=t),s&&(o.logType=s),a&&(o.page=a);let l=await ge(`/developer/agents/${encodeURIComponent(r)}/logs`,{query:o,fetchFn:c.fetchFn});return{content:[{type:"text",text:JSON.stringify(l,null,2)}]}}};var pr=Object.values(Et),Ct=new Qe({name:"lua-platform",version:"1.6.0"},{capabilities:{tools:{}}});Ct.setRequestHandler(_t,async()=>({tools:pr.map(r=>r.spec)}));Ct.setRequestHandler(yt,async r=>{let e=pr.find(t=>t.spec.name===r.params.name);if(!e)throw new Error(`Unknown tool: ${r.params.name}`);try{return await e.handler(r.params.arguments??{})}catch(t){return{content:[{type:"text",text:`Error: ${t.message}`}],isError:!0}}});function hr(r){process.stderr.write(JSON.stringify(r)+` +`,()=>process.exit(1))}process.on("uncaughtException",r=>{hr({event:"mcp_server_crash",kind:"uncaughtException",message:r?.message,stack:r?.stack,plugin_version:"1.6.0",lua_cli_version:process.env.LUA_CLI_VERSION??null,platform:process.platform,ts:new Date().toISOString()})});process.on("unhandledRejection",r=>{hr({event:"mcp_server_crash",kind:"unhandledRejection",reason:String(r),stack:r?.stack,plugin_version:"1.6.0",lua_cli_version:process.env.LUA_CLI_VERSION??null,platform:process.platform,ts:new Date().toISOString()})});await Ct.connect(new tt); +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vbm9kZV9tb2R1bGVzL3pvZC92My9leHRlcm5hbC5qcyIsICIuLi9ub2RlX21vZHVsZXMvem9kL3YzL2hlbHBlcnMvdXRpbC5qcyIsICIuLi9ub2RlX21vZHVsZXMvem9kL3YzL1pvZEVycm9yLmpzIiwgIi4uL25vZGVfbW9kdWxlcy96b2QvdjMvbG9jYWxlcy9lbi5qcyIsICIuLi9ub2RlX21vZHVsZXMvem9kL3YzL2Vycm9ycy5qcyIsICIuLi9ub2RlX21vZHVsZXMvem9kL3YzL2hlbHBlcnMvcGFyc2VVdGlsLmpzIiwgIi4uL25vZGVfbW9kdWxlcy96b2QvdjMvaGVscGVycy9lcnJvclV0aWwuanMiLCAiLi4vbm9kZV9tb2R1bGVzL3pvZC92My90eXBlcy5qcyIsICIuLi9ub2RlX21vZHVsZXMvQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zcmMvdHlwZXMudHMiLCAiLi4vbm9kZV9tb2R1bGVzL0Btb2RlbGNvbnRleHRwcm90b2NvbC9zZGsvc3JjL3NoYXJlZC9wcm90b2NvbC50cyIsICIuLi9ub2RlX21vZHVsZXMvQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zcmMvc2VydmVyL2luZGV4LnRzIiwgIi4uL25vZGVfbW9kdWxlcy9AbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NyYy9zZXJ2ZXIvc3RkaW8udHMiLCAiLi4vbm9kZV9tb2R1bGVzL0Btb2RlbGNvbnRleHRwcm90b2NvbC9zZGsvc3JjL3NoYXJlZC9zdGRpby50cyIsICIuLi9zcmMvdG9vbHMvaW5kZXgubWpzIiwgIi4uL3NyYy9ydW4tbHVhLm1qcyIsICIuLi9zcmMvdG9vbHMvbGlzdC1hZ2VudHMubWpzIiwgIi4uL3NyYy90b29scy9nZXQtYWdlbnQubWpzIiwgIi4uL3NyYy9hdXRoLm1qcyIsICIuLi9zcmMvYXBpLWNsaWVudC5tanMiLCAiLi4vc3JjL3Jlc3BvbnNlLXNoYXBlcy5tanMiLCAiLi4vc3JjL3Rvb2xzL2xpc3QtcHJpbWl0aXZlLXZlcnNpb25zLm1qcyIsICIuLi9zcmMvdG9vbHMvZ2V0LWRlcGxveW1lbnQtc3RhdHVzLm1qcyIsICIuLi9zcmMvdG9vbHMvdGFpbC1sb2dzLm1qcyIsICIuLi9zcmMvc2VydmVyLm1qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiZXhwb3J0ICogZnJvbSBcIi4vZXJyb3JzLmpzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9oZWxwZXJzL3BhcnNlVXRpbC5qc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vaGVscGVycy90eXBlQWxpYXNlcy5qc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vaGVscGVycy91dGlsLmpzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi90eXBlcy5qc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vWm9kRXJyb3IuanNcIjtcbiIsICJleHBvcnQgdmFyIHV0aWw7XG4oZnVuY3Rpb24gKHV0aWwpIHtcbiAgICB1dGlsLmFzc2VydEVxdWFsID0gKF8pID0+IHsgfTtcbiAgICBmdW5jdGlvbiBhc3NlcnRJcyhfYXJnKSB7IH1cbiAgICB1dGlsLmFzc2VydElzID0gYXNzZXJ0SXM7XG4gICAgZnVuY3Rpb24gYXNzZXJ0TmV2ZXIoX3gpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gICAgfVxuICAgIHV0aWwuYXNzZXJ0TmV2ZXIgPSBhc3NlcnROZXZlcjtcbiAgICB1dGlsLmFycmF5VG9FbnVtID0gKGl0ZW1zKSA9PiB7XG4gICAgICAgIGNvbnN0IG9iaiA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHtcbiAgICAgICAgICAgIG9ialtpdGVtXSA9IGl0ZW07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9iajtcbiAgICB9O1xuICAgIHV0aWwuZ2V0VmFsaWRFbnVtVmFsdWVzID0gKG9iaikgPT4ge1xuICAgICAgICBjb25zdCB2YWxpZEtleXMgPSB1dGlsLm9iamVjdEtleXMob2JqKS5maWx0ZXIoKGspID0+IHR5cGVvZiBvYmpbb2JqW2tdXSAhPT0gXCJudW1iZXJcIik7XG4gICAgICAgIGNvbnN0IGZpbHRlcmVkID0ge307XG4gICAgICAgIGZvciAoY29uc3QgayBvZiB2YWxpZEtleXMpIHtcbiAgICAgICAgICAgIGZpbHRlcmVkW2tdID0gb2JqW2tdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1dGlsLm9iamVjdFZhbHVlcyhmaWx0ZXJlZCk7XG4gICAgfTtcbiAgICB1dGlsLm9iamVjdFZhbHVlcyA9IChvYmopID0+IHtcbiAgICAgICAgcmV0dXJuIHV0aWwub2JqZWN0S2V5cyhvYmopLm1hcChmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIG9ialtlXTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICB1dGlsLm9iamVjdEtleXMgPSB0eXBlb2YgT2JqZWN0LmtleXMgPT09IFwiZnVuY3Rpb25cIiAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGJhbi9iYW5cbiAgICAgICAgPyAob2JqKSA9PiBPYmplY3Qua2V5cyhvYmopIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgYmFuL2JhblxuICAgICAgICA6IChvYmplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGtleXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIG9iamVjdCkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleXMucHVzaChrZXkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBrZXlzO1xuICAgICAgICB9O1xuICAgIHV0aWwuZmluZCA9IChhcnIsIGNoZWNrZXIpID0+IHtcbiAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIGFycikge1xuICAgICAgICAgICAgaWYgKGNoZWNrZXIoaXRlbSkpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9O1xuICAgIHV0aWwuaXNJbnRlZ2VyID0gdHlwZW9mIE51bWJlci5pc0ludGVnZXIgPT09IFwiZnVuY3Rpb25cIlxuICAgICAgICA/ICh2YWwpID0+IE51bWJlci5pc0ludGVnZXIodmFsKSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGJhbi9iYW5cbiAgICAgICAgOiAodmFsKSA9PiB0eXBlb2YgdmFsID09PSBcIm51bWJlclwiICYmIE51bWJlci5pc0Zpbml0ZSh2YWwpICYmIE1hdGguZmxvb3IodmFsKSA9PT0gdmFsO1xuICAgIGZ1bmN0aW9uIGpvaW5WYWx1ZXMoYXJyYXksIHNlcGFyYXRvciA9IFwiIHwgXCIpIHtcbiAgICAgICAgcmV0dXJuIGFycmF5Lm1hcCgodmFsKSA9PiAodHlwZW9mIHZhbCA9PT0gXCJzdHJpbmdcIiA/IGAnJHt2YWx9J2AgOiB2YWwpKS5qb2luKHNlcGFyYXRvcik7XG4gICAgfVxuICAgIHV0aWwuam9pblZhbHVlcyA9IGpvaW5WYWx1ZXM7XG4gICAgdXRpbC5qc29uU3RyaW5naWZ5UmVwbGFjZXIgPSAoXywgdmFsdWUpID0+IHtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJiaWdpbnRcIikge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH07XG59KSh1dGlsIHx8ICh1dGlsID0ge30pKTtcbmV4cG9ydCB2YXIgb2JqZWN0VXRpbDtcbihmdW5jdGlvbiAob2JqZWN0VXRpbCkge1xuICAgIG9iamVjdFV0aWwubWVyZ2VTaGFwZXMgPSAoZmlyc3QsIHNlY29uZCkgPT4ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4uZmlyc3QsXG4gICAgICAgICAgICAuLi5zZWNvbmQsIC8vIHNlY29uZCBvdmVyd3JpdGVzIGZpcnN0XG4gICAgICAgIH07XG4gICAgfTtcbn0pKG9iamVjdFV0aWwgfHwgKG9iamVjdFV0aWwgPSB7fSkpO1xuZXhwb3J0IGNvbnN0IFpvZFBhcnNlZFR5cGUgPSB1dGlsLmFycmF5VG9FbnVtKFtcbiAgICBcInN0cmluZ1wiLFxuICAgIFwibmFuXCIsXG4gICAgXCJudW1iZXJcIixcbiAgICBcImludGVnZXJcIixcbiAgICBcImZsb2F0XCIsXG4gICAgXCJib29sZWFuXCIsXG4gICAgXCJkYXRlXCIsXG4gICAgXCJiaWdpbnRcIixcbiAgICBcInN5bWJvbFwiLFxuICAgIFwiZnVuY3Rpb25cIixcbiAgICBcInVuZGVmaW5lZFwiLFxuICAgIFwibnVsbFwiLFxuICAgIFwiYXJyYXlcIixcbiAgICBcIm9iamVjdFwiLFxuICAgIFwidW5rbm93blwiLFxuICAgIFwicHJvbWlzZVwiLFxuICAgIFwidm9pZFwiLFxuICAgIFwibmV2ZXJcIixcbiAgICBcIm1hcFwiLFxuICAgIFwic2V0XCIsXG5dKTtcbmV4cG9ydCBjb25zdCBnZXRQYXJzZWRUeXBlID0gKGRhdGEpID0+IHtcbiAgICBjb25zdCB0ID0gdHlwZW9mIGRhdGE7XG4gICAgc3dpdGNoICh0KSB7XG4gICAgICAgIGNhc2UgXCJ1bmRlZmluZWRcIjpcbiAgICAgICAgICAgIHJldHVybiBab2RQYXJzZWRUeXBlLnVuZGVmaW5lZDtcbiAgICAgICAgY2FzZSBcInN0cmluZ1wiOlxuICAgICAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuc3RyaW5nO1xuICAgICAgICBjYXNlIFwibnVtYmVyXCI6XG4gICAgICAgICAgICByZXR1cm4gTnVtYmVyLmlzTmFOKGRhdGEpID8gWm9kUGFyc2VkVHlwZS5uYW4gOiBab2RQYXJzZWRUeXBlLm51bWJlcjtcbiAgICAgICAgY2FzZSBcImJvb2xlYW5cIjpcbiAgICAgICAgICAgIHJldHVybiBab2RQYXJzZWRUeXBlLmJvb2xlYW47XG4gICAgICAgIGNhc2UgXCJmdW5jdGlvblwiOlxuICAgICAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuZnVuY3Rpb247XG4gICAgICAgIGNhc2UgXCJiaWdpbnRcIjpcbiAgICAgICAgICAgIHJldHVybiBab2RQYXJzZWRUeXBlLmJpZ2ludDtcbiAgICAgICAgY2FzZSBcInN5bWJvbFwiOlxuICAgICAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuc3ltYm9sO1xuICAgICAgICBjYXNlIFwib2JqZWN0XCI6XG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBab2RQYXJzZWRUeXBlLmFycmF5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRhdGEgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5udWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRhdGEudGhlbiAmJiB0eXBlb2YgZGF0YS50aGVuID09PSBcImZ1bmN0aW9uXCIgJiYgZGF0YS5jYXRjaCAmJiB0eXBlb2YgZGF0YS5jYXRjaCA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUucHJvbWlzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgTWFwICE9PSBcInVuZGVmaW5lZFwiICYmIGRhdGEgaW5zdGFuY2VvZiBNYXApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5tYXA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIFNldCAhPT0gXCJ1bmRlZmluZWRcIiAmJiBkYXRhIGluc3RhbmNlb2YgU2V0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuc2V0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBEYXRlICE9PSBcInVuZGVmaW5lZFwiICYmIGRhdGEgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuZGF0ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBab2RQYXJzZWRUeXBlLm9iamVjdDtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBab2RQYXJzZWRUeXBlLnVua25vd247XG4gICAgfVxufTtcbiIsICJpbXBvcnQgeyB1dGlsIH0gZnJvbSBcIi4vaGVscGVycy91dGlsLmpzXCI7XG5leHBvcnQgY29uc3QgWm9kSXNzdWVDb2RlID0gdXRpbC5hcnJheVRvRW51bShbXG4gICAgXCJpbnZhbGlkX3R5cGVcIixcbiAgICBcImludmFsaWRfbGl0ZXJhbFwiLFxuICAgIFwiY3VzdG9tXCIsXG4gICAgXCJpbnZhbGlkX3VuaW9uXCIsXG4gICAgXCJpbnZhbGlkX3VuaW9uX2Rpc2NyaW1pbmF0b3JcIixcbiAgICBcImludmFsaWRfZW51bV92YWx1ZVwiLFxuICAgIFwidW5yZWNvZ25pemVkX2tleXNcIixcbiAgICBcImludmFsaWRfYXJndW1lbnRzXCIsXG4gICAgXCJpbnZhbGlkX3JldHVybl90eXBlXCIsXG4gICAgXCJpbnZhbGlkX2RhdGVcIixcbiAgICBcImludmFsaWRfc3RyaW5nXCIsXG4gICAgXCJ0b29fc21hbGxcIixcbiAgICBcInRvb19iaWdcIixcbiAgICBcImludmFsaWRfaW50ZXJzZWN0aW9uX3R5cGVzXCIsXG4gICAgXCJub3RfbXVsdGlwbGVfb2ZcIixcbiAgICBcIm5vdF9maW5pdGVcIixcbl0pO1xuZXhwb3J0IGNvbnN0IHF1b3RlbGVzc0pzb24gPSAob2JqKSA9PiB7XG4gICAgY29uc3QganNvbiA9IEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgMik7XG4gICAgcmV0dXJuIGpzb24ucmVwbGFjZSgvXCIoW15cIl0rKVwiOi9nLCBcIiQxOlwiKTtcbn07XG5leHBvcnQgY2xhc3MgWm9kRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gICAgZ2V0IGVycm9ycygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNzdWVzO1xuICAgIH1cbiAgICBjb25zdHJ1Y3Rvcihpc3N1ZXMpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5pc3N1ZXMgPSBbXTtcbiAgICAgICAgdGhpcy5hZGRJc3N1ZSA9IChzdWIpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaXNzdWVzID0gWy4uLnRoaXMuaXNzdWVzLCBzdWJdO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmFkZElzc3VlcyA9IChzdWJzID0gW10pID0+IHtcbiAgICAgICAgICAgIHRoaXMuaXNzdWVzID0gWy4uLnRoaXMuaXNzdWVzLCAuLi5zdWJzXTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgYWN0dWFsUHJvdG8gPSBuZXcudGFyZ2V0LnByb3RvdHlwZTtcbiAgICAgICAgaWYgKE9iamVjdC5zZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGJhbi9iYW5cbiAgICAgICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBhY3R1YWxQcm90byk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9fcHJvdG9fXyA9IGFjdHVhbFByb3RvO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubmFtZSA9IFwiWm9kRXJyb3JcIjtcbiAgICAgICAgdGhpcy5pc3N1ZXMgPSBpc3N1ZXM7XG4gICAgfVxuICAgIGZvcm1hdChfbWFwcGVyKSB7XG4gICAgICAgIGNvbnN0IG1hcHBlciA9IF9tYXBwZXIgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChpc3N1ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc3N1ZS5tZXNzYWdlO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgY29uc3QgZmllbGRFcnJvcnMgPSB7IF9lcnJvcnM6IFtdIH07XG4gICAgICAgIGNvbnN0IHByb2Nlc3NFcnJvciA9IChlcnJvcikgPT4ge1xuICAgICAgICAgICAgZm9yIChjb25zdCBpc3N1ZSBvZiBlcnJvci5pc3N1ZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNzdWUuY29kZSA9PT0gXCJpbnZhbGlkX3VuaW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNzdWUudW5pb25FcnJvcnMubWFwKHByb2Nlc3NFcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGlzc3VlLmNvZGUgPT09IFwiaW52YWxpZF9yZXR1cm5fdHlwZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NFcnJvcihpc3N1ZS5yZXR1cm5UeXBlRXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChpc3N1ZS5jb2RlID09PSBcImludmFsaWRfYXJndW1lbnRzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc0Vycm9yKGlzc3VlLmFyZ3VtZW50c0Vycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoaXNzdWUucGF0aC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgZmllbGRFcnJvcnMuX2Vycm9ycy5wdXNoKG1hcHBlcihpc3N1ZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGN1cnIgPSBmaWVsZEVycm9ycztcbiAgICAgICAgICAgICAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaSA8IGlzc3VlLnBhdGgubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlbCA9IGlzc3VlLnBhdGhbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXJtaW5hbCA9IGkgPT09IGlzc3VlLnBhdGgubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGVybWluYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyW2VsXSA9IGN1cnJbZWxdIHx8IHsgX2Vycm9yczogW10gfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiAodHlwZW9mIGVsID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gICBjdXJyW2VsXSA9IGN1cnJbZWxdIHx8IHsgX2Vycm9yczogW10gfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB9IGVsc2UgaWYgKHR5cGVvZiBlbCA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgY29uc3QgZXJyb3JBcnJheTogYW55ID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gICBlcnJvckFycmF5Ll9lcnJvcnMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAgIGN1cnJbZWxdID0gY3VycltlbF0gfHwgZXJyb3JBcnJheTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyW2VsXSA9IGN1cnJbZWxdIHx8IHsgX2Vycm9yczogW10gfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyW2VsXS5fZXJyb3JzLnB1c2gobWFwcGVyKGlzc3VlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyID0gY3VycltlbF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHByb2Nlc3NFcnJvcih0aGlzKTtcbiAgICAgICAgcmV0dXJuIGZpZWxkRXJyb3JzO1xuICAgIH1cbiAgICBzdGF0aWMgYXNzZXJ0KHZhbHVlKSB7XG4gICAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgWm9kRXJyb3IpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vdCBhIFpvZEVycm9yOiAke3ZhbHVlfWApO1xuICAgICAgICB9XG4gICAgfVxuICAgIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlO1xuICAgIH1cbiAgICBnZXQgbWVzc2FnZSgpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHRoaXMuaXNzdWVzLCB1dGlsLmpzb25TdHJpbmdpZnlSZXBsYWNlciwgMik7XG4gICAgfVxuICAgIGdldCBpc0VtcHR5KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc3N1ZXMubGVuZ3RoID09PSAwO1xuICAgIH1cbiAgICBmbGF0dGVuKG1hcHBlciA9IChpc3N1ZSkgPT4gaXNzdWUubWVzc2FnZSkge1xuICAgICAgICBjb25zdCBmaWVsZEVycm9ycyA9IHt9O1xuICAgICAgICBjb25zdCBmb3JtRXJyb3JzID0gW107XG4gICAgICAgIGZvciAoY29uc3Qgc3ViIG9mIHRoaXMuaXNzdWVzKSB7XG4gICAgICAgICAgICBpZiAoc3ViLnBhdGgubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpcnN0RWwgPSBzdWIucGF0aFswXTtcbiAgICAgICAgICAgICAgICBmaWVsZEVycm9yc1tmaXJzdEVsXSA9IGZpZWxkRXJyb3JzW2ZpcnN0RWxdIHx8IFtdO1xuICAgICAgICAgICAgICAgIGZpZWxkRXJyb3JzW2ZpcnN0RWxdLnB1c2gobWFwcGVyKHN1YikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZm9ybUVycm9ycy5wdXNoKG1hcHBlcihzdWIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBmb3JtRXJyb3JzLCBmaWVsZEVycm9ycyB9O1xuICAgIH1cbiAgICBnZXQgZm9ybUVycm9ycygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZmxhdHRlbigpO1xuICAgIH1cbn1cblpvZEVycm9yLmNyZWF0ZSA9IChpc3N1ZXMpID0+IHtcbiAgICBjb25zdCBlcnJvciA9IG5ldyBab2RFcnJvcihpc3N1ZXMpO1xuICAgIHJldHVybiBlcnJvcjtcbn07XG4iLCAiaW1wb3J0IHsgWm9kSXNzdWVDb2RlIH0gZnJvbSBcIi4uL1pvZEVycm9yLmpzXCI7XG5pbXBvcnQgeyB1dGlsLCBab2RQYXJzZWRUeXBlIH0gZnJvbSBcIi4uL2hlbHBlcnMvdXRpbC5qc1wiO1xuY29uc3QgZXJyb3JNYXAgPSAoaXNzdWUsIF9jdHgpID0+IHtcbiAgICBsZXQgbWVzc2FnZTtcbiAgICBzd2l0Y2ggKGlzc3VlLmNvZGUpIHtcbiAgICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlOlxuICAgICAgICAgICAgaWYgKGlzc3VlLnJlY2VpdmVkID09PSBab2RQYXJzZWRUeXBlLnVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBcIlJlcXVpcmVkXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlID0gYEV4cGVjdGVkICR7aXNzdWUuZXhwZWN0ZWR9LCByZWNlaXZlZCAke2lzc3VlLnJlY2VpdmVkfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9saXRlcmFsOlxuICAgICAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGxpdGVyYWwgdmFsdWUsIGV4cGVjdGVkICR7SlNPTi5zdHJpbmdpZnkoaXNzdWUuZXhwZWN0ZWQsIHV0aWwuanNvblN0cmluZ2lmeVJlcGxhY2VyKX1gO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLnVucmVjb2duaXplZF9rZXlzOlxuICAgICAgICAgICAgbWVzc2FnZSA9IGBVbnJlY29nbml6ZWQga2V5KHMpIGluIG9iamVjdDogJHt1dGlsLmpvaW5WYWx1ZXMoaXNzdWUua2V5cywgXCIsIFwiKX1gO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfdW5pb246XG4gICAgICAgICAgICBtZXNzYWdlID0gYEludmFsaWQgaW5wdXRgO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfdW5pb25fZGlzY3JpbWluYXRvcjpcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBgSW52YWxpZCBkaXNjcmltaW5hdG9yIHZhbHVlLiBFeHBlY3RlZCAke3V0aWwuam9pblZhbHVlcyhpc3N1ZS5vcHRpb25zKX1gO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfZW51bV92YWx1ZTpcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBgSW52YWxpZCBlbnVtIHZhbHVlLiBFeHBlY3RlZCAke3V0aWwuam9pblZhbHVlcyhpc3N1ZS5vcHRpb25zKX0sIHJlY2VpdmVkICcke2lzc3VlLnJlY2VpdmVkfSdgO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfYXJndW1lbnRzOlxuICAgICAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGZ1bmN0aW9uIGFyZ3VtZW50c2A7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9yZXR1cm5fdHlwZTpcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBgSW52YWxpZCBmdW5jdGlvbiByZXR1cm4gdHlwZWA7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9kYXRlOlxuICAgICAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGRhdGVgO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nOlxuICAgICAgICAgICAgaWYgKHR5cGVvZiBpc3N1ZS52YWxpZGF0aW9uID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKFwiaW5jbHVkZXNcIiBpbiBpc3N1ZS52YWxpZGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBgSW52YWxpZCBpbnB1dDogbXVzdCBpbmNsdWRlIFwiJHtpc3N1ZS52YWxpZGF0aW9uLmluY2x1ZGVzfVwiYDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpc3N1ZS52YWxpZGF0aW9uLnBvc2l0aW9uID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gYCR7bWVzc2FnZX0gYXQgb25lIG9yIG1vcmUgcG9zaXRpb25zIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAke2lzc3VlLnZhbGlkYXRpb24ucG9zaXRpb259YDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChcInN0YXJ0c1dpdGhcIiBpbiBpc3N1ZS52YWxpZGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBgSW52YWxpZCBpbnB1dDogbXVzdCBzdGFydCB3aXRoIFwiJHtpc3N1ZS52YWxpZGF0aW9uLnN0YXJ0c1dpdGh9XCJgO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChcImVuZHNXaXRoXCIgaW4gaXNzdWUudmFsaWRhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gYEludmFsaWQgaW5wdXQ6IG11c3QgZW5kIHdpdGggXCIke2lzc3VlLnZhbGlkYXRpb24uZW5kc1dpdGh9XCJgO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdXRpbC5hc3NlcnROZXZlcihpc3N1ZS52YWxpZGF0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChpc3N1ZS52YWxpZGF0aW9uICE9PSBcInJlZ2V4XCIpIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlID0gYEludmFsaWQgJHtpc3N1ZS52YWxpZGF0aW9ufWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlID0gXCJJbnZhbGlkXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBab2RJc3N1ZUNvZGUudG9vX3NtYWxsOlxuICAgICAgICAgICAgaWYgKGlzc3VlLnR5cGUgPT09IFwiYXJyYXlcIilcbiAgICAgICAgICAgICAgICBtZXNzYWdlID0gYEFycmF5IG11c3QgY29udGFpbiAke2lzc3VlLmV4YWN0ID8gXCJleGFjdGx5XCIgOiBpc3N1ZS5pbmNsdXNpdmUgPyBgYXQgbGVhc3RgIDogYG1vcmUgdGhhbmB9ICR7aXNzdWUubWluaW11bX0gZWxlbWVudChzKWA7XG4gICAgICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSBcInN0cmluZ1wiKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBgU3RyaW5nIG11c3QgY29udGFpbiAke2lzc3VlLmV4YWN0ID8gXCJleGFjdGx5XCIgOiBpc3N1ZS5pbmNsdXNpdmUgPyBgYXQgbGVhc3RgIDogYG92ZXJgfSAke2lzc3VlLm1pbmltdW19IGNoYXJhY3RlcihzKWA7XG4gICAgICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBgTnVtYmVyIG11c3QgYmUgJHtpc3N1ZS5leGFjdCA/IGBleGFjdGx5IGVxdWFsIHRvIGAgOiBpc3N1ZS5pbmNsdXNpdmUgPyBgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIGAgOiBgZ3JlYXRlciB0aGFuIGB9JHtpc3N1ZS5taW5pbXVtfWA7XG4gICAgICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSBcImJpZ2ludFwiKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBgTnVtYmVyIG11c3QgYmUgJHtpc3N1ZS5leGFjdCA/IGBleGFjdGx5IGVxdWFsIHRvIGAgOiBpc3N1ZS5pbmNsdXNpdmUgPyBgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIGAgOiBgZ3JlYXRlciB0aGFuIGB9JHtpc3N1ZS5taW5pbXVtfWA7XG4gICAgICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSBcImRhdGVcIilcbiAgICAgICAgICAgICAgICBtZXNzYWdlID0gYERhdGUgbXVzdCBiZSAke2lzc3VlLmV4YWN0ID8gYGV4YWN0bHkgZXF1YWwgdG8gYCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gYCA6IGBncmVhdGVyIHRoYW4gYH0ke25ldyBEYXRlKE51bWJlcihpc3N1ZS5taW5pbXVtKSl9YDtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICBtZXNzYWdlID0gXCJJbnZhbGlkIGlucHV0XCI7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBab2RJc3N1ZUNvZGUudG9vX2JpZzpcbiAgICAgICAgICAgIGlmIChpc3N1ZS50eXBlID09PSBcImFycmF5XCIpXG4gICAgICAgICAgICAgICAgbWVzc2FnZSA9IGBBcnJheSBtdXN0IGNvbnRhaW4gJHtpc3N1ZS5leGFjdCA/IGBleGFjdGx5YCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBhdCBtb3N0YCA6IGBsZXNzIHRoYW5gfSAke2lzc3VlLm1heGltdW19IGVsZW1lbnQocylgO1xuICAgICAgICAgICAgZWxzZSBpZiAoaXNzdWUudHlwZSA9PT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgICAgICBtZXNzYWdlID0gYFN0cmluZyBtdXN0IGNvbnRhaW4gJHtpc3N1ZS5leGFjdCA/IGBleGFjdGx5YCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBhdCBtb3N0YCA6IGB1bmRlcmB9ICR7aXNzdWUubWF4aW11bX0gY2hhcmFjdGVyKHMpYDtcbiAgICAgICAgICAgIGVsc2UgaWYgKGlzc3VlLnR5cGUgPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgbWVzc2FnZSA9IGBOdW1iZXIgbXVzdCBiZSAke2lzc3VlLmV4YWN0ID8gYGV4YWN0bHlgIDogaXNzdWUuaW5jbHVzaXZlID8gYGxlc3MgdGhhbiBvciBlcXVhbCB0b2AgOiBgbGVzcyB0aGFuYH0gJHtpc3N1ZS5tYXhpbXVtfWA7XG4gICAgICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSBcImJpZ2ludFwiKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBgQmlnSW50IG11c3QgYmUgJHtpc3N1ZS5leGFjdCA/IGBleGFjdGx5YCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBsZXNzIHRoYW4gb3IgZXF1YWwgdG9gIDogYGxlc3MgdGhhbmB9ICR7aXNzdWUubWF4aW11bX1gO1xuICAgICAgICAgICAgZWxzZSBpZiAoaXNzdWUudHlwZSA9PT0gXCJkYXRlXCIpXG4gICAgICAgICAgICAgICAgbWVzc2FnZSA9IGBEYXRlIG11c3QgYmUgJHtpc3N1ZS5leGFjdCA/IGBleGFjdGx5YCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBzbWFsbGVyIHRoYW4gb3IgZXF1YWwgdG9gIDogYHNtYWxsZXIgdGhhbmB9ICR7bmV3IERhdGUoTnVtYmVyKGlzc3VlLm1heGltdW0pKX1gO1xuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBcIkludmFsaWQgaW5wdXRcIjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFpvZElzc3VlQ29kZS5jdXN0b206XG4gICAgICAgICAgICBtZXNzYWdlID0gYEludmFsaWQgaW5wdXRgO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfaW50ZXJzZWN0aW9uX3R5cGVzOlxuICAgICAgICAgICAgbWVzc2FnZSA9IGBJbnRlcnNlY3Rpb24gcmVzdWx0cyBjb3VsZCBub3QgYmUgbWVyZ2VkYDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFpvZElzc3VlQ29kZS5ub3RfbXVsdGlwbGVfb2Y6XG4gICAgICAgICAgICBtZXNzYWdlID0gYE51bWJlciBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgJHtpc3N1ZS5tdWx0aXBsZU9mfWA7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBab2RJc3N1ZUNvZGUubm90X2Zpbml0ZTpcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBcIk51bWJlciBtdXN0IGJlIGZpbml0ZVwiO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBtZXNzYWdlID0gX2N0eC5kZWZhdWx0RXJyb3I7XG4gICAgICAgICAgICB1dGlsLmFzc2VydE5ldmVyKGlzc3VlKTtcbiAgICB9XG4gICAgcmV0dXJuIHsgbWVzc2FnZSB9O1xufTtcbmV4cG9ydCBkZWZhdWx0IGVycm9yTWFwO1xuIiwgImltcG9ydCBkZWZhdWx0RXJyb3JNYXAgZnJvbSBcIi4vbG9jYWxlcy9lbi5qc1wiO1xubGV0IG92ZXJyaWRlRXJyb3JNYXAgPSBkZWZhdWx0RXJyb3JNYXA7XG5leHBvcnQgeyBkZWZhdWx0RXJyb3JNYXAgfTtcbmV4cG9ydCBmdW5jdGlvbiBzZXRFcnJvck1hcChtYXApIHtcbiAgICBvdmVycmlkZUVycm9yTWFwID0gbWFwO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdldEVycm9yTWFwKCkge1xuICAgIHJldHVybiBvdmVycmlkZUVycm9yTWFwO1xufVxuIiwgImltcG9ydCB7IGdldEVycm9yTWFwIH0gZnJvbSBcIi4uL2Vycm9ycy5qc1wiO1xuaW1wb3J0IGRlZmF1bHRFcnJvck1hcCBmcm9tIFwiLi4vbG9jYWxlcy9lbi5qc1wiO1xuZXhwb3J0IGNvbnN0IG1ha2VJc3N1ZSA9IChwYXJhbXMpID0+IHtcbiAgICBjb25zdCB7IGRhdGEsIHBhdGgsIGVycm9yTWFwcywgaXNzdWVEYXRhIH0gPSBwYXJhbXM7XG4gICAgY29uc3QgZnVsbFBhdGggPSBbLi4ucGF0aCwgLi4uKGlzc3VlRGF0YS5wYXRoIHx8IFtdKV07XG4gICAgY29uc3QgZnVsbElzc3VlID0ge1xuICAgICAgICAuLi5pc3N1ZURhdGEsXG4gICAgICAgIHBhdGg6IGZ1bGxQYXRoLFxuICAgIH07XG4gICAgaWYgKGlzc3VlRGF0YS5tZXNzYWdlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLmlzc3VlRGF0YSxcbiAgICAgICAgICAgIHBhdGg6IGZ1bGxQYXRoLFxuICAgICAgICAgICAgbWVzc2FnZTogaXNzdWVEYXRhLm1lc3NhZ2UsXG4gICAgICAgIH07XG4gICAgfVxuICAgIGxldCBlcnJvck1lc3NhZ2UgPSBcIlwiO1xuICAgIGNvbnN0IG1hcHMgPSBlcnJvck1hcHNcbiAgICAgICAgLmZpbHRlcigobSkgPT4gISFtKVxuICAgICAgICAuc2xpY2UoKVxuICAgICAgICAucmV2ZXJzZSgpO1xuICAgIGZvciAoY29uc3QgbWFwIG9mIG1hcHMpIHtcbiAgICAgICAgZXJyb3JNZXNzYWdlID0gbWFwKGZ1bGxJc3N1ZSwgeyBkYXRhLCBkZWZhdWx0RXJyb3I6IGVycm9yTWVzc2FnZSB9KS5tZXNzYWdlO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICAuLi5pc3N1ZURhdGEsXG4gICAgICAgIHBhdGg6IGZ1bGxQYXRoLFxuICAgICAgICBtZXNzYWdlOiBlcnJvck1lc3NhZ2UsXG4gICAgfTtcbn07XG5leHBvcnQgY29uc3QgRU1QVFlfUEFUSCA9IFtdO1xuZXhwb3J0IGZ1bmN0aW9uIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgaXNzdWVEYXRhKSB7XG4gICAgY29uc3Qgb3ZlcnJpZGVNYXAgPSBnZXRFcnJvck1hcCgpO1xuICAgIGNvbnN0IGlzc3VlID0gbWFrZUlzc3VlKHtcbiAgICAgICAgaXNzdWVEYXRhOiBpc3N1ZURhdGEsXG4gICAgICAgIGRhdGE6IGN0eC5kYXRhLFxuICAgICAgICBwYXRoOiBjdHgucGF0aCxcbiAgICAgICAgZXJyb3JNYXBzOiBbXG4gICAgICAgICAgICBjdHguY29tbW9uLmNvbnRleHR1YWxFcnJvck1hcCwgLy8gY29udGV4dHVhbCBlcnJvciBtYXAgaXMgZmlyc3QgcHJpb3JpdHlcbiAgICAgICAgICAgIGN0eC5zY2hlbWFFcnJvck1hcCwgLy8gdGhlbiBzY2hlbWEtYm91bmQgbWFwIGlmIGF2YWlsYWJsZVxuICAgICAgICAgICAgb3ZlcnJpZGVNYXAsIC8vIHRoZW4gZ2xvYmFsIG92ZXJyaWRlIG1hcFxuICAgICAgICAgICAgb3ZlcnJpZGVNYXAgPT09IGRlZmF1bHRFcnJvck1hcCA/IHVuZGVmaW5lZCA6IGRlZmF1bHRFcnJvck1hcCwgLy8gdGhlbiBnbG9iYWwgZGVmYXVsdCBtYXBcbiAgICAgICAgXS5maWx0ZXIoKHgpID0+ICEheCksXG4gICAgfSk7XG4gICAgY3R4LmNvbW1vbi5pc3N1ZXMucHVzaChpc3N1ZSk7XG59XG5leHBvcnQgY2xhc3MgUGFyc2VTdGF0dXMge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnZhbHVlID0gXCJ2YWxpZFwiO1xuICAgIH1cbiAgICBkaXJ0eSgpIHtcbiAgICAgICAgaWYgKHRoaXMudmFsdWUgPT09IFwidmFsaWRcIilcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBcImRpcnR5XCI7XG4gICAgfVxuICAgIGFib3J0KCkge1xuICAgICAgICBpZiAodGhpcy52YWx1ZSAhPT0gXCJhYm9ydGVkXCIpXG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gXCJhYm9ydGVkXCI7XG4gICAgfVxuICAgIHN0YXRpYyBtZXJnZUFycmF5KHN0YXR1cywgcmVzdWx0cykge1xuICAgICAgICBjb25zdCBhcnJheVZhbHVlID0gW107XG4gICAgICAgIGZvciAoY29uc3QgcyBvZiByZXN1bHRzKSB7XG4gICAgICAgICAgICBpZiAocy5zdGF0dXMgPT09IFwiYWJvcnRlZFwiKVxuICAgICAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICAgICAgaWYgKHMuc3RhdHVzID09PSBcImRpcnR5XCIpXG4gICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICBhcnJheVZhbHVlLnB1c2gocy52YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBhcnJheVZhbHVlIH07XG4gICAgfVxuICAgIHN0YXRpYyBhc3luYyBtZXJnZU9iamVjdEFzeW5jKHN0YXR1cywgcGFpcnMpIHtcbiAgICAgICAgY29uc3Qgc3luY1BhaXJzID0gW107XG4gICAgICAgIGZvciAoY29uc3QgcGFpciBvZiBwYWlycykge1xuICAgICAgICAgICAgY29uc3Qga2V5ID0gYXdhaXQgcGFpci5rZXk7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGF3YWl0IHBhaXIudmFsdWU7XG4gICAgICAgICAgICBzeW5jUGFpcnMucHVzaCh7XG4gICAgICAgICAgICAgICAga2V5LFxuICAgICAgICAgICAgICAgIHZhbHVlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFBhcnNlU3RhdHVzLm1lcmdlT2JqZWN0U3luYyhzdGF0dXMsIHN5bmNQYWlycyk7XG4gICAgfVxuICAgIHN0YXRpYyBtZXJnZU9iamVjdFN5bmMoc3RhdHVzLCBwYWlycykge1xuICAgICAgICBjb25zdCBmaW5hbE9iamVjdCA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHtcbiAgICAgICAgICAgIGNvbnN0IHsga2V5LCB2YWx1ZSB9ID0gcGFpcjtcbiAgICAgICAgICAgIGlmIChrZXkuc3RhdHVzID09PSBcImFib3J0ZWRcIilcbiAgICAgICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgICAgIGlmICh2YWx1ZS5zdGF0dXMgPT09IFwiYWJvcnRlZFwiKVxuICAgICAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICAgICAgaWYgKGtleS5zdGF0dXMgPT09IFwiZGlydHlcIilcbiAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgIGlmICh2YWx1ZS5zdGF0dXMgPT09IFwiZGlydHlcIilcbiAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgIGlmIChrZXkudmFsdWUgIT09IFwiX19wcm90b19fXCIgJiYgKHR5cGVvZiB2YWx1ZS52YWx1ZSAhPT0gXCJ1bmRlZmluZWRcIiB8fCBwYWlyLmFsd2F5c1NldCkpIHtcbiAgICAgICAgICAgICAgICBmaW5hbE9iamVjdFtrZXkudmFsdWVdID0gdmFsdWUudmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBmaW5hbE9iamVjdCB9O1xuICAgIH1cbn1cbmV4cG9ydCBjb25zdCBJTlZBTElEID0gT2JqZWN0LmZyZWV6ZSh7XG4gICAgc3RhdHVzOiBcImFib3J0ZWRcIixcbn0pO1xuZXhwb3J0IGNvbnN0IERJUlRZID0gKHZhbHVlKSA9PiAoeyBzdGF0dXM6IFwiZGlydHlcIiwgdmFsdWUgfSk7XG5leHBvcnQgY29uc3QgT0sgPSAodmFsdWUpID0+ICh7IHN0YXR1czogXCJ2YWxpZFwiLCB2YWx1ZSB9KTtcbmV4cG9ydCBjb25zdCBpc0Fib3J0ZWQgPSAoeCkgPT4geC5zdGF0dXMgPT09IFwiYWJvcnRlZFwiO1xuZXhwb3J0IGNvbnN0IGlzRGlydHkgPSAoeCkgPT4geC5zdGF0dXMgPT09IFwiZGlydHlcIjtcbmV4cG9ydCBjb25zdCBpc1ZhbGlkID0gKHgpID0+IHguc3RhdHVzID09PSBcInZhbGlkXCI7XG5leHBvcnQgY29uc3QgaXNBc3luYyA9ICh4KSA9PiB0eXBlb2YgUHJvbWlzZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiB4IGluc3RhbmNlb2YgUHJvbWlzZTtcbiIsICJleHBvcnQgdmFyIGVycm9yVXRpbDtcbihmdW5jdGlvbiAoZXJyb3JVdGlsKSB7XG4gICAgZXJyb3JVdGlsLmVyclRvT2JqID0gKG1lc3NhZ2UpID0+IHR5cGVvZiBtZXNzYWdlID09PSBcInN0cmluZ1wiID8geyBtZXNzYWdlIH0gOiBtZXNzYWdlIHx8IHt9O1xuICAgIC8vIGJpb21lLWlnbm9yZSBsaW50OlxuICAgIGVycm9yVXRpbC50b1N0cmluZyA9IChtZXNzYWdlKSA9PiB0eXBlb2YgbWVzc2FnZSA9PT0gXCJzdHJpbmdcIiA/IG1lc3NhZ2UgOiBtZXNzYWdlPy5tZXNzYWdlO1xufSkoZXJyb3JVdGlsIHx8IChlcnJvclV0aWwgPSB7fSkpO1xuIiwgImltcG9ydCB7IFpvZEVycm9yLCBab2RJc3N1ZUNvZGUsIH0gZnJvbSBcIi4vWm9kRXJyb3IuanNcIjtcbmltcG9ydCB7IGRlZmF1bHRFcnJvck1hcCwgZ2V0RXJyb3JNYXAgfSBmcm9tIFwiLi9lcnJvcnMuanNcIjtcbmltcG9ydCB7IGVycm9yVXRpbCB9IGZyb20gXCIuL2hlbHBlcnMvZXJyb3JVdGlsLmpzXCI7XG5pbXBvcnQgeyBESVJUWSwgSU5WQUxJRCwgT0ssIFBhcnNlU3RhdHVzLCBhZGRJc3N1ZVRvQ29udGV4dCwgaXNBYm9ydGVkLCBpc0FzeW5jLCBpc0RpcnR5LCBpc1ZhbGlkLCBtYWtlSXNzdWUsIH0gZnJvbSBcIi4vaGVscGVycy9wYXJzZVV0aWwuanNcIjtcbmltcG9ydCB7IHV0aWwsIFpvZFBhcnNlZFR5cGUsIGdldFBhcnNlZFR5cGUgfSBmcm9tIFwiLi9oZWxwZXJzL3V0aWwuanNcIjtcbmNsYXNzIFBhcnNlSW5wdXRMYXp5UGF0aCB7XG4gICAgY29uc3RydWN0b3IocGFyZW50LCB2YWx1ZSwgcGF0aCwga2V5KSB7XG4gICAgICAgIHRoaXMuX2NhY2hlZFBhdGggPSBbXTtcbiAgICAgICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgICAgIHRoaXMuZGF0YSA9IHZhbHVlO1xuICAgICAgICB0aGlzLl9wYXRoID0gcGF0aDtcbiAgICAgICAgdGhpcy5fa2V5ID0ga2V5O1xuICAgIH1cbiAgICBnZXQgcGF0aCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9jYWNoZWRQYXRoLmxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodGhpcy5fa2V5KSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2NhY2hlZFBhdGgucHVzaCguLi50aGlzLl9wYXRoLCAuLi50aGlzLl9rZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2FjaGVkUGF0aC5wdXNoKC4uLnRoaXMuX3BhdGgsIHRoaXMuX2tleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhY2hlZFBhdGg7XG4gICAgfVxufVxuY29uc3QgaGFuZGxlUmVzdWx0ID0gKGN0eCwgcmVzdWx0KSA9PiB7XG4gICAgaWYgKGlzVmFsaWQocmVzdWx0KSkge1xuICAgICAgICByZXR1cm4geyBzdWNjZXNzOiB0cnVlLCBkYXRhOiByZXN1bHQudmFsdWUgfTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlmICghY3R4LmNvbW1vbi5pc3N1ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJWYWxpZGF0aW9uIGZhaWxlZCBidXQgbm8gaXNzdWVzIGRldGVjdGVkLlwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICBnZXQgZXJyb3IoKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX2Vycm9yKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZXJyb3I7XG4gICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgWm9kRXJyb3IoY3R4LmNvbW1vbi5pc3N1ZXMpO1xuICAgICAgICAgICAgICAgIHRoaXMuX2Vycm9yID0gZXJyb3I7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2Vycm9yO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICB9XG59O1xuZnVuY3Rpb24gcHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpIHtcbiAgICBpZiAoIXBhcmFtcylcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIGNvbnN0IHsgZXJyb3JNYXAsIGludmFsaWRfdHlwZV9lcnJvciwgcmVxdWlyZWRfZXJyb3IsIGRlc2NyaXB0aW9uIH0gPSBwYXJhbXM7XG4gICAgaWYgKGVycm9yTWFwICYmIChpbnZhbGlkX3R5cGVfZXJyb3IgfHwgcmVxdWlyZWRfZXJyb3IpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3QgdXNlIFwiaW52YWxpZF90eXBlX2Vycm9yXCIgb3IgXCJyZXF1aXJlZF9lcnJvclwiIGluIGNvbmp1bmN0aW9uIHdpdGggY3VzdG9tIGVycm9yIG1hcC5gKTtcbiAgICB9XG4gICAgaWYgKGVycm9yTWFwKVxuICAgICAgICByZXR1cm4geyBlcnJvck1hcDogZXJyb3JNYXAsIGRlc2NyaXB0aW9uIH07XG4gICAgY29uc3QgY3VzdG9tTWFwID0gKGlzcywgY3R4KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgbWVzc2FnZSB9ID0gcGFyYW1zO1xuICAgICAgICBpZiAoaXNzLmNvZGUgPT09IFwiaW52YWxpZF9lbnVtX3ZhbHVlXCIpIHtcbiAgICAgICAgICAgIHJldHVybiB7IG1lc3NhZ2U6IG1lc3NhZ2UgPz8gY3R4LmRlZmF1bHRFcnJvciB9O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgY3R4LmRhdGEgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgIHJldHVybiB7IG1lc3NhZ2U6IG1lc3NhZ2UgPz8gcmVxdWlyZWRfZXJyb3IgPz8gY3R4LmRlZmF1bHRFcnJvciB9O1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc3MuY29kZSAhPT0gXCJpbnZhbGlkX3R5cGVcIilcbiAgICAgICAgICAgIHJldHVybiB7IG1lc3NhZ2U6IGN0eC5kZWZhdWx0RXJyb3IgfTtcbiAgICAgICAgcmV0dXJuIHsgbWVzc2FnZTogbWVzc2FnZSA/PyBpbnZhbGlkX3R5cGVfZXJyb3IgPz8gY3R4LmRlZmF1bHRFcnJvciB9O1xuICAgIH07XG4gICAgcmV0dXJuIHsgZXJyb3JNYXA6IGN1c3RvbU1hcCwgZGVzY3JpcHRpb24gfTtcbn1cbmV4cG9ydCBjbGFzcyBab2RUeXBlIHtcbiAgICBnZXQgZGVzY3JpcHRpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYuZGVzY3JpcHRpb247XG4gICAgfVxuICAgIF9nZXRUeXBlKGlucHV0KSB7XG4gICAgICAgIHJldHVybiBnZXRQYXJzZWRUeXBlKGlucHV0LmRhdGEpO1xuICAgIH1cbiAgICBfZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCkge1xuICAgICAgICByZXR1cm4gKGN0eCB8fCB7XG4gICAgICAgICAgICBjb21tb246IGlucHV0LnBhcmVudC5jb21tb24sXG4gICAgICAgICAgICBkYXRhOiBpbnB1dC5kYXRhLFxuICAgICAgICAgICAgcGFyc2VkVHlwZTogZ2V0UGFyc2VkVHlwZShpbnB1dC5kYXRhKSxcbiAgICAgICAgICAgIHNjaGVtYUVycm9yTWFwOiB0aGlzLl9kZWYuZXJyb3JNYXAsXG4gICAgICAgICAgICBwYXRoOiBpbnB1dC5wYXRoLFxuICAgICAgICAgICAgcGFyZW50OiBpbnB1dC5wYXJlbnQsXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBfcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdGF0dXM6IG5ldyBQYXJzZVN0YXR1cygpLFxuICAgICAgICAgICAgY3R4OiB7XG4gICAgICAgICAgICAgICAgY29tbW9uOiBpbnB1dC5wYXJlbnQuY29tbW9uLFxuICAgICAgICAgICAgICAgIGRhdGE6IGlucHV0LmRhdGEsXG4gICAgICAgICAgICAgICAgcGFyc2VkVHlwZTogZ2V0UGFyc2VkVHlwZShpbnB1dC5kYXRhKSxcbiAgICAgICAgICAgICAgICBzY2hlbWFFcnJvck1hcDogdGhpcy5fZGVmLmVycm9yTWFwLFxuICAgICAgICAgICAgICAgIHBhdGg6IGlucHV0LnBhdGgsXG4gICAgICAgICAgICAgICAgcGFyZW50OiBpbnB1dC5wYXJlbnQsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgIH1cbiAgICBfcGFyc2VTeW5jKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX3BhcnNlKGlucHV0KTtcbiAgICAgICAgaWYgKGlzQXN5bmMocmVzdWx0KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU3luY2hyb25vdXMgcGFyc2UgZW5jb3VudGVyZWQgcHJvbWlzZS5cIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgX3BhcnNlQXN5bmMoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fcGFyc2UoaW5wdXQpO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCk7XG4gICAgfVxuICAgIHBhcnNlKGRhdGEsIHBhcmFtcykge1xuICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLnNhZmVQYXJzZShkYXRhLCBwYXJhbXMpO1xuICAgICAgICBpZiAocmVzdWx0LnN1Y2Nlc3MpXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0LmRhdGE7XG4gICAgICAgIHRocm93IHJlc3VsdC5lcnJvcjtcbiAgICB9XG4gICAgc2FmZVBhcnNlKGRhdGEsIHBhcmFtcykge1xuICAgICAgICBjb25zdCBjdHggPSB7XG4gICAgICAgICAgICBjb21tb246IHtcbiAgICAgICAgICAgICAgICBpc3N1ZXM6IFtdLFxuICAgICAgICAgICAgICAgIGFzeW5jOiBwYXJhbXM/LmFzeW5jID8/IGZhbHNlLFxuICAgICAgICAgICAgICAgIGNvbnRleHR1YWxFcnJvck1hcDogcGFyYW1zPy5lcnJvck1hcCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYXRoOiBwYXJhbXM/LnBhdGggfHwgW10sXG4gICAgICAgICAgICBzY2hlbWFFcnJvck1hcDogdGhpcy5fZGVmLmVycm9yTWFwLFxuICAgICAgICAgICAgcGFyZW50OiBudWxsLFxuICAgICAgICAgICAgZGF0YSxcbiAgICAgICAgICAgIHBhcnNlZFR5cGU6IGdldFBhcnNlZFR5cGUoZGF0YSksXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX3BhcnNlU3luYyh7IGRhdGEsIHBhdGg6IGN0eC5wYXRoLCBwYXJlbnQ6IGN0eCB9KTtcbiAgICAgICAgcmV0dXJuIGhhbmRsZVJlc3VsdChjdHgsIHJlc3VsdCk7XG4gICAgfVxuICAgIFwifnZhbGlkYXRlXCIoZGF0YSkge1xuICAgICAgICBjb25zdCBjdHggPSB7XG4gICAgICAgICAgICBjb21tb246IHtcbiAgICAgICAgICAgICAgICBpc3N1ZXM6IFtdLFxuICAgICAgICAgICAgICAgIGFzeW5jOiAhIXRoaXNbXCJ+c3RhbmRhcmRcIl0uYXN5bmMsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGF0aDogW10sXG4gICAgICAgICAgICBzY2hlbWFFcnJvck1hcDogdGhpcy5fZGVmLmVycm9yTWFwLFxuICAgICAgICAgICAgcGFyZW50OiBudWxsLFxuICAgICAgICAgICAgZGF0YSxcbiAgICAgICAgICAgIHBhcnNlZFR5cGU6IGdldFBhcnNlZFR5cGUoZGF0YSksXG4gICAgICAgIH07XG4gICAgICAgIGlmICghdGhpc1tcIn5zdGFuZGFyZFwiXS5hc3luYykge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLl9wYXJzZVN5bmMoeyBkYXRhLCBwYXRoOiBbXSwgcGFyZW50OiBjdHggfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWQocmVzdWx0KVxuICAgICAgICAgICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiByZXN1bHQudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc3N1ZXM6IGN0eC5jb21tb24uaXNzdWVzLFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIGlmIChlcnI/Lm1lc3NhZ2U/LnRvTG93ZXJDYXNlKCk/LmluY2x1ZGVzKFwiZW5jb3VudGVyZWRcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpc1tcIn5zdGFuZGFyZFwiXS5hc3luYyA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGN0eC5jb21tb24gPSB7XG4gICAgICAgICAgICAgICAgICAgIGlzc3VlczogW10sXG4gICAgICAgICAgICAgICAgICAgIGFzeW5jOiB0cnVlLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX3BhcnNlQXN5bmMoeyBkYXRhLCBwYXRoOiBbXSwgcGFyZW50OiBjdHggfSkudGhlbigocmVzdWx0KSA9PiBpc1ZhbGlkKHJlc3VsdClcbiAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgIHZhbHVlOiByZXN1bHQudmFsdWUsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICBpc3N1ZXM6IGN0eC5jb21tb24uaXNzdWVzLFxuICAgICAgICAgICAgfSk7XG4gICAgfVxuICAgIGFzeW5jIHBhcnNlQXN5bmMoZGF0YSwgcGFyYW1zKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuc2FmZVBhcnNlQXN5bmMoZGF0YSwgcGFyYW1zKTtcbiAgICAgICAgaWYgKHJlc3VsdC5zdWNjZXNzKVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5kYXRhO1xuICAgICAgICB0aHJvdyByZXN1bHQuZXJyb3I7XG4gICAgfVxuICAgIGFzeW5jIHNhZmVQYXJzZUFzeW5jKGRhdGEsIHBhcmFtcykge1xuICAgICAgICBjb25zdCBjdHggPSB7XG4gICAgICAgICAgICBjb21tb246IHtcbiAgICAgICAgICAgICAgICBpc3N1ZXM6IFtdLFxuICAgICAgICAgICAgICAgIGNvbnRleHR1YWxFcnJvck1hcDogcGFyYW1zPy5lcnJvck1hcCxcbiAgICAgICAgICAgICAgICBhc3luYzogdHJ1ZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYXRoOiBwYXJhbXM/LnBhdGggfHwgW10sXG4gICAgICAgICAgICBzY2hlbWFFcnJvck1hcDogdGhpcy5fZGVmLmVycm9yTWFwLFxuICAgICAgICAgICAgcGFyZW50OiBudWxsLFxuICAgICAgICAgICAgZGF0YSxcbiAgICAgICAgICAgIHBhcnNlZFR5cGU6IGdldFBhcnNlZFR5cGUoZGF0YSksXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IG1heWJlQXN5bmNSZXN1bHQgPSB0aGlzLl9wYXJzZSh7IGRhdGEsIHBhdGg6IGN0eC5wYXRoLCBwYXJlbnQ6IGN0eCB9KTtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgKGlzQXN5bmMobWF5YmVBc3luY1Jlc3VsdCkgPyBtYXliZUFzeW5jUmVzdWx0IDogUHJvbWlzZS5yZXNvbHZlKG1heWJlQXN5bmNSZXN1bHQpKTtcbiAgICAgICAgcmV0dXJuIGhhbmRsZVJlc3VsdChjdHgsIHJlc3VsdCk7XG4gICAgfVxuICAgIHJlZmluZShjaGVjaywgbWVzc2FnZSkge1xuICAgICAgICBjb25zdCBnZXRJc3N1ZVByb3BlcnRpZXMgPSAodmFsKSA9PiB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgPT09IFwic3RyaW5nXCIgfHwgdHlwZW9mIG1lc3NhZ2UgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyBtZXNzYWdlIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgbWVzc2FnZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2UodmFsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gdGhpcy5fcmVmaW5lbWVudCgodmFsLCBjdHgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGNoZWNrKHZhbCk7XG4gICAgICAgICAgICBjb25zdCBzZXRFcnJvciA9ICgpID0+IGN0eC5hZGRJc3N1ZSh7XG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmN1c3RvbSxcbiAgICAgICAgICAgICAgICAuLi5nZXRJc3N1ZVByb3BlcnRpZXModmFsKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBQcm9taXNlICE9PSBcInVuZGVmaW5lZFwiICYmIHJlc3VsdCBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0LnRoZW4oKGRhdGEpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRFcnJvcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgc2V0RXJyb3IoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJlZmluZW1lbnQoY2hlY2ssIHJlZmluZW1lbnREYXRhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZWZpbmVtZW50KCh2YWwsIGN0eCkgPT4ge1xuICAgICAgICAgICAgaWYgKCFjaGVjayh2YWwpKSB7XG4gICAgICAgICAgICAgICAgY3R4LmFkZElzc3VlKHR5cGVvZiByZWZpbmVtZW50RGF0YSA9PT0gXCJmdW5jdGlvblwiID8gcmVmaW5lbWVudERhdGEodmFsLCBjdHgpIDogcmVmaW5lbWVudERhdGEpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgX3JlZmluZW1lbnQocmVmaW5lbWVudCkge1xuICAgICAgICByZXR1cm4gbmV3IFpvZEVmZmVjdHMoe1xuICAgICAgICAgICAgc2NoZW1hOiB0aGlzLFxuICAgICAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RFZmZlY3RzLFxuICAgICAgICAgICAgZWZmZWN0OiB7IHR5cGU6IFwicmVmaW5lbWVudFwiLCByZWZpbmVtZW50IH0sXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdXBlclJlZmluZShyZWZpbmVtZW50KSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZWZpbmVtZW50KHJlZmluZW1lbnQpO1xuICAgIH1cbiAgICBjb25zdHJ1Y3RvcihkZWYpIHtcbiAgICAgICAgLyoqIEFsaWFzIG9mIHNhZmVQYXJzZUFzeW5jICovXG4gICAgICAgIHRoaXMuc3BhID0gdGhpcy5zYWZlUGFyc2VBc3luYztcbiAgICAgICAgdGhpcy5fZGVmID0gZGVmO1xuICAgICAgICB0aGlzLnBhcnNlID0gdGhpcy5wYXJzZS5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLnNhZmVQYXJzZSA9IHRoaXMuc2FmZVBhcnNlLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMucGFyc2VBc3luYyA9IHRoaXMucGFyc2VBc3luYy5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLnNhZmVQYXJzZUFzeW5jID0gdGhpcy5zYWZlUGFyc2VBc3luYy5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLnNwYSA9IHRoaXMuc3BhLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMucmVmaW5lID0gdGhpcy5yZWZpbmUuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5yZWZpbmVtZW50ID0gdGhpcy5yZWZpbmVtZW50LmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuc3VwZXJSZWZpbmUgPSB0aGlzLnN1cGVyUmVmaW5lLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMub3B0aW9uYWwgPSB0aGlzLm9wdGlvbmFsLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMubnVsbGFibGUgPSB0aGlzLm51bGxhYmxlLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMubnVsbGlzaCA9IHRoaXMubnVsbGlzaC5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLmFycmF5ID0gdGhpcy5hcnJheS5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLnByb21pc2UgPSB0aGlzLnByb21pc2UuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5vciA9IHRoaXMub3IuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5hbmQgPSB0aGlzLmFuZC5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLnRyYW5zZm9ybSA9IHRoaXMudHJhbnNmb3JtLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuYnJhbmQgPSB0aGlzLmJyYW5kLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuZGVmYXVsdCA9IHRoaXMuZGVmYXVsdC5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLmNhdGNoID0gdGhpcy5jYXRjaC5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLmRlc2NyaWJlID0gdGhpcy5kZXNjcmliZS5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLnBpcGUgPSB0aGlzLnBpcGUuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5yZWFkb25seSA9IHRoaXMucmVhZG9ubHkuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5pc051bGxhYmxlID0gdGhpcy5pc051bGxhYmxlLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuaXNPcHRpb25hbCA9IHRoaXMuaXNPcHRpb25hbC5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzW1wifnN0YW5kYXJkXCJdID0ge1xuICAgICAgICAgICAgdmVyc2lvbjogMSxcbiAgICAgICAgICAgIHZlbmRvcjogXCJ6b2RcIixcbiAgICAgICAgICAgIHZhbGlkYXRlOiAoZGF0YSkgPT4gdGhpc1tcIn52YWxpZGF0ZVwiXShkYXRhKSxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgb3B0aW9uYWwoKSB7XG4gICAgICAgIHJldHVybiBab2RPcHRpb25hbC5jcmVhdGUodGhpcywgdGhpcy5fZGVmKTtcbiAgICB9XG4gICAgbnVsbGFibGUoKSB7XG4gICAgICAgIHJldHVybiBab2ROdWxsYWJsZS5jcmVhdGUodGhpcywgdGhpcy5fZGVmKTtcbiAgICB9XG4gICAgbnVsbGlzaCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubnVsbGFibGUoKS5vcHRpb25hbCgpO1xuICAgIH1cbiAgICBhcnJheSgpIHtcbiAgICAgICAgcmV0dXJuIFpvZEFycmF5LmNyZWF0ZSh0aGlzKTtcbiAgICB9XG4gICAgcHJvbWlzZSgpIHtcbiAgICAgICAgcmV0dXJuIFpvZFByb21pc2UuY3JlYXRlKHRoaXMsIHRoaXMuX2RlZik7XG4gICAgfVxuICAgIG9yKG9wdGlvbikge1xuICAgICAgICByZXR1cm4gWm9kVW5pb24uY3JlYXRlKFt0aGlzLCBvcHRpb25dLCB0aGlzLl9kZWYpO1xuICAgIH1cbiAgICBhbmQoaW5jb21pbmcpIHtcbiAgICAgICAgcmV0dXJuIFpvZEludGVyc2VjdGlvbi5jcmVhdGUodGhpcywgaW5jb21pbmcsIHRoaXMuX2RlZik7XG4gICAgfVxuICAgIHRyYW5zZm9ybSh0cmFuc2Zvcm0pIHtcbiAgICAgICAgcmV0dXJuIG5ldyBab2RFZmZlY3RzKHtcbiAgICAgICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXModGhpcy5fZGVmKSxcbiAgICAgICAgICAgIHNjaGVtYTogdGhpcyxcbiAgICAgICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRWZmZWN0cyxcbiAgICAgICAgICAgIGVmZmVjdDogeyB0eXBlOiBcInRyYW5zZm9ybVwiLCB0cmFuc2Zvcm0gfSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGRlZmF1bHQoZGVmKSB7XG4gICAgICAgIGNvbnN0IGRlZmF1bHRWYWx1ZUZ1bmMgPSB0eXBlb2YgZGVmID09PSBcImZ1bmN0aW9uXCIgPyBkZWYgOiAoKSA9PiBkZWY7XG4gICAgICAgIHJldHVybiBuZXcgWm9kRGVmYXVsdCh7XG4gICAgICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHRoaXMuX2RlZiksXG4gICAgICAgICAgICBpbm5lclR5cGU6IHRoaXMsXG4gICAgICAgICAgICBkZWZhdWx0VmFsdWU6IGRlZmF1bHRWYWx1ZUZ1bmMsXG4gICAgICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZERlZmF1bHQsXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBicmFuZCgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBab2RCcmFuZGVkKHtcbiAgICAgICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kQnJhbmRlZCxcbiAgICAgICAgICAgIHR5cGU6IHRoaXMsXG4gICAgICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHRoaXMuX2RlZiksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBjYXRjaChkZWYpIHtcbiAgICAgICAgY29uc3QgY2F0Y2hWYWx1ZUZ1bmMgPSB0eXBlb2YgZGVmID09PSBcImZ1bmN0aW9uXCIgPyBkZWYgOiAoKSA9PiBkZWY7XG4gICAgICAgIHJldHVybiBuZXcgWm9kQ2F0Y2goe1xuICAgICAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyh0aGlzLl9kZWYpLFxuICAgICAgICAgICAgaW5uZXJUeXBlOiB0aGlzLFxuICAgICAgICAgICAgY2F0Y2hWYWx1ZTogY2F0Y2hWYWx1ZUZ1bmMsXG4gICAgICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZENhdGNoLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgZGVzY3JpYmUoZGVzY3JpcHRpb24pIHtcbiAgICAgICAgY29uc3QgVGhpcyA9IHRoaXMuY29uc3RydWN0b3I7XG4gICAgICAgIHJldHVybiBuZXcgVGhpcyh7XG4gICAgICAgICAgICAuLi50aGlzLl9kZWYsXG4gICAgICAgICAgICBkZXNjcmlwdGlvbixcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHBpcGUodGFyZ2V0KSB7XG4gICAgICAgIHJldHVybiBab2RQaXBlbGluZS5jcmVhdGUodGhpcywgdGFyZ2V0KTtcbiAgICB9XG4gICAgcmVhZG9ubHkoKSB7XG4gICAgICAgIHJldHVybiBab2RSZWFkb25seS5jcmVhdGUodGhpcyk7XG4gICAgfVxuICAgIGlzT3B0aW9uYWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNhZmVQYXJzZSh1bmRlZmluZWQpLnN1Y2Nlc3M7XG4gICAgfVxuICAgIGlzTnVsbGFibGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNhZmVQYXJzZShudWxsKS5zdWNjZXNzO1xuICAgIH1cbn1cbmNvbnN0IGN1aWRSZWdleCA9IC9eY1teXFxzLV17OCx9JC9pO1xuY29uc3QgY3VpZDJSZWdleCA9IC9eWzAtOWEtel0rJC87XG5jb25zdCB1bGlkUmVnZXggPSAvXlswLTlBLUhKS01OUC1UVi1aXXsyNn0kL2k7XG4vLyBjb25zdCB1dWlkUmVnZXggPVxuLy8gICAvXihbYS1mMC05XXs4fS1bYS1mMC05XXs0fS1bMS01XVthLWYwLTldezN9LVthLWYwLTldezR9LVthLWYwLTldezEyfXwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDApJC9pO1xuY29uc3QgdXVpZFJlZ2V4ID0gL15bMC05YS1mQS1GXXs4fVxcYi1bMC05YS1mQS1GXXs0fVxcYi1bMC05YS1mQS1GXXs0fVxcYi1bMC05YS1mQS1GXXs0fVxcYi1bMC05YS1mQS1GXXsxMn0kL2k7XG5jb25zdCBuYW5vaWRSZWdleCA9IC9eW2EtejAtOV8tXXsyMX0kL2k7XG5jb25zdCBqd3RSZWdleCA9IC9eW0EtWmEtejAtOS1fXStcXC5bQS1aYS16MC05LV9dK1xcLltBLVphLXowLTktX10qJC87XG5jb25zdCBkdXJhdGlvblJlZ2V4ID0gL15bLStdP1AoPyEkKSg/Oig/OlstK10/XFxkK1kpfCg/OlstK10/XFxkK1suLF1cXGQrWSQpKT8oPzooPzpbLStdP1xcZCtNKXwoPzpbLStdP1xcZCtbLixdXFxkK00kKSk/KD86KD86Wy0rXT9cXGQrVyl8KD86Wy0rXT9cXGQrWy4sXVxcZCtXJCkpPyg/Oig/OlstK10/XFxkK0QpfCg/OlstK10/XFxkK1suLF1cXGQrRCQpKT8oPzpUKD89W1xcZCstXSkoPzooPzpbLStdP1xcZCtIKXwoPzpbLStdP1xcZCtbLixdXFxkK0gkKSk/KD86KD86Wy0rXT9cXGQrTSl8KD86Wy0rXT9cXGQrWy4sXVxcZCtNJCkpPyg/OlstK10/XFxkKyg/OlsuLF1cXGQrKT9TKT8pPz8kLztcbi8vIGZyb20gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzQ2MTgxLzE1NTAxNTVcbi8vIG9sZCB2ZXJzaW9uOiB0b28gc2xvdywgZGlkbid0IHN1cHBvcnQgdW5pY29kZVxuLy8gY29uc3QgZW1haWxSZWdleCA9IC9eKCgoW2Etel18XFxkfFshI1xcJCUmJ1xcKlxcK1xcLVxcLz1cXD9cXF5fYHtcXHx9fl18W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pKyhcXC4oW2Etel18XFxkfFshI1xcJCUmJ1xcKlxcK1xcLVxcLz1cXD9cXF5fYHtcXHx9fl18W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pKykqKXwoKFxceDIyKSgoKChcXHgyMHxcXHgwOSkqKFxceDBkXFx4MGEpKT8oXFx4MjB8XFx4MDkpKyk/KChbXFx4MDEtXFx4MDhcXHgwYlxceDBjXFx4MGUtXFx4MWZcXHg3Zl18XFx4MjF8W1xceDIzLVxceDViXXxbXFx4NWQtXFx4N2VdfFtcXHUwMEEwLVxcdUQ3RkZcXHVGOTAwLVxcdUZEQ0ZcXHVGREYwLVxcdUZGRUZdKXwoXFxcXChbXFx4MDEtXFx4MDlcXHgwYlxceDBjXFx4MGQtXFx4N2ZdfFtcXHUwMEEwLVxcdUQ3RkZcXHVGOTAwLVxcdUZEQ0ZcXHVGREYwLVxcdUZGRUZdKSkpKSooKChcXHgyMHxcXHgwOSkqKFxceDBkXFx4MGEpKT8oXFx4MjB8XFx4MDkpKyk/KFxceDIyKSkpQCgoKFthLXpdfFxcZHxbXFx1MDBBMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRkVGXSl8KChbYS16XXxcXGR8W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pKFthLXpdfFxcZHwtfFxcLnxffH58W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pKihbYS16XXxcXGR8W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pKSlcXC4pKygoW2Etel18W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pfCgoW2Etel18W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pKFthLXpdfFxcZHwtfFxcLnxffH58W1xcdTAwQTAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0pKihbYS16XXxbXFx1MDBBMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRkVGXSkpKSQvaTtcbi8vb2xkIGVtYWlsIHJlZ2V4XG4vLyBjb25zdCBlbWFpbFJlZ2V4ID0gL14oKFtePD4oKVtcXF0uLDs6XFxzQFwiXSsoXFwuW148PigpW1xcXS4sOzpcXHNAXCJdKykqKXwoXCIuK1wiKSlAKCg/IS0pKFtePD4oKVtcXF0uLDs6XFxzQFwiXStcXC4pK1tePD4oKVtcXF0uLDs6XFxzQFwiXXsxLH0pW14tPD4oKVtcXF0uLDs6XFxzQFwiXSQvaTtcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuLy8gY29uc3QgZW1haWxSZWdleCA9XG4vLyAgIC9eKChbXjw+KClbXFxdXFxcXC4sOzpcXHNAXFxcIl0rKFxcLltePD4oKVtcXF1cXFxcLiw7Olxcc0BcXFwiXSspKil8KFxcXCIuK1xcXCIpKUAoKFxcWygoKDI1WzAtNV0pfCgyWzAtNF1bMC05XSl8KDFbMC05XXsyfSl8KFswLTldezEsMn0pKVxcLil7M30oKDI1WzAtNV0pfCgyWzAtNF1bMC05XSl8KDFbMC05XXsyfSl8KFswLTldezEsMn0pKVxcXSl8KFxcW0lQdjY6KChbYS1mMC05XXsxLDR9Oil7N318OjooW2EtZjAtOV17MSw0fTopezAsNn18KFthLWYwLTldezEsNH06KXsxfTooW2EtZjAtOV17MSw0fTopezAsNX18KFthLWYwLTldezEsNH06KXsyfTooW2EtZjAtOV17MSw0fTopezAsNH18KFthLWYwLTldezEsNH06KXszfTooW2EtZjAtOV17MSw0fTopezAsM318KFthLWYwLTldezEsNH06KXs0fTooW2EtZjAtOV17MSw0fTopezAsMn18KFthLWYwLTldezEsNH06KXs1fTooW2EtZjAtOV17MSw0fTopezAsMX0pKFthLWYwLTldezEsNH18KCgoMjVbMC01XSl8KDJbMC00XVswLTldKXwoMVswLTldezJ9KXwoWzAtOV17MSwyfSkpXFwuKXszfSgoMjVbMC01XSl8KDJbMC00XVswLTldKXwoMVswLTldezJ9KXwoWzAtOV17MSwyfSkpKVxcXSl8KFtBLVphLXowLTldKFtBLVphLXowLTktXSpbQS1aYS16MC05XSkqKFxcLltBLVphLXpdezIsfSkrKSkkLztcbi8vIGNvbnN0IGVtYWlsUmVnZXggPVxuLy8gICAvXlthLXpBLVowLTlcXC5cXCFcXCNcXCRcXCVcXCZcXCdcXCpcXCtcXC9cXD1cXD9cXF5cXF9cXGBcXHtcXHxcXH1cXH5cXC1dK0BbYS16QS1aMC05XSg/OlthLXpBLVowLTktXXswLDYxfVthLXpBLVowLTldKT8oPzpcXC5bYS16QS1aMC05XSg/OlthLXpBLVowLTktXXswLDYxfVthLXpBLVowLTldKT8pKiQvO1xuLy8gY29uc3QgZW1haWxSZWdleCA9XG4vLyAgIC9eKD86W2EtejAtOSEjJCUmJyorLz0/Xl9ge3x9fi1dKyg/OlxcLlthLXowLTkhIyQlJicqKy89P15fYHt8fX4tXSspKnxcIig/OltcXHgwMS1cXHgwOFxceDBiXFx4MGNcXHgwZS1cXHgxZlxceDIxXFx4MjMtXFx4NWJcXHg1ZC1cXHg3Zl18XFxcXFtcXHgwMS1cXHgwOVxceDBiXFx4MGNcXHgwZS1cXHg3Zl0pKlwiKUAoPzooPzpbYS16MC05XSg/OlthLXowLTktXSpbYS16MC05XSk/XFwuKStbYS16MC05XSg/OlthLXowLTktXSpbYS16MC05XSk/fFxcWyg/Oig/OjI1WzAtNV18MlswLTRdWzAtOV18WzAxXT9bMC05XVswLTldPylcXC4pezN9KD86MjVbMC01XXwyWzAtNF1bMC05XXxbMDFdP1swLTldWzAtOV0/fFthLXowLTktXSpbYS16MC05XTooPzpbXFx4MDEtXFx4MDhcXHgwYlxceDBjXFx4MGUtXFx4MWZcXHgyMS1cXHg1YVxceDUzLVxceDdmXXxcXFxcW1xceDAxLVxceDA5XFx4MGJcXHgwY1xceDBlLVxceDdmXSkrKVxcXSkkL2k7XG5jb25zdCBlbWFpbFJlZ2V4ID0gL14oPyFcXC4pKD8hLipcXC5cXC4pKFtBLVowLTlfJytcXC1cXC5dKilbQS1aMC05XystXUAoW0EtWjAtOV1bQS1aMC05XFwtXSpcXC4pK1tBLVpdezIsfSQvaTtcbi8vIGNvbnN0IGVtYWlsUmVnZXggPVxuLy8gICAvXlthLXowLTkuISMkJSZcdTIwMTkqKy89P15fYHt8fX4tXStAW2EtejAtOS1dKyg/OlxcLlthLXowLTlcXC1dKykqJC9pO1xuLy8gZnJvbSBodHRwczovL3RoZWtldmluc2NvdHQuY29tL2Vtb2ppcy1pbi1qYXZhc2NyaXB0LyN3cml0aW5nLWEtcmVndWxhci1leHByZXNzaW9uXG5jb25zdCBfZW1vamlSZWdleCA9IGBeKFxcXFxwe0V4dGVuZGVkX1BpY3RvZ3JhcGhpY318XFxcXHB7RW1vamlfQ29tcG9uZW50fSkrJGA7XG5sZXQgZW1vamlSZWdleDtcbi8vIGZhc3Rlciwgc2ltcGxlciwgc2FmZXJcbmNvbnN0IGlwdjRSZWdleCA9IC9eKD86KD86MjVbMC01XXwyWzAtNF1bMC05XXwxWzAtOV1bMC05XXxbMS05XVswLTldfFswLTldKVxcLil7M30oPzoyNVswLTVdfDJbMC00XVswLTldfDFbMC05XVswLTldfFsxLTldWzAtOV18WzAtOV0pJC87XG5jb25zdCBpcHY0Q2lkclJlZ2V4ID0gL14oPzooPzoyNVswLTVdfDJbMC00XVswLTldfDFbMC05XVswLTldfFsxLTldWzAtOV18WzAtOV0pXFwuKXszfSg/OjI1WzAtNV18MlswLTRdWzAtOV18MVswLTldWzAtOV18WzEtOV1bMC05XXxbMC05XSlcXC8oM1swLTJdfFsxMl0/WzAtOV0pJC87XG4vLyBjb25zdCBpcHY2UmVnZXggPVxuLy8gL14oKFthLWYwLTldezEsNH06KXs3fXw6OihbYS1mMC05XXsxLDR9Oil7MCw2fXwoW2EtZjAtOV17MSw0fTopezF9OihbYS1mMC05XXsxLDR9Oil7MCw1fXwoW2EtZjAtOV17MSw0fTopezJ9OihbYS1mMC05XXsxLDR9Oil7MCw0fXwoW2EtZjAtOV17MSw0fTopezN9OihbYS1mMC05XXsxLDR9Oil7MCwzfXwoW2EtZjAtOV17MSw0fTopezR9OihbYS1mMC05XXsxLDR9Oil7MCwyfXwoW2EtZjAtOV17MSw0fTopezV9OihbYS1mMC05XXsxLDR9Oil7MCwxfSkoW2EtZjAtOV17MSw0fXwoKCgyNVswLTVdKXwoMlswLTRdWzAtOV0pfCgxWzAtOV17Mn0pfChbMC05XXsxLDJ9KSlcXC4pezN9KCgyNVswLTVdKXwoMlswLTRdWzAtOV0pfCgxWzAtOV17Mn0pfChbMC05XXsxLDJ9KSkpJC87XG5jb25zdCBpcHY2UmVnZXggPSAvXigoWzAtOWEtZkEtRl17MSw0fTopezcsN31bMC05YS1mQS1GXXsxLDR9fChbMC05YS1mQS1GXXsxLDR9Oil7MSw3fTp8KFswLTlhLWZBLUZdezEsNH06KXsxLDZ9OlswLTlhLWZBLUZdezEsNH18KFswLTlhLWZBLUZdezEsNH06KXsxLDV9KDpbMC05YS1mQS1GXXsxLDR9KXsxLDJ9fChbMC05YS1mQS1GXXsxLDR9Oil7MSw0fSg6WzAtOWEtZkEtRl17MSw0fSl7MSwzfXwoWzAtOWEtZkEtRl17MSw0fTopezEsM30oOlswLTlhLWZBLUZdezEsNH0pezEsNH18KFswLTlhLWZBLUZdezEsNH06KXsxLDJ9KDpbMC05YS1mQS1GXXsxLDR9KXsxLDV9fFswLTlhLWZBLUZdezEsNH06KCg6WzAtOWEtZkEtRl17MSw0fSl7MSw2fSl8OigoOlswLTlhLWZBLUZdezEsNH0pezEsN318Oil8ZmU4MDooOlswLTlhLWZBLUZdezAsNH0pezAsNH0lWzAtOWEtekEtWl17MSx9fDo6KGZmZmYoOjB7MSw0fSl7MCwxfTopezAsMX0oKDI1WzAtNV18KDJbMC00XXwxezAsMX1bMC05XSl7MCwxfVswLTldKVxcLil7MywzfSgyNVswLTVdfCgyWzAtNF18MXswLDF9WzAtOV0pezAsMX1bMC05XSl8KFswLTlhLWZBLUZdezEsNH06KXsxLDR9OigoMjVbMC01XXwoMlswLTRdfDF7MCwxfVswLTldKXswLDF9WzAtOV0pXFwuKXszLDN9KDI1WzAtNV18KDJbMC00XXwxezAsMX1bMC05XSl7MCwxfVswLTldKSkkLztcbmNvbnN0IGlwdjZDaWRyUmVnZXggPSAvXigoWzAtOWEtZkEtRl17MSw0fTopezcsN31bMC05YS1mQS1GXXsxLDR9fChbMC05YS1mQS1GXXsxLDR9Oil7MSw3fTp8KFswLTlhLWZBLUZdezEsNH06KXsxLDZ9OlswLTlhLWZBLUZdezEsNH18KFswLTlhLWZBLUZdezEsNH06KXsxLDV9KDpbMC05YS1mQS1GXXsxLDR9KXsxLDJ9fChbMC05YS1mQS1GXXsxLDR9Oil7MSw0fSg6WzAtOWEtZkEtRl17MSw0fSl7MSwzfXwoWzAtOWEtZkEtRl17MSw0fTopezEsM30oOlswLTlhLWZBLUZdezEsNH0pezEsNH18KFswLTlhLWZBLUZdezEsNH06KXsxLDJ9KDpbMC05YS1mQS1GXXsxLDR9KXsxLDV9fFswLTlhLWZBLUZdezEsNH06KCg6WzAtOWEtZkEtRl17MSw0fSl7MSw2fSl8OigoOlswLTlhLWZBLUZdezEsNH0pezEsN318Oil8ZmU4MDooOlswLTlhLWZBLUZdezAsNH0pezAsNH0lWzAtOWEtekEtWl17MSx9fDo6KGZmZmYoOjB7MSw0fSl7MCwxfTopezAsMX0oKDI1WzAtNV18KDJbMC00XXwxezAsMX1bMC05XSl7MCwxfVswLTldKVxcLil7MywzfSgyNVswLTVdfCgyWzAtNF18MXswLDF9WzAtOV0pezAsMX1bMC05XSl8KFswLTlhLWZBLUZdezEsNH06KXsxLDR9OigoMjVbMC01XXwoMlswLTRdfDF7MCwxfVswLTldKXswLDF9WzAtOV0pXFwuKXszLDN9KDI1WzAtNV18KDJbMC00XXwxezAsMX1bMC05XSl7MCwxfVswLTldKSlcXC8oMTJbMC04XXwxWzAxXVswLTldfFsxLTldP1swLTldKSQvO1xuLy8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNzg2MDM5Mi9kZXRlcm1pbmUtaWYtc3RyaW5nLWlzLWluLWJhc2U2NC11c2luZy1qYXZhc2NyaXB0XG5jb25zdCBiYXNlNjRSZWdleCA9IC9eKFswLTlhLXpBLVorL117NH0pKigoWzAtOWEtekEtWisvXXsyfT09KXwoWzAtOWEtekEtWisvXXszfT0pKT8kLztcbi8vIGh0dHBzOi8vYmFzZTY0Lmd1cnUvc3RhbmRhcmRzL2Jhc2U2NHVybFxuY29uc3QgYmFzZTY0dXJsUmVnZXggPSAvXihbMC05YS16QS1aLV9dezR9KSooKFswLTlhLXpBLVotX117Mn0oPT0pPyl8KFswLTlhLXpBLVotX117M30oPSk/KSk/JC87XG4vLyBzaW1wbGVcbi8vIGNvbnN0IGRhdGVSZWdleFNvdXJjZSA9IGBcXFxcZHs0fS1cXFxcZHsyfS1cXFxcZHsyfWA7XG4vLyBubyBsZWFwIHllYXIgdmFsaWRhdGlvblxuLy8gY29uc3QgZGF0ZVJlZ2V4U291cmNlID0gYFxcXFxkezR9LSgoMFsxMzU3OF18MTB8MTIpLTMxfCgwWzEzLTldfDFbMC0yXSktMzB8KDBbMS05XXwxWzAtMl0pLSgwWzEtOV18MVxcXFxkfDJcXFxcZCkpYDtcbi8vIHdpdGggbGVhcCB5ZWFyIHZhbGlkYXRpb25cbmNvbnN0IGRhdGVSZWdleFNvdXJjZSA9IGAoKFxcXFxkXFxcXGRbMjQ2OF1bMDQ4XXxcXFxcZFxcXFxkWzEzNTc5XVsyNl18XFxcXGRcXFxcZDBbNDhdfFswMjQ2OF1bMDQ4XTAwfFsxMzU3OV1bMjZdMDApLTAyLTI5fFxcXFxkezR9LSgoMFsxMzU3OF18MVswMl0pLSgwWzEtOV18WzEyXVxcXFxkfDNbMDFdKXwoMFs0NjldfDExKS0oMFsxLTldfFsxMl1cXFxcZHwzMCl8KDAyKS0oMFsxLTldfDFcXFxcZHwyWzAtOF0pKSlgO1xuY29uc3QgZGF0ZVJlZ2V4ID0gbmV3IFJlZ0V4cChgXiR7ZGF0ZVJlZ2V4U291cmNlfSRgKTtcbmZ1bmN0aW9uIHRpbWVSZWdleFNvdXJjZShhcmdzKSB7XG4gICAgbGV0IHNlY29uZHNSZWdleFNvdXJjZSA9IGBbMC01XVxcXFxkYDtcbiAgICBpZiAoYXJncy5wcmVjaXNpb24pIHtcbiAgICAgICAgc2Vjb25kc1JlZ2V4U291cmNlID0gYCR7c2Vjb25kc1JlZ2V4U291cmNlfVxcXFwuXFxcXGR7JHthcmdzLnByZWNpc2lvbn19YDtcbiAgICB9XG4gICAgZWxzZSBpZiAoYXJncy5wcmVjaXNpb24gPT0gbnVsbCkge1xuICAgICAgICBzZWNvbmRzUmVnZXhTb3VyY2UgPSBgJHtzZWNvbmRzUmVnZXhTb3VyY2V9KFxcXFwuXFxcXGQrKT9gO1xuICAgIH1cbiAgICBjb25zdCBzZWNvbmRzUXVhbnRpZmllciA9IGFyZ3MucHJlY2lzaW9uID8gXCIrXCIgOiBcIj9cIjsgLy8gcmVxdWlyZSBzZWNvbmRzIGlmIHByZWNpc2lvbiBpcyBub256ZXJvXG4gICAgcmV0dXJuIGAoWzAxXVxcXFxkfDJbMC0zXSk6WzAtNV1cXFxcZCg6JHtzZWNvbmRzUmVnZXhTb3VyY2V9KSR7c2Vjb25kc1F1YW50aWZpZXJ9YDtcbn1cbmZ1bmN0aW9uIHRpbWVSZWdleChhcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAoYF4ke3RpbWVSZWdleFNvdXJjZShhcmdzKX0kYCk7XG59XG4vLyBBZGFwdGVkIGZyb20gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzMxNDMyMzFcbmV4cG9ydCBmdW5jdGlvbiBkYXRldGltZVJlZ2V4KGFyZ3MpIHtcbiAgICBsZXQgcmVnZXggPSBgJHtkYXRlUmVnZXhTb3VyY2V9VCR7dGltZVJlZ2V4U291cmNlKGFyZ3MpfWA7XG4gICAgY29uc3Qgb3B0cyA9IFtdO1xuICAgIG9wdHMucHVzaChhcmdzLmxvY2FsID8gYFo/YCA6IGBaYCk7XG4gICAgaWYgKGFyZ3Mub2Zmc2V0KVxuICAgICAgICBvcHRzLnB1c2goYChbKy1dXFxcXGR7Mn06P1xcXFxkezJ9KWApO1xuICAgIHJlZ2V4ID0gYCR7cmVnZXh9KCR7b3B0cy5qb2luKFwifFwiKX0pYDtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cChgXiR7cmVnZXh9JGApO1xufVxuZnVuY3Rpb24gaXNWYWxpZElQKGlwLCB2ZXJzaW9uKSB7XG4gICAgaWYgKCh2ZXJzaW9uID09PSBcInY0XCIgfHwgIXZlcnNpb24pICYmIGlwdjRSZWdleC50ZXN0KGlwKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKCh2ZXJzaW9uID09PSBcInY2XCIgfHwgIXZlcnNpb24pICYmIGlwdjZSZWdleC50ZXN0KGlwKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuZnVuY3Rpb24gaXNWYWxpZEpXVChqd3QsIGFsZykge1xuICAgIGlmICghand0UmVnZXgudGVzdChqd3QpKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgW2hlYWRlcl0gPSBqd3Quc3BsaXQoXCIuXCIpO1xuICAgICAgICBpZiAoIWhlYWRlcilcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgLy8gQ29udmVydCBiYXNlNjR1cmwgdG8gYmFzZTY0XG4gICAgICAgIGNvbnN0IGJhc2U2NCA9IGhlYWRlclxuICAgICAgICAgICAgLnJlcGxhY2UoLy0vZywgXCIrXCIpXG4gICAgICAgICAgICAucmVwbGFjZSgvXy9nLCBcIi9cIilcbiAgICAgICAgICAgIC5wYWRFbmQoaGVhZGVyLmxlbmd0aCArICgoNCAtIChoZWFkZXIubGVuZ3RoICUgNCkpICUgNCksIFwiPVwiKTtcbiAgICAgICAgY29uc3QgZGVjb2RlZCA9IEpTT04ucGFyc2UoYXRvYihiYXNlNjQpKTtcbiAgICAgICAgaWYgKHR5cGVvZiBkZWNvZGVkICE9PSBcIm9iamVjdFwiIHx8IGRlY29kZWQgPT09IG51bGwpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIGlmIChcInR5cFwiIGluIGRlY29kZWQgJiYgZGVjb2RlZD8udHlwICE9PSBcIkpXVFwiKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBpZiAoIWRlY29kZWQuYWxnKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBpZiAoYWxnICYmIGRlY29kZWQuYWxnICE9PSBhbGcpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBjYXRjaCB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59XG5mdW5jdGlvbiBpc1ZhbGlkQ2lkcihpcCwgdmVyc2lvbikge1xuICAgIGlmICgodmVyc2lvbiA9PT0gXCJ2NFwiIHx8ICF2ZXJzaW9uKSAmJiBpcHY0Q2lkclJlZ2V4LnRlc3QoaXApKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoKHZlcnNpb24gPT09IFwidjZcIiB8fCAhdmVyc2lvbikgJiYgaXB2NkNpZHJSZWdleC50ZXN0KGlwKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuZXhwb3J0IGNsYXNzIFpvZFN0cmluZyBleHRlbmRzIFpvZFR5cGUge1xuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICBpZiAodGhpcy5fZGVmLmNvZXJjZSkge1xuICAgICAgICAgICAgaW5wdXQuZGF0YSA9IFN0cmluZyhpbnB1dC5kYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7XG4gICAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLnN0cmluZykge1xuICAgICAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpO1xuICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSxcbiAgICAgICAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5zdHJpbmcsXG4gICAgICAgICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzdGF0dXMgPSBuZXcgUGFyc2VTdGF0dXMoKTtcbiAgICAgICAgbGV0IGN0eCA9IHVuZGVmaW5lZDtcbiAgICAgICAgZm9yIChjb25zdCBjaGVjayBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7XG4gICAgICAgICAgICBpZiAoY2hlY2sua2luZCA9PT0gXCJtaW5cIikge1xuICAgICAgICAgICAgICAgIGlmIChpbnB1dC5kYXRhLmxlbmd0aCA8IGNoZWNrLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpO1xuICAgICAgICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsXG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5pbXVtOiBjaGVjay52YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBleGFjdDogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gXCJtYXhcIikge1xuICAgICAgICAgICAgICAgIGlmIChpbnB1dC5kYXRhLmxlbmd0aCA+IGNoZWNrLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpO1xuICAgICAgICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fYmlnLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF4aW11bTogY2hlY2sudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09IFwibGVuZ3RoXCIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0b29CaWcgPSBpbnB1dC5kYXRhLmxlbmd0aCA+IGNoZWNrLnZhbHVlO1xuICAgICAgICAgICAgICAgIGNvbnN0IHRvb1NtYWxsID0gaW5wdXQuZGF0YS5sZW5ndGggPCBjaGVjay52YWx1ZTtcbiAgICAgICAgICAgICAgICBpZiAodG9vQmlnIHx8IHRvb1NtYWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodG9vQmlnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX2JpZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhpbXVtOiBjaGVjay52YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGFjdDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodG9vU21hbGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluaW11bTogY2hlY2sudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhhY3Q6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09IFwiZW1haWxcIikge1xuICAgICAgICAgICAgICAgIGlmICghZW1haWxSZWdleC50ZXN0KGlucHV0LmRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpO1xuICAgICAgICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRpb246IFwiZW1haWxcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcImVtb2ppXCIpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWVtb2ppUmVnZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgZW1vamlSZWdleCA9IG5ldyBSZWdFeHAoX2Vtb2ppUmVnZXgsIFwidVwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFlbW9qaVJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGlvbjogXCJlbW9qaVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09IFwidXVpZFwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF1dWlkUmVnZXgudGVzdChpbnB1dC5kYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTtcbiAgICAgICAgICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0aW9uOiBcInV1aWRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcIm5hbm9pZFwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFuYW5vaWRSZWdleC50ZXN0KGlucHV0LmRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpO1xuICAgICAgICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRpb246IFwibmFub2lkXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gXCJjdWlkXCIpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWN1aWRSZWdleC50ZXN0KGlucHV0LmRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpO1xuICAgICAgICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRpb246IFwiY3VpZFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09IFwiY3VpZDJcIikge1xuICAgICAgICAgICAgICAgIGlmICghY3VpZDJSZWdleC50ZXN0KGlucHV0LmRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpO1xuICAgICAgICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRpb246IFwiY3VpZDJcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcInVsaWRcIikge1xuICAgICAgICAgICAgICAgIGlmICghdWxpZFJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGlvbjogXCJ1bGlkXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gXCJ1cmxcIikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIG5ldyBVUkwoaW5wdXQuZGF0YSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGlvbjogXCJ1cmxcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcInJlZ2V4XCIpIHtcbiAgICAgICAgICAgICAgICBjaGVjay5yZWdleC5sYXN0SW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIGNvbnN0IHRlc3RSZXN1bHQgPSBjaGVjay5yZWdleC50ZXN0KGlucHV0LmRhdGEpO1xuICAgICAgICAgICAgICAgIGlmICghdGVzdFJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTtcbiAgICAgICAgICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0aW9uOiBcInJlZ2V4XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gXCJ0cmltXCIpIHtcbiAgICAgICAgICAgICAgICBpbnB1dC5kYXRhID0gaW5wdXQuZGF0YS50cmltKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcImluY2x1ZGVzXCIpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWlucHV0LmRhdGEuaW5jbHVkZXMoY2hlY2sudmFsdWUsIGNoZWNrLnBvc2l0aW9uKSkge1xuICAgICAgICAgICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTtcbiAgICAgICAgICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0aW9uOiB7IGluY2x1ZGVzOiBjaGVjay52YWx1ZSwgcG9zaXRpb246IGNoZWNrLnBvc2l0aW9uIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gXCJ0b0xvd2VyQ2FzZVwiKSB7XG4gICAgICAgICAgICAgICAgaW5wdXQuZGF0YSA9IGlucHV0LmRhdGEudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09IFwidG9VcHBlckNhc2VcIikge1xuICAgICAgICAgICAgICAgIGlucHV0LmRhdGEgPSBpbnB1dC5kYXRhLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcInN0YXJ0c1dpdGhcIikge1xuICAgICAgICAgICAgICAgIGlmICghaW5wdXQuZGF0YS5zdGFydHNXaXRoKGNoZWNrLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTtcbiAgICAgICAgICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0aW9uOiB7IHN0YXJ0c1dpdGg6IGNoZWNrLnZhbHVlIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gXCJlbmRzV2l0aFwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpbnB1dC5kYXRhLmVuZHNXaXRoKGNoZWNrLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTtcbiAgICAgICAgICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0aW9uOiB7IGVuZHNXaXRoOiBjaGVjay52YWx1ZSB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09IFwiZGF0ZXRpbWVcIikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlZ2V4ID0gZGF0ZXRpbWVSZWdleChjaGVjayk7XG4gICAgICAgICAgICAgICAgaWYgKCFyZWdleC50ZXN0KGlucHV0LmRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpO1xuICAgICAgICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRpb246IFwiZGF0ZXRpbWVcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcImRhdGVcIikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlZ2V4ID0gZGF0ZVJlZ2V4O1xuICAgICAgICAgICAgICAgIGlmICghcmVnZXgudGVzdChpbnB1dC5kYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTtcbiAgICAgICAgICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0aW9uOiBcImRhdGVcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcInRpbWVcIikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlZ2V4ID0gdGltZVJlZ2V4KGNoZWNrKTtcbiAgICAgICAgICAgICAgICBpZiAoIXJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGlvbjogXCJ0aW1lXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gXCJkdXJhdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkdXJhdGlvblJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGlvbjogXCJkdXJhdGlvblwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09IFwiaXBcIikge1xuICAgICAgICAgICAgICAgIGlmICghaXNWYWxpZElQKGlucHV0LmRhdGEsIGNoZWNrLnZlcnNpb24pKSB7XG4gICAgICAgICAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpO1xuICAgICAgICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbGlkYXRpb246IFwiaXBcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcImp3dFwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpc1ZhbGlkSldUKGlucHV0LmRhdGEsIGNoZWNrLmFsZykpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGlvbjogXCJqd3RcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcImNpZHJcIikge1xuICAgICAgICAgICAgICAgIGlmICghaXNWYWxpZENpZHIoaW5wdXQuZGF0YSwgY2hlY2sudmVyc2lvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGlvbjogXCJjaWRyXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gXCJiYXNlNjRcIikge1xuICAgICAgICAgICAgICAgIGlmICghYmFzZTY0UmVnZXgudGVzdChpbnB1dC5kYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTtcbiAgICAgICAgICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZGF0aW9uOiBcImJhc2U2NFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09IFwiYmFzZTY0dXJsXCIpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWJhc2U2NHVybFJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGlvbjogXCJiYXNlNjR1cmxcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB1dGlsLmFzc2VydE5ldmVyKGNoZWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IGlucHV0LmRhdGEgfTtcbiAgICB9XG4gICAgX3JlZ2V4KHJlZ2V4LCB2YWxpZGF0aW9uLCBtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlZmluZW1lbnQoKGRhdGEpID0+IHJlZ2V4LnRlc3QoZGF0YSksIHtcbiAgICAgICAgICAgIHZhbGlkYXRpb24sXG4gICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsXG4gICAgICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBfYWRkQ2hlY2soY2hlY2spIHtcbiAgICAgICAgcmV0dXJuIG5ldyBab2RTdHJpbmcoe1xuICAgICAgICAgICAgLi4udGhpcy5fZGVmLFxuICAgICAgICAgICAgY2hlY2tzOiBbLi4udGhpcy5fZGVmLmNoZWNrcywgY2hlY2tdLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgZW1haWwobWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soeyBraW5kOiBcImVtYWlsXCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTtcbiAgICB9XG4gICAgdXJsKG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogXCJ1cmxcIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pO1xuICAgIH1cbiAgICBlbW9qaShtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7IGtpbmQ6IFwiZW1vamlcIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pO1xuICAgIH1cbiAgICB1dWlkKG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogXCJ1dWlkXCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTtcbiAgICB9XG4gICAgbmFub2lkKG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogXCJuYW5vaWRcIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pO1xuICAgIH1cbiAgICBjdWlkKG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogXCJjdWlkXCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTtcbiAgICB9XG4gICAgY3VpZDIobWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soeyBraW5kOiBcImN1aWQyXCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTtcbiAgICB9XG4gICAgdWxpZChtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7IGtpbmQ6IFwidWxpZFwiLCAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkgfSk7XG4gICAgfVxuICAgIGJhc2U2NChtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7IGtpbmQ6IFwiYmFzZTY0XCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTtcbiAgICB9XG4gICAgYmFzZTY0dXJsKG1lc3NhZ2UpIHtcbiAgICAgICAgLy8gYmFzZTY0dXJsIGVuY29kaW5nIGlzIGEgbW9kaWZpY2F0aW9uIG9mIGJhc2U2NCB0aGF0IGNhbiBzYWZlbHkgYmUgdXNlZCBpbiBVUkxzIGFuZCBmaWxlbmFtZXNcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHtcbiAgICAgICAgICAgIGtpbmQ6IFwiYmFzZTY0dXJsXCIsXG4gICAgICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBqd3Qob3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soeyBraW5kOiBcImp3dFwiLCAuLi5lcnJvclV0aWwuZXJyVG9PYmoob3B0aW9ucykgfSk7XG4gICAgfVxuICAgIGlwKG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogXCJpcFwiLCAuLi5lcnJvclV0aWwuZXJyVG9PYmoob3B0aW9ucykgfSk7XG4gICAgfVxuICAgIGNpZHIob3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soeyBraW5kOiBcImNpZHJcIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG9wdGlvbnMpIH0pO1xuICAgIH1cbiAgICBkYXRldGltZShvcHRpb25zKSB7XG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHtcbiAgICAgICAgICAgICAgICBraW5kOiBcImRhdGV0aW1lXCIsXG4gICAgICAgICAgICAgICAgcHJlY2lzaW9uOiBudWxsLFxuICAgICAgICAgICAgICAgIG9mZnNldDogZmFsc2UsXG4gICAgICAgICAgICAgICAgbG9jYWw6IGZhbHNlLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IG9wdGlvbnMsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soe1xuICAgICAgICAgICAga2luZDogXCJkYXRldGltZVwiLFxuICAgICAgICAgICAgcHJlY2lzaW9uOiB0eXBlb2Ygb3B0aW9ucz8ucHJlY2lzaW9uID09PSBcInVuZGVmaW5lZFwiID8gbnVsbCA6IG9wdGlvbnM/LnByZWNpc2lvbixcbiAgICAgICAgICAgIG9mZnNldDogb3B0aW9ucz8ub2Zmc2V0ID8/IGZhbHNlLFxuICAgICAgICAgICAgbG9jYWw6IG9wdGlvbnM/LmxvY2FsID8/IGZhbHNlLFxuICAgICAgICAgICAgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG9wdGlvbnM/Lm1lc3NhZ2UpLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgZGF0ZShtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7IGtpbmQ6IFwiZGF0ZVwiLCBtZXNzYWdlIH0pO1xuICAgIH1cbiAgICB0aW1lKG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soe1xuICAgICAgICAgICAgICAgIGtpbmQ6IFwidGltZVwiLFxuICAgICAgICAgICAgICAgIHByZWNpc2lvbjogbnVsbCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBvcHRpb25zLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHtcbiAgICAgICAgICAgIGtpbmQ6IFwidGltZVwiLFxuICAgICAgICAgICAgcHJlY2lzaW9uOiB0eXBlb2Ygb3B0aW9ucz8ucHJlY2lzaW9uID09PSBcInVuZGVmaW5lZFwiID8gbnVsbCA6IG9wdGlvbnM/LnByZWNpc2lvbixcbiAgICAgICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihvcHRpb25zPy5tZXNzYWdlKSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGR1cmF0aW9uKG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogXCJkdXJhdGlvblwiLCAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkgfSk7XG4gICAgfVxuICAgIHJlZ2V4KHJlZ2V4LCBtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7XG4gICAgICAgICAgICBraW5kOiBcInJlZ2V4XCIsXG4gICAgICAgICAgICByZWdleDogcmVnZXgsXG4gICAgICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBpbmNsdWRlcyh2YWx1ZSwgb3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soe1xuICAgICAgICAgICAga2luZDogXCJpbmNsdWRlc1wiLFxuICAgICAgICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgcG9zaXRpb246IG9wdGlvbnM/LnBvc2l0aW9uLFxuICAgICAgICAgICAgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG9wdGlvbnM/Lm1lc3NhZ2UpLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgc3RhcnRzV2l0aCh2YWx1ZSwgbWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soe1xuICAgICAgICAgICAga2luZDogXCJzdGFydHNXaXRoXCIsXG4gICAgICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbmRzV2l0aCh2YWx1ZSwgbWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soe1xuICAgICAgICAgICAga2luZDogXCJlbmRzV2l0aFwiLFxuICAgICAgICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgbWluKG1pbkxlbmd0aCwgbWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soe1xuICAgICAgICAgICAga2luZDogXCJtaW5cIixcbiAgICAgICAgICAgIHZhbHVlOiBtaW5MZW5ndGgsXG4gICAgICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBtYXgobWF4TGVuZ3RoLCBtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7XG4gICAgICAgICAgICBraW5kOiBcIm1heFwiLFxuICAgICAgICAgICAgdmFsdWU6IG1heExlbmd0aCxcbiAgICAgICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGxlbmd0aChsZW4sIG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHtcbiAgICAgICAgICAgIGtpbmQ6IFwibGVuZ3RoXCIsXG4gICAgICAgICAgICB2YWx1ZTogbGVuLFxuICAgICAgICAgICAgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRXF1aXZhbGVudCB0byBgLm1pbigxKWBcbiAgICAgKi9cbiAgICBub25lbXB0eShtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1pbigxLCBlcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkpO1xuICAgIH1cbiAgICB0cmltKCkge1xuICAgICAgICByZXR1cm4gbmV3IFpvZFN0cmluZyh7XG4gICAgICAgICAgICAuLi50aGlzLl9kZWYsXG4gICAgICAgICAgICBjaGVja3M6IFsuLi50aGlzLl9kZWYuY2hlY2tzLCB7IGtpbmQ6IFwidHJpbVwiIH1dLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgdG9Mb3dlckNhc2UoKSB7XG4gICAgICAgIHJldHVybiBuZXcgWm9kU3RyaW5nKHtcbiAgICAgICAgICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgICAgIGNoZWNrczogWy4uLnRoaXMuX2RlZi5jaGVja3MsIHsga2luZDogXCJ0b0xvd2VyQ2FzZVwiIH1dLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgdG9VcHBlckNhc2UoKSB7XG4gICAgICAgIHJldHVybiBuZXcgWm9kU3RyaW5nKHtcbiAgICAgICAgICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgICAgIGNoZWNrczogWy4uLnRoaXMuX2RlZi5jaGVja3MsIHsga2luZDogXCJ0b1VwcGVyQ2FzZVwiIH1dLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgZ2V0IGlzRGF0ZXRpbWUoKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09IFwiZGF0ZXRpbWVcIik7XG4gICAgfVxuICAgIGdldCBpc0RhdGUoKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09IFwiZGF0ZVwiKTtcbiAgICB9XG4gICAgZ2V0IGlzVGltZSgpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gXCJ0aW1lXCIpO1xuICAgIH1cbiAgICBnZXQgaXNEdXJhdGlvbigpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gXCJkdXJhdGlvblwiKTtcbiAgICB9XG4gICAgZ2V0IGlzRW1haWwoKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09IFwiZW1haWxcIik7XG4gICAgfVxuICAgIGdldCBpc1VSTCgpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gXCJ1cmxcIik7XG4gICAgfVxuICAgIGdldCBpc0Vtb2ppKCkge1xuICAgICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSBcImVtb2ppXCIpO1xuICAgIH1cbiAgICBnZXQgaXNVVUlEKCkge1xuICAgICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSBcInV1aWRcIik7XG4gICAgfVxuICAgIGdldCBpc05BTk9JRCgpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gXCJuYW5vaWRcIik7XG4gICAgfVxuICAgIGdldCBpc0NVSUQoKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09IFwiY3VpZFwiKTtcbiAgICB9XG4gICAgZ2V0IGlzQ1VJRDIoKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09IFwiY3VpZDJcIik7XG4gICAgfVxuICAgIGdldCBpc1VMSUQoKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09IFwidWxpZFwiKTtcbiAgICB9XG4gICAgZ2V0IGlzSVAoKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09IFwiaXBcIik7XG4gICAgfVxuICAgIGdldCBpc0NJRFIoKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09IFwiY2lkclwiKTtcbiAgICB9XG4gICAgZ2V0IGlzQmFzZTY0KCkge1xuICAgICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSBcImJhc2U2NFwiKTtcbiAgICB9XG4gICAgZ2V0IGlzQmFzZTY0dXJsKCkge1xuICAgICAgICAvLyBiYXNlNjR1cmwgZW5jb2RpbmcgaXMgYSBtb2RpZmljYXRpb24gb2YgYmFzZTY0IHRoYXQgY2FuIHNhZmVseSBiZSB1c2VkIGluIFVSTHMgYW5kIGZpbGVuYW1lc1xuICAgICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSBcImJhc2U2NHVybFwiKTtcbiAgICB9XG4gICAgZ2V0IG1pbkxlbmd0aCgpIHtcbiAgICAgICAgbGV0IG1pbiA9IG51bGw7XG4gICAgICAgIGZvciAoY29uc3QgY2ggb2YgdGhpcy5fZGVmLmNoZWNrcykge1xuICAgICAgICAgICAgaWYgKGNoLmtpbmQgPT09IFwibWluXCIpIHtcbiAgICAgICAgICAgICAgICBpZiAobWluID09PSBudWxsIHx8IGNoLnZhbHVlID4gbWluKVxuICAgICAgICAgICAgICAgICAgICBtaW4gPSBjaC52YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWluO1xuICAgIH1cbiAgICBnZXQgbWF4TGVuZ3RoKCkge1xuICAgICAgICBsZXQgbWF4ID0gbnVsbDtcbiAgICAgICAgZm9yIChjb25zdCBjaCBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7XG4gICAgICAgICAgICBpZiAoY2gua2luZCA9PT0gXCJtYXhcIikge1xuICAgICAgICAgICAgICAgIGlmIChtYXggPT09IG51bGwgfHwgY2gudmFsdWUgPCBtYXgpXG4gICAgICAgICAgICAgICAgICAgIG1heCA9IGNoLnZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtYXg7XG4gICAgfVxufVxuWm9kU3RyaW5nLmNyZWF0ZSA9IChwYXJhbXMpID0+IHtcbiAgICByZXR1cm4gbmV3IFpvZFN0cmluZyh7XG4gICAgICAgIGNoZWNrczogW10sXG4gICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kU3RyaW5nLFxuICAgICAgICBjb2VyY2U6IHBhcmFtcz8uY29lcmNlID8/IGZhbHNlLFxuICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgfSk7XG59O1xuLy8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMzk2NjQ4NC93aHktZG9lcy1tb2R1bHVzLW9wZXJhdG9yLXJldHVybi1mcmFjdGlvbmFsLW51bWJlci1pbi1qYXZhc2NyaXB0LzMxNzExMDM0IzMxNzExMDM0XG5mdW5jdGlvbiBmbG9hdFNhZmVSZW1haW5kZXIodmFsLCBzdGVwKSB7XG4gICAgY29uc3QgdmFsRGVjQ291bnQgPSAodmFsLnRvU3RyaW5nKCkuc3BsaXQoXCIuXCIpWzFdIHx8IFwiXCIpLmxlbmd0aDtcbiAgICBjb25zdCBzdGVwRGVjQ291bnQgPSAoc3RlcC50b1N0cmluZygpLnNwbGl0KFwiLlwiKVsxXSB8fCBcIlwiKS5sZW5ndGg7XG4gICAgY29uc3QgZGVjQ291bnQgPSB2YWxEZWNDb3VudCA+IHN0ZXBEZWNDb3VudCA/IHZhbERlY0NvdW50IDogc3RlcERlY0NvdW50O1xuICAgIGNvbnN0IHZhbEludCA9IE51bWJlci5wYXJzZUludCh2YWwudG9GaXhlZChkZWNDb3VudCkucmVwbGFjZShcIi5cIiwgXCJcIikpO1xuICAgIGNvbnN0IHN0ZXBJbnQgPSBOdW1iZXIucGFyc2VJbnQoc3RlcC50b0ZpeGVkKGRlY0NvdW50KS5yZXBsYWNlKFwiLlwiLCBcIlwiKSk7XG4gICAgcmV0dXJuICh2YWxJbnQgJSBzdGVwSW50KSAvIDEwICoqIGRlY0NvdW50O1xufVxuZXhwb3J0IGNsYXNzIFpvZE51bWJlciBleHRlbmRzIFpvZFR5cGUge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLm1pbiA9IHRoaXMuZ3RlO1xuICAgICAgICB0aGlzLm1heCA9IHRoaXMubHRlO1xuICAgICAgICB0aGlzLnN0ZXAgPSB0aGlzLm11bHRpcGxlT2Y7XG4gICAgfVxuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICBpZiAodGhpcy5fZGVmLmNvZXJjZSkge1xuICAgICAgICAgICAgaW5wdXQuZGF0YSA9IE51bWJlcihpbnB1dC5kYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7XG4gICAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm51bWJlcikge1xuICAgICAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpO1xuICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSxcbiAgICAgICAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5udW1iZXIsXG4gICAgICAgICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgfVxuICAgICAgICBsZXQgY3R4ID0gdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBzdGF0dXMgPSBuZXcgUGFyc2VTdGF0dXMoKTtcbiAgICAgICAgZm9yIChjb25zdCBjaGVjayBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7XG4gICAgICAgICAgICBpZiAoY2hlY2sua2luZCA9PT0gXCJpbnRcIikge1xuICAgICAgICAgICAgICAgIGlmICghdXRpbC5pc0ludGVnZXIoaW5wdXQuZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVjdGVkOiBcImludGVnZXJcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmVkOiBcImZsb2F0XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gXCJtaW5cIikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRvb1NtYWxsID0gY2hlY2suaW5jbHVzaXZlID8gaW5wdXQuZGF0YSA8IGNoZWNrLnZhbHVlIDogaW5wdXQuZGF0YSA8PSBjaGVjay52YWx1ZTtcbiAgICAgICAgICAgICAgICBpZiAodG9vU21hbGwpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19zbWFsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbmltdW06IGNoZWNrLnZhbHVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJudW1iZXJcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1c2l2ZTogY2hlY2suaW5jbHVzaXZlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09IFwibWF4XCIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0b29CaWcgPSBjaGVjay5pbmNsdXNpdmUgPyBpbnB1dC5kYXRhID4gY2hlY2sudmFsdWUgOiBpbnB1dC5kYXRhID49IGNoZWNrLnZhbHVlO1xuICAgICAgICAgICAgICAgIGlmICh0b29CaWcpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19iaWcsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhpbXVtOiBjaGVjay52YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwibnVtYmVyXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbmNsdXNpdmU6IGNoZWNrLmluY2x1c2l2ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcIm11bHRpcGxlT2ZcIikge1xuICAgICAgICAgICAgICAgIGlmIChmbG9hdFNhZmVSZW1haW5kZXIoaW5wdXQuZGF0YSwgY2hlY2sudmFsdWUpICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpO1xuICAgICAgICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5ub3RfbXVsdGlwbGVfb2YsXG4gICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZU9mOiBjaGVjay52YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcImZpbml0ZVwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFOdW1iZXIuaXNGaW5pdGUoaW5wdXQuZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLm5vdF9maW5pdGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdXRpbC5hc3NlcnROZXZlcihjaGVjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBpbnB1dC5kYXRhIH07XG4gICAgfVxuICAgIGd0ZSh2YWx1ZSwgbWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdChcIm1pblwiLCB2YWx1ZSwgdHJ1ZSwgZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpKTtcbiAgICB9XG4gICAgZ3QodmFsdWUsIG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2V0TGltaXQoXCJtaW5cIiwgdmFsdWUsIGZhbHNlLCBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkpO1xuICAgIH1cbiAgICBsdGUodmFsdWUsIG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2V0TGltaXQoXCJtYXhcIiwgdmFsdWUsIHRydWUsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7XG4gICAgfVxuICAgIGx0KHZhbHVlLCBtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KFwibWF4XCIsIHZhbHVlLCBmYWxzZSwgZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpKTtcbiAgICB9XG4gICAgc2V0TGltaXQoa2luZCwgdmFsdWUsIGluY2x1c2l2ZSwgbWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gbmV3IFpvZE51bWJlcih7XG4gICAgICAgICAgICAuLi50aGlzLl9kZWYsXG4gICAgICAgICAgICBjaGVja3M6IFtcbiAgICAgICAgICAgICAgICAuLi50aGlzLl9kZWYuY2hlY2tzLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAga2luZCxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIGluY2x1c2l2ZSxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgX2FkZENoZWNrKGNoZWNrKSB7XG4gICAgICAgIHJldHVybiBuZXcgWm9kTnVtYmVyKHtcbiAgICAgICAgICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgICAgIGNoZWNrczogWy4uLnRoaXMuX2RlZi5jaGVja3MsIGNoZWNrXSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGludChtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7XG4gICAgICAgICAgICBraW5kOiBcImludFwiLFxuICAgICAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcG9zaXRpdmUobWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soe1xuICAgICAgICAgICAga2luZDogXCJtaW5cIixcbiAgICAgICAgICAgIHZhbHVlOiAwLFxuICAgICAgICAgICAgaW5jbHVzaXZlOiBmYWxzZSxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIG5lZ2F0aXZlKG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHtcbiAgICAgICAgICAgIGtpbmQ6IFwibWF4XCIsXG4gICAgICAgICAgICB2YWx1ZTogMCxcbiAgICAgICAgICAgIGluY2x1c2l2ZTogZmFsc2UsXG4gICAgICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBub25wb3NpdGl2ZShtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7XG4gICAgICAgICAgICBraW5kOiBcIm1heFwiLFxuICAgICAgICAgICAgdmFsdWU6IDAsXG4gICAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsXG4gICAgICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBub25uZWdhdGl2ZShtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7XG4gICAgICAgICAgICBraW5kOiBcIm1pblwiLFxuICAgICAgICAgICAgdmFsdWU6IDAsXG4gICAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsXG4gICAgICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBtdWx0aXBsZU9mKHZhbHVlLCBtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7XG4gICAgICAgICAgICBraW5kOiBcIm11bHRpcGxlT2ZcIixcbiAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGZpbml0ZShtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7XG4gICAgICAgICAgICBraW5kOiBcImZpbml0ZVwiLFxuICAgICAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgc2FmZShtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7XG4gICAgICAgICAgICBraW5kOiBcIm1pblwiLFxuICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLFxuICAgICAgICAgICAgdmFsdWU6IE51bWJlci5NSU5fU0FGRV9JTlRFR0VSLFxuICAgICAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpLFxuICAgICAgICB9KS5fYWRkQ2hlY2soe1xuICAgICAgICAgICAga2luZDogXCJtYXhcIixcbiAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSxcbiAgICAgICAgICAgIHZhbHVlOiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUixcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGdldCBtaW5WYWx1ZSgpIHtcbiAgICAgICAgbGV0IG1pbiA9IG51bGw7XG4gICAgICAgIGZvciAoY29uc3QgY2ggb2YgdGhpcy5fZGVmLmNoZWNrcykge1xuICAgICAgICAgICAgaWYgKGNoLmtpbmQgPT09IFwibWluXCIpIHtcbiAgICAgICAgICAgICAgICBpZiAobWluID09PSBudWxsIHx8IGNoLnZhbHVlID4gbWluKVxuICAgICAgICAgICAgICAgICAgICBtaW4gPSBjaC52YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWluO1xuICAgIH1cbiAgICBnZXQgbWF4VmFsdWUoKSB7XG4gICAgICAgIGxldCBtYXggPSBudWxsO1xuICAgICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHtcbiAgICAgICAgICAgIGlmIChjaC5raW5kID09PSBcIm1heFwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKG1heCA9PT0gbnVsbCB8fCBjaC52YWx1ZSA8IG1heClcbiAgICAgICAgICAgICAgICAgICAgbWF4ID0gY2gudmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1heDtcbiAgICB9XG4gICAgZ2V0IGlzSW50KCkge1xuICAgICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSBcImludFwiIHx8IChjaC5raW5kID09PSBcIm11bHRpcGxlT2ZcIiAmJiB1dGlsLmlzSW50ZWdlcihjaC52YWx1ZSkpKTtcbiAgICB9XG4gICAgZ2V0IGlzRmluaXRlKCkge1xuICAgICAgICBsZXQgbWF4ID0gbnVsbDtcbiAgICAgICAgbGV0IG1pbiA9IG51bGw7XG4gICAgICAgIGZvciAoY29uc3QgY2ggb2YgdGhpcy5fZGVmLmNoZWNrcykge1xuICAgICAgICAgICAgaWYgKGNoLmtpbmQgPT09IFwiZmluaXRlXCIgfHwgY2gua2luZCA9PT0gXCJpbnRcIiB8fCBjaC5raW5kID09PSBcIm11bHRpcGxlT2ZcIikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY2gua2luZCA9PT0gXCJtaW5cIikge1xuICAgICAgICAgICAgICAgIGlmIChtaW4gPT09IG51bGwgfHwgY2gudmFsdWUgPiBtaW4pXG4gICAgICAgICAgICAgICAgICAgIG1pbiA9IGNoLnZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY2gua2luZCA9PT0gXCJtYXhcIikge1xuICAgICAgICAgICAgICAgIGlmIChtYXggPT09IG51bGwgfHwgY2gudmFsdWUgPCBtYXgpXG4gICAgICAgICAgICAgICAgICAgIG1heCA9IGNoLnZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBOdW1iZXIuaXNGaW5pdGUobWluKSAmJiBOdW1iZXIuaXNGaW5pdGUobWF4KTtcbiAgICB9XG59XG5ab2ROdW1iZXIuY3JlYXRlID0gKHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kTnVtYmVyKHtcbiAgICAgICAgY2hlY2tzOiBbXSxcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2ROdW1iZXIsXG4gICAgICAgIGNvZXJjZTogcGFyYW1zPy5jb2VyY2UgfHwgZmFsc2UsXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5leHBvcnQgY2xhc3MgWm9kQmlnSW50IGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMubWluID0gdGhpcy5ndGU7XG4gICAgICAgIHRoaXMubWF4ID0gdGhpcy5sdGU7XG4gICAgfVxuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICBpZiAodGhpcy5fZGVmLmNvZXJjZSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpbnB1dC5kYXRhID0gQmlnSW50KGlucHV0LmRhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2gge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9nZXRJbnZhbGlkSW5wdXQoaW5wdXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTtcbiAgICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUuYmlnaW50KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fZ2V0SW52YWxpZElucHV0KGlucHV0KTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgY3R4ID0gdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBzdGF0dXMgPSBuZXcgUGFyc2VTdGF0dXMoKTtcbiAgICAgICAgZm9yIChjb25zdCBjaGVjayBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7XG4gICAgICAgICAgICBpZiAoY2hlY2sua2luZCA9PT0gXCJtaW5cIikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRvb1NtYWxsID0gY2hlY2suaW5jbHVzaXZlID8gaW5wdXQuZGF0YSA8IGNoZWNrLnZhbHVlIDogaW5wdXQuZGF0YSA8PSBjaGVjay52YWx1ZTtcbiAgICAgICAgICAgICAgICBpZiAodG9vU21hbGwpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19zbWFsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwiYmlnaW50XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5pbXVtOiBjaGVjay52YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1c2l2ZTogY2hlY2suaW5jbHVzaXZlLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09IFwibWF4XCIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0b29CaWcgPSBjaGVjay5pbmNsdXNpdmUgPyBpbnB1dC5kYXRhID4gY2hlY2sudmFsdWUgOiBpbnB1dC5kYXRhID49IGNoZWNrLnZhbHVlO1xuICAgICAgICAgICAgICAgIGlmICh0b29CaWcpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19iaWcsXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcImJpZ2ludFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF4aW11bTogY2hlY2sudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbmNsdXNpdmU6IGNoZWNrLmluY2x1c2l2ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcIm11bHRpcGxlT2ZcIikge1xuICAgICAgICAgICAgICAgIGlmIChpbnB1dC5kYXRhICUgY2hlY2sudmFsdWUgIT09IEJpZ0ludCgwKSkge1xuICAgICAgICAgICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTtcbiAgICAgICAgICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUubm90X211bHRpcGxlX29mLFxuICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGVPZjogY2hlY2sudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdXRpbC5hc3NlcnROZXZlcihjaGVjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBpbnB1dC5kYXRhIH07XG4gICAgfVxuICAgIF9nZXRJbnZhbGlkSW5wdXQoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpO1xuICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsXG4gICAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5iaWdpbnQsXG4gICAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICB9XG4gICAgZ3RlKHZhbHVlLCBtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KFwibWluXCIsIHZhbHVlLCB0cnVlLCBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkpO1xuICAgIH1cbiAgICBndCh2YWx1ZSwgbWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdChcIm1pblwiLCB2YWx1ZSwgZmFsc2UsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7XG4gICAgfVxuICAgIGx0ZSh2YWx1ZSwgbWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdChcIm1heFwiLCB2YWx1ZSwgdHJ1ZSwgZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpKTtcbiAgICB9XG4gICAgbHQodmFsdWUsIG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2V0TGltaXQoXCJtYXhcIiwgdmFsdWUsIGZhbHNlLCBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkpO1xuICAgIH1cbiAgICBzZXRMaW1pdChraW5kLCB2YWx1ZSwgaW5jbHVzaXZlLCBtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiBuZXcgWm9kQmlnSW50KHtcbiAgICAgICAgICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgICAgIGNoZWNrczogW1xuICAgICAgICAgICAgICAgIC4uLnRoaXMuX2RlZi5jaGVja3MsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBraW5kLFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgaW5jbHVzaXZlLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSksXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBfYWRkQ2hlY2soY2hlY2spIHtcbiAgICAgICAgcmV0dXJuIG5ldyBab2RCaWdJbnQoe1xuICAgICAgICAgICAgLi4udGhpcy5fZGVmLFxuICAgICAgICAgICAgY2hlY2tzOiBbLi4udGhpcy5fZGVmLmNoZWNrcywgY2hlY2tdLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcG9zaXRpdmUobWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soe1xuICAgICAgICAgICAga2luZDogXCJtaW5cIixcbiAgICAgICAgICAgIHZhbHVlOiBCaWdJbnQoMCksXG4gICAgICAgICAgICBpbmNsdXNpdmU6IGZhbHNlLFxuICAgICAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgbmVnYXRpdmUobWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soe1xuICAgICAgICAgICAga2luZDogXCJtYXhcIixcbiAgICAgICAgICAgIHZhbHVlOiBCaWdJbnQoMCksXG4gICAgICAgICAgICBpbmNsdXNpdmU6IGZhbHNlLFxuICAgICAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgbm9ucG9zaXRpdmUobWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soe1xuICAgICAgICAgICAga2luZDogXCJtYXhcIixcbiAgICAgICAgICAgIHZhbHVlOiBCaWdJbnQoMCksXG4gICAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsXG4gICAgICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBub25uZWdhdGl2ZShtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7XG4gICAgICAgICAgICBraW5kOiBcIm1pblwiLFxuICAgICAgICAgICAgdmFsdWU6IEJpZ0ludCgwKSxcbiAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIG11bHRpcGxlT2YodmFsdWUsIG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHtcbiAgICAgICAgICAgIGtpbmQ6IFwibXVsdGlwbGVPZlwiLFxuICAgICAgICAgICAgdmFsdWUsXG4gICAgICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBnZXQgbWluVmFsdWUoKSB7XG4gICAgICAgIGxldCBtaW4gPSBudWxsO1xuICAgICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHtcbiAgICAgICAgICAgIGlmIChjaC5raW5kID09PSBcIm1pblwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKG1pbiA9PT0gbnVsbCB8fCBjaC52YWx1ZSA+IG1pbilcbiAgICAgICAgICAgICAgICAgICAgbWluID0gY2gudmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1pbjtcbiAgICB9XG4gICAgZ2V0IG1heFZhbHVlKCkge1xuICAgICAgICBsZXQgbWF4ID0gbnVsbDtcbiAgICAgICAgZm9yIChjb25zdCBjaCBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7XG4gICAgICAgICAgICBpZiAoY2gua2luZCA9PT0gXCJtYXhcIikge1xuICAgICAgICAgICAgICAgIGlmIChtYXggPT09IG51bGwgfHwgY2gudmFsdWUgPCBtYXgpXG4gICAgICAgICAgICAgICAgICAgIG1heCA9IGNoLnZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtYXg7XG4gICAgfVxufVxuWm9kQmlnSW50LmNyZWF0ZSA9IChwYXJhbXMpID0+IHtcbiAgICByZXR1cm4gbmV3IFpvZEJpZ0ludCh7XG4gICAgICAgIGNoZWNrczogW10sXG4gICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kQmlnSW50LFxuICAgICAgICBjb2VyY2U6IHBhcmFtcz8uY29lcmNlID8/IGZhbHNlLFxuICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgfSk7XG59O1xuZXhwb3J0IGNsYXNzIFpvZEJvb2xlYW4gZXh0ZW5kcyBab2RUeXBlIHtcbiAgICBfcGFyc2UoaW5wdXQpIHtcbiAgICAgICAgaWYgKHRoaXMuX2RlZi5jb2VyY2UpIHtcbiAgICAgICAgICAgIGlucHV0LmRhdGEgPSBCb29sZWFuKGlucHV0LmRhdGEpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTtcbiAgICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUuYm9vbGVhbikge1xuICAgICAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpO1xuICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSxcbiAgICAgICAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5ib29sZWFuLFxuICAgICAgICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIE9LKGlucHV0LmRhdGEpO1xuICAgIH1cbn1cblpvZEJvb2xlYW4uY3JlYXRlID0gKHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kQm9vbGVhbih7XG4gICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kQm9vbGVhbixcbiAgICAgICAgY29lcmNlOiBwYXJhbXM/LmNvZXJjZSB8fCBmYWxzZSxcbiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpLFxuICAgIH0pO1xufTtcbmV4cG9ydCBjbGFzcyBab2REYXRlIGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgX3BhcnNlKGlucHV0KSB7XG4gICAgICAgIGlmICh0aGlzLl9kZWYuY29lcmNlKSB7XG4gICAgICAgICAgICBpbnB1dC5kYXRhID0gbmV3IERhdGUoaW5wdXQuZGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpO1xuICAgICAgICBpZiAocGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5kYXRlKSB7XG4gICAgICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7XG4gICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLFxuICAgICAgICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmRhdGUsXG4gICAgICAgICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoTnVtYmVyLmlzTmFOKGlucHV0LmRhdGEuZ2V0VGltZSgpKSkge1xuICAgICAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpO1xuICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfZGF0ZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc3RhdHVzID0gbmV3IFBhcnNlU3RhdHVzKCk7XG4gICAgICAgIGxldCBjdHggPSB1bmRlZmluZWQ7XG4gICAgICAgIGZvciAoY29uc3QgY2hlY2sgb2YgdGhpcy5fZGVmLmNoZWNrcykge1xuICAgICAgICAgICAgaWYgKGNoZWNrLmtpbmQgPT09IFwibWluXCIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5wdXQuZGF0YS5nZXRUaW1lKCkgPCBjaGVjay52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTtcbiAgICAgICAgICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbmltdW06IGNoZWNrLnZhbHVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJkYXRlXCIsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGVjay5raW5kID09PSBcIm1heFwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlucHV0LmRhdGEuZ2V0VGltZSgpID4gY2hlY2sudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19iaWcsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF4aW11bTogY2hlY2sudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcImRhdGVcIixcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHV0aWwuYXNzZXJ0TmV2ZXIoY2hlY2spO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdGF0dXM6IHN0YXR1cy52YWx1ZSxcbiAgICAgICAgICAgIHZhbHVlOiBuZXcgRGF0ZShpbnB1dC5kYXRhLmdldFRpbWUoKSksXG4gICAgICAgIH07XG4gICAgfVxuICAgIF9hZGRDaGVjayhjaGVjaykge1xuICAgICAgICByZXR1cm4gbmV3IFpvZERhdGUoe1xuICAgICAgICAgICAgLi4udGhpcy5fZGVmLFxuICAgICAgICAgICAgY2hlY2tzOiBbLi4udGhpcy5fZGVmLmNoZWNrcywgY2hlY2tdLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgbWluKG1pbkRhdGUsIG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHtcbiAgICAgICAgICAgIGtpbmQ6IFwibWluXCIsXG4gICAgICAgICAgICB2YWx1ZTogbWluRGF0ZS5nZXRUaW1lKCksXG4gICAgICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBtYXgobWF4RGF0ZSwgbWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soe1xuICAgICAgICAgICAga2luZDogXCJtYXhcIixcbiAgICAgICAgICAgIHZhbHVlOiBtYXhEYXRlLmdldFRpbWUoKSxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGdldCBtaW5EYXRlKCkge1xuICAgICAgICBsZXQgbWluID0gbnVsbDtcbiAgICAgICAgZm9yIChjb25zdCBjaCBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7XG4gICAgICAgICAgICBpZiAoY2gua2luZCA9PT0gXCJtaW5cIikge1xuICAgICAgICAgICAgICAgIGlmIChtaW4gPT09IG51bGwgfHwgY2gudmFsdWUgPiBtaW4pXG4gICAgICAgICAgICAgICAgICAgIG1pbiA9IGNoLnZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtaW4gIT0gbnVsbCA/IG5ldyBEYXRlKG1pbikgOiBudWxsO1xuICAgIH1cbiAgICBnZXQgbWF4RGF0ZSgpIHtcbiAgICAgICAgbGV0IG1heCA9IG51bGw7XG4gICAgICAgIGZvciAoY29uc3QgY2ggb2YgdGhpcy5fZGVmLmNoZWNrcykge1xuICAgICAgICAgICAgaWYgKGNoLmtpbmQgPT09IFwibWF4XCIpIHtcbiAgICAgICAgICAgICAgICBpZiAobWF4ID09PSBudWxsIHx8IGNoLnZhbHVlIDwgbWF4KVxuICAgICAgICAgICAgICAgICAgICBtYXggPSBjaC52YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWF4ICE9IG51bGwgPyBuZXcgRGF0ZShtYXgpIDogbnVsbDtcbiAgICB9XG59XG5ab2REYXRlLmNyZWF0ZSA9IChwYXJhbXMpID0+IHtcbiAgICByZXR1cm4gbmV3IFpvZERhdGUoe1xuICAgICAgICBjaGVja3M6IFtdLFxuICAgICAgICBjb2VyY2U6IHBhcmFtcz8uY29lcmNlIHx8IGZhbHNlLFxuICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZERhdGUsXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5leHBvcnQgY2xhc3MgWm9kU3ltYm9sIGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgX3BhcnNlKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTtcbiAgICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUuc3ltYm9sKSB7XG4gICAgICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7XG4gICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLFxuICAgICAgICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLnN5bWJvbCxcbiAgICAgICAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBPSyhpbnB1dC5kYXRhKTtcbiAgICB9XG59XG5ab2RTeW1ib2wuY3JlYXRlID0gKHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kU3ltYm9sKHtcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RTeW1ib2wsXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5leHBvcnQgY2xhc3MgWm9kVW5kZWZpbmVkIGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgX3BhcnNlKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTtcbiAgICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7XG4gICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLFxuICAgICAgICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLnVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBPSyhpbnB1dC5kYXRhKTtcbiAgICB9XG59XG5ab2RVbmRlZmluZWQuY3JlYXRlID0gKHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kVW5kZWZpbmVkKHtcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RVbmRlZmluZWQsXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5leHBvcnQgY2xhc3MgWm9kTnVsbCBleHRlbmRzIFpvZFR5cGUge1xuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7XG4gICAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm51bGwpIHtcbiAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTtcbiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsXG4gICAgICAgICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUubnVsbCxcbiAgICAgICAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBPSyhpbnB1dC5kYXRhKTtcbiAgICB9XG59XG5ab2ROdWxsLmNyZWF0ZSA9IChwYXJhbXMpID0+IHtcbiAgICByZXR1cm4gbmV3IFpvZE51bGwoe1xuICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE51bGwsXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5leHBvcnQgY2xhc3MgWm9kQW55IGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIC8vIHRvIHByZXZlbnQgaW5zdGFuY2VzIG9mIG90aGVyIGNsYXNzZXMgZnJvbSBleHRlbmRpbmcgWm9kQW55LiB0aGlzIGNhdXNlcyBpc3N1ZXMgd2l0aCBjYXRjaGFsbCBpbiBab2RPYmplY3QuXG4gICAgICAgIHRoaXMuX2FueSA9IHRydWU7XG4gICAgfVxuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICByZXR1cm4gT0soaW5wdXQuZGF0YSk7XG4gICAgfVxufVxuWm9kQW55LmNyZWF0ZSA9IChwYXJhbXMpID0+IHtcbiAgICByZXR1cm4gbmV3IFpvZEFueSh7XG4gICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kQW55LFxuICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgfSk7XG59O1xuZXhwb3J0IGNsYXNzIFpvZFVua25vd24gZXh0ZW5kcyBab2RUeXBlIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgLy8gcmVxdWlyZWRcbiAgICAgICAgdGhpcy5fdW5rbm93biA9IHRydWU7XG4gICAgfVxuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICByZXR1cm4gT0soaW5wdXQuZGF0YSk7XG4gICAgfVxufVxuWm9kVW5rbm93bi5jcmVhdGUgPSAocGFyYW1zKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBab2RVbmtub3duKHtcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RVbmtub3duLFxuICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgfSk7XG59O1xuZXhwb3J0IGNsYXNzIFpvZE5ldmVyIGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgX3BhcnNlKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTtcbiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLFxuICAgICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUubmV2ZXIsXG4gICAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICB9XG59XG5ab2ROZXZlci5jcmVhdGUgPSAocGFyYW1zKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBab2ROZXZlcih7XG4gICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kTmV2ZXIsXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5leHBvcnQgY2xhc3MgWm9kVm9pZCBleHRlbmRzIFpvZFR5cGUge1xuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7XG4gICAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLnVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpO1xuICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSxcbiAgICAgICAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS52b2lkLFxuICAgICAgICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIE9LKGlucHV0LmRhdGEpO1xuICAgIH1cbn1cblpvZFZvaWQuY3JlYXRlID0gKHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kVm9pZCh7XG4gICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kVm9pZCxcbiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpLFxuICAgIH0pO1xufTtcbmV4cG9ydCBjbGFzcyBab2RBcnJheSBleHRlbmRzIFpvZFR5cGUge1xuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICBjb25zdCB7IGN0eCwgc3RhdHVzIH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpO1xuICAgICAgICBjb25zdCBkZWYgPSB0aGlzLl9kZWY7XG4gICAgICAgIGlmIChjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5hcnJheSkge1xuICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSxcbiAgICAgICAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5hcnJheSxcbiAgICAgICAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkZWYuZXhhY3RMZW5ndGggIT09IG51bGwpIHtcbiAgICAgICAgICAgIGNvbnN0IHRvb0JpZyA9IGN0eC5kYXRhLmxlbmd0aCA+IGRlZi5leGFjdExlbmd0aC52YWx1ZTtcbiAgICAgICAgICAgIGNvbnN0IHRvb1NtYWxsID0gY3R4LmRhdGEubGVuZ3RoIDwgZGVmLmV4YWN0TGVuZ3RoLnZhbHVlO1xuICAgICAgICAgICAgaWYgKHRvb0JpZyB8fCB0b29TbWFsbCkge1xuICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICBjb2RlOiB0b29CaWcgPyBab2RJc3N1ZUNvZGUudG9vX2JpZyA6IFpvZElzc3VlQ29kZS50b29fc21hbGwsXG4gICAgICAgICAgICAgICAgICAgIG1pbmltdW06ICh0b29TbWFsbCA/IGRlZi5leGFjdExlbmd0aC52YWx1ZSA6IHVuZGVmaW5lZCksXG4gICAgICAgICAgICAgICAgICAgIG1heGltdW06ICh0b29CaWcgPyBkZWYuZXhhY3RMZW5ndGgudmFsdWUgOiB1bmRlZmluZWQpLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiBcImFycmF5XCIsXG4gICAgICAgICAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgZXhhY3Q6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGRlZi5leGFjdExlbmd0aC5tZXNzYWdlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChkZWYubWluTGVuZ3RoICE9PSBudWxsKSB7XG4gICAgICAgICAgICBpZiAoY3R4LmRhdGEubGVuZ3RoIDwgZGVmLm1pbkxlbmd0aC52YWx1ZSkge1xuICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLFxuICAgICAgICAgICAgICAgICAgICBtaW5pbXVtOiBkZWYubWluTGVuZ3RoLnZhbHVlLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiBcImFycmF5XCIsXG4gICAgICAgICAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBkZWYubWluTGVuZ3RoLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRlZi5tYXhMZW5ndGggIT09IG51bGwpIHtcbiAgICAgICAgICAgIGlmIChjdHguZGF0YS5sZW5ndGggPiBkZWYubWF4TGVuZ3RoLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fYmlnLFxuICAgICAgICAgICAgICAgICAgICBtYXhpbXVtOiBkZWYubWF4TGVuZ3RoLnZhbHVlLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiBcImFycmF5XCIsXG4gICAgICAgICAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBkZWYubWF4TGVuZ3RoLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChbLi4uY3R4LmRhdGFdLm1hcCgoaXRlbSwgaSkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBkZWYudHlwZS5fcGFyc2VBc3luYyhuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwgaXRlbSwgY3R4LnBhdGgsIGkpKTtcbiAgICAgICAgICAgIH0pKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VBcnJheShzdGF0dXMsIHJlc3VsdCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZXN1bHQgPSBbLi4uY3R4LmRhdGFdLm1hcCgoaXRlbSwgaSkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGRlZi50eXBlLl9wYXJzZVN5bmMobmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIGl0ZW0sIGN0eC5wYXRoLCBpKSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VBcnJheShzdGF0dXMsIHJlc3VsdCk7XG4gICAgfVxuICAgIGdldCBlbGVtZW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGVmLnR5cGU7XG4gICAgfVxuICAgIG1pbihtaW5MZW5ndGgsIG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBab2RBcnJheSh7XG4gICAgICAgICAgICAuLi50aGlzLl9kZWYsXG4gICAgICAgICAgICBtaW5MZW5ndGg6IHsgdmFsdWU6IG1pbkxlbmd0aCwgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpIH0sXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBtYXgobWF4TGVuZ3RoLCBtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiBuZXcgWm9kQXJyYXkoe1xuICAgICAgICAgICAgLi4udGhpcy5fZGVmLFxuICAgICAgICAgICAgbWF4TGVuZ3RoOiB7IHZhbHVlOiBtYXhMZW5ndGgsIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSB9LFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgbGVuZ3RoKGxlbiwgbWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gbmV3IFpvZEFycmF5KHtcbiAgICAgICAgICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgICAgIGV4YWN0TGVuZ3RoOiB7IHZhbHVlOiBsZW4sIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSB9LFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgbm9uZW1wdHkobWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5taW4oMSwgbWVzc2FnZSk7XG4gICAgfVxufVxuWm9kQXJyYXkuY3JlYXRlID0gKHNjaGVtYSwgcGFyYW1zKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBab2RBcnJheSh7XG4gICAgICAgIHR5cGU6IHNjaGVtYSxcbiAgICAgICAgbWluTGVuZ3RoOiBudWxsLFxuICAgICAgICBtYXhMZW5ndGg6IG51bGwsXG4gICAgICAgIGV4YWN0TGVuZ3RoOiBudWxsLFxuICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEFycmF5LFxuICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgfSk7XG59O1xuZnVuY3Rpb24gZGVlcFBhcnRpYWxpZnkoc2NoZW1hKSB7XG4gICAgaWYgKHNjaGVtYSBpbnN0YW5jZW9mIFpvZE9iamVjdCkge1xuICAgICAgICBjb25zdCBuZXdTaGFwZSA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBzY2hlbWEuc2hhcGUpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkU2NoZW1hID0gc2NoZW1hLnNoYXBlW2tleV07XG4gICAgICAgICAgICBuZXdTaGFwZVtrZXldID0gWm9kT3B0aW9uYWwuY3JlYXRlKGRlZXBQYXJ0aWFsaWZ5KGZpZWxkU2NoZW1hKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBab2RPYmplY3Qoe1xuICAgICAgICAgICAgLi4uc2NoZW1hLl9kZWYsXG4gICAgICAgICAgICBzaGFwZTogKCkgPT4gbmV3U2hhcGUsXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIGlmIChzY2hlbWEgaW5zdGFuY2VvZiBab2RBcnJheSkge1xuICAgICAgICByZXR1cm4gbmV3IFpvZEFycmF5KHtcbiAgICAgICAgICAgIC4uLnNjaGVtYS5fZGVmLFxuICAgICAgICAgICAgdHlwZTogZGVlcFBhcnRpYWxpZnkoc2NoZW1hLmVsZW1lbnQpLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAoc2NoZW1hIGluc3RhbmNlb2YgWm9kT3B0aW9uYWwpIHtcbiAgICAgICAgcmV0dXJuIFpvZE9wdGlvbmFsLmNyZWF0ZShkZWVwUGFydGlhbGlmeShzY2hlbWEudW53cmFwKCkpKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoc2NoZW1hIGluc3RhbmNlb2YgWm9kTnVsbGFibGUpIHtcbiAgICAgICAgcmV0dXJuIFpvZE51bGxhYmxlLmNyZWF0ZShkZWVwUGFydGlhbGlmeShzY2hlbWEudW53cmFwKCkpKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoc2NoZW1hIGluc3RhbmNlb2YgWm9kVHVwbGUpIHtcbiAgICAgICAgcmV0dXJuIFpvZFR1cGxlLmNyZWF0ZShzY2hlbWEuaXRlbXMubWFwKChpdGVtKSA9PiBkZWVwUGFydGlhbGlmeShpdGVtKSkpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHNjaGVtYTtcbiAgICB9XG59XG5leHBvcnQgY2xhc3MgWm9kT2JqZWN0IGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuX2NhY2hlZCA9IG51bGw7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAZGVwcmVjYXRlZCBJbiBtb3N0IGNhc2VzLCB0aGlzIGlzIG5vIGxvbmdlciBuZWVkZWQgLSB1bmtub3duIHByb3BlcnRpZXMgYXJlIG5vdyBzaWxlbnRseSBzdHJpcHBlZC5cbiAgICAgICAgICogSWYgeW91IHdhbnQgdG8gcGFzcyB0aHJvdWdoIHVua25vd24gcHJvcGVydGllcywgdXNlIGAucGFzc3Rocm91Z2goKWAgaW5zdGVhZC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMubm9uc3RyaWN0ID0gdGhpcy5wYXNzdGhyb3VnaDtcbiAgICAgICAgLy8gZXh0ZW5kPFxuICAgICAgICAvLyAgIEF1Z21lbnRhdGlvbiBleHRlbmRzIFpvZFJhd1NoYXBlLFxuICAgICAgICAvLyAgIE5ld091dHB1dCBleHRlbmRzIHV0aWwuZmxhdHRlbjx7XG4gICAgICAgIC8vICAgICBbayBpbiBrZXlvZiBBdWdtZW50YXRpb24gfCBrZXlvZiBPdXRwdXRdOiBrIGV4dGVuZHMga2V5b2YgQXVnbWVudGF0aW9uXG4gICAgICAgIC8vICAgICAgID8gQXVnbWVudGF0aW9uW2tdW1wiX291dHB1dFwiXVxuICAgICAgICAvLyAgICAgICA6IGsgZXh0ZW5kcyBrZXlvZiBPdXRwdXRcbiAgICAgICAgLy8gICAgICAgPyBPdXRwdXRba11cbiAgICAgICAgLy8gICAgICAgOiBuZXZlcjtcbiAgICAgICAgLy8gICB9PixcbiAgICAgICAgLy8gICBOZXdJbnB1dCBleHRlbmRzIHV0aWwuZmxhdHRlbjx7XG4gICAgICAgIC8vICAgICBbayBpbiBrZXlvZiBBdWdtZW50YXRpb24gfCBrZXlvZiBJbnB1dF06IGsgZXh0ZW5kcyBrZXlvZiBBdWdtZW50YXRpb25cbiAgICAgICAgLy8gICAgICAgPyBBdWdtZW50YXRpb25ba11bXCJfaW5wdXRcIl1cbiAgICAgICAgLy8gICAgICAgOiBrIGV4dGVuZHMga2V5b2YgSW5wdXRcbiAgICAgICAgLy8gICAgICAgPyBJbnB1dFtrXVxuICAgICAgICAvLyAgICAgICA6IG5ldmVyO1xuICAgICAgICAvLyAgIH0+XG4gICAgICAgIC8vID4oXG4gICAgICAgIC8vICAgYXVnbWVudGF0aW9uOiBBdWdtZW50YXRpb25cbiAgICAgICAgLy8gKTogWm9kT2JqZWN0PFxuICAgICAgICAvLyAgIGV4dGVuZFNoYXBlPFQsIEF1Z21lbnRhdGlvbj4sXG4gICAgICAgIC8vICAgVW5rbm93bktleXMsXG4gICAgICAgIC8vICAgQ2F0Y2hhbGwsXG4gICAgICAgIC8vICAgTmV3T3V0cHV0LFxuICAgICAgICAvLyAgIE5ld0lucHV0XG4gICAgICAgIC8vID4ge1xuICAgICAgICAvLyAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHtcbiAgICAgICAgLy8gICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgLy8gICAgIHNoYXBlOiAoKSA9PiAoe1xuICAgICAgICAvLyAgICAgICAuLi50aGlzLl9kZWYuc2hhcGUoKSxcbiAgICAgICAgLy8gICAgICAgLi4uYXVnbWVudGF0aW9uLFxuICAgICAgICAvLyAgICAgfSksXG4gICAgICAgIC8vICAgfSkgYXMgYW55O1xuICAgICAgICAvLyB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAZGVwcmVjYXRlZCBVc2UgYC5leHRlbmRgIGluc3RlYWRcbiAgICAgICAgICogICovXG4gICAgICAgIHRoaXMuYXVnbWVudCA9IHRoaXMuZXh0ZW5kO1xuICAgIH1cbiAgICBfZ2V0Q2FjaGVkKCkge1xuICAgICAgICBpZiAodGhpcy5fY2FjaGVkICE9PSBudWxsKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2NhY2hlZDtcbiAgICAgICAgY29uc3Qgc2hhcGUgPSB0aGlzLl9kZWYuc2hhcGUoKTtcbiAgICAgICAgY29uc3Qga2V5cyA9IHV0aWwub2JqZWN0S2V5cyhzaGFwZSk7XG4gICAgICAgIHRoaXMuX2NhY2hlZCA9IHsgc2hhcGUsIGtleXMgfTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhY2hlZDtcbiAgICB9XG4gICAgX3BhcnNlKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTtcbiAgICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUub2JqZWN0KSB7XG4gICAgICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7XG4gICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLFxuICAgICAgICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm9iamVjdCxcbiAgICAgICAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHsgc3RhdHVzLCBjdHggfSA9IHRoaXMuX3Byb2Nlc3NJbnB1dFBhcmFtcyhpbnB1dCk7XG4gICAgICAgIGNvbnN0IHsgc2hhcGUsIGtleXM6IHNoYXBlS2V5cyB9ID0gdGhpcy5fZ2V0Q2FjaGVkKCk7XG4gICAgICAgIGNvbnN0IGV4dHJhS2V5cyA9IFtdO1xuICAgICAgICBpZiAoISh0aGlzLl9kZWYuY2F0Y2hhbGwgaW5zdGFuY2VvZiBab2ROZXZlciAmJiB0aGlzLl9kZWYudW5rbm93bktleXMgPT09IFwic3RyaXBcIikpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIGN0eC5kYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFzaGFwZUtleXMuaW5jbHVkZXMoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICBleHRyYUtleXMucHVzaChrZXkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwYWlycyA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBzaGFwZUtleXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGtleVZhbGlkYXRvciA9IHNoYXBlW2tleV07XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGN0eC5kYXRhW2tleV07XG4gICAgICAgICAgICBwYWlycy5wdXNoKHtcbiAgICAgICAgICAgICAgICBrZXk6IHsgc3RhdHVzOiBcInZhbGlkXCIsIHZhbHVlOiBrZXkgfSxcbiAgICAgICAgICAgICAgICB2YWx1ZToga2V5VmFsaWRhdG9yLl9wYXJzZShuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwgdmFsdWUsIGN0eC5wYXRoLCBrZXkpKSxcbiAgICAgICAgICAgICAgICBhbHdheXNTZXQ6IGtleSBpbiBjdHguZGF0YSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9kZWYuY2F0Y2hhbGwgaW5zdGFuY2VvZiBab2ROZXZlcikge1xuICAgICAgICAgICAgY29uc3QgdW5rbm93bktleXMgPSB0aGlzLl9kZWYudW5rbm93bktleXM7XG4gICAgICAgICAgICBpZiAodW5rbm93bktleXMgPT09IFwicGFzc3Rocm91Z2hcIikge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIGV4dHJhS2V5cykge1xuICAgICAgICAgICAgICAgICAgICBwYWlycy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleTogeyBzdGF0dXM6IFwidmFsaWRcIiwgdmFsdWU6IGtleSB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHsgc3RhdHVzOiBcInZhbGlkXCIsIHZhbHVlOiBjdHguZGF0YVtrZXldIH0sXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHVua25vd25LZXlzID09PSBcInN0cmljdFwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV4dHJhS2V5cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnVucmVjb2duaXplZF9rZXlzLFxuICAgICAgICAgICAgICAgICAgICAgICAga2V5czogZXh0cmFLZXlzLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodW5rbm93bktleXMgPT09IFwic3RyaXBcIikge1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnRlcm5hbCBab2RPYmplY3QgZXJyb3I6IGludmFsaWQgdW5rbm93bktleXMgdmFsdWUuYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBydW4gY2F0Y2hhbGwgdmFsaWRhdGlvblxuICAgICAgICAgICAgY29uc3QgY2F0Y2hhbGwgPSB0aGlzLl9kZWYuY2F0Y2hhbGw7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBleHRyYUtleXMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGN0eC5kYXRhW2tleV07XG4gICAgICAgICAgICAgICAgcGFpcnMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGtleTogeyBzdGF0dXM6IFwidmFsaWRcIiwgdmFsdWU6IGtleSB9LFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogY2F0Y2hhbGwuX3BhcnNlKG5ldyBQYXJzZUlucHV0TGF6eVBhdGgoY3R4LCB2YWx1ZSwgY3R4LnBhdGgsIGtleSkgLy8sIGN0eC5jaGlsZChrZXkpLCB2YWx1ZSwgZ2V0UGFyc2VkVHlwZSh2YWx1ZSlcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgYWx3YXlzU2V0OiBrZXkgaW4gY3R4LmRhdGEsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgICAgIC50aGVuKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzeW5jUGFpcnMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qga2V5ID0gYXdhaXQgcGFpci5rZXk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgcGFpci52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgc3luY1BhaXJzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5LFxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBhbHdheXNTZXQ6IHBhaXIuYWx3YXlzU2V0LFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN5bmNQYWlycztcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLnRoZW4oKHN5bmNQYWlycykgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBQYXJzZVN0YXR1cy5tZXJnZU9iamVjdFN5bmMoc3RhdHVzLCBzeW5jUGFpcnMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VPYmplY3RTeW5jKHN0YXR1cywgcGFpcnMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdldCBzaGFwZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi5zaGFwZSgpO1xuICAgIH1cbiAgICBzdHJpY3QobWVzc2FnZSkge1xuICAgICAgICBlcnJvclV0aWwuZXJyVG9PYmo7XG4gICAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHtcbiAgICAgICAgICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgICAgIHVua25vd25LZXlzOiBcInN0cmljdFwiLFxuICAgICAgICAgICAgLi4uKG1lc3NhZ2UgIT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvck1hcDogKGlzc3VlLCBjdHgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmF1bHRFcnJvciA9IHRoaXMuX2RlZi5lcnJvck1hcD8uKGlzc3VlLCBjdHgpLm1lc3NhZ2UgPz8gY3R4LmRlZmF1bHRFcnJvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc3N1ZS5jb2RlID09PSBcInVucmVjb2duaXplZF9rZXlzXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpLm1lc3NhZ2UgPz8gZGVmYXVsdEVycm9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGRlZmF1bHRFcnJvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgc3RyaXAoKSB7XG4gICAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHtcbiAgICAgICAgICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgICAgIHVua25vd25LZXlzOiBcInN0cmlwXCIsXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBwYXNzdGhyb3VnaCgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBab2RPYmplY3Qoe1xuICAgICAgICAgICAgLi4udGhpcy5fZGVmLFxuICAgICAgICAgICAgdW5rbm93bktleXM6IFwicGFzc3Rocm91Z2hcIixcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8vIGNvbnN0IEF1Z21lbnRGYWN0b3J5ID1cbiAgICAvLyAgIDxEZWYgZXh0ZW5kcyBab2RPYmplY3REZWY+KGRlZjogRGVmKSA9PlxuICAgIC8vICAgPEF1Z21lbnRhdGlvbiBleHRlbmRzIFpvZFJhd1NoYXBlPihcbiAgICAvLyAgICAgYXVnbWVudGF0aW9uOiBBdWdtZW50YXRpb25cbiAgICAvLyAgICk6IFpvZE9iamVjdDxcbiAgICAvLyAgICAgZXh0ZW5kU2hhcGU8UmV0dXJuVHlwZTxEZWZbXCJzaGFwZVwiXT4sIEF1Z21lbnRhdGlvbj4sXG4gICAgLy8gICAgIERlZltcInVua25vd25LZXlzXCJdLFxuICAgIC8vICAgICBEZWZbXCJjYXRjaGFsbFwiXVxuICAgIC8vICAgPiA9PiB7XG4gICAgLy8gICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHtcbiAgICAvLyAgICAgICAuLi5kZWYsXG4gICAgLy8gICAgICAgc2hhcGU6ICgpID0+ICh7XG4gICAgLy8gICAgICAgICAuLi5kZWYuc2hhcGUoKSxcbiAgICAvLyAgICAgICAgIC4uLmF1Z21lbnRhdGlvbixcbiAgICAvLyAgICAgICB9KSxcbiAgICAvLyAgICAgfSkgYXMgYW55O1xuICAgIC8vICAgfTtcbiAgICBleHRlbmQoYXVnbWVudGF0aW9uKSB7XG4gICAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHtcbiAgICAgICAgICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgICAgIHNoYXBlOiAoKSA9PiAoe1xuICAgICAgICAgICAgICAgIC4uLnRoaXMuX2RlZi5zaGFwZSgpLFxuICAgICAgICAgICAgICAgIC4uLmF1Z21lbnRhdGlvbixcbiAgICAgICAgICAgIH0pLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUHJpb3IgdG8gem9kQDEuMC4xMiB0aGVyZSB3YXMgYSBidWcgaW4gdGhlXG4gICAgICogaW5mZXJyZWQgdHlwZSBvZiBtZXJnZWQgb2JqZWN0cy4gUGxlYXNlXG4gICAgICogdXBncmFkZSBpZiB5b3UgYXJlIGV4cGVyaWVuY2luZyBpc3N1ZXMuXG4gICAgICovXG4gICAgbWVyZ2UobWVyZ2luZykge1xuICAgICAgICBjb25zdCBtZXJnZWQgPSBuZXcgWm9kT2JqZWN0KHtcbiAgICAgICAgICAgIHVua25vd25LZXlzOiBtZXJnaW5nLl9kZWYudW5rbm93bktleXMsXG4gICAgICAgICAgICBjYXRjaGFsbDogbWVyZ2luZy5fZGVmLmNhdGNoYWxsLFxuICAgICAgICAgICAgc2hhcGU6ICgpID0+ICh7XG4gICAgICAgICAgICAgICAgLi4udGhpcy5fZGVmLnNoYXBlKCksXG4gICAgICAgICAgICAgICAgLi4ubWVyZ2luZy5fZGVmLnNoYXBlKCksXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kT2JqZWN0LFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG1lcmdlZDtcbiAgICB9XG4gICAgLy8gbWVyZ2U8XG4gICAgLy8gICBJbmNvbWluZyBleHRlbmRzIEFueVpvZE9iamVjdCxcbiAgICAvLyAgIEF1Z21lbnRhdGlvbiBleHRlbmRzIEluY29taW5nW1wic2hhcGVcIl0sXG4gICAgLy8gICBOZXdPdXRwdXQgZXh0ZW5kcyB7XG4gICAgLy8gICAgIFtrIGluIGtleW9mIEF1Z21lbnRhdGlvbiB8IGtleW9mIE91dHB1dF06IGsgZXh0ZW5kcyBrZXlvZiBBdWdtZW50YXRpb25cbiAgICAvLyAgICAgICA/IEF1Z21lbnRhdGlvbltrXVtcIl9vdXRwdXRcIl1cbiAgICAvLyAgICAgICA6IGsgZXh0ZW5kcyBrZXlvZiBPdXRwdXRcbiAgICAvLyAgICAgICA/IE91dHB1dFtrXVxuICAgIC8vICAgICAgIDogbmV2ZXI7XG4gICAgLy8gICB9LFxuICAgIC8vICAgTmV3SW5wdXQgZXh0ZW5kcyB7XG4gICAgLy8gICAgIFtrIGluIGtleW9mIEF1Z21lbnRhdGlvbiB8IGtleW9mIElucHV0XTogayBleHRlbmRzIGtleW9mIEF1Z21lbnRhdGlvblxuICAgIC8vICAgICAgID8gQXVnbWVudGF0aW9uW2tdW1wiX2lucHV0XCJdXG4gICAgLy8gICAgICAgOiBrIGV4dGVuZHMga2V5b2YgSW5wdXRcbiAgICAvLyAgICAgICA/IElucHV0W2tdXG4gICAgLy8gICAgICAgOiBuZXZlcjtcbiAgICAvLyAgIH1cbiAgICAvLyA+KFxuICAgIC8vICAgbWVyZ2luZzogSW5jb21pbmdcbiAgICAvLyApOiBab2RPYmplY3Q8XG4gICAgLy8gICBleHRlbmRTaGFwZTxULCBSZXR1cm5UeXBlPEluY29taW5nW1wiX2RlZlwiXVtcInNoYXBlXCJdPj4sXG4gICAgLy8gICBJbmNvbWluZ1tcIl9kZWZcIl1bXCJ1bmtub3duS2V5c1wiXSxcbiAgICAvLyAgIEluY29taW5nW1wiX2RlZlwiXVtcImNhdGNoYWxsXCJdLFxuICAgIC8vICAgTmV3T3V0cHV0LFxuICAgIC8vICAgTmV3SW5wdXRcbiAgICAvLyA+IHtcbiAgICAvLyAgIGNvbnN0IG1lcmdlZDogYW55ID0gbmV3IFpvZE9iamVjdCh7XG4gICAgLy8gICAgIHVua25vd25LZXlzOiBtZXJnaW5nLl9kZWYudW5rbm93bktleXMsXG4gICAgLy8gICAgIGNhdGNoYWxsOiBtZXJnaW5nLl9kZWYuY2F0Y2hhbGwsXG4gICAgLy8gICAgIHNoYXBlOiAoKSA9PlxuICAgIC8vICAgICAgIG9iamVjdFV0aWwubWVyZ2VTaGFwZXModGhpcy5fZGVmLnNoYXBlKCksIG1lcmdpbmcuX2RlZi5zaGFwZSgpKSxcbiAgICAvLyAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RPYmplY3QsXG4gICAgLy8gICB9KSBhcyBhbnk7XG4gICAgLy8gICByZXR1cm4gbWVyZ2VkO1xuICAgIC8vIH1cbiAgICBzZXRLZXkoa2V5LCBzY2hlbWEpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXVnbWVudCh7IFtrZXldOiBzY2hlbWEgfSk7XG4gICAgfVxuICAgIC8vIG1lcmdlPEluY29taW5nIGV4dGVuZHMgQW55Wm9kT2JqZWN0PihcbiAgICAvLyAgIG1lcmdpbmc6IEluY29taW5nXG4gICAgLy8gKTogLy9ab2RPYmplY3Q8VCAmIEluY29taW5nW1wiX3NoYXBlXCJdLCBVbmtub3duS2V5cywgQ2F0Y2hhbGw+ID0gKG1lcmdpbmcpID0+IHtcbiAgICAvLyBab2RPYmplY3Q8XG4gICAgLy8gICBleHRlbmRTaGFwZTxULCBSZXR1cm5UeXBlPEluY29taW5nW1wiX2RlZlwiXVtcInNoYXBlXCJdPj4sXG4gICAgLy8gICBJbmNvbWluZ1tcIl9kZWZcIl1bXCJ1bmtub3duS2V5c1wiXSxcbiAgICAvLyAgIEluY29taW5nW1wiX2RlZlwiXVtcImNhdGNoYWxsXCJdXG4gICAgLy8gPiB7XG4gICAgLy8gICAvLyBjb25zdCBtZXJnZWRTaGFwZSA9IG9iamVjdFV0aWwubWVyZ2VTaGFwZXMoXG4gICAgLy8gICAvLyAgIHRoaXMuX2RlZi5zaGFwZSgpLFxuICAgIC8vICAgLy8gICBtZXJnaW5nLl9kZWYuc2hhcGUoKVxuICAgIC8vICAgLy8gKTtcbiAgICAvLyAgIGNvbnN0IG1lcmdlZDogYW55ID0gbmV3IFpvZE9iamVjdCh7XG4gICAgLy8gICAgIHVua25vd25LZXlzOiBtZXJnaW5nLl9kZWYudW5rbm93bktleXMsXG4gICAgLy8gICAgIGNhdGNoYWxsOiBtZXJnaW5nLl9kZWYuY2F0Y2hhbGwsXG4gICAgLy8gICAgIHNoYXBlOiAoKSA9PlxuICAgIC8vICAgICAgIG9iamVjdFV0aWwubWVyZ2VTaGFwZXModGhpcy5fZGVmLnNoYXBlKCksIG1lcmdpbmcuX2RlZi5zaGFwZSgpKSxcbiAgICAvLyAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RPYmplY3QsXG4gICAgLy8gICB9KSBhcyBhbnk7XG4gICAgLy8gICByZXR1cm4gbWVyZ2VkO1xuICAgIC8vIH1cbiAgICBjYXRjaGFsbChpbmRleCkge1xuICAgICAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7XG4gICAgICAgICAgICAuLi50aGlzLl9kZWYsXG4gICAgICAgICAgICBjYXRjaGFsbDogaW5kZXgsXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBwaWNrKG1hc2spIHtcbiAgICAgICAgY29uc3Qgc2hhcGUgPSB7fTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgdXRpbC5vYmplY3RLZXlzKG1hc2spKSB7XG4gICAgICAgICAgICBpZiAobWFza1trZXldICYmIHRoaXMuc2hhcGVba2V5XSkge1xuICAgICAgICAgICAgICAgIHNoYXBlW2tleV0gPSB0aGlzLnNoYXBlW2tleV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBab2RPYmplY3Qoe1xuICAgICAgICAgICAgLi4udGhpcy5fZGVmLFxuICAgICAgICAgICAgc2hhcGU6ICgpID0+IHNoYXBlLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgb21pdChtYXNrKSB7XG4gICAgICAgIGNvbnN0IHNoYXBlID0ge307XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIHV0aWwub2JqZWN0S2V5cyh0aGlzLnNoYXBlKSkge1xuICAgICAgICAgICAgaWYgKCFtYXNrW2tleV0pIHtcbiAgICAgICAgICAgICAgICBzaGFwZVtrZXldID0gdGhpcy5zaGFwZVtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHtcbiAgICAgICAgICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgICAgIHNoYXBlOiAoKSA9PiBzaGFwZSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBkZXByZWNhdGVkXG4gICAgICovXG4gICAgZGVlcFBhcnRpYWwoKSB7XG4gICAgICAgIHJldHVybiBkZWVwUGFydGlhbGlmeSh0aGlzKTtcbiAgICB9XG4gICAgcGFydGlhbChtYXNrKSB7XG4gICAgICAgIGNvbnN0IG5ld1NoYXBlID0ge307XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIHV0aWwub2JqZWN0S2V5cyh0aGlzLnNoYXBlKSkge1xuICAgICAgICAgICAgY29uc3QgZmllbGRTY2hlbWEgPSB0aGlzLnNoYXBlW2tleV07XG4gICAgICAgICAgICBpZiAobWFzayAmJiAhbWFza1trZXldKSB7XG4gICAgICAgICAgICAgICAgbmV3U2hhcGVba2V5XSA9IGZpZWxkU2NoZW1hO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbmV3U2hhcGVba2V5XSA9IGZpZWxkU2NoZW1hLm9wdGlvbmFsKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBab2RPYmplY3Qoe1xuICAgICAgICAgICAgLi4udGhpcy5fZGVmLFxuICAgICAgICAgICAgc2hhcGU6ICgpID0+IG5ld1NoYXBlLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmVxdWlyZWQobWFzaykge1xuICAgICAgICBjb25zdCBuZXdTaGFwZSA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiB1dGlsLm9iamVjdEtleXModGhpcy5zaGFwZSkpIHtcbiAgICAgICAgICAgIGlmIChtYXNrICYmICFtYXNrW2tleV0pIHtcbiAgICAgICAgICAgICAgICBuZXdTaGFwZVtrZXldID0gdGhpcy5zaGFwZVtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmllbGRTY2hlbWEgPSB0aGlzLnNoYXBlW2tleV07XG4gICAgICAgICAgICAgICAgbGV0IG5ld0ZpZWxkID0gZmllbGRTY2hlbWE7XG4gICAgICAgICAgICAgICAgd2hpbGUgKG5ld0ZpZWxkIGluc3RhbmNlb2YgWm9kT3B0aW9uYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3RmllbGQgPSBuZXdGaWVsZC5fZGVmLmlubmVyVHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbmV3U2hhcGVba2V5XSA9IG5ld0ZpZWxkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHtcbiAgICAgICAgICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgICAgIHNoYXBlOiAoKSA9PiBuZXdTaGFwZSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGtleW9mKCkge1xuICAgICAgICByZXR1cm4gY3JlYXRlWm9kRW51bSh1dGlsLm9iamVjdEtleXModGhpcy5zaGFwZSkpO1xuICAgIH1cbn1cblpvZE9iamVjdC5jcmVhdGUgPSAoc2hhcGUsIHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHtcbiAgICAgICAgc2hhcGU6ICgpID0+IHNoYXBlLFxuICAgICAgICB1bmtub3duS2V5czogXCJzdHJpcFwiLFxuICAgICAgICBjYXRjaGFsbDogWm9kTmV2ZXIuY3JlYXRlKCksXG4gICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kT2JqZWN0LFxuICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgfSk7XG59O1xuWm9kT2JqZWN0LnN0cmljdENyZWF0ZSA9IChzaGFwZSwgcGFyYW1zKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBab2RPYmplY3Qoe1xuICAgICAgICBzaGFwZTogKCkgPT4gc2hhcGUsXG4gICAgICAgIHVua25vd25LZXlzOiBcInN0cmljdFwiLFxuICAgICAgICBjYXRjaGFsbDogWm9kTmV2ZXIuY3JlYXRlKCksXG4gICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kT2JqZWN0LFxuICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgfSk7XG59O1xuWm9kT2JqZWN0LmxhenljcmVhdGUgPSAoc2hhcGUsIHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHtcbiAgICAgICAgc2hhcGUsXG4gICAgICAgIHVua25vd25LZXlzOiBcInN0cmlwXCIsXG4gICAgICAgIGNhdGNoYWxsOiBab2ROZXZlci5jcmVhdGUoKSxcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RPYmplY3QsXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5leHBvcnQgY2xhc3MgWm9kVW5pb24gZXh0ZW5kcyBab2RUeXBlIHtcbiAgICBfcGFyc2UoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgeyBjdHggfSA9IHRoaXMuX3Byb2Nlc3NJbnB1dFBhcmFtcyhpbnB1dCk7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLl9kZWYub3B0aW9ucztcbiAgICAgICAgZnVuY3Rpb24gaGFuZGxlUmVzdWx0cyhyZXN1bHRzKSB7XG4gICAgICAgICAgICAvLyByZXR1cm4gZmlyc3QgaXNzdWUtZnJlZSB2YWxpZGF0aW9uIGlmIGl0IGV4aXN0c1xuICAgICAgICAgICAgZm9yIChjb25zdCByZXN1bHQgb2YgcmVzdWx0cykge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQucmVzdWx0LnN0YXR1cyA9PT0gXCJ2YWxpZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQucmVzdWx0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAoY29uc3QgcmVzdWx0IG9mIHJlc3VsdHMpIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0LnJlc3VsdC5zdGF0dXMgPT09IFwiZGlydHlcIikge1xuICAgICAgICAgICAgICAgICAgICAvLyBhZGQgaXNzdWVzIGZyb20gZGlydHkgb3B0aW9uXG4gICAgICAgICAgICAgICAgICAgIGN0eC5jb21tb24uaXNzdWVzLnB1c2goLi4ucmVzdWx0LmN0eC5jb21tb24uaXNzdWVzKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gcmV0dXJuIGludmFsaWRcbiAgICAgICAgICAgIGNvbnN0IHVuaW9uRXJyb3JzID0gcmVzdWx0cy5tYXAoKHJlc3VsdCkgPT4gbmV3IFpvZEVycm9yKHJlc3VsdC5jdHguY29tbW9uLmlzc3VlcykpO1xuICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdW5pb24sXG4gICAgICAgICAgICAgICAgdW5pb25FcnJvcnMsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwob3B0aW9ucy5tYXAoYXN5bmMgKG9wdGlvbikgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNoaWxkQ3R4ID0ge1xuICAgICAgICAgICAgICAgICAgICAuLi5jdHgsXG4gICAgICAgICAgICAgICAgICAgIGNvbW1vbjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uY3R4LmNvbW1vbixcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzc3VlczogW10sXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHBhcmVudDogbnVsbCxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdDogYXdhaXQgb3B0aW9uLl9wYXJzZUFzeW5jKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IGN0eC5kYXRhLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGF0aDogY3R4LnBhdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnQ6IGNoaWxkQ3R4LFxuICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgY3R4OiBjaGlsZEN0eCxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSkpLnRoZW4oaGFuZGxlUmVzdWx0cyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBsZXQgZGlydHkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBjb25zdCBpc3N1ZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoY29uc3Qgb3B0aW9uIG9mIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjaGlsZEN0eCA9IHtcbiAgICAgICAgICAgICAgICAgICAgLi4uY3R4LFxuICAgICAgICAgICAgICAgICAgICBjb21tb246IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmN0eC5jb21tb24sXG4gICAgICAgICAgICAgICAgICAgICAgICBpc3N1ZXM6IFtdLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBwYXJlbnQ6IG51bGwsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBvcHRpb24uX3BhcnNlU3luYyh7XG4gICAgICAgICAgICAgICAgICAgIGRhdGE6IGN0eC5kYXRhLFxuICAgICAgICAgICAgICAgICAgICBwYXRoOiBjdHgucGF0aCxcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50OiBjaGlsZEN0eCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gXCJ2YWxpZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHJlc3VsdC5zdGF0dXMgPT09IFwiZGlydHlcIiAmJiAhZGlydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGlydHkgPSB7IHJlc3VsdCwgY3R4OiBjaGlsZEN0eCB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRDdHguY29tbW9uLmlzc3Vlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNzdWVzLnB1c2goY2hpbGRDdHguY29tbW9uLmlzc3Vlcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRpcnR5KSB7XG4gICAgICAgICAgICAgICAgY3R4LmNvbW1vbi5pc3N1ZXMucHVzaCguLi5kaXJ0eS5jdHguY29tbW9uLmlzc3Vlcyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpcnR5LnJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHVuaW9uRXJyb3JzID0gaXNzdWVzLm1hcCgoaXNzdWVzKSA9PiBuZXcgWm9kRXJyb3IoaXNzdWVzKSk7XG4gICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF91bmlvbixcbiAgICAgICAgICAgICAgICB1bmlvbkVycm9ycyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZ2V0IG9wdGlvbnMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYub3B0aW9ucztcbiAgICB9XG59XG5ab2RVbmlvbi5jcmVhdGUgPSAodHlwZXMsIHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kVW5pb24oe1xuICAgICAgICBvcHRpb25zOiB0eXBlcyxcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RVbmlvbixcbiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpLFxuICAgIH0pO1xufTtcbi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuLy8vLy8vLy8vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vLy8vLy8vLy9cbi8vLy8vLy8vLy8gICAgICBab2REaXNjcmltaW5hdGVkVW5pb24gICAgICAvLy8vLy8vLy8vXG4vLy8vLy8vLy8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8vLy8vLy8vL1xuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5jb25zdCBnZXREaXNjcmltaW5hdG9yID0gKHR5cGUpID0+IHtcbiAgICBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZExhenkpIHtcbiAgICAgICAgcmV0dXJuIGdldERpc2NyaW1pbmF0b3IodHlwZS5zY2hlbWEpO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlIGluc3RhbmNlb2YgWm9kRWZmZWN0cykge1xuICAgICAgICByZXR1cm4gZ2V0RGlzY3JpbWluYXRvcih0eXBlLmlubmVyVHlwZSgpKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZExpdGVyYWwpIHtcbiAgICAgICAgcmV0dXJuIFt0eXBlLnZhbHVlXTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZEVudW0pIHtcbiAgICAgICAgcmV0dXJuIHR5cGUub3B0aW9ucztcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZE5hdGl2ZUVudW0pIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGJhbi9iYW5cbiAgICAgICAgcmV0dXJuIHV0aWwub2JqZWN0VmFsdWVzKHR5cGUuZW51bSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2REZWZhdWx0KSB7XG4gICAgICAgIHJldHVybiBnZXREaXNjcmltaW5hdG9yKHR5cGUuX2RlZi5pbm5lclR5cGUpO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlIGluc3RhbmNlb2YgWm9kVW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBbdW5kZWZpbmVkXTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZE51bGwpIHtcbiAgICAgICAgcmV0dXJuIFtudWxsXTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZE9wdGlvbmFsKSB7XG4gICAgICAgIHJldHVybiBbdW5kZWZpbmVkLCAuLi5nZXREaXNjcmltaW5hdG9yKHR5cGUudW53cmFwKCkpXTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZE51bGxhYmxlKSB7XG4gICAgICAgIHJldHVybiBbbnVsbCwgLi4uZ2V0RGlzY3JpbWluYXRvcih0eXBlLnVud3JhcCgpKV07XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RCcmFuZGVkKSB7XG4gICAgICAgIHJldHVybiBnZXREaXNjcmltaW5hdG9yKHR5cGUudW53cmFwKCkpO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlIGluc3RhbmNlb2YgWm9kUmVhZG9ubHkpIHtcbiAgICAgICAgcmV0dXJuIGdldERpc2NyaW1pbmF0b3IodHlwZS51bndyYXAoKSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RDYXRjaCkge1xuICAgICAgICByZXR1cm4gZ2V0RGlzY3JpbWluYXRvcih0eXBlLl9kZWYuaW5uZXJUeXBlKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG59O1xuZXhwb3J0IGNsYXNzIFpvZERpc2NyaW1pbmF0ZWRVbmlvbiBleHRlbmRzIFpvZFR5cGUge1xuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTtcbiAgICAgICAgaWYgKGN0eC5wYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm9iamVjdCkge1xuICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSxcbiAgICAgICAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5vYmplY3QsXG4gICAgICAgICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkaXNjcmltaW5hdG9yID0gdGhpcy5kaXNjcmltaW5hdG9yO1xuICAgICAgICBjb25zdCBkaXNjcmltaW5hdG9yVmFsdWUgPSBjdHguZGF0YVtkaXNjcmltaW5hdG9yXTtcbiAgICAgICAgY29uc3Qgb3B0aW9uID0gdGhpcy5vcHRpb25zTWFwLmdldChkaXNjcmltaW5hdG9yVmFsdWUpO1xuICAgICAgICBpZiAoIW9wdGlvbikge1xuICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdW5pb25fZGlzY3JpbWluYXRvcixcbiAgICAgICAgICAgICAgICBvcHRpb25zOiBBcnJheS5mcm9tKHRoaXMub3B0aW9uc01hcC5rZXlzKCkpLFxuICAgICAgICAgICAgICAgIHBhdGg6IFtkaXNjcmltaW5hdG9yXSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHtcbiAgICAgICAgICAgIHJldHVybiBvcHRpb24uX3BhcnNlQXN5bmMoe1xuICAgICAgICAgICAgICAgIGRhdGE6IGN0eC5kYXRhLFxuICAgICAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLFxuICAgICAgICAgICAgICAgIHBhcmVudDogY3R4LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gb3B0aW9uLl9wYXJzZVN5bmMoe1xuICAgICAgICAgICAgICAgIGRhdGE6IGN0eC5kYXRhLFxuICAgICAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLFxuICAgICAgICAgICAgICAgIHBhcmVudDogY3R4LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZ2V0IGRpc2NyaW1pbmF0b3IoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYuZGlzY3JpbWluYXRvcjtcbiAgICB9XG4gICAgZ2V0IG9wdGlvbnMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYub3B0aW9ucztcbiAgICB9XG4gICAgZ2V0IG9wdGlvbnNNYXAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYub3B0aW9uc01hcDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBkaXNjcmltaW5hdGVkIHVuaW9uIHNjaGVtYS4gSXRzIGJlaGF2aW91ciBpcyB2ZXJ5IHNpbWlsYXIgdG8gdGhhdCBvZiB0aGUgbm9ybWFsIHoudW5pb24oKSBjb25zdHJ1Y3Rvci5cbiAgICAgKiBIb3dldmVyLCBpdCBvbmx5IGFsbG93cyBhIHVuaW9uIG9mIG9iamVjdHMsIGFsbCBvZiB3aGljaCBuZWVkIHRvIHNoYXJlIGEgZGlzY3JpbWluYXRvciBwcm9wZXJ0eS4gVGhpcyBwcm9wZXJ0eSBtdXN0XG4gICAgICogaGF2ZSBhIGRpZmZlcmVudCB2YWx1ZSBmb3IgZWFjaCBvYmplY3QgaW4gdGhlIHVuaW9uLlxuICAgICAqIEBwYXJhbSBkaXNjcmltaW5hdG9yIHRoZSBuYW1lIG9mIHRoZSBkaXNjcmltaW5hdG9yIHByb3BlcnR5XG4gICAgICogQHBhcmFtIHR5cGVzIGFuIGFycmF5IG9mIG9iamVjdCBzY2hlbWFzXG4gICAgICogQHBhcmFtIHBhcmFtc1xuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGUoZGlzY3JpbWluYXRvciwgb3B0aW9ucywgcGFyYW1zKSB7XG4gICAgICAgIC8vIEdldCBhbGwgdGhlIHZhbGlkIGRpc2NyaW1pbmF0b3IgdmFsdWVzXG4gICAgICAgIGNvbnN0IG9wdGlvbnNNYXAgPSBuZXcgTWFwKCk7XG4gICAgICAgIC8vIHRyeSB7XG4gICAgICAgIGZvciAoY29uc3QgdHlwZSBvZiBvcHRpb25zKSB7XG4gICAgICAgICAgICBjb25zdCBkaXNjcmltaW5hdG9yVmFsdWVzID0gZ2V0RGlzY3JpbWluYXRvcih0eXBlLnNoYXBlW2Rpc2NyaW1pbmF0b3JdKTtcbiAgICAgICAgICAgIGlmICghZGlzY3JpbWluYXRvclZhbHVlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEEgZGlzY3JpbWluYXRvciB2YWx1ZSBmb3Iga2V5IFxcYCR7ZGlzY3JpbWluYXRvcn1cXGAgY291bGQgbm90IGJlIGV4dHJhY3RlZCBmcm9tIGFsbCBzY2hlbWEgb3B0aW9uc2ApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChjb25zdCB2YWx1ZSBvZiBkaXNjcmltaW5hdG9yVmFsdWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnNNYXAuaGFzKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERpc2NyaW1pbmF0b3IgcHJvcGVydHkgJHtTdHJpbmcoZGlzY3JpbWluYXRvcil9IGhhcyBkdXBsaWNhdGUgdmFsdWUgJHtTdHJpbmcodmFsdWUpfWApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvcHRpb25zTWFwLnNldCh2YWx1ZSwgdHlwZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBab2REaXNjcmltaW5hdGVkVW5pb24oe1xuICAgICAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2REaXNjcmltaW5hdGVkVW5pb24sXG4gICAgICAgICAgICBkaXNjcmltaW5hdG9yLFxuICAgICAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgICAgIG9wdGlvbnNNYXAsXG4gICAgICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgICAgIH0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIG1lcmdlVmFsdWVzKGEsIGIpIHtcbiAgICBjb25zdCBhVHlwZSA9IGdldFBhcnNlZFR5cGUoYSk7XG4gICAgY29uc3QgYlR5cGUgPSBnZXRQYXJzZWRUeXBlKGIpO1xuICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgIHJldHVybiB7IHZhbGlkOiB0cnVlLCBkYXRhOiBhIH07XG4gICAgfVxuICAgIGVsc2UgaWYgKGFUeXBlID09PSBab2RQYXJzZWRUeXBlLm9iamVjdCAmJiBiVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS5vYmplY3QpIHtcbiAgICAgICAgY29uc3QgYktleXMgPSB1dGlsLm9iamVjdEtleXMoYik7XG4gICAgICAgIGNvbnN0IHNoYXJlZEtleXMgPSB1dGlsLm9iamVjdEtleXMoYSkuZmlsdGVyKChrZXkpID0+IGJLZXlzLmluZGV4T2Yoa2V5KSAhPT0gLTEpO1xuICAgICAgICBjb25zdCBuZXdPYmogPSB7IC4uLmEsIC4uLmIgfTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgb2Ygc2hhcmVkS2V5cykge1xuICAgICAgICAgICAgY29uc3Qgc2hhcmVkVmFsdWUgPSBtZXJnZVZhbHVlcyhhW2tleV0sIGJba2V5XSk7XG4gICAgICAgICAgICBpZiAoIXNoYXJlZFZhbHVlLnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgdmFsaWQ6IGZhbHNlIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBuZXdPYmpba2V5XSA9IHNoYXJlZFZhbHVlLmRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgdmFsaWQ6IHRydWUsIGRhdGE6IG5ld09iaiB9O1xuICAgIH1cbiAgICBlbHNlIGlmIChhVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS5hcnJheSAmJiBiVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS5hcnJheSkge1xuICAgICAgICBpZiAoYS5sZW5ndGggIT09IGIubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4geyB2YWxpZDogZmFsc2UgfTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBuZXdBcnJheSA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgYS5sZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgICAgIGNvbnN0IGl0ZW1BID0gYVtpbmRleF07XG4gICAgICAgICAgICBjb25zdCBpdGVtQiA9IGJbaW5kZXhdO1xuICAgICAgICAgICAgY29uc3Qgc2hhcmVkVmFsdWUgPSBtZXJnZVZhbHVlcyhpdGVtQSwgaXRlbUIpO1xuICAgICAgICAgICAgaWYgKCFzaGFyZWRWYWx1ZS52YWxpZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbmV3QXJyYXkucHVzaChzaGFyZWRWYWx1ZS5kYXRhKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyB2YWxpZDogdHJ1ZSwgZGF0YTogbmV3QXJyYXkgfTtcbiAgICB9XG4gICAgZWxzZSBpZiAoYVR5cGUgPT09IFpvZFBhcnNlZFR5cGUuZGF0ZSAmJiBiVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS5kYXRlICYmICthID09PSArYikge1xuICAgICAgICByZXR1cm4geyB2YWxpZDogdHJ1ZSwgZGF0YTogYSB9O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHsgdmFsaWQ6IGZhbHNlIH07XG4gICAgfVxufVxuZXhwb3J0IGNsYXNzIFpvZEludGVyc2VjdGlvbiBleHRlbmRzIFpvZFR5cGUge1xuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICBjb25zdCB7IHN0YXR1cywgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpO1xuICAgICAgICBjb25zdCBoYW5kbGVQYXJzZWQgPSAocGFyc2VkTGVmdCwgcGFyc2VkUmlnaHQpID0+IHtcbiAgICAgICAgICAgIGlmIChpc0Fib3J0ZWQocGFyc2VkTGVmdCkgfHwgaXNBYm9ydGVkKHBhcnNlZFJpZ2h0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbWVyZ2VkID0gbWVyZ2VWYWx1ZXMocGFyc2VkTGVmdC52YWx1ZSwgcGFyc2VkUmlnaHQudmFsdWUpO1xuICAgICAgICAgICAgaWYgKCFtZXJnZWQudmFsaWQpIHtcbiAgICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfaW50ZXJzZWN0aW9uX3R5cGVzLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzRGlydHkocGFyc2VkTGVmdCkgfHwgaXNEaXJ0eShwYXJzZWRSaWdodCkpIHtcbiAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7IHN0YXR1czogc3RhdHVzLnZhbHVlLCB2YWx1ZTogbWVyZ2VkLmRhdGEgfTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICAgICAgdGhpcy5fZGVmLmxlZnQuX3BhcnNlQXN5bmMoe1xuICAgICAgICAgICAgICAgICAgICBkYXRhOiBjdHguZGF0YSxcbiAgICAgICAgICAgICAgICAgICAgcGF0aDogY3R4LnBhdGgsXG4gICAgICAgICAgICAgICAgICAgIHBhcmVudDogY3R4LFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIHRoaXMuX2RlZi5yaWdodC5fcGFyc2VBc3luYyh7XG4gICAgICAgICAgICAgICAgICAgIGRhdGE6IGN0eC5kYXRhLFxuICAgICAgICAgICAgICAgICAgICBwYXRoOiBjdHgucGF0aCxcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50OiBjdHgsXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBdKS50aGVuKChbbGVmdCwgcmlnaHRdKSA9PiBoYW5kbGVQYXJzZWQobGVmdCwgcmlnaHQpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBoYW5kbGVQYXJzZWQodGhpcy5fZGVmLmxlZnQuX3BhcnNlU3luYyh7XG4gICAgICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsXG4gICAgICAgICAgICAgICAgcGF0aDogY3R4LnBhdGgsXG4gICAgICAgICAgICAgICAgcGFyZW50OiBjdHgsXG4gICAgICAgICAgICB9KSwgdGhpcy5fZGVmLnJpZ2h0Ll9wYXJzZVN5bmMoe1xuICAgICAgICAgICAgICAgIGRhdGE6IGN0eC5kYXRhLFxuICAgICAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLFxuICAgICAgICAgICAgICAgIHBhcmVudDogY3R4LFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgfVxufVxuWm9kSW50ZXJzZWN0aW9uLmNyZWF0ZSA9IChsZWZ0LCByaWdodCwgcGFyYW1zKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBab2RJbnRlcnNlY3Rpb24oe1xuICAgICAgICBsZWZ0OiBsZWZ0LFxuICAgICAgICByaWdodDogcmlnaHQsXG4gICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kSW50ZXJzZWN0aW9uLFxuICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgfSk7XG59O1xuLy8gdHlwZSBab2RUdXBsZUl0ZW1zID0gW1pvZFR5cGVBbnksIC4uLlpvZFR5cGVBbnlbXV07XG5leHBvcnQgY2xhc3MgWm9kVHVwbGUgZXh0ZW5kcyBab2RUeXBlIHtcbiAgICBfcGFyc2UoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTtcbiAgICAgICAgaWYgKGN0eC5wYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLmFycmF5KSB7XG4gICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLFxuICAgICAgICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmFycmF5LFxuICAgICAgICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGN0eC5kYXRhLmxlbmd0aCA8IHRoaXMuX2RlZi5pdGVtcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsXG4gICAgICAgICAgICAgICAgbWluaW11bTogdGhpcy5fZGVmLml0ZW1zLmxlbmd0aCxcbiAgICAgICAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsXG4gICAgICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHR5cGU6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmVzdCA9IHRoaXMuX2RlZi5yZXN0O1xuICAgICAgICBpZiAoIXJlc3QgJiYgY3R4LmRhdGEubGVuZ3RoID4gdGhpcy5fZGVmLml0ZW1zLmxlbmd0aCkge1xuICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19iaWcsXG4gICAgICAgICAgICAgICAgbWF4aW11bTogdGhpcy5fZGVmLml0ZW1zLmxlbmd0aCxcbiAgICAgICAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsXG4gICAgICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHR5cGU6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaXRlbXMgPSBbLi4uY3R4LmRhdGFdXG4gICAgICAgICAgICAubWFwKChpdGVtLCBpdGVtSW5kZXgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHNjaGVtYSA9IHRoaXMuX2RlZi5pdGVtc1tpdGVtSW5kZXhdIHx8IHRoaXMuX2RlZi5yZXN0O1xuICAgICAgICAgICAgaWYgKCFzY2hlbWEpXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICByZXR1cm4gc2NoZW1hLl9wYXJzZShuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwgaXRlbSwgY3R4LnBhdGgsIGl0ZW1JbmRleCkpO1xuICAgICAgICB9KVxuICAgICAgICAgICAgLmZpbHRlcigoeCkgPT4gISF4KTsgLy8gZmlsdGVyIG51bGxzXG4gICAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwoaXRlbXMpLnRoZW4oKHJlc3VsdHMpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VBcnJheShzdGF0dXMsIHJlc3VsdHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VBcnJheShzdGF0dXMsIGl0ZW1zKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBnZXQgaXRlbXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYuaXRlbXM7XG4gICAgfVxuICAgIHJlc3QocmVzdCkge1xuICAgICAgICByZXR1cm4gbmV3IFpvZFR1cGxlKHtcbiAgICAgICAgICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgICAgIHJlc3QsXG4gICAgICAgIH0pO1xuICAgIH1cbn1cblpvZFR1cGxlLmNyZWF0ZSA9IChzY2hlbWFzLCBwYXJhbXMpID0+IHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoc2NoZW1hcykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiWW91IG11c3QgcGFzcyBhbiBhcnJheSBvZiBzY2hlbWFzIHRvIHoudHVwbGUoWyAuLi4gXSlcIik7XG4gICAgfVxuICAgIHJldHVybiBuZXcgWm9kVHVwbGUoe1xuICAgICAgICBpdGVtczogc2NoZW1hcyxcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RUdXBsZSxcbiAgICAgICAgcmVzdDogbnVsbCxcbiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpLFxuICAgIH0pO1xufTtcbmV4cG9ydCBjbGFzcyBab2RSZWNvcmQgZXh0ZW5kcyBab2RUeXBlIHtcbiAgICBnZXQga2V5U2NoZW1hKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGVmLmtleVR5cGU7XG4gICAgfVxuICAgIGdldCB2YWx1ZVNjaGVtYSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi52YWx1ZVR5cGU7XG4gICAgfVxuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICBjb25zdCB7IHN0YXR1cywgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpO1xuICAgICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUub2JqZWN0KSB7XG4gICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLFxuICAgICAgICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm9iamVjdCxcbiAgICAgICAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBhaXJzID0gW107XG4gICAgICAgIGNvbnN0IGtleVR5cGUgPSB0aGlzLl9kZWYua2V5VHlwZTtcbiAgICAgICAgY29uc3QgdmFsdWVUeXBlID0gdGhpcy5fZGVmLnZhbHVlVHlwZTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gY3R4LmRhdGEpIHtcbiAgICAgICAgICAgIHBhaXJzLnB1c2goe1xuICAgICAgICAgICAgICAgIGtleToga2V5VHlwZS5fcGFyc2UobmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIGtleSwgY3R4LnBhdGgsIGtleSkpLFxuICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZVR5cGUuX3BhcnNlKG5ldyBQYXJzZUlucHV0TGF6eVBhdGgoY3R4LCBjdHguZGF0YVtrZXldLCBjdHgucGF0aCwga2V5KSksXG4gICAgICAgICAgICAgICAgYWx3YXlzU2V0OiBrZXkgaW4gY3R4LmRhdGEsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYykge1xuICAgICAgICAgICAgcmV0dXJuIFBhcnNlU3RhdHVzLm1lcmdlT2JqZWN0QXN5bmMoc3RhdHVzLCBwYWlycyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VPYmplY3RTeW5jKHN0YXR1cywgcGFpcnMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdldCBlbGVtZW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGVmLnZhbHVlVHlwZTtcbiAgICB9XG4gICAgc3RhdGljIGNyZWF0ZShmaXJzdCwgc2Vjb25kLCB0aGlyZCkge1xuICAgICAgICBpZiAoc2Vjb25kIGluc3RhbmNlb2YgWm9kVHlwZSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBab2RSZWNvcmQoe1xuICAgICAgICAgICAgICAgIGtleVR5cGU6IGZpcnN0LFxuICAgICAgICAgICAgICAgIHZhbHVlVHlwZTogc2Vjb25kLFxuICAgICAgICAgICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kUmVjb3JkLFxuICAgICAgICAgICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXModGhpcmQpLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBab2RSZWNvcmQoe1xuICAgICAgICAgICAga2V5VHlwZTogWm9kU3RyaW5nLmNyZWF0ZSgpLFxuICAgICAgICAgICAgdmFsdWVUeXBlOiBmaXJzdCxcbiAgICAgICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kUmVjb3JkLFxuICAgICAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhzZWNvbmQpLFxuICAgICAgICB9KTtcbiAgICB9XG59XG5leHBvcnQgY2xhc3MgWm9kTWFwIGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgZ2V0IGtleVNjaGVtYSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi5rZXlUeXBlO1xuICAgIH1cbiAgICBnZXQgdmFsdWVTY2hlbWEoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYudmFsdWVUeXBlO1xuICAgIH1cbiAgICBfcGFyc2UoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTtcbiAgICAgICAgaWYgKGN0eC5wYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm1hcCkge1xuICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSxcbiAgICAgICAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5tYXAsXG4gICAgICAgICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBrZXlUeXBlID0gdGhpcy5fZGVmLmtleVR5cGU7XG4gICAgICAgIGNvbnN0IHZhbHVlVHlwZSA9IHRoaXMuX2RlZi52YWx1ZVR5cGU7XG4gICAgICAgIGNvbnN0IHBhaXJzID0gWy4uLmN0eC5kYXRhLmVudHJpZXMoKV0ubWFwKChba2V5LCB2YWx1ZV0sIGluZGV4KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGtleToga2V5VHlwZS5fcGFyc2UobmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIGtleSwgY3R4LnBhdGgsIFtpbmRleCwgXCJrZXlcIl0pKSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogdmFsdWVUeXBlLl9wYXJzZShuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwgdmFsdWUsIGN0eC5wYXRoLCBbaW5kZXgsIFwidmFsdWVcIl0pKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYykge1xuICAgICAgICAgICAgY29uc3QgZmluYWxNYXAgPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbihhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBwYWlyIG9mIHBhaXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGtleSA9IGF3YWl0IHBhaXIua2V5O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGF3YWl0IHBhaXIudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkuc3RhdHVzID09PSBcImFib3J0ZWRcIiB8fCB2YWx1ZS5zdGF0dXMgPT09IFwiYWJvcnRlZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5LnN0YXR1cyA9PT0gXCJkaXJ0eVwiIHx8IHZhbHVlLnN0YXR1cyA9PT0gXCJkaXJ0eVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBmaW5hbE1hcC5zZXQoa2V5LnZhbHVlLCB2YWx1ZS52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB7IHN0YXR1czogc3RhdHVzLnZhbHVlLCB2YWx1ZTogZmluYWxNYXAgfTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgZmluYWxNYXAgPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBrZXkgPSBwYWlyLmtleTtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHBhaXIudmFsdWU7XG4gICAgICAgICAgICAgICAgaWYgKGtleS5zdGF0dXMgPT09IFwiYWJvcnRlZFwiIHx8IHZhbHVlLnN0YXR1cyA9PT0gXCJhYm9ydGVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChrZXkuc3RhdHVzID09PSBcImRpcnR5XCIgfHwgdmFsdWUuc3RhdHVzID09PSBcImRpcnR5XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZpbmFsTWFwLnNldChrZXkudmFsdWUsIHZhbHVlLnZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7IHN0YXR1czogc3RhdHVzLnZhbHVlLCB2YWx1ZTogZmluYWxNYXAgfTtcbiAgICAgICAgfVxuICAgIH1cbn1cblpvZE1hcC5jcmVhdGUgPSAoa2V5VHlwZSwgdmFsdWVUeXBlLCBwYXJhbXMpID0+IHtcbiAgICByZXR1cm4gbmV3IFpvZE1hcCh7XG4gICAgICAgIHZhbHVlVHlwZSxcbiAgICAgICAga2V5VHlwZSxcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RNYXAsXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5leHBvcnQgY2xhc3MgWm9kU2V0IGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgX3BhcnNlKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IHsgc3RhdHVzLCBjdHggfSA9IHRoaXMuX3Byb2Nlc3NJbnB1dFBhcmFtcyhpbnB1dCk7XG4gICAgICAgIGlmIChjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5zZXQpIHtcbiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsXG4gICAgICAgICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUuc2V0LFxuICAgICAgICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGVmID0gdGhpcy5fZGVmO1xuICAgICAgICBpZiAoZGVmLm1pblNpemUgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGlmIChjdHguZGF0YS5zaXplIDwgZGVmLm1pblNpemUudmFsdWUpIHtcbiAgICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19zbWFsbCxcbiAgICAgICAgICAgICAgICAgICAgbWluaW11bTogZGVmLm1pblNpemUudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic2V0XCIsXG4gICAgICAgICAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBkZWYubWluU2l6ZS5tZXNzYWdlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChkZWYubWF4U2l6ZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKGN0eC5kYXRhLnNpemUgPiBkZWYubWF4U2l6ZS52YWx1ZSkge1xuICAgICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX2JpZyxcbiAgICAgICAgICAgICAgICAgICAgbWF4aW11bTogZGVmLm1heFNpemUudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic2V0XCIsXG4gICAgICAgICAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBkZWYubWF4U2l6ZS5tZXNzYWdlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHZhbHVlVHlwZSA9IHRoaXMuX2RlZi52YWx1ZVR5cGU7XG4gICAgICAgIGZ1bmN0aW9uIGZpbmFsaXplU2V0KGVsZW1lbnRzKSB7XG4gICAgICAgICAgICBjb25zdCBwYXJzZWRTZXQgPSBuZXcgU2V0KCk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZWxlbWVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC5zdGF0dXMgPT09IFwiYWJvcnRlZFwiKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC5zdGF0dXMgPT09IFwiZGlydHlcIilcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7XG4gICAgICAgICAgICAgICAgcGFyc2VkU2V0LmFkZChlbGVtZW50LnZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7IHN0YXR1czogc3RhdHVzLnZhbHVlLCB2YWx1ZTogcGFyc2VkU2V0IH07XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZWxlbWVudHMgPSBbLi4uY3R4LmRhdGEudmFsdWVzKCldLm1hcCgoaXRlbSwgaSkgPT4gdmFsdWVUeXBlLl9wYXJzZShuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwgaXRlbSwgY3R4LnBhdGgsIGkpKSk7XG4gICAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwoZWxlbWVudHMpLnRoZW4oKGVsZW1lbnRzKSA9PiBmaW5hbGl6ZVNldChlbGVtZW50cykpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZpbmFsaXplU2V0KGVsZW1lbnRzKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBtaW4obWluU2l6ZSwgbWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gbmV3IFpvZFNldCh7XG4gICAgICAgICAgICAuLi50aGlzLl9kZWYsXG4gICAgICAgICAgICBtaW5TaXplOiB7IHZhbHVlOiBtaW5TaXplLCBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkgfSxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIG1heChtYXhTaXplLCBtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiBuZXcgWm9kU2V0KHtcbiAgICAgICAgICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgICAgIG1heFNpemU6IHsgdmFsdWU6IG1heFNpemUsIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSB9LFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgc2l6ZShzaXplLCBtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1pbihzaXplLCBtZXNzYWdlKS5tYXgoc2l6ZSwgbWVzc2FnZSk7XG4gICAgfVxuICAgIG5vbmVtcHR5KG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWluKDEsIG1lc3NhZ2UpO1xuICAgIH1cbn1cblpvZFNldC5jcmVhdGUgPSAodmFsdWVUeXBlLCBwYXJhbXMpID0+IHtcbiAgICByZXR1cm4gbmV3IFpvZFNldCh7XG4gICAgICAgIHZhbHVlVHlwZSxcbiAgICAgICAgbWluU2l6ZTogbnVsbCxcbiAgICAgICAgbWF4U2l6ZTogbnVsbCxcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RTZXQsXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5leHBvcnQgY2xhc3MgWm9kRnVuY3Rpb24gZXh0ZW5kcyBab2RUeXBlIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgdGhpcy52YWxpZGF0ZSA9IHRoaXMuaW1wbGVtZW50O1xuICAgIH1cbiAgICBfcGFyc2UoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgeyBjdHggfSA9IHRoaXMuX3Byb2Nlc3NJbnB1dFBhcmFtcyhpbnB1dCk7XG4gICAgICAgIGlmIChjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5mdW5jdGlvbikge1xuICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7XG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSxcbiAgICAgICAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5mdW5jdGlvbixcbiAgICAgICAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIG1ha2VBcmdzSXNzdWUoYXJncywgZXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBtYWtlSXNzdWUoe1xuICAgICAgICAgICAgICAgIGRhdGE6IGFyZ3MsXG4gICAgICAgICAgICAgICAgcGF0aDogY3R4LnBhdGgsXG4gICAgICAgICAgICAgICAgZXJyb3JNYXBzOiBbY3R4LmNvbW1vbi5jb250ZXh0dWFsRXJyb3JNYXAsIGN0eC5zY2hlbWFFcnJvck1hcCwgZ2V0RXJyb3JNYXAoKSwgZGVmYXVsdEVycm9yTWFwXS5maWx0ZXIoKHgpID0+ICEheCksXG4gICAgICAgICAgICAgICAgaXNzdWVEYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX2FyZ3VtZW50cyxcbiAgICAgICAgICAgICAgICAgICAgYXJndW1lbnRzRXJyb3I6IGVycm9yLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBtYWtlUmV0dXJuc0lzc3VlKHJldHVybnMsIGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gbWFrZUlzc3VlKHtcbiAgICAgICAgICAgICAgICBkYXRhOiByZXR1cm5zLFxuICAgICAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLFxuICAgICAgICAgICAgICAgIGVycm9yTWFwczogW2N0eC5jb21tb24uY29udGV4dHVhbEVycm9yTWFwLCBjdHguc2NoZW1hRXJyb3JNYXAsIGdldEVycm9yTWFwKCksIGRlZmF1bHRFcnJvck1hcF0uZmlsdGVyKCh4KSA9PiAhIXgpLFxuICAgICAgICAgICAgICAgIGlzc3VlRGF0YToge1xuICAgICAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9yZXR1cm5fdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuVHlwZUVycm9yOiBlcnJvcixcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGFyYW1zID0geyBlcnJvck1hcDogY3R4LmNvbW1vbi5jb250ZXh0dWFsRXJyb3JNYXAgfTtcbiAgICAgICAgY29uc3QgZm4gPSBjdHguZGF0YTtcbiAgICAgICAgaWYgKHRoaXMuX2RlZi5yZXR1cm5zIGluc3RhbmNlb2YgWm9kUHJvbWlzZSkge1xuICAgICAgICAgICAgLy8gV291bGQgbG92ZSBhIHdheSB0byBhdm9pZCBkaXNhYmxpbmcgdGhpcyBydWxlLCBidXQgd2UgbmVlZFxuICAgICAgICAgICAgLy8gYW4gYWxpYXMgKHVzaW5nIGFuIGFycm93IGZ1bmN0aW9uIHdhcyB3aGF0IGNhdXNlZCAyNjUxKS5cbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdGhpcy1hbGlhc1xuICAgICAgICAgICAgY29uc3QgbWUgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIE9LKGFzeW5jIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgWm9kRXJyb3IoW10pO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhcnNlZEFyZ3MgPSBhd2FpdCBtZS5fZGVmLmFyZ3MucGFyc2VBc3luYyhhcmdzLCBwYXJhbXMpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yLmFkZElzc3VlKG1ha2VBcmdzSXNzdWUoYXJncywgZSkpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBSZWZsZWN0LmFwcGx5KGZuLCB0aGlzLCBwYXJzZWRBcmdzKTtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJzZWRSZXR1cm5zID0gYXdhaXQgbWUuX2RlZi5yZXR1cm5zLl9kZWYudHlwZVxuICAgICAgICAgICAgICAgICAgICAucGFyc2VBc3luYyhyZXN1bHQsIHBhcmFtcylcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yLmFkZElzc3VlKG1ha2VSZXR1cm5zSXNzdWUocmVzdWx0LCBlKSk7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXJzZWRSZXR1cm5zO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBXb3VsZCBsb3ZlIGEgd2F5IHRvIGF2b2lkIGRpc2FibGluZyB0aGlzIHJ1bGUsIGJ1dCB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhbiBhbGlhcyAodXNpbmcgYW4gYXJyb3cgZnVuY3Rpb24gd2FzIHdoYXQgY2F1c2VkIDI2NTEpLlxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby10aGlzLWFsaWFzXG4gICAgICAgICAgICBjb25zdCBtZSA9IHRoaXM7XG4gICAgICAgICAgICByZXR1cm4gT0soZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJzZWRBcmdzID0gbWUuX2RlZi5hcmdzLnNhZmVQYXJzZShhcmdzLCBwYXJhbXMpO1xuICAgICAgICAgICAgICAgIGlmICghcGFyc2VkQXJncy5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBab2RFcnJvcihbbWFrZUFyZ3NJc3N1ZShhcmdzLCBwYXJzZWRBcmdzLmVycm9yKV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBSZWZsZWN0LmFwcGx5KGZuLCB0aGlzLCBwYXJzZWRBcmdzLmRhdGEpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhcnNlZFJldHVybnMgPSBtZS5fZGVmLnJldHVybnMuc2FmZVBhcnNlKHJlc3VsdCwgcGFyYW1zKTtcbiAgICAgICAgICAgICAgICBpZiAoIXBhcnNlZFJldHVybnMuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgWm9kRXJyb3IoW21ha2VSZXR1cm5zSXNzdWUocmVzdWx0LCBwYXJzZWRSZXR1cm5zLmVycm9yKV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyc2VkUmV0dXJucy5kYXRhO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcGFyYW1ldGVycygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi5hcmdzO1xuICAgIH1cbiAgICByZXR1cm5UeXBlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGVmLnJldHVybnM7XG4gICAgfVxuICAgIGFyZ3MoLi4uaXRlbXMpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBab2RGdW5jdGlvbih7XG4gICAgICAgICAgICAuLi50aGlzLl9kZWYsXG4gICAgICAgICAgICBhcmdzOiBab2RUdXBsZS5jcmVhdGUoaXRlbXMpLnJlc3QoWm9kVW5rbm93bi5jcmVhdGUoKSksXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm5zKHJldHVyblR5cGUpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBab2RGdW5jdGlvbih7XG4gICAgICAgICAgICAuLi50aGlzLl9kZWYsXG4gICAgICAgICAgICByZXR1cm5zOiByZXR1cm5UeXBlLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgaW1wbGVtZW50KGZ1bmMpIHtcbiAgICAgICAgY29uc3QgdmFsaWRhdGVkRnVuYyA9IHRoaXMucGFyc2UoZnVuYyk7XG4gICAgICAgIHJldHVybiB2YWxpZGF0ZWRGdW5jO1xuICAgIH1cbiAgICBzdHJpY3RJbXBsZW1lbnQoZnVuYykge1xuICAgICAgICBjb25zdCB2YWxpZGF0ZWRGdW5jID0gdGhpcy5wYXJzZShmdW5jKTtcbiAgICAgICAgcmV0dXJuIHZhbGlkYXRlZEZ1bmM7XG4gICAgfVxuICAgIHN0YXRpYyBjcmVhdGUoYXJncywgcmV0dXJucywgcGFyYW1zKSB7XG4gICAgICAgIHJldHVybiBuZXcgWm9kRnVuY3Rpb24oe1xuICAgICAgICAgICAgYXJnczogKGFyZ3MgPyBhcmdzIDogWm9kVHVwbGUuY3JlYXRlKFtdKS5yZXN0KFpvZFVua25vd24uY3JlYXRlKCkpKSxcbiAgICAgICAgICAgIHJldHVybnM6IHJldHVybnMgfHwgWm9kVW5rbm93bi5jcmVhdGUoKSxcbiAgICAgICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRnVuY3Rpb24sXG4gICAgICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgICAgIH0pO1xuICAgIH1cbn1cbmV4cG9ydCBjbGFzcyBab2RMYXp5IGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgZ2V0IHNjaGVtYSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi5nZXR0ZXIoKTtcbiAgICB9XG4gICAgX3BhcnNlKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpO1xuICAgICAgICBjb25zdCBsYXp5U2NoZW1hID0gdGhpcy5fZGVmLmdldHRlcigpO1xuICAgICAgICByZXR1cm4gbGF6eVNjaGVtYS5fcGFyc2UoeyBkYXRhOiBjdHguZGF0YSwgcGF0aDogY3R4LnBhdGgsIHBhcmVudDogY3R4IH0pO1xuICAgIH1cbn1cblpvZExhenkuY3JlYXRlID0gKGdldHRlciwgcGFyYW1zKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBab2RMYXp5KHtcbiAgICAgICAgZ2V0dGVyOiBnZXR0ZXIsXG4gICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kTGF6eSxcbiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpLFxuICAgIH0pO1xufTtcbmV4cG9ydCBjbGFzcyBab2RMaXRlcmFsIGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgX3BhcnNlKGlucHV0KSB7XG4gICAgICAgIGlmIChpbnB1dC5kYXRhICE9PSB0aGlzLl9kZWYudmFsdWUpIHtcbiAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTtcbiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgIHJlY2VpdmVkOiBjdHguZGF0YSxcbiAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9saXRlcmFsLFxuICAgICAgICAgICAgICAgIGV4cGVjdGVkOiB0aGlzLl9kZWYudmFsdWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHN0YXR1czogXCJ2YWxpZFwiLCB2YWx1ZTogaW5wdXQuZGF0YSB9O1xuICAgIH1cbiAgICBnZXQgdmFsdWUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYudmFsdWU7XG4gICAgfVxufVxuWm9kTGl0ZXJhbC5jcmVhdGUgPSAodmFsdWUsIHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kTGl0ZXJhbCh7XG4gICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RMaXRlcmFsLFxuICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgfSk7XG59O1xuZnVuY3Rpb24gY3JlYXRlWm9kRW51bSh2YWx1ZXMsIHBhcmFtcykge1xuICAgIHJldHVybiBuZXcgWm9kRW51bSh7XG4gICAgICAgIHZhbHVlcyxcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RFbnVtLFxuICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgfSk7XG59XG5leHBvcnQgY2xhc3MgWm9kRW51bSBleHRlbmRzIFpvZFR5cGUge1xuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0LmRhdGEgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTtcbiAgICAgICAgICAgIGNvbnN0IGV4cGVjdGVkVmFsdWVzID0gdGhpcy5fZGVmLnZhbHVlcztcbiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgIGV4cGVjdGVkOiB1dGlsLmpvaW5WYWx1ZXMoZXhwZWN0ZWRWYWx1ZXMpLFxuICAgICAgICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZSxcbiAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuX2NhY2hlKSB7XG4gICAgICAgICAgICB0aGlzLl9jYWNoZSA9IG5ldyBTZXQodGhpcy5fZGVmLnZhbHVlcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLl9jYWNoZS5oYXMoaW5wdXQuZGF0YSkpIHtcbiAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTtcbiAgICAgICAgICAgIGNvbnN0IGV4cGVjdGVkVmFsdWVzID0gdGhpcy5fZGVmLnZhbHVlcztcbiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgIHJlY2VpdmVkOiBjdHguZGF0YSxcbiAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9lbnVtX3ZhbHVlLFxuICAgICAgICAgICAgICAgIG9wdGlvbnM6IGV4cGVjdGVkVmFsdWVzLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gT0soaW5wdXQuZGF0YSk7XG4gICAgfVxuICAgIGdldCBvcHRpb25zKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGVmLnZhbHVlcztcbiAgICB9XG4gICAgZ2V0IGVudW0oKSB7XG4gICAgICAgIGNvbnN0IGVudW1WYWx1ZXMgPSB7fTtcbiAgICAgICAgZm9yIChjb25zdCB2YWwgb2YgdGhpcy5fZGVmLnZhbHVlcykge1xuICAgICAgICAgICAgZW51bVZhbHVlc1t2YWxdID0gdmFsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlbnVtVmFsdWVzO1xuICAgIH1cbiAgICBnZXQgVmFsdWVzKCkge1xuICAgICAgICBjb25zdCBlbnVtVmFsdWVzID0ge307XG4gICAgICAgIGZvciAoY29uc3QgdmFsIG9mIHRoaXMuX2RlZi52YWx1ZXMpIHtcbiAgICAgICAgICAgIGVudW1WYWx1ZXNbdmFsXSA9IHZhbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZW51bVZhbHVlcztcbiAgICB9XG4gICAgZ2V0IEVudW0oKSB7XG4gICAgICAgIGNvbnN0IGVudW1WYWx1ZXMgPSB7fTtcbiAgICAgICAgZm9yIChjb25zdCB2YWwgb2YgdGhpcy5fZGVmLnZhbHVlcykge1xuICAgICAgICAgICAgZW51bVZhbHVlc1t2YWxdID0gdmFsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlbnVtVmFsdWVzO1xuICAgIH1cbiAgICBleHRyYWN0KHZhbHVlcywgbmV3RGVmID0gdGhpcy5fZGVmKSB7XG4gICAgICAgIHJldHVybiBab2RFbnVtLmNyZWF0ZSh2YWx1ZXMsIHtcbiAgICAgICAgICAgIC4uLnRoaXMuX2RlZixcbiAgICAgICAgICAgIC4uLm5ld0RlZixcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGV4Y2x1ZGUodmFsdWVzLCBuZXdEZWYgPSB0aGlzLl9kZWYpIHtcbiAgICAgICAgcmV0dXJuIFpvZEVudW0uY3JlYXRlKHRoaXMub3B0aW9ucy5maWx0ZXIoKG9wdCkgPT4gIXZhbHVlcy5pbmNsdWRlcyhvcHQpKSwge1xuICAgICAgICAgICAgLi4udGhpcy5fZGVmLFxuICAgICAgICAgICAgLi4ubmV3RGVmLFxuICAgICAgICB9KTtcbiAgICB9XG59XG5ab2RFbnVtLmNyZWF0ZSA9IGNyZWF0ZVpvZEVudW07XG5leHBvcnQgY2xhc3MgWm9kTmF0aXZlRW51bSBleHRlbmRzIFpvZFR5cGUge1xuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICBjb25zdCBuYXRpdmVFbnVtVmFsdWVzID0gdXRpbC5nZXRWYWxpZEVudW1WYWx1ZXModGhpcy5fZGVmLnZhbHVlcyk7XG4gICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTtcbiAgICAgICAgaWYgKGN0eC5wYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLnN0cmluZyAmJiBjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5udW1iZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IGV4cGVjdGVkVmFsdWVzID0gdXRpbC5vYmplY3RWYWx1ZXMobmF0aXZlRW51bVZhbHVlcyk7XG4gICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICBleHBlY3RlZDogdXRpbC5qb2luVmFsdWVzKGV4cGVjdGVkVmFsdWVzKSxcbiAgICAgICAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUsXG4gICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLl9jYWNoZSkge1xuICAgICAgICAgICAgdGhpcy5fY2FjaGUgPSBuZXcgU2V0KHV0aWwuZ2V0VmFsaWRFbnVtVmFsdWVzKHRoaXMuX2RlZi52YWx1ZXMpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuX2NhY2hlLmhhcyhpbnB1dC5kYXRhKSkge1xuICAgICAgICAgICAgY29uc3QgZXhwZWN0ZWRWYWx1ZXMgPSB1dGlsLm9iamVjdFZhbHVlcyhuYXRpdmVFbnVtVmFsdWVzKTtcbiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwge1xuICAgICAgICAgICAgICAgIHJlY2VpdmVkOiBjdHguZGF0YSxcbiAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9lbnVtX3ZhbHVlLFxuICAgICAgICAgICAgICAgIG9wdGlvbnM6IGV4cGVjdGVkVmFsdWVzLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gT0soaW5wdXQuZGF0YSk7XG4gICAgfVxuICAgIGdldCBlbnVtKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGVmLnZhbHVlcztcbiAgICB9XG59XG5ab2ROYXRpdmVFbnVtLmNyZWF0ZSA9ICh2YWx1ZXMsIHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kTmF0aXZlRW51bSh7XG4gICAgICAgIHZhbHVlczogdmFsdWVzLFxuICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE5hdGl2ZUVudW0sXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5leHBvcnQgY2xhc3MgWm9kUHJvbWlzZSBleHRlbmRzIFpvZFR5cGUge1xuICAgIHVud3JhcCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi50eXBlO1xuICAgIH1cbiAgICBfcGFyc2UoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgeyBjdHggfSA9IHRoaXMuX3Byb2Nlc3NJbnB1dFBhcmFtcyhpbnB1dCk7XG4gICAgICAgIGlmIChjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5wcm9taXNlICYmIGN0eC5jb21tb24uYXN5bmMgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLFxuICAgICAgICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLnByb21pc2UsXG4gICAgICAgICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwcm9taXNpZmllZCA9IGN0eC5wYXJzZWRUeXBlID09PSBab2RQYXJzZWRUeXBlLnByb21pc2UgPyBjdHguZGF0YSA6IFByb21pc2UucmVzb2x2ZShjdHguZGF0YSk7XG4gICAgICAgIHJldHVybiBPSyhwcm9taXNpZmllZC50aGVuKChkYXRhKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fZGVmLnR5cGUucGFyc2VBc3luYyhkYXRhLCB7XG4gICAgICAgICAgICAgICAgcGF0aDogY3R4LnBhdGgsXG4gICAgICAgICAgICAgICAgZXJyb3JNYXA6IGN0eC5jb21tb24uY29udGV4dHVhbEVycm9yTWFwLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pKTtcbiAgICB9XG59XG5ab2RQcm9taXNlLmNyZWF0ZSA9IChzY2hlbWEsIHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kUHJvbWlzZSh7XG4gICAgICAgIHR5cGU6IHNjaGVtYSxcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RQcm9taXNlLFxuICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgfSk7XG59O1xuZXhwb3J0IGNsYXNzIFpvZEVmZmVjdHMgZXh0ZW5kcyBab2RUeXBlIHtcbiAgICBpbm5lclR5cGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYuc2NoZW1hO1xuICAgIH1cbiAgICBzb3VyY2VUeXBlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGVmLnNjaGVtYS5fZGVmLnR5cGVOYW1lID09PSBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRWZmZWN0c1xuICAgICAgICAgICAgPyB0aGlzLl9kZWYuc2NoZW1hLnNvdXJjZVR5cGUoKVxuICAgICAgICAgICAgOiB0aGlzLl9kZWYuc2NoZW1hO1xuICAgIH1cbiAgICBfcGFyc2UoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTtcbiAgICAgICAgY29uc3QgZWZmZWN0ID0gdGhpcy5fZGVmLmVmZmVjdCB8fCBudWxsO1xuICAgICAgICBjb25zdCBjaGVja0N0eCA9IHtcbiAgICAgICAgICAgIGFkZElzc3VlOiAoYXJnKSA9PiB7XG4gICAgICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCBhcmcpO1xuICAgICAgICAgICAgICAgIGlmIChhcmcuZmF0YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzLmFib3J0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0IHBhdGgoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN0eC5wYXRoO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgICAgY2hlY2tDdHguYWRkSXNzdWUgPSBjaGVja0N0eC5hZGRJc3N1ZS5iaW5kKGNoZWNrQ3R4KTtcbiAgICAgICAgaWYgKGVmZmVjdC50eXBlID09PSBcInByZXByb2Nlc3NcIikge1xuICAgICAgICAgICAgY29uc3QgcHJvY2Vzc2VkID0gZWZmZWN0LnRyYW5zZm9ybShjdHguZGF0YSwgY2hlY2tDdHgpO1xuICAgICAgICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHByb2Nlc3NlZCkudGhlbihhc3luYyAocHJvY2Vzc2VkKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0dXMudmFsdWUgPT09IFwiYWJvcnRlZFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuX2RlZi5zY2hlbWEuX3BhcnNlQXN5bmMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogcHJvY2Vzc2VkLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGF0aDogY3R4LnBhdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnQ6IGN0eCxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSBcImFib3J0ZWRcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gXCJkaXJ0eVwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIERJUlRZKHJlc3VsdC52YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0dXMudmFsdWUgPT09IFwiZGlydHlcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBESVJUWShyZXN1bHQudmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHN0YXR1cy52YWx1ZSA9PT0gXCJhYm9ydGVkXCIpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX2RlZi5zY2hlbWEuX3BhcnNlU3luYyh7XG4gICAgICAgICAgICAgICAgICAgIGRhdGE6IHByb2Nlc3NlZCxcbiAgICAgICAgICAgICAgICAgICAgcGF0aDogY3R4LnBhdGgsXG4gICAgICAgICAgICAgICAgICAgIHBhcmVudDogY3R4LFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSBcImFib3J0ZWRcIilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5zdGF0dXMgPT09IFwiZGlydHlcIilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIERJUlRZKHJlc3VsdC52YWx1ZSk7XG4gICAgICAgICAgICAgICAgaWYgKHN0YXR1cy52YWx1ZSA9PT0gXCJkaXJ0eVwiKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gRElSVFkocmVzdWx0LnZhbHVlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChlZmZlY3QudHlwZSA9PT0gXCJyZWZpbmVtZW50XCIpIHtcbiAgICAgICAgICAgIGNvbnN0IGV4ZWN1dGVSZWZpbmVtZW50ID0gKGFjYykgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGVmZmVjdC5yZWZpbmVtZW50KGFjYywgY2hlY2tDdHgpO1xuICAgICAgICAgICAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzdWx0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQXN5bmMgcmVmaW5lbWVudCBlbmNvdW50ZXJlZCBkdXJpbmcgc3luY2hyb25vdXMgcGFyc2Ugb3BlcmF0aW9uLiBVc2UgLnBhcnNlQXN5bmMgaW5zdGVhZC5cIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaW5uZXIgPSB0aGlzLl9kZWYuc2NoZW1hLl9wYXJzZVN5bmMoe1xuICAgICAgICAgICAgICAgICAgICBkYXRhOiBjdHguZGF0YSxcbiAgICAgICAgICAgICAgICAgICAgcGF0aDogY3R4LnBhdGgsXG4gICAgICAgICAgICAgICAgICAgIHBhcmVudDogY3R4LFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChpbm5lci5zdGF0dXMgPT09IFwiYWJvcnRlZFwiKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgICAgICAgICBpZiAoaW5uZXIuc3RhdHVzID09PSBcImRpcnR5XCIpXG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgICAgIC8vIHJldHVybiB2YWx1ZSBpcyBpZ25vcmVkXG4gICAgICAgICAgICAgICAgZXhlY3V0ZVJlZmluZW1lbnQoaW5uZXIudmFsdWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiB7IHN0YXR1czogc3RhdHVzLnZhbHVlLCB2YWx1ZTogaW5uZXIudmFsdWUgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9kZWYuc2NoZW1hLl9wYXJzZUFzeW5jKHsgZGF0YTogY3R4LmRhdGEsIHBhdGg6IGN0eC5wYXRoLCBwYXJlbnQ6IGN0eCB9KS50aGVuKChpbm5lcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5uZXIuc3RhdHVzID09PSBcImFib3J0ZWRcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5uZXIuc3RhdHVzID09PSBcImRpcnR5XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV4ZWN1dGVSZWZpbmVtZW50KGlubmVyLnZhbHVlKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IHN0YXR1czogc3RhdHVzLnZhbHVlLCB2YWx1ZTogaW5uZXIudmFsdWUgfTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVmZmVjdC50eXBlID09PSBcInRyYW5zZm9ybVwiKSB7XG4gICAgICAgICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBiYXNlID0gdGhpcy5fZGVmLnNjaGVtYS5fcGFyc2VTeW5jKHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsXG4gICAgICAgICAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLFxuICAgICAgICAgICAgICAgICAgICBwYXJlbnQ6IGN0eCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoIWlzVmFsaWQoYmFzZSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGVmZmVjdC50cmFuc2Zvcm0oYmFzZS52YWx1ZSwgY2hlY2tDdHgpO1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQXN5bmNocm9ub3VzIHRyYW5zZm9ybSBlbmNvdW50ZXJlZCBkdXJpbmcgc3luY2hyb25vdXMgcGFyc2Ugb3BlcmF0aW9uLiBVc2UgLnBhcnNlQXN5bmMgaW5zdGVhZC5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiByZXN1bHQgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9kZWYuc2NoZW1hLl9wYXJzZUFzeW5jKHsgZGF0YTogY3R4LmRhdGEsIHBhdGg6IGN0eC5wYXRoLCBwYXJlbnQ6IGN0eCB9KS50aGVuKChiYXNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWYWxpZChiYXNlKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGVmZmVjdC50cmFuc2Zvcm0oYmFzZS52YWx1ZSwgY2hlY2tDdHgpKS50aGVuKChyZXN1bHQpID0+ICh7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXM6IHN0YXR1cy52YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiByZXN1bHQsXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB1dGlsLmFzc2VydE5ldmVyKGVmZmVjdCk7XG4gICAgfVxufVxuWm9kRWZmZWN0cy5jcmVhdGUgPSAoc2NoZW1hLCBlZmZlY3QsIHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kRWZmZWN0cyh7XG4gICAgICAgIHNjaGVtYSxcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RFZmZlY3RzLFxuICAgICAgICBlZmZlY3QsXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5ab2RFZmZlY3RzLmNyZWF0ZVdpdGhQcmVwcm9jZXNzID0gKHByZXByb2Nlc3MsIHNjaGVtYSwgcGFyYW1zKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBab2RFZmZlY3RzKHtcbiAgICAgICAgc2NoZW1hLFxuICAgICAgICBlZmZlY3Q6IHsgdHlwZTogXCJwcmVwcm9jZXNzXCIsIHRyYW5zZm9ybTogcHJlcHJvY2VzcyB9LFxuICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVmZmVjdHMsXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5leHBvcnQgeyBab2RFZmZlY3RzIGFzIFpvZFRyYW5zZm9ybWVyIH07XG5leHBvcnQgY2xhc3MgWm9kT3B0aW9uYWwgZXh0ZW5kcyBab2RUeXBlIHtcbiAgICBfcGFyc2UoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpO1xuICAgICAgICBpZiAocGFyc2VkVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS51bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBPSyh1bmRlZmluZWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYuaW5uZXJUeXBlLl9wYXJzZShpbnB1dCk7XG4gICAgfVxuICAgIHVud3JhcCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi5pbm5lclR5cGU7XG4gICAgfVxufVxuWm9kT3B0aW9uYWwuY3JlYXRlID0gKHR5cGUsIHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kT3B0aW9uYWwoe1xuICAgICAgICBpbm5lclR5cGU6IHR5cGUsXG4gICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kT3B0aW9uYWwsXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5leHBvcnQgY2xhc3MgWm9kTnVsbGFibGUgZXh0ZW5kcyBab2RUeXBlIHtcbiAgICBfcGFyc2UoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpO1xuICAgICAgICBpZiAocGFyc2VkVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS5udWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gT0sobnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi5pbm5lclR5cGUuX3BhcnNlKGlucHV0KTtcbiAgICB9XG4gICAgdW53cmFwKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZTtcbiAgICB9XG59XG5ab2ROdWxsYWJsZS5jcmVhdGUgPSAodHlwZSwgcGFyYW1zKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBab2ROdWxsYWJsZSh7XG4gICAgICAgIGlubmVyVHlwZTogdHlwZSxcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2ROdWxsYWJsZSxcbiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpLFxuICAgIH0pO1xufTtcbmV4cG9ydCBjbGFzcyBab2REZWZhdWx0IGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgX3BhcnNlKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpO1xuICAgICAgICBsZXQgZGF0YSA9IGN0eC5kYXRhO1xuICAgICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgPT09IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBkYXRhID0gdGhpcy5fZGVmLmRlZmF1bHRWYWx1ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYuaW5uZXJUeXBlLl9wYXJzZSh7XG4gICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgcGF0aDogY3R4LnBhdGgsXG4gICAgICAgICAgICBwYXJlbnQ6IGN0eCxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJlbW92ZURlZmF1bHQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYuaW5uZXJUeXBlO1xuICAgIH1cbn1cblpvZERlZmF1bHQuY3JlYXRlID0gKHR5cGUsIHBhcmFtcykgPT4ge1xuICAgIHJldHVybiBuZXcgWm9kRGVmYXVsdCh7XG4gICAgICAgIGlubmVyVHlwZTogdHlwZSxcbiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2REZWZhdWx0LFxuICAgICAgICBkZWZhdWx0VmFsdWU6IHR5cGVvZiBwYXJhbXMuZGVmYXVsdCA9PT0gXCJmdW5jdGlvblwiID8gcGFyYW1zLmRlZmF1bHQgOiAoKSA9PiBwYXJhbXMuZGVmYXVsdCxcbiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpLFxuICAgIH0pO1xufTtcbmV4cG9ydCBjbGFzcyBab2RDYXRjaCBleHRlbmRzIFpvZFR5cGUge1xuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTtcbiAgICAgICAgLy8gbmV3Q3R4IGlzIHVzZWQgdG8gbm90IGNvbGxlY3QgaXNzdWVzIGZyb20gaW5uZXIgdHlwZXMgaW4gY3R4XG4gICAgICAgIGNvbnN0IG5ld0N0eCA9IHtcbiAgICAgICAgICAgIC4uLmN0eCxcbiAgICAgICAgICAgIGNvbW1vbjoge1xuICAgICAgICAgICAgICAgIC4uLmN0eC5jb21tb24sXG4gICAgICAgICAgICAgICAgaXNzdWVzOiBbXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX2RlZi5pbm5lclR5cGUuX3BhcnNlKHtcbiAgICAgICAgICAgIGRhdGE6IG5ld0N0eC5kYXRhLFxuICAgICAgICAgICAgcGF0aDogbmV3Q3R4LnBhdGgsXG4gICAgICAgICAgICBwYXJlbnQ6IHtcbiAgICAgICAgICAgICAgICAuLi5uZXdDdHgsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGlzQXN5bmMocmVzdWx0KSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXM6IFwidmFsaWRcIixcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHJlc3VsdC5zdGF0dXMgPT09IFwidmFsaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgPyByZXN1bHQudmFsdWVcbiAgICAgICAgICAgICAgICAgICAgICAgIDogdGhpcy5fZGVmLmNhdGNoVmFsdWUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldCBlcnJvcigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBab2RFcnJvcihuZXdDdHguY29tbW9uLmlzc3Vlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dDogbmV3Q3R4LmRhdGEsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHN0YXR1czogXCJ2YWxpZFwiLFxuICAgICAgICAgICAgICAgIHZhbHVlOiByZXN1bHQuc3RhdHVzID09PSBcInZhbGlkXCJcbiAgICAgICAgICAgICAgICAgICAgPyByZXN1bHQudmFsdWVcbiAgICAgICAgICAgICAgICAgICAgOiB0aGlzLl9kZWYuY2F0Y2hWYWx1ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBnZXQgZXJyb3IoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBab2RFcnJvcihuZXdDdHguY29tbW9uLmlzc3Vlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQ6IG5ld0N0eC5kYXRhLFxuICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmVtb3ZlQ2F0Y2goKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYuaW5uZXJUeXBlO1xuICAgIH1cbn1cblpvZENhdGNoLmNyZWF0ZSA9ICh0eXBlLCBwYXJhbXMpID0+IHtcbiAgICByZXR1cm4gbmV3IFpvZENhdGNoKHtcbiAgICAgICAgaW5uZXJUeXBlOiB0eXBlLFxuICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZENhdGNoLFxuICAgICAgICBjYXRjaFZhbHVlOiB0eXBlb2YgcGFyYW1zLmNhdGNoID09PSBcImZ1bmN0aW9uXCIgPyBwYXJhbXMuY2F0Y2ggOiAoKSA9PiBwYXJhbXMuY2F0Y2gsXG4gICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSxcbiAgICB9KTtcbn07XG5leHBvcnQgY2xhc3MgWm9kTmFOIGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgX3BhcnNlKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTtcbiAgICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUubmFuKSB7XG4gICAgICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7XG4gICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHtcbiAgICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLFxuICAgICAgICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm5hbixcbiAgICAgICAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBJTlZBTElEO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHN0YXR1czogXCJ2YWxpZFwiLCB2YWx1ZTogaW5wdXQuZGF0YSB9O1xuICAgIH1cbn1cblpvZE5hTi5jcmVhdGUgPSAocGFyYW1zKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBab2ROYU4oe1xuICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE5hTixcbiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpLFxuICAgIH0pO1xufTtcbmV4cG9ydCBjb25zdCBCUkFORCA9IFN5bWJvbChcInpvZF9icmFuZFwiKTtcbmV4cG9ydCBjbGFzcyBab2RCcmFuZGVkIGV4dGVuZHMgWm9kVHlwZSB7XG4gICAgX3BhcnNlKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpO1xuICAgICAgICBjb25zdCBkYXRhID0gY3R4LmRhdGE7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYudHlwZS5fcGFyc2Uoe1xuICAgICAgICAgICAgZGF0YSxcbiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLFxuICAgICAgICAgICAgcGFyZW50OiBjdHgsXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICB1bndyYXAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYudHlwZTtcbiAgICB9XG59XG5leHBvcnQgY2xhc3MgWm9kUGlwZWxpbmUgZXh0ZW5kcyBab2RUeXBlIHtcbiAgICBfcGFyc2UoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTtcbiAgICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHtcbiAgICAgICAgICAgIGNvbnN0IGhhbmRsZUFzeW5jID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGluUmVzdWx0ID0gYXdhaXQgdGhpcy5fZGVmLmluLl9wYXJzZUFzeW5jKHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsXG4gICAgICAgICAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLFxuICAgICAgICAgICAgICAgICAgICBwYXJlbnQ6IGN0eCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoaW5SZXN1bHQuc3RhdHVzID09PSBcImFib3J0ZWRcIilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgICAgICAgICAgaWYgKGluUmVzdWx0LnN0YXR1cyA9PT0gXCJkaXJ0eVwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gRElSVFkoaW5SZXN1bHQudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi5vdXQuX3BhcnNlQXN5bmMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogaW5SZXN1bHQudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRoOiBjdHgucGF0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudDogY3R4LFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIGhhbmRsZUFzeW5jKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBpblJlc3VsdCA9IHRoaXMuX2RlZi5pbi5fcGFyc2VTeW5jKHtcbiAgICAgICAgICAgICAgICBkYXRhOiBjdHguZGF0YSxcbiAgICAgICAgICAgICAgICBwYXRoOiBjdHgucGF0aCxcbiAgICAgICAgICAgICAgICBwYXJlbnQ6IGN0eCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKGluUmVzdWx0LnN0YXR1cyA9PT0gXCJhYm9ydGVkXCIpXG4gICAgICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgICAgICBpZiAoaW5SZXN1bHQuc3RhdHVzID09PSBcImRpcnR5XCIpIHtcbiAgICAgICAgICAgICAgICBzdGF0dXMuZGlydHkoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXM6IFwiZGlydHlcIixcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGluUmVzdWx0LnZhbHVlLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZGVmLm91dC5fcGFyc2VTeW5jKHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogaW5SZXN1bHQudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLFxuICAgICAgICAgICAgICAgICAgICBwYXJlbnQ6IGN0eCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBzdGF0aWMgY3JlYXRlKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBab2RQaXBlbGluZSh7XG4gICAgICAgICAgICBpbjogYSxcbiAgICAgICAgICAgIG91dDogYixcbiAgICAgICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kUGlwZWxpbmUsXG4gICAgICAgIH0pO1xuICAgIH1cbn1cbmV4cG9ydCBjbGFzcyBab2RSZWFkb25seSBleHRlbmRzIFpvZFR5cGUge1xuICAgIF9wYXJzZShpbnB1dCkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLl9kZWYuaW5uZXJUeXBlLl9wYXJzZShpbnB1dCk7XG4gICAgICAgIGNvbnN0IGZyZWV6ZSA9IChkYXRhKSA9PiB7XG4gICAgICAgICAgICBpZiAoaXNWYWxpZChkYXRhKSkge1xuICAgICAgICAgICAgICAgIGRhdGEudmFsdWUgPSBPYmplY3QuZnJlZXplKGRhdGEudmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBpc0FzeW5jKHJlc3VsdCkgPyByZXN1bHQudGhlbigoZGF0YSkgPT4gZnJlZXplKGRhdGEpKSA6IGZyZWV6ZShyZXN1bHQpO1xuICAgIH1cbiAgICB1bndyYXAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYuaW5uZXJUeXBlO1xuICAgIH1cbn1cblpvZFJlYWRvbmx5LmNyZWF0ZSA9ICh0eXBlLCBwYXJhbXMpID0+IHtcbiAgICByZXR1cm4gbmV3IFpvZFJlYWRvbmx5KHtcbiAgICAgICAgaW5uZXJUeXBlOiB0eXBlLFxuICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZFJlYWRvbmx5LFxuICAgICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcyksXG4gICAgfSk7XG59O1xuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuLy8vLy8vLy8vLyAgICAgICAgICAgICAgICAgICAgLy8vLy8vLy8vL1xuLy8vLy8vLy8vLyAgICAgIHouY3VzdG9tICAgICAgLy8vLy8vLy8vL1xuLy8vLy8vLy8vLyAgICAgICAgICAgICAgICAgICAgLy8vLy8vLy8vL1xuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuZnVuY3Rpb24gY2xlYW5QYXJhbXMocGFyYW1zLCBkYXRhKSB7XG4gICAgY29uc3QgcCA9IHR5cGVvZiBwYXJhbXMgPT09IFwiZnVuY3Rpb25cIiA/IHBhcmFtcyhkYXRhKSA6IHR5cGVvZiBwYXJhbXMgPT09IFwic3RyaW5nXCIgPyB7IG1lc3NhZ2U6IHBhcmFtcyB9IDogcGFyYW1zO1xuICAgIGNvbnN0IHAyID0gdHlwZW9mIHAgPT09IFwic3RyaW5nXCIgPyB7IG1lc3NhZ2U6IHAgfSA6IHA7XG4gICAgcmV0dXJuIHAyO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGN1c3RvbShjaGVjaywgX3BhcmFtcyA9IHt9LCBcbi8qKlxuICogQGRlcHJlY2F0ZWRcbiAqXG4gKiBQYXNzIGBmYXRhbGAgaW50byB0aGUgcGFyYW1zIG9iamVjdCBpbnN0ZWFkOlxuICpcbiAqIGBgYHRzXG4gKiB6LnN0cmluZygpLmN1c3RvbSgodmFsKSA9PiB2YWwubGVuZ3RoID4gNSwgeyBmYXRhbDogZmFsc2UgfSlcbiAqIGBgYFxuICpcbiAqL1xuZmF0YWwpIHtcbiAgICBpZiAoY2hlY2spXG4gICAgICAgIHJldHVybiBab2RBbnkuY3JlYXRlKCkuc3VwZXJSZWZpbmUoKGRhdGEsIGN0eCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgciA9IGNoZWNrKGRhdGEpO1xuICAgICAgICAgICAgaWYgKHIgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHIudGhlbigocikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IGNsZWFuUGFyYW1zKF9wYXJhbXMsIGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgX2ZhdGFsID0gcGFyYW1zLmZhdGFsID8/IGZhdGFsID8/IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdHguYWRkSXNzdWUoeyBjb2RlOiBcImN1c3RvbVwiLCAuLi5wYXJhbXMsIGZhdGFsOiBfZmF0YWwgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghcikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IGNsZWFuUGFyYW1zKF9wYXJhbXMsIGRhdGEpO1xuICAgICAgICAgICAgICAgIGNvbnN0IF9mYXRhbCA9IHBhcmFtcy5mYXRhbCA/PyBmYXRhbCA/PyB0cnVlO1xuICAgICAgICAgICAgICAgIGN0eC5hZGRJc3N1ZSh7IGNvZGU6IFwiY3VzdG9tXCIsIC4uLnBhcmFtcywgZmF0YWw6IF9mYXRhbCB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSk7XG4gICAgcmV0dXJuIFpvZEFueS5jcmVhdGUoKTtcbn1cbmV4cG9ydCB7IFpvZFR5cGUgYXMgU2NoZW1hLCBab2RUeXBlIGFzIFpvZFNjaGVtYSB9O1xuZXhwb3J0IGNvbnN0IGxhdGUgPSB7XG4gICAgb2JqZWN0OiBab2RPYmplY3QubGF6eWNyZWF0ZSxcbn07XG5leHBvcnQgdmFyIFpvZEZpcnN0UGFydHlUeXBlS2luZDtcbihmdW5jdGlvbiAoWm9kRmlyc3RQYXJ0eVR5cGVLaW5kKSB7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kU3RyaW5nXCJdID0gXCJab2RTdHJpbmdcIjtcbiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmRbXCJab2ROdW1iZXJcIl0gPSBcIlpvZE51bWJlclwiO1xuICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZFtcIlpvZE5hTlwiXSA9IFwiWm9kTmFOXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kQmlnSW50XCJdID0gXCJab2RCaWdJbnRcIjtcbiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmRbXCJab2RCb29sZWFuXCJdID0gXCJab2RCb29sZWFuXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kRGF0ZVwiXSA9IFwiWm9kRGF0ZVwiO1xuICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZFtcIlpvZFN5bWJvbFwiXSA9IFwiWm9kU3ltYm9sXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kVW5kZWZpbmVkXCJdID0gXCJab2RVbmRlZmluZWRcIjtcbiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmRbXCJab2ROdWxsXCJdID0gXCJab2ROdWxsXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kQW55XCJdID0gXCJab2RBbnlcIjtcbiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmRbXCJab2RVbmtub3duXCJdID0gXCJab2RVbmtub3duXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kTmV2ZXJcIl0gPSBcIlpvZE5ldmVyXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kVm9pZFwiXSA9IFwiWm9kVm9pZFwiO1xuICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZFtcIlpvZEFycmF5XCJdID0gXCJab2RBcnJheVwiO1xuICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZFtcIlpvZE9iamVjdFwiXSA9IFwiWm9kT2JqZWN0XCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kVW5pb25cIl0gPSBcIlpvZFVuaW9uXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kRGlzY3JpbWluYXRlZFVuaW9uXCJdID0gXCJab2REaXNjcmltaW5hdGVkVW5pb25cIjtcbiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmRbXCJab2RJbnRlcnNlY3Rpb25cIl0gPSBcIlpvZEludGVyc2VjdGlvblwiO1xuICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZFtcIlpvZFR1cGxlXCJdID0gXCJab2RUdXBsZVwiO1xuICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZFtcIlpvZFJlY29yZFwiXSA9IFwiWm9kUmVjb3JkXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kTWFwXCJdID0gXCJab2RNYXBcIjtcbiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmRbXCJab2RTZXRcIl0gPSBcIlpvZFNldFwiO1xuICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZFtcIlpvZEZ1bmN0aW9uXCJdID0gXCJab2RGdW5jdGlvblwiO1xuICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZFtcIlpvZExhenlcIl0gPSBcIlpvZExhenlcIjtcbiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmRbXCJab2RMaXRlcmFsXCJdID0gXCJab2RMaXRlcmFsXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kRW51bVwiXSA9IFwiWm9kRW51bVwiO1xuICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZFtcIlpvZEVmZmVjdHNcIl0gPSBcIlpvZEVmZmVjdHNcIjtcbiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmRbXCJab2ROYXRpdmVFbnVtXCJdID0gXCJab2ROYXRpdmVFbnVtXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kT3B0aW9uYWxcIl0gPSBcIlpvZE9wdGlvbmFsXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kTnVsbGFibGVcIl0gPSBcIlpvZE51bGxhYmxlXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kRGVmYXVsdFwiXSA9IFwiWm9kRGVmYXVsdFwiO1xuICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZFtcIlpvZENhdGNoXCJdID0gXCJab2RDYXRjaFwiO1xuICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZFtcIlpvZFByb21pc2VcIl0gPSBcIlpvZFByb21pc2VcIjtcbiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmRbXCJab2RCcmFuZGVkXCJdID0gXCJab2RCcmFuZGVkXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kUGlwZWxpbmVcIl0gPSBcIlpvZFBpcGVsaW5lXCI7XG4gICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kW1wiWm9kUmVhZG9ubHlcIl0gPSBcIlpvZFJlYWRvbmx5XCI7XG59KShab2RGaXJzdFBhcnR5VHlwZUtpbmQgfHwgKFpvZEZpcnN0UGFydHlUeXBlS2luZCA9IHt9KSk7XG4vLyByZXF1aXJlcyBUUyA0LjQrXG5jbGFzcyBDbGFzcyB7XG4gICAgY29uc3RydWN0b3IoLi4uXykgeyB9XG59XG5jb25zdCBpbnN0YW5jZU9mVHlwZSA9IChcbi8vIGNvbnN0IGluc3RhbmNlT2ZUeXBlID0gPFQgZXh0ZW5kcyBuZXcgKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnk+KFxuY2xzLCBwYXJhbXMgPSB7XG4gICAgbWVzc2FnZTogYElucHV0IG5vdCBpbnN0YW5jZSBvZiAke2Nscy5uYW1lfWAsXG59KSA9PiBjdXN0b20oKGRhdGEpID0+IGRhdGEgaW5zdGFuY2VvZiBjbHMsIHBhcmFtcyk7XG5jb25zdCBzdHJpbmdUeXBlID0gWm9kU3RyaW5nLmNyZWF0ZTtcbmNvbnN0IG51bWJlclR5cGUgPSBab2ROdW1iZXIuY3JlYXRlO1xuY29uc3QgbmFuVHlwZSA9IFpvZE5hTi5jcmVhdGU7XG5jb25zdCBiaWdJbnRUeXBlID0gWm9kQmlnSW50LmNyZWF0ZTtcbmNvbnN0IGJvb2xlYW5UeXBlID0gWm9kQm9vbGVhbi5jcmVhdGU7XG5jb25zdCBkYXRlVHlwZSA9IFpvZERhdGUuY3JlYXRlO1xuY29uc3Qgc3ltYm9sVHlwZSA9IFpvZFN5bWJvbC5jcmVhdGU7XG5jb25zdCB1bmRlZmluZWRUeXBlID0gWm9kVW5kZWZpbmVkLmNyZWF0ZTtcbmNvbnN0IG51bGxUeXBlID0gWm9kTnVsbC5jcmVhdGU7XG5jb25zdCBhbnlUeXBlID0gWm9kQW55LmNyZWF0ZTtcbmNvbnN0IHVua25vd25UeXBlID0gWm9kVW5rbm93bi5jcmVhdGU7XG5jb25zdCBuZXZlclR5cGUgPSBab2ROZXZlci5jcmVhdGU7XG5jb25zdCB2b2lkVHlwZSA9IFpvZFZvaWQuY3JlYXRlO1xuY29uc3QgYXJyYXlUeXBlID0gWm9kQXJyYXkuY3JlYXRlO1xuY29uc3Qgb2JqZWN0VHlwZSA9IFpvZE9iamVjdC5jcmVhdGU7XG5jb25zdCBzdHJpY3RPYmplY3RUeXBlID0gWm9kT2JqZWN0LnN0cmljdENyZWF0ZTtcbmNvbnN0IHVuaW9uVHlwZSA9IFpvZFVuaW9uLmNyZWF0ZTtcbmNvbnN0IGRpc2NyaW1pbmF0ZWRVbmlvblR5cGUgPSBab2REaXNjcmltaW5hdGVkVW5pb24uY3JlYXRlO1xuY29uc3QgaW50ZXJzZWN0aW9uVHlwZSA9IFpvZEludGVyc2VjdGlvbi5jcmVhdGU7XG5jb25zdCB0dXBsZVR5cGUgPSBab2RUdXBsZS5jcmVhdGU7XG5jb25zdCByZWNvcmRUeXBlID0gWm9kUmVjb3JkLmNyZWF0ZTtcbmNvbnN0IG1hcFR5cGUgPSBab2RNYXAuY3JlYXRlO1xuY29uc3Qgc2V0VHlwZSA9IFpvZFNldC5jcmVhdGU7XG5jb25zdCBmdW5jdGlvblR5cGUgPSBab2RGdW5jdGlvbi5jcmVhdGU7XG5jb25zdCBsYXp5VHlwZSA9IFpvZExhenkuY3JlYXRlO1xuY29uc3QgbGl0ZXJhbFR5cGUgPSBab2RMaXRlcmFsLmNyZWF0ZTtcbmNvbnN0IGVudW1UeXBlID0gWm9kRW51bS5jcmVhdGU7XG5jb25zdCBuYXRpdmVFbnVtVHlwZSA9IFpvZE5hdGl2ZUVudW0uY3JlYXRlO1xuY29uc3QgcHJvbWlzZVR5cGUgPSBab2RQcm9taXNlLmNyZWF0ZTtcbmNvbnN0IGVmZmVjdHNUeXBlID0gWm9kRWZmZWN0cy5jcmVhdGU7XG5jb25zdCBvcHRpb25hbFR5cGUgPSBab2RPcHRpb25hbC5jcmVhdGU7XG5jb25zdCBudWxsYWJsZVR5cGUgPSBab2ROdWxsYWJsZS5jcmVhdGU7XG5jb25zdCBwcmVwcm9jZXNzVHlwZSA9IFpvZEVmZmVjdHMuY3JlYXRlV2l0aFByZXByb2Nlc3M7XG5jb25zdCBwaXBlbGluZVR5cGUgPSBab2RQaXBlbGluZS5jcmVhdGU7XG5jb25zdCBvc3RyaW5nID0gKCkgPT4gc3RyaW5nVHlwZSgpLm9wdGlvbmFsKCk7XG5jb25zdCBvbnVtYmVyID0gKCkgPT4gbnVtYmVyVHlwZSgpLm9wdGlvbmFsKCk7XG5jb25zdCBvYm9vbGVhbiA9ICgpID0+IGJvb2xlYW5UeXBlKCkub3B0aW9uYWwoKTtcbmV4cG9ydCBjb25zdCBjb2VyY2UgPSB7XG4gICAgc3RyaW5nOiAoKGFyZykgPT4gWm9kU3RyaW5nLmNyZWF0ZSh7IC4uLmFyZywgY29lcmNlOiB0cnVlIH0pKSxcbiAgICBudW1iZXI6ICgoYXJnKSA9PiBab2ROdW1iZXIuY3JlYXRlKHsgLi4uYXJnLCBjb2VyY2U6IHRydWUgfSkpLFxuICAgIGJvb2xlYW46ICgoYXJnKSA9PiBab2RCb29sZWFuLmNyZWF0ZSh7XG4gICAgICAgIC4uLmFyZyxcbiAgICAgICAgY29lcmNlOiB0cnVlLFxuICAgIH0pKSxcbiAgICBiaWdpbnQ6ICgoYXJnKSA9PiBab2RCaWdJbnQuY3JlYXRlKHsgLi4uYXJnLCBjb2VyY2U6IHRydWUgfSkpLFxuICAgIGRhdGU6ICgoYXJnKSA9PiBab2REYXRlLmNyZWF0ZSh7IC4uLmFyZywgY29lcmNlOiB0cnVlIH0pKSxcbn07XG5leHBvcnQgeyBhbnlUeXBlIGFzIGFueSwgYXJyYXlUeXBlIGFzIGFycmF5LCBiaWdJbnRUeXBlIGFzIGJpZ2ludCwgYm9vbGVhblR5cGUgYXMgYm9vbGVhbiwgZGF0ZVR5cGUgYXMgZGF0ZSwgZGlzY3JpbWluYXRlZFVuaW9uVHlwZSBhcyBkaXNjcmltaW5hdGVkVW5pb24sIGVmZmVjdHNUeXBlIGFzIGVmZmVjdCwgZW51bVR5cGUgYXMgZW51bSwgZnVuY3Rpb25UeXBlIGFzIGZ1bmN0aW9uLCBpbnN0YW5jZU9mVHlwZSBhcyBpbnN0YW5jZW9mLCBpbnRlcnNlY3Rpb25UeXBlIGFzIGludGVyc2VjdGlvbiwgbGF6eVR5cGUgYXMgbGF6eSwgbGl0ZXJhbFR5cGUgYXMgbGl0ZXJhbCwgbWFwVHlwZSBhcyBtYXAsIG5hblR5cGUgYXMgbmFuLCBuYXRpdmVFbnVtVHlwZSBhcyBuYXRpdmVFbnVtLCBuZXZlclR5cGUgYXMgbmV2ZXIsIG51bGxUeXBlIGFzIG51bGwsIG51bGxhYmxlVHlwZSBhcyBudWxsYWJsZSwgbnVtYmVyVHlwZSBhcyBudW1iZXIsIG9iamVjdFR5cGUgYXMgb2JqZWN0LCBvYm9vbGVhbiwgb251bWJlciwgb3B0aW9uYWxUeXBlIGFzIG9wdGlvbmFsLCBvc3RyaW5nLCBwaXBlbGluZVR5cGUgYXMgcGlwZWxpbmUsIHByZXByb2Nlc3NUeXBlIGFzIHByZXByb2Nlc3MsIHByb21pc2VUeXBlIGFzIHByb21pc2UsIHJlY29yZFR5cGUgYXMgcmVjb3JkLCBzZXRUeXBlIGFzIHNldCwgc3RyaWN0T2JqZWN0VHlwZSBhcyBzdHJpY3RPYmplY3QsIHN0cmluZ1R5cGUgYXMgc3RyaW5nLCBzeW1ib2xUeXBlIGFzIHN5bWJvbCwgZWZmZWN0c1R5cGUgYXMgdHJhbnNmb3JtZXIsIHR1cGxlVHlwZSBhcyB0dXBsZSwgdW5kZWZpbmVkVHlwZSBhcyB1bmRlZmluZWQsIHVuaW9uVHlwZSBhcyB1bmlvbiwgdW5rbm93blR5cGUgYXMgdW5rbm93biwgdm9pZFR5cGUgYXMgdm9pZCwgfTtcbmV4cG9ydCBjb25zdCBORVZFUiA9IElOVkFMSUQ7XG4iLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCAiZXhwb3J0IHsgbGlzdEFnZW50cyB9IGZyb20gJy4vbGlzdC1hZ2VudHMubWpzJztcbmV4cG9ydCB7IGdldEFnZW50IH0gZnJvbSAnLi9nZXQtYWdlbnQubWpzJztcbmV4cG9ydCB7IGxpc3RQcmltaXRpdmVWZXJzaW9ucyB9IGZyb20gJy4vbGlzdC1wcmltaXRpdmUtdmVyc2lvbnMubWpzJztcbmV4cG9ydCB7IGdldERlcGxveW1lbnRTdGF0dXMgfSBmcm9tICcuL2dldC1kZXBsb3ltZW50LXN0YXR1cy5tanMnO1xuZXhwb3J0IHsgdGFpbExvZ3MgfSBmcm9tICcuL3RhaWwtbG9ncy5tanMnO1xuLy8gY2hlY2tfZHJpZnQgcmVtb3ZlZCBpbiB2MS4yNSBcdTIwMTQgdXNlIEJhc2gobHVhIHN5bmMgLS1jaGVjaykgZGlyZWN0bHkuIFRoZVxuLy8gTUNQIHNlcnZlciBpcyBsb2NhbCBhbmQgc28gaXMgdGhlIENMSTsgcmVpbXBsZW1lbnRpbmcgZHJpZnQgZGV0ZWN0aW9uXG4vLyBzZXJ2ZXItc2lkZSBvciBpbiB0aGUgTUNQIHdvdWxkIGR1cGxpY2F0ZSBsb2dpYyB0aGF0IGx1YS1jbGkgYWxyZWFkeSBvd25zLlxuIiwgIi8vIFNoYXJlZCBzdWJwcm9jZXNzIGhlbHBlciBmb3IgdG9vbHMgdGhhdCBzaGVsbCBvdXQgdG8gdGhlIGx1YS1jbGkgYmluYXJ5LlxuLy9cbi8vIFdoeSBzaGVsbCBvdXQgYXQgYWxsOiB0aGVyZSBpcyBubyBcImxpc3QgZXZlcnkgYWdlbnQgdGhpcyBjcmVkZW50aWFsIGNhblxuLy8gcmVhY2hcIiBSRVNUIHJvdXRlIFx1MjAxNCBgbHVhIGFnZW50cyAtLWpzb25gIGFscmVhZHkgZG9lcyB0aGUgY3JlZGVudGlhbC10by1cbi8vIGF1dGhvcml6YXRpb24tcHJvamVjdGlvbiByZXNvbHV0aW9uIChQUk8tMTcxMikgZm9yIGV2ZXJ5IGNyZWRlbnRpYWwgY2xhc3Ncbi8vIChBUEkga2V5LCB0eXBlZCBzY29wZWQga2V5LCByZW5ld2FibGUgc2Vzc2lvbikuIFJlaW1wbGVtZW50aW5nIHRoYXQgaW4gdGhlXG4vLyBNQ1Agd291bGQgZHVwbGljYXRlIGxvZ2ljIGx1YS1jbGkgb3ducy5cblxuaW1wb3J0IHsgc3Bhd24gfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnO1xuXG4vLyBgbHVhIGFnZW50c2Agd2Fsa3MgZXZlcnkgb3JnYW5pc2F0aW9uIHRoZSBjcmVkZW50aWFsIGNhbiBzZWUgYW5kLCBmb3IgYVxuLy8gc2Vzc2lvbiBsb2dpbiwgcmVmcmVzaGVzIHRoZSBzZXNzaW9uIGZpcnN0LiBNZWFzdXJlZCAyMDI2LTA5LTEyIG9uIGFcbi8vIDE0NC1vcmcgYWNjb3VudDogMThcdTIwMTMyNSBzLiBUaGUgYnVkZ2V0IG11c3QgY292ZXIgdGhhdC5cbmNvbnN0IERFRkFVTFRfVElNRU9VVF9NUyA9IDYwXzAwMDtcblxuLyoqXG4gKiBSdW4gYGx1YSA8YXJncz5gIGFuZCByZXNvbHZlIHdpdGggaXRzIHN0ZG91dC5cbiAqXG4gKiBPbiBXaW5kb3dzIHRoZSBucG0gYmluIGlzIGEgYGx1YS5jbWRgIHNoaW0sIHdoaWNoIE5vZGUgKFx1MjI2NTE4LjIwIC8gXHUyMjY1MjAuMTIpXG4gKiByZWZ1c2VzIHRvIHNwYXduIHdpdGhvdXQgYSBzaGVsbDsgdGhlIGFyZ3MgYXJlIGZpeGVkIGxpdGVyYWxzIChubyB1c2VyXG4gKiBpbnB1dCksIHNvIGBzaGVsbDogdHJ1ZWAgdGhlcmUgaXMgc2FmZS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBhcmdzXG4gKiBAcGFyYW0ge3tzcGF3bkZuPzogdHlwZW9mIHNwYXduLCB0aW1lb3V0TXM/OiBudW1iZXIsIGxhYmVsPzogc3RyaW5nfX0gW29wdHNdXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuTHVhKGFyZ3MsIHsgc3Bhd25GbiA9IHNwYXduLCB0aW1lb3V0TXMgPSBERUZBVUxUX1RJTUVPVVRfTVMsIGxhYmVsID0gJ2x1YScgfSA9IHt9KSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgY2hpbGQgPSBzcGF3bkZuKCdsdWEnLCBhcmdzLCB7XG4gICAgICBzaGVsbDogcHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJyxcbiAgICAgIHdpbmRvd3NIaWRlOiB0cnVlLFxuICAgICAgZW52OiB7IC4uLnByb2Nlc3MuZW52LCBMVUFfTk9fQkFOTkVSOiAnMScsIExVQV9OT19ISU5UUzogJzEnIH0sXG4gICAgfSk7XG4gICAgbGV0IHN0ZG91dCA9ICcnO1xuICAgIGxldCBzdGRlcnIgPSAnJztcbiAgICBjaGlsZC5zdGRvdXQub24oJ2RhdGEnLCAoZCkgPT4geyBzdGRvdXQgKz0gZC50b1N0cmluZygndXRmOCcpOyB9KTtcbiAgICBjaGlsZC5zdGRlcnIub24oJ2RhdGEnLCAoZCkgPT4geyBzdGRlcnIgKz0gZC50b1N0cmluZygndXRmOCcpOyB9KTtcblxuICAgIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBjaGlsZC5raWxsKCdTSUdURVJNJyk7XG4gICAgICByZWplY3QobmV3IEVycm9yKGAke2xhYmVsfTogJ2x1YSAke2FyZ3Muam9pbignICcpfScgdGltZWQgb3V0IGFmdGVyICR7dGltZW91dE1zfW1zYCkpO1xuICAgIH0sIHRpbWVvdXRNcyk7XG5cbiAgICBjaGlsZC5vbignZXhpdCcsIChjb2RlKSA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgaWYgKGNvZGUgIT09IDApIHJlamVjdChuZXcgRXJyb3IoYCdsdWEgJHthcmdzLmpvaW4oJyAnKX0nIGV4aXRlZCAke2NvZGV9OiAke3N0ZGVyci50cmltKCl9YCkpO1xuICAgICAgZWxzZSByZXNvbHZlKHN0ZG91dCk7XG4gICAgfSk7XG4gICAgY2hpbGQub24oJ2Vycm9yJywgKGVycikgPT4ge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIHJlamVjdChlcnIpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuLyoqXG4gKiBGbGF0dGVuIGBsdWEgYWdlbnRzIC0tanNvbmAgb3V0cHV0IChsdWEtY2xpIFx1MjI2NSAzLjI4OiBhbiBhcnJheSBvZlxuICogQ3JlZGVudGlhbE9yZ2FuaXphdGlvbiByb3dzIFx1MjAxNCBgeyBvcmdJZCwgbmFtZT8sIGFyY2hpdmVkLCBkaXNjb3ZlcmVkVmlhLFxuICogYWdlbnRzOiBbeyBhZ2VudElkLCBuYW1lPywgdmlzaWJpbGl0eSwgZGlzcGxheVJvbGVzIH1dIH1gLCBzZWVcbiAqIHBhY2thZ2VzL2x1YS1jbGkvc3JjL3NlcnZpY2VzL2NyZWRlbnRpYWwtb3BlcmF0aW9uYWwtY29udGV4dC50cykgaW50byBhXG4gKiBjb21wYWN0IGFnZW50IGxpc3QuIE9sZGVyIGZsYXQgc2hhcGVzIGFyZSB0b2xlcmF0ZWQgZm9yIGZvcndhcmQtY29tcGF0LlxuICpcbiAqIEBwYXJhbSB7dW5rbm93bn0gcGFyc2VkXG4gKiBAcmV0dXJucyB7QXJyYXk8e2lkOiBzdHJpbmcsIG5hbWU6IHN0cmluZ3xudWxsLCBvcmdJZDogc3RyaW5nfG51bGwsIG9yZ05hbWU6IHN0cmluZ3xudWxsLCB2aXNpYmlsaXR5OiBzdHJpbmd8bnVsbH0+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gZmxhdHRlbkFnZW50cyhwYXJzZWQpIHtcbiAgY29uc3Qgb2JqID0gLyoqIEB0eXBlIHthbnl9ICovIChwYXJzZWQpO1xuICBjb25zdCBlbnRyaWVzID0gQXJyYXkuaXNBcnJheShvYmopID8gb2JqIDogKG9iaj8uYWdlbnRzID8/IG9iaj8ub3JncyA/PyBbXSk7XG4gIGNvbnN0IGxvb2tzTGlrZU9yZ3MgPSBlbnRyaWVzLmxlbmd0aCA+IDAgJiYgZW50cmllc1swXSAmJiBBcnJheS5pc0FycmF5KGVudHJpZXNbMF0uYWdlbnRzKTtcblxuICBpZiAobG9va3NMaWtlT3Jncykge1xuICAgIHJldHVybiBlbnRyaWVzLmZsYXRNYXAoKG9yZykgPT4gKG9yZy5hZ2VudHMgPz8gW10pLm1hcCgoYSkgPT4gKHtcbiAgICAgIGlkOiBhLmFnZW50SWQgPz8gYS5pZCA/PyBhLl9pZCxcbiAgICAgIG5hbWU6IGEubmFtZSA/PyBudWxsLFxuICAgICAgb3JnSWQ6IG9yZy5vcmdJZCA/PyBvcmcuaWQgPz8gb3JnLl9pZCA/PyBudWxsLFxuICAgICAgb3JnTmFtZTogb3JnLm5hbWUgPz8gb3JnLnJlZ2lzdGVyZWROYW1lID8/IG51bGwsXG4gICAgICB2aXNpYmlsaXR5OiBhLnZpc2liaWxpdHkgPz8gbnVsbCxcbiAgICB9KSkpO1xuICB9XG4gIHJldHVybiBlbnRyaWVzLm1hcCgoYSkgPT4gKHtcbiAgICBpZDogYS5hZ2VudElkID8/IGEuaWQgPz8gYS5faWQsXG4gICAgbmFtZTogYS5uYW1lID8/IG51bGwsXG4gICAgb3JnSWQ6IGEub3JnSWQgPz8gbnVsbCxcbiAgICBvcmdOYW1lOiBhLm9yZ05hbWUgPz8gbnVsbCxcbiAgICB2aXNpYmlsaXR5OiBhLnZpc2liaWxpdHkgPz8gbnVsbCxcbiAgfSkpO1xufVxuXG4vKipcbiAqIFJ1biBgbHVhIGFnZW50cyAtLWpzb24gLS1jaWAgYW5kIHJldHVybiB0aGUgZmxhdHRlbmVkIGFnZW50IGxpc3QuXG4gKlxuICogQHBhcmFtIHt7c3Bhd25Gbj86IHR5cGVvZiBzcGF3biwgbGFiZWw/OiBzdHJpbmd9fSBbb3B0c11cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxpc3RBZ2VudHNWaWFDbGkoeyBzcGF3bkZuLCBsYWJlbCA9ICdsaXN0X2FnZW50cycgfSA9IHt9KSB7XG4gIGNvbnN0IHN0ZG91dCA9IGF3YWl0IHJ1bkx1YShbJ2FnZW50cycsICctLWpzb24nLCAnLS1jaSddLCB7IHNwYXduRm4sIGxhYmVsIH0pO1xuICBsZXQgcGFyc2VkO1xuICB0cnkge1xuICAgIHBhcnNlZCA9IEpTT04ucGFyc2Uoc3Rkb3V0KTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke2xhYmVsfTogY291bGQgbm90IHBhcnNlICdsdWEgYWdlbnRzIC0tanNvbicgb3V0cHV0OiAke2Vyci5tZXNzYWdlfWApO1xuICB9XG4gIHJldHVybiBmbGF0dGVuQWdlbnRzKHBhcnNlZCk7XG59XG4iLCAiaW1wb3J0IHsgbGlzdEFnZW50c1ZpYUNsaSB9IGZyb20gJy4uL3J1bi1sdWEubWpzJztcblxuLy8gU2hlbGxzIG91dCB0byBgbHVhIGFnZW50cyAtLWpzb24gLS1jaWAgKHNlZSBydW4tbHVhLm1qcyBmb3Igd2h5KS4gVGhlIENMSVxuLy8gZW1pdHMgb25lIHJvdyBwZXIgb3JnYW5pc2F0aW9uIHdpdGggYSBuZXN0ZWQgYGFnZW50c2AgYXJyYXk7IHdlIGZsYXR0ZW4uXG5cbmV4cG9ydCBjb25zdCBsaXN0QWdlbnRzID0ge1xuICBzcGVjOiB7XG4gICAgbmFtZTogJ2xpc3RfYWdlbnRzJyxcbiAgICBkZXNjcmlwdGlvbjogJ0xpc3QgYWxsIEx1YSBhZ2VudHMgdGhlIGF1dGhlbnRpY2F0ZWQgY3JlZGVudGlhbCBjYW4gcmVhY2guIFJldHVybnMgYSBjb21wYWN0IGFycmF5IG9mIHtpZCwgbmFtZSwgb3JnSWQsIG9yZ05hbWUsIHZpc2liaWxpdHl9IGZsYXR0ZW5lZCBhY3Jvc3MgYWxsIG9yZ2FuaXNhdGlvbnMuIFNhbWUgZGF0YSBhcyBgbHVhIGFnZW50cyAtLWpzb25gIFx1MjAxNCBpdCByZXNvbHZlcyBldmVyeSBvcmdhbmlzYXRpb24sIHNvIG9uIGFjY291bnRzIHdpdGggbWFueSBvcmdzIHRoaXMgdGFrZXMgMjAgcyBvciBtb3JlOyBwcmVmZXIgZ2V0X2FnZW50IHdoZW4geW91IGFscmVhZHkga25vdyB0aGUgaWQuJyxcbiAgICBpbnB1dFNjaGVtYToge1xuICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICBwcm9wZXJ0aWVzOiB7fSxcbiAgICAgIHJlcXVpcmVkOiBbXSxcbiAgICB9LFxuICB9LFxuICBhc3luYyBoYW5kbGVyKF9hcmdzLCBkZXBzID0ge30pIHtcbiAgICBjb25zdCBjb21wYWN0ID0gYXdhaXQgbGlzdEFnZW50c1ZpYUNsaSh7IHNwYXduRm46IGRlcHMuc3Bhd25GbiwgbGFiZWw6ICdsaXN0X2FnZW50cycgfSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IFt7IHR5cGU6ICd0ZXh0JywgdGV4dDogSlNPTi5zdHJpbmdpZnkoY29tcGFjdCwgbnVsbCwgMikgfV0sXG4gICAgfTtcbiAgfSxcbn07XG4iLCAiaW1wb3J0IHsgbGlzdEFnZW50c1ZpYUNsaSB9IGZyb20gJy4uL3J1bi1sdWEubWpzJztcblxuLy8gVGhlcmUgaXMgbm8gY29uc29saWRhdGVkIGBHRVQgL2RldmVsb3Blci9hZ2VudHMvOmFnZW50SWRgIHJvdXRlLCBhbmQgdGhlXG4vLyBwdWJsaWMgYC9wdWJsaWMvYWdlbnRzLzphZ2VudElkYCByb3V0ZSBpcyBvcmlnaW4tZ3VhcmRlZCAoYnJvd3NlciBvbmx5KS5cbi8vIFRoZSBhZ2VudCdzIGlkZW50aXR5IChpZCwgbmFtZSwgb3JnLCB2aXNpYmlsaXR5KSBJUyBpbiBgbHVhIGFnZW50cyAtLWpzb25gLFxuLy8gc28gd2Ugc2hlbGwgb3V0IGFuZCBmaWx0ZXIgXHUyMDE0IHNhbWUgcGF0aCBhcyBsaXN0X2FnZW50cy4gUGVyc29uYSwgbW9kZWwgYW5kXG4vLyBlbnYgbGl2ZSBiZWhpbmQgc2VwYXJhdGUgcGVyLXJlc291cmNlIHJvdXRlczsgdXNlIHRoZSBkZWRpY2F0ZWQgdG9vbHMgKG9yXG4vLyBgbHVhIHN0YXR1cyAtLWpzb25gIGluc2lkZSB0aGUgcHJvamVjdCkgZm9yIHRob3NlLlxuXG5leHBvcnQgY29uc3QgZ2V0QWdlbnQgPSB7XG4gIHNwZWM6IHtcbiAgICBuYW1lOiAnZ2V0X2FnZW50JyxcbiAgICBkZXNjcmlwdGlvbjogJ0xvb2sgdXAgb25lIEx1YSBhZ2VudCBieSBJRCBhbmQgcmV0dXJuIHtpZCwgbmFtZSwgb3JnSWQsIG9yZ05hbWUsIHZpc2liaWxpdHl9LiBGb3Igd2hhdCBpcyBsaXZlIHVzZSBnZXRfZGVwbG95bWVudF9zdGF0dXMgLyBsaXN0X3ByaW1pdGl2ZV92ZXJzaW9uczsgZm9yIGxvZ3MgdXNlIHRhaWxfbG9ncy4nLFxuICAgIGlucHV0U2NoZW1hOiB7XG4gICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgYWdlbnRJZDogeyB0eXBlOiAnc3RyaW5nJywgZGVzY3JpcHRpb246ICdBZ2VudCBJRCAodGhlIGBpZGAgZmllbGQgZnJvbSBsaXN0X2FnZW50czsgYWxzbyBgYWdlbnQuYWdlbnRJZGAgaW4gbHVhLnNraWxsLnlhbWwpJyB9LFxuICAgICAgfSxcbiAgICAgIHJlcXVpcmVkOiBbJ2FnZW50SWQnXSxcbiAgICB9LFxuICB9LFxuICBhc3luYyBoYW5kbGVyKHsgYWdlbnRJZCB9LCBkZXBzID0ge30pIHtcbiAgICBpZiAoIWFnZW50SWQpIHRocm93IG5ldyBFcnJvcignYWdlbnRJZCBpcyByZXF1aXJlZCcpO1xuICAgIGNvbnN0IGFnZW50cyA9IGF3YWl0IGxpc3RBZ2VudHNWaWFDbGkoeyBzcGF3bkZuOiBkZXBzLnNwYXduRm4sIGxhYmVsOiAnZ2V0X2FnZW50JyB9KTtcbiAgICBjb25zdCBtYXRjaCA9IGFnZW50cy5maW5kKChhKSA9PiBhLmlkID09PSBhZ2VudElkKSA/PyBudWxsO1xuXG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBnZXRfYWdlbnQ6IG5vIGFnZW50IHdpdGggaWQgXCIke2FnZW50SWR9XCIgZm91bmQgaW4gdGhlIGF1dGhlbnRpY2F0ZWQgY3JlZGVudGlhbCdzIGFjY2Vzc2libGUgb3Jncy4gUnVuIGxpc3RfYWdlbnRzIHRvIHNlZSBhdmFpbGFibGUgYWdlbnRzLmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbeyB0eXBlOiAndGV4dCcsIHRleHQ6IEpTT04uc3RyaW5naWZ5KG1hdGNoLCBudWxsLCAyKSB9XSxcbiAgICB9O1xuICB9LFxufTtcbiIsICIvLyBDcmVkZW50aWFsIHJlc29sdXRpb24gZm9yIHRoZSBNQ1Agc2VydmVyLiBSZXNvbHZlZCBvbiBFVkVSWSBjYWxsLCBub3QgYXRcbi8vIHNlcnZlciBzdGFydHVwIFx1MjAxNCBzdXBwb3J0cyB0aGUgZmxvdyB3aGVyZSBhIHVzZXIgcmUtcnVucyBgbHVhIGF1dGggY29uZmlndXJlYFxuLy8gbWlkLXNlc3Npb24uXG4vL1xuLy8gVGhlIGNoYWluIE1VU1QgbWF0Y2ggbHVhLWNsaSdzIGByZXNvbHZlUmVxdWVzdENyZWRlbnRpYWwoKWBcbi8vIChwYWNrYWdlcy9sdWEtY2xpL3NyYy9zZXJ2aWNlcy9yZXF1ZXN0LWNyZWRlbnRpYWwudHMsIGx1YS1jbGkgMy4zMy4wKTpcbi8vXG4vLyAgIDEuIExVQV9BUElfS0VZIGluIHRoZSBwcm9jZXNzIGVudmlyb25tZW50LiBsdWEtY2xpIGxvYWRzIGAuLy5lbnZgIGludG9cbi8vICAgICAgcHJvY2Vzcy5lbnYgZmlyc3QgKGBpbXBvcnQgJ2RvdGVudi9jb25maWcnYCksIHNvIGEgYC5lbnZgIHZhbHVlIGluIHRoZVxuLy8gICAgICB3b3JraW5nIGRpcmVjdG9yeSBpcyBwYXJ0IG9mIHRoaXMgdGllciBcdTIwMTQgaXQgYmVhdHMgYSBzdG9yZWQgc2Vzc2lvbi5cbi8vICAgMi4gVGhlIHJlbmV3YWJsZSBmaXJzdC1wYXJ0eSBzZXNzaW9uIGBsdWEgYXV0aCBjb25maWd1cmVgIChlbWFpbCArIE9UUClcbi8vICAgICAgd3JpdGVzIHRvIH4vLmx1YS1jbGkvc2Vzc2lvbnMvPGVudi1oYXNoPi5qc29uLiBUaGlzIGlzIHRoZSBERUZBVUxUXG4vLyAgICAgIGxvZ2luIHNpbmNlIGx1YS1jbGkgMy4yOSBhbmQgaXQgREVMRVRFUyB+Ly5sdWEtY2xpL2NyZWRlbnRpYWxzLCBzbyBhblxuLy8gICAgICBNQ1Agc2VydmVyIHRoYXQgb25seSByZWFkIHRoZSBjcmVkZW50aWFscyBmaWxlIGZhaWxlZCBmb3IgZXZlcnlcbi8vICAgICAgc2Vzc2lvbiB1c2VyLiBUaGUgZmlsZSBob2xkcyBhIEZpcmViYXNlIHJlZnJlc2ggdG9rZW47IHRoZSBiZWFyZXIgaXNcbi8vICAgICAgYSBzaG9ydC1saXZlZCBJRCB0b2tlbiBvYnRhaW5lZCBmcm9tIEdvb2dsZSdzIHNlY3VyZXRva2VuIGVuZHBvaW50LlxuLy8gICAzLiB+Ly5sdWEtY2xpL2NyZWRlbnRpYWxzIFx1MjAxNCBhIHBsYWluLXRleHQgQVBJIGtleSAodHlwZWQgYGFwaV88dXVpZD4uPDQzPmBcbi8vICAgICAgb3IgbGVnYWN5KSwgd3JpdHRlbiB3aGVuIHRoZSB1c2VyIHBpY2tzIHRoZSBBUEkta2V5IG9wdGlvbiBvZlxuLy8gICAgICBgbHVhIGF1dGggY29uZmlndXJlYC5cbi8vXG4vLyBUaGlzIGZpbGUgZGVsaWJlcmF0ZWx5IGR1cGxpY2F0ZXMgbGliL2NyZWRlbnRpYWxzLm1qcyBiZWNhdXNlIHRoZSBNQ1Bcbi8vIHNlcnZlciBpcyBhIHNlcGFyYXRlIG5wbSBwYWNrYWdlIGFuZCBjYW4ndCByZWFjaCBpbnRvIHRoZSBwbHVnaW4ncyBsaWIvLlxuXG5pbXBvcnQgeyByZWFkRmlsZSwgcmVhZGRpciwgc3RhdCB9IGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnO1xuaW1wb3J0IHsgam9pbiwgZGlybmFtZSB9IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBob21lZGlyIH0gZnJvbSAnbm9kZTpvcyc7XG5cbmNvbnN0IERFRkFVTFRfQVBJX1VSTCA9ICdodHRwczovL2FwaS5oZXlsdWEuYWknO1xuY29uc3QgRklSRUJBU0VfUkVGUkVTSF9VUkwgPSAnaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGVhcGlzLmNvbS92MS90b2tlbic7XG5jb25zdCBSRUZSRVNIX1RJTUVPVVRfTVMgPSAxNV8wMDA7XG5jb25zdCBSRUZSRVNIX1NLRVdfTVMgPSA2MF8wMDA7XG5cbi8vIEdvb2dsZSdzIHZlcmRpY3RzIHRoYXQgdGhlIHN0b3JlZCByZWZyZXNoIHRva2VuIGNhbiBuZXZlciB3b3JrIGFnYWluLlxuLy8gTWlycm9ycyBsdWEtY2xpJ3MgUkVKRUNURURfUkVGUkVTSF9SRUFTT05TIChzZXJ2aWNlcy9maXJlYmFzZS1zZXNzaW9uLnRzKS5cbmNvbnN0IFJFSkVDVEVEX1JFRlJFU0hfUkVBU09OUyA9IFtcbiAgJ1RPS0VOX0VYUElSRUQnLFxuICAnVVNFUl9ESVNBQkxFRCcsXG4gICdVU0VSX05PVF9GT1VORCcsXG4gICdJTlZBTElEX1JFRlJFU0hfVE9LRU4nLFxuICAnSU5WQUxJRF9HUkFOVF9UWVBFJyxcbiAgJ01JU1NJTkdfUkVGUkVTSF9UT0tFTicsXG5dO1xuXG4vLyBJbi1wcm9jZXNzIGNhY2hlIG9mIHJlZnJlc2hlZCBJRCB0b2tlbnMsIGtleWVkIGJ5IHNlc3Npb24gZmlsZSBwYXRoLlxuY29uc3QgdG9rZW5DYWNoZSA9IG5ldyBNYXAoKTtcblxuLyoqIEV4cG9ydGVkIGZvciB0ZXN0cy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGVhclRva2VuQ2FjaGUoKSB7XG4gIHRva2VuQ2FjaGUuY2xlYXIoKTtcbn1cblxuLyoqXG4gKiBQYXJzZSBhIGRvdGVudi1zdHlsZSBmaWxlIGZvciBMVUFfQVBJX0tFWSB0aGUgd2F5IGRvdGVudiBkb2VzOiBvcHRpb25hbFxuICogYGV4cG9ydCBgIHByZWZpeCwgc3Vycm91bmRpbmcgc2luZ2xlL2RvdWJsZSBxdW90ZXMgc3RyaXBwZWQsIGEgdHJhaWxpbmdcbiAqIGAgIyBjb21tZW50YCBkcm9wcGVkIGZyb20gdW5xdW90ZWQgdmFsdWVzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBjb250ZW50XG4gKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZURvdGVudkFwaUtleShjb250ZW50KSB7XG4gIGZvciAoY29uc3QgcmF3TGluZSBvZiBjb250ZW50LnNwbGl0KC9cXHI/XFxuLykpIHtcbiAgICBjb25zdCBtID0gcmF3TGluZS5tYXRjaCgvXlxccyooPzpleHBvcnRcXHMrKT9MVUFfQVBJX0tFWVxccyo9XFxzKiguKikkLyk7XG4gICAgaWYgKCFtKSBjb250aW51ZTtcbiAgICBsZXQgdmFsdWUgPSBtWzFdLnRyaW0oKTtcbiAgICBjb25zdCBxdW90ZWQgPSB2YWx1ZS5tYXRjaCgvXihbJ1wiYF0pKC4qPylcXDEoPzpcXHMrIy4qKT9cXHMqJC8pO1xuICAgIGlmIChxdW90ZWQpIHZhbHVlID0gcXVvdGVkWzJdO1xuICAgIGVsc2UgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKC9cXHMrIy4qJC8sICcnKS50cmltKCk7XG4gICAgcmV0dXJuIHZhbHVlIHx8IG51bGw7XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogTG9jYXRlIHRoZSBsdWEtY2xpIHNlc3Npb24gZmlsZSBmb3IgdGhlIEFQSSBiYXNlIFVSTCBpbiB1c2UuIGx1YS1jbGkgbmFtZXNcbiAqIHRoZSBmaWxlIGJ5IGEgaGFzaCBvZiAoYXBpVXJsLCBhdXRoVXJsLCBmaXJlYmFzZVdlYkFwaUtleSk7IHJhdGhlciB0aGFuXG4gKiByZWNvbXB1dGUgaXQgd2Ugc2NhbiB0aGUgZGlyZWN0b3J5IGZvciBhIGBmaXJlYmFzZS1zZXNzaW9uYCByZWNvcmQgd2hvc2VcbiAqIGBhcGlVcmxgIG1hdGNoZXMsIG5ld2VzdCBmaXJzdC5cbiAqXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx7cGF0aDogc3RyaW5nLCBzZXNzaW9uOiBvYmplY3R9fG51bGw+fVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmluZFNlc3Npb25GaWxlKHsgc2Vzc2lvbnNEaXIsIGFwaVVybCB9KSB7XG4gIGxldCBuYW1lcztcbiAgdHJ5IHtcbiAgICBuYW1lcyA9IGF3YWl0IHJlYWRkaXIoc2Vzc2lvbnNEaXIpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBjb25zdCBjYW5kaWRhdGVzID0gW107XG4gIGZvciAoY29uc3QgbmFtZSBvZiBuYW1lcykge1xuICAgIGlmICghbmFtZS5lbmRzV2l0aCgnLmpzb24nKSB8fCBuYW1lLnN0YXJ0c1dpdGgoJy4nKSkgY29udGludWU7XG4gICAgY29uc3QgcGF0aCA9IGpvaW4oc2Vzc2lvbnNEaXIsIG5hbWUpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBzZXNzaW9uID0gSlNPTi5wYXJzZShhd2FpdCByZWFkRmlsZShwYXRoLCAndXRmOCcpKTtcbiAgICAgIGlmIChzZXNzaW9uPy5raW5kICE9PSAnZmlyZWJhc2Utc2Vzc2lvbicgfHwgc2Vzc2lvbj8udmVyc2lvbiAhPT0gMSkgY29udGludWU7XG4gICAgICBpZiAodHlwZW9mIHNlc3Npb24ucmVmcmVzaFRva2VuICE9PSAnc3RyaW5nJyB8fCAhc2Vzc2lvbi5yZWZyZXNoVG9rZW4pIGNvbnRpbnVlO1xuICAgICAgaWYgKHR5cGVvZiBzZXNzaW9uLmZpcmViYXNlV2ViQXBpS2V5ICE9PSAnc3RyaW5nJyB8fCAhc2Vzc2lvbi5maXJlYmFzZVdlYkFwaUtleSkgY29udGludWU7XG4gICAgICBpZiAoc2Vzc2lvbi5hcGlVcmwgIT09IGFwaVVybCkgY29udGludWU7XG4gICAgICBjb25zdCB7IG10aW1lTXMgfSA9IGF3YWl0IHN0YXQocGF0aCk7XG4gICAgICBjYW5kaWRhdGVzLnB1c2goeyBwYXRoLCBzZXNzaW9uLCBtdGltZU1zIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gdW5yZWFkYWJsZSAvIG1hbGZvcm1lZCBcdTIwMTQgc2tpcCwgbHVhLWNsaSB3aWxsIGNvbXBsYWluIG9uIGl0cyBvd25cbiAgICB9XG4gIH1cbiAgaWYgKGNhbmRpZGF0ZXMubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcbiAgY2FuZGlkYXRlcy5zb3J0KChhLCBiKSA9PiBiLm10aW1lTXMgLSBhLm10aW1lTXMpO1xuICByZXR1cm4geyBwYXRoOiBjYW5kaWRhdGVzWzBdLnBhdGgsIHNlc3Npb246IGNhbmRpZGF0ZXNbMF0uc2Vzc2lvbiB9O1xufVxuXG4vKipcbiAqIEV4Y2hhbmdlIHRoZSBzdG9yZWQgcmVmcmVzaCB0b2tlbiBmb3IgYSBGaXJlYmFzZSBJRCB0b2tlbiAodGhlIGJlYXJlclxuICogbHVhLWFwaSBhY2NlcHRzKS4gQ2FjaGVkIGluLXByb2Nlc3MgdW50aWwgNjAgcyBiZWZvcmUgZXhwaXJ5LiBUaGUgc2Vzc2lvblxuICogZmlsZSBpcyBuZXZlciB3cml0dGVuOiBsdWEtY2xpIG93bnMgaXQuXG4gKlxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gYmVhcmVyIHRva2VuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWZyZXNoU2Vzc2lvbkJlYXJlcih7IHBhdGgsIHNlc3Npb24sIGZldGNoRm4gPSBnbG9iYWxUaGlzLmZldGNoLCBub3cgPSBEYXRlLm5vdyB9KSB7XG4gIGNvbnN0IGNhY2hlZCA9IHRva2VuQ2FjaGUuZ2V0KHBhdGgpO1xuICBpZiAoY2FjaGVkICYmIGNhY2hlZC5leHBpcmVzQXQgLSBub3coKSA+IFJFRlJFU0hfU0tFV19NUykgcmV0dXJuIGNhY2hlZC5pZFRva2VuO1xuXG4gIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiBjb250cm9sbGVyLmFib3J0KCksIFJFRlJFU0hfVElNRU9VVF9NUyk7XG4gIGxldCByZXM7XG4gIHRyeSB7XG4gICAgcmVzID0gYXdhaXQgZmV0Y2hGbihgJHtGSVJFQkFTRV9SRUZSRVNIX1VSTH0/a2V5PSR7ZW5jb2RlVVJJQ29tcG9uZW50KHNlc3Npb24uZmlyZWJhc2VXZWJBcGlLZXkpfWAsIHtcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcgfSxcbiAgICAgIGJvZHk6IG5ldyBVUkxTZWFyY2hQYXJhbXMoeyBncmFudF90eXBlOiAncmVmcmVzaF90b2tlbicsIHJlZnJlc2hfdG9rZW46IHNlc3Npb24ucmVmcmVzaFRva2VuIH0pLnRvU3RyaW5nKCksXG4gICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgIH0pO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgTUNQX0FVVEhfVU5BVkFJTEFCTEU6IGNvdWxkIG5vdCByZWZyZXNoIHRoZSBsdWEtY2xpIHNlc3Npb24gKCR7ZXJyPy5uYW1lID09PSAnQWJvcnRFcnJvcicgPyAndGltZWQgb3V0JyA6IGVyci5tZXNzYWdlfSkuIGAgK1xuICAgICAgJ0NoZWNrIHlvdXIgbmV0d29yaywgb3Igc2V0IExVQV9BUElfS0VZIHRvIGJ5cGFzcyB0aGUgc2Vzc2lvbi4nXG4gICAgKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICB9XG5cbiAgaWYgKCFyZXMub2spIHtcbiAgICBsZXQgcmVhc29uID0gcmVzLnN0YXR1c1RleHQgPz8gU3RyaW5nKHJlcy5zdGF0dXMpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVzLmpzb24oKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBib2R5Py5lcnJvcj8ubWVzc2FnZTtcbiAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycgJiYgbWVzc2FnZSkgcmVhc29uID0gbWVzc2FnZS5zcGxpdCgnOicpWzBdLnRyaW0oKTtcbiAgICB9IGNhdGNoIHsgLyoga2VlcCBzdGF0dXNUZXh0ICovIH1cbiAgICBjb25zdCByZWplY3RlZCA9IHJlcy5zdGF0dXMgPCA1MDAgJiYgUkVKRUNURURfUkVGUkVTSF9SRUFTT05TLmZpbmQoKHIpID0+IHJlYXNvbi50b1VwcGVyQ2FzZSgpLmluY2x1ZGVzKHIpKTtcbiAgICBpZiAocmVqZWN0ZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYE1DUF9BVVRIX1NUQUxFOiB5b3VyIGx1YS1jbGkgc2Vzc2lvbiB3YXMgc2lnbmVkIG91dCAoJHtyZWplY3RlZH0pLiBgICtcbiAgICAgICAgJ1NpZ25pbmcgb3V0IG9mIHRoZSBMdWEgZGFzaGJvYXJkLCBkZXNrdG9wIG9yIG1vYmlsZSBhcHAgYWxzbyBlbmRzIENMSSBzZXNzaW9ucy4gJyArXG4gICAgICAgICdSdW4gYGx1YSBhdXRoIGNvbmZpZ3VyZWAgaW4gYSB0ZXJtaW5hbCB0byBzaWduIGluIGFnYWluLidcbiAgICAgICk7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgTUNQX0FVVEhfVU5BVkFJTEFCTEU6IGx1YS1jbGkgc2Vzc2lvbiByZWZyZXNoIGZhaWxlZCAoJHtyZXMuc3RhdHVzfSAke3JlYXNvbn0pLiBSZXRyeSBpbiBhIG1vbWVudC5gKTtcbiAgfVxuXG4gIGNvbnN0IGJvZHkgPSBhd2FpdCByZXMuanNvbigpO1xuICBjb25zdCBpZFRva2VuID0gYm9keT8uaWRfdG9rZW47XG4gIGNvbnN0IGV4cGlyZXNJbiA9IE51bWJlcihib2R5Py5leHBpcmVzX2luKTtcbiAgaWYgKHR5cGVvZiBpZFRva2VuICE9PSAnc3RyaW5nJyB8fCAhaWRUb2tlbiB8fCAhTnVtYmVyLmlzRmluaXRlKGV4cGlyZXNJbikgfHwgZXhwaXJlc0luIDw9IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01DUF9BVVRIX1VOQVZBSUxBQkxFOiB0aGUgc2Vzc2lvbiByZWZyZXNoIHJldHVybmVkIGFuIGludmFsaWQgdG9rZW4uIFJ1biBgbHVhIGF1dGggY29uZmlndXJlYCBhZ2Fpbi4nKTtcbiAgfVxuICB0b2tlbkNhY2hlLnNldChwYXRoLCB7IGlkVG9rZW4sIGV4cGlyZXNBdDogbm93KCkgKyBleHBpcmVzSW4gKiAxMDAwIH0pO1xuICByZXR1cm4gaWRUb2tlbjtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBiZWFyZXIgdG9rZW4gZXZlcnkgbHVhLWFwaSByZXF1ZXN0IHNob3VsZCBjYXJyeS5cbiAqXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fVxuICogQHRocm93cyB7RXJyb3J9IE1DUF9BVVRIX1NUQUxFIHdoZW4gbm8gY3JlZGVudGlhbCByZXNvbHZlcyBmcm9tIGFueSB0aWVyXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlQXBpS2V5KHtcbiAgZW52ID0gcHJvY2Vzcy5lbnYsXG4gIGNyZWRlbnRpYWxzUGF0aCA9IGVudi5MVUFfQ1JFREVOVElBTFNfUEFUSCA/PyBqb2luKGhvbWVkaXIoKSwgJy5sdWEtY2xpJywgJ2NyZWRlbnRpYWxzJyksXG4gIHNlc3Npb25zRGlyID0gZW52LkxVQV9TRVNTSU9OU19ESVIgPz8gam9pbihkaXJuYW1lKGNyZWRlbnRpYWxzUGF0aCksICdzZXNzaW9ucycpLFxuICBjd2QgPSBwcm9jZXNzLmN3ZCgpLFxuICBhcGlVcmwgPSBlbnYuTFVBX0FQSV9VUkwgfHwgREVGQVVMVF9BUElfVVJMLFxuICBmZXRjaEZuID0gZ2xvYmFsVGhpcy5mZXRjaCxcbiAgbm93ID0gRGF0ZS5ub3csXG59ID0ge30pIHtcbiAgLy8gVGllciAxYTogcHJvY2VzcyBlbnZpcm9ubWVudFxuICBpZiAoZW52LkxVQV9BUElfS0VZICYmIGVudi5MVUFfQVBJX0tFWS50cmltKCkpIHJldHVybiBlbnYuTFVBX0FQSV9LRVkudHJpbSgpO1xuXG4gIC8vIFRpZXIgMWI6IC5lbnYgaW4gdGhlIHdvcmtpbmcgZGlyZWN0b3J5IChsdWEtY2xpIGxvYWRzIGl0IGludG8gcHJvY2Vzcy5lbnZcbiAgLy8gYmVmb3JlIHJlYWRpbmcgTFVBX0FQSV9LRVksIHNvIGl0IHJhbmtzIGFib3ZlIHRoZSBzdG9yZWQgc2Vzc2lvbilcbiAgdHJ5IHtcbiAgICBjb25zdCBmcm9tRG90ZW52ID0gcGFyc2VEb3RlbnZBcGlLZXkoYXdhaXQgcmVhZEZpbGUoam9pbihjd2QsICcuZW52JyksICd1dGY4JykpO1xuICAgIGlmIChmcm9tRG90ZW52KSByZXR1cm4gZnJvbURvdGVudjtcbiAgfSBjYXRjaCB7IC8qIG5vIC5lbnYgXHUyMDE0IGZhbGwgdGhyb3VnaCAqLyB9XG5cbiAgLy8gVGllciAyOiByZW5ld2FibGUgZmlyc3QtcGFydHkgc2Vzc2lvblxuICBjb25zdCBmb3VuZCA9IGF3YWl0IGZpbmRTZXNzaW9uRmlsZSh7IHNlc3Npb25zRGlyLCBhcGlVcmwgfSk7XG4gIGlmIChmb3VuZCkgcmV0dXJuIHJlZnJlc2hTZXNzaW9uQmVhcmVyKHsgLi4uZm91bmQsIGZldGNoRm4sIG5vdyB9KTtcblxuICAvLyBUaWVyIDM6IH4vLmx1YS1jbGkvY3JlZGVudGlhbHMgKHBsYWluIHRleHQgQVBJIGtleSlcbiAgdHJ5IHtcbiAgICBjb25zdCByYXcgPSAoYXdhaXQgcmVhZEZpbGUoY3JlZGVudGlhbHNQYXRoLCAndXRmOCcpKS50cmltKCk7XG4gICAgaWYgKHJhdykge1xuICAgICAgaWYgKHJhdy5zdGFydHNXaXRoKCd7JykpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKHJhdyk7XG4gICAgICAgICAgaWYgKHBhcnNlZD8uYXBpS2V5KSByZXR1cm4gcGFyc2VkLmFwaUtleTtcbiAgICAgICAgfSBjYXRjaCB7IC8qIG5vdCBKU09OIGRlc3BpdGUgbGVhZGluZyBicmFjZSAqLyB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmF3O1xuICAgIH1cbiAgfSBjYXRjaCB7IC8qIG1pc3NpbmcgLyB1bnJlYWRhYmxlIFx1MjAxNCBmYWxsIHRocm91Z2ggKi8gfVxuXG4gIHRocm93IG5ldyBFcnJvcihcbiAgICAnTUNQX0FVVEhfU1RBTEU6IE5vIGx1YS1jbGkgY3JlZGVudGlhbHMgZm91bmQgaW4gTFVBX0FQSV9LRVksIC5lbnYsIH4vLmx1YS1jbGkvc2Vzc2lvbnMsIG9yIH4vLmx1YS1jbGkvY3JlZGVudGlhbHMuICcgK1xuICAgICdSdW4gYGx1YSBhdXRoIGNvbmZpZ3VyZWAgaW4gYSB0ZXJtaW5hbCAob3IgL2x1YS1hdXRoIGluIENsYXVkZSBDb2RlKS4nXG4gICk7XG59XG4iLCAiLy8gVGhpbiBIVFRQIHdyYXBwZXIgYXJvdW5kIGx1YS1hcGkuIFBlciB0ZWNoIHNwZWMgXHUwMEE3OC5cbi8vXG4vLyBXZSBkbyBOT1QgaW1wb3J0IGx1YS1jbGkncyBIdHRwQ2xpZW50IGNsYXNzZXMgYXQgcnVudGltZSAod291bGQgZm9yY2Vcbi8vIHRoZSBlbnRpcmUgbHVhLWNsaSBwYWNrYWdlIHRvIGJlIGJ1bmRsZWQpLiBJbnN0ZWFkLCB0aGlzIG1pbmltYWwgY2xpZW50XG4vLyBoaXRzIHRoZSBzYW1lIFJFU1QgZW5kcG9pbnRzIGx1YS1jbGkgZG9lcy4gRXZlcnkgcm91dGUsIHF1ZXJ5IHBhcmFtZXRlclxuLy8gYW5kIGVudmVsb3BlIHVzZWQgYnkgdGhlIHRvb2xzIGlzIHZlcmlmaWVkIGFnYWluc3QgcGFja2FnZXMvbHVhLWFwaVxuLy8gKGNvbnRyb2xsZXJzL2RldmVsb3Blci8qKiwgZHRvLyoqKSBcdTIwMTQgc2VlIHJlc3BvbnNlLXNoYXBlcy5tanMuXG5cbmltcG9ydCB7IHJlc29sdmVBcGlLZXkgfSBmcm9tICcuL2F1dGgubWpzJztcblxuY29uc3QgREVGQVVMVF9CQVNFX1VSTCA9ICdodHRwczovL2FwaS5oZXlsdWEuYWknO1xuY29uc3QgREVGQVVMVF9USU1FT1VUX01TID0gMTBfMDAwO1xuXG4vLyBTY29wZSBlYWNoIHJvdXRlIGZhbWlseSB0aGUgdG9vbHMgY2FsbCBhY3R1YWxseSByZXF1aXJlcyBcdTIwMTQgcmVhZCBmcm9tIHRoZVxuLy8gYEBSZXF1aXJlU2NvcGUoLi4uKWAgZGVjb3JhdG9yIG9uIGV2ZXJ5IEdFVCB0aGUgdG9vbHMgaGl0LCB1bmRlclxuLy8gbHVhLWNvcmUtc2VydmljZXMgcGFja2FnZXMvbHVhLWFwaS9zcmMvY29udHJvbGxlcnMvZGV2ZWxvcGVyLzpcbi8vICAgc2tpbGxzL2Jhc2UuY29udHJvbGxlci50cywgd2ViaG9va3MvYmFzZS5jb250cm9sbGVyLnRzLFxuLy8gICBqb2JzL2Jhc2UuY29udHJvbGxlci50cywgdHJpZ2dlcnMvYmFzZS5jb250cm9sbGVyLnRzLFxuLy8gICBwcmVwcm9jZXNzb3JzL2Jhc2UuY29udHJvbGxlci50cywgcG9zdHByb2Nlc3NvcnMvYmFzZS5jb250cm9sbGVyLnRzXG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdTIxOTIgJ2F1dG9tYXRpb25zOnJlYWQnIChsaXN0ICsgOmlkL3ZlcnNpb25zKVxuLy8gICB3b3JrZmxvd3MvYmFzZS5jb250cm9sbGVyLnRzICAgXHUyMTkyICd3b3JrZmxvd3M6cmVhZCcgICAoR0VUIDphZ2VudElkLCBHRVQgOmFnZW50SWQvOndvcmtmbG93SWQvdmVyc2lvbnMpXG4vLyAgIHBlcnNvbmEvYmFzZS5jb250cm9sbGVyLnRzICAgICBcdTIxOTIgJ2FnZW50czpyZWFkJyAgICAgIChHRVQgOmFnZW50SWQvcGVyc29uYS92ZXJzaW9ucylcbi8vICAgYmFzZS5jb250cm9sbGVyLnRzICAgICAgICAgICAgIFx1MjE5MiAna25vd2xlZGdlOnJlYWQnICAgKEdFVCBhZ2VudHMvOmFnZW50SWQvbG9ncylcbi8vIFdvcmtmbG93cyBhcmUgTk9UIHVuZGVyIGF1dG9tYXRpb25zOnJlYWQgXHUyMDE0IHRoZXkgaGF2ZSB0aGVpciBvd24gc2NvcGUgcGFpclxuLy8gKHdvcmtmbG93czpyZWFkIC8gd29ya2Zsb3dzOndyaXRlKS5cbmV4cG9ydCBjb25zdCBST1VURV9TQ09QRVMgPSBPYmplY3QuZnJlZXplKHtcbiAgc2tpbGxzOiAnYXV0b21hdGlvbnM6cmVhZCcsXG4gIHdlYmhvb2tzOiAnYXV0b21hdGlvbnM6cmVhZCcsXG4gIGpvYnM6ICdhdXRvbWF0aW9uczpyZWFkJyxcbiAgdHJpZ2dlcnM6ICdhdXRvbWF0aW9uczpyZWFkJyxcbiAgcHJlcHJvY2Vzc29yczogJ2F1dG9tYXRpb25zOnJlYWQnLFxuICBwb3N0cHJvY2Vzc29yczogJ2F1dG9tYXRpb25zOnJlYWQnLFxuICB3b3JrZmxvd3M6ICd3b3JrZmxvd3M6cmVhZCcsXG4gIHBlcnNvbmE6ICdhZ2VudHM6cmVhZCcsXG4gIGxvZ3M6ICdrbm93bGVkZ2U6cmVhZCcsXG59KTtcblxuY29uc3QgUk9VVEVfU0NPUEVfU1VNTUFSWSA9XG4gICdza2lsbHMvd2ViaG9va3Mvam9icy90cmlnZ2Vycy9wcmVwcm9jZXNzb3JzL3Bvc3Rwcm9jZXNzb3JzIG5lZWQgYXV0b21hdGlvbnM6cmVhZCwgd29ya2Zsb3dzIG5lZWQgJyArXG4gICd3b3JrZmxvd3M6cmVhZCwgcGVyc29uYSBuZWVkcyBhZ2VudHM6cmVhZCwgbG9ncyBuZWVkIGtub3dsZWRnZTpyZWFkJztcblxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCAtIEFQSSBwYXRoICh3aXRoIGxlYWRpbmcgc2xhc2gpXG4gKiBAcGFyYW0ge3ttZXRob2Q/OiBzdHJpbmcsIGJvZHk/OiBvYmplY3QsIHF1ZXJ5PzogUmVjb3JkPHN0cmluZyxzdHJpbmd8bnVtYmVyPiwgZmV0Y2hGbj86IHR5cGVvZiBmZXRjaCwgYmFzZVVybD86IHN0cmluZywgdGltZW91dE1zPzogbnVtYmVyfX0gW29wdHNdXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhcGlSZXF1ZXN0KHBhdGgsIHtcbiAgbWV0aG9kID0gJ0dFVCcsXG4gIGJvZHksXG4gIHF1ZXJ5LFxuICBmZXRjaEZuID0gZ2xvYmFsVGhpcy5mZXRjaCxcbiAgYmFzZVVybCA9IHByb2Nlc3MuZW52LkxVQV9BUElfVVJMIHx8IERFRkFVTFRfQkFTRV9VUkwsXG4gIHRpbWVvdXRNcyA9IERFRkFVTFRfVElNRU9VVF9NUyxcbn0gPSB7fSkge1xuICBjb25zdCBhcGlLZXkgPSBhd2FpdCByZXNvbHZlQXBpS2V5KCk7XG4gIC8vIEpvaW4gYnkgc3RyaW5nIGNvbmNhdGVuYXRpb24sIE5PVCBgbmV3IFVSTChwYXRoLCBiYXNlVXJsKWA6IHRoZSBXSEFUV0dcbiAgLy8gcmVzb2x2ZXIgdHJlYXRzIGEgbGVhZGluZy1zbGFzaCBwYXRoIGFzIGhvc3QtYWJzb2x1dGUgYW5kIHdvdWxkIGRyb3AgYW55XG4gIC8vIHBhdGggcHJlZml4IG9uIExVQV9BUElfVVJMIChodHRwczovL2hvc3QvYXBpICsgL2RldmVsb3Blci94IFx1MjE5MlxuICAvLyBodHRwczovL2hvc3QvZGV2ZWxvcGVyL3gpLiBgcGF0aGAgYWx3YXlzIHN0YXJ0cyB3aXRoICcvJywgc28gc3RyaXAgb25lXG4gIC8vIHRyYWlsaW5nIHNsYXNoIGZyb20gdGhlIGJhc2UgYW5kIGNvbmNhdGVuYXRlLlxuICBjb25zdCB1cmwgPSBuZXcgVVJMKGJhc2VVcmwucmVwbGFjZSgvXFwvJC8sICcnKSArIHBhdGgpO1xuICBpZiAocXVlcnkpIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKHF1ZXJ5KSkgdXJsLnNlYXJjaFBhcmFtcy5zZXQoaywgU3RyaW5nKHYpKTtcblxuICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4gY29udHJvbGxlci5hYm9ydCgpLCB0aW1lb3V0TXMpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgZmV0Y2hGbih1cmwudG9TdHJpbmcoKSwge1xuICAgICAgbWV0aG9kLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnQXV0aG9yaXphdGlvbic6IGBCZWFyZXIgJHthcGlLZXl9YCxcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgJ1gtTHVhLUNsaWVudCc6ICdjbGF1ZGUtcGx1Z2luLzEuNi4wJyxcbiAgICAgIH0sXG4gICAgICBib2R5OiBib2R5ID8gSlNPTi5zdHJpbmdpZnkoYm9keSkgOiB1bmRlZmluZWQsXG4gICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgIH0pO1xuXG4gICAgaWYgKHJlcy5zdGF0dXMgPT09IDQwMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnTUNQX0FVVEhfU1RBTEU6IGx1YS1hcGkgcmV0dXJuZWQgNDAxLiBUaGUgY3JlZGVudGlhbCBpcyBtaXNzaW5nLCBleHBpcmVkLCBvciB0aGUgc2Vzc2lvbiB3YXMgc2lnbmVkIG91dCAnICtcbiAgICAgICAgJyhzaWduaW5nIG91dCBvZiB0aGUgTHVhIGRhc2hib2FyZCBvciBhcHBzIGFsc28gZW5kcyBDTEkgc2Vzc2lvbnMpLiBSdW4gYGx1YSBhdXRoIGNvbmZpZ3VyZWAgaW4gYSB0ZXJtaW5hbCwgJyArXG4gICAgICAgICdvciByZS1ydW4gL2x1YS1kb2N0b3IuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHJlcy5zdGF0dXMgPT09IDQwMykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgTUNQX0ZPUkJJRERFTjogbHVhLWFwaSByZXR1cm5lZCA0MDMgZm9yICR7cGF0aH0uIFRoZSBjcmVkZW50aWFsIGNhbm5vdCBhY2Nlc3MgdGhpcyBhZ2VudCBvciBvcmcsIG9yIGl0IGxhY2tzIGAgK1xuICAgICAgICBgdGhlIHJvdXRlIHNjb3BlICgke1JPVVRFX1NDT1BFX1NVTU1BUll9IFx1MjAxNCB0eXBlZCBrZXlzIGFyZSBzY29wZWQgdG8gdGhlIGFnZW50cyBhbmQgcm9sZSBjaG9zZW4gYXQgYCArXG4gICAgICAgICdgbHVhIGF1dGggY29uZmlndXJlYCkuIFJlLXJ1biAvbHVhLWRvY3RvciBvciBjaGVjayB0aGUgTFVBX0FQSV9LRVkgZW52IHZhci4nXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIXJlcy5vaykge1xuICAgICAgLy8gVHJ5IHRvIHBhcnNlIGx1YS1hcGkncyBzdHJ1Y3R1cmVkIGVycm9yIGVudmVsb3BlOlxuICAgICAgLy8gICB7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogeyBtZXNzYWdlLCBzdGF0dXNDb2RlLCBjb2RlPywgLi4uIH0gfVxuICAgICAgLy8gRmFsbHMgYmFjayB0byByYXcgdGV4dCBvbiBwYXJzZSBmYWlsdXJlIChlLmcuIHByb3h5IDUwMiB3aXRoIEhUTUwgYm9keSkuXG4gICAgICBjb25zdCByYXcgPSBhd2FpdCByZXMudGV4dCgpO1xuICAgICAgbGV0IGZyaWVuZGx5TXNnID0gcmF3O1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShyYXcpO1xuICAgICAgICBmcmllbmRseU1zZyA9IHBhcnNlZD8uZXJyb3I/Lm1lc3NhZ2UgPz8gcGFyc2VkPy5tZXNzYWdlID8/IHJhdztcbiAgICAgICAgY29uc3QgY29kZSA9IHBhcnNlZD8uZXJyb3I/LmNvZGU7XG4gICAgICAgIGlmICh0eXBlb2YgY29kZSA9PT0gJ3N0cmluZycgJiYgY29kZSAmJiAhU3RyaW5nKGZyaWVuZGx5TXNnKS5pbmNsdWRlcyhjb2RlKSkgZnJpZW5kbHlNc2cgPSBgJHtjb2RlfTogJHtmcmllbmRseU1zZ31gO1xuICAgICAgfSBjYXRjaCB7IC8qIG5vdCBKU09OOyByYXcgaXMgZmluZSAqLyB9XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGx1YS1hcGkgJHtyZXMuc3RhdHVzfTogJHtmcmllbmRseU1zZ31gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXdhaXQgcmVzLmpzb24oKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaWYgKGVyci5uYW1lID09PSAnQWJvcnRFcnJvcicpIHRocm93IG5ldyBFcnJvcihgTUNQX1RJTUVPVVQ6ICR7cGF0aH0gZGlkIG5vdCByZXNwb25kIGluICR7dGltZW91dE1zfW1zYCk7XG4gICAgdGhyb3cgZXJyO1xuICB9IGZpbmFsbHkge1xuICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gIH1cbn1cbiIsICIvLyBQZXItdHlwZSByZXNwb25zZS1zaGFwZSBleHRyYWN0b3JzLlxuLy9cbi8vIGx1YS1hcGkncyBkZXZlbG9wZXIgZW5kcG9pbnRzIGhhdmUgSU5DT05TSVNURU5UIHJlc3BvbnNlIHNoYXBlcyBhY3Jvc3Ncbi8vIHByaW1pdGl2ZSB0eXBlcy4gVmVyaWZpZWQgYWdhaW5zdCBwYWNrYWdlcy9sdWEtYXBpL3NyYy9kdG8vKi5kdG8udHMgYW5kXG4vLyBwYWNrYWdlcy9sdWEtYXBpL3NyYy9jb250cm9sbGVycy9kZXZlbG9wZXIvKiovYmFzZS5jb250cm9sbGVyLnRzLCBwbHVzXG4vLyBwYWNrYWdlcy9sdWEtY2xpL3NyYy9pbnRlcmZhY2VzL3dvcmtmbG93cy50cyAobHVhLWNsaSAzLjMzLjApOlxuLy9cbi8vICAgU2tpbGxzICAgICAgICAgR0VUIC9kZXZlbG9wZXIvc2tpbGxzLzphZ2VudElkICAgICAgICAgICAgICAgICAgICAgIFx1MjE5MiB7IHNraWxsczogU2tpbGxEdG9bXSB9XG4vLyAgICAgICAgICAgICAgICAgIEdFVCAvZGV2ZWxvcGVyL3NraWxscy86YWdlbnRJZC86c2tpbGxJZC92ZXJzaW9ucyAgICBcdTIxOTIgeyB2ZXJzaW9uczogW3sgdmVyc2lvbiwgY3JlYXRlZERhdGUsIGlzQ3VycmVudCwgLi4uIH1dIH1cbi8vICAgV2ViaG9va3MgICAgICAgR0VUIC9kZXZlbG9wZXIvd2ViaG9va3MvOmFnZW50SWQgICAgICAgICAgICAgICAgICAgIFx1MjE5MiB7IHN1Y2Nlc3MsIGRhdGE6IHsgd2ViaG9va3MgfSB9XG4vLyAgICAgICAgICAgICAgICAgIEdFVCAuLi4vOndlYmhvb2tJZC92ZXJzaW9ucyAgICAgICAgICAgICAgICAgICAgICAgICBcdTIxOTIgeyBzdWNjZXNzLCBkYXRhOiB7IHZlcnNpb25zOiBbeyB2ZXJzaW9uLCB3ZWJob29rSWQsIGNyZWF0ZWRBdCwgaXNBY3RpdmUgfV0sIGFjdGl2ZVZlcnNpb25JZD8gfSB9XG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2aWNlcy9kZXZlbG9wZXIud2ViaG9vay5zZXJ2aWNlLnRzIHNldHMgYHdlYmhvb2tJZDogdi5pZGAgXHUyMDE0IHRoZVxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyc2lvbiBST1cgaWQgdW5kZXIgYSBtaXNuYW1lZCBrZXk7IHRoZXJlIGlzIG5vIHZlcnNpb25JZC9pZCwgc29cbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcnNpb25JZCgpIGlzIG51bGwgYW5kIHRoZSBlbnZlbG9wZSdzIGFjdGl2ZVZlcnNpb25JZCBpcyB0aGUgb25seSBpZClcbi8vICAgSm9icyAgICAgICAgICAgR0VUIC9kZXZlbG9wZXIvam9icy86YWdlbnRJZCAgICAgICAgICAgICAgICAgICAgICAgIFx1MjE5MiB7IHN1Y2Nlc3MsIGRhdGE6IHsgam9icyB9IH1cbi8vICAgICAgICAgICAgICAgICAgR0VUIC4uLi86am9iSWQvdmVyc2lvbnMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFx1MjE5MiB7IHN1Y2Nlc3MsIGRhdGE6IEpvYlZlcnNpb25EdG9bXSB9ICAgXHUyMTkwIGFycmF5IHVuZGVyIGRhdGE7IGBhY3RpdmVgXG4vLyAgIFRyaWdnZXJzICAgICAgIEdFVCAvZGV2ZWxvcGVyL3RyaWdnZXJzLzphZ2VudElkICAgICAgICAgICAgICAgICAgICBcdTIxOTIgeyBzdWNjZXNzLCBkYXRhOiB7IHRyaWdnZXJzIH0gfVxuLy8gICAgICAgICAgICAgICAgICBHRVQgLi4uLzp0cmlnZ2VySWQvdmVyc2lvbnMgICAgICAgICAgICAgICAgICAgICAgICAgXHUyMTkyIHsgc3VjY2VzcywgZGF0YTogeyB2ZXJzaW9uczogW3sgdmVyc2lvbiwgdmVyc2lvbklkLCBjcmVhdGVkQXQsIGlzQWN0aXZlIH1dLCBhY3RpdmVWZXJzaW9uSWQ/IH0gfVxuLy8gICBQcmVwcm9jZXNzb3JzICBHRVQgL2RldmVsb3Blci9wcmVwcm9jZXNzb3JzLzphZ2VudElkICAgICAgICAgICAgICAgXHUyMTkyIHsgc3VjY2VzcywgZGF0YTogeyBwcmVwcm9jZXNzb3JzIH0gfVxuLy8gICAgICAgICAgICAgICAgICBHRVQgLi4uLzpwcmVwcm9jZXNzb3JJZC92ZXJzaW9ucyAgICAgICAgICAgICAgICAgICAgXHUyMTkyIHsgc3VjY2VzcywgZGF0YTogeyB2ZXJzaW9uczogW3sgdmVyc2lvbklkLCB2ZXJzaW9uLCBpc0FjdGl2ZSwgY3JlYXRlZEF0IH1dLCBhY3RpdmVWZXJzaW9uSWQ/IH0gfVxuLy8gICBQb3N0cHJvY2Vzc29ycyBHRVQgL2RldmVsb3Blci9wb3N0cHJvY2Vzc29ycy86YWdlbnRJZCAgICAgICAgICAgICAgXHUyMTkyIHsgc3VjY2VzcywgZGF0YTogeyBwb3N0cHJvY2Vzc29ycyB9IH1cbi8vICAgICAgICAgICAgICAgICAgR0VUIC4uLi86cG9zdHByb2Nlc3NvcklkL3ZlcnNpb25zICAgICAgICAgICAgICAgICAgIFx1MjE5MiBzYW1lIGZhbWlseSBhcyBwcmVwcm9jZXNzb3JzXG4vLyAgIFdvcmtmbG93cyAgICAgIEdFVCAvZGV2ZWxvcGVyL3dvcmtmbG93cy86YWdlbnRJZCAgICAgICAgICAgICAgICAgICBcdTIxOTIgeyBzdWNjZXNzLCBkYXRhOiB7IHdvcmtmbG93cyB9IH0gICAoY29kZS9zY3JpcHQgcHJvamVjdGVkIG91dClcbi8vICAgICAgICAgICAgICAgICAgR0VUIC4uLi86d29ya2Zsb3dJZC92ZXJzaW9ucyAgICAgICAgICAgICAgICAgICAgICAgIFx1MjE5MiB7IHN1Y2Nlc3MsIGRhdGE6IFdvcmtmbG93VmVyc2lvbltdIH0gICBcdTIxOTAgYXJyYXkgdW5kZXIgZGF0YTsgYGFjdGl2ZWBcbi8vICAgUGVyc29uYSAgICAgICAgR0VUIC9kZXZlbG9wZXIvYWdlbnRzLzphZ2VudElkL3BlcnNvbmEvdmVyc2lvbnMgICAgIFx1MjE5MiB7IHN0YXR1cywgbWVzc2FnZSwgdmVyc2lvbnM6IFt7IHZlcnNpb246IG51bWJlciwgY3JlYXRlZERhdGU6IG51bWJlciwgaXNDdXJyZW50LCBwZXJzb25hIH1dIH1cbi8vXG4vLyBObyB2ZXJzaW9uIERUTyBjYXJyaWVzIGBkZXBsb3llZEF0YCBvciBgc291cmNlSGFzaGAuIFRoZSBcImxpdmVcIiBmbGFnIGlzXG4vLyBgaXNDdXJyZW50YCAoc2tpbGwsIHBlcnNvbmEpLCBgYWN0aXZlYCAoam9iLCB3b3JrZmxvdykgb3IgYGlzQWN0aXZlYCAvXG4vLyBgYWN0aXZlVmVyc2lvbklkYCAod2ViaG9vaywgdHJpZ2dlciwgcHJlL3Bvc3Rwcm9jZXNzb3IpLiBDcmVhdGlvbiB0aW1lIGlzXG4vLyBgY3JlYXRlZEF0YCAoSVNPIHN0cmluZykgZXZlcnl3aGVyZSBleGNlcHQgc2tpbGwvcGVyc29uYSAoYGNyZWF0ZWREYXRlYDtcbi8vIHBlcnNvbmEncyBpcyBhbiBlcG9jaC1tcyBudW1iZXIpLlxuXG5jb25zdCBMSVNUX0VYVFJBQ1RPUlMgPSB7XG4gIHNraWxsOiAgICAgICAgIChyKSA9PiByPy5za2lsbHMgPz8gW10sXG4gIHdlYmhvb2s6ICAgICAgIChyKSA9PiByPy5kYXRhPy53ZWJob29rcyA/PyBbXSxcbiAgam9iOiAgICAgICAgICAgKHIpID0+IHI/LmRhdGE/LmpvYnMgPz8gW10sXG4gIHRyaWdnZXI6ICAgICAgIChyKSA9PiByPy5kYXRhPy50cmlnZ2VycyA/PyBbXSxcbiAgcHJlcHJvY2Vzc29yOiAgKHIpID0+IHI/LmRhdGE/LnByZXByb2Nlc3NvcnMgPz8gW10sXG4gIHBvc3Rwcm9jZXNzb3I6IChyKSA9PiByPy5kYXRhPy5wb3N0cHJvY2Vzc29ycyA/PyBbXSxcbiAgd29ya2Zsb3c6ICAgICAgKHIpID0+IHI/LmRhdGE/LndvcmtmbG93cyA/PyBbXSxcbn07XG5cbmNvbnN0IFZFUlNJT05TX0VYVFJBQ1RPUlMgPSB7XG4gIHNraWxsOiAgICAgICAgIChyKSA9PiByPy52ZXJzaW9ucyA/PyBbXSxcbiAgd2ViaG9vazogICAgICAgKHIpID0+IHI/LmRhdGE/LnZlcnNpb25zID8/IFtdLFxuICBqb2I6ICAgICAgICAgICAocikgPT4gKEFycmF5LmlzQXJyYXkocj8uZGF0YSkgPyByLmRhdGEgOiBbXSksXG4gIHRyaWdnZXI6ICAgICAgIChyKSA9PiByPy5kYXRhPy52ZXJzaW9ucyA/PyBbXSxcbiAgcHJlcHJvY2Vzc29yOiAgKHIpID0+IHI/LmRhdGE/LnZlcnNpb25zID8/IFtdLFxuICBwb3N0cHJvY2Vzc29yOiAocikgPT4gcj8uZGF0YT8udmVyc2lvbnMgPz8gW10sXG4gIHdvcmtmbG93OiAgICAgIChyKSA9PiAoQXJyYXkuaXNBcnJheShyPy5kYXRhKSA/IHIuZGF0YSA6IFtdKSxcbiAgcGVyc29uYTogICAgICAgKHIpID0+IHI/LnZlcnNpb25zID8/IFtdLFxufTtcblxuLyoqIFVSTCBwYXRoIHNlZ21lbnQgdW5kZXIgL2RldmVsb3Blci8gZm9yIGVhY2ggbGlzdGFibGUgdHlwZS4gKi9cbmV4cG9ydCBjb25zdCBMSVNUX1BBVEhTID0ge1xuICBza2lsbDogJ3NraWxscycsXG4gIHdlYmhvb2s6ICd3ZWJob29rcycsXG4gIGpvYjogJ2pvYnMnLFxuICB0cmlnZ2VyOiAndHJpZ2dlcnMnLFxuICBwcmVwcm9jZXNzb3I6ICdwcmVwcm9jZXNzb3JzJyxcbiAgcG9zdHByb2Nlc3NvcjogJ3Bvc3Rwcm9jZXNzb3JzJyxcbiAgd29ya2Zsb3c6ICd3b3JrZmxvd3MnLFxufTtcblxuLyoqXG4gKiBFeHRyYWN0IGEgbGlzdCBvZiBwcmltaXRpdmVzIGZyb20gYSBsaXN0LWVuZHBvaW50IHJlc3BvbnNlLlxuICogQHRocm93cyBpZiB0aGUgdHlwZSBpcyB1bmtub3duLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdExpc3QodHlwZSwgcmVzcG9uc2UpIHtcbiAgY29uc3QgZm4gPSBMSVNUX0VYVFJBQ1RPUlNbdHlwZV07XG4gIGlmICghZm4pIHRocm93IG5ldyBFcnJvcihgZXh0cmFjdExpc3Q6IHVua25vd24gcHJpbWl0aXZlIHR5cGUgXCIke3R5cGV9XCIuIFZhbGlkOiAke09iamVjdC5rZXlzKExJU1RfRVhUUkFDVE9SUykuam9pbignLCAnKX1gKTtcbiAgcmV0dXJuIGZuKHJlc3BvbnNlKTtcbn1cblxuLyoqXG4gKiBFeHRyYWN0IGEgbGlzdCBvZiB2ZXJzaW9ucyBmcm9tIGEgdmVyc2lvbnMtZW5kcG9pbnQgcmVzcG9uc2UuXG4gKiBAdGhyb3dzIGlmIHRoZSB0eXBlIGlzIHVua25vd24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0VmVyc2lvbnModHlwZSwgcmVzcG9uc2UpIHtcbiAgY29uc3QgZm4gPSBWRVJTSU9OU19FWFRSQUNUT1JTW3R5cGVdO1xuICBpZiAoIWZuKSB0aHJvdyBuZXcgRXJyb3IoYGV4dHJhY3RWZXJzaW9uczogdW5rbm93biBwcmltaXRpdmUgdHlwZSBcIiR7dHlwZX1cIi4gVmFsaWQ6ICR7T2JqZWN0LmtleXMoVkVSU0lPTlNfRVhUUkFDVE9SUykuam9pbignLCAnKX1gKTtcbiAgcmV0dXJuIGZuKHJlc3BvbnNlKTtcbn1cblxuLyoqXG4gKiBUaGUgYGFjdGl2ZVZlcnNpb25JZGAgYSB2ZXJzaW9ucyBlbnZlbG9wZSBtYXkgY2FycnkgYmVzaWRlIGl0cyBhcnJheVxuICogKHdlYmhvb2ssIHRyaWdnZXIsIHByZS9wb3N0cHJvY2Vzc29yKS4gTnVsbCBmb3IgdGhlIG90aGVyIGZhbWlsaWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdEFjdGl2ZVZlcnNpb25JZChyZXNwb25zZSkge1xuICBjb25zdCBpZCA9IHJlc3BvbnNlPy5kYXRhPy5hY3RpdmVWZXJzaW9uSWQ7XG4gIHJldHVybiB0eXBlb2YgaWQgPT09ICdzdHJpbmcnICYmIGlkID8gaWQgOiBudWxsO1xufVxuXG4vKipcbiAqIElzIHRoaXMgdmVyc2lvbiB0aGUgb25lIHRoYXQgaXMgbGl2ZT8gRWFjaCBmYW1pbHkgc3BlbGxzIGl0IGRpZmZlcmVudGx5LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlXG4gKiBAcGFyYW0ge29iamVjdH0gdmVyc2lvbiAtIG9uZSBlbGVtZW50IG9mIGV4dHJhY3RWZXJzaW9ucygpXG4gKiBAcGFyYW0ge29iamVjdH0gW3Jlc3BvbnNlXSAtIHRoZSB2ZXJzaW9ucyBlbnZlbG9wZSAoZm9yIGFjdGl2ZVZlcnNpb25JZClcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQWN0aXZlVmVyc2lvbih0eXBlLCB2ZXJzaW9uLCByZXNwb25zZSkge1xuICBpZiAoIXZlcnNpb24gfHwgdHlwZW9mIHZlcnNpb24gIT09ICdvYmplY3QnKSByZXR1cm4gZmFsc2U7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgJ3NraWxsJzpcbiAgICBjYXNlICdwZXJzb25hJzpcbiAgICAgIHJldHVybiB2ZXJzaW9uLmlzQ3VycmVudCA9PT0gdHJ1ZTtcbiAgICBjYXNlICdqb2InOlxuICAgIGNhc2UgJ3dvcmtmbG93JzpcbiAgICAgIHJldHVybiB2ZXJzaW9uLmFjdGl2ZSA9PT0gdHJ1ZTtcbiAgICBjYXNlICd3ZWJob29rJzpcbiAgICBjYXNlICd0cmlnZ2VyJzpcbiAgICBjYXNlICdwcmVwcm9jZXNzb3InOlxuICAgIGNhc2UgJ3Bvc3Rwcm9jZXNzb3InOiB7XG4gICAgICBpZiAodmVyc2lvbi5pc0FjdGl2ZSA9PT0gdHJ1ZSkgcmV0dXJuIHRydWU7XG4gICAgICBjb25zdCBhY3RpdmVJZCA9IGV4dHJhY3RBY3RpdmVWZXJzaW9uSWQocmVzcG9uc2UpO1xuICAgICAgY29uc3Qgb3duSWQgPSB2ZXJzaW9uLnZlcnNpb25JZCA/PyB2ZXJzaW9uLmlkID8/IG51bGw7XG4gICAgICByZXR1cm4gISFhY3RpdmVJZCAmJiBvd25JZCA9PT0gYWN0aXZlSWQ7XG4gICAgfVxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLyoqXG4gKiBJU08tODYwMSBjcmVhdGlvbiB0aW1lIG9mIGEgdmVyc2lvbiwgb3IgbnVsbC4gTm9ybWFsaXNlcyBza2lsbC9wZXJzb25hJ3NcbiAqIGBjcmVhdGVkRGF0ZWAgKHBlcnNvbmE6IGVwb2NoIG1zKSBvbnRvIHRoZSBgY3JlYXRlZEF0YCBuYW1lLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmVyc2lvbkNyZWF0ZWRBdCh2ZXJzaW9uKSB7XG4gIGlmICghdmVyc2lvbiB8fCB0eXBlb2YgdmVyc2lvbiAhPT0gJ29iamVjdCcpIHJldHVybiBudWxsO1xuICBjb25zdCByYXcgPSB2ZXJzaW9uLmNyZWF0ZWRBdCA/PyB2ZXJzaW9uLmNyZWF0ZWREYXRlID8/IG51bGw7XG4gIGlmIChyYXcgPT0gbnVsbCkgcmV0dXJuIG51bGw7XG4gIGlmICh0eXBlb2YgcmF3ID09PSAnbnVtYmVyJykgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShyYXcpID8gbmV3IERhdGUocmF3KS50b0lTT1N0cmluZygpIDogbnVsbDtcbiAgcmV0dXJuIFN0cmluZyhyYXcpO1xufVxuXG4vKiogSWRlbnRpZmllciBvZiBhIHZlcnNpb24gcm93ICh0aGUgc2xvdCBsdWEtYXBpIGtleXMgYGFjdGl2ZVZlcnNpb25JZGAgb24pLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZlcnNpb25JZCh2ZXJzaW9uKSB7XG4gIGlmICghdmVyc2lvbiB8fCB0eXBlb2YgdmVyc2lvbiAhPT0gJ29iamVjdCcpIHJldHVybiBudWxsO1xuICByZXR1cm4gdmVyc2lvbi52ZXJzaW9uSWQgPz8gdmVyc2lvbi5pZCA/PyBudWxsO1xufVxuXG5leHBvcnQgY29uc3QgU1VQUE9SVEVEX0xJU1RfVFlQRVMgPSBPYmplY3Qua2V5cyhMSVNUX0VYVFJBQ1RPUlMpO1xuZXhwb3J0IGNvbnN0IFNVUFBPUlRFRF9WRVJTSU9OX1RZUEVTID0gT2JqZWN0LmtleXMoVkVSU0lPTlNfRVhUUkFDVE9SUyk7XG4iLCAiaW1wb3J0IHsgYXBpUmVxdWVzdCB9IGZyb20gJy4uL2FwaS1jbGllbnQubWpzJztcbmltcG9ydCB7XG4gIGV4dHJhY3RMaXN0LFxuICBleHRyYWN0VmVyc2lvbnMsXG4gIGV4dHJhY3RBY3RpdmVWZXJzaW9uSWQsXG4gIGlzQWN0aXZlVmVyc2lvbixcbiAgdmVyc2lvbkNyZWF0ZWRBdCxcbiAgdmVyc2lvbklkLFxuICBMSVNUX1BBVEhTLFxuICBTVVBQT1JURURfVkVSU0lPTl9UWVBFUyxcbn0gZnJvbSAnLi4vcmVzcG9uc2Utc2hhcGVzLm1qcyc7XG5cbmNvbnN0IFZBTElEX1RZUEVTID0gbmV3IFNldChTVVBQT1JURURfVkVSU0lPTl9UWVBFUyk7XG5cbmV4cG9ydCBjb25zdCBsaXN0UHJpbWl0aXZlVmVyc2lvbnMgPSB7XG4gIHNwZWM6IHtcbiAgICBuYW1lOiAnbGlzdF9wcmltaXRpdmVfdmVyc2lvbnMnLFxuICAgIC8vIFdoaWNoIGZhbWlsaWVzIGNhcnJ5IGEgcGVyLWVudHJ5IGlkIFx1MjAxNCB2ZXJpZmllZCBpbiBsdWEtYXBpJ3Mgc2VydmljZVxuICAgIC8vIG1hcHBlcnMgKHBhY2thZ2VzL2x1YS1hcGkvc3JjL3NlcnZpY2VzLyk6XG4gICAgLy8gICBkZXZlbG9wZXIudHJpZ2dlci5zZXJ2aWNlLnRzIGdldFRyaWdnZXJWZXJzaW9ucyAgICAgICAgICAgIFx1MjE5MiB7IHZlcnNpb24sIHZlcnNpb25JZDogdi5pZCwgY3JlYXRlZEF0LCBpc0FjdGl2ZSB9XG4gICAgLy8gICBkZXZlbG9wZXIucHJlcHJvY2Vzc29yLnNlcnZpY2UudHMgZ2V0UHJlUHJvY2Vzc29yVmVyc2lvbnMgIFx1MjE5MiB7IHZlcnNpb25JZDogdi5pZCwgdmVyc2lvbiwgaXNBY3RpdmUsIGNyZWF0ZWRBdCB9XG4gICAgLy8gICBkZXZlbG9wZXIucG9zdHByb2Nlc3Nvci5zZXJ2aWNlLnRzIGdldFBvc3RQcm9jZXNzb3JWZXJzaW9uc1x1MjE5MiBzYW1lIGFzIHByZXByb2Nlc3NvclxuICAgIC8vICAgZGV2ZWxvcGVyLndvcmtmbG93LnNlcnZpY2UudHMgdG9WZXJzaW9uRHRvICAgICAgICAgICAgICAgICBcdTIxOTIgeyBpZCwgdmVyc2lvbiwgYWN0aXZlLCAuLi4gfVxuICAgIC8vICAgZHRvL2pvYi5kdG8udHMgSm9iVmVyc2lvbkR0byAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdTIxOTIgeyBpZCwgdmVyc2lvbiwgYWN0aXZlLCAuLi4gfVxuICAgIC8vICAgZGV2ZWxvcGVyLndlYmhvb2suc2VydmljZS50cyBnZXRXZWJob29rVmVyc2lvbnMgICAgICAgICAgICBcdTIxOTIgeyB2ZXJzaW9uLCB3ZWJob29rSWQ6IHYuaWQsIGNyZWF0ZWRBdCwgaXNBY3RpdmUgfVxuICAgIC8vICAgICAgIChOTyB2ZXJzaW9uSWQvaWQga2V5IFx1MjAxNCB0aGUgcm93IGlkIGlzIHN0YXNoZWQgdW5kZXIgdGhlIG1pc25hbWVkXG4gICAgLy8gICAgICAgIGB3ZWJob29rSWRgLCB3aGljaCB3ZSBkZWxpYmVyYXRlbHkgZG8gbm90IHJlYWQgYXMgYSB2ZXJzaW9uIGlkKVxuICAgIC8vICAgZHRvL3NraWxsLmR0by50cyBTa2lsbFZlcnNpb25EdG8gICAgICAgICAgICAgICAgICAgICAgICAgICBcdTIxOTIgeyB2ZXJzaW9uLCBjcmVhdGVkRGF0ZSwgY3JlYXRlZEJ5LCBpc0N1cnJlbnQgfSAobm8gaWQpXG4gICAgLy8gICBwZXJzb25hL2Jhc2UuY29udHJvbGxlci50cyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFx1MjE5MiB7IHZlcnNpb246IG51bWJlciwgY3JlYXRlZERhdGUsIGlzQ3VycmVudCwgcGVyc29uYSB9IChubyBpZClcbiAgICBkZXNjcmlwdGlvbjogJ0xpc3QgdGhlIHNlcnZlci1zaWRlIHZlcnNpb25zIG9mIG9uZSBwcmltaXRpdmUgKHNraWxsLCB3ZWJob29rLCBqb2IsIHRyaWdnZXIsIHByZXByb2Nlc3NvciwgcG9zdHByb2Nlc3Nvciwgd29ya2Zsb3cpIG9yIHRoZSBhZ2VudCBwZXJzb25hLiBSZXR1cm5zIHsgYWN0aXZlVmVyc2lvbklkLCB2ZXJzaW9uczogW3t2ZXJzaW9uLCB2ZXJzaW9uSWQsIGFjdGl2ZSwgY3JlYXRlZEF0fV0gfSBcdTIwMTQgYGFjdGl2ZWAgaXMgdGhlIHZlcnNpb24gY3VycmVudGx5IGxpdmUuIGB2ZXJzaW9uSWRgIGlzIG51bGwgZm9yIHR5cGVzIHdob3NlIHZlcnNpb25zIHJvdXRlIGNhcnJpZXMgbm8gcGVyLWVudHJ5IGlkOiBza2lsbCwgcGVyc29uYSBhbmQgd2ViaG9vayAodGhlIHdlYmhvb2sgcm91dGUgZXhwb3NlcyB0aGUgcm93IGlkIG9ubHkgdW5kZXIgYSBtaXNuYW1lZCBgd2ViaG9va0lkYCBrZXkpLiBGb3IgdGhvc2UsIGlkZW50aWZ5IGEgdmVyc2lvbiBieSBgdmVyc2lvbmA7IGZvciB3ZWJob29rcyB0aGUgbGl2ZSByb3cgaWQgaXMgdGhlIHRvcC1sZXZlbCBgYWN0aXZlVmVyc2lvbklkYC4gYGFjdGl2ZVZlcnNpb25JZGAgaXMgcG9wdWxhdGVkIG9ubHkgZm9yIHdlYmhvb2ssIHRyaWdnZXIsIHByZXByb2Nlc3NvciBhbmQgcG9zdHByb2Nlc3NvciBlbnZlbG9wZXMgYW5kIGlzIG51bGwgZm9yIHNraWxsLCBqb2IsIHdvcmtmbG93IGFuZCBwZXJzb25hLicsXG4gICAgaW5wdXRTY2hlbWE6IHtcbiAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICBhZ2VudElkOiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gICAgICAgIHR5cGU6IHsgdHlwZTogJ3N0cmluZycsIGVudW06IFsuLi5WQUxJRF9UWVBFU10gfSxcbiAgICAgICAgbmFtZTogeyB0eXBlOiAnc3RyaW5nJywgZGVzY3JpcHRpb246ICdQcmltaXRpdmUgbmFtZSBhcyB3cml0dGVuIGluIGx1YS5za2lsbC55YW1sIChvbWl0IGZvciBwZXJzb25hIFx1MjAxNCBhbiBhZ2VudCBoYXMgb25seSBvbmUpJyB9LFxuICAgICAgfSxcbiAgICAgIHJlcXVpcmVkOiBbJ2FnZW50SWQnLCAndHlwZSddLFxuICAgIH0sXG4gIH0sXG4gIGFzeW5jIGhhbmRsZXIoeyBhZ2VudElkLCB0eXBlLCBuYW1lIH0sIGRlcHMgPSB7fSkge1xuICAgIGlmICghYWdlbnRJZCB8fCAhdHlwZSkgdGhyb3cgbmV3IEVycm9yKCdhZ2VudElkIGFuZCB0eXBlIGFyZSByZXF1aXJlZCcpO1xuICAgIGlmICghVkFMSURfVFlQRVMuaGFzKHR5cGUpKSB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgdHlwZTogJHt0eXBlfS4gVmFsaWQ6ICR7Wy4uLlZBTElEX1RZUEVTXS5qb2luKCcsICcpfWApO1xuICAgIGlmICh0eXBlICE9PSAncGVyc29uYScgJiYgIW5hbWUpIHRocm93IG5ldyBFcnJvcignbmFtZSBpcyByZXF1aXJlZCBmb3IgYWxsIHR5cGVzIGV4Y2VwdCBwZXJzb25hJyk7XG5cbiAgICAvLyBWZXJzaW9ucyBsaXZlIHVuZGVyIC9kZXZlbG9wZXIvPHBsdXJhbD4vOmFnZW50SWQvOmlkL3ZlcnNpb25zLCBFWENFUFRcbiAgICAvLyBwZXJzb25hIHdoaWNoIGxpdmVzIHVuZGVyIC9kZXZlbG9wZXIvYWdlbnRzLzphZ2VudElkL3BlcnNvbmEvdmVyc2lvbnNcbiAgICAvLyAobm8gOmlkKS4gVGhlIDppZCBzbG90IGlzIHRoZSBzZXJ2ZXIgaWQgKHNraWxsSWQgLyB3ZWJob29rSWQgLyAuLi4pLFxuICAgIC8vIG5ldmVyIHRoZSBuYW1lIFx1MjAxNCBzbyByZXNvbHZlIG5hbWUgXHUyMTkyIGlkIGJ5IGxpc3RpbmcgZmlyc3QuXG4gICAgbGV0IHBhdGg7XG4gICAgaWYgKHR5cGUgPT09ICdwZXJzb25hJykge1xuICAgICAgcGF0aCA9IGAvZGV2ZWxvcGVyL2FnZW50cy8ke2VuY29kZVVSSUNvbXBvbmVudChhZ2VudElkKX0vcGVyc29uYS92ZXJzaW9uc2A7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGlkID0gYXdhaXQgcmVzb2x2ZU5hbWVUb0lkKHsgYWdlbnRJZCwgdHlwZSwgbmFtZSwgZmV0Y2hGbjogZGVwcy5mZXRjaEZuIH0pO1xuICAgICAgcGF0aCA9IGAvZGV2ZWxvcGVyLyR7TElTVF9QQVRIU1t0eXBlXX0vJHtlbmNvZGVVUklDb21wb25lbnQoYWdlbnRJZCl9LyR7ZW5jb2RlVVJJQ29tcG9uZW50KGlkKX0vdmVyc2lvbnNgO1xuICAgIH1cblxuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBhcGlSZXF1ZXN0KHBhdGgsIHsgZmV0Y2hGbjogZGVwcy5mZXRjaEZuIH0pO1xuICAgIGNvbnN0IHZlcnNpb25zID0gZXh0cmFjdFZlcnNpb25zKHR5cGUsIGRhdGEpO1xuICAgIGNvbnN0IGNvbXBhY3QgPSB2ZXJzaW9ucy5tYXAoKHYpID0+ICh7XG4gICAgICB2ZXJzaW9uOiB2LnZlcnNpb24sXG4gICAgICB2ZXJzaW9uSWQ6IHZlcnNpb25JZCh2KSxcbiAgICAgIGFjdGl2ZTogaXNBY3RpdmVWZXJzaW9uKHR5cGUsIHYsIGRhdGEpLFxuICAgICAgY3JlYXRlZEF0OiB2ZXJzaW9uQ3JlYXRlZEF0KHYpLFxuICAgIH0pKTtcbiAgICBjb25zdCByZXN1bHQgPSB7IGFnZW50SWQsIHR5cGUsIG5hbWU6IHR5cGUgPT09ICdwZXJzb25hJyA/IG51bGwgOiBuYW1lLCBhY3RpdmVWZXJzaW9uSWQ6IGV4dHJhY3RBY3RpdmVWZXJzaW9uSWQoZGF0YSksIHZlcnNpb25zOiBjb21wYWN0IH07XG4gICAgcmV0dXJuIHsgY29udGVudDogW3sgdHlwZTogJ3RleHQnLCB0ZXh0OiBKU09OLnN0cmluZ2lmeShyZXN1bHQsIG51bGwsIDIpIH1dIH07XG4gIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlTmFtZVRvSWQoeyBhZ2VudElkLCB0eXBlLCBuYW1lLCBmZXRjaEZuIH0pIHtcbiAgY29uc3QgbGlzdFBhdGggPSBgL2RldmVsb3Blci8ke0xJU1RfUEFUSFNbdHlwZV19LyR7ZW5jb2RlVVJJQ29tcG9uZW50KGFnZW50SWQpfWA7XG4gIGNvbnN0IGxpc3RSZXNwb25zZSA9IGF3YWl0IGFwaVJlcXVlc3QobGlzdFBhdGgsIHsgZmV0Y2hGbiB9KTtcbiAgY29uc3QgaXRlbXMgPSBleHRyYWN0TGlzdCh0eXBlLCBsaXN0UmVzcG9uc2UpO1xuICBjb25zdCBtYXRjaCA9IGl0ZW1zLmZpbmQoKHApID0+IHAubmFtZSA9PT0gbmFtZSk7XG4gIGlmICghbWF0Y2gpIHtcbiAgICBjb25zdCBhdmFpbGFibGUgPSBpdGVtcy5tYXAoKHApID0+IHAubmFtZSkuZmlsdGVyKEJvb2xlYW4pLmpvaW4oJywgJykgfHwgJyhub25lKSc7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBsaXN0X3ByaW1pdGl2ZV92ZXJzaW9uczogbm8gJHt0eXBlfSBuYW1lZCBcIiR7bmFtZX1cIiBvbiBhZ2VudCAke2FnZW50SWR9LiBBdmFpbGFibGU6ICR7YXZhaWxhYmxlfWApO1xuICB9XG4gIGNvbnN0IGlkID0gbWF0Y2guaWQgPz8gbWF0Y2guX2lkO1xuICBpZiAoIWlkKSB0aHJvdyBuZXcgRXJyb3IoYGxpc3RfcHJpbWl0aXZlX3ZlcnNpb25zOiAke3R5cGV9IFwiJHtuYW1lfVwiIGV4aXN0cyBidXQgaGFzIG5vIGlkIGZpZWxkYCk7XG4gIHJldHVybiBpZDtcbn1cbiIsICJpbXBvcnQgeyBhcGlSZXF1ZXN0IH0gZnJvbSAnLi4vYXBpLWNsaWVudC5tanMnO1xuaW1wb3J0IHtcbiAgZXh0cmFjdExpc3QsXG4gIGV4dHJhY3RWZXJzaW9ucyxcbiAgZXh0cmFjdEFjdGl2ZVZlcnNpb25JZCxcbiAgaXNBY3RpdmVWZXJzaW9uLFxuICB2ZXJzaW9uQ3JlYXRlZEF0LFxuICB2ZXJzaW9uSWQsXG4gIExJU1RfUEFUSFMsXG59IGZyb20gJy4uL3Jlc3BvbnNlLXNoYXBlcy5tanMnO1xuXG4vLyBDb21wb3NlcyBcIndoYXQgaXMgbGl2ZVwiIGZyb20gdGhlIHBlci10eXBlIGx1YS1hcGkgbGlzdCArIHZlcnNpb25zIHJvdXRlcy5cbi8vIFRoZXJlIGlzIG5vIHNpbmdsZSBgL2FnZW50cy86aWQvcHJvZHVjdGlvbmAgcm91dGU7IGBsdWEgc3RhdHVzIC0tanNvbmBcbi8vIGdpdmVzIHRoZSBzYW1lIHBpY3R1cmUgZm9yIHRoZSBDVVJSRU5UIHByb2plY3QgKGxvY2FsIHZzIGRlcGxveWVkKSBhbmQgaXNcbi8vIHRoZSBiZXR0ZXIgdG9vbCB3aGVuIGEgbHVhLnNraWxsLnlhbWwgaXMgYXQgaGFuZC4gVGhpcyB0b29sIHdvcmtzIGZvciBhbnlcbi8vIGFnZW50IHRoZSBjcmVkZW50aWFsIGNhbiByZWFjaCwgcHJvamVjdCBvciBub3QuXG4vL1xuLy8gUGVyLXR5cGUgZW52ZWxvcGUgaGFuZGxpbmcgbGl2ZXMgaW4gcmVzcG9uc2Utc2hhcGVzLm1qcy5cbi8vXG4vLyBSZXF1ZXN0IGZhbi1vdXQgKDEgKyA3ICsgTiB2ZXJzaW9uIGxvb2t1cHMpIGlzIHBhcmFsbGVsaXNlZCBpbiB0d28gcGhhc2VzOlxuLy8gICAxLiB0aGUgcGVyc29uYSBjYWxsIGFuZCB0aGUgc2V2ZW4gbGlzdCBjYWxscyBydW4gdG9nZXRoZXI7XG4vLyAgIDIuIHBlciB0eXBlLCBpdGVtIHZlcnNpb24gbG9va3VwcyBydW4gaW4gY2h1bmtzIG9mIFZFUlNJT05TX0NIVU5LX1NJWkUuXG4vLyBPdXRwdXQgb3JkZXIgaXMgZGV0ZXJtaW5pc3RpYyByZWdhcmRsZXNzIG9mIGNvbXBsZXRpb24gb3JkZXI6IHR5cGVzIGluXG4vLyBQUklNSVRJVkVfVFlQRVMgb3JkZXIsIGl0ZW1zIGluIHRoZSBvcmRlciB0aGUgbGlzdCByb3V0ZSByZXR1cm5lZCB0aGVtLlxuLy8gQSB3YWxsLWNsb2NrIGJ1ZGdldCAoQlVER0VUX01TLCBpbmplY3RhYmxlIGFzIGRlcHMuYnVkZ2V0TXMpIHN0b3BzIE5FV1xuLy8gcmVxdWVzdHMgb25jZSBleGNlZWRlZDsgYWxyZWFkeS1pc3N1ZWQgcmVxdWVzdHMgc3RpbGwgY29tcGxldGUuIEl0ZW1zIHRoYXRcbi8vIGNvdWxkIG5vdCBiZSBsb29rZWQgdXAgYXJlIHN0aWxsIGxpc3RlZCwgd2l0aCBgZXJyb3I6IFwic2tpcHBlZDogXHUyMDI2XCJgLCBhbmRcbi8vIHRoZSByZXN1bHQgY2FycmllcyBgcGFydGlhbDogdHJ1ZWAgKyBgcGFydGlhbFJlYXNvbmAuXG5cbmNvbnN0IFBSSU1JVElWRV9UWVBFUyA9IFsnc2tpbGwnLCAnd2ViaG9vaycsICdqb2InLCAndHJpZ2dlcicsICdwcmVwcm9jZXNzb3InLCAncG9zdHByb2Nlc3NvcicsICd3b3JrZmxvdyddO1xuY29uc3QgVkVSU0lPTlNfQ0hVTktfU0laRSA9IDU7XG5jb25zdCBERUZBVUxUX0JVREdFVF9NUyA9IDQ1XzAwMDtcblxuZXhwb3J0IGNvbnN0IGdldERlcGxveW1lbnRTdGF0dXMgPSB7XG4gIHNwZWM6IHtcbiAgICBuYW1lOiAnZ2V0X2RlcGxveW1lbnRfc3RhdHVzJyxcbiAgICBkZXNjcmlwdGlvbjogJ1doYXQgaXMgbGl2ZSByaWdodCBub3cgZm9yIGFuIGFnZW50OiBmb3IgZXZlcnkgc2tpbGwsIHdlYmhvb2ssIGpvYiwgdHJpZ2dlciwgcHJlcHJvY2Vzc29yLCBwb3N0cHJvY2Vzc29yIGFuZCB3b3JrZmxvdyB0aGUgYWN0aXZlIChkZXBsb3llZCkgdmVyc2lvbiwgcGx1cyB0aGUgYWN0aXZlIHBlcnNvbmEgdmVyc2lvbi4gQ29tcG9zZWQgZnJvbSB0aGUgcGVyLXR5cGUgbHVhLWFwaSB2ZXJzaW9uIHJvdXRlcyAobGlzdCBjYWxscyBpbiBwYXJhbGxlbCwgdGhlbiBwZXItaXRlbSB2ZXJzaW9uIGxvb2t1cHMgaW4gY2h1bmtzIG9mIDUpLiBCb3VuZGVkIGJ5IGEgNDUgcyB3YWxsLWNsb2NrIGJ1ZGdldDogaWYgZXhjZWVkZWQsIHJlbWFpbmluZyBpdGVtcyBhcmUgbGlzdGVkIHdpdGggYGVycm9yOiBcInNraXBwZWQ6IFx1MjAyNlwiYCBhbmQgdGhlIHJlc3VsdCBjYXJyaWVzIGBwYXJ0aWFsOiB0cnVlYCArIGBwYXJ0aWFsUmVhc29uYC4gSW5zaWRlIGEgcHJvamVjdCwgYGx1YSBzdGF0dXMgLS1qc29uYCBhZGRpdGlvbmFsbHkgY29tcGFyZXMgbG9jYWwgdnMgZGVwbG95ZWQuJyxcbiAgICBpbnB1dFNjaGVtYToge1xuICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIGFnZW50SWQ6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgIH0sXG4gICAgICByZXF1aXJlZDogWydhZ2VudElkJ10sXG4gICAgfSxcbiAgfSxcbiAgYXN5bmMgaGFuZGxlcih7IGFnZW50SWQgfSwgZGVwcyA9IHt9KSB7XG4gICAgaWYgKCFhZ2VudElkKSB0aHJvdyBuZXcgRXJyb3IoJ2FnZW50SWQgaXMgcmVxdWlyZWQnKTtcbiAgICBjb25zdCBpZCA9IGVuY29kZVVSSUNvbXBvbmVudChhZ2VudElkKTtcbiAgICBjb25zdCBidWRnZXRNcyA9IE51bWJlci5pc0Zpbml0ZShkZXBzLmJ1ZGdldE1zKSA/IGRlcHMuYnVkZ2V0TXMgOiBERUZBVUxUX0JVREdFVF9NUztcbiAgICBjb25zdCBzdGFydGVkQXQgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IG92ZXJCdWRnZXQgPSAoKSA9PiBEYXRlLm5vdygpIC0gc3RhcnRlZEF0ID4gYnVkZ2V0TXM7XG4gICAgY29uc3QgZ2V0ID0gKHBhdGgpID0+IGFwaVJlcXVlc3QocGF0aCwgeyBmZXRjaEZuOiBkZXBzLmZldGNoRm4gfSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSB7IGFnZW50SWQsIHBlcnNvbmE6IG51bGwsIHByaW1pdGl2ZXM6IHt9IH07XG4gICAgLy8gU2VlZCBrZXlzIHVwIGZyb250IHNvIHRoZSBvdXRwdXQga2V5IG9yZGVyIG5ldmVyIGRlcGVuZHMgb24gdGltaW5nLlxuICAgIGZvciAoY29uc3QgdHlwZSBvZiBQUklNSVRJVkVfVFlQRVMpIHJlc3VsdC5wcmltaXRpdmVzW3R5cGVdID0gW107XG5cbiAgICAvLyBQaGFzZSAxOiBwZXJzb25hICsgZXZlcnkgbGlzdCByb3V0ZSwgYWxsIGluIGZsaWdodCBhdCBvbmNlLlxuICAgIC8vIFBlcnNvbmE6IG9uZSBwZXIgYWdlbnQsIHZlcnNpb25zIHVuZGVyIC9kZXZlbG9wZXIvYWdlbnRzLzphZ2VudElkL3BlcnNvbmEvdmVyc2lvbnMuXG4gICAgY29uc3QgW3BlcnNvbmFPdXRjb21lLCAuLi5saXN0T3V0Y29tZXNdID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFtcbiAgICAgIGdldChgL2RldmVsb3Blci9hZ2VudHMvJHtpZH0vcGVyc29uYS92ZXJzaW9uc2ApLFxuICAgICAgLi4uUFJJTUlUSVZFX1RZUEVTLm1hcCgodHlwZSkgPT4gZ2V0KGAvZGV2ZWxvcGVyLyR7TElTVF9QQVRIU1t0eXBlXX0vJHtpZH1gKSksXG4gICAgXSk7XG5cbiAgICBpZiAocGVyc29uYU91dGNvbWUuc3RhdHVzID09PSAnZnVsZmlsbGVkJykge1xuICAgICAgY29uc3QgcGVyc29uYVJlc3BvbnNlID0gcGVyc29uYU91dGNvbWUudmFsdWU7XG4gICAgICBjb25zdCB2ZXJzaW9ucyA9IGV4dHJhY3RWZXJzaW9ucygncGVyc29uYScsIHBlcnNvbmFSZXNwb25zZSk7XG4gICAgICBjb25zdCBhY3RpdmUgPSB2ZXJzaW9ucy5maW5kKCh2KSA9PiBpc0FjdGl2ZVZlcnNpb24oJ3BlcnNvbmEnLCB2LCBwZXJzb25hUmVzcG9uc2UpKSA/PyBudWxsO1xuICAgICAgcmVzdWx0LnBlcnNvbmEgPSB7XG4gICAgICAgIGFjdGl2ZVZlcnNpb246IGFjdGl2ZT8udmVyc2lvbiA/PyBudWxsLFxuICAgICAgICBhY3RpdmVWZXJzaW9uQ3JlYXRlZEF0OiB2ZXJzaW9uQ3JlYXRlZEF0KGFjdGl2ZSksXG4gICAgICAgIHZlcnNpb25Db3VudDogdmVyc2lvbnMubGVuZ3RoLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0LnBlcnNvbmEgPSB7IGVycm9yOiBwZXJzb25hT3V0Y29tZS5yZWFzb24/Lm1lc3NhZ2UgPz8gU3RyaW5nKHBlcnNvbmFPdXRjb21lLnJlYXNvbikgfTtcbiAgICB9XG5cbiAgICAvLyBQaGFzZSAyOiBwZXIgdHlwZSwgcmVzb2x2ZSBlYWNoIGl0ZW0ncyB2ZXJzaW9ucyBpbiBjaHVua3MuIFR5cGVzIGFyZVxuICAgIC8vIHZpc2l0ZWQgc2VxdWVudGlhbGx5IChjYW5vbmljYWwgb3JkZXIpOyB3aXRoaW4gYSB0eXBlIHVwIHRvXG4gICAgLy8gVkVSU0lPTlNfQ0hVTktfU0laRSBsb29rdXBzIGFyZSBpbiBmbGlnaHQgdG9nZXRoZXIuXG4gICAgbGV0IGJ1ZGdldEV4aGF1c3RlZCA9IGZhbHNlO1xuICAgIGxldCBza2lwcGVkID0gMDtcbiAgICBsZXQgdG90YWwgPSAwO1xuXG4gICAgZm9yIChsZXQgdCA9IDA7IHQgPCBQUklNSVRJVkVfVFlQRVMubGVuZ3RoOyB0KyspIHtcbiAgICAgIGNvbnN0IHR5cGUgPSBQUklNSVRJVkVfVFlQRVNbdF07XG4gICAgICBjb25zdCBwYXRoID0gTElTVF9QQVRIU1t0eXBlXTtcbiAgICAgIGNvbnN0IG91dGNvbWUgPSBsaXN0T3V0Y29tZXNbdF07XG4gICAgICBpZiAob3V0Y29tZS5zdGF0dXMgIT09ICdmdWxmaWxsZWQnKSB7XG4gICAgICAgIHJlc3VsdC5wcmltaXRpdmVzW3R5cGVdID0geyBlcnJvcjogb3V0Y29tZS5yZWFzb24/Lm1lc3NhZ2UgPz8gU3RyaW5nKG91dGNvbWUucmVhc29uKSB9O1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gVGhlIFVSTCBzbG90IGlzIHRoZSBzZXJ2ZXIgaWQgKDpza2lsbElkIC8gOndlYmhvb2tJZCAvIC4uLiksIG5ldmVyXG4gICAgICAvLyB0aGUgbmFtZS4gSXRlbXMgd2l0aG91dCBhbiBpZCBhcmUgZHJvcHBlZCwgYXMgYmVmb3JlLlxuICAgICAgY29uc3QgdGFyZ2V0cyA9IGV4dHJhY3RMaXN0KHR5cGUsIG91dGNvbWUudmFsdWUpXG4gICAgICAgIC5tYXAoKHApID0+ICh7IHAsIHByaW1JZDogcC5pZCA/PyBwLl9pZCwgbmFtZTogcC5uYW1lID8/IHAuaWQgPz8gcC5faWQgfSkpXG4gICAgICAgIC5maWx0ZXIoKHRndCkgPT4gdGd0LnByaW1JZCk7XG4gICAgICB0b3RhbCArPSB0YXJnZXRzLmxlbmd0aDtcblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0YXJnZXRzLmxlbmd0aDsgaSArPSBWRVJTSU9OU19DSFVOS19TSVpFKSB7XG4gICAgICAgIGNvbnN0IGNodW5rID0gdGFyZ2V0cy5zbGljZShpLCBpICsgVkVSU0lPTlNfQ0hVTktfU0laRSk7XG5cbiAgICAgICAgaWYgKGJ1ZGdldEV4aGF1c3RlZCB8fCBvdmVyQnVkZ2V0KCkpIHtcbiAgICAgICAgICBidWRnZXRFeGhhdXN0ZWQgPSB0cnVlO1xuICAgICAgICAgIHNraXBwZWQgKz0gY2h1bmsubGVuZ3RoO1xuICAgICAgICAgIGZvciAoY29uc3QgeyBuYW1lLCBwcmltSWQgfSBvZiBjaHVuaykge1xuICAgICAgICAgICAgcmVzdWx0LnByaW1pdGl2ZXNbdHlwZV0ucHVzaCh7XG4gICAgICAgICAgICAgIG5hbWUsIGlkOiBwcmltSWQsXG4gICAgICAgICAgICAgIGVycm9yOiBgc2tpcHBlZDogd2FsbC1jbG9jayBidWRnZXQgb2YgJHtidWRnZXRNc31tcyBleGhhdXN0ZWQgYmVmb3JlIHRoaXMgdmVyc2lvbiBsb29rdXAgd2FzIGlzc3VlZGAsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBvdXRjb21lcyA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcbiAgICAgICAgICBjaHVuay5tYXAoKHsgcHJpbUlkIH0pID0+IGdldChgL2RldmVsb3Blci8ke3BhdGh9LyR7aWR9LyR7ZW5jb2RlVVJJQ29tcG9uZW50KHByaW1JZCl9L3ZlcnNpb25zYCkpXG4gICAgICAgICk7XG5cbiAgICAgICAgb3V0Y29tZXMuZm9yRWFjaCgodm8sIGopID0+IHtcbiAgICAgICAgICBjb25zdCB7IHAsIHByaW1JZCwgbmFtZSB9ID0gY2h1bmtbal07XG4gICAgICAgICAgaWYgKHZvLnN0YXR1cyAhPT0gJ2Z1bGZpbGxlZCcpIHtcbiAgICAgICAgICAgIHJlc3VsdC5wcmltaXRpdmVzW3R5cGVdLnB1c2goeyBuYW1lLCBpZDogcHJpbUlkLCBlcnJvcjogdm8ucmVhc29uPy5tZXNzYWdlID8/IFN0cmluZyh2by5yZWFzb24pIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCB2ZXJzaW9uc1Jlc3BvbnNlID0gdm8udmFsdWU7XG4gICAgICAgICAgY29uc3QgdmVyc2lvbnMgPSBleHRyYWN0VmVyc2lvbnModHlwZSwgdmVyc2lvbnNSZXNwb25zZSk7XG4gICAgICAgICAgY29uc3QgYWN0aXZlID0gdmVyc2lvbnMuZmluZCgodikgPT4gaXNBY3RpdmVWZXJzaW9uKHR5cGUsIHYsIHZlcnNpb25zUmVzcG9uc2UpKSA/PyBudWxsO1xuXG4gICAgICAgICAgY29uc3QgZW50cnkgPSB7XG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgaWQ6IHByaW1JZCxcbiAgICAgICAgICAgIGFjdGl2ZVZlcnNpb246IGFjdGl2ZT8udmVyc2lvbiA/PyBudWxsLFxuICAgICAgICAgICAgYWN0aXZlVmVyc2lvbklkOiB2ZXJzaW9uSWQoYWN0aXZlKSA/PyBleHRyYWN0QWN0aXZlVmVyc2lvbklkKHZlcnNpb25zUmVzcG9uc2UpLFxuICAgICAgICAgICAgYWN0aXZlVmVyc2lvbkNyZWF0ZWRBdDogdmVyc2lvbkNyZWF0ZWRBdChhY3RpdmUpLFxuICAgICAgICAgICAgdmVyc2lvbkNvdW50OiB2ZXJzaW9ucy5sZW5ndGgsXG4gICAgICAgICAgfTtcbiAgICAgICAgICAvLyBSZWNvcmRzIHRoYXQgY2FycnkgdGhlaXIgb3duIGVuYWJsZWQvZGlzYWJsZWQgc3dpdGNoLlxuICAgICAgICAgIGlmICh0eXBlb2YgcC5hY3RpdmUgPT09ICdib29sZWFuJykgZW50cnkuZW5hYmxlZCA9IHAuYWN0aXZlO1xuICAgICAgICAgIGlmICh0eXBlID09PSAnd29ya2Zsb3cnICYmIHR5cGVvZiBwLmR5bmFtaWMgPT09ICdib29sZWFuJykgZW50cnkuZHluYW1pYyA9IHAuZHluYW1pYztcbiAgICAgICAgICByZXN1bHQucHJpbWl0aXZlc1t0eXBlXS5wdXNoKGVudHJ5KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHNraXBwZWQgPiAwKSB7XG4gICAgICByZXN1bHQucGFydGlhbCA9IHRydWU7XG4gICAgICByZXN1bHQucGFydGlhbFJlYXNvbiA9XG4gICAgICAgIGBXYWxsLWNsb2NrIGJ1ZGdldCBvZiAke2J1ZGdldE1zfW1zIGV4Y2VlZGVkIGFmdGVyICR7RGF0ZS5ub3coKSAtIHN0YXJ0ZWRBdH1tczsgYCArXG4gICAgICAgIGAke3NraXBwZWR9IG9mICR7dG90YWx9IHZlcnNpb24gbG9va3VwcyB3ZXJlIG5vdCBpc3N1ZWQgKGVudHJpZXMgY2FycnkgZXJyb3I6IFwic2tpcHBlZDogXHUyMDI2XCIpLmA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IFt7IHR5cGU6ICd0ZXh0JywgdGV4dDogSlNPTi5zdHJpbmdpZnkocmVzdWx0LCBudWxsLCAyKSB9XSxcbiAgICB9O1xuICB9LFxufTtcbiIsICJpbXBvcnQgeyBhcGlSZXF1ZXN0IH0gZnJvbSAnLi4vYXBpLWNsaWVudC5tanMnO1xuXG4vLyBUaGUgYGxvZ1NvdXJjZWAgZW51bSBsdWEtYXBpIGFjY2VwdHMgXHUyMDE0IEFHRU5UX0xPR19TT1VSQ0VTIGluXG4vLyBwYWNrYWdlcy9zaGFyZWQtdHlwZXMvc3JjL3ZtLWV4ZWN1dGlvbi1sb2cudHlwZXMudHMgKHRoZSBzaW5nbGUgc291cmNlIG9mXG4vLyB0cnV0aCBldmVyeSBzZXJ2aWNlIGltcG9ydHMpLiBgYWxsYCBpcyB0aGUgTUNQLXNpZGUgc2VudGluZWwgZm9yIFwibm9cbi8vIGZpbHRlclwiLiBOb3RlOiBgbHVhIGxvZ3MgLS10eXBlYCBhY2NlcHRzIGEgbmFycm93ZXIgbGlzdCBhbmQgbm8gYG1hc3RyYWAuXG5leHBvcnQgY29uc3QgTE9HX1NPVVJDRVMgPSBbXG4gICdza2lsbCcsICdqb2InLCAnd2ViaG9vaycsICd0cmlnZ2VyJywgJ3ByZXByb2Nlc3NvcicsICdwb3N0cHJvY2Vzc29yJyxcbiAgJ3VzZXJfbWVzc2FnZScsICdhZ2VudF9yZXNwb25zZScsICdhZ2VudF9lcnJvcicsICdydW50aW1lJywgJ21jcCcsICdyYWcnLFxuICAnZGV2aWNlJywgJ2RldmljZS10cmlnZ2VyJywgJ21vZGVsLXJlc29sdmVyJyxcbiAgJ3dvcmtmbG93LXN0ZXAnLCAnd29ya2Zsb3ctc2NyaXB0JywgJ3dvcmtmbG93Jyxcbl07XG5cbi8vIFRoZSBgbG9nVHlwZWAgcXVlcnkgcGFyYW0gXHUyMDE0IEdFVCAvZGV2ZWxvcGVyL2FnZW50cy86YWdlbnRJZC9sb2dzIHJlYWRzIGl0XG4vLyAoY29udHJvbGxlcnMvZGV2ZWxvcGVyL2Jhc2UuY29udHJvbGxlci50cykgYW5kIGRldmVsb3Blci5zZXJ2aWNlLnRzXG4vLyBnZXRBZ2VudExvZ3MgYXBwbGllcyBpdCB2ZXJiYXRpbSBhcyBgZmlsdGVyLnN1YlR5cGUgPSBsb2dUeXBlYC4gVGhlXG4vLyBhY2NlcHRlZCB2YWx1ZXMgYXJlIHRoZXJlZm9yZSB0aGUgVm1FeGVjdXRpb25Mb2cgYHN1YlR5cGVgIGVudW0gaW5cbi8vIHBhY2thZ2VzL3NoYXJlZC1zY2hlbWFzL3NyYy92bUV4ZWN1dGlvbkxvZ3Muc2NoZW1hLnRzOlxuLy8gICBlbnVtOiBbJ3N0YXJ0JywgJ2NvbXBsZXRlJywgJ2Vycm9yJywgJ2RlYnVnJywgJ3dhcm4nLCAnaW5mbyddXG4vLyAobWlycm9yZWQgYnkgbHVhLWNsaSdzIExvZ0VudHJ5LnN1YlR5cGUgaW4gc3JjL2ludGVyZmFjZXMvbG9ncy50cykuIEFueVxuLy8gb3RoZXIgc3RyaW5nIGlzIG5vdCByZWplY3RlZCBzZXJ2ZXItc2lkZSBcdTIwMTQgaXQgc2ltcGx5IG1hdGNoZXMgbm90aGluZy5cbmV4cG9ydCBjb25zdCBMT0dfVFlQRVMgPSBbJ2Vycm9yJywgJ3dhcm4nLCAnaW5mbycsICdkZWJ1ZycsICdzdGFydCcsICdjb21wbGV0ZSddO1xuXG5jb25zdCBWQUxJRF9UWVBFUyA9IG5ldyBTZXQoWydhbGwnLCAuLi5MT0dfU09VUkNFU10pO1xuY29uc3QgVkFMSURfTE9HX1RZUEVTID0gbmV3IFNldChMT0dfVFlQRVMpO1xuXG5leHBvcnQgY29uc3QgdGFpbExvZ3MgPSB7XG4gIHNwZWM6IHtcbiAgICBuYW1lOiAndGFpbF9sb2dzJyxcbiAgICBkZXNjcmlwdGlvbjogJ0ZldGNoIHJlY2VudCBleGVjdXRpb24gbG9ncyBmb3IgYW4gYWdlbnQgKHNhbWUgZGF0YSBhcyBgbHVhIGxvZ3MgLS1qc29uYCkuIFJldHVybnMgeyBsb2dzOiBMb2dFbnRyeVtdLCBwYWdpbmF0aW9uIH0uIEVhY2ggTG9nRW50cnkgaGFzIGBzdWJUeXBlYCAoZXJyb3IgfCB3YXJuIHwgaW5mbyB8IGRlYnVnIHwgc3RhcnQgfCBjb21wbGV0ZSksIGBtZXNzYWdlYCwgYHRpbWVzdGFtcGAsIGFuZCBgbWV0YWRhdGEubG9nU291cmNlYCAvIGBtZXRhZGF0YS5wcmltaXRpdmVOYW1lYCBcdTIwMTQgdGhlcmUgaXMgTk8gYGxldmVsYCBmaWVsZC4gRmlsdGVyIGJ5IHNvdXJjZSAoYHR5cGVgKSwgcHJpbWl0aXZlIChgbmFtZWApIGFuZC9vciBzZXZlcml0eSAoYGxvZ1R5cGVgLCB3aGljaCBmaWx0ZXJzIG9uIGBzdWJUeXBlYCkuJyxcbiAgICBpbnB1dFNjaGVtYToge1xuICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIGFnZW50SWQ6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICAgdHlwZToge1xuICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgIGVudW06IFsuLi5WQUxJRF9UWVBFU10sXG4gICAgICAgICAgZGVmYXVsdDogJ2FsbCcsXG4gICAgICAgICAgZGVzY3JpcHRpb246ICdMb2cgc291cmNlIGZpbHRlciAobWFwcyB0byBsdWEtYXBpIGBsb2dTb3VyY2VgKS4gYGFsbGAgPSBubyBmaWx0ZXIuJyxcbiAgICAgICAgfSxcbiAgICAgICAgbmFtZTogeyB0eXBlOiAnc3RyaW5nJywgZGVzY3JpcHRpb246ICdGaWx0ZXIgYnkgcHJpbWl0aXZlIG5hbWUgKG9wdGlvbmFsOyBtYXBzIHRvIGBwcmltaXRpdmVOYW1lYCknIH0sXG4gICAgICAgIGxvZ1R5cGU6IHtcbiAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICBlbnVtOiBMT0dfVFlQRVMsXG4gICAgICAgICAgZGVzY3JpcHRpb246ICdGaWx0ZXIgYnkgTG9nRW50cnkgYHN1YlR5cGVgIChvcHRpb25hbDsgbWFwcyB0byBsdWEtYXBpIGBsb2dUeXBlYCkuIE9taXQgZm9yIGV2ZXJ5IHNldmVyaXR5LiBlLmcuIGBlcnJvcmAgdG8gc2VlIG9ubHkgZmFpbHVyZXMuJyxcbiAgICAgICAgfSxcbiAgICAgICAgLy8gbHVhLWFwaSBjYXBzIGxpbWl0IGF0IDEwMCBzZXJ2ZXItc2lkZSAoTWF0aC5taW4oMTAwLCAuLi4pIGluXG4gICAgICAgIC8vIGNvbnRyb2xsZXJzL2RldmVsb3Blci9iYXNlLmNvbnRyb2xsZXIudHMpLiBNYXRjaCB0aGUgc2VydmVyIGNhcCBzb1xuICAgICAgICAvLyB0aGUgdG9vbCdzIGNvbnRyYWN0IGlzIGhvbmVzdC5cbiAgICAgICAgbGltaXQ6IHsgdHlwZTogJ251bWJlcicsIGRlZmF1bHQ6IDUwLCBtaW5pbXVtOiAxLCBtYXhpbXVtOiAxMDAgfSxcbiAgICAgICAgcGFnZTogeyB0eXBlOiAnbnVtYmVyJywgbWluaW11bTogMSwgZGVzY3JpcHRpb246ICdQYWdlIG51bWJlciBmb3IgcGFnaW5hdGlvbiAob3B0aW9uYWwpJyB9LFxuICAgICAgfSxcbiAgICAgIHJlcXVpcmVkOiBbJ2FnZW50SWQnXSxcbiAgICB9LFxuICB9LFxuICBhc3luYyBoYW5kbGVyKHsgYWdlbnRJZCwgdHlwZSA9ICdhbGwnLCBuYW1lLCBsb2dUeXBlLCBsaW1pdCA9IDUwLCBwYWdlIH0sIGRlcHMgPSB7fSkge1xuICAgIGlmICghYWdlbnRJZCkgdGhyb3cgbmV3IEVycm9yKCdhZ2VudElkIGlzIHJlcXVpcmVkJyk7XG4gICAgaWYgKCFWQUxJRF9UWVBFUy5oYXModHlwZSkpIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB0eXBlOiAke3R5cGV9LiBWYWxpZDogJHtbLi4uVkFMSURfVFlQRVNdLmpvaW4oJywgJyl9YCk7XG4gICAgaWYgKGxvZ1R5cGUgIT09IHVuZGVmaW5lZCAmJiAhVkFMSURfTE9HX1RZUEVTLmhhcyhsb2dUeXBlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGxvZ1R5cGU6ICR7bG9nVHlwZX0uIFZhbGlkOiAke0xPR19UWVBFUy5qb2luKCcsICcpfWApO1xuICAgIH1cbiAgICAvLyBEZWZlbnNpdmUgY2FwIG1hdGNoaW5nIHRoZSBzZXJ2ZXItc2lkZSBsaW1pdDsgcmVqZWN0cyBsb3VkIHJhdGhlclxuICAgIC8vIHRoYW4gc2lsZW50bHkgdHJ1bmNhdGluZy5cbiAgICBpZiAobGltaXQgPiAxMDApIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBsaW1pdDogJHtsaW1pdH0uIGx1YS1hcGkgY2FwcyBsb2dzIGF0IDEwMCBlbnRyaWVzIHBlciBjYWxsLmApO1xuICAgIC8vIFJvdXRlOiBHRVQgL2RldmVsb3Blci9hZ2VudHMvOmFnZW50SWQvbG9ncyAoY29udHJvbGxlcnMvZGV2ZWxvcGVyL2Jhc2UuY29udHJvbGxlci50cykuXG4gICAgLy8gUXVlcnkgcGFyYW1zIHRoZSBzZXJ2ZXIgcmVhZHM6IHBhZ2UsIGxpbWl0LCBzb3J0QnksIHNvcnRPcmRlciwgbG9nU291cmNlLFxuICAgIC8vIHByaW1pdGl2ZUlkLCBwcmltaXRpdmVOYW1lLCB0b29sSWQsIHRvb2xOYW1lLCBsb2dUeXBlLCB1c2VySWQuIFRoZVxuICAgIC8vIHR5cGUgZmlsdGVyIGlzIGBsb2dTb3VyY2VgIFx1MjAxNCBhIGBwcmltaXRpdmVUeXBlYCBwYXJhbSBpcyBzaWxlbnRseSBpZ25vcmVkLlxuICAgIGNvbnN0IHF1ZXJ5ID0geyBsaW1pdCB9O1xuICAgIGlmICh0eXBlICE9PSAnYWxsJykgcXVlcnkubG9nU291cmNlID0gdHlwZTtcbiAgICBpZiAobmFtZSkgcXVlcnkucHJpbWl0aXZlTmFtZSA9IG5hbWU7XG4gICAgaWYgKGxvZ1R5cGUpIHF1ZXJ5LmxvZ1R5cGUgPSBsb2dUeXBlO1xuICAgIGlmIChwYWdlKSBxdWVyeS5wYWdlID0gcGFnZTtcbiAgICBjb25zdCBkYXRhID0gYXdhaXQgYXBpUmVxdWVzdChcbiAgICAgIGAvZGV2ZWxvcGVyL2FnZW50cy8ke2VuY29kZVVSSUNvbXBvbmVudChhZ2VudElkKX0vbG9nc2AsXG4gICAgICB7IHF1ZXJ5LCBmZXRjaEZuOiBkZXBzLmZldGNoRm4gfVxuICAgICk7XG4gICAgcmV0dXJuIHsgY29udGVudDogW3sgdHlwZTogJ3RleHQnLCB0ZXh0OiBKU09OLnN0cmluZ2lmeShkYXRhLCBudWxsLCAyKSB9XSB9O1xuICB9LFxufTtcbiIsICIvLyBNQ1Agc3RkaW8gc2VydmVyIGJvb3RzdHJhcC4gUGVyIHRlY2ggc3BlYyBcdTAwQTc4LjEuXG5cbmltcG9ydCB7IFNlcnZlciB9IGZyb20gJ0Btb2RlbGNvbnRleHRwcm90b2NvbC9zZGsvc2VydmVyL2luZGV4LmpzJztcbmltcG9ydCB7IFN0ZGlvU2VydmVyVHJhbnNwb3J0IH0gZnJvbSAnQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zZXJ2ZXIvc3RkaW8uanMnO1xuaW1wb3J0IHtcbiAgQ2FsbFRvb2xSZXF1ZXN0U2NoZW1hLFxuICBMaXN0VG9vbHNSZXF1ZXN0U2NoZW1hLFxufSBmcm9tICdAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3R5cGVzLmpzJztcbmltcG9ydCAqIGFzIHRvb2xzIGZyb20gJy4vdG9vbHMvaW5kZXgubWpzJztcblxuY29uc3QgVE9PTF9SRUdJU1RSWSA9IE9iamVjdC52YWx1ZXModG9vbHMpO1xuXG5jb25zdCBzZXJ2ZXIgPSBuZXcgU2VydmVyKFxuICB7IG5hbWU6ICdsdWEtcGxhdGZvcm0nLCB2ZXJzaW9uOiAnMS42LjAnIH0sXG4gIHsgY2FwYWJpbGl0aWVzOiB7IHRvb2xzOiB7fSB9IH1cbik7XG5cbnNlcnZlci5zZXRSZXF1ZXN0SGFuZGxlcihMaXN0VG9vbHNSZXF1ZXN0U2NoZW1hLCBhc3luYyAoKSA9PiAoe1xuICB0b29sczogVE9PTF9SRUdJU1RSWS5tYXAoKHQpID0+IHQuc3BlYyksXG59KSk7XG5cbnNlcnZlci5zZXRSZXF1ZXN0SGFuZGxlcihDYWxsVG9vbFJlcXVlc3RTY2hlbWEsIGFzeW5jIChyZXEpID0+IHtcbiAgY29uc3QgdG9vbCA9IFRPT0xfUkVHSVNUUlkuZmluZCgodCkgPT4gdC5zcGVjLm5hbWUgPT09IHJlcS5wYXJhbXMubmFtZSk7XG4gIGlmICghdG9vbCkgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHRvb2w6ICR7cmVxLnBhcmFtcy5uYW1lfWApO1xuICB0cnkge1xuICAgIHJldHVybiBhd2FpdCB0b29sLmhhbmRsZXIocmVxLnBhcmFtcy5hcmd1bWVudHMgPz8ge30pO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogW3sgdHlwZTogJ3RleHQnLCB0ZXh0OiBgRXJyb3I6ICR7ZXJyLm1lc3NhZ2V9YCB9XSxcbiAgICAgIGlzRXJyb3I6IHRydWUsXG4gICAgfTtcbiAgfVxufSk7XG5cbi8vIFx1MDBBNzE5LjYgY3Jhc2ggcmVwb3J0aW5nIFx1MjAxNCBtdXN0IGxhbmQgQkVGT1JFIHByb2Nlc3MgZXhpdCBzbyB0aGUgZXZlbnQgcmVhY2hlc1xuLy8gdGVsZW1ldHJ5LiBXaW5kb3dzIGNhbiBkcm9wIHRoZSBsYXN0IHN0ZGVyciB3cml0ZSBpZiBwcm9jZXNzLmV4aXQgZmlyZXNcbi8vIHN5bmNocm9ub3VzbHkgYWZ0ZXIgaXQ7IHNhbWUgYnVnIGNsYXNzIGFzIGxpYi9ob29rLXJ1bnRpbWUubWpzJ3MgZXhpdCgpLlxuLy8gRXhpdCBvbmx5IGluc2lkZSB0aGUgd3JpdGUgY2FsbGJhY2sgc28gdGhlIGZsdXNoIGNvbXBsZXRlcy5cbmZ1bmN0aW9uIHJlcG9ydENyYXNoQW5kRXhpdChwYXlsb2FkKSB7XG4gIHByb2Nlc3Muc3RkZXJyLndyaXRlKEpTT04uc3RyaW5naWZ5KHBheWxvYWQpICsgJ1xcbicsICgpID0+IHByb2Nlc3MuZXhpdCgxKSk7XG59XG5cbnByb2Nlc3Mub24oJ3VuY2F1Z2h0RXhjZXB0aW9uJywgKGVycikgPT4ge1xuICByZXBvcnRDcmFzaEFuZEV4aXQoe1xuICAgIGV2ZW50OiAnbWNwX3NlcnZlcl9jcmFzaCcsXG4gICAga2luZDogJ3VuY2F1Z2h0RXhjZXB0aW9uJyxcbiAgICBtZXNzYWdlOiBlcnI/Lm1lc3NhZ2UsXG4gICAgc3RhY2s6IGVycj8uc3RhY2ssXG4gICAgcGx1Z2luX3ZlcnNpb246ICcxLjYuMCcsXG4gICAgbHVhX2NsaV92ZXJzaW9uOiBwcm9jZXNzLmVudi5MVUFfQ0xJX1ZFUlNJT04gPz8gbnVsbCxcbiAgICBwbGF0Zm9ybTogcHJvY2Vzcy5wbGF0Zm9ybSxcbiAgICB0czogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICB9KTtcbn0pO1xuXG5wcm9jZXNzLm9uKCd1bmhhbmRsZWRSZWplY3Rpb24nLCAocmVhc29uKSA9PiB7XG4gIHJlcG9ydENyYXNoQW5kRXhpdCh7XG4gICAgZXZlbnQ6ICdtY3Bfc2VydmVyX2NyYXNoJyxcbiAgICBraW5kOiAndW5oYW5kbGVkUmVqZWN0aW9uJyxcbiAgICByZWFzb246IFN0cmluZyhyZWFzb24pLFxuICAgIHN0YWNrOiAvKiogQHR5cGUge2FueX0gKi8gKHJlYXNvbik/LnN0YWNrLFxuICAgIHBsdWdpbl92ZXJzaW9uOiAnMS42LjAnLFxuICAgIGx1YV9jbGlfdmVyc2lvbjogcHJvY2Vzcy5lbnYuTFVBX0NMSV9WRVJTSU9OID8/IG51bGwsXG4gICAgcGxhdGZvcm06IHByb2Nlc3MucGxhdGZvcm0sXG4gICAgdHM6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgfSk7XG59KTtcblxu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LElBQUksaUJBQW1CLEtBQ2hELFNBQVUsUUFBUSxTQUNsQixHQUFJLElBQUksS0FBSyxFQUFFLFlBQVksQ0FDN0IsQ0FBQyxDQUNILENBQUMsRUFFRCxNQUFNVixHQUFPLFFBQVEsSUFBSVcsRUFBc0IiLAogICJuYW1lcyI6IFsiZXh0ZXJuYWxfZXhwb3J0cyIsICJfX2V4cG9ydCIsICJCUkFORCIsICJESVJUWSIsICJFTVBUWV9QQVRIIiwgIklOVkFMSUQiLCAiTkVWRVIiLCAiT0siLCAiUGFyc2VTdGF0dXMiLCAiWm9kVHlwZSIsICJab2RBbnkiLCAiWm9kQXJyYXkiLCAiWm9kQmlnSW50IiwgIlpvZEJvb2xlYW4iLCAiWm9kQnJhbmRlZCIsICJab2RDYXRjaCIsICJab2REYXRlIiwgIlpvZERlZmF1bHQiLCAiWm9kRGlzY3JpbWluYXRlZFVuaW9uIiwgIlpvZEVmZmVjdHMiLCAiWm9kRW51bSIsICJab2RFcnJvciIsICJab2RGaXJzdFBhcnR5VHlwZUtpbmQiLCAiWm9kRnVuY3Rpb24iLCAiWm9kSW50ZXJzZWN0aW9uIiwgIlpvZElzc3VlQ29kZSIsICJab2RMYXp5IiwgIlpvZExpdGVyYWwiLCAiWm9kTWFwIiwgIlpvZE5hTiIsICJab2ROYXRpdmVFbnVtIiwgIlpvZE5ldmVyIiwgIlpvZE51bGwiLCAiWm9kTnVsbGFibGUiLCAiWm9kTnVtYmVyIiwgIlpvZE9iamVjdCIsICJab2RPcHRpb25hbCIsICJab2RQYXJzZWRUeXBlIiwgIlpvZFBpcGVsaW5lIiwgIlpvZFByb21pc2UiLCAiWm9kUmVhZG9ubHkiLCAiWm9kUmVjb3JkIiwgIlpvZFNldCIsICJab2RTdHJpbmciLCAiWm9kU3ltYm9sIiwgIlpvZFR1cGxlIiwgIlpvZFVuZGVmaW5lZCIsICJab2RVbmlvbiIsICJab2RVbmtub3duIiwgIlpvZFZvaWQiLCAiYWRkSXNzdWVUb0NvbnRleHQiLCAiYW55VHlwZSIsICJhcnJheVR5cGUiLCAiYmlnSW50VHlwZSIsICJib29sZWFuVHlwZSIsICJjb2VyY2UiLCAiY3VzdG9tIiwgImRhdGVUeXBlIiwgImRhdGV0aW1lUmVnZXgiLCAiZW5fZGVmYXVsdCIsICJkaXNjcmltaW5hdGVkVW5pb25UeXBlIiwgImVmZmVjdHNUeXBlIiwgImVudW1UeXBlIiwgImZ1bmN0aW9uVHlwZSIsICJnZXRFcnJvck1hcCIsICJnZXRQYXJzZWRUeXBlIiwgImluc3RhbmNlT2ZUeXBlIiwgImludGVyc2VjdGlvblR5cGUiLCAiaXNBYm9ydGVkIiwgImlzQXN5bmMiLCAiaXNEaXJ0eSIsICJpc1ZhbGlkIiwgImxhdGUiLCAibGF6eVR5cGUiLCAibGl0ZXJhbFR5cGUiLCAibWFrZUlzc3VlIiwgIm1hcFR5cGUiLCAibmFuVHlwZSIsICJuYXRpdmVFbnVtVHlwZSIsICJuZXZlclR5cGUiLCAibnVsbFR5cGUiLCAibnVsbGFibGVUeXBlIiwgIm51bWJlclR5cGUiLCAib2JqZWN0VHlwZSIsICJvYmplY3RVdGlsIiwgIm9ib29sZWFuIiwgIm9udW1iZXIiLCAib3B0aW9uYWxUeXBlIiwgIm9zdHJpbmciLCAicGlwZWxpbmVUeXBlIiwgInByZXByb2Nlc3NUeXBlIiwgInByb21pc2VUeXBlIiwgInF1b3RlbGVzc0pzb24iLCAicmVjb3JkVHlwZSIsICJzZXRUeXBlIiwgInNldEVycm9yTWFwIiwgInN0cmljdE9iamVjdFR5cGUiLCAic3RyaW5nVHlwZSIsICJzeW1ib2xUeXBlIiwgInR1cGxlVHlwZSIsICJ1bmRlZmluZWRUeXBlIiwgInVuaW9uVHlwZSIsICJ1bmtub3duVHlwZSIsICJ1dGlsIiwgInZvaWRUeXBlIiwgInV0aWwiLCAiXyIsICJhc3NlcnRJcyIsICJfYXJnIiwgImFzc2VydE5ldmVyIiwgIl94IiwgIml0ZW1zIiwgIm9iaiIsICJpdGVtIiwgInZhbGlkS2V5cyIsICJrIiwgImZpbHRlcmVkIiwgImUiLCAib2JqZWN0IiwgImtleXMiLCAia2V5IiwgImFyciIsICJjaGVja2VyIiwgInZhbCIsICJqb2luVmFsdWVzIiwgImFycmF5IiwgInNlcGFyYXRvciIsICJ2YWx1ZSIsICJvYmplY3RVdGlsIiwgImZpcnN0IiwgInNlY29uZCIsICJab2RQYXJzZWRUeXBlIiwgImdldFBhcnNlZFR5cGUiLCAiZGF0YSIsICJab2RJc3N1ZUNvZGUiLCAidXRpbCIsICJxdW90ZWxlc3NKc29uIiwgIm9iaiIsICJab2RFcnJvciIsICJfWm9kRXJyb3IiLCAiaXNzdWVzIiwgInN1YiIsICJzdWJzIiwgImFjdHVhbFByb3RvIiwgIl9tYXBwZXIiLCAibWFwcGVyIiwgImlzc3VlIiwgImZpZWxkRXJyb3JzIiwgInByb2Nlc3NFcnJvciIsICJlcnJvciIsICJjdXJyIiwgImkiLCAiZWwiLCAidmFsdWUiLCAiZm9ybUVycm9ycyIsICJmaXJzdEVsIiwgImVycm9yTWFwIiwgImlzc3VlIiwgIl9jdHgiLCAibWVzc2FnZSIsICJab2RJc3N1ZUNvZGUiLCAiWm9kUGFyc2VkVHlwZSIsICJ1dGlsIiwgImVuX2RlZmF1bHQiLCAib3ZlcnJpZGVFcnJvck1hcCIsICJlbl9kZWZhdWx0IiwgInNldEVycm9yTWFwIiwgIm1hcCIsICJvdmVycmlkZUVycm9yTWFwIiwgImdldEVycm9yTWFwIiwgIm1ha2VJc3N1ZSIsICJwYXJhbXMiLCAiZGF0YSIsICJwYXRoIiwgImVycm9yTWFwcyIsICJpc3N1ZURhdGEiLCAiZnVsbFBhdGgiLCAiZnVsbElzc3VlIiwgImVycm9yTWVzc2FnZSIsICJtYXBzIiwgIm0iLCAibWFwIiwgIkVNUFRZX1BBVEgiLCAiYWRkSXNzdWVUb0NvbnRleHQiLCAiY3R4IiwgIm92ZXJyaWRlTWFwIiwgImdldEVycm9yTWFwIiwgImlzc3VlIiwgImVuX2RlZmF1bHQiLCAieCIsICJQYXJzZVN0YXR1cyIsICJfUGFyc2VTdGF0dXMiLCAic3RhdHVzIiwgInJlc3VsdHMiLCAiYXJyYXlWYWx1ZSIsICJzIiwgIklOVkFMSUQiLCAicGFpcnMiLCAic3luY1BhaXJzIiwgInBhaXIiLCAia2V5IiwgInZhbHVlIiwgImZpbmFsT2JqZWN0IiwgIkRJUlRZIiwgIk9LIiwgImlzQWJvcnRlZCIsICJpc0RpcnR5IiwgImlzVmFsaWQiLCAiaXNBc3luYyIsICJlcnJvclV0aWwiLCAibWVzc2FnZSIsICJQYXJzZUlucHV0TGF6eVBhdGgiLCAicGFyZW50IiwgInZhbHVlIiwgInBhdGgiLCAia2V5IiwgImhhbmRsZVJlc3VsdCIsICJjdHgiLCAicmVzdWx0IiwgImlzVmFsaWQiLCAiZXJyb3IiLCAiWm9kRXJyb3IiLCAicHJvY2Vzc0NyZWF0ZVBhcmFtcyIsICJwYXJhbXMiLCAiZXJyb3JNYXAiLCAiaW52YWxpZF90eXBlX2Vycm9yIiwgInJlcXVpcmVkX2Vycm9yIiwgImRlc2NyaXB0aW9uIiwgImlzcyIsICJtZXNzYWdlIiwgIlpvZFR5cGUiLCAiaW5wdXQiLCAiZ2V0UGFyc2VkVHlwZSIsICJQYXJzZVN0YXR1cyIsICJpc0FzeW5jIiwgImRhdGEiLCAiZXJyIiwgIm1heWJlQXN5bmNSZXN1bHQiLCAiY2hlY2siLCAiZ2V0SXNzdWVQcm9wZXJ0aWVzIiwgInZhbCIsICJzZXRFcnJvciIsICJab2RJc3N1ZUNvZGUiLCAicmVmaW5lbWVudERhdGEiLCAicmVmaW5lbWVudCIsICJab2RFZmZlY3RzIiwgIlpvZEZpcnN0UGFydHlUeXBlS2luZCIsICJkZWYiLCAiWm9kT3B0aW9uYWwiLCAiWm9kTnVsbGFibGUiLCAiWm9kQXJyYXkiLCAiWm9kUHJvbWlzZSIsICJvcHRpb24iLCAiWm9kVW5pb24iLCAiaW5jb21pbmciLCAiWm9kSW50ZXJzZWN0aW9uIiwgInRyYW5zZm9ybSIsICJkZWZhdWx0VmFsdWVGdW5jIiwgIlpvZERlZmF1bHQiLCAiWm9kQnJhbmRlZCIsICJjYXRjaFZhbHVlRnVuYyIsICJab2RDYXRjaCIsICJUaGlzIiwgInRhcmdldCIsICJab2RQaXBlbGluZSIsICJab2RSZWFkb25seSIsICJjdWlkUmVnZXgiLCAiY3VpZDJSZWdleCIsICJ1bGlkUmVnZXgiLCAidXVpZFJlZ2V4IiwgIm5hbm9pZFJlZ2V4IiwgImp3dFJlZ2V4IiwgImR1cmF0aW9uUmVnZXgiLCAiZW1haWxSZWdleCIsICJfZW1vamlSZWdleCIsICJlbW9qaVJlZ2V4IiwgImlwdjRSZWdleCIsICJpcHY0Q2lkclJlZ2V4IiwgImlwdjZSZWdleCIsICJpcHY2Q2lkclJlZ2V4IiwgImJhc2U2NFJlZ2V4IiwgImJhc2U2NHVybFJlZ2V4IiwgImRhdGVSZWdleFNvdXJjZSIsICJkYXRlUmVnZXgiLCAidGltZVJlZ2V4U291cmNlIiwgImFyZ3MiLCAic2Vjb25kc1JlZ2V4U291cmNlIiwgInNlY29uZHNRdWFudGlmaWVyIiwgInRpbWVSZWdleCIsICJkYXRldGltZVJlZ2V4IiwgInJlZ2V4IiwgIm9wdHMiLCAiaXNWYWxpZElQIiwgImlwIiwgInZlcnNpb24iLCAiaXNWYWxpZEpXVCIsICJqd3QiLCAiYWxnIiwgImhlYWRlciIsICJiYXNlNjQiLCAiZGVjb2RlZCIsICJpc1ZhbGlkQ2lkciIsICJab2RTdHJpbmciLCAiX1pvZFN0cmluZyIsICJab2RQYXJzZWRUeXBlIiwgImFkZElzc3VlVG9Db250ZXh0IiwgIklOVkFMSUQiLCAic3RhdHVzIiwgInRvb0JpZyIsICJ0b29TbWFsbCIsICJ1dGlsIiwgInZhbGlkYXRpb24iLCAiZXJyb3JVdGlsIiwgIm9wdGlvbnMiLCAibWluTGVuZ3RoIiwgIm1heExlbmd0aCIsICJsZW4iLCAiY2giLCAibWluIiwgIm1heCIsICJmbG9hdFNhZmVSZW1haW5kZXIiLCAic3RlcCIsICJ2YWxEZWNDb3VudCIsICJzdGVwRGVjQ291bnQiLCAiZGVjQ291bnQiLCAidmFsSW50IiwgInN0ZXBJbnQiLCAiWm9kTnVtYmVyIiwgIl9ab2ROdW1iZXIiLCAia2luZCIsICJpbmNsdXNpdmUiLCAiWm9kQmlnSW50IiwgIl9ab2RCaWdJbnQiLCAiWm9kQm9vbGVhbiIsICJPSyIsICJab2REYXRlIiwgIl9ab2REYXRlIiwgIm1pbkRhdGUiLCAibWF4RGF0ZSIsICJab2RTeW1ib2wiLCAiWm9kVW5kZWZpbmVkIiwgIlpvZE51bGwiLCAiWm9kQW55IiwgIlpvZFVua25vd24iLCAiWm9kTmV2ZXIiLCAiWm9kVm9pZCIsICJfWm9kQXJyYXkiLCAiaXRlbSIsICJpIiwgInNjaGVtYSIsICJkZWVwUGFydGlhbGlmeSIsICJab2RPYmplY3QiLCAibmV3U2hhcGUiLCAiZmllbGRTY2hlbWEiLCAiWm9kVHVwbGUiLCAiX1pvZE9iamVjdCIsICJzaGFwZSIsICJrZXlzIiwgInNoYXBlS2V5cyIsICJleHRyYUtleXMiLCAicGFpcnMiLCAia2V5VmFsaWRhdG9yIiwgInVua25vd25LZXlzIiwgImNhdGNoYWxsIiwgInN5bmNQYWlycyIsICJwYWlyIiwgImlzc3VlIiwgImRlZmF1bHRFcnJvciIsICJhdWdtZW50YXRpb24iLCAibWVyZ2luZyIsICJpbmRleCIsICJtYXNrIiwgIm5ld0ZpZWxkIiwgImNyZWF0ZVpvZEVudW0iLCAiaGFuZGxlUmVzdWx0cyIsICJyZXN1bHRzIiwgInVuaW9uRXJyb3JzIiwgImNoaWxkQ3R4IiwgImRpcnR5IiwgImlzc3VlcyIsICJ0eXBlcyIsICJnZXREaXNjcmltaW5hdG9yIiwgInR5cGUiLCAiWm9kTGF6eSIsICJab2RMaXRlcmFsIiwgIlpvZEVudW0iLCAiWm9kTmF0aXZlRW51bSIsICJab2REaXNjcmltaW5hdGVkVW5pb24iLCAiX1pvZERpc2NyaW1pbmF0ZWRVbmlvbiIsICJkaXNjcmltaW5hdG9yIiwgImRpc2NyaW1pbmF0b3JWYWx1ZSIsICJvcHRpb25zTWFwIiwgImRpc2NyaW1pbmF0b3JWYWx1ZXMiLCAibWVyZ2VWYWx1ZXMiLCAiYSIsICJiIiwgImFUeXBlIiwgImJUeXBlIiwgImJLZXlzIiwgInNoYXJlZEtleXMiLCAibmV3T2JqIiwgInNoYXJlZFZhbHVlIiwgIm5ld0FycmF5IiwgIml0ZW1BIiwgIml0ZW1CIiwgImhhbmRsZVBhcnNlZCIsICJwYXJzZWRMZWZ0IiwgInBhcnNlZFJpZ2h0IiwgImlzQWJvcnRlZCIsICJtZXJnZWQiLCAiaXNEaXJ0eSIsICJsZWZ0IiwgInJpZ2h0IiwgIl9ab2RUdXBsZSIsICJpdGVtcyIsICJpdGVtSW5kZXgiLCAieCIsICJyZXN0IiwgInNjaGVtYXMiLCAiWm9kUmVjb3JkIiwgIl9ab2RSZWNvcmQiLCAia2V5VHlwZSIsICJ2YWx1ZVR5cGUiLCAiZmlyc3QiLCAic2Vjb25kIiwgInRoaXJkIiwgIlpvZE1hcCIsICJmaW5hbE1hcCIsICJab2RTZXQiLCAiX1pvZFNldCIsICJmaW5hbGl6ZVNldCIsICJlbGVtZW50cyIsICJwYXJzZWRTZXQiLCAiZWxlbWVudCIsICJtaW5TaXplIiwgIm1heFNpemUiLCAic2l6ZSIsICJab2RGdW5jdGlvbiIsICJfWm9kRnVuY3Rpb24iLCAibWFrZUFyZ3NJc3N1ZSIsICJtYWtlSXNzdWUiLCAiZ2V0RXJyb3JNYXAiLCAiZW5fZGVmYXVsdCIsICJtYWtlUmV0dXJuc0lzc3VlIiwgInJldHVybnMiLCAiZm4iLCAibWUiLCAicGFyc2VkQXJncyIsICJlIiwgInBhcnNlZFJldHVybnMiLCAicmV0dXJuVHlwZSIsICJmdW5jIiwgImdldHRlciIsICJ2YWx1ZXMiLCAiX1pvZEVudW0iLCAiZXhwZWN0ZWRWYWx1ZXMiLCAiZW51bVZhbHVlcyIsICJuZXdEZWYiLCAib3B0IiwgIm5hdGl2ZUVudW1WYWx1ZXMiLCAicHJvbWlzaWZpZWQiLCAiZWZmZWN0IiwgImNoZWNrQ3R4IiwgImFyZyIsICJwcm9jZXNzZWQiLCAiRElSVFkiLCAiZXhlY3V0ZVJlZmluZW1lbnQiLCAiYWNjIiwgImlubmVyIiwgImJhc2UiLCAicHJlcHJvY2VzcyIsICJab2RPcHRpb25hbCIsICJab2RUeXBlIiwgImlucHV0IiwgIlpvZFBhcnNlZFR5cGUiLCAiT0siLCAidHlwZSIsICJwYXJhbXMiLCAiWm9kRmlyc3RQYXJ0eVR5cGVLaW5kIiwgInByb2Nlc3NDcmVhdGVQYXJhbXMiLCAiWm9kTnVsbGFibGUiLCAiWm9kRGVmYXVsdCIsICJjdHgiLCAiZGF0YSIsICJab2RDYXRjaCIsICJuZXdDdHgiLCAicmVzdWx0IiwgImlzQXN5bmMiLCAiWm9kRXJyb3IiLCAiWm9kTmFOIiwgImFkZElzc3VlVG9Db250ZXh0IiwgIlpvZElzc3VlQ29kZSIsICJJTlZBTElEIiwgIkJSQU5EIiwgIlpvZEJyYW5kZWQiLCAiWm9kUGlwZWxpbmUiLCAiX1pvZFBpcGVsaW5lIiwgInN0YXR1cyIsICJpblJlc3VsdCIsICJESVJUWSIsICJhIiwgImIiLCAiWm9kUmVhZG9ubHkiLCAiZnJlZXplIiwgImlzVmFsaWQiLCAiY2xlYW5QYXJhbXMiLCAicCIsICJjdXN0b20iLCAiY2hlY2siLCAiX3BhcmFtcyIsICJmYXRhbCIsICJab2RBbnkiLCAiciIsICJfZmF0YWwiLCAibGF0ZSIsICJab2RPYmplY3QiLCAiWm9kRmlyc3RQYXJ0eVR5cGVLaW5kIiwgImluc3RhbmNlT2ZUeXBlIiwgImNscyIsICJwYXJhbXMiLCAiY3VzdG9tIiwgImRhdGEiLCAic3RyaW5nVHlwZSIsICJab2RTdHJpbmciLCAibnVtYmVyVHlwZSIsICJab2ROdW1iZXIiLCAibmFuVHlwZSIsICJab2ROYU4iLCAiYmlnSW50VHlwZSIsICJab2RCaWdJbnQiLCAiYm9vbGVhblR5cGUiLCAiWm9kQm9vbGVhbiIsICJkYXRlVHlwZSIsICJab2REYXRlIiwgInN5bWJvbFR5cGUiLCAiWm9kU3ltYm9sIiwgInVuZGVmaW5lZFR5cGUiLCAiWm9kVW5kZWZpbmVkIiwgIm51bGxUeXBlIiwgIlpvZE51bGwiLCAiYW55VHlwZSIsICJab2RBbnkiLCAidW5rbm93blR5cGUiLCAiWm9kVW5rbm93biIsICJuZXZlclR5cGUiLCAiWm9kTmV2ZXIiLCAidm9pZFR5cGUiLCAiWm9kVm9pZCIsICJhcnJheVR5cGUiLCAiWm9kQXJyYXkiLCAib2JqZWN0VHlwZSIsICJab2RPYmplY3QiLCAic3RyaWN0T2JqZWN0VHlwZSIsICJ1bmlvblR5cGUiLCAiWm9kVW5pb24iLCAiZGlzY3JpbWluYXRlZFVuaW9uVHlwZSIsICJab2REaXNjcmltaW5hdGVkVW5pb24iLCAiaW50ZXJzZWN0aW9uVHlwZSIsICJab2RJbnRlcnNlY3Rpb24iLCAidHVwbGVUeXBlIiwgIlpvZFR1cGxlIiwgInJlY29yZFR5cGUiLCAiWm9kUmVjb3JkIiwgIm1hcFR5cGUiLCAiWm9kTWFwIiwgInNldFR5cGUiLCAiWm9kU2V0IiwgImZ1bmN0aW9uVHlwZSIsICJab2RGdW5jdGlvbiIsICJsYXp5VHlwZSIsICJab2RMYXp5IiwgImxpdGVyYWxUeXBlIiwgIlpvZExpdGVyYWwiLCAiZW51bVR5cGUiLCAiWm9kRW51bSIsICJuYXRpdmVFbnVtVHlwZSIsICJab2ROYXRpdmVFbnVtIiwgInByb21pc2VUeXBlIiwgIlpvZFByb21pc2UiLCAiZWZmZWN0c1R5cGUiLCAiWm9kRWZmZWN0cyIsICJvcHRpb25hbFR5cGUiLCAiWm9kT3B0aW9uYWwiLCAibnVsbGFibGVUeXBlIiwgIlpvZE51bGxhYmxlIiwgInByZXByb2Nlc3NUeXBlIiwgInBpcGVsaW5lVHlwZSIsICJab2RQaXBlbGluZSIsICJvc3RyaW5nIiwgIm9udW1iZXIiLCAib2Jvb2xlYW4iLCAiY29lcmNlIiwgImFyZyIsICJORVZFUiIsICJJTlZBTElEIiwgIkxBVEVTVF9QUk9UT0NPTF9WRVJTSU9OIiwgIlNVUFBPUlRFRF9QUk9UT0NPTF9WRVJTSU9OUyIsICJKU09OUlBDX1ZFUlNJT04iLCAiUHJvZ3Jlc3NUb2tlblNjaGVtYSIsICJleHRlcm5hbF9leHBvcnRzIiwgIkN1cnNvclNjaGVtYSIsICJCYXNlUmVxdWVzdFBhcmFtc1NjaGVtYSIsICJSZXF1ZXN0U2NoZW1hIiwgIkJhc2VOb3RpZmljYXRpb25QYXJhbXNTY2hlbWEiLCAiTm90aWZpY2F0aW9uU2NoZW1hIiwgIlJlc3VsdFNjaGVtYSIsICJSZXF1ZXN0SWRTY2hlbWEiLCAiSlNPTlJQQ1JlcXVlc3RTY2hlbWEiLCAiSlNPTlJQQ05vdGlmaWNhdGlvblNjaGVtYSIsICJKU09OUlBDUmVzcG9uc2VTY2hlbWEiLCAiRXJyb3JDb2RlIiwgIkpTT05SUENFcnJvclNjaGVtYSIsICJKU09OUlBDTWVzc2FnZVNjaGVtYSIsICJFbXB0eVJlc3VsdFNjaGVtYSIsICJDYW5jZWxsZWROb3RpZmljYXRpb25TY2hlbWEiLCAiSW1wbGVtZW50YXRpb25TY2hlbWEiLCAiQ2xpZW50Q2FwYWJpbGl0aWVzU2NoZW1hIiwgIkluaXRpYWxpemVSZXF1ZXN0U2NoZW1hIiwgIlNlcnZlckNhcGFiaWxpdGllc1NjaGVtYSIsICJJbml0aWFsaXplUmVzdWx0U2NoZW1hIiwgIkluaXRpYWxpemVkTm90aWZpY2F0aW9uU2NoZW1hIiwgIlBpbmdSZXF1ZXN0U2NoZW1hIiwgIlByb2dyZXNzU2NoZW1hIiwgIlByb2dyZXNzTm90aWZpY2F0aW9uU2NoZW1hIiwgIlBhZ2luYXRlZFJlcXVlc3RTY2hlbWEiLCAiUGFnaW5hdGVkUmVzdWx0U2NoZW1hIiwgIlJlc291cmNlQ29udGVudHNTY2hlbWEiLCAiVGV4dFJlc291cmNlQ29udGVudHNTY2hlbWEiLCAiQmxvYlJlc291cmNlQ29udGVudHNTY2hlbWEiLCAiUmVzb3VyY2VTY2hlbWEiLCAiUmVzb3VyY2VUZW1wbGF0ZVNjaGVtYSIsICJMaXN0UmVzb3VyY2VzUmVxdWVzdFNjaGVtYSIsICJMaXN0UmVzb3VyY2VzUmVzdWx0U2NoZW1hIiwgIkxpc3RSZXNvdXJjZVRlbXBsYXRlc1JlcXVlc3RTY2hlbWEiLCAiTGlzdFJlc291cmNlVGVtcGxhdGVzUmVzdWx0U2NoZW1hIiwgIlJlYWRSZXNvdXJjZVJlcXVlc3RTY2hlbWEiLCAiUmVhZFJlc291cmNlUmVzdWx0U2NoZW1hIiwgIlJlc291cmNlTGlzdENoYW5nZWROb3RpZmljYXRpb25TY2hlbWEiLCAiU3Vic2NyaWJlUmVxdWVzdFNjaGVtYSIsICJVbnN1YnNjcmliZVJlcXVlc3RTY2hlbWEiLCAiUmVzb3VyY2VVcGRhdGVkTm90aWZpY2F0aW9uU2NoZW1hIiwgIlByb21wdEFyZ3VtZW50U2NoZW1hIiwgIlByb21wdFNjaGVtYSIsICJMaXN0UHJvbXB0c1JlcXVlc3RTY2hlbWEiLCAiTGlzdFByb21wdHNSZXN1bHRTY2hlbWEiLCAiR2V0UHJvbXB0UmVxdWVzdFNjaGVtYSIsICJUZXh0Q29udGVudFNjaGVtYSIsICJJbWFnZUNvbnRlbnRTY2hlbWEiLCAiRW1iZWRkZWRSZXNvdXJjZVNjaGVtYSIsICJQcm9tcHRNZXNzYWdlU2NoZW1hIiwgIkdldFByb21wdFJlc3VsdFNjaGVtYSIsICJQcm9tcHRMaXN0Q2hhbmdlZE5vdGlmaWNhdGlvblNjaGVtYSIsICJUb29sU2NoZW1hIiwgIkxpc3RUb29sc1JlcXVlc3RTY2hlbWEiLCAiTGlzdFRvb2xzUmVzdWx0U2NoZW1hIiwgIkNhbGxUb29sUmVzdWx0U2NoZW1hIiwgIkNvbXBhdGliaWxpdHlDYWxsVG9vbFJlc3VsdFNjaGVtYSIsICJDYWxsVG9vbFJlcXVlc3RTY2hlbWEiLCAiVG9vbExpc3RDaGFuZ2VkTm90aWZpY2F0aW9uU2NoZW1hIiwgIkxvZ2dpbmdMZXZlbFNjaGVtYSIsICJTZXRMZXZlbFJlcXVlc3RTY2hlbWEiLCAiTG9nZ2luZ01lc3NhZ2VOb3RpZmljYXRpb25TY2hlbWEiLCAiTW9kZWxIaW50U2NoZW1hIiwgIk1vZGVsUHJlZmVyZW5jZXNTY2hlbWEiLCAiU2FtcGxpbmdNZXNzYWdlU2NoZW1hIiwgIkNyZWF0ZU1lc3NhZ2VSZXF1ZXN0U2NoZW1hIiwgIkNyZWF0ZU1lc3NhZ2VSZXN1bHRTY2hlbWEiLCAiUmVzb3VyY2VSZWZlcmVuY2VTY2hlbWEiLCAiUHJvbXB0UmVmZXJlbmNlU2NoZW1hIiwgIkNvbXBsZXRlUmVxdWVzdFNjaGVtYSIsICJDb21wbGV0ZVJlc3VsdFNjaGVtYSIsICJSb290U2NoZW1hIiwgIkxpc3RSb290c1JlcXVlc3RTY2hlbWEiLCAiTGlzdFJvb3RzUmVzdWx0U2NoZW1hIiwgIlJvb3RzTGlzdENoYW5nZWROb3RpZmljYXRpb25TY2hlbWEiLCAiQ2xpZW50UmVxdWVzdFNjaGVtYSIsICJDbGllbnROb3RpZmljYXRpb25TY2hlbWEiLCAiQ2xpZW50UmVzdWx0U2NoZW1hIiwgIlNlcnZlclJlcXVlc3RTY2hlbWEiLCAiU2VydmVyTm90aWZpY2F0aW9uU2NoZW1hIiwgIlNlcnZlclJlc3VsdFNjaGVtYSIsICJNY3BFcnJvciIsICJjb2RlIiwgIm1lc3NhZ2UiLCAiZGF0YSIsICJERUZBVUxUX1JFUVVFU1RfVElNRU9VVF9NU0VDIiwgIlByb3RvY29sIiwgIl9vcHRpb25zIiwgIkNhbmNlbGxlZE5vdGlmaWNhdGlvblNjaGVtYSIsICJub3RpZmljYXRpb24iLCAiY29udHJvbGxlciIsICJQcm9ncmVzc05vdGlmaWNhdGlvblNjaGVtYSIsICJQaW5nUmVxdWVzdFNjaGVtYSIsICJfcmVxdWVzdCIsICJ0cmFuc3BvcnQiLCAiZXJyb3IiLCAibWVzc2FnZSIsICJyZXNwb25zZUhhbmRsZXJzIiwgIl9hIiwgIk1jcEVycm9yIiwgIkVycm9yQ29kZSIsICJoYW5kbGVyIiwgInJlcXVlc3QiLCAiX2IiLCAiYWJvcnRDb250cm9sbGVyIiwgInJlc3VsdCIsICJwcm9ncmVzcyIsICJ0b3RhbCIsICJwcm9ncmVzc1Rva2VuIiwgInJlc3BvbnNlIiwgIm1lc3NhZ2VJZCIsICJyZXN1bHRTY2hlbWEiLCAib3B0aW9ucyIsICJyZXNvbHZlIiwgInJlamVjdCIsICJqc29ucnBjUmVxdWVzdCIsICJ0aW1lb3V0SWQiLCAiY2FuY2VsIiwgInJlYXNvbiIsICJfYyIsICJ0aW1lb3V0IiwgIl9kIiwgImpzb25ycGNOb3RpZmljYXRpb24iLCAicmVxdWVzdFNjaGVtYSIsICJtZXRob2QiLCAiZXh0cmEiLCAibm90aWZpY2F0aW9uU2NoZW1hIiwgIlNlcnZlciIsICJQcm90b2NvbCIsICJfc2VydmVySW5mbyIsICJvcHRpb25zIiwgIkluaXRpYWxpemVSZXF1ZXN0U2NoZW1hIiwgInJlcXVlc3QiLCAiSW5pdGlhbGl6ZWROb3RpZmljYXRpb25TY2hlbWEiLCAiX2EiLCAibWV0aG9kIiwgIl9iIiwgInJlcXVlc3RlZFZlcnNpb24iLCAiU1VQUE9SVEVEX1BST1RPQ09MX1ZFUlNJT05TIiwgIkxBVEVTVF9QUk9UT0NPTF9WRVJTSU9OIiwgIkVtcHR5UmVzdWx0U2NoZW1hIiwgInBhcmFtcyIsICJDcmVhdGVNZXNzYWdlUmVzdWx0U2NoZW1hIiwgIkxpc3RSb290c1Jlc3VsdFNjaGVtYSIsICJwcm9jZXNzIiwgIlJlYWRCdWZmZXIiLCAiY2h1bmsiLCAiaW5kZXgiLCAibGluZSIsICJkZXNlcmlhbGl6ZU1lc3NhZ2UiLCAiSlNPTlJQQ01lc3NhZ2VTY2hlbWEiLCAic2VyaWFsaXplTWVzc2FnZSIsICJtZXNzYWdlIiwgIlN0ZGlvU2VydmVyVHJhbnNwb3J0IiwgIl9zdGRpbiIsICJwcm9jZXNzIiwgIl9zdGRvdXQiLCAiUmVhZEJ1ZmZlciIsICJjaHVuayIsICJlcnJvciIsICJfYSIsICJtZXNzYWdlIiwgIl9iIiwgInJlc29sdmUiLCAianNvbiIsICJzZXJpYWxpemVNZXNzYWdlIiwgInRvb2xzX2V4cG9ydHMiLCAiX19leHBvcnQiLCAiZ2V0QWdlbnQiLCAiZ2V0RGVwbG95bWVudFN0YXR1cyIsICJsaXN0QWdlbnRzIiwgImxpc3RQcmltaXRpdmVWZXJzaW9ucyIsICJ0YWlsTG9ncyIsICJzcGF3biIsICJERUZBVUxUX1RJTUVPVVRfTVMiLCAicnVuTHVhIiwgImFyZ3MiLCAic3Bhd25GbiIsICJ0aW1lb3V0TXMiLCAibGFiZWwiLCAicmVzb2x2ZSIsICJyZWplY3QiLCAiY2hpbGQiLCAic3Rkb3V0IiwgInN0ZGVyciIsICJkIiwgInRpbWVyIiwgImNvZGUiLCAiZXJyIiwgImZsYXR0ZW5BZ2VudHMiLCAicGFyc2VkIiwgIm9iaiIsICJlbnRyaWVzIiwgIm9yZyIsICJhIiwgImxpc3RBZ2VudHNWaWFDbGkiLCAibGlzdEFnZW50cyIsICJfYXJncyIsICJkZXBzIiwgImNvbXBhY3QiLCAibGlzdEFnZW50c1ZpYUNsaSIsICJnZXRBZ2VudCIsICJhZ2VudElkIiwgImRlcHMiLCAibWF0Y2giLCAibGlzdEFnZW50c1ZpYUNsaSIsICJhIiwgInJlYWRGaWxlIiwgInJlYWRkaXIiLCAic3RhdCIsICJqb2luIiwgImRpcm5hbWUiLCAiaG9tZWRpciIsICJERUZBVUxUX0FQSV9VUkwiLCAiRklSRUJBU0VfUkVGUkVTSF9VUkwiLCAiUkVGUkVTSF9USU1FT1VUX01TIiwgIlJFRlJFU0hfU0tFV19NUyIsICJSRUpFQ1RFRF9SRUZSRVNIX1JFQVNPTlMiLCAidG9rZW5DYWNoZSIsICJwYXJzZURvdGVudkFwaUtleSIsICJjb250ZW50IiwgInJhd0xpbmUiLCAibSIsICJ2YWx1ZSIsICJxdW90ZWQiLCAiZmluZFNlc3Npb25GaWxlIiwgInNlc3Npb25zRGlyIiwgImFwaVVybCIsICJuYW1lcyIsICJyZWFkZGlyIiwgImNhbmRpZGF0ZXMiLCAibmFtZSIsICJwYXRoIiwgImpvaW4iLCAic2Vzc2lvbiIsICJyZWFkRmlsZSIsICJtdGltZU1zIiwgInN0YXQiLCAiYSIsICJiIiwgInJlZnJlc2hTZXNzaW9uQmVhcmVyIiwgImZldGNoRm4iLCAibm93IiwgImNhY2hlZCIsICJ0b2tlbkNhY2hlIiwgIlJFRlJFU0hfU0tFV19NUyIsICJjb250cm9sbGVyIiwgInRpbWVyIiwgIlJFRlJFU0hfVElNRU9VVF9NUyIsICJyZXMiLCAiRklSRUJBU0VfUkVGUkVTSF9VUkwiLCAiZXJyIiwgInJlYXNvbiIsICJtZXNzYWdlIiwgInJlamVjdGVkIiwgIlJFSkVDVEVEX1JFRlJFU0hfUkVBU09OUyIsICJyIiwgImJvZHkiLCAiaWRUb2tlbiIsICJleHBpcmVzSW4iLCAicmVzb2x2ZUFwaUtleSIsICJlbnYiLCAiY3JlZGVudGlhbHNQYXRoIiwgImhvbWVkaXIiLCAiZGlybmFtZSIsICJjd2QiLCAiREVGQVVMVF9BUElfVVJMIiwgImZyb21Eb3RlbnYiLCAiZm91bmQiLCAicmF3IiwgInBhcnNlZCIsICJERUZBVUxUX0JBU0VfVVJMIiwgIkRFRkFVTFRfVElNRU9VVF9NUyIsICJST1VURV9TQ09QRVMiLCAiUk9VVEVfU0NPUEVfU1VNTUFSWSIsICJhcGlSZXF1ZXN0IiwgInBhdGgiLCAibWV0aG9kIiwgImJvZHkiLCAicXVlcnkiLCAiZmV0Y2hGbiIsICJiYXNlVXJsIiwgInRpbWVvdXRNcyIsICJhcGlLZXkiLCAicmVzb2x2ZUFwaUtleSIsICJ1cmwiLCAiayIsICJ2IiwgImNvbnRyb2xsZXIiLCAidGltZXIiLCAicmVzIiwgInJhdyIsICJmcmllbmRseU1zZyIsICJwYXJzZWQiLCAiY29kZSIsICJlcnIiLCAiTElTVF9FWFRSQUNUT1JTIiwgIlZFUlNJT05TX0VYVFJBQ1RPUlMiLCAiTElTVF9QQVRIUyIsICJleHRyYWN0TGlzdCIsICJ0eXBlIiwgInJlc3BvbnNlIiwgImZuIiwgImV4dHJhY3RWZXJzaW9ucyIsICJleHRyYWN0QWN0aXZlVmVyc2lvbklkIiwgImlkIiwgImlzQWN0aXZlVmVyc2lvbiIsICJ2ZXJzaW9uIiwgImFjdGl2ZUlkIiwgIm93bklkIiwgInZlcnNpb25DcmVhdGVkQXQiLCAicmF3IiwgInZlcnNpb25JZCIsICJTVVBQT1JURURfTElTVF9UWVBFUyIsICJTVVBQT1JURURfVkVSU0lPTl9UWVBFUyIsICJWQUxJRF9UWVBFUyIsICJTVVBQT1JURURfVkVSU0lPTl9UWVBFUyIsICJsaXN0UHJpbWl0aXZlVmVyc2lvbnMiLCAiYWdlbnRJZCIsICJ0eXBlIiwgIm5hbWUiLCAiZGVwcyIsICJwYXRoIiwgImlkIiwgInJlc29sdmVOYW1lVG9JZCIsICJMSVNUX1BBVEhTIiwgImRhdGEiLCAiYXBpUmVxdWVzdCIsICJjb21wYWN0IiwgImV4dHJhY3RWZXJzaW9ucyIsICJ2IiwgInZlcnNpb25JZCIsICJpc0FjdGl2ZVZlcnNpb24iLCAidmVyc2lvbkNyZWF0ZWRBdCIsICJyZXN1bHQiLCAiZXh0cmFjdEFjdGl2ZVZlcnNpb25JZCIsICJmZXRjaEZuIiwgImxpc3RQYXRoIiwgImxpc3RSZXNwb25zZSIsICJpdGVtcyIsICJleHRyYWN0TGlzdCIsICJtYXRjaCIsICJwIiwgImF2YWlsYWJsZSIsICJQUklNSVRJVkVfVFlQRVMiLCAiVkVSU0lPTlNfQ0hVTktfU0laRSIsICJERUZBVUxUX0JVREdFVF9NUyIsICJnZXREZXBsb3ltZW50U3RhdHVzIiwgImFnZW50SWQiLCAiZGVwcyIsICJpZCIsICJidWRnZXRNcyIsICJzdGFydGVkQXQiLCAib3ZlckJ1ZGdldCIsICJnZXQiLCAicGF0aCIsICJhcGlSZXF1ZXN0IiwgInJlc3VsdCIsICJ0eXBlIiwgInBlcnNvbmFPdXRjb21lIiwgImxpc3RPdXRjb21lcyIsICJMSVNUX1BBVEhTIiwgInBlcnNvbmFSZXNwb25zZSIsICJ2ZXJzaW9ucyIsICJleHRyYWN0VmVyc2lvbnMiLCAiYWN0aXZlIiwgInYiLCAiaXNBY3RpdmVWZXJzaW9uIiwgInZlcnNpb25DcmVhdGVkQXQiLCAiYnVkZ2V0RXhoYXVzdGVkIiwgInNraXBwZWQiLCAidG90YWwiLCAidCIsICJvdXRjb21lIiwgInRhcmdldHMiLCAiZXh0cmFjdExpc3QiLCAicCIsICJ0Z3QiLCAiaSIsICJjaHVuayIsICJuYW1lIiwgInByaW1JZCIsICJ2byIsICJqIiwgInZlcnNpb25zUmVzcG9uc2UiLCAiZW50cnkiLCAidmVyc2lvbklkIiwgImV4dHJhY3RBY3RpdmVWZXJzaW9uSWQiLCAiTE9HX1NPVVJDRVMiLCAiTE9HX1RZUEVTIiwgIlZBTElEX1RZUEVTIiwgIlZBTElEX0xPR19UWVBFUyIsICJ0YWlsTG9ncyIsICJhZ2VudElkIiwgInR5cGUiLCAibmFtZSIsICJsb2dUeXBlIiwgImxpbWl0IiwgInBhZ2UiLCAiZGVwcyIsICJxdWVyeSIsICJkYXRhIiwgImFwaVJlcXVlc3QiLCAiVE9PTF9SRUdJU1RSWSIsICJ0b29sc19leHBvcnRzIiwgInNlcnZlciIsICJTZXJ2ZXIiLCAiTGlzdFRvb2xzUmVxdWVzdFNjaGVtYSIsICJ0IiwgIkNhbGxUb29sUmVxdWVzdFNjaGVtYSIsICJyZXEiLCAidG9vbCIsICJlcnIiLCAicmVwb3J0Q3Jhc2hBbmRFeGl0IiwgInBheWxvYWQiLCAicmVhc29uIiwgIlN0ZGlvU2VydmVyVHJhbnNwb3J0Il0KfQo= diff --git a/plugins/lua-agent-builder/mcp/lua-platform/package-lock.json b/plugins/lua-agent-builder/mcp/lua-platform/package-lock.json index b451b1f..0c554d3 100644 --- a/plugins/lua-agent-builder/mcp/lua-platform/package-lock.json +++ b/plugins/lua-agent-builder/mcp/lua-platform/package-lock.json @@ -1,12 +1,12 @@ { "name": "@lua/claude-plugin-mcp", - "version": "1.5.0", + "version": "1.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@lua/claude-plugin-mcp", - "version": "1.5.0", + "version": "1.6.0", "dependencies": { "@modelcontextprotocol/sdk": "~0.6.0" }, diff --git a/plugins/lua-agent-builder/mcp/lua-platform/package.json b/plugins/lua-agent-builder/mcp/lua-platform/package.json index 1250fb4..6ce4e91 100644 --- a/plugins/lua-agent-builder/mcp/lua-platform/package.json +++ b/plugins/lua-agent-builder/mcp/lua-platform/package.json @@ -1,6 +1,6 @@ { "name": "@lua/claude-plugin-mcp", - "version": "1.5.0", + "version": "1.6.0", "description": "Read-only MCP server for the lua-agent-builder Claude Code plugin", "type": "module", "main": "dist/server.js", diff --git a/plugins/lua-agent-builder/mcp/lua-platform/scripts/bundle.mjs b/plugins/lua-agent-builder/mcp/lua-platform/scripts/bundle.mjs index 8e3f200..36b9b34 100644 --- a/plugins/lua-agent-builder/mcp/lua-platform/scripts/bundle.mjs +++ b/plugins/lua-agent-builder/mcp/lua-platform/scripts/bundle.mjs @@ -1,22 +1,33 @@ #!/usr/bin/env node import { build } from 'esbuild'; -// Iteration-13 audit: removed `packages: 'bundle'` β€” that option only exists -// in esbuild β‰₯0.22 but the pinned dep is `^0.20.0` (would fail at build with -// `Invalid value "bundle" in "--packages=bundle"`). The MCP server has only -// one npm runtime dep (`@modelcontextprotocol/sdk`, marked external below) -// and node builtins (auto-external), so `bundle: true` alone correctly -// bundles every relative import without needing `packages: 'bundle'`. +// EM-WS8 (1.6.0): EVERYTHING is bundled, `@modelcontextprotocol/sdk` included. +// The plugin ships no node_modules β€” marketplace installs copy the directory +// verbatim and the Lua Job tier bakes it into an image the same way β€” so an +// external SDK made the server die with ERR_MODULE_NOT_FOUND on every install +// (Claude Code shows it as `lua-platform CONNECTION_CLOSED`). +// tests/standalone-bundle.test.mjs copies dist/server.js into an empty temp +// directory and lists the tools over stdio to keep it that way. +// +// Iteration-13 audit: `packages: 'bundle'` is not used β€” that option only +// exists in esbuild >=0.22 and the pinned dep is `^0.20.0`; `bundle: true` +// with no `external` already bundles every npm import. Node builtins stay +// external automatically (`platform: 'node'`). +// +// The banner gives the ESM bundle a real `require`, so any CommonJS module +// the SDK pulls in can still `require()` a node builtin. await build({ entryPoints: ['src/server.mjs'], bundle: true, platform: 'node', target: 'node18', format: 'esm', - external: ['@modelcontextprotocol/sdk'], + banner: { + js: "import { createRequire as __luaCreateRequire } from 'node:module'; const require = __luaCreateRequire(import.meta.url);", + }, minify: true, sourcemap: 'inline', outfile: 'dist/server.js', }); -console.log('βœ“ Bundled to dist/server.js'); +console.log('βœ“ Bundled to dist/server.js (self-contained, no runtime node_modules needed)'); diff --git a/plugins/lua-agent-builder/mcp/lua-platform/src/api-client.mjs b/plugins/lua-agent-builder/mcp/lua-platform/src/api-client.mjs index 4b8ba48..2bd9d1a 100644 --- a/plugins/lua-agent-builder/mcp/lua-platform/src/api-client.mjs +++ b/plugins/lua-agent-builder/mcp/lua-platform/src/api-client.mjs @@ -69,7 +69,7 @@ export async function apiRequest(path, { headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json', - 'X-Lua-Client': 'claude-plugin/1.5.0', + 'X-Lua-Client': 'claude-plugin/1.6.0', }, body: body ? JSON.stringify(body) : undefined, signal: controller.signal, diff --git a/plugins/lua-agent-builder/mcp/lua-platform/src/server.mjs b/plugins/lua-agent-builder/mcp/lua-platform/src/server.mjs index 8f787dc..1673055 100644 --- a/plugins/lua-agent-builder/mcp/lua-platform/src/server.mjs +++ b/plugins/lua-agent-builder/mcp/lua-platform/src/server.mjs @@ -11,7 +11,7 @@ import * as tools from './tools/index.mjs'; const TOOL_REGISTRY = Object.values(tools); const server = new Server( - { name: 'lua-platform', version: '1.5.0' }, + { name: 'lua-platform', version: '1.6.0' }, { capabilities: { tools: {} } } ); @@ -46,7 +46,7 @@ process.on('uncaughtException', (err) => { kind: 'uncaughtException', message: err?.message, stack: err?.stack, - plugin_version: '1.5.0', + plugin_version: '1.6.0', lua_cli_version: process.env.LUA_CLI_VERSION ?? null, platform: process.platform, ts: new Date().toISOString(), @@ -59,7 +59,7 @@ process.on('unhandledRejection', (reason) => { kind: 'unhandledRejection', reason: String(reason), stack: /** @type {any} */ (reason)?.stack, - plugin_version: '1.5.0', + plugin_version: '1.6.0', lua_cli_version: process.env.LUA_CLI_VERSION ?? null, platform: process.platform, ts: new Date().toISOString(), diff --git a/plugins/lua-agent-builder/mcp/lua-platform/tests/standalone-bundle.test.mjs b/plugins/lua-agent-builder/mcp/lua-platform/tests/standalone-bundle.test.mjs new file mode 100644 index 0000000..725354c --- /dev/null +++ b/plugins/lua-agent-builder/mcp/lua-platform/tests/standalone-bundle.test.mjs @@ -0,0 +1,131 @@ +// EM-WS8: dist/server.js must run with NO node_modules anywhere above it. +// +// Marketplace installs copy the plugin verbatim β€” no `npm ci` runs β€” and the +// Lua Job tier bakes the plugin into an image the same way. Until 1.6.0 the +// bundle left `@modelcontextprotocol/sdk` external, so the server died with +// ERR_MODULE_NOT_FOUND on every such install (Claude Code reported it as +// `lua-platform CONNECTION_CLOSED`). +// +// The test copies the bundle into a fresh temp directory before spawning it. +// Spawning it in place would pass vacuously: Node resolves a bare import by +// walking up the parent directories, and CI has just run `npm ci` in +// mcp/lua-platform/, so the SDK would be found in ../node_modules. + +import { describe, test, expect, beforeAll, afterAll } from '@jest/globals'; +import { spawn } from 'node:child_process'; +import { copyFileSync, mkdirSync, mkdtempSync, readFileSync, rmSync, existsSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { dirname, join, resolve, parse } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const PKG_DIR = resolve(__dirname, '..'); +const DIST = join(PKG_DIR, 'dist', 'server.js'); +const PKG_VERSION = JSON.parse(readFileSync(join(PKG_DIR, 'package.json'), 'utf8')).version; + +const EXPECTED_TOOLS = [ + 'get_agent', + 'get_deployment_status', + 'list_agents', + 'list_primitive_versions', + 'tail_logs', +]; + +/** True if any directory from `dir` up to the filesystem root has a node_modules. */ +function nodeModulesAbove(dir) { + let cur = dir; + const { root } = parse(cur); + for (;;) { + if (existsSync(join(cur, 'node_modules'))) return cur; + if (cur === root) return null; + cur = dirname(cur); + } +} + +/** + * Spawn `node ` with a scrubbed environment, send newline-delimited + * JSON-RPC requests, and resolve with every response keyed by id once the + * responses for all `waitFor` ids arrived (or reject on exit/timeout). + */ +function rpcSession(file, cwd, messages, waitFor) { + return new Promise((resolveP, reject) => { + const env = { ...process.env, LUA_API_KEY: 'test', LUA_CREDENTIALS_PATH: '/nonexistent' }; + delete env.NODE_PATH; + delete env.NODE_OPTIONS; + const child = spawn(process.execPath, [file], { cwd, env, shell: false, windowsHide: true }); + const responses = new Map(); + let buf = ''; + let stderr = ''; + const finish = (err) => { + clearTimeout(timer); + child.kill(); + if (err) reject(err); else resolveP(responses); + }; + const timer = setTimeout( + () => finish(new Error(`timed out; got ids ${[...responses.keys()]}; stderr=${stderr}`)), + 10_000, + ); + child.stdout.on('data', (d) => { + buf += d.toString('utf8'); + let nl; + while ((nl = buf.indexOf('\n')) >= 0) { + const line = buf.slice(0, nl).trim(); + buf = buf.slice(nl + 1); + if (!line) continue; + const msg = JSON.parse(line); + if (msg.id !== undefined) responses.set(msg.id, msg); + } + if (waitFor.every((id) => responses.has(id))) finish(); + }); + child.stderr.on('data', (d) => { stderr += d.toString('utf8'); }); + child.on('exit', (code) => finish(new Error(`server exited ${code} before replying: ${stderr}`))); + child.on('error', finish); + for (const m of messages) child.stdin.write(JSON.stringify(m) + '\n'); + }); +} + +describe('dist/server.js runs standalone (no node_modules)', () => { + let tmp; + let copied; + + beforeAll(() => { + // Mirror the shipped layout: package.json (its `"type": "module"` makes + // Node 18/20 load dist/server.js as ESM) next to dist/server.js β€” and + // nothing else, in particular no node_modules. + tmp = mkdtempSync(join(tmpdir(), 'lua-mcp-standalone-')); + mkdirSync(join(tmp, 'dist')); + copyFileSync(join(PKG_DIR, 'package.json'), join(tmp, 'package.json')); + copied = join(tmp, 'dist', 'server.js'); + copyFileSync(DIST, copied); + }); + afterAll(() => { rmSync(tmp, { recursive: true, force: true }); }); + + test('the isolation is real: no node_modules above the copied bundle', () => { + expect(nodeModulesAbove(tmp)).toBeNull(); + }); + + test('initialize + tools/list answer with the five read-only tools', async () => { + const responses = await rpcSession(copied, tmp, [ + { + jsonrpc: '2.0', id: 1, method: 'initialize', + params: { + protocolVersion: '2024-11-05', + capabilities: {}, + clientInfo: { name: 'standalone-test', version: '0.0.0' }, + }, + }, + { jsonrpc: '2.0', method: 'notifications/initialized' }, + { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} }, + ], [1, 2]); + + const init = responses.get(1); + expect(init.error).toBeUndefined(); + expect(init.result.serverInfo.name).toBe('lua-platform'); + // Catches a version bump that forgot to rebuild dist/. + expect(init.result.serverInfo.version).toBe(PKG_VERSION); + + const list = responses.get(2); + expect(list.error).toBeUndefined(); + expect(list.result.tools.map((t) => t.name).sort()).toEqual(EXPECTED_TOOLS); + }); +}); diff --git a/plugins/lua-agent-builder/package-lock.json b/plugins/lua-agent-builder/package-lock.json index 7b31cf7..ef1ed28 100644 --- a/plugins/lua-agent-builder/package-lock.json +++ b/plugins/lua-agent-builder/package-lock.json @@ -1,12 +1,12 @@ { "name": "claude-code-lua-plugin", - "version": "1.5.0", + "version": "1.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "claude-code-lua-plugin", - "version": "1.5.0", + "version": "1.6.0", "devDependencies": { "@types/node": "^20.11.0", "eslint": "^8.57.0", diff --git a/plugins/lua-agent-builder/package.json b/plugins/lua-agent-builder/package.json index 2614d5d..7c2a07e 100644 --- a/plugins/lua-agent-builder/package.json +++ b/plugins/lua-agent-builder/package.json @@ -1,6 +1,6 @@ { "name": "claude-code-lua-plugin", - "version": "1.5.0", + "version": "1.6.0", "description": "Plugin assets for the lua-agent-builder Claude Code plugin", "private": true, "type": "module", diff --git a/plugins/lua-agent-builder/test/hooks/confirm-deploy.integration.test.mjs b/plugins/lua-agent-builder/test/hooks/confirm-deploy.integration.test.mjs index ed05fe8..de128cb 100644 --- a/plugins/lua-agent-builder/test/hooks/confirm-deploy.integration.test.mjs +++ b/plugins/lua-agent-builder/test/hooks/confirm-deploy.integration.test.mjs @@ -25,6 +25,26 @@ describe('confirm-deploy script entry (spawned)', () => { expect(result.stderr).toContain('Use /lua-deploy'); }); + // EM-WS8: the Job-tier audit's chain bypasses, end to end. + test.each([ + 'cd agent && lua deploy all --force', + 'true; lua version promote 3', + 'FOO=1 lua deploy all', + 'npx lua-cli deploy all', + 'export LUA_DEPLOY_CONFIRMED=1; lua deploy all', + ])('exits 2 on the chained / launched form %s', async (command) => { + const result = await runHook('confirm-deploy.mjs', { tool_input: { command } }, { env: { LUA_PLUGIN_HEADLESS: '' } }); + expect(result.exitCode).toBe(2); + expect(result.stderr).toContain('DEPLOY_DENIED_BARE'); + }); + + test('exits 0 when the prefix sits on the simple command that deploys', async () => { + const result = await runHook('confirm-deploy.mjs', { + tool_input: { command: 'cd agent && LUA_DEPLOY_CONFIRMED=1 lua deploy skill --ci --force' }, + }, { env: { LUA_PLUGIN_HEADLESS: '' } }); + expect(result.exitCode).toBe(0); + }); + test('exits 2 with DEPLOY_DENIED_AUTO on --auto-deploy', async () => { const result = await runHook('confirm-deploy.mjs', { tool_input: { command: 'LUA_DEPLOY_CONFIRMED=1 lua deploy --auto-deploy' }, diff --git a/plugins/lua-agent-builder/test/hooks/headless.test.mjs b/plugins/lua-agent-builder/test/hooks/headless.test.mjs new file mode 100644 index 0000000..79c49f7 --- /dev/null +++ b/plugins/lua-agent-builder/test/hooks/headless.test.mjs @@ -0,0 +1,172 @@ +// EM-WS8 (1.6.0): LUA_PLUGIN_HEADLESS=1 β€” the hooks in an unattended run +// (`claude -p` in the Lua Job tier). Two invariants: +// 1. no message a hook injects or returns points at a slash command β€” the +// slashes need AskUserQuestion or the Agent tool, unavailable headless; +// 2. nothing that is blocked interactively is allowed headless, and the +// LUA_DEPLOY_CONFIRMED=1 prefix is void (the model would confirm to itself). + +import { describe, test, expect, beforeAll, afterAll } from '@jest/globals'; +import { mkdtempSync, writeFileSync, rmSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { isHeadless, HEADLESS_NOTE } from '../../lib/headless.mjs'; +import { decide as confirmDeploy } from '../../hooks/confirm-deploy.mjs'; +import { decide as blockAutoDeploy } from '../../hooks/block-auto-deploy.mjs'; +import { decide as checkAuth } from '../../hooks/check-lua-auth.mjs'; +import { decide as checkVersion, PINNED_MIN_LUA_CLI } from '../../hooks/check-lua-version.mjs'; +import { decide as detectProject } from '../../hooks/detect-project.mjs'; +import { decide as postDeploySmoke } from '../../hooks/post-deploy-smoke.mjs'; +import { runHook } from '../helpers/run-hook.mjs'; + +const HEADLESS = { LUA_PLUGIN_HEADLESS: '1' }; +const INTERACTIVE = {}; +const SLASH = /\/lua-[a-z]/; +const versionOK = { exitCode: 0, stdout: `${PINNED_MIN_LUA_CLI}\n`, stderr: '' }; + +describe('isHeadless()', () => { + test.each([ + ['1', true], ['true', true], ['TRUE', true], [' yes ', true], ['on', true], + ['0', false], ['false', false], ['', false], [undefined, false], ['headless', false], + ])('LUA_PLUGIN_HEADLESS=%p β†’ %p', (value, expected) => { + expect(isHeadless({ LUA_PLUGIN_HEADLESS: value })).toBe(expected); + }); + + test('defaults to process.env and tolerates a missing env', () => { + expect(typeof isHeadless()).toBe('boolean'); + expect(isHeadless(undefined)).toBe(isHeadless(process.env)); + expect(isHeadless(null)).toBe(false); + }); + + test('the shared note names no slash command', () => { + expect(HEADLESS_NOTE).not.toMatch(SLASH); + }); +}); + +describe('check-lua-auth headless: a neutral note, never "run /lua-auth"', () => { + test.each([ + [{ exitCode: 9, stdout: '', stderr: 'βœ– auth' }, 'exited 9'], + [{ exitCode: 1, stdout: '', stderr: 'boom' }, 'exited 1'], + [{ exitCode: 11, stdout: '', stderr: 'βœ– unavailable' }, 'exited 11'], + [{ exitCode: 403, stdout: '', stderr: 'proxy: route not allowed' }, 'exited 403'], + [{ exitCode: null, stdout: '', stderr: '', timedOut: true }, 'did not answer'], + ])('%p', (authResult, outcome) => { + const result = checkAuth(versionOK, authResult, HEADLESS); + expect(result?.warn).toContain('could not be confirmed'); + expect(result?.warn).toContain(outcome); + expect(result?.warn).toContain('proxy'); + expect(result?.warn).not.toMatch(SLASH); + expect(result?.warn).not.toContain('not authenticated'); + }); + + test('success stays silent headless too', () => { + expect(checkAuth(versionOK, { exitCode: 0, stdout: '{}', stderr: '' }, HEADLESS)).toBeNull(); + expect(checkAuth(versionOK, { exitCode: 10, stdout: '', stderr: '' }, HEADLESS)).toBeNull(); + expect(checkAuth({ exitCode: -1, stdout: '', stderr: '' }, { exitCode: -1 }, HEADLESS)).toBeNull(); + }); + + test('interactive keeps recommending /lua-auth', () => { + expect(checkAuth(versionOK, { exitCode: 9, stdout: '', stderr: '' }, INTERACTIVE)?.warn).toContain('/lua-auth'); + }); +}); + +describe('check-lua-version headless: same findings, no /lua-doctor, /lua-update or npm install', () => { + test.each([ + [{ exitCode: -1, stdout: '', stderr: 'ENOENT' }, 'Could not detect lua-cli'], + [{ exitCode: 0, stdout: 'garbage', stderr: '' }, "Couldn't parse"], + [{ exitCode: 0, stdout: '1.0.0', stderr: '' }, 'older than'], + ])('%p', (versionResult, finding) => { + const warn = checkVersion(versionResult, HEADLESS)?.warn; + expect(warn).toContain(finding); + expect(warn).not.toMatch(SLASH); + expect(warn).not.toContain('npm i'); + expect(warn).toContain('headless'); + }); + + test('interactive text is unchanged', () => { + expect(checkVersion({ exitCode: -1, stdout: '' }, INTERACTIVE)?.warn).toBe('Could not detect lua-cli version. Run /lua-doctor to install.'); + expect(checkVersion({ exitCode: 0, stdout: 'garbage' }, INTERACTIVE)?.warn).toContain('Run /lua-doctor.'); + expect(checkVersion({ exitCode: 0, stdout: '1.0.0' }, INTERACTIVE)?.warn).toContain('/lua-update'); + expect(checkVersion(versionOK, HEADLESS)).toBeNull(); + }); +}); + +describe('detect-project headless', () => { + let dir; + beforeAll(() => { + dir = mkdtempSync(join(tmpdir(), 'lua-headless-')); + writeFileSync(join(dir, 'lua.skill.yaml'), 'agent:\n agentId: agent_123\n'); + }); + afterAll(() => rmSync(dir, { recursive: true, force: true })); + + test('reports the project without pointing at /lua-doctor', () => { + expect(detectProject(null, { cwd: dir, env: HEADLESS })).toEqual({ warn: 'βœ“ Lua agent project detected: agent_123.' }); + }); + + test('interactive keeps the pointer', () => { + expect(detectProject(null, { cwd: dir, env: INTERACTIVE })?.warn).toContain('/lua-doctor'); + }); +}); + +describe('confirm-deploy headless: every production verb blocked, the prefix is void', () => { + test.each([ + 'lua deploy all --force', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy skill --ci --name x --set-version latest --force', + 'env LUA_DEPLOY_CONFIRMED=1 lua version promote 3', + 'LUA_DEPLOY_CONFIRMED=1 lua marketplace template apply --template-id t --all-installed --force', + 'cd x && npx lua-cli workflows activate outreach', + ])('%s', (command) => { + const result = confirmDeploy({ tool_input: { command } }, HEADLESS); + expect(result?.block).toBe(true); + expect(result?.reason).toContain('DEPLOY_DENIED_HEADLESS'); + expect(result?.reason).not.toMatch(SLASH); + }); + + test('the same prefixed command is allowed interactively', () => { + expect(confirmDeploy({ tool_input: { command: 'LUA_DEPLOY_CONFIRMED=1 lua version promote 3' } }, INTERACTIVE)).toBeNull(); + }); + + test('--auto-deploy is blocked headless without a slash pointer', () => { + const result = confirmDeploy({ tool_input: { command: 'lua push skill --ci --force --auto-deploy' } }, HEADLESS); + expect(result?.block).toBe(true); + expect(result?.reason).toContain('DEPLOY_DENIED_AUTO'); + expect(result?.reason).not.toMatch(SLASH); + }); + + test('non-production commands pass headless', () => { + for (const command of ['lua push all --ci --force', 'lua version create --ci -m "x"', 'lua compile --ci', 'git status']) { + expect(confirmDeploy({ tool_input: { command } }, HEADLESS)).toBeNull(); + } + }); + + test('spawned with LUA_PLUGIN_HEADLESS=1, a prefixed deploy exits 2', async () => { + const result = await runHook( + 'confirm-deploy.mjs', + { tool_input: { command: 'LUA_DEPLOY_CONFIRMED=1 lua deploy skill --ci --force' } }, + { env: HEADLESS }, + ); + expect(result.exitCode).toBe(2); + expect(result.stderr).toContain('DEPLOY_DENIED_HEADLESS'); + }); +}); + +describe('block-auto-deploy headless', () => { + test('still blocks, names no slash', () => { + const result = blockAutoDeploy({ tool_input: { command: 'lua push all --auto-deploy' } }, HEADLESS); + expect(result?.block).toBe(true); + expect(result?.reason).not.toMatch(SLASH); + }); + + test('interactive keeps /lua-deploy', () => { + expect(blockAutoDeploy({ tool_input: { command: 'lua push all --auto-deploy' } }, INTERACTIVE)?.reason).toContain('/lua-deploy'); + }); +}); + +describe('post-deploy-smoke headless', () => { + test('never spawns the production ping', async () => { + const spawnLuaFn = async () => { throw new Error('must not spawn headless'); }; + await expect(postDeploySmoke( + { tool_input: { command: 'LUA_DEPLOY_CONFIRMED=1 lua version promote 3' }, tool_response: { success: true } }, + { spawnLuaFn, env: HEADLESS }, + )).resolves.toBeNull(); + }); +}); diff --git a/plugins/lua-agent-builder/test/lib/tokenizer-hardening.test.mjs b/plugins/lua-agent-builder/test/lib/tokenizer-hardening.test.mjs new file mode 100644 index 0000000..08ca064 --- /dev/null +++ b/plugins/lua-agent-builder/test/lib/tokenizer-hardening.test.mjs @@ -0,0 +1,352 @@ +// EM-WS8 (1.6.0): the confirm-deploy parser bypasses from the Job-tier audit +// (finding 3; `lib/tokenizer.mjs:81-96` in 1.5.0) and the shell shapes that +// neighbour them. Every case here PASSED the 1.5.0 regex classifier. + +import { describe, test, expect } from '@jest/globals'; +import { classifyProductionCommand, isPrefixedDeploy, lex, UNRESOLVED_LABEL } from '../../lib/tokenizer.mjs'; + +const bare = (label, slash = '/lua-deploy') => ({ label, slash, prefixed: false }); +const DEPLOY = bare('lua deploy'); +const PROMOTE = bare('lua version promote'); + +describe('the five bypasses named in the Job-tier audit', () => { + test.each([ + ['cd x && lua deploy all --force', DEPLOY], + ['true; lua version promote 3', PROMOTE], + ['FOO=1 lua deploy all', DEPLOY], + ['/usr/local/bin/lua deploy all', DEPLOY], + ['npx lua deploy all', DEPLOY], + ])('%s is classified and not prefixed', (cmd, expected) => { + expect(classifyProductionCommand(cmd)).toEqual(expected); + }); +}); + +describe('verbs anywhere in a command chain', () => { + test.each([ + 'false || lua deploy all', + 'lua compile --ci && lua deploy all', + 'lua compile --ci\nlua deploy all', + 'lua compile --ci & lua deploy all', + 'lua compile --ci; lua deploy all', + '(lua deploy all)', + '(cd agent && lua deploy all)', + '{ lua deploy all; }', + 'if true; then lua deploy all; fi', + 'for i in 1; do lua deploy all; done', + '! lua deploy all', + 'lua status |& lua deploy all', + 'f() { lua deploy all; }; f', + 'case x in x) lua deploy all;; esac', + ])('%s', (cmd) => { + expect(classifyProductionCommand(cmd)).toEqual(DEPLOY); + }); +}); + +describe('env-assignment prefixes, wrappers and binary paths', () => { + test.each([ + 'FOO=1 BAR=2 lua deploy all', + 'env FOO=1 lua deploy all', + 'env -i PATH=/usr/bin lua deploy all', + 'command lua deploy all', + 'exec lua deploy all', + 'nohup lua deploy all', + 'time lua deploy all', + 'timeout 60 lua deploy all', + 'sudo -u deployer lua deploy all', + './node_modules/.bin/lua deploy all', + '~/.npm-global/bin/heylua deploy all', + '"C:\\Users\\me\\AppData\\Roaming\\npm\\lua.cmd" deploy all', + 'C:/Users/me/AppData/Roaming/npm/lua.cmd deploy all', + '"lua" deploy all', + "'lua' deploy all", + 'l\\ua deploy all', + 'lu""a deploy all', + ])('%s', (cmd) => { + expect(classifyProductionCommand(cmd)).toEqual(DEPLOY); + }); +}); + +describe('package runners and node entry points', () => { + test.each([ + 'npx lua deploy all', + 'npx lua-cli deploy all', + 'npx -y lua-cli@3.38.0 deploy all', + 'npx --yes lua-cli@latest deploy all', + 'npx -p lua-cli lua deploy all', + 'pnpm exec lua deploy all', + 'pnpm dlx lua-cli deploy all', + 'pnpx lua-cli deploy all', + 'yarn lua deploy all', + 'yarn dlx lua-cli deploy all', + 'npm exec -- lua deploy all', + 'npm x lua-cli -- deploy all', + 'bunx lua-cli deploy all', + 'node /x/lua deploy all', + 'node ./node_modules/.bin/lua deploy all', + 'node node_modules/lua-cli/dist/index.js deploy all', + 'node --no-warnings -r dotenv/config /usr/lib/node_modules/lua-cli/dist/index.js deploy all', + 'node /opt/heylua/dist/index.js deploy all', + '/opt/lua-cli/dist/index.js deploy all', + ])('%s', (cmd) => { + expect(classifyProductionCommand(cmd)).toEqual(DEPLOY); + }); + + test('`lua-cli` alone at the head is not an installed binary (unchanged from 1.5.0)', () => { + expect(classifyProductionCommand('lua-cli deploy')).toBeNull(); + }); + + test('node running some other script is not lua', () => { + expect(classifyProductionCommand('node scripts/build.mjs deploy all')).toBeNull(); + expect(classifyProductionCommand('node --version')).toBeNull(); + }); +}); + +describe('options between the binary and the verb', () => { + test.each([ + ['lua --ci deploy all', 'lua deploy'], + ['lua workflows -v 3 deploy outreach', 'lua workflows deploy'], + ['lua workflows --version=3 deploy outreach', 'lua workflows deploy'], + ['lua persona --force production deploy --persona-version 5', 'lua persona production deploy'], + ['lua version --json promote 3', 'lua version promote'], + ])('%s β†’ %s', (cmd, label) => { + expect(classifyProductionCommand(cmd)?.label).toBe(label); + }); +}); + +describe('aliases the 1.5.0 table missed', () => { + test.each([ + ['lua marketplace templates publish --template-id t', 'lua marketplace template publish'], + ['lua marketplace agent-template submit --template-id t', 'lua marketplace template publish'], + ['lua marketplace agent-templates rollout --template-id t', 'lua marketplace template apply'], + ['lua workflows DEPLOY outreach -v 2', 'lua workflows deploy'], + ['lua mcp ON fs', 'lua mcp activate'], + ['lua persona LIVE Publish --persona-version 5', 'lua persona production deploy'], + ])('%s β†’ %s', (cmd, label) => { + expect(classifyProductionCommand(cmd)?.label).toBe(label); + expect(classifyProductionCommand(`LUA_DEPLOY_CONFIRMED=1 ${cmd}`)?.prefixed).toBe(true); + }); +}); + +describe('substitutions and strings run by another shell', () => { + test.each([ + 'echo $(lua deploy all)', + 'echo "$(lua deploy all)"', + 'echo `lua deploy all`', + 'echo "`lua deploy all`"', + 'lua chat --ci -e sandbox -m "$(lua version promote 3)" -t t1', + 'diff <(lua deploy all) /dev/null', + 'tee >(lua deploy all) < /dev/null', + 'bash -c "lua deploy all"', + "sh -lc 'lua deploy all'", + 'zsh -c "cd x && lua deploy all"', + '/bin/bash -c "lua deploy all"', + 'eval "lua deploy all"', + 'eval lua deploy all', + 'ssh prod-box "lua deploy all"', + 'watch -n 5 "lua deploy all"', + 'npx -c "lua deploy all"', + 'printf "lua deploy all" | sh', + 'echo "lua deploy all" | bash -s', + 'bash < { + const c = classifyProductionCommand(cmd); + expect(c).not.toBeNull(); + expect(c.prefixed).toBe(false); + }); + + test('inline interpreter code is searched as text', () => { + for (const cmd of [ + "node -e \"require('child_process').execSync('lua deploy all')\"", + "python3 -c \"import os; os.system('lua version promote 3')\"", + "perl -e 'system(\"lua deploy all\")'", + 'python3 < { + for (const cmd of [ + 'bash -c "LUA_DEPLOY_CONFIRMED=1 lua deploy skill"', + 'echo $(LUA_DEPLOY_CONFIRMED=1 lua deploy skill)', + '(LUA_DEPLOY_CONFIRMED=1 lua deploy skill)', + '{ LUA_DEPLOY_CONFIRMED=1 lua deploy skill; }', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy skill | tee log', + 'echo y | LUA_DEPLOY_CONFIRMED=1 lua deploy skill', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy skill |& cat', + ]) { + expect({ cmd, prefixed: isPrefixedDeploy(cmd) }).toEqual({ cmd, prefixed: false }); + expect(classifyProductionCommand(cmd)).not.toBeNull(); + } + }); +}); + +describe('shell variables in the binary or verb position (cannot be resolved β†’ blocked)', () => { + test.each([ + ['L=lua; $L deploy all', 'lua deploy'], + ['"$LUA_BIN" version promote 3', 'lua version promote'], + ['$(which lua) deploy all', 'lua deploy'], + ['env $LUA deploy all', 'lua deploy'], + ["$'\\x6cua' deploy all", 'lua deploy'], + ['lua $VERB all', UNRESOLVED_LABEL], + ['lua "$VERB" all', UNRESOLVED_LABEL], + ['lua workflows $ACTION outreach', UNRESOLVED_LABEL], + ['lua ${CMD} all', UNRESOLVED_LABEL], + ])('%s β†’ %s', (cmd, label) => { + expect(classifyProductionCommand(cmd)).toEqual({ label, slash: '/lua-deploy', prefixed: false }); + }); + + test('a prefixed command with a variable verb is still blocked', () => { + expect(isPrefixedDeploy('LUA_DEPLOY_CONFIRMED=1 lua $VERB all')).toBe(false); + }); + + test('a variable that is not in command position is just an argument', () => { + expect(classifyProductionCommand('echo $HOME deploy all')).toBeNull(); + expect(classifyProductionCommand('lua test --ci skill --name $SKILL')).toBeNull(); + expect(classifyProductionCommand('lua chat --ci -e sandbox -m "$MSG" -t t1')).toBeNull(); + }); +}); + +describe('LUA_DEPLOY_CONFIRMED=1 counts only on the same simple command', () => { + test.each([ + 'export LUA_DEPLOY_CONFIRMED=1; lua deploy all', + 'export LUA_DEPLOY_CONFIRMED=1 && lua deploy all', + 'LUA_DEPLOY_CONFIRMED=1 true && lua deploy all', + 'LUA_DEPLOY_CONFIRMED=1; lua deploy all', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy skill; lua version promote 3', + 'LUA_DEPLOY_CONFIRMED=1 lua compile --ci && lua deploy all', + 'LUA_DEPLOY_CONFIRMED=1 npx lua deploy all', + 'LUA_DEPLOY_CONFIRMED=1 /usr/local/bin/lua deploy all', + 'LUA_DEPLOY_CONFIRMED=1 node node_modules/lua-cli/dist/index.js deploy all', + 'FOO=1 LUA_DEPLOY_CONFIRMED=1 lua deploy all', + 'LUA_DEPLOY_CONFIRMED=1 FOO=1 lua deploy all', + 'LUA_DEPLOY_CONFIRMED=1 env lua deploy all', + '"LUA_DEPLOY_CONFIRMED=1" lua deploy all', + 'sudo LUA_DEPLOY_CONFIRMED=1 lua deploy all', + 'if LUA_DEPLOY_CONFIRMED=1 lua deploy all; then :; fi', + ])('blocks %s', (cmd) => { + expect(isPrefixedDeploy(cmd)).toBe(false); + expect(classifyProductionCommand(cmd)?.prefixed).toBe(false); + }); + + test.each([ + 'cd agent && LUA_DEPLOY_CONFIRMED=1 lua deploy skill --ci --name x --set-version latest --force', + 'lua compile --ci && LUA_DEPLOY_CONFIRMED=1 lua deploy all --ci --force', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy skill --ci --force && LUA_DEPLOY_CONFIRMED=1 lua deploy webhook --ci --force', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy skill --ci --name x --set-version 1 --force > deploy.log 2>&1', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy all --ci --force 2>/dev/null', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy all --ci --force &> deploy.log', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy all --ci --force # ship it', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy all \\\n --ci --force', + 'LUA_DEPLOY_CONFIRMED=1 lua marketplace template publish --template-id t --changelog "fix: a; b && c" --yes', + "LUA_DEPLOY_CONFIRMED=1 lua workflows deploy outreach -v 'latest'", + 'LUA_DEPLOY_CONFIRMED=1 heylua version promote 3', + 'env LUA_DEPLOY_CONFIRMED=1 lua-ai mcp activate fs', + ])('allows %s', (cmd) => { + expect(isPrefixedDeploy(cmd)).toBe(true); + }); +}); + +describe('false-positive guards: text that only MENTIONS a verb', () => { + test.each([ + 'git commit -m "lua deploy all"', + "git commit -m 'chore: document lua version promote 3'", + "echo 'lua version promote 3'", + 'grep -r "lua deploy" .', + 'grep -rn "lua workflows activate" commands/', + 'lua push skill --ci --force && lua compile --ci', + 'lua chat --ci -e production -m "please lua deploy all" -t t1', + 'gh pr create --title "x" --body "run lua deploy all after merge"', + 'cat > notes.md < notes.md\nlua version promote 3\nEOF", + 'lua deployment', + 'lua workflows status deploy', + 'lua workflows deactivate outreach', + 'lua test --ci skill --name deploy', + 'lua logs --ci --type all --json 2>&1 | head -20', + 'arr=(lua deploy all); echo ok', + 'git log --oneline -5 # lua deploy all', + 'echo "\\"lua deploy\\" is gated"', + 'echo "cost: $5" && lua status --json --ci', + ])('%s', (cmd) => { + expect(classifyProductionCommand(cmd)).toBeNull(); + }); +}); + +describe('input the lexer cannot close falls back to a textual search (fail closed)', () => { + test.each([ + 'bash -c "lua deploy all', + "echo 'unterminated && lua deploy all", + 'echo $(lua deploy all', + 'echo `lua deploy all', + 'echo "`lua deploy all', + "echo $'lua deploy all", + 'arr=(lua deploy all', + 'lua-cli/dist/index.js --ci deploy all "', + ])('%s', (cmd) => { + expect(classifyProductionCommand(cmd)?.prefixed).toBe(false); + }); + + test('deeply nested shells stop recursing and search the rest as text', () => { + let cmd = 'lua deploy all'; + for (let k = 0; k < 10; k++) cmd = `eval ${JSON.stringify(cmd)}`; + expect(classifyProductionCommand(cmd)?.prefixed).toBe(false); + }); +}); + +describe('lex()', () => { + test('splits a chain into simple commands and marks pipelines and groups', () => { + const { segments, subs, opaque } = lex('a 1 && (b 2 | c 3); d "x y" 2>&1 > out'); + expect(opaque).toBe(false); + expect(subs).toEqual([]); + expect(segments.map((s) => s.words.map((w) => w.text))).toEqual([['a', '1'], ['b', '2'], ['c', '3'], ['d', 'x y']]); + expect(segments.map((s) => s.pipeline)).toEqual([false, true, true, false]); + expect(segments.map((s) => s.grouped)).toEqual([false, true, true, false]); + }); + + test('collects substitutions, heredocs and here-strings', () => { + const { segments, subs } = lex('x $(y) `z` <(w) <<< "h s"\ncat < { + const { segments } = lex('cat < { + const { segments } = lex('a "q\\"x\\\\y\\z" $"loc" b\\ c 3< in # c\n <> rw x >| y'); + expect(segments[0].words.map((w) => w.text)).toEqual(['a', 'q"x\\y\\z', 'loc', 'b c']); + expect(segments[1].words.map((w) => w.text)).toEqual(['x']); + }); + + test('double-quoted line continuation and a trailing escape', () => { + const { segments } = lex('a "x\\\ny" b\\'); + expect(segments[0].words.map((w) => w.text)).toEqual(['a', 'xy', 'b']); + }); + + test('an empty pipe stage still marks the pipeline', () => { + const { segments } = lex('a || b | | c'); + expect(segments.map((s) => s.pipeline)).toEqual([false, true, true]); + }); + + test('a substitution body keeps its quoted parentheses', () => { + expect(lex('echo $(printf \'a)\' "b)\\")" \\) x)').subs).toEqual(['printf \'a)\' "b)\\")" \\) x']); + expect(lex("echo $(printf 'a").opaque).toBe(true); + expect(lex('echo $(printf "a').opaque).toBe(true); + }); + + test('an unmatched ")" and a lone "$" do not throw', () => { + expect(lex('a ) b $').segments.map((s) => s.words.map((w) => w.text))).toEqual([['a'], ['b', '$']]); + }); +}); From c2732b0d17d313b444452daae7ace24b33bb2c5e Mon Sep 17 00:00:00 2001 From: lua-stefan-kruger Date: Sat, 26 Sep 2026 10:32:59 +0100 Subject: [PATCH 2/3] EM-WS8: fail closed on classifier errors; remove exponential backtracking in the textual fallback The textual-fallback option group could split --a two ways and backtracked exponentially on a failing match (28 options ~200 s), past the 10 s hook timeout, where the hook fails open. One parse per option now (<1 ms); an internal classifier error blocks any command that mentions a lua binary. Adds timing bounds, a 3000-case shell fuzz, and the fail-closed seam test. Co-Authored-By: Claude Opus 5.5 --- plugins/lua-agent-builder/CHANGELOG.md | 4 ++ plugins/lua-agent-builder/lib/tokenizer.mjs | 24 ++++++++++-- .../test/lib/tokenizer-hardening.test.mjs | 38 +++++++++++++++++++ 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/plugins/lua-agent-builder/CHANGELOG.md b/plugins/lua-agent-builder/CHANGELOG.md index 784749e..43f0913 100644 --- a/plugins/lua-agent-builder/CHANGELOG.md +++ b/plugins/lua-agent-builder/CHANGELOG.md @@ -54,6 +54,10 @@ It now lexes the command the way a POSIX shell does (quotes, escapes, `&& || ; | - Allowed: `cd agent && LUA_DEPLOY_CONFIRMED=1 lua deploy skill …`, and redirections such as `> deploy.log 2>&1`. - Every form `/lua-deploy`, the deploy pilot and `/lua-template` emit is unchanged and still allowed. - **Text that only *mentions* a verb stays unclassified**: `git commit -m "lua deploy all"`, `grep -r "lua deploy" .`, `lua chat … -m "please lua deploy all"`, and a heredoc written to a file. +- **Fails closed, and stays fast.** A hook that throws or runs past its 10 s timeout fails *open*, so: + - an internal classifier error now returns an unresolved, unprefixed hit for any command that mentions a lua binary; + - the textual-fallback option pattern has exactly one parse per option. A draft with `-{1,2}[\w-]+` backtracked exponentially (28 options β‰ˆ 200 s); it now takes under 1 ms. + - Tests bound pathological inputs to 500 ms and fuzz 3,000 random shell strings. - `classifyProductionCommand` keeps its `{ label, slash, prefixed }` shape, and `PRODUCTION_COMMANDS` keeps `label` / `slash` / `re`, now with a `seq` token table. `lex()` and `UNRESOLVED_LABEL` are new exports. - The `DEPLOY_DENIED_BARE` text now explains where the prefix counts. - New `test/lib/tokenizer-hardening.test.mjs`, about 170 cases: diff --git a/plugins/lua-agent-builder/lib/tokenizer.mjs b/plugins/lua-agent-builder/lib/tokenizer.mjs index b099960..43f933c 100644 --- a/plugins/lua-agent-builder/lib/tokenizer.mjs +++ b/plugins/lua-agent-builder/lib/tokenizer.mjs @@ -158,16 +158,26 @@ export const SMOKE_LABELS = new Set([ // Unanchored textual patterns β€” the fallback for input the lexer cannot close // and for inline interpreter code. `lua-cli/` covers a node entry point. +// +// The option group MUST have exactly one way to match each option: `--?` +// then a word character first. An earlier `-{1,2}[\w-]+` could split `--a` +// as `--`+`a` or `-`+`-a`, which backtracked exponentially on a failing +// match (28 options β‰ˆ 200 s) β€” past the hook timeout, and a hook that times +// out fails OPEN. test/lib/tokenizer-hardening.test.mjs pins the bound. +const RAW_OPTION = '(?:--?\\w[\\w-]*(?:=\\S*)?\\s+)*'; const RAW_PATTERNS = PRODUCTION_COMMANDS.map((e) => ({ entry: e, re: new RegExp( - `(? `(?:${alts.join('|')})`).join('\\s+(?:-{1,2}[\\w-]+(?:=\\S*)?\\s+)*') + + `(? `(?:${alts.join('|')})`).join(`\\s+${RAW_OPTION}`) + '(?![\\w-])', 'i', ), })); +/** Does the text mention a lua binary at all? (Used to fail closed on an internal error.) */ +const MENTIONS_LUA = /(? !h.prefixed) ?? hits[0]; return { label, slash, prefixed }; diff --git a/plugins/lua-agent-builder/test/lib/tokenizer-hardening.test.mjs b/plugins/lua-agent-builder/test/lib/tokenizer-hardening.test.mjs index 08ca064..255a482 100644 --- a/plugins/lua-agent-builder/test/lib/tokenizer-hardening.test.mjs +++ b/plugins/lua-agent-builder/test/lib/tokenizer-hardening.test.mjs @@ -302,6 +302,44 @@ describe('input the lexer cannot close falls back to a textual search (fail clos }); }); +describe('the classifier stays fast and fails closed (a hook that times out or throws fails OPEN)', () => { + // Before the fix, 28 options made the textual fallback backtrack for ~200 s. + test.each([ + ['inline code', 'node -e 1 "lua ' + '--a '.repeat(40) + 'zz"; lua deploy all', 'lua deploy'], + ['opaque input', 'lua ' + '--a '.repeat(40) + 'zz "', null], + ['opaque input with values', 'lua ' + '--a=1 '.repeat(40) + 'zz "', null], + ['opaque input that deploys', 'lua ' + '--a=1 '.repeat(40) + 'deploy all "', 'lua deploy'], + ['long chains', 'lua status --ci && '.repeat(400) + 'lua deploy all', 'lua deploy'], + ['deep substitutions', 'echo '.concat('$('.repeat(50), 'lua deploy all', ')'.repeat(50)), 'lua deploy'], + ])('%s', (_name, cmd, label) => { + const t0 = performance.now(); + const result = classifyProductionCommand(cmd); + expect(performance.now() - t0).toBeLessThan(500); + expect(result?.label ?? null).toBe(label); + }); + + test('random shell soup never throws and never takes long', () => { + const parts = ['"', "'", '\\', '$', '(', ')', '`', '|', '&', ';', '<', '>', '{', '}', '\n', ' ', '#', '=', + 'lua deploy all', 'lua', 'deploy', '--ci', '< { seed = (seed * 1103515245 + 12345) % 2 ** 31; return seed % n; }; + const t0 = performance.now(); + for (let k = 0; k < 3000; k++) { + let cmd = ''; + for (let p = rand(30); p > 0; p--) cmd += parts[rand(parts.length)]; + expect(() => classifyProductionCommand(cmd)).not.toThrow(); + } + expect(performance.now() - t0).toBeLessThan(10_000); + }); + + test('an internal error blocks a command that mentions lua, and ignores one that does not', () => { + const boom = () => { throw new Error('classifier bug'); }; + expect(classifyProductionCommand('lua status', { analyze: boom })) + .toEqual({ label: UNRESOLVED_LABEL, slash: '/lua-deploy', prefixed: false }); + expect(classifyProductionCommand('git status', { analyze: boom })).toBeNull(); + }); +}); + describe('lex()', () => { test('splits a chain into simple commands and marks pipelines and groups', () => { const { segments, subs, opaque } = lex('a 1 && (b 2 | c 3); d "x y" 2>&1 > out'); From 8c14feee0a3f727783fe82afc7bdcc5545d49924 Mon Sep 17 00:00:00 2001 From: lua-stefan-kruger Date: Sat, 26 Sep 2026 11:11:33 +0100 Subject: [PATCH 3/3] =?UTF-8?q?EM-WS8:=20address=20PR=20#15=20review=20?= =?UTF-8?q?=E2=80=94=20fail=20closed=20inside=20the=20hook=20timeout,=20cl?= =?UTF-8?q?ose=20bypasses,=20cut=20false=20positives?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. CRITICAL (hook times out β†’ fails open): the textual fallback is now a linear token scan reusing matchArgs (the RAW regexes were quadratic on `lua/` runs); findClose/heredoc skipping, matchArgs and command-position walking are linear. Commands over 32 KB, a spent 1.5 s budget, or an internal error block the command when it mentions lua (DEPLOY_DENIED_UNCLASSIFIABLE). New test/hooks/confirm-deploy.timeout spawns the real hook on adversarial inputs up to 100 KB and asserts a decision in < 2 s. 2. HIGH bypasses: computed binary + computed verb when the command mentions lua; `lua${IFS}deploy` split at expansions; unquoted globs and brace expansion are computed words; unicode spaces separate. 3. MEDIUM: env -S / --split-string, awk system()/pipes, osascript -e, editor -c '!…', sed e, git -c alias '!…', tmux/screen, docker exec sh -c, bash < <(…) / source <(…), $(…) in unquoted heredocs, heredoc written to a script that is then run. 4. MEDIUM false positives: findClose skips heredoc bodies and comments (Claude Code's own `gh pr create --body "$(cat <<'EOF' … EOF)"` passes); the binary is matched only in command position (`cp -r lua deploy`, `ls lua deploy`, `echo lua deploy all` pass); runners count only in command position (`rg x .` is not `source`). 5. LOW: dist/THIRD_PARTY_NOTICES.txt generated from the esbuild metafile (SDK + zod, MIT, full texts); legalComments: 'eof'. dist/server.js is byte-identical. The review's probe sets (bypass.json, fp.json, perf.mjs, e2e.mjs) are unit and spawned tests. 808 plugin tests + 149 MCP tests pass; coverage gates and all lints green. Co-Authored-By: Claude Opus 5.5 --- docs/JOB_TIER.md | 1 + plugins/lua-agent-builder/CHANGELOG.md | 35 +- plugins/lua-agent-builder/SECURITY.md | 2 +- .../hooks/confirm-deploy.mjs | 14 +- plugins/lua-agent-builder/lib/tokenizer.mjs | 552 +++++++++++++----- .../mcp/lua-platform/README.md | 4 +- .../lua-platform/dist/THIRD_PARTY_NOTICES.txt | 53 ++ .../mcp/lua-platform/scripts/bundle.mjs | 41 +- .../hooks/confirm-deploy.timeout.test.mjs | 49 ++ .../test/hooks/headless.test.mjs | 11 + .../test/lib/tokenizer-hardening.test.mjs | 200 ++++++- 11 files changed, 800 insertions(+), 162 deletions(-) create mode 100644 plugins/lua-agent-builder/mcp/lua-platform/dist/THIRD_PARTY_NOTICES.txt create mode 100644 plugins/lua-agent-builder/test/hooks/confirm-deploy.timeout.test.mjs diff --git a/docs/JOB_TIER.md b/docs/JOB_TIER.md index b2f237e..df29880 100644 --- a/docs/JOB_TIER.md +++ b/docs/JOB_TIER.md @@ -91,6 +91,7 @@ The following work inline with their arguments given up front: - in a string run by `bash -c` / `eval` / `ssh` / `… | sh`, or in a heredoc fed to a shell; - behind `FOO=1` prefixes, `sudo` / `env` / `timeout`, `npx lua`, `npx lua-cli`, `pnpm exec lua` or `node …/lua-cli/…`, and at a binary path. - A shell variable in the binary or verb position is blocked. +- It fails closed. A command over 32 KB, one that exhausts the 1.5 s budget, or an internal error is blocked if it mentions lua, because a hook that hits its timeout lets the command run. - The confirmation prefix counts only as the first word of the exact simple command that runs the verb. It is still a **belt**: diff --git a/plugins/lua-agent-builder/CHANGELOG.md b/plugins/lua-agent-builder/CHANGELOG.md index 43f0913..fdc2867 100644 --- a/plugins/lua-agent-builder/CHANGELOG.md +++ b/plugins/lua-agent-builder/CHANGELOG.md @@ -13,7 +13,7 @@ The lua-cli pin is unchanged (3.38.0). ### `lua-platform` runs with no `node_modules` -- `mcp/lua-platform/scripts/bundle.mjs` no longer marks `@modelcontextprotocol/sdk` external. `dist/server.js` now inlines every npm dependency from the committed lockfile: 106 KB β†’ 529 KB, against a 5 MB budget. +- `mcp/lua-platform/scripts/bundle.mjs` no longer marks `@modelcontextprotocol/sdk` external. `dist/server.js` now inlines every npm dependency from the committed lockfile: 106 KB β†’ 529 KB, against a 5 MB budget. The build also writes `dist/THIRD_PARTY_NOTICES.txt`, generated from the esbuild metafile: every bundled package (`@modelcontextprotocol/sdk`, `zod`, both MIT) with its version and full licence text. Any `/*! */` legal comments are kept at the end of the bundle. - Before this, a marketplace install, or the plugin baked into an image, died with `ERR_MODULE_NOT_FOUND`, which Claude Code reports as `lua-platform CONNECTION_CLOSED`. The plugin ships no `node_modules`, and `.mcp.json` launches `dist/server.js` directly. - A `createRequire` banner gives the ESM bundle a real `require` for any CommonJS dependency. - New `tests/standalone-bundle.test.mjs`: @@ -54,19 +54,40 @@ It now lexes the command the way a POSIX shell does (quotes, escapes, `&& || ; | - Allowed: `cd agent && LUA_DEPLOY_CONFIRMED=1 lua deploy skill …`, and redirections such as `> deploy.log 2>&1`. - Every form `/lua-deploy`, the deploy pilot and `/lua-template` emit is unchanged and still allowed. - **Text that only *mentions* a verb stays unclassified**: `git commit -m "lua deploy all"`, `grep -r "lua deploy" .`, `lua chat … -m "please lua deploy all"`, and a heredoc written to a file. -- **Fails closed, and stays fast.** A hook that throws or runs past its 10 s timeout fails *open*, so: - - an internal classifier error now returns an unresolved, unprefixed hit for any command that mentions a lua binary; - - the textual-fallback option pattern has exactly one parse per option. A draft with `-{1,2}[\w-]+` backtracked exponentially (28 options β‰ˆ 200 s); it now takes under 1 ms. - - Tests bound pathological inputs to 500 ms and fuzz 3,000 random shell strings. +- **Fails closed, and decides inside the hook timeout.** A PreToolUse hook that throws or runs past its 10 s timeout fails *open*. The independent review reproduced exactly that against a draft, with 24 KB inputs. So: + - Everything is linear. + - The textual fallback is a token scan that reuses the parser's argument matcher, not a set of regexes. + - Two regex drafts backtracked: one exponentially (28 options β‰ˆ 200 s), one quadratically (`lua/` Γ— 6000 β‰ˆ 10 s). + - A command over **32 KB** (`MAX_COMMAND_LENGTH`) is not parsed. + - A classification has a **1.5 s budget** (`TIME_BUDGET_MS`). + - An over-length command, a spent budget, or an internal error **blocks** the command if it mentions a lua binary (`DEPLOY_DENIED_UNCLASSIFIABLE`, `lua `), and passes it otherwise. + - New `test/hooks/confirm-deploy.timeout.test.mjs` spawns the real hook on adversarial inputs up to 100 KB, including the review's reproductions and inputs just under the cap. It asserts a decision in under 2 s. + - The review's performance probe and a 3,000-string shell fuzz run as unit tests. +- **Command position only.** The binary is recognised as the command a shell would run, not at any word position. + - Recognised: the first word after assignments, and the command a wrapper, launcher or shell keyword runs, including `find … -exec lua` and `if/then/do/coproc`. + - `cp -r lua deploy`, `ls lua deploy` and `echo lua deploy all` no longer block. + - A pipeline feeding a shell (`echo lua deploy all | sh`) is still searched. +- **Computed words (review finding 2).** An unquoted glob (`/usr/local/bin/lu? deploy`) or brace expansion (`{lua,} deploy`, `lua de{ploy,} all`) is a runtime-computed word, like `$VAR`. `lua${IFS}deploy${IFS}all` is split at its expansions. A computed binary with a computed verb (`$(printf lua) $(printf deploy) all`, `L=lua; V=deploy; $L $V all`) is blocked when the command mentions lua anywhere. Unicode spaces count as separators. +- **More strings that run as code (review finding 3):** + - `env -S` / `--split-string`; + - awk `system(…)`, `print … | "cmd"` and `"cmd" | getline`; + - `osascript -e`, and editor `-c '!…'` / `+cmd`; + - GNU sed's `e` command and `s///e`; + - `git -c alias.x='!…'`; + - `tmux` / `screen`, `docker exec c sh -c` (a shell name counts at any position), and `bash < <(…)` / `source <(…)`; + - `$(…)` inside an unquoted heredoc; + - a heredoc written to a script that the same command then runs (`cat > x.sh <` counts when the path is a lua-cli entry point -// (`…/lua-cli/dist/index.js`, `…/bin/lua`); +// * the lua binary is recognised in COMMAND POSITION, by basename +// (`/usr/local/bin/lua`, `./node_modules/.bin/heylua`, `lua.cmd`, `LUA`): +// the first word after env assignments, and the command a wrapper runs β€” +// `sudo`/`env`/`command`/`exec`/`timeout N`/`nohup`/`xargs`/`watch`/ +// `coproc`/`if`/`then`/…, launchers (`npx lua`, `npx lua-cli`, +// `npx -y lua-cli@3`, `pnpm exec lua`, `pnpm dlx lua-cli`, `yarn lua`, +// `npm exec -- lua`, `bunx lua`), `node [opts] …/lua-cli/dist/index.js` +// and `find … -exec lua …`. `cp -r lua deploy` is not a deploy; // * option tokens between the binary and the verb are skipped (both as // boolean flags and as `--flag value` pairs); -// * a shell variable in the binary or verb position (`$L deploy all`, -// `lua $VERB skill`) cannot be resolved and is blocked (fail closed); +// * a word the shell computes at runtime β€” `$VAR`, `$(…)`, `${IFS}`, +// `$'\x6c…'`, an unquoted glob (`lu?`) or brace expansion (`{lua,}`) β€” +// in the binary or verb position cannot be resolved and is blocked when +// the command mentions lua (fail closed); // * `$(…)`, backticks and `<(…)` are parsed recursively, also inside -// double quotes; a string handed to a shell (`bash -c`, `sh -c`, `eval`, -// `ssh host "…"`, `watch`, `npx -c`, `… | sh`, a heredoc or here-string -// fed to a shell, `trap`, `alias`) is parsed recursively too; inline code -// for `node -e` / `python -c` / `perl -e` is searched textually; +// double quotes and unquoted heredocs; heredoc bodies are skipped as text +// (`gh pr create --body "$(cat <<'EOF' … EOF)"` is not code); a string +// handed to a shell (`bash -c`, `eval`, `ssh`, `env -S`, `watch`, +// `tmux`, `npx -c`, `… | sh`, `bash < <(…)`, a heredoc fed to a shell or +// written to a script that is then run, `trap`, `alias`, +// `git -c alias.x='!…'`) is parsed recursively too; inline code for +// `node -e` / `python -c` / `perl -e` / `osascript -e`, awk `system(…)`, +// sed's `e` command and editor `-c '!…'` is searched as text; // * input the lexer cannot close (an unterminated quote or substitution) -// falls back to an unanchored textual search. +// falls back to a textual token search; +// * everything is linear; a command over MAX_COMMAND_LENGTH, one that runs +// past TIME_BUDGET_MS, or an internal error BLOCKS if the command +// mentions lua β€” the hook must decide inside its timeout, because a hook +// that times out fails open. // // The LUA_DEPLOY_CONFIRMED=1 allowance survives ONLY in its canonical shape: // `[env ]LUA_DEPLOY_CONFIRMED=1 lua|heylua|lua-ai …` as ONE simple @@ -87,31 +97,62 @@ const BINARIES = new Set(['lua', 'heylua', 'lua-ai']); /** Also accepted after a launcher (`npx lua-cli …`) or as a node entry point. */ const PACKAGES = new Set([...BINARIES, 'lua-cli']); -/** Commands that take ANOTHER command as argv (the verb can follow them). */ +/** + * Commands (and shell keywords) that take ANOTHER command as argv: the word + * after them β€” past their options and option values β€” is again in command + * position. The lua binary is only recognised in command position, so + * `cp -r lua deploy` and `ls lua deploy` are not deploys. + */ const WRAPPERS = new Set([ 'env', 'command', 'exec', 'builtin', 'nohup', 'time', 'nice', 'ionice', 'timeout', 'sudo', 'doas', 'xargs', 'stdbuf', 'setsid', 'caffeinate', 'unbuffer', 'chronic', 'npx', 'pnpx', 'bunx', 'npm', - 'pnpm', 'yarn', 'bun', 'run', 'exec', 'dlx', 'x', '!', '{', 'then', 'do', 'else', 'if', 'while', 'until', + 'pnpm', 'yarn', 'bun', 'run', 'dlx', 'x', 'eval', 'watch', 'coproc', 'flock', 'nodemon', 'entr', + 'node', 'nodejs', 'tsx', 'ts-node', 'deno', 'ssh', 'su', 'runuser', 'parallel', 'strace', 'ltrace', + 'gtimeout', 'unshare', 'chroot', 'nsenter', 'firejail', 'script', 'tmux', 'screen', + '!', 'then', 'do', 'else', 'elif', 'if', 'while', 'until', ]); -/** Commands that run a STRING as shell code (their string arguments are parsed recursively). */ +/** `find … -exec CMD …`: the word after one of these is in command position. */ +const EXEC_FLAGS = new Set(['-exec', '-execdir', '-ok', '-okdir']); + +/** Commands that run a STRING as shell code (their string arguments are parsed, and searched, as code). */ const SCRIPT_RUNNERS = new Set([ 'sh', 'bash', 'zsh', 'dash', 'ksh', 'mksh', 'ash', 'fish', 'busybox', 'pwsh', 'powershell', 'cmd', 'eval', 'ssh', 'su', 'runuser', 'script', 'flock', 'watch', 'parallel', 'npx', 'npm', 'concurrently', - 'nodemon', 'entr', 'trap', 'at', 'batch', + 'nodemon', 'entr', 'trap', 'at', 'batch', 'source', '.', 'tmux', 'screen', 'xargs', ]); -/** Interpreters whose inline code (`-e`, `-c`, `-p`, …) is searched textually. */ -const INLINE_CODE = new Set(['node', 'nodejs', 'bun', 'deno', 'python', 'python3', 'perl', 'ruby', 'php']); +/** Shell interpreters: their name counts as a runner at any word position. */ +const SHELLS = new Set(['sh', 'bash', 'zsh', 'dash', 'ksh', 'mksh', 'ash', 'fish', 'pwsh', 'powershell']); -/** `node`-like launchers that take a script path as their first positional. */ -const NODE_LIKE = new Set(['node', 'nodejs', 'bun', 'tsx', 'ts-node']); +/** Shells, and `source`/`.` β€” running one of these on a FILE executes whatever was written to it. */ +const FILE_RUNNERS = new Set(['sh', 'bash', 'zsh', 'dash', 'ksh', 'mksh', 'ash', 'fish', 'source', '.']); -/** Node options that consume the following word. */ -const NODE_VALUE_FLAGS = new Set(['-r', '--require', '--import', '--loader', '--experimental-loader', '--env-file', '--title', '--inspect-port']); +/** Interpreters whose inline code (after `-e`, `-c`, `-p`, `-r`, …) is searched textually. */ +const INLINE_CODE = new Set([ + 'node', 'nodejs', 'bun', 'deno', 'python', 'python2', 'python3', 'perl', 'ruby', 'php', 'osascript', + 'luajit', 'tclsh', 'rscript', 'pwsh', 'powershell', +]); +/** An option that introduces inline code for one of INLINE_CODE (`-e`, `-pe`, `-c`, `--eval`, …). */ +const INLINE_FLAG = /^-(?:[a-zA-Z]*[ecEpr]|-eval|-print|-command|-exec)$/; +/** awk runs shell commands through `system(…)`, `print … | "cmd"` and `"cmd" | getline`. */ +const AWK = new Set(['awk', 'gawk', 'mawk', 'nawk', 'busybox']); +const AWK_EXEC = /system\s*\(|\|\s*["'$]|["']\s*\|\s*getline|\|&/; +/** Editors whose `-c` / `+cmd` / `:!cmd` run shell commands. */ +const EDITORS = new Set(['vim', 'vi', 'nvim', 'ex', 'view', 'gvim', 'mvim', 'nano', 'emacs']); const MAX_DEPTH = 6; +/** + * Commands longer than this are not parsed: a command that mentions a lua + * binary is blocked as unclassifiable, any other passes. Every step below is + * linear, but the hook must decide well inside its 10 s timeout on any input β€” + * a hook that times out fails OPEN. + */ +export const MAX_COMMAND_LENGTH = 32 * 1024; +/** Wall-clock budget for one classification; exceeding it fails closed. */ +export const TIME_BUDGET_MS = 1500; + const rule = (label, seq, slash) => ({ label, seq, @@ -146,8 +187,10 @@ export const PRODUCTION_COMMANDS = [ rule('lua marketplace template apply', [['marketplace'], TEMPLATE, ['apply', 'deploy', 'fleet-apply', 'rollout']], '/lua-template'), ]; -/** Label for a lua invocation whose verb is a shell variable (cannot be resolved statically). */ +/** Label for a lua invocation whose binary or verb comes from an expansion (cannot be resolved statically). */ export const UNRESOLVED_LABEL = 'lua '; +/** Label for a command that mentions lua but could not be classified (too long, over budget, internal error). */ +export const UNCLASSIFIABLE_LABEL = 'lua '; /** Labels whose success should trigger the post-deploy smoke check (something now runs live). */ export const SMOKE_LABELS = new Set([ @@ -159,25 +202,33 @@ export const SMOKE_LABELS = new Set([ // Unanchored textual patterns β€” the fallback for input the lexer cannot close // and for inline interpreter code. `lua-cli/` covers a node entry point. // -// The option group MUST have exactly one way to match each option: `--?` -// then a word character first. An earlier `-{1,2}[\w-]+` could split `--a` -// as `--`+`a` or `-`+`-a`, which backtracked exponentially on a failing -// match (28 options β‰ˆ 200 s) β€” past the hook timeout, and a hook that times -// out fails OPEN. test/lib/tokenizer-hardening.test.mjs pins the bound. -const RAW_OPTION = '(?:--?\\w[\\w-]*(?:=\\S*)?\\s+)*'; -const RAW_PATTERNS = PRODUCTION_COMMANDS.map((e) => ({ - entry: e, - re: new RegExp( - `(? `(?:${alts.join('|')})`).join(`\\s+${RAW_OPTION}`) + - '(?![\\w-])', - 'i', - ), -})); - -/** Does the text mention a lua binary at all? (Used to fail closed on an internal error.) */ +// The textual fallback (for input the lexer cannot close, and for inline +// interpreter code) is a TOKEN scan, not a regex: split on everything that +// cannot be part of a word, then read each lua token's next few tokens with +// the same matchArgs() the parser uses. Linear in the text, and interruptible +// by the time budget. Two regex drafts were not: `-{1,2}[\w-]+` backtracked +// exponentially (28 options β‰ˆ 200 s) and a path group re-scanned the text +// from every `lua` (`lua/` Γ— 6000 β‰ˆ 10 s) β€” both past the hook timeout, where +// a hook fails OPEN. test/lib/tokenizer-hardening.test.mjs and +// test/hooks/confirm-deploy.timeout.test.mjs pin the bound. +const RAW_TOKEN_SPLIT = /[^\w.@/\\-]+/; + +/** Does the text mention a lua binary at all? (Used to fail closed.) */ const MENTIONS_LUA = /(? deadline) throw new BudgetExceeded('time budget exceeded'); +} + // ── Lexer ────────────────────────────────────────────────────────────────── /** @@ -186,13 +237,77 @@ const MENTIONS_LUA = /(? ({ words: [], sep: null, grouped: false, pipeline: false, pipeId: 0, heredocs: [], herestrings: [] }); +const newSegment = () => ({ + words: [], sep: null, grouped: false, pipeline: false, pipeId: 0, heredocs: [], herestrings: [], subs: [], +}); -/** Index of the `)` closing the `(` at `start`, honouring quotes and nesting; -1 if none. */ +/** + * Parse the delimiter of a heredoc whose `<<` starts at `i`. + * @returns {{delim: string, strip: boolean, quoted: boolean, end: number}} + */ +function parseHeredocDelim(src, i) { + const n = src.length; + i += 2; + const strip = src[i] === '-'; + if (strip) i++; + while (src[i] === ' ' || src[i] === '\t') i++; + let delim = ''; + let quoted = false; + while (i < n && !/[\s;&|<>()]/.test(src[i])) { + if (src[i] === "'" || src[i] === '"' || src[i] === '\\') quoted = true; + else delim += src[i]; + i++; + } + return { delim, strip, quoted, end: i }; +} + +/** + * Skip heredoc bodies that start at `i` (just after a newline), one per + * pending delimiter. Returns the index after the last body and each body. + */ +function skipHeredocBodies(src, i, pending) { + const n = src.length; + const bodies = []; + for (const h of pending) { + const lines = []; + while (i < n) { + checkBudget(); + let end = src.indexOf('\n', i); + if (end < 0) end = n; + const line = src.slice(i, end); + i = end + 1; + if ((h.strip ? line.replace(/^\t+/, '') : line) === h.delim) break; + lines.push(line); + } + if (i > n) i = n; + bodies.push(lines.join('\n')); + } + return { next: i, bodies }; +} + +/** + * Index of the `)` closing the `(` at `start`, honouring quotes, nesting and + * heredoc bodies (a body is literal text: `$(cat <<'EOF'\n it's \nEOF\n)` is + * how Claude Code writes every commit message and PR body); -1 if none. + */ function findClose(src, start) { let depth = 0; + let pending = []; for (let i = start; i < src.length; i++) { + checkBudget(); const c = src[i]; + if (c === '\n' && pending.length) { + i = skipHeredocBodies(src, i + 1, pending).next - 1; + pending = []; + continue; + } + if (c === '<' && src[i + 1] === '<') { + if (src[i + 2] === '<') { i += 2; continue; } + const h = parseHeredocDelim(src, i); + pending.push(h); + i = h.end - 1; + continue; + } if (c === '\\') { i++; continue; } if (c === "'") { const j = src.indexOf("'", i + 1); @@ -207,6 +322,13 @@ function findClose(src, start) { i = j; continue; } + if (c === '#' && (i === start + 1 || /[\s;&|(]/.test(src[i - 1]))) { + // A comment runs to end of line; its quotes and parentheses are text. + const nl = src.indexOf('\n', i); + if (nl < 0) return -1; + i = nl - 1; + continue; + } if (c === '(') depth++; else if (c === ')' && --depth === 0) return i; } @@ -224,9 +346,14 @@ function findBacktick(src, start) { /** * Split a shell command into simple commands. Collects command-substitution - * bodies (`$(…)`, backticks, `<(…)`) in `subs` for recursive inspection and + * bodies (`$(…)`, backticks, `<(…)`, and those inside an unquoted heredoc) in + * `subs` β€” and in the owning segment's `subs` β€” for recursive inspection, and * sets `opaque` when something could not be closed. * + * A word is `dynamic` when the shell would compute it at runtime: parameter + * or command expansion, ANSI-C quoting, an unquoted glob (`lu?`, `l*a`) or an + * unquoted brace expansion (`{lua,}`, `de{ploy,}`). + * * @param {string} src * @returns {{segments: Segment[], subs: string[], opaque: boolean}} */ @@ -236,30 +363,42 @@ export function lex(src) { const subs = []; let opaque = false; let seg = newSegment(); - /** @type {Word|null} */ + /** @type {(Word & {brace?: boolean})|null} */ let word = null; let depth = 0; let redirTarget = null; // null | 'file' | 'herestring' - /** @type {{delim: string, strip: boolean, seg: Segment}[]} */ + /** @type {{delim: string, strip: boolean, quoted: boolean, seg: Segment}[]} */ let pendingHeredocs = []; const n = src.length; let i = 0; + const addSub = (text) => { subs.push(text); seg.subs.push(text); }; const startWord = () => { if (!word) word = { text: '', quoted: false, dynamic: false }; return word; }; const endWord = () => { if (!word) return; - if (redirTarget === 'herestring') seg.herestrings.push(word.text); - if (redirTarget) redirTarget = null; - else if (!word.quoted && (word.text === '{' || word.text === '}')) { - // Brace group: `{ cmd; }` runs in the current shell but is still a group. - depth = Math.max(0, depth + (word.text === '{' ? 1 : -1)); - if (word.text === '{') seg.grouped = true; - } else seg.words.push(word); + const w = word; word = null; + if (w.brace && /\{[^{}]*(?:,|\.\.)[^{}]*\}/.test(w.text)) w.dynamic = true; + delete w.brace; + if (redirTarget) { + if (redirTarget === 'herestring') seg.herestrings.push(w.text); + redirTarget = null; + return; + } + if (!w.quoted && w.text === '{') { + // Brace group: `{ cmd; }` (also `function f { …; }`). What precedes it is + // its own command; what follows starts a new, grouped one. + if (seg.words.length) endSegment(';'); + depth++; + seg.grouped = true; + return; + } + if (!w.quoted && w.text === '}') { depth = Math.max(0, depth - 1); return; } + seg.words.push(w); }; const endSegment = (sep) => { endWord(); - if (seg.words.length || seg.heredocs.length || seg.herestrings.length) { + if (seg.words.length || seg.heredocs.length || seg.herestrings.length || seg.subs.length) { seg.sep = sep; if (depth > 0) seg.grouped = true; segments.push(seg); @@ -271,29 +410,46 @@ export function lex(src) { const takeSubstitution = (open) => { // `open` indexes the `(` of `$(`, `<(` or `>(`. const close = findClose(src, open); - if (close < 0) { opaque = true; subs.push(src.slice(open + 1)); return n; } - subs.push(src.slice(open + 1, close)); + if (close < 0) { opaque = true; addSub(src.slice(open + 1)); return n; } + addSub(src.slice(open + 1, close)); return close + 1; }; - const readHeredocBodies = () => { - for (const h of pendingHeredocs) { - const lines = []; - let found = false; - while (i < n) { - let end = src.indexOf('\n', i); - if (end < 0) end = n; - const line = src.slice(i, end); - i = end + 1; - if ((h.strip ? line.replace(/^\t+/, '') : line) === h.delim) { found = true; break; } - lines.push(line); + /** Command substitutions inside an UNQUOTED heredoc body run (`cat < { + for (let k = 0; k < body.length; k++) { + checkBudget(); + if (body[k] === '\\') { k++; continue; } + if (body[k] === '$' && body[k + 1] === '(') { + const close = findClose(body, k + 1); + const text = close < 0 ? body.slice(k + 2) : body.slice(k + 2, close); + if (close < 0) opaque = true; + subs.push(text); + owner.subs.push(text); + if (close < 0) return; + k = close; + } else if (body[k] === '`') { + const close = findBacktick(body, k); + const text = close < 0 ? body.slice(k + 1) : body.slice(k + 1, close); + if (close < 0) opaque = true; + subs.push(text); + owner.subs.push(text); + if (close < 0) return; + k = close; } - h.seg.heredocs.push(lines.join('\n')); - if (!found) i = n; } + }; + const readHeredocBodies = () => { + const { next, bodies } = skipHeredocBodies(src, i, pendingHeredocs); + pendingHeredocs.forEach((h, k) => { + h.seg.heredocs.push(bodies[k]); + if (!h.quoted) scanExpandingBody(bodies[k], h.seg); + }); + i = next; pendingHeredocs = []; }; while (i < n) { + checkBudget(); const c = src[i]; const next = src[i + 1]; @@ -320,6 +476,7 @@ export function lex(src) { let j = i + 1; let closed = false; while (j < n) { + checkBudget(); const d = src[j]; if (d === '"') { closed = true; break; } if (d === '\\') { @@ -334,8 +491,8 @@ export function lex(src) { if (d === '`') { const k = findBacktick(src, j); w.dynamic = true; - if (k < 0) { opaque = true; subs.push(src.slice(j + 1)); j = n; break; } - subs.push(src.slice(j + 1, k)); + if (k < 0) { opaque = true; addSub(src.slice(j + 1)); j = n; break; } + addSub(src.slice(j + 1, k)); w.text += '`…`'; j = k + 1; continue; @@ -352,8 +509,8 @@ export function lex(src) { const w = startWord(); w.dynamic = true; const k = findBacktick(src, i); - if (k < 0) { opaque = true; subs.push(src.slice(i + 1)); i = n; continue; } - subs.push(src.slice(i + 1, k)); + if (k < 0) { opaque = true; addSub(src.slice(i + 1)); i = n; continue; } + addSub(src.slice(i + 1, k)); w.text += '`…`'; i = k + 1; continue; @@ -378,7 +535,7 @@ export function lex(src) { i++; continue; } - if (c === ' ' || c === '\t' || c === '\r') { endWord(); i++; continue; } + if (c === ' ' || c === '\t' || c === '\r' || UNICODE_SPACE.test(c)) { endWord(); i++; continue; } if (c === '\n') { endWord(); i++; @@ -447,16 +604,9 @@ export function lex(src) { else endWord(); if (src.startsWith('<<<', i)) { i += 3; redirTarget = 'herestring'; continue; } if (src.startsWith('<<', i)) { - i += 2; - const strip = src[i] === '-'; - if (strip) i++; - while (src[i] === ' ' || src[i] === '\t') i++; - let delim = ''; - while (i < n && !/[\s;&|<>()]/.test(src[i])) { - if (src[i] !== "'" && src[i] !== '"' && src[i] !== '\\') delim += src[i]; - i++; - } - pendingHeredocs.push({ delim, strip, seg }); + const h = parseHeredocDelim(src, i); + pendingHeredocs.push({ delim: h.delim, strip: h.strip, quoted: h.quoted, seg }); + i = h.end; continue; } i++; @@ -469,7 +619,10 @@ export function lex(src) { redirTarget = 'file'; continue; } - startWord().text += c; + const w = startWord(); + if (c === '*' || c === '?' || c === '[') w.dynamic = true; // unquoted glob + if (c === '{') w.brace = true; // possible brace expansion, decided at endWord + w.text += c; i++; } if (pendingHeredocs.length) readHeredocBodies(); @@ -500,52 +653,82 @@ function commandName(text) { } const isFlag = (w) => w.text.length > 1 && w.text.startsWith('-'); +/** An assignment in the shell's sense (unquoted name). */ const isAssignment = (w) => !w.quoted && /^[A-Za-z_][A-Za-z0-9_]*=/.test(w.text); +/** Anything that LOOKS like an assignment β€” skipped when looking for the command (fail closed). */ +const looksLikeAssignment = (w) => /^[A-Za-z_][A-Za-z0-9_]*=/.test(w.text); const isPrefixWord = (w) => !!w && !w.quoted && !w.dynamic && w.text === 'LUA_DEPLOY_CONFIRMED=1'; +const nameOf = (w) => (w.dynamic ? '' : commandName(w.text)); -/** True when every word before `j` is an assignment, a wrapper/launcher, an option or a bare number. */ -function isCommandPosition(words, j) { - for (let k = 0; k < j; k++) { - const w = words[k]; - if (isAssignment(w) || isFlag(w) || /^\d+[smhd]?$/.test(w.text) || WRAPPERS.has(commandName(w.text))) continue; - return false; - } - return true; +/** Is `text` (a literal word, or the literal head of a dynamic one) a lua-cli binary or entry point? */ +function isLuaBinaryText(text, afterLauncher) { + const name = commandName(text); + if (BINARIES.has(name)) return true; + // `lua-cli` is the package name, not an installed binary: gated after a + // launcher (`npx lua-cli`), or as a path to the package. + if (name === 'lua-cli' && (afterLauncher || /[\\/]/.test(text))) return true; + // The entry point run by node or through its shebang: `…/lua-cli/dist/index.js`. + // Only the tail is examined, so a pathological 30 KB word costs one bounded scan. + return /(?:^|[\\/])(?:lua-cli|heylua|lua-ai)[\\/]\S*\.[mc]?js$/i.test(text.slice(-512)); } -/** Does `path` (the script handed to node) point at a lua-cli entry point? */ -function isLuaEntryPoint(path) { - const base = commandName(path).replace(/\.(?:m|c)?js$/i, ''); - if (PACKAGES.has(base)) return true; - return /(?:^|[\\/])(?:lua-cli|heylua|lua-ai)(?:[\\/]|$)/i.test(path); +/** Splits a dynamic word at its expansions: `lua${IFS}deploy${IFS}all` β†’ lua, deploy, all. */ +const EXPANSION = /\$\{[^}]*\}|\$[A-Za-z_][A-Za-z0-9_]*|\$[0-9@*#?$!-]|\$\(…\)|`…`|\$'[^']*'|[<>]\(…\)|[*?]|\[[^\]]*\]|[{},]/; + +/** + * Word indexes in command position: the first word after any leading + * assignments, and β€” after a wrapper (`sudo`, `env`, `npx`, `timeout`, `if`, + * `xargs`, `node`, …) β€” the next word past its options, option values, + * assignments and durations. An option's value may itself be the command + * (`sudo -u me lua …` vs `sudo -E lua …`), so both readings are kept. + * `find … -exec CMD` adds CMD. + */ +function commandPositions(words) { + const out = new Set(); + const seen = new Set(); + const walk = (start) => { + let k = start; + while (k < words.length && looksLikeAssignment(words[k])) k++; + if (k >= words.length || seen.has(k)) return; + seen.add(k); + out.add(k); + if (!WRAPPERS.has(nameOf(words[k]))) return; + let q = k + 1; + let afterFlag = false; + while (q < words.length) { + checkBudget(); + const w = words[q]; + if (w.text === '--' || isFlag(w)) { afterFlag = w.text !== '--' && !w.text.includes('='); q++; continue; } + if (looksLikeAssignment(w) || /^\d+(?:\.\d+)?[smhd]?$/.test(w.text)) { afterFlag = false; q++; continue; } + walk(q); + if (!afterFlag) return; + afterFlag = false; // it may have been the option's value: keep looking + q++; + } + }; + walk(0); + words.forEach((w, k) => { if (EXEC_FLAGS.has(w.text) && k + 1 < words.length) walk(k + 1); }); + return [...out].sort((a, b) => a - b); } /** - * If a lua-cli invocation starts at word `j`, return the index of its first - * argument (and whether the binary itself was a shell variable); else null. + * If a lua-cli invocation starts at word `j` (a command position), return its + * arguments and whether the binary itself was computed at runtime; else null. */ -function invocationAt(words, j) { +function invocationAt(words, j, afterLauncher) { const w = words[j]; + const rest = words.slice(j + 1, j + 1 + 64); if (w.dynamic) { - return isCommandPosition(words, j) ? { start: j + 1, dynamicHead: true } : null; - } - const name = commandName(w.text); - if (BINARIES.has(name)) return { start: j + 1, dynamicHead: false }; - // `lua-cli` is the package name, not an installed binary: gated after a - // launcher (`npx lua-cli`), or as a path to the package. - if (name === 'lua-cli' && (j > 0 || /[\\/]/.test(w.text))) return { start: j + 1, dynamicHead: false }; - // The entry point run directly through its shebang: `/opt/lua-cli/dist/index.js deploy`. - if (/(?:^|[\\/])(?:lua-cli|heylua|lua-ai)[\\/].*\.[mc]?js$/i.test(w.text)) return { start: j + 1, dynamicHead: false }; - if (NODE_LIKE.has(name)) { - let k = j + 1; - while (k < words.length && isFlag(words[k])) { - if (NODE_VALUE_FLAGS.has(words[k].text)) k++; - k++; - } - if (k < words.length && !words[k].dynamic && isLuaEntryPoint(words[k].text)) { - return { start: k + 1, dynamicHead: false }; + // `lua${IFS}deploy`, `"$DIR/lua"`: the literal part can still name lua. + const pieces = w.text.split(new RegExp(EXPANSION.source, 'g')).filter(Boolean); + if (pieces.length && isLuaBinaryText(pieces[0], true)) { + const extra = pieces.slice(1).flatMap((p) => p.split(/\s+/)).filter(Boolean) + .map((text) => ({ text, quoted: false, dynamic: false })); + return { args: [...extra, ...rest], dynamicHead: false }; } + return { args: rest, dynamicHead: true }; } + if (isLuaBinaryText(w.text, afterLauncher)) return { args: rest, dynamicHead: false }; return null; } @@ -555,7 +738,7 @@ function invocationAt(words, j) { * pairs β€” so neither reading hides a verb. * * @param {Word[]} args - * @param {boolean} allowDynamic a `$VAR` token may stand in for a verb + * @param {boolean} allowDynamic a computed token may stand in for a verb * @returns {{label: string, slash: string, dynamic: boolean}|null} */ function matchArgs(args, allowDynamic) { @@ -563,6 +746,7 @@ function matchArgs(args, allowDynamic) { const strict = []; // flags and the word after a value-less `--flag` dropped let pendingValue = false; for (const a of args) { + if (loose.length >= 3 && strict.length >= 3) break; if (a.text === '--') { pendingValue = false; continue; } if (isFlag(a)) { pendingValue = !a.text.includes('='); continue; } loose.push(a); @@ -592,56 +776,103 @@ function matchArgs(args, allowDynamic) { return dynamicHit; } -/** Unanchored textual search, for text the lexer cannot structure. */ +/** Unanchored textual search, for text the lexer cannot structure. Linear: a bounded window per lua token. */ function rawSearch(text, hits) { - for (const { entry, re } of RAW_PATTERNS) { - if (re.test(text)) hits.push({ label: entry.label, slash: entry.slash, prefixed: false }); + checkBudget(); + if (!MENTIONS_LUA.test(text)) return; + const toks = text.split(RAW_TOKEN_SPLIT); + for (let k = 0; k < toks.length; k++) { + checkBudget(); + const t = toks[k]; + if (!t || !isLuaBinaryText(t, true)) continue; + const args = []; + for (let q = k + 1; q < toks.length && args.length < 64; q++) { + if (toks[q]) args.push({ text: toks[q], quoted: false, dynamic: false }); + } + const m = matchArgs(args, false); + if (m) hits.push({ label: m.label, slash: m.slash, prefixed: false }); } } +/** GNU sed's `e` command / `s///e` flag runs the pattern space as a shell command. */ +function sedExecutes(script) { + if (/(?:^|[;\n{}]|\d|\$|\/)\s*e(?:\s|$)/.test(script)) return true; + const m = /^s(.)/.exec(script); + if (!m) return false; + const parts = script.split(m[1]); + return parts.length >= 4 && /e/.test(parts[parts.length - 1]); +} + /** + * @typedef {{nested: boolean, depth: number, mentionsLua: boolean}} Ctx * @param {Segment} seg - * @param {{nested: boolean, depth: number}} ctx + * @param {Ctx} ctx * @param {boolean} pipedIntoRunner another stage of this pipeline runs its input as code * @param {Array<{label: string, slash: string, prefixed: boolean}>} hits */ function analyzeSegment(seg, ctx, pipedIntoRunner, hits) { + checkBudget(); const words = seg.words; - const names = words.map((w) => (w.dynamic ? '' : commandName(w.text))); - const runsStrings = pipedIntoRunner || names.some((nm) => SCRIPT_RUNNERS.has(nm)); - const inlineCode = names.some((nm) => INLINE_CODE.has(nm)); - const nested = { nested: true, depth: ctx.depth + 1 }; - + const names = words.map(nameOf); + const positions = commandPositions(words); + // A runner counts in command position (`sudo bash -c`, `xargs sh -c`); a + // shell's name counts anywhere (`docker exec c sh -c …`). `rg x .` is not `source`. + const hasRunner = + positions.some((j) => SCRIPT_RUNNERS.has(names[j])) || names.some((nm) => SHELLS.has(nm)); + const runsStrings = pipedIntoRunner || hasRunner; + const inline = names.some((nm) => INLINE_CODE.has(nm)); + const awk = names.some((nm) => AWK.has(nm)); + const editor = names.some((nm) => EDITORS.has(nm)); + const sed = names.some((nm) => nm === 'sed' || nm === 'gsed'); + const hasEnv = names.includes('env'); + const nested = { ...ctx, nested: true, depth: ctx.depth + 1 }; + + // Whatever feeds a shell (`… | sh`) or a runner's argv (`ssh host lua …`, + // `eval lua …`) is searched as text as well as parsed. + if (runsStrings) rawSearch(words.map((w) => w.text).join(' '), hits); words.forEach((w, k) => { if (k === 0) return; + const prev = words[k - 1].text; if (runsStrings && /[\s;&|`$()]/.test(w.text)) analyzeScript(w.text, nested, hits); - if (inlineCode) rawSearch(w.text, hits); + if (inline && (INLINE_FLAG.test(prev) || (prev === 'eval' && names.includes('deno')))) rawSearch(w.text, hits); + if (awk && AWK_EXEC.test(w.text)) rawSearch(w.text, hits); + if (editor && (/^[-+]c$|^--cmd$/.test(prev) || /^[+:]/.test(w.text) || w.text.includes('!'))) rawSearch(w.text, hits); + if (sed && !isFlag(w) && sedExecutes(w.text)) rawSearch(w.text, hits); + if (hasEnv && (prev === '-S' || prev === '--split-string')) analyzeScript(w.text, nested, hits); + if (hasEnv && /^(?:-S|--split-string=)./.test(w.text)) analyzeScript(w.text.replace(/^(?:-S|--split-string=)/, ''), nested, hits); + // `git -c alias.x='!cmd'` runs cmd through the shell. + const alias = /^alias\.[^=]*=\s*!(.*)$/s.exec(w.text); + if (alias) { analyzeScript(alias[1], nested, hits); rawSearch(alias[1], hits); } if (names[0] === 'alias' || names[0] === 'trap') { const eq = w.text.indexOf('='); - if (eq > 0) analyzeScript(w.text.slice(eq + 1), nested, hits); + analyzeScript(eq > 0 ? w.text.slice(eq + 1) : w.text, nested, hits); } }); for (const body of [...seg.heredocs, ...seg.herestrings]) { - if (runsStrings || inlineCode || names.some((nm) => nm === 'source' || nm === '.')) { + if (runsStrings || inline || awk) { analyzeScript(body, nested, hits); - if (inlineCode) rawSearch(body, hits); + rawSearch(body, hits); } } + // `bash < <(echo lua …)`, `source <(…)`: the substitution's OUTPUT is code. + if (runsStrings) for (const sub of seg.subs) rawSearch(sub, hits); - for (let j = 0; j < words.length; j++) { - const inv = invocationAt(words, j); + for (const j of positions) { + const afterLauncher = j > 0; + const inv = invocationAt(words, j, afterLauncher); if (!inv) continue; - const args = words.slice(inv.start); - // `… | xargs lua` or `lua` with nothing but a variable after it: the verb - // arrives at runtime and cannot be classified. + // `… | xargs lua`: the verb arrives on stdin and cannot be classified. const fedByXargs = names.slice(0, j).includes('xargs'); - let match = matchArgs(args, !inv.dynamicHead); + // A computed binary with a computed verb (`$(printf lua) $(printf deploy)`) + // is blocked when the command mentions lua anywhere. + let match = matchArgs(inv.args, !inv.dynamicHead || ctx.mentionsLua); if (!match && fedByXargs && !inv.dynamicHead) { match = { label: UNRESOLVED_LABEL, slash: '/lua-deploy', dynamic: true }; } if (!match) continue; const canonicalPrefix = !inv.dynamicHead && + !words[j].dynamic && BINARIES.has(words[j].text) && ((j === 1 && isPrefixWord(words[0])) || (j === 2 && words[0].text === 'env' && !words[0].quoted && isPrefixWord(words[1]))); @@ -653,10 +884,11 @@ function analyzeSegment(seg, ctx, pipedIntoRunner, hits) { /** * @param {string} src - * @param {{nested: boolean, depth: number}} ctx + * @param {Ctx} ctx * @param {Array<{label: string, slash: string, prefixed: boolean}>} hits */ function analyzeScript(src, ctx, hits) { + checkBudget(); if (ctx.depth > MAX_DEPTH) { rawSearch(src, hits); return; } const { segments, subs, opaque } = lex(src); if (opaque) rawSearch(src, hits); @@ -665,13 +897,27 @@ function analyzeScript(src, ctx, hits) { // turns every string in the pipeline into code. const runnerPipes = new Set( segments - .filter((s) => s.pipeline && s.words.some((w) => !w.dynamic && SCRIPT_RUNNERS.has(commandName(w.text)))) + .filter((s) => s.pipeline && commandPositions(s.words).some((j) => SCRIPT_RUNNERS.has(nameOf(s.words[j])))) .map((s) => s.pipeId), ); for (const seg of segments) analyzeSegment(seg, ctx, runnerPipes.has(seg.pipeId), hits); - for (const sub of subs) analyzeScript(sub, { nested: true, depth: ctx.depth + 1 }, hits); + for (const sub of subs) analyzeScript(sub, { ...ctx, nested: true, depth: ctx.depth + 1 }, hits); + + // `cat > x.sh < { + const first = commandPositions(s.words)[0]; + if (first === undefined) return false; + const w = s.words[first]; + if (/\.(?:sh|bash|zsh|command)$/i.test(w.text)) return true; + return FILE_RUNNERS.has(nameOf(w)) && s.words.slice(first + 1).some((a) => !isFlag(a)); + }); + if (runsAFile) { + for (const s of segments) for (const body of [...s.heredocs, ...s.herestrings]) rawSearch(body, hits); + } } +const unclassifiable = () => ({ label: UNCLASSIFIABLE_LABEL, slash: '/lua-deploy', prefixed: false }); + /** * Classify a command. Returns null for commands that run no gated verb, or * `{ label, slash, prefixed }` for a production-affecting lua-cli verb. When a @@ -679,18 +925,28 @@ function analyzeScript(src, ctx, hits) { * returned (so one unconfirmed verb blocks the whole chain); `prefixed` is * true only when every gated verb in it carries the canonical prefix. * + * Fails closed: a command that mentions a lua binary and is longer than + * MAX_COMMAND_LENGTH, runs past TIME_BUDGET_MS, or trips an internal error + * is returned as UNCLASSIFIABLE_LABEL, unprefixed. + * * @param {unknown} command - * @param {{analyze?: Function}} [opts] β€” test seam for the fail-closed path + * @param {{analyze?: Function, budgetMs?: number}} [opts] β€” test seams * @returns {{label: string, slash: string, prefixed: boolean}|null} */ -export function classifyProductionCommand(command, { analyze = analyzeScript } = {}) { +export function classifyProductionCommand(command, { analyze = analyzeScript, budgetMs = TIME_BUDGET_MS } = {}) { if (typeof command !== 'string') return null; + const mentionsLua = MENTIONS_LUA.test(command); + if (command.length > MAX_COMMAND_LENGTH) return mentionsLua ? unclassifiable() : null; const hits = []; + deadline = performance.now() + budgetMs; + ticks = 0; try { - analyze(command, { nested: false, depth: 0 }, hits); + analyze(command, { nested: false, depth: 0, mentionsLua }, hits); } catch { - // Fail closed: a classifier bug must not wave a lua command through. - return MENTIONS_LUA.test(command) ? { label: UNRESOLVED_LABEL, slash: '/lua-deploy', prefixed: false } : null; + // A classifier bug or a spent budget must not wave a lua command through. + return mentionsLua ? unclassifiable() : null; + } finally { + deadline = Infinity; } if (hits.length === 0) return null; const { label, slash, prefixed } = hits.find((h) => !h.prefixed) ?? hits[0]; diff --git a/plugins/lua-agent-builder/mcp/lua-platform/README.md b/plugins/lua-agent-builder/mcp/lua-platform/README.md index 7543e8b..cf9dc5c 100644 --- a/plugins/lua-agent-builder/mcp/lua-platform/README.md +++ b/plugins/lua-agent-builder/mcp/lua-platform/README.md @@ -81,7 +81,9 @@ Output: `dist/server.js` β€” a single self-contained file. Since 1.6.0 every npm dependency, `@modelcontextprotocol/sdk` included, is bundled from the lockfile, so the server runs with no `node_modules` anywhere (a marketplace install, or the plugin baked into a Lua Job-tier image). -`tests/standalone-bundle.test.mjs` copies the bundle into an empty temp +The build also writes `dist/THIRD_PARTY_NOTICES.txt` (every bundled package, its +version and its full licence text, from the esbuild metafile); ship it with the +bundle. `tests/standalone-bundle.test.mjs` copies the bundle into an empty temp directory and lists the tools over stdio to keep it that way; rebuild after any change to `src/` or a dependency bump and commit `dist/`. The plugin's `.mcp.json` launches it via `node ${CLAUDE_PLUGIN_ROOT}/mcp/lua-platform/dist/server.js`; the built file diff --git a/plugins/lua-agent-builder/mcp/lua-platform/dist/THIRD_PARTY_NOTICES.txt b/plugins/lua-agent-builder/mcp/lua-platform/dist/THIRD_PARTY_NOTICES.txt new file mode 100644 index 0000000..2ba01c5 --- /dev/null +++ b/plugins/lua-agent-builder/mcp/lua-platform/dist/THIRD_PARTY_NOTICES.txt @@ -0,0 +1,53 @@ +Third-party software bundled into dist/server.js (@lua/claude-plugin-mcp). +Generated by scripts/bundle.mjs from the esbuild metafile; do not edit by hand. + +@modelcontextprotocol/sdk@0.6.1 β€” MIT + +MIT License + +Copyright (c) 2024 Anthropic, PBC + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +------------------------------------------------------------------------------ + +zod@3.25.76 β€” MIT +Source: git+https://github.com/colinhacks/zod.git + +MIT License + +Copyright (c) 2025 Colin McDonnell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/lua-agent-builder/mcp/lua-platform/scripts/bundle.mjs b/plugins/lua-agent-builder/mcp/lua-platform/scripts/bundle.mjs index 36b9b34..c289f82 100644 --- a/plugins/lua-agent-builder/mcp/lua-platform/scripts/bundle.mjs +++ b/plugins/lua-agent-builder/mcp/lua-platform/scripts/bundle.mjs @@ -1,5 +1,7 @@ #!/usr/bin/env node import { build } from 'esbuild'; +import { readFileSync, readdirSync, writeFileSync, existsSync } from 'node:fs'; +import { join } from 'node:path'; // EM-WS8 (1.6.0): EVERYTHING is bundled, `@modelcontextprotocol/sdk` included. // The plugin ships no node_modules β€” marketplace installs copy the directory @@ -16,7 +18,12 @@ import { build } from 'esbuild'; // // The banner gives the ESM bundle a real `require`, so any CommonJS module // the SDK pulls in can still `require()` a node builtin. -await build({ +// +// Licences: the bundle redistributes third-party code, so the build also +// writes dist/THIRD_PARTY_NOTICES.txt β€” every npm package esbuild actually +// pulled in (from the metafile), with its version, licence and full licence +// text β€” and keeps any `/*! … */` legal comments at the end of the bundle. +const result = await build({ entryPoints: ['src/server.mjs'], bundle: true, platform: 'node', @@ -26,8 +33,38 @@ await build({ js: "import { createRequire as __luaCreateRequire } from 'node:module'; const require = __luaCreateRequire(import.meta.url);", }, minify: true, + legalComments: 'eof', + metafile: true, sourcemap: 'inline', outfile: 'dist/server.js', }); -console.log('βœ“ Bundled to dist/server.js (self-contained, no runtime node_modules needed)'); +/** node_modules//… β†’ package directory, for every bundled input. */ +const packageDirs = new Set(); +for (const input of Object.keys(result.metafile.inputs)) { + const m = /^(.*?node_modules\/(?:@[^/]+\/)?[^/]+)\//.exec(input.replace(/\\/g, '/')); + if (m) packageDirs.add(m[1]); +} + +const LICENCE_FILE = /^(?:licen[cs]e|copying|notice)(?:[.-].*)?$/i; +const sections = [...packageDirs].sort().map((dir) => { + const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')); + const licence = typeof pkg.license === 'string' ? pkg.license : pkg.license?.type ?? 'UNKNOWN'; + const files = existsSync(dir) ? readdirSync(dir).filter((f) => LICENCE_FILE.test(f)).sort() : []; + const texts = files.map((f) => readFileSync(join(dir, f), 'utf8').trim()); + return [ + `${pkg.name}@${pkg.version} β€” ${licence}`, + pkg.repository ? `Source: ${typeof pkg.repository === 'string' ? pkg.repository : pkg.repository.url}` : null, + '', + texts.length ? texts.join('\n\n') : `(No licence file ships with the package; its package.json declares ${licence}.)`, + ].filter((l) => l !== null).join('\n'); +}); + +writeFileSync( + 'dist/THIRD_PARTY_NOTICES.txt', + 'Third-party software bundled into dist/server.js (@lua/claude-plugin-mcp).\n' + + 'Generated by scripts/bundle.mjs from the esbuild metafile; do not edit by hand.\n\n' + + sections.join('\n\n' + '-'.repeat(78) + '\n\n') + '\n', +); + +console.log(`βœ“ Bundled to dist/server.js (self-contained, no runtime node_modules needed); ${packageDirs.size} third-party package(s) listed in dist/THIRD_PARTY_NOTICES.txt`); diff --git a/plugins/lua-agent-builder/test/hooks/confirm-deploy.timeout.test.mjs b/plugins/lua-agent-builder/test/hooks/confirm-deploy.timeout.test.mjs new file mode 100644 index 0000000..4f49a6e --- /dev/null +++ b/plugins/lua-agent-builder/test/hooks/confirm-deploy.timeout.test.mjs @@ -0,0 +1,49 @@ +// EM-WS8 review finding 1: a PreToolUse hook that is killed by its timeout +// (10 s in hooks.json) fails OPEN β€” the command runs. The independent review +// reproduced exactly that with 24 KB inputs against an earlier draft. This +// test spawns the REAL hook script, as Claude Code does, on adversarial inputs +// up to 100 KB and asserts it DECIDES (exit 2 / exit 0, never a signal) well +// inside the timeout. + +import { describe, test, expect } from '@jest/globals'; +import { runHook } from '../helpers/run-hook.mjs'; +import { MAX_COMMAND_LENGTH } from '../../lib/tokenizer.mjs'; + +const LIMIT_MS = 2_000; +const KB = 1024; +const fill = (unit, bytes) => unit.repeat(Math.ceil(bytes / unit.length)); + +// [name, command, expected exit code] +const CASES = [ + // The review's reproductions, at their size and at 100 KB. + ['opaque lua/ run, 24 KB', 'lua deploy all; echo ' + fill('lua/', 24 * KB) + " '", 2], + ['inline-code lua/ run, 16 KB', 'node -e "' + fill('lua/', 16 * KB) + '"; lua deploy all', 2], + ['lua words, 60 KB', 'echo ' + fill('lua ', 60 * KB) + '; lua deploy all', 2], + ['opaque lua/ run, 100 KB', 'lua deploy all; echo ' + fill('lua/', 100 * KB) + " '", 2], + ['inline-code lua/ run, 100 KB', 'node -e "' + fill('lua/', 100 * KB) + '"; lua deploy all', 2], + ['lua words, 100 KB', 'echo ' + fill('lua ', 100 * KB) + '; lua deploy all', 2], + ['options, 100 KB', 'lua ' + fill('--a ', 100 * KB) + 'x "', 2], + ['nested substitutions, 100 KB', fill('$(', 50 * KB) + 'lua deploy all' + fill(')', 50 * KB), 2], + ['heredocs, 100 KB', fill('cat < { + test.each(CASES)('%s', async (_name, command, expectedExit) => { + const t0 = Date.now(); + const result = await runHook( + 'confirm-deploy.mjs', + { tool_input: { command } }, + { timeoutMs: 10_000, env: { LUA_PLUGIN_HEADLESS: '' } }, + ); + const elapsed = Date.now() - t0; + expect({ exitCode: result.exitCode, fast: elapsed < LIMIT_MS }).toEqual({ exitCode: expectedExit, fast: true }); + }, 15_000); +}); diff --git a/plugins/lua-agent-builder/test/hooks/headless.test.mjs b/plugins/lua-agent-builder/test/hooks/headless.test.mjs index 79c49f7..296c4dc 100644 --- a/plugins/lua-agent-builder/test/hooks/headless.test.mjs +++ b/plugins/lua-agent-builder/test/hooks/headless.test.mjs @@ -149,6 +149,17 @@ describe('confirm-deploy headless: every production verb blocked, the prefix is }); }); +describe('confirm-deploy: an unclassifiable command', () => { + test('is blocked with its own reason, interactive and headless alike', () => { + const command = `lua status ${'x'.repeat(40 * 1024)}`; + const interactive = confirmDeploy({ tool_input: { command } }, INTERACTIVE); + expect(interactive?.block).toBe(true); + expect(interactive?.reason).toContain('DEPLOY_DENIED_UNCLASSIFIABLE'); + expect(interactive?.reason).not.toMatch(SLASH); + expect(confirmDeploy({ tool_input: { command } }, HEADLESS)?.block).toBe(true); + }); +}); + describe('block-auto-deploy headless', () => { test('still blocks, names no slash', () => { const result = blockAutoDeploy({ tool_input: { command: 'lua push all --auto-deploy' } }, HEADLESS); diff --git a/plugins/lua-agent-builder/test/lib/tokenizer-hardening.test.mjs b/plugins/lua-agent-builder/test/lib/tokenizer-hardening.test.mjs index 255a482..d3d4d60 100644 --- a/plugins/lua-agent-builder/test/lib/tokenizer-hardening.test.mjs +++ b/plugins/lua-agent-builder/test/lib/tokenizer-hardening.test.mjs @@ -3,7 +3,9 @@ // neighbour them. Every case here PASSED the 1.5.0 regex classifier. import { describe, test, expect } from '@jest/globals'; -import { classifyProductionCommand, isPrefixedDeploy, lex, UNRESOLVED_LABEL } from '../../lib/tokenizer.mjs'; +import { + classifyProductionCommand, isPrefixedDeploy, lex, UNRESOLVED_LABEL, UNCLASSIFIABLE_LABEL, MAX_COMMAND_LENGTH, TIME_BUDGET_MS, +} from '../../lib/tokenizer.mjs'; const bare = (label, slash = '/lua-deploy') => ({ label, slash, prefixed: false }); const DEPLOY = bare('lua deploy'); @@ -335,9 +337,203 @@ describe('the classifier stays fast and fails closed (a hook that times out or t test('an internal error blocks a command that mentions lua, and ignores one that does not', () => { const boom = () => { throw new Error('classifier bug'); }; expect(classifyProductionCommand('lua status', { analyze: boom })) - .toEqual({ label: UNRESOLVED_LABEL, slash: '/lua-deploy', prefixed: false }); + .toEqual({ label: UNCLASSIFIABLE_LABEL, slash: '/lua-deploy', prefixed: false }); expect(classifyProductionCommand('git status', { analyze: boom })).toBeNull(); }); + + test('a spent time budget fails closed', () => { + const cmd = 'lua status --ci && '.repeat(2000) + 'lua status'; + expect(classifyProductionCommand(cmd, { budgetMs: -1 })) + .toEqual({ label: UNCLASSIFIABLE_LABEL, slash: '/lua-deploy', prefixed: false }); + expect(classifyProductionCommand(cmd.replace(/lua/g, 'git'), { budgetMs: -1 })).toBeNull(); + // The budget is per call: the next call starts fresh. + expect(classifyProductionCommand('lua status --ci')).toBeNull(); + }); + + test(`a command over ${MAX_COMMAND_LENGTH} bytes is blocked if it mentions lua, passed if not`, () => { + const pad = 'x'.repeat(MAX_COMMAND_LENGTH); + expect(classifyProductionCommand(`lua status ${pad}`)) + .toEqual({ label: UNCLASSIFIABLE_LABEL, slash: '/lua-deploy', prefixed: false }); + expect(classifyProductionCommand(`git status ${pad}`)).toBeNull(); + }); + + // The reviewer's performance probe: every shape decides within budget. + test.each([ + ['opts-unclosed', 'lua ' + '--a '.repeat(5000) + 'x "'], + ['opts-unclosed-mixed', 'lua ' + '-a=b --c-d '.repeat(2500) + "'"], + ['many-lua-unclosed', 'lua lua-cli/x '.repeat(2000) + "'"], + ['many-lua-words', 'lua '.repeat(7000) + 'x'], + ['nested-subs', '$('.repeat(3000) + 'lua deploy all' + ')'.repeat(3000)], + ['nested-unclosed', '$('.repeat(15000)], + ['nested-quotes-subs', '"$('.repeat(3000) + 'x' + ')"'.repeat(3000)], + ['many-subs', '$(true) '.repeat(4000)], + ['many-backticks-unclosed', '`' + ' $( '.repeat(7000)], + ['open-parens', '('.repeat(30000)], + ['findclose-quad', '$( '.repeat(5000) + "'"], + ['dq-subs-unclosed', '"' + '$( '.repeat(5000)], + ['backtick-dq', '"' + '`x` '.repeat(7000)], + ['heredocs', 'cat < { + const t0 = performance.now(); + expect(() => classifyProductionCommand(cmd)).not.toThrow(); + expect(performance.now() - t0).toBeLessThan(TIME_BUDGET_MS + 250); + }); +}); + +// The independent review's probe sets (bypass.json / fp.json), verbatim. +describe('review probes: bypasses are blocked', () => { + test.each([ + '{lua,} deploy all', + 'lua de{ploy,} all', + 'lua {deploy,} all', + '/usr/local/bin/lu? deploy all', + '/usr/local/bin/l*a deploy all', + 'lua${IFS}deploy${IFS}all', + '$(printf lua) $(printf deploy) all', + 'L=lua; V=deploy; $L $V all', + 'env -S "lua deploy all"', + 'env --split-string="lua deploy all"', + 'tmux new -d "lua deploy all"', + 'awk \'BEGIN{system("lua deploy all")}\'', + 'gawk \'BEGIN{print "x" | "lua deploy all"}\'', + "osascript -e 'do shell script \"lua deploy all\"'", + "git -c alias.x='!lua deploy all' x", + "vim -c '!lua deploy all' -c q", + "sed -n '1e lua deploy all' /etc/hosts", + "sed 's/x/lua deploy all/e' f", + 'lua\tdeploy all', + "find . -maxdepth 0 -exec sh -c 'lua deploy all' \\;", + 'find . -maxdepth 0 -exec lua deploy all \\;', + 'xargs -a <(echo deploy all) lua', + 'echo deploy all | xargs -I{} lua {}', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy all\nlua version promote 3', + 'L\\UA_DEPLOY_CONFIRMED=1 lua deploy all', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy all & lua version promote 3', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy all || lua mcp on x', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy all <<< "$(lua version promote 3)"', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy all\\\n; lua version promote 3', + 'lua Deploy all', + 'LUA deploy all', + 'Lua.exe deploy all', + "ruby -e 'system %q(lua deploy all)'", + "parallel ::: 'lua deploy all'", + 'watch -n1 lua deploy all', + 'coproc lua deploy all', + 'case x in x) lua deploy all;; esac', + 'function f { lua deploy all; }; f', + "x=$'\\x6cua'; $x deploy all", + "$'\\x6cua' deploy all", + "lua $'\\x64eploy' all", + 'lua "$(echo deploy)" all', + "printf '%s' 'lua deploy all' | bash", + 'echo lua deploy all | sh', + "bash <<< 'lua deploy all'", + 'bash < <(echo lua deploy all)', + 'source <(echo lua deploy all)', + 'lua --profile=x -- deploy all', + 'npx --yes lua-cli@latest deploy all', + 'npm x lua-cli deploy all', + 'node --require=x ./node_modules/lua-cli/dist/index.js deploy all', + 'node --no-warnings --stack-size 999 ./node_modules/lua-cli/dist/index.js deploy all', + 'node --stack-size 999 ./node_modules/lua-cli/dist/index.js deploy all', + 'lua marketplace templates rollout x', + 'lua persona live publish', + "cat > x.sh <<'EOF'\nlua deploy all\nEOF\nsh x.sh", + "cat > x.sh <<'EOF'\nlua deploy all\nEOF\n./x.sh", + 'cat < { + const c = classifyProductionCommand(cmd); + expect(c).not.toBeNull(); + expect(c.prefixed).toBe(false); + }); + + test('not bypasses: a comment, and command names lua-cli does not have', () => { + expect(classifyProductionCommand('LUA_DEPLOY_CONFIRMED=1 lua deploy all # ; lua version promote 3')?.prefixed).toBe(true); + expect(classifyProductionCommand('lua workflow deploy x -v 1')).toBeNull(); + expect(classifyProductionCommand('lua skill deploy')).toBeNull(); + }); +}); + +describe('review probes: interactive commands are not blocked', () => { + test.each([ + 'lua compile --ci', + "lua test skill --name x --input '{}' --ci", + 'lua chat --ci -e sandbox -m "please deploy all the things" -t abc', + 'lua chat --ci -e production -m "lua deploy all" -t abc', + 'lua push all --ci --force', + 'lua push skill --name deploy --ci', + 'lua logs --ci --json --type deploy', + 'lua logs --ci --json --since 1h | jq \'.[] | select(.msg|test("deploy"))\'', + 'lua status --json --ci', + 'lua version list', + 'lua version create -m "before deploy"', + 'lua workflows list', + 'lua env production --list', + "git commit -m \"$(cat <<'EOF'\nfix: don't run lua deploy all bare (it's gated)\n\nCo-Authored-By: x\nEOF\n)\"", + "git commit -m \"$(cat <<'EOF'\nfeat(deploy): support lua version promote (see docs)\nEOF\n)\"", + "gh pr create --title x --body \"$(cat <<'EOF'\n## Summary\n- blocks `lua deploy all` bare\n- it's fine :)\nEOF\n)\"", + "git log --oneline | grep 'lua deploy'", + 'grep -rn "lua deploy" docs/', + "rg 'lua version promote' .", + "cat > notes.md <<'EOF'\nRun lua deploy all after review\nEOF", + 'npm test && npm run lint', + 'npm run deploy', + 'cp -r lua deploy', + 'ls lua deploy', + 'echo lua deploy all', + 'cd lua && npm install', + 'node scripts/check.mjs "lua deploy all"', + "python3 -c 'print(1)' && echo done", + 'echo "Next: lua deploy all"', + "echo 'Next: lua deploy all'", + "printf 'lua deploy all\\n' >> TODO.md", + "sed -i '' 's/lua deploy all/LUA_DEPLOY_CONFIRMED=1 lua deploy all/' README.md", + "awk '/lua deploy/ {print}' notes.md", + ])('%j', (cmd) => { + expect(classifyProductionCommand(cmd)).toBeNull(); + }); + + test.each([ + 'LUA_DEPLOY_CONFIRMED=1 lua deploy skill --name x --skill-version 3 --ci --force', + 'LUA_DEPLOY_CONFIRMED=1 lua version promote 4 --ci', + 'env LUA_DEPLOY_CONFIRMED=1 lua mcp activate x --ci', + 'cd agent && LUA_DEPLOY_CONFIRMED=1 lua deploy all --ci --force', + 'LUA_DEPLOY_CONFIRMED=1 lua deploy all --ci --force && lua status --json --ci', + ])('the confirmed form is allowed: %j', (cmd) => { + expect(isPrefixedDeploy(cmd)).toBe(true); + }); + + test.each([ + 'LUA_DEPLOY_CONFIRMED=1 lua deploy all --ci --force 2>&1 | tail -20', + 'LUA_DEPLOY_CONFIRMED=1 npx lua deploy all', + ])('by design a pipe or launcher voids the prefix: %j', (cmd) => { + expect(classifyProductionCommand(cmd)?.prefixed).toBe(false); + }); }); describe('lex()', () => {