From 2dca5ec426b7d3cd3ad96817151c48c028348ca8 Mon Sep 17 00:00:00 2001 From: lua-stefan-kruger Date: Sun, 20 Sep 2026 15:23:52 +0100 Subject: [PATCH] =?UTF-8?q?feat(plugin):=201.4.0=20=E2=80=94=20Job-tier=20?= =?UTF-8?q?billing=20is=20per=20model=20reply,=20and=20the=20lua-cli=203.3?= =?UTF-8?q?7.0=20cost=20read-outs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The plugin described a Job-tier attempt as a flat 4 credits and every run budget in "credits". Both are wrong for a priced run. Verified against lua-core-services main ebcf6689c (the lua-cli 3.37.0 release) — the CLI renderers, the wire shapes, lua-api's deploy advisory, the Job model legs and labels in shared-types and lua-core's Job rate module — never the docs. The rule (platform behaviour, true on every CLI, so NOT marked with a version gate): a Job step is billed per model REPLY, not per attempt — one credit per reply on a legacy plan, actions (price band × the model's multiplier per model call, cached prompt tokens at the fraction the provider charges) on a seat plan. The flat "1 credit / 4 credits" rule is kept, scoped to a run the platform is still metering flat, which is what `status` prints verbatim for such a run. A Job step runs on its own `model`, failing that the platform's Job default, failing that the org's — never the agent's — so leaving it off is a cost decision. `raise-budget --credits ` keeps its flag name on both plans but `` is a cap in the run's own unit. The read-outs (marked ⏳ 3.37.0 and described as printed only when the server projects them): the `Tokens:` line and the Uncached/Cached/Output step columns (signals, not charges — never summed: a cache read is a subset of input), the ⚙ Job-model line, the engine-aware budget sentence and `finished past the cap`, the three budget events in `workflows logs`, the unit-aware `raise-budget` confirmation and the `job-model-default` deploy advisory. lua-cli 3.37.0 adds NO command and NO option — its only command-definitions change is the `--credits` help string — so every shape the plugin emits still runs on 3.36.0 and only prints less. `PINNED_MIN_LUA_CLI` moves to 3.37.0 because the subagents now read that output. `lint-pinned-version` is therefore red by design until 3.37.0 is on npm; it was not weakened. No permission rule, hook, tokenizer or lint verb list changed, because no command surface did. Audit: lua-docs-v2-plan/plan-job-billing/reviews/plugin-audit-2026-09-20.md Co-Authored-By: Claude Fable 5.1 --- .claude-plugin/marketplace.json | 2 +- README.md | 2 +- docs/USER_GUIDE.md | 16 +++++++---- .../.claude-plugin/plugin.json | 2 +- plugins/lua-agent-builder/CHANGELOG.md | 28 +++++++++++++++++++ plugins/lua-agent-builder/README.md | 4 +-- .../lua-agent-builder/agents/lua-architect.md | 5 ++-- plugins/lua-agent-builder/agents/lua-debug.md | 1 + .../agents/lua-deploy-pilot.md | 1 + plugins/lua-agent-builder/agents/lua-qa.md | 2 +- .../agents/lua-skill-builder.md | 2 +- .../lua-agent-builder/commands/lua-deploy.md | 2 +- .../lua-agent-builder/commands/lua-doctor.md | 2 +- .../lua-agent-builder/commands/lua-init.md | 2 +- .../lua-agent-builder/commands/lua-logs.md | 2 +- .../lua-agent-builder/commands/lua-push.md | 2 +- .../lua-agent-builder/commands/lua-status.md | 2 +- .../lua-agent-builder/commands/lua-update.md | 2 +- .../commands/lua-workflow.md | 6 ++-- .../hooks/check-lua-version.mjs | 23 +++++++++------ .../lib/knowledge/cli-reference.md | 6 ++-- .../lib/knowledge/decision-trees.md | 4 ++- .../lib/knowledge/primitives.md | 7 +++-- .../lib/knowledge/workflows.md | 27 ++++++++++++------ .../mcp/lua-platform/dist/server.js | 6 ++-- .../mcp/lua-platform/package-lock.json | 4 +-- .../mcp/lua-platform/package.json | 2 +- .../mcp/lua-platform/src/api-client.mjs | 2 +- .../mcp/lua-platform/src/server.mjs | 6 ++-- plugins/lua-agent-builder/package-lock.json | 4 +-- plugins/lua-agent-builder/package.json | 2 +- 31 files changed, 118 insertions(+), 60 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index aea8ec4..11fdd88 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.3.0", + "version": "1.4.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 0547038..183022c 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,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/) | 20 slash commands, 5 subagents, 10 hooks, a 5-file knowledge base verified against lua-cli source (3.33.0 base; 1.3.0 adds per-step model classes and the workflow autonomy envelope from lua-cli 3.36.0, read from `main` / `feat/workflow-autonomy`), a local read-only platform MCP server and the public docs MCP | +| [`lua-agent-builder`](./plugins/lua-agent-builder/) | 20 slash commands, 5 subagents, 10 hooks, a 5-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, read from `main`), a local read-only platform MCP server and the public docs MCP | ## Quick walkthrough diff --git a/docs/USER_GUIDE.md b/docs/USER_GUIDE.md index 5a8d6ae..bd67a48 100644 --- a/docs/USER_GUIDE.md +++ b/docs/USER_GUIDE.md @@ -2,7 +2,7 @@ A complete walkthrough of the [`lua-agent-builder`](https://github.com/lua-ai-global/claude-code-lua-plugin) Claude Code plugin — what it does, how to install it, the canonical build loops (tools, integrations, workflows, templates), the safety model, and what to do when things go wrong. -The plugin wraps **lua-cli 3.36.0** (the pinned minimum: the 3.33.0 base plus the 3.36.0 workflow verbs, marked ⏳ in the knowledge base), the TypeScript SDK/CLI for the Lua agent platform. It has nothing to do with the Lua programming language. Everything in this guide (command shapes, SDK types, API routes) was verified against the lua-cli and lua-api source, not only the public docs. +The plugin wraps **lua-cli 3.37.0** (the pinned minimum: the 3.33.0 base, the 3.36.0 workflow verbs and the 3.37.0 Job-billing read-outs, all marked ⏳ in the knowledge base), the TypeScript SDK/CLI for the Lua agent platform. It has nothing to do with the Lua programming language. Everything in this guide (command shapes, SDK types, API routes) was verified against the lua-cli and lua-api source, not only the public docs. If you just want to start: [Installation](#installation) → [Your first agent](#your-first-agent). @@ -34,7 +34,7 @@ If you just want to start: [Installation](#installation) → [Your first agent]( - **Slash commands** wrap every `lua` command you need (`/lua-init`, `/lua-new`, `/lua-test`, `/lua-workflow`, `/lua-push`, `/lua-deploy`, `/lua-status`, …), collect the inputs up-front in one prompt, and surface errors with the CLI's typed exit codes explained. - **Subagents** do the heavy lifting in their own context with restricted tools: the architect plans, the skill-builder scaffolds and tests any primitive (including workflows, triggers, devices and voices), the debug agent diagnoses failures, the deploy pilot runs the gated ship sequence, the QA agent runs conversational and offline-workflow suites. -- **A knowledge base** (`lib/knowledge/`) gives those agents the exact SDK shapes, workflow builder, CLI matrix, integration patterns and decision trees — checked against lua-cli source (3.33.0 base; the ⏳ additions against the `main` / `feat/workflow-autonomy` refs lua-cli 3.36.0 is cut from). +- **A knowledge base** (`lib/knowledge/`) gives those agents the exact SDK shapes, workflow builder, CLI matrix, integration patterns and decision trees — checked against lua-cli source (3.33.0 base; the ⏳ additions against the `main` / `feat/workflow-autonomy` refs lua-cli 3.36.0 and 3.37.0 are cut from). - **Hooks** probe your environment, inject the current agent into Claude's context, and gate every production-affecting verb. - **Two MCP servers**: a local read-only platform server (what's deployed, versions, logs) and the public docs MCP. @@ -45,12 +45,14 @@ If you just want to start: [Installation](#installation) → [Your first agent]( | Requirement | Why | How | |---|---|---| | **Node.js ≥ 18** | hooks and the MCP server are Node ESM | macOS `brew install node@20` · Windows `winget install OpenJS.NodeJS.LTS` · Linux NodeSource / `nvm install 20` | -| **lua-cli ≥ 3.36.0** | the command shapes the plugin emits (3.36.0 adds the workflow policy, clear-gate and recompose verbs the knowledge base describes) | `npm install -g lua-cli` (or `/lua-update`) | +| **lua-cli ≥ 3.37.0** | the command shapes and output the plugin reads (3.36.0 added the workflow policy, clear-gate and recompose verbs; 3.37.0 adds no verb at all — it prints what a run cost: the `Tokens:` line, the per-step token columns, the `⚙` Job-model line, the engine-aware budget wording, the budget events in `workflows logs`) | `npm install -g lua-cli` (or `/lua-update`) | | **Claude Code** | the host | https://claude.com/claude-code | | **A Lua account** | to talk to `api.heylua.ai` | https://admin.heylua.ai — `/lua-auth` guides the login | `/lua-doctor` checks all of these and offers consent-gated fixes. Platforms: macOS 14+, Ubuntu 22.04+, Windows 11; CI runs the suite on all three with Node 18 and 20. +New in the 1.4.0 knowledge base: **what a workflow run costs.** A Job-tier step is billed per model **reply**, not per attempt — a coding turn that answers two hundred times is charged two hundred times — which is one credit per reply on a legacy plan and, on a seat plan, **actions** (the call's price band × the model's multiplier, with cached prompt tokens counted at the fraction the provider charges). `lua workflows raise-budget --credits ` keeps its flag name on both plans, but `` is a cap in the run's OWN unit — actions on a seat plan — and `/lua-workflow status` names it. A Job step also runs on its own `model`, failing that the platform's Job default, failing that your organization's — never the agent's model — so leaving `model` off a Job step is a cost decision. Those are platform rules, true on any CLI. **lua-cli 3.37.0** is what makes them visible: a `Tokens:` line and `Uncached` / `Cached` / `Output` columns under `--steps` (signals, never charges — do not add them up), `⚙ : model … · × · chosen by ` on Job rows, `finished past the cap` on a run that crossed its budget and completed anyway, the three budget events in `lua workflows logs`, a `raise-budget` confirmation that names the unit, and a `job-model-default` advisory at `lua workflows deploy`. 3.37.0 adds no command and no option, so nothing the plugin runs breaks on an older CLI — it simply prints less. + Two platform features are new in the 1.3.0 knowledge base: **per-step model classes** (`taskClass`, `model: 'class/fast|balanced|strong'`, `requires`, `effort`, `lua models list --workflows`, `lua workflows policy models`, `lua push workflow --apply-effort`, `clear-gate`, `recompose`) and the **workflow autonomy envelope** (`lua workflows policy autonomy`, the `Consent: auto (policy)` line). They need **lua-cli 3.36.0 or later** — the plugin's pinned minimum since 1.3.0; the knowledge files mark them ⏳ and were read from the lua-cli source on `main` / `feat/workflow-autonomy`, the refs 3.36.0 is cut from, so the slashes tell you when your CLI predates a verb (exit 2) instead of guessing. --- @@ -121,6 +123,7 @@ Workflows are durable multi-step graphs with approvals, signals, fan-out, retrie 5. `/lua-workflow start reply-approval --input @in.json` (one confirmation) → `/lua-workflow status ` → `/lua-workflow approve ` / `signal` / `resume` / `cancel`. 6. ⏳ **A model per step** (lua-cli 3.36.0 or later): give each `agentStep` a `taskClass` (`classify extract transform draft research reason code judge`) and `model: 'class/fast' | 'class/balanced' | 'class/strong'` — the platform resolves the class through your organization's policy (`/lua-workflow policy models get`; an admin sets `maxClass`, `classMap`, `allow`, `pins`, `fallback`, `consent-actions`), `requires: ['structured']` when the step has an `outputSchema`, and an `effort` that is recorded but only applied once you push with `--apply-effort`. `/lua-workflow models` shows the catalog as a step sees it (class, best for, speed, cost). A step whose class cannot be served parks instead of failing — `/lua-workflow clear-gate ` once the policy is fixed. 7. ⏳ **Will it start without asking?** A run the agent composes or starts from chat above 15 steps · 20 credits · 1 h parks `gated` until someone consents from the desktop (`status` exits 6 under `--strict`). An organization can pre-consent to a bounded envelope — `/lua-workflow policy autonomy get` shows it; an admin sets it with `lua workflows policy autonomy set --enabled on --max-credits --max-steps --max-duration --max-actions --max-runs-per-hour --forms graph,static` (the plugin asks before that org-wide write). Such a start shows `Consent: auto (policy) — ≤ …` on `status`. Goal runs and batch starts always ask; a refusal (`askAboveThresholds: false`) is never turned into an auto-start. +8. **What did it cost?** `/lua-workflow status ` — the `Budget:` line gives the figure, the unit your organization counts in (credits, or **actions** on a seat plan) and one sentence saying what that unit buys. A Job step is charged per model **reply**, so budget from replies; pin `model` on every Job step (it otherwise runs on the platform or organization default and bills every reply at that model's multiplier). Parked on the budget? `/lua-workflow raise-budget ` — `` is in the run's own unit even though the flag is spelled `--credits`. ⏳ On lua-cli 3.37.0 or later `status` adds a `Tokens:` line and per-step token columns (signals, not charges — never add them up), an `⚙` line naming the Job model and its multiplier, and `lua workflows logs` finally shows the budget park / raise / exceeded events. Chat-composed workflows can't be deployed from the CLI (`WORKFLOW_DYNAMIC`); `/lua-workflow export ` brings one into source, and ⏳ `/lua-workflow recompose ` rewrites its task classes into `class/` as a new version. @@ -185,7 +188,7 @@ Subagents never ask questions; the slash that spawned them already collected the | Event | Hook | What it does | |---|---|---| -| SessionStart | `check-lua-version` | warns (never blocks) if lua-cli < 3.36.0, pointing at `/lua-update` / `npm i -g lua-cli@latest` | +| SessionStart | `check-lua-version` | warns (never blocks) if lua-cli < 3.37.0, pointing at `/lua-update` / `npm i -g lua-cli@latest` | | SessionStart | `detect-project` | "✓ Lua agent project detected: " from `lua.skill.yaml` | | SessionStart | `check-lua-auth` | probes `lua models list --json --ci` (1–2 s); exit 9 → recommends `/lua-auth`, exit 11 → API-unreachable note, timeout → "could not confirm" | | UserPromptSubmit | `inject-context` | `[lua] agent: / org: ` every prompt | @@ -256,6 +259,7 @@ Precedence is deny → ask → allow. **The production gate is the `confirm-depl - **Compile: "No skills found" or a primitive is missing from the manifest** — it isn't referenced from the `LuaAgent` arrays in `src/index.ts`. - **Workflow push refused** — `unplaced_step`, `tool_unbundled`, `env-template-missing`, `WORKFLOW_NAME_TAKEN`; ⏳ `task-class-without-model`, `model-class-unknown` (and the other vocabulary codes), `model-class-resolution-off`; the debug subagent maps each to a fix (`lib/knowledge/workflows.md` §9). - **A workflow run sits `gated` / exit 6** — a consent gate is a person's to clear from the desktop or the approvals inbox (`lua workflows approve` needs a `wfa_` id and cannot); ⏳ on lua-cli 3.36.0 or later `status --strict` exits 6 on it (below 3.36.0 it exits 0). A `model_policy` park (⏳) is cleared with `/lua-workflow clear-gate ` once the org's model policy serves the class. +- **A budget figure or a raise in the wrong unit** — a seat organization counts **actions**, a legacy one **credits**; read the unit off `/lua-workflow status ` and pass `--credits ` with `` in THAT unit (the flag name never changes). Below lua-cli 3.37.0 the raise confirmation always says "credits" whatever the plan — ignore the word, check `status`. - **`lua push all` made a workflow live** — ⏳ lua-cli 3.36.0 or newer pushes and activates workflows in stage-all (`lib/knowledge/cli-reference.md` §4); push per type, or use `/lua-deploy` for workflows, when that is not what you want. --- @@ -274,6 +278,8 @@ Precedence is deny → ask → allow. **The production gate is the `confirm-depl **Where does my code go?** From lua-cli to `api.heylua.ai` (and `webhook.heylua.ai`, `cdn.heylua.ai`). The MCP server talks to `api.heylua.ai` and, for a session login, to Google's token endpoint to refresh the session. Claude Code sends the conversation to Anthropic per its own policy. -**How do I update the plugin?** `/plugin marketplace update claude-code-lua-plugin` then reinstall; 1.3.0 targets lua-cli 3.36.0 (the pin; it carries the per-step model classes and workflow autonomy verbs the plugin describes). +**How do I update the plugin?** `/plugin marketplace update claude-code-lua-plugin` then reinstall; 1.4.0 targets lua-cli 3.37.0 (the pin; 3.36.0 carries the per-step model classes and workflow autonomy verbs, 3.37.0 the Job-billing read-outs the plugin describes). + +**Why does my run show no `Tokens:` line or `⚙` model line?** Those print only when the server projected the figures — an unmetered run, a run metered before the platform shipped them, or a CLI below 3.37.0. A missing line means "nobody reported", not a fault; and the token figures are never what you were charged (the `Budget:` line is), so never sum them. **Where do I report bugs?** Plugin: https://github.com/lua-ai-global/claude-code-lua-plugin/issues · Security: security@heylua.ai · lua-cli: https://github.com/lua-ai-global/lua-cli/issues · Docs: https://docs.heylua.ai (and `mcp__plugin_lua-agent-builder_lua-docs__submit_feedback` for a wrong page). diff --git a/plugins/lua-agent-builder/.claude-plugin/plugin.json b/plugins/lua-agent-builder/.claude-plugin/plugin.json index 0e19439..bb8cd18 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.3.0", + "version": "1.4.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 f9a6f6d..5ff94cb 100644 --- a/plugins/lua-agent-builder/CHANGELOG.md +++ b/plugins/lua-agent-builder/CHANGELOG.md @@ -2,6 +2,34 @@ 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.4.0 — 2026-09-20 + +**What a workflow run costs, and why.** The plugin described a Job-tier attempt as a flat 4 credits and every run budget in "credits". Both are wrong for a priced run: a Job step is billed per model **REPLY** — one credit per reply on a legacy plan, **actions** (the call's price band × the resolved model's multiplier, cached prompt tokens at the fraction the provider charges) on a seat plan — and a coding turn makes dozens of replies in ONE attempt. Read from lua-core-services `main` at `ebcf6689c` (the lua-cli 3.37.0 release, `#3095`; the billing train `#3094`) — the CLI renderers in `src/commands/workflows.ts`, the wire shapes in `src/interfaces/workflows.ts`, the deploy advisory in lua-api's developer workflow service, the Job model legs and their labels in shared-types, the cache weighting in lua-core's Job rate module — never from the public docs. + +**Version.** lua-cli **3.37.0** adds **no command and no option**: its only `src/cli/command-definitions.ts` change is the `--credits` help string, so every shape the plugin emits runs unchanged on 3.36.0 and only prints less. `PINNED_MIN_LUA_CLI` moves 3.36.0 → 3.37.0 because the plugin's agents now READ output that only 3.37.0 prints. The existing "⏳ 3.36.0 or later" markers are untouched; new material is marked "⏳ 3.37.0". + +### The billing rule (true on every CLI — not gated on 3.37.0) + +- `workflows.md` §4 — the flat rule ("an inline agent step is 1 credit, a Job-tier attempt is 4, tokens never metered") is now scoped to a run the platform is still metering flat, which is exactly what `lua workflows status` still prints for such a run, and the **priced** legacy and seat rules stand beside it. Budget a Job workflow from model replies, not steps. +- `workflows.md` §4 — **which model a Job step runs on is not the agent's model**: the step's own `model`, failing that the platform's Job default, failing that the organization's. Every reply is billed at that model's multiplier, so pinning `model` on a Job step is a cost decision. Mirrored in `decision-trees.md` ("Which model?"), `primitives.md` §11 and gotcha 35, `agents/lua-architect.md` (decision 6), `agents/lua-skill-builder.md` and `agents/lua-qa.md` (an unpinned Job step is now a QA finding). +- `lua workflows raise-budget --credits ` — the **flag keeps its name on both plans**, but `` is a cap in the run's own unit (actions on a seat plan). Corrected in `workflows.md` §4 and §7, `primitives.md` §12, `commands/lua-workflow.md`, `commands/lua-status.md`, `agents/lua-debug.md` and the user guide; `decision-trees.md`'s "credit budget" is now "run budget (credits, or actions on a seat plan)". The consent ladder's own "≤ 20 credits" is a different quantity and is deliberately unchanged. + +### The lua-cli 3.37.0 read-outs (⏳, and printed only when the server projects them) + +- `workflows.md` §2 gains **"Reading what a run cost"**: the engine-aware `Budget:` sentence and `finished past the cap`; the run-level `Tokens:` line; the `Uncached` / `Cached` / `Output` step columns (`Cached` folds reads and writes for width; `—`, never `0`, for a step nobody reported); the `⚙` Job-model line naming the model, the multiplier and the leg that chose it; and the reminder that these are **signals, not charges** and must never be summed — a cache read is a subset of the uncached input figure. A missing line means "not projected", not a defect. +- `lua workflows logs` now renders `step.job_model_resolved` and the three budget events (`run.budget_parked`, `run.budget_raised`, `run.budget_exceeded`), which below 3.37.0 it did not print at all; the unit inside them is the gate's own word and is quoted verbatim (`workflows.md` §2, `commands/lua-logs.md`, `commands/lua-workflow.md`). +- `lua workflows deploy` prints a `job-model-default` **advisory** (` ⚠ `) for a Job step that names no `model` — advisory only, the deploy still succeeds, like the older `job-tier-not-enabled` (`workflows.md` §4 and §8, `cli-reference.md` §4, `commands/lua-deploy.md`, `agents/lua-deploy-pilot.md`, `decision-trees.md`). +- `raise-budget` names the unit it raised, and a seat run parked before its first priced call no longer reads the legacy sentence. + +### Unchanged on purpose + +- No new verb, flag, permission rule or hook behaviour: `lib/permissions-template.json`, `hooks/hooks.json`, `confirm-deploy`, `tokenizer`, `scripts/lint-knowledge-commands.mjs` and `scripts/lint-cli-flags.mjs` all hold, because 3.37.0 adds no command surface. +- `budget.unit`, `budget.reserved` and `usage.engine` are **not** new in 3.37.0 — 3.36.0 already sent them; `reserved` still has no human line and is `--json` only. + +### Housekeeping + +- Bump 1.3.0 → 1.4.0 everywhere; `mcp/lua-platform/dist/server.js` rebuilt; `PINNED_MIN_LUA_CLI` 3.36.0 → 3.37.0 (`hooks/check-lua-version.mjs`, `/lua-init`, `/lua-update`, `/lua-doctor`, both READMEs and the user guide). `scripts/lint-pinned-version.mjs` compares the pin with npm's `latest` and is therefore **red by design until lua-cli 3.37.0 is published**; it was not weakened. + ## 1.3.0 — 2026-09-18 Two shipped platform features reach the knowledge base, the slash commands and the subagents: **per-step model classes** for workflows and the **workflow autonomy envelope** (pre-consented starts). Every claim was read from lua-core-services — lua-cli `main` at `12cefb7ec` (WMC-E7 `#2969`, hotfixes H7 `#3053` and H8 `#3051`, the stage-all fix `#3024`) and `feat/workflow-autonomy` at `378403322` (WMC-A1…A7) — never from the public docs. **Version**: lua-cli 3.36.0 — cut from those two refs and published 2026-09-18 — carries all of it and nothing below it does (3.35.0, tag `8d65d1ba8`, has none of the verbs), so every addition is marked "⏳ requires lua-cli 3.36.0 or later" and `PINNED_MIN_LUA_CLI` moves 3.33.0 → 3.36.0 (the session hook now also names `npm i -g lua-cli@latest`). That pin is the only hook change (no hook reads a `lua workflows` exit code); the permission template gains the new verbs. diff --git a/plugins/lua-agent-builder/README.md b/plugins/lua-agent-builder/README.md index 53b91e4..50e7a4d 100644 --- a/plugins/lua-agent-builder/README.md +++ b/plugins/lua-agent-builder/README.md @@ -2,7 +2,7 @@ A [Claude Code](https://code.claude.com) plugin for building, testing, and deploying [Lua AI agents](https://heylua.ai) from inside your Claude Code session. It wraps the `lua-cli` toolchain (a TypeScript SDK/CLI — unrelated to the Lua programming language) with single-permission slash commands, hook-enforced production gates, a source-verified knowledge base, and two MCP servers. -Verified against **lua-cli 3.33.0** (September 2026): every command shape, SDK type and API endpoint the plugin uses was read from the lua-cli / lua-api source, not from the public docs. 1.3.0 adds the per-step model classes (`taskClass`, `class/fast|balanced|strong`, `--apply-effort`, `lua workflows policy models`, `clear-gate`, `recompose`, `lua models list --workflows`) and the workflow autonomy envelope (`lua workflows policy autonomy`, `Consent: auto (policy)`), read from lua-cli `main` and `feat/workflow-autonomy` — the refs lua-cli 3.36.0 is cut from — and marked ⏳ in the knowledge base; the pin is 3.36.0 since 1.3.0. +Verified against **lua-cli 3.33.0** (September 2026): every command shape, SDK type and API endpoint the plugin uses was read from the lua-cli / lua-api source, not from the public docs. 1.3.0 added the per-step model classes (`taskClass`, `class/fast|balanced|strong`, `--apply-effort`, `lua workflows policy models`, `clear-gate`, `recompose`, `lua models list --workflows`) and the workflow autonomy envelope (`lua workflows policy autonomy`, `Consent: auto (policy)`) from lua-cli 3.36.0. 1.4.0 corrects what a workflow run COSTS — a Job-tier step is billed per model reply (a credit per reply on a legacy plan, actions = price band × the model's multiplier with cached tokens at the provider's fraction on a seat plan), a Job step runs on its own `model` and not the agent's, and `raise-budget --credits ` raises a cap counted in the run's own unit — and describes the lua-cli 3.37.0 read-outs that show it (`Tokens:`, the `Uncached`/`Cached`/`Output` columns, the `⚙` Job-model line, `finished past the cap`, the budget events in `workflows logs`, the `job-model-default` deploy advisory), read from lua-cli `main` and marked ⏳. The pin is 3.37.0 since 1.4.0; 3.37.0 adds no command and no option, so every shape the plugin emits still runs on 3.36.0. ## Install @@ -10,7 +10,7 @@ Verified against **lua-cli 3.33.0** (September 2026): every command shape, SDK t /plugin marketplace add lua-ai-global/claude-code-lua-plugin /plugin install lua-agent-builder@claude-code-lua-plugin /reload-plugins -/lua-doctor # Node, npm, lua-cli ≥ 3.36.0, auth, permission rules +/lua-doctor # Node, npm, lua-cli ≥ 3.37.0, auth, permission rules ``` New login runs in your own terminal (`lua auth configure`) — the plugin never handles your email, one-time code or credential. `/lua-auth` guides it. diff --git a/plugins/lua-agent-builder/agents/lua-architect.md b/plugins/lua-agent-builder/agents/lua-architect.md index ea88c36..74bccfb 100644 --- a/plugins/lua-agent-builder/agents/lua-architect.md +++ b/plugins/lua-agent-builder/agents/lua-architect.md @@ -47,7 +47,8 @@ Apply these decisions in order (details in decision-trees.md): 4. **Per-user vs agent-wide data**: `User` vs `Data` (declare `index` on filtered fields — from a `lua test` seed run; deployed code cannot declare one). Commerce → `Products/Baskets/Orders` unless Shopify/WooCommerce owns the cart (mind the `OrderStatus.FULFILLED` / `fullfilled` spelling split, primitives.md §12). 5. **Processors** only for agent-wide uniform transforms. 6. **Model**: omit for the platform default (`alibaba/qwen3.8-flash`); recommend a code from `lua models list --json --ci`, never an invented one; a per-request resolver when channels differ. - - **Per agent step in a workflow** (⏳ lua-cli 3.36.0 or later — the plugin's pinned minimum; write it into the plan; workflows.md §2, decision-trees.md "Which model?"): give every `agentStep` a `taskClass` (`classify extract transform draft research reason code judge`) and a `model: 'class/fast' | 'class/balanced' | 'class/strong'` following the platform map — classify / extract / transform → fast, draft / research / judge → balanced, reason / code → strong — checked against the org's ceiling and overrides in `lua workflows policy models get --ci` (`maxClass`, `classMap`, `allow`, `pins`); `requires: ['structured']` on every step with an `outputSchema` (`vision` for images, `largeContext`, `codeExecution`); a one-line `modelReason`; `effort` `low` for tool-heavy orchestration and `high` for reason / code, saying plainly that effort is **recorded, not applied** until the workflow is pushed with `--apply-effort`. Pin a concrete code (from `lua models list --workflows --json --ci`, never invented — pin-only rows are marked) only when a trait forces it; the server checks a pin against the org's approved set at push, and today a pin the org has excluded is warned about, not refused. A pushed `taskClass` without a `model` is refused at push (`task-class-without-model`), not at compile. + - **Per agent step in a workflow** (⏳ lua-cli 3.36.0 or later — the plugin pins 3.37.0; write it into the plan; workflows.md §2, decision-trees.md "Which model?"): give every `agentStep` a `taskClass` (`classify extract transform draft research reason code judge`) and a `model: 'class/fast' | 'class/balanced' | 'class/strong'` following the platform map — classify / extract / transform → fast, draft / research / judge → balanced, reason / code → strong — checked against the org's ceiling and overrides in `lua workflows policy models get --ci` (`maxClass`, `classMap`, `allow`, `pins`); `requires: ['structured']` on every step with an `outputSchema` (`vision` for images, `largeContext`, `codeExecution`); a one-line `modelReason`; `effort` `low` for tool-heavy orchestration and `high` for reason / code, saying plainly that effort is **recorded, not applied** until the workflow is pushed with `--apply-effort`. Pin a concrete code (from `lua models list --workflows --json --ci`, never invented — pin-only rows are marked) only when a trait forces it; the server checks a pin against the org's approved set at push, and today a pin the org has excluded is warned about, not refused. A pushed `taskClass` without a `model` is refused at push (`task-class-without-model`), not at compile. + - **Cost of a Job-tier step** (platform behaviour, true on every CLI; workflows.md §4): a Job step is billed per model **REPLY**, not per attempt — one credit per reply on a legacy plan, actions (the call's price band × the model's multiplier, per model call, cached prompt tokens at the provider's fraction) on a seat plan — and a coding turn answers dozens of times in one attempt. Size the run budget from replies, not steps, and say in the plan which unit the organization counts in. A Job step runs on its own `model`, failing that the platform's Job default, failing that the org's — **not** the agent's model — so pin `model` on every Job step and name the reason; an unpinned one inherits whatever the default is that day and bills every reply at that model's multiplier (⏳ lua-cli 3.37.0 or later warns `job-model-default` at deploy and shows the chosen model as `⚙ … ×` under `lua workflows status --steps`). - **Consent and autonomy** (platform on `feat/workflow-autonomy`, production 2026-09-18; CLI verbs ⏳ 3.36.0+; workflows.md §3, decision-trees.md "Will a workflow start without asking a person?"): a run the agent composes or starts from chat above the consent ladder — 15 steps · 20 credits · 1 h expected wall — parks `gated` until a person consents, unless the organization's autonomy envelope admits it (`lua workflows policy autonomy get --ci`: `enabled` must be true; defaults 20 credits · 15 steps · 1 d · forms graph,static · `maxActions` = the org's `consentActions` · 20 runs per hour per agent). Compose for **starting without a question**: keep a chat-started graph within the envelope, keep waits short (an approval or signal wait counts toward the expected wall — a 7-day wait always asks), avoid the script form unless the envelope lists it, and state in the plan which starts still ask — goal runs and batch starts never auto-start, an org with `askAboveThresholds: false` refuses rather than asks (autonomy never turns a refuse into anything), and a spent hourly allowance turns a start back into a question. `lua workflows start` / REST / SDK starts are not scored by the ladder. When the plan needs a wider envelope, write the exact line for an org administrator — e.g. `lua workflows policy autonomy set --enabled on --max-credits 40 --max-steps 20 --max-duration 86400 --forms graph,static` — and say it is an org-wide consent surface the plugin confirms before running. 7. **Channel constraints**: WhatsApp → template strategy outside the 24 h window; voice → a `LuaVoice` and fast tools; email → plain text/HTML; Teams group chats → `conversationId` sends. 8. **RAG / resources**: when the agent must answer from documents (FAQs, policies, manuals, price lists), that is a platform **resource** in the knowledge base, not a tool — never invent a `search_docs` / `lookup_faq` tool. `lua resources list --ci` shows what is uploaded, `lua resources view --resource-name ` reads one, `lua resources delete --resource-name ` removes one; create/update are interactive only (`src/commands/resources.ts` — the user runs `lua resources` in their terminal or uses the dashboard). Retrieval is enabled per agent with `lua features list --ci` → `lua features enable --feature-name ` (the server names the feature; `findFeature` matches name or title case-insensitively). It happens inside the agent turn; verify with `/lua-logs` type `rag` (`logSource: 'rag'`, aliases `kb|knowledge|knowledgebase`). Workflows bind retrieval declaratively with `fromKnowledge({ source, query, maxChars?, topK? })` (workflows.md §2; not emulated offline). @@ -82,7 +83,7 @@ Output the plan in this format (target < 900 words; the user reads this): - `` — ; does ### Workflows (only if the job/workflow rule says so) -- `` — trigger: ; steps: , requires, effort) → approval (approver, timeout, onTimeout) → foreach … → step>; budget ; Job tier? ; consent: (⏳ lua-cli 3.36.0 or later for the model members and the policy verbs) +- `` — trigger: ; steps: , requires, effort) → approval (approver, timeout, onTimeout) → foreach … → step>; budget ; Job tier? ; consent: (⏳ lua-cli 3.36.0 or later for the model members and the policy verbs) ### Processors (only if needed) -
diff --git a/plugins/lua-agent-builder/agents/lua-debug.md b/plugins/lua-agent-builder/agents/lua-debug.md
index db6cc48..3b8d3aa 100644
--- a/plugins/lua-agent-builder/agents/lua-debug.md
+++ b/plugins/lua-agent-builder/agents/lua-debug.md
@@ -30,6 +30,7 @@ A `lua compile --ci`, `lua test --ci` or `lua push` invocation failed, or a work
    - **Push refused** → `unplaced_step`, `tool_unbundled`, `env-template-missing`, `WORKFLOW_NAME_TAKEN` (409), `WORKFLOW_FORM_MISMATCH` (400), `budget-exceeds-cap`; `--set-version` must be `x.y.z`. ⏳ lua-cli 3.36.0 or later model-selection refusals (workflows.md §2, §9): `model-class-unknown` / `task-class-unknown` / `model-trait-unknown` / `effort-unknown` / `model-reason-too-long` are refused locally before any POST (`issues[]` names the step and path — the fix is the vocabulary: `class/fast|balanced|strong`, `classify extract transform draft research reason code judge`, `vision structured largeContext codeExecution`, `low medium high`, ≤ 160 chars); `task-class-without-model` is the server's (add `model: 'class/'` next to the `taskClass` — `lua compile` never reports it); `model-class-resolution-off` means the environment has classes off (pin an approved code or drop `model`).
    - **Run parked on a model class** (⏳; `lua workflows status ` prints `⏸️ Paused — a step's model request cannot be resolved under the current policy:` with a code and step; `gate.kind: 'model_policy'`) → the step asked for a class the org policy cannot serve right now (`lua workflows policy models get`: `maxClass`, `allow`, `classes`). It parks, never fails. Point the user at `/lua-workflow clear-gate ` (`lua workflows clear-gate  --kind model_policy`) once the policy is fixed, or at lowering the class in the definition. `lua workflows logs ` shows `step.model_resolved` / `step.model_policy_warning` (`model policy warning:  ` — e.g. a pin the org excluded, warn-only today).
    - **Run `gated` that nobody asked about / a run that started with nobody asked** (⏳) → `status` prints `Consent:  auto (policy) — ≤  ·  · ` when the org's autonomy envelope admitted the start (`consent.via: 'autonomy'`, `approvedBy: 'system:policy'`) — that is the org policy (`lua workflows policy autonomy get`), not a defect; a `start-consent` gate with no line is an ordinary ask (above 15 steps · 20 credits · 1 h expected wall) waiting for a person. An `approval` step parked on the org admins although the node names `approver: 'creator'` is the H8 escalation: `⇅ : approver escalated  →  — the initiator is excluded (maker-checker)` — expected when `excludeInitiator: true` and the creator started the run.
+   - **Run parked on its budget, or a cost nobody expected** → `lua workflows status `: the `Budget:` line names the unit the ORGANIZATION counts in (`budget.unit` / `usage.engine` under `--json`) — **credits** on a legacy plan, **actions** on a seat plan — and the sentence after it says what that unit buys. Never quote "credits" to a seat organization, and never derive the unit from a number. `lua workflows raise-budget  --credits ` is the raise on both plans (the flag name does not change); `` is in the run's own unit. A surprising figure on a Job step is almost always the **per-reply** rule: a Job attempt is charged once per model reply (dozens per coding turn) at `price band × the model's multiplier`, so look at which model the step ran on — ⏳ lua-cli 3.37.0 or later prints `⚙ : model  · × · chosen by ` under `status --steps` and `job model → …` in `logs`, and `chosen by platform default` / `org default` means the step named no `model` of its own (fix: pin it). ⏳ `finished past the cap` on the `Budget:` line (`budget.exceeded`) means the run crossed its cap and completed anyway — not a park, nothing to raise. ⏳ `Tokens:` and the `Uncached`/`Cached`/`Output` columns are signals, **not** charges: never add them together (a cache read is a subset of the input figure on OpenAI-compatible providers) and never present them as what the run was billed. Any of these lines missing means the server projected nothing for them — an unmetered run or an older server — not a defect.
    - **Workflow run failed (exit 4)** → `lua workflows status  --steps --json`: the failing step's `error.code`; `binding_unresolved`/`input_schema_invalid`/`credentials_unresolved` park pre-dispatch. Re-test offline with `lua test --ci workflow --name  --input '' --from-run `: the driver fetches that run and each planned step from the API, seeds every `completed` step whose ancestors are all seeded (latest attempt wins) with its output and effects, and re-drives from the first pending step — so only the failing step and what follows re-execute (`[from-run] N step(s) seeded from `). Exit `3` = the run was not found; exit `2` `[from-run] graph differs (N steps changed) — pass --force to seed anyway` = your compiled `graphHash` no longer matches the run's (you changed the graph) — add `--force` to seed the steps that still line up.
 
 4. **Unknown message?** Search the docs with `mcp__plugin_lua-agent-builder_lua-docs__search_lua_cli ""` or `mcp__plugin_lua-agent-builder_lua-docs__query_docs_filesystem_lua_cli "rg -n '' /"`; `WebFetch https://docs.heylua.ai/cli/troubleshooting` is the fallback. Never guess at internals.
diff --git a/plugins/lua-agent-builder/agents/lua-deploy-pilot.md b/plugins/lua-agent-builder/agents/lua-deploy-pilot.md
index 506abc8..52638f3 100644
--- a/plugins/lua-agent-builder/agents/lua-deploy-pilot.md
+++ b/plugins/lua-agent-builder/agents/lua-deploy-pilot.md
@@ -12,6 +12,7 @@ lua-cli facts this sequence relies on (verified against 3.33.0; details in `${CL
 - `lua deploy all --force` deploys the latest version of everything and ignores `--set-version` and `--name` — on a versioned agent it has the same skill/persona snapshot problem, so route `all` through an agent version there.
 - Every production verb is blocked in bare form by the `confirm-deploy` hook; the `LUA_DEPLOY_CONFIRMED=1` prefix is what the hook and the permission template's allow rules accept. If the prefixed command is nevertheless denied by the permission layer, the user's own `.claude/settings.json` (or a global one) carries a deny/ask rule such as `Bash(lua deploy*)` or `Bash(lua *)` that Claude Code evaluates past the env prefix — report that rule and stop; do not try another spelling. Never use `--auto-deploy`.
 - `lua status --json --ci` reports per-primitive `diffs[].status` ∈ `synced | ahead | behind | not deployed` and `orphans[]`.
+- `lua workflows deploy` can answer with **advisory** warnings printed as `  ⚠ ` under the success line. They never fail the deploy and must never be reported as one: `job-tier-not-enabled` (the version uses the Job tier but the organization has it off — `lua workflows start` will be refused until an administrator enables it) and ⏳ lua-cli 3.37.0 or later `job-model-default` (a Job step names no `model`, so it runs on the platform default for Job steps, else the organization's — and every model reply of every attempt is billed at that model's multiplier; the message names the step, and the model and multiplier when the server can resolve them). Quote each advisory verbatim in the report and, for `job-model-default`, name the step so the author can pin its `model`.
 - ⏳ lua-cli 3.36.0 or later (check `lua --version`): `lua push all` also pushes every workflow **and activates the pushed version** (main `push.ts`, PR #3024: workflows are queued for deployment with or without `--auto-deploy`, under `🚀 Activating workflow version(s) …`). On that CLI a stage-all for target `all` / `agent-version` is itself a workflow go-live — list those workflows and versions under "what went live" and give `LUA_DEPLOY_CONFIRMED=1 lua workflows deploy  -v ` as their rollback. `lua push workflow … --apply-effort` (each agent step's `effort` is applied from that version on; a plain push records it only) is added only when `notes` asks for it, and reported.
 
 ## The gates
diff --git a/plugins/lua-agent-builder/agents/lua-qa.md b/plugins/lua-agent-builder/agents/lua-qa.md
index 2f8235b..e2c0e95 100644
--- a/plugins/lua-agent-builder/agents/lua-qa.md
+++ b/plugins/lua-agent-builder/agents/lua-qa.md
@@ -44,7 +44,7 @@ For each workflow, run one offline scenario per predicate branch, no platform ca
 lua test --ci workflow --name  --input '' --agents fake --fast-retries [--step-output =''] [--approve ] [--deny ] [--signal ='']
 ```
 
-Exit `0` completed · `2` flag/schema problem (report as a finding: the input schema or a step's output schema) · `4` a step failed · `5` fixture missing. List workflows with `lua workflows list --ci`. The offline driver never reads an agent step's `model` / `taskClass` / `requires` / `effort` (⏳ lua-cli 3.36.0 or later members) — class resolution, the consent ladder and the org's autonomy envelope are platform behaviour and are **not** exercised here; note in the report when a workflow relies on them (a `taskClass` without a `model` is only refused at push, so flag it as a finding when you see one in `src/workflows/`).
+Exit `0` completed · `2` flag/schema problem (report as a finding: the input schema or a step's output schema) · `4` a step failed · `5` fixture missing. List workflows with `lua workflows list --ci`. The offline driver never reads an agent step's `model` / `taskClass` / `requires` / `effort` (⏳ lua-cli 3.36.0 or later members) — class resolution, the consent ladder and the org's autonomy envelope are platform behaviour and are **not** exercised here; note in the report when a workflow relies on them (a `taskClass` without a `model` is only refused at push, so flag it as a finding when you see one in `src/workflows/`). The driver also reports **no cost**: credits, actions, tokens and the Job model are all platform figures — flag a **Job-tier `agentStep` that names no `model`** as a finding (it runs on the platform or org default and every model reply of the attempt is billed at that model's multiplier; workflows.md §4), and never estimate a run's price from the offline ledger.
 
 ## Step 3 — log scan
 
diff --git a/plugins/lua-agent-builder/agents/lua-skill-builder.md b/plugins/lua-agent-builder/agents/lua-skill-builder.md
index e59f2e4..fea34fe 100644
--- a/plugins/lua-agent-builder/agents/lua-skill-builder.md
+++ b/plugins/lua-agent-builder/agents/lua-skill-builder.md
@@ -25,7 +25,7 @@ If the project has `examples/` (from `lua init --with-examples`), mirror the mat
    - mcp → `src/mcp/.ts` (`new LuaMCPServer({ transport: 'streamable-http', url, headers: () => ({...}) })`)
    - device → `src/devices/.ts` (`defineDevice`) · device-trigger → `src/devices/.trigger.ts` (`defineDeviceTrigger`)
    - voice → `src/voices/.ts` (`defineVoice`)
-   - workflow → `src/workflows/.ts` (`export const  = createWorkflow({ … }).then(…).commit()`, config as an inline object literal, every `createStep` placed). ⏳ lua-cli 3.36.0 or later (the plugin's pinned minimum — check the installed `lua --version`): an `agentStep` may carry `taskClass` (`classify | extract | transform | draft | research | reason | code | judge`), `model: 'class/fast' | 'class/balanced' | 'class/strong'` (or an approved code), `requires: ['structured' | 'vision' | 'largeContext' | 'codeExecution']` (`structured` whenever there is an `outputSchema`), `modelReason` (≤ 160 chars) and `effort: 'low' | 'medium' | 'high'`. Rules (workflows.md §2): a `taskClass` **must** come with a `model` on a pushed definition (`task-class-without-model` — refused at push by the server, invisible to `lua compile`); a misspelled class / task class / trait / effort is refused at push too (`model-class-unknown` etc., before any POST); `effort` is recorded and never applied unless the user later pushes with `lua push workflow --apply-effort` — say so in the report; the offline `lua test workflow` ignores all of them. On an older CLI the typings lack these members and `tsc` rejects them — leave them out.
+   - workflow → `src/workflows/.ts` (`export const  = createWorkflow({ … }).then(…).commit()`, config as an inline object literal, every `createStep` placed). ⏳ lua-cli 3.36.0 or later (the plugin pins 3.37.0 — check the installed `lua --version`): an `agentStep` may carry `taskClass` (`classify | extract | transform | draft | research | reason | code | judge`), `model: 'class/fast' | 'class/balanced' | 'class/strong'` (or an approved code), `requires: ['structured' | 'vision' | 'largeContext' | 'codeExecution']` (`structured` whenever there is an `outputSchema`), `modelReason` (≤ 160 chars) and `effort: 'low' | 'medium' | 'high'`. Rules (workflows.md §2): a `taskClass` **must** come with a `model` on a pushed definition (`task-class-without-model` — refused at push by the server, invisible to `lua compile`); a misspelled class / task class / trait / effort is refused at push too (`model-class-unknown` etc., before any POST); `effort` is recorded and never applied unless the user later pushes with `lua push workflow --apply-effort` — say so in the report; the offline `lua test workflow` ignores all of them. On an older CLI the typings lack these members and `tsc` rejects them — leave them out. Independently of the CLI version: a step with `tier: 'job'` (or any `workspace`) should always name its own `model` — a Job step falls back to the platform's Job default, then the organization's, never the agent's, and every model reply of the attempt is billed at that model's multiplier (workflows.md §4). Say in the report which model each Job step pins and why.
    - workflow-script → `src/workflows/.workflow.script.js` (workflows.md §5; lua-cli `src/compiler/utils/workflow-script-lint.ts`): a plain-JS ES module with **no imports**; first statement `export const meta = { name: '', description, phases?, whenToUse?, concurrency?, sampleArgs? }` as a pure literal ≤ 4096 bytes where `meta.name` **equals the file stem**; the body is top-level `await` code over the host bindings (`agent`, `tool`, `workflow`, `parallel` of **thunks**, `foreach`, `step(label, fn)`, `approval`, `waitForSignal`, `sleep`, `memo`, `once`, `log`, `phase`, `bail`, `args`, `env.now()` / `env.random()`); a top-level `return` is the run output; never `Date.now()`, `new Date()`, `Math.random()`, `globalThis`, `eval`. Mirror `examples/workflows/adversarial-verify.workflow.script.js` when present
 2. **Write it** with the shapes from primitives.md: imports only from `'lua-cli'` and `'zod'`; a Zod `inputSchema` on every tool/webhook body/trigger; precise tool `description`s (the LLM picks tools by description); secrets via `env('KEY')`; no module-level state; `JobSchedule` uses `expression` / `executeAt` / `seconds`. Never `defineTool`, never `lua-cli/skill`, never `welcomeMessage`. Production-validated rules (primitives.md §4, §6, §12): a **webhook** must `safeParse` its body/headers/query first thing in `execute` (the declared schemas are never applied), stay short and idempotent (no wall timeout deployed; the caller times out at ~90 s and retries), and set `secret` only for callers you control (a string literal — `env()` fails `lua compile`; vendor-signed senders cannot satisfy it — verify their HMAC in a `defineTrigger` `verify` over `rawBody`); a **job** always gets a finite `retry.maxAttempts` (deployed retries are a fixed `backoffSeconds` wait, ≤ 10 attempts, none without it) and an idempotent `execute`; deployed **`Data` writes** use the string/2-arg forms (an `index` is declared from a `lua test` run only); **commerce** code that fulfils orders reads the `OrderStatus.FULFILLED` / `fullfilled` note before using it.
 3. **Register it in `src/index.ts`**: add the import and put the instance in the right `LuaAgent` array (`skills`, `webhooks`, `triggers`, `jobs`, `workflows`, `preProcessors`, `postProcessors`, `mcpServers`, `devices`, `deviceTriggers`, `voices`). A tool goes into its skill's `tools: [...]`, not into the agent. Unregistered primitives are silently not compiled. Exception: a `workflow-script` is never registered — the compiler scans `src/workflows/*.workflow.script.js` itself (`detectWorkflowScriptFiles`), so leave `src/index.ts` alone for that type.
diff --git a/plugins/lua-agent-builder/commands/lua-deploy.md b/plugins/lua-agent-builder/commands/lua-deploy.md
index 5fd3c63..ad56e21 100644
--- a/plugins/lua-agent-builder/commands/lua-deploy.md
+++ b/plugins/lua-agent-builder/commands/lua-deploy.md
@@ -33,7 +33,7 @@ Use the **Agent tool** with `subagent_type: "lua-deploy-pilot"` and a prompt con
    - `skill` / `all` on an agent **without** agent versions → `LUA_DEPLOY_CONFIRMED=1 lua deploy skill --ci --name  --set-version  --force` / `… lua deploy all --ci --force`
    - `skill` / `all` on an agent **with** agent versions → `lua version create --ci -m ""` then `LUA_DEPLOY_CONFIRMED=1 lua version promote ` — `lua deploy skill` has no scoped promote there: it goes live at once but leaves the active version's snapshot stale, and the next promote (or rollback) silently reverts it
    - `persona` → the `lua push agent` in step 4 **is** the deploy (the pushed persona version is persisted `published` and served at once; `lua version promote` never changes the served persona). A verb runs only to roll back to an earlier version: `LUA_DEPLOY_CONFIRMED=1 lua deploy persona --ci --set-version  --force`
-   - `workflow` → `LUA_DEPLOY_CONFIRMED=1 lua workflows deploy  -v ` (+ `… lua workflows activate ` when asked to enable its schedule/triggers)
+   - `workflow` → `LUA_DEPLOY_CONFIRMED=1 lua workflows deploy  -v ` (+ `… lua workflows activate ` when asked to enable its schedule/triggers). The deploy may print `  ⚠` **advisory** lines under the success line and still succeed — `job-tier-not-enabled` (an administrator must switch the Job tier on, or `start` is refused) and ⏳ lua-cli 3.37.0 or later `job-model-default` (a Job step names no `model`: it runs on the platform or org default and every model reply is billed at that model's multiplier). Report them; never treat one as a failed deploy
    - `mcp` → `LUA_DEPLOY_CONFIRMED=1 lua mcp activate `
    - `device device-trigger voice agent-version` → `lua version create --ci -m ""` then `LUA_DEPLOY_CONFIRMED=1 lua version promote `
 6. Smoke check: `lua logs --ci --type all --limit 30 --json` scanned for `subType === 'error'`, plus `mcp__plugin_lua-agent-builder_lua-platform__get_deployment_status`; the `post-deploy-smoke` hook also pings production.
diff --git a/plugins/lua-agent-builder/commands/lua-doctor.md b/plugins/lua-agent-builder/commands/lua-doctor.md
index fa15b4b..a676fa9 100644
--- a/plugins/lua-agent-builder/commands/lua-doctor.md
+++ b/plugins/lua-agent-builder/commands/lua-doctor.md
@@ -15,7 +15,7 @@ Run `Bash(npm --version)`; if non-zero try `pnpm --version`. If neither, AskUser
 
 ## Step 3 — lua-cli
 
-Run `Bash(lua --version)`. Not installed → AskUserQuestion to install via `npm install -g lua-cli`. Installed but below `PINNED_MIN_LUA_CLI` in `${CLAUDE_PLUGIN_ROOT}/hooks/check-lua-version.mjs` (3.36.0 — the plugin's knowledge describes workflow verbs that do not exist below it) → point at `/lua-update`.
+Run `Bash(lua --version)`. Not installed → AskUserQuestion to install via `npm install -g lua-cli`. Installed but below `PINNED_MIN_LUA_CLI` in `${CLAUDE_PLUGIN_ROOT}/hooks/check-lua-version.mjs` (3.37.0 — the plugin's knowledge describes workflow verbs that do not exist below 3.36.0 and cost read-outs that only 3.37.0 prints) → point at `/lua-update`.
 
 ## Step 4 — authentication
 
diff --git a/plugins/lua-agent-builder/commands/lua-init.md b/plugins/lua-agent-builder/commands/lua-init.md
index ce8cff1..1a7f876 100644
--- a/plugins/lua-agent-builder/commands/lua-init.md
+++ b/plugins/lua-agent-builder/commands/lua-init.md
@@ -8,7 +8,7 @@ You are `/lua-init`. The user wants a Lua agent project in the current directory
 ## Step 0 — preflight
 
 1. **Auth probe**: Run `Bash(lua models list --json --ci)` — a 1–2 s authenticated call (no project needed). Exit 0 or 10 = authenticated (10 = a typed key scoped away from the model catalog; fine). Exit 9 = not authenticated: use the **Skill tool** with `skill: "lua-auth"`, then re-probe; if still 9, abort with the CLI error verbatim. Exit 11 = the Lua API is unreachable: abort with that line (do not start a login). Do not use `lua agents` as the probe — it walks every organisation and can take 20 s or more on large accounts. If authentication cannot be established, abort: "Authentication didn't complete. Re-run `/lua-auth` then `/lua-init`."
-2. **Version probe** (informational): `Bash(lua --version)`. If below the plugin's pinned minimum (`PINNED_MIN_LUA_CLI` in `${CLAUDE_PLUGIN_ROOT}/hooks/check-lua-version.mjs`, currently 3.36.0), use the **Skill tool** with `skill: "lua-update"` — that slash asks its own confirmation. If declined, continue with the older CLI.
+2. **Version probe** (informational): `Bash(lua --version)`. If below the plugin's pinned minimum (`PINNED_MIN_LUA_CLI` in `${CLAUDE_PLUGIN_ROOT}/hooks/check-lua-version.mjs`, currently 3.37.0), use the **Skill tool** with `skill: "lua-update"` — that slash asks its own confirmation. If declined, continue with the older CLI.
 3. **Existing project**: if `lua.skill.yaml` exists here, say so; `lua init` over it requires `--force` (exit 2 otherwise) — only proceed if the user's request clearly means re-init.
 
 ## Step 1 — collect inputs (single permission per §3.7)
diff --git a/plugins/lua-agent-builder/commands/lua-logs.md b/plugins/lua-agent-builder/commands/lua-logs.md
index 638ad9e..7a1e358 100644
--- a/plugins/lua-agent-builder/commands/lua-logs.md
+++ b/plugins/lua-agent-builder/commands/lua-logs.md
@@ -22,4 +22,4 @@ If `$ARGUMENTS` already contains a type, use it. Otherwise AskUserQuestion **onc
 
 ## Step 3 — present
 
-`--json` prints `{ logs: LogEntry[], pagination }` (for `calls`: `{ calls[], total, page, totalPages }`). Each `LogEntry` has `timestamp`, `type` (`log`|`metric`), **`subType`** (`error` | `warn` | `info` | `debug` | `start` | `complete` — there is no `level` field), `message`, `duration?`, and `metadata` (`logSource`, `primitiveName`, `primitiveId`, `toolId`, `toolName`, `userId`, `agentId`, `runId`, `channel`). There is **no `environment` field** — sandbox vs production is not recorded on a log entry. `metadata.channel === 'dev'` marks turns sent by `lua chat` (CLI traffic, in either environment — not a sandbox marker); `'pop'` is the website widget, `'web'` other web clients. A tool that throws lands under `logSource: 'skill'` with `subType: 'error'`; `agent_error` entries come only from the chat pipeline itself. Group by `subType`, errors first, then by `metadata.logSource`/`primitiveName`. Offer to drill into one entry; don't dump raw JSON unless asked. `runId` on an entry is the conversation/run to correlate with `lua workflows status ` when `logSource` is a workflow source. A run's own timeline is `lua workflows logs ` (`/lua-workflow logs`), which ⏳ on lua-cli 3.36.0 or later also shows the two model events — `step.model_resolved` (`model resolved →  ()`) and `step.model_policy_warning` (`model policy warning:  …`, e.g. a pinned model the organization has excluded, warn-only today).
+`--json` prints `{ logs: LogEntry[], pagination }` (for `calls`: `{ calls[], total, page, totalPages }`). Each `LogEntry` has `timestamp`, `type` (`log`|`metric`), **`subType`** (`error` | `warn` | `info` | `debug` | `start` | `complete` — there is no `level` field), `message`, `duration?`, and `metadata` (`logSource`, `primitiveName`, `primitiveId`, `toolId`, `toolName`, `userId`, `agentId`, `runId`, `channel`). There is **no `environment` field** — sandbox vs production is not recorded on a log entry. `metadata.channel === 'dev'` marks turns sent by `lua chat` (CLI traffic, in either environment — not a sandbox marker); `'pop'` is the website widget, `'web'` other web clients. A tool that throws lands under `logSource: 'skill'` with `subType: 'error'`; `agent_error` entries come only from the chat pipeline itself. Group by `subType`, errors first, then by `metadata.logSource`/`primitiveName`. Offer to drill into one entry; don't dump raw JSON unless asked. `runId` on an entry is the conversation/run to correlate with `lua workflows status ` when `logSource` is a workflow source. A run's own timeline is `lua workflows logs ` (`/lua-workflow logs`), which ⏳ on lua-cli 3.36.0 or later also shows the model events — `step.model_resolved` (`model resolved →  ()`) and `step.model_policy_warning` (`model policy warning:  …`, e.g. a pinned model the organization has excluded, warn-only today) — and ⏳ on 3.37.0 or later the Job-model and budget events: `step.job_model_resolved` (`job model →  × ()`, with `— uncalibrated model, fallback rate` when no calibrated rate could be quoted) and `run.budget_parked` / `run.budget_raised` / `run.budget_exceeded`, which below 3.37.0 `logs` did not print at all. The unit inside a budget line is whatever the gate chose (`actions` on a seat plan, `credits` on legacy) — repeat it verbatim.
diff --git a/plugins/lua-agent-builder/commands/lua-push.md b/plugins/lua-agent-builder/commands/lua-push.md
index 3ab6960..de21a82 100644
--- a/plugins/lua-agent-builder/commands/lua-push.md
+++ b/plugins/lua-agent-builder/commands/lua-push.md
@@ -32,7 +32,7 @@ Always `--ci --force`. **NEVER** `--auto-deploy` (denied at the permission layer
 
 `--set-version` must be `x.y.z`; a `0.x.y` value draws the `warn-version-zero` hook. A push also attaches per-skill source so the admin Builder sees CLI edits (`--no-include-source` disables that) and refreshes the source backup.
 
-⏳ **lua-cli 3.36.0 or later** (the plugin's pinned minimum; the installed `lua --version` tells you which case applies):
+⏳ **lua-cli 3.36.0 or later** (the plugin pins 3.37.0; the installed `lua --version` tells you which case applies):
 - `workflow` pushes accept `--apply-effort`: the pushed envelope is stamped `luaWorkflow: 2` and each agent step's `effort` is sent to the model from that version on — a plain push records effort and applies nothing. Add it only when `$ARGUMENTS` says `--apply-effort` or the user asks; say so in the report (`⚙️ --apply-effort: … per-step effort ENABLED` is the CLI's own notice).
 - ⚠ **`lua push all` also pushes every workflow and ACTIVATES the pushed version** (main `push.ts`, PR #3024 — stage-all queues workflows for deployment with or without `--auto-deploy`; below 3.36.0 workflows are simply excluded). On that CLI, before running `all` in a project whose `dist-v2/manifest.json` lists workflows, tell the user in your one line that the workflow versions go **live**; if that is not wanted, push per type instead (`skill`, `webhook`, …) and leave workflows to `/lua-deploy`.
 
diff --git a/plugins/lua-agent-builder/commands/lua-status.md b/plugins/lua-agent-builder/commands/lua-status.md
index ccd9e5b..21b80dc 100644
--- a/plugins/lua-agent-builder/commands/lua-status.md
+++ b/plugins/lua-agent-builder/commands/lua-status.md
@@ -24,4 +24,4 @@ For what is live on any agent (not just this project) the `mcp__plugin_lua-agent
 
 ## Workflow runs are not in `lua status`
 
-`lua status` reports primitives, not runs. When the user asks about a run, hand off to `/lua-workflow status ` (`lua workflows status  --steps --json`) and read it as follows: `status: 'gated'` with `gate.kind: 'start-consent'` = waiting for a person's consent (cleared from the desktop; ⏳ lua-cli 3.36.0 or later exits 6 under `--strict`, older CLIs exit 0 — never read 0 as "still running" there); `gate.kind: 'model_policy'` (⏳) = a step's model class cannot be resolved under the org policy — `lua workflows clear-gate  --kind model_policy`; `gate.kind: 'budget' | 'billing' | 'exception'` = `raise-budget` / top-up / `retry-step` or `resolve-step`; a `consent.via: 'autonomy'` stamp (⏳, printed as `Consent:  auto (policy) — ≤ …`) = the organization's autonomy envelope admitted the start and nobody was asked; a step's `suspend.approverFallback` (`⇅ approver escalated  → `) = the approval went to the org admins because the initiator was excluded.
+`lua status` reports primitives, not runs. When the user asks about a run, hand off to `/lua-workflow status ` (`lua workflows status  --steps --json`) and read it as follows: `status: 'gated'` with `gate.kind: 'start-consent'` = waiting for a person's consent (cleared from the desktop; ⏳ lua-cli 3.36.0 or later exits 6 under `--strict`, older CLIs exit 0 — never read 0 as "still running" there); `gate.kind: 'model_policy'` (⏳) = a step's model class cannot be resolved under the org policy — `lua workflows clear-gate  --kind model_policy`; `gate.kind: 'budget' | 'billing' | 'exception'` = `raise-budget` / top-up / `retry-step` or `resolve-step` — for a budget park read `budget.unit` (and `usage.engine`) before you name a number: the cap is in **credits** on a legacy plan and **actions** on a seat plan, and `lua workflows raise-budget  --credits ` takes `` in that unit even though the flag is always spelled `--credits`; `budget.exceeded: true` means the run went past its cap and finished anyway rather than parking; a `consent.via: 'autonomy'` stamp (⏳, printed as `Consent:  auto (policy) — ≤ …`) = the organization's autonomy envelope admitted the start and nobody was asked; a step's `suspend.approverFallback` (`⇅ approver escalated  → `) = the approval went to the org admins because the initiator was excluded.
diff --git a/plugins/lua-agent-builder/commands/lua-update.md b/plugins/lua-agent-builder/commands/lua-update.md
index 208f8a8..50a4d53 100644
--- a/plugins/lua-agent-builder/commands/lua-update.md
+++ b/plugins/lua-agent-builder/commands/lua-update.md
@@ -6,7 +6,7 @@ You are `/lua-update`. The user wants to update their lua-cli installation.
 
 ## Step 1 — capture the current version
 
-Run `Bash(lua --version)`; capture as `OLD_VERSION`. The plugin targets lua-cli ≥ 3.36.0 (`PINNED_MIN_LUA_CLI` in `${CLAUDE_PLUGIN_ROOT}/hooks/check-lua-version.mjs`).
+Run `Bash(lua --version)`; capture as `OLD_VERSION`. The plugin targets lua-cli ≥ 3.37.0 (`PINNED_MIN_LUA_CLI` in `${CLAUDE_PLUGIN_ROOT}/hooks/check-lua-version.mjs`).
 
 ## Step 2 — confirm (single permission per §3.7)
 
diff --git a/plugins/lua-agent-builder/commands/lua-workflow.md b/plugins/lua-agent-builder/commands/lua-workflow.md
index c0039d8..577931a 100644
--- a/plugins/lua-agent-builder/commands/lua-workflow.md
+++ b/plugins/lua-agent-builder/commands/lua-workflow.md
@@ -14,7 +14,7 @@ Run `Bash(lua models list --json --ci)` — a 1–2 s authenticated call (no pro
 
 - `list` → `Bash(lua workflows list --ci)`; `view ` → `Bash(lua workflows view  --json)` (includes schedules and goals); `versions ` → `Bash(lua workflows versions )`
 - `runs [name]` → `Bash(lua workflows runs [--workflow ] [--status ] --limit 20)`
-- `status ` → `Bash(lua workflows status  --steps --json)` — summarise `status`, the parked step (`suspend.approvalId` is what `approve` needs), `gate` (`start-consent` = a consent gate a **person** clears from the desktop — `approve` cannot, it needs a `wfa_` id; ⏳ `model_policy` = a step's model class cannot be resolved under the org policy — offer `clear-gate`), `nextAction`, `budget`, and ⏳ (lua-cli 3.36.0 or later) the run's `consent` stamp (`via: 'autonomy'` — say "started without asking: the organization's autonomy envelope admitted it (≤ )"; the human view prints it as `Consent:  auto (policy) — ≤ …`), any step's `suspend.approverFallback` (`⇅ : approver escalated  → ` — the approval went to the org admins because the initiator was excluded), the per-step `taskClass` / `modelRequested` / `modelResolved` / `modelReason` / `modelFallback` and the `usage.byModel` roll-up
+- `status ` → `Bash(lua workflows status  --steps --json)` — summarise `status`, the parked step (`suspend.approvalId` is what `approve` needs), `gate` (`start-consent` = a consent gate a **person** clears from the desktop — `approve` cannot, it needs a `wfa_` id; ⏳ `model_policy` = a step's model class cannot be resolved under the org policy — offer `clear-gate`), `nextAction`, `budget`, and ⏳ (lua-cli 3.36.0 or later) the run's `consent` stamp (`via: 'autonomy'` — say "started without asking: the organization's autonomy envelope admitted it (≤ )"; the human view prints it as `Consent:  auto (policy) — ≤ …`), any step's `suspend.approverFallback` (`⇅ : approver escalated  → ` — the approval went to the org admins because the initiator was excluded), the per-step `taskClass` / `modelRequested` / `modelResolved` / `modelReason` / `modelFallback` and the `usage.byModel` roll-up. Read `budget` with its unit: `budget.unit` (and `usage.engine`) says whether this run counts **credits** (legacy) or **actions** (seat plan) — quote the run's own word, never "credits" by reflex — and `budget.exceeded` means the run crossed its cap and finished anyway (the human view appends `finished past the cap`). ⏳ lua-cli 3.37.0 or later also prints `Tokens:` (uncached in · cache read · cache write · out — **signals, not charges; never add them up**, a cache read is a subset of the input figure), `Uncached`/`Cached`/`Output` columns under `--steps`, and `⚙ : model  · × · chosen by ` on Job-tier rows (`steps[].job`) — that multiplier applies to every model reply the attempt made. Any of these missing means the server did not project it, not that something is wrong
 - ⏳ `policy models get` / `policy autonomy get` (lua-cli 3.36.0 or later — below it `policy` is an unknown action, exit 2: say the installed CLI predates the plugin's pinned minimum and stop) → `Bash(lua workflows policy models get --ci)` / `Bash(lua workflows policy autonomy get --ci)` — the ORGANIZATION's model policy (`compose`, `maxClass`, `consentActions`, `pins`, `fallback`, `allow`, `classes`, `classMap`) or its autonomy envelope (the STORED block and the EFFECTIVE one the server resolved; `enabled` not true ⇒ nothing is pre-consented); `models` → `Bash(lua models list --workflows --json --ci)` — the catalog as a workflow step sees it (class, best for, speed, cost, efforts)
 - `logs ` → `Bash(lua workflows logs )`; `env-overlay ` → `Bash(lua workflows env-overlay  -v latest)`
 - `approval-payload  ` → `Bash(lua workflows approval-payload  --approval )`
@@ -29,7 +29,7 @@ Run `Bash(lua models list --json --ci)` — a 1–2 s authenticated call (no pro
 - `resume  ` → `lua workflows resume  --step  --data ''`
 - `retry-step  ` → `lua workflows retry-step  --step  [--note '']`
 - `resolve-step   skip|complete|fail` → `lua workflows resolve-step  --step  --outcome  [--output '']`
-- `raise-budget  ` → `lua workflows raise-budget  --credits `
+- `raise-budget  ` → `lua workflows raise-budget  --credits ` — the flag is `--credits` on every plan, but `` is the new cap in the **run's own unit**: read `budget.unit` / `usage.engine` from `status --json` first and say "actions" to a seat organization. ⏳ lua-cli 3.37.0 or later prints the unit itself (`✅ budget raised to 200 actions`); below it the confirmation always says "credits", so state the unit yourself
 - `cancel ` → `lua workflows cancel  --reason ''` (two-stage: a second cancel after `forceAvailableAt` forces)
 - `export ` → `lua workflows export  --out ./exported` (writes `src/workflows/.ts` for a chat-composed workflow)
 - `schedules …` / `goals …` → build from the help in workflows.md §7 and confirm the same way
@@ -41,4 +41,4 @@ Run `Bash(lua models list --json --ci)` — a 1–2 s authenticated call (no pro
 
 ## Step 2 — present
 
-Map exit codes: `0` ok · `1` API refusal (print the `✖` line; `RUNS_IN_FLIGHT` = `concurrencyPolicy: forbid` and a run is live — ⚠ not produced by `lua workflows start` today, the start route skips the policy check) · `3` not found · `4` run failed · `5` cancelled · `6` gated — a consent gate (`gate.kind: 'start-consent'`: a person clears it from the desktop or the approvals inbox; `approve` cannot; ⏳ on lua-cli 3.36.0 or later `start` prints the server's consent card first, and `status --strict` exits 6 on such a run where older CLIs exited 0), quota or billing (`nextAction` says `top_up` or `raise_budget`) · `7` timeout reached while the run is live (offer `watch`) · `8` parked waiting for a human (show the approval id / signal name / step to resume and the matching verb; ⏳ a `model_policy` park names `clear-gate`). For `--json` output summarise `data`; never dump it raw unless asked.
+Map exit codes: `0` ok · `1` API refusal (print the `✖` line; `RUNS_IN_FLIGHT` = `concurrencyPolicy: forbid` and a run is live — ⚠ not produced by `lua workflows start` today, the start route skips the policy check) · `3` not found · `4` run failed · `5` cancelled · `6` gated — a consent gate (`gate.kind: 'start-consent'`: a person clears it from the desktop or the approvals inbox; `approve` cannot; ⏳ on lua-cli 3.36.0 or later `start` prints the server's consent card first, and `status --strict` exits 6 on such a run where older CLIs exited 0), quota or billing (`nextAction` says `top_up` or `raise_budget`) · `7` timeout reached while the run is live (offer `watch`) · `8` parked waiting for a human (show the approval id / signal name / step to resume and the matching verb; ⏳ a `model_policy` park names `clear-gate`). For `--json` output summarise `data`; never dump it raw unless asked. ⏳ lua-cli 3.37.0 or later, `logs ` also carries the money timeline — `run.budget_parked` / `run.budget_raised` / `run.budget_exceeded` and `step.job_model_resolved` (`job model →  × ()`); the unit inside those lines is the gate's own word and must be quoted as-is.
diff --git a/plugins/lua-agent-builder/hooks/check-lua-version.mjs b/plugins/lua-agent-builder/hooks/check-lua-version.mjs
index ae7bd35..e5180b6 100644
--- a/plugins/lua-agent-builder/hooks/check-lua-version.mjs
+++ b/plugins/lua-agent-builder/hooks/check-lua-version.mjs
@@ -7,19 +7,26 @@ import { runHook, checkNodeVersion, isMainScript } from '../lib/hook-runtime.mjs
 import { spawnLua } from '../lib/lua-cli.mjs';
 
 // Pinned minimum lua-cli version. The plugin's commands, agents and knowledge
-// files describe the lua-cli 3.36.0 surface: the 3.33.0 base (workflows,
+// files describe the lua-cli 3.37.0 surface: the 3.33.0 base (workflows,
 // triggers, devices, voice, agent versions, `lua auth sessions`, the typed
 // exit-code classes, `lua test preprocessor|postprocessor|workflow`, `lua push
-// --no-include-source`) plus the 3.36.0 workflow verbs (`policy models|autonomy`,
+// --no-include-source`), the 3.36.0 workflow verbs (`policy models|autonomy`,
 // `clear-gate`, `recompose`, `models list --workflows`, `push --apply-effort`)
-// that answer exit 2 on anything older.
+// that answer exit 2 on anything older, and the 3.37.0 Job-billing read-outs
+// (the `Tokens:` line and the `Uncached`/`Cached`/`Output` columns, the `⚙`
+// Job-model line, the engine-aware budget wording and `finished past the cap`,
+// the budget events in `workflows logs`, the unit-aware `raise-budget`
+// confirmation and the `job-model-default` deploy advisory). 3.37.0 adds NO
+// command and NO option — every shape the plugin emits already runs on 3.36.0,
+// which is why this pin still only warns.
 // Older CLIs still work for the core loop — this hook only WARNS, never
 // blocks — but a user on an older release sees the upgrade hint once per
-// session so the command shapes the plugin emits match what their CLI
-// accepts. The pin must be a version that is published on npm (3.36.0 is
-// published 2026-09-18), so `/lua-update` can always satisfy it; the lint at
-// scripts/lint-pinned-version.mjs enforces that inside the monorepo.
-export const PINNED_MIN_LUA_CLI = '3.36.0';
+// session so the output the plugin's agents read matches what their CLI
+// prints. The pin must be a version that is published on npm, so
+// `/lua-update` can always satisfy it; the lint at
+// scripts/lint-pinned-version.mjs enforces that inside the monorepo (it is
+// RED by design between raising this pin and the npm publish of 3.37.0).
+export const PINNED_MIN_LUA_CLI = '3.37.0';
 
 /**
  * Parse "X.Y.Z" into [X, Y, Z]. Returns null on garbage input.
diff --git a/plugins/lua-agent-builder/lib/knowledge/cli-reference.md b/plugins/lua-agent-builder/lib/knowledge/cli-reference.md
index 9bdf807..5bf562c 100644
--- a/plugins/lua-agent-builder/lib/knowledge/cli-reference.md
+++ b/plugins/lua-agent-builder/lib/knowledge/cli-reference.md
@@ -1,6 +1,6 @@
-# lua-cli command reference (3.33.0 base · 3.36.0 additions marked ⏳)
+# lua-cli command reference (3.33.0 base · 3.36.0 / 3.37.0 additions marked ⏳)
 
-Read from `src/cli/command-definitions.ts`, `src/utils/aliases.ts`, `src/index.ts`, `src/errors/cli.error.ts`, `src/services/request-credential.ts` and the per-command implementations in `src/commands/` of lua-cli 3.33.0. The installed CLI's `lua  --help` is authoritative for flags; this file adds what the help text gets wrong or omits (marked ⚠). Entries marked **⏳** require **lua-cli 3.36.0 or later** (the plugin's pinned minimum); they were read from lua-cli `main` / `feat/workflow-autonomy`, the refs 3.36.0 is cut from (per-step model classes, workflow autonomy, the stage-all change), and answer exit 2 below 3.36.0.
+Read from `src/cli/command-definitions.ts`, `src/utils/aliases.ts`, `src/index.ts`, `src/errors/cli.error.ts`, `src/services/request-credential.ts` and the per-command implementations in `src/commands/` of lua-cli 3.33.0. The installed CLI's `lua  --help` is authoritative for flags; this file adds what the help text gets wrong or omits (marked ⚠). Entries marked **⏳** require **lua-cli 3.36.0 or later** (the plugin's pin is **3.37.0** since 1.4.0); they were read from lua-cli `main` / `feat/workflow-autonomy`, the refs 3.36.0 is cut from (per-step model classes, workflow autonomy, the stage-all change), and answer exit 2 below 3.36.0. Entries marked **⏳ 3.37.0** are the Job-billing read-outs: lua-cli 3.37.0 added **no command and no option** — its only `src/cli/command-definitions.ts` change is the `--credits` help string — so every command shape here is identical on 3.36.0 and 3.37.0, and only the output differs.
 
 lua-cli is a TypeScript toolchain. It has nothing to do with the Lua programming language.
 
@@ -87,7 +87,7 @@ Legend — **RO** read-only · **L** local write · **S** server write (staging/
 |---|---|---|
 | `lua push [type] [--name n] [--set-version x.y.z] [--force] [--fresh] [--no-include-source]` | `type` ∈ `skill agent webhook trigger job preprocessor postprocessor mcp device device-trigger voice workflow backup all` (⚠ help lists a shorter set; `persona` is an alias of `agent`). No type or `all --force` = **stage-all** (auto-bumps every versioned primitive, upserts MCP servers, pushes agent config + backup; **workflows are NOT included** — the stage-all handler list at `push.ts` ~1196-1206 is skill webhook trigger job preprocessor postprocessor device device-trigger voice, so a workflow is pushed only with `lua push workflow --name `). ⚠ ⏳ **That changes in lua-cli 3.36.0** (main `push.ts`, commit af66332ee / PR #3024 of 2026-09-17, not in 3.35.0): `workflowH` joins the stage-all handler list and every pushed workflow is **always queued for activation** — `toDeploy` takes it with or without `--auto-deploy` and the run prints `🚀 Activating workflow version(s) — workflows deploy on their own, not via \`lua version promote\`…` — so on that CLI `lua push all --ci --force` pushes every workflow *and makes the pushed version live*. Treat `lua push all` as production-affecting for workflows once `lua --version` is 3.36.0 or newer. ⏳ `--apply-effort` (workflow pushes only, `lua push all --apply-effort` included) stamps the pushed envelope `luaWorkflow: 2` so each agent step's `effort` reaches the model from that version on; a plain push never does (workflows.md §2). Granular with `--name`; one entity auto-selects; several without `--name` → prompt (exit 1 under `--ci`); `--name` with no type throws a plain Error → exit **1** (`lua test` gives the same sentence exit 2). `--set-version` must be `x.y.z`; omitted + `--force` ⇒ patch bump. `--auto-deploy` is **ignored by `lua push` and `lua push all`** (`src/commands/push.ts` ~543-554 prints `--auto-deploy is ignored when agent versioning is on` and clears the flag before stage-all runs, so nothing goes live — MCP servers included, even though the CLI's own usage text still advertises `lua push all --force --auto-deploy` as "push and deploy all"). It has an effect **only on a single-primitive push**: `lua push mcp --auto-deploy` activates the server (~1093-1101), `lua push agent --auto-deploy` deploys the persona version (~975-984), and every versioned type (`skill webhook trigger job preprocessor postprocessor device device-trigger voice workflow`) publishes the pushed version to production (`pushVersionedPrimitive` → `genericDeployAfterPush` → `handler.publishVersion`, ~396-460). Those single-primitive effects are production go-lives with no confirmation, which is why this plugin denies the flag in every form — **never used by this plugin**. ⚠ **Stage-all exits 0 on partial failure**: `pushAllCommand` collects per-item failures, prints `❌ Failed to push : …` and a `⚠️  N component(s) failed to push` summary, then `✅ Push All Complete!` and returns without setting an exit code (`push.ts` ~1300-1353; `process.exitCode` is never set in the file) — parse the output for `❌ Failed to push` / `component(s) failed`, never the exit code (validated live 2026-09-13) | S (+P with `--auto-deploy` on a single primitive) |
 | `lua deploy  --name  --set-version  --force` | `type` ∈ `skill webhook trigger job preprocessor postprocessor persona all` (⚠ help/menu omit `trigger`). `all --force` deploys the latest version of everything and **ignores `--set-version`**. Persona takes an integer or `latest`. **What "deploy" does depends on the kind** (§5). For `webhook job preprocessor postprocessor trigger` (and `lua workflows deploy`) the server performs a **scoped promote** — it creates and promotes a new agent version scoped to that one primitive, so the change is live at once *and* the agent-version history stays consistent (lua-api `scoped-promote.util.ts`; the `ScopedPromotePrimitiveType` union is exactly `webhooks jobs preprocessors postprocessors triggers workflows`). For **`skill` there is no scoped promote**: `lua deploy skill` only moves the skill's `activeVersionId` pointer (and refreshes the per-skill blob lua-core reads every turn) — **live immediately, on a versioned agent too** — but the active agent version's snapshot keeps its old pin, so `lua version status` reports a mismatch and the next `lua version promote` (a rollback included) writes the snapshot's skill pins back onto the live rows and **silently reverts that deploy** (lua-agents `agent-version.service.ts` `applyAgentsDBWritesInTx`). The **persona is different again: it is live on `lua push agent`** — the CLI's `POST …/persona/version` reaches lua-agents `createPersonaVersion`, which persists the version as `published` and rewrites `subAgent.persona` at once (`persona.service.ts` `persistPersona` → `updateAgentPersona`), and lua-core reads `subAgent.persona` directly on every turn (`prompt.service.ts`); there is no staged persona. So `lua deploy persona --set-version ` is the **re-point / rollback** verb (`setAgentPersonaVersion` rewrites the served persona from that version), and `lua version promote` **never changes the served persona** — it only flips persona-version status flags and sets `activeAgentVersionId` + `model`. ⚠ The CLI's own info line — "for agents under versioning `lua deploy` creates and promotes a new agent version scoped to this primitive" — is wrong for skill and persona (`src/commands/deploy.ts` ~228). On an agent with **no** agent versions yet every `lua deploy ` simply goes live (promote no-ops with `no-active-version`; readers fall back to the live pointer). Plugin rule: versioned agent + skill ⇒ push, `lua version create`, `lua version promote` — never `lua deploy skill`; persona ⇒ `lua push agent` *is* the deploy, `lua deploy persona ` the rollback. ⚠ **`lua deploy all --force` exits 0 on failure**, and a primitive whose stored id is stale or that has no versions is not even counted as failed — it prints `ℹ️  No versions for  "", skipping` and still `✅ Deployed N primitives successfully` / `All deployed` (`deploy.ts` ~537-545, ~604-645; no exit code is set) — read the output for `skipping` and `deployment(s) failed` (validated live 2026-09-13) | **P** |
-| `lua workflows deploy  -v ` | the only way to make a workflow version live (⏳ on lua-cli 3.36.0 `lua push all` also activates the workflows it pushes — see the push row) | **P** |
+| `lua workflows deploy  -v ` | the only way to make a workflow version live (⏳ on lua-cli 3.36.0 `lua push all` also activates the workflows it pushes — see the push row). Prints **advisory** `  ⚠ ` lines under the success line and still succeeds: `job-tier-not-enabled`, and ⏳ 3.37.0 `job-model-default` — a Job step naming no `model` runs on the platform (else org) default and every model reply is billed at that model's multiplier (workflows.md §4) | **P** |
 | ⏳ `lua workflows policy models get\|set …` · `lua workflows policy autonomy get\|set …` · `lua workflows clear-gate  --kind model_policy` · `lua workflows recompose ` | the ORGANIZATION's workflow policy (`/admin/orgs//workflow-policy`; administrator; `get` read-only, `set` writes org-wide — `policy autonomy set --enabled on` decides which agent-started runs skip the consent card), a `model_policy` park cleared by hand, a new version of a chat-composed definition. Flags and value sets in workflows.md §2–§3; unknown action (exit 2) below 3.36.0 | RO / S |
 | `lua version create [-m msg] [--auto-push] [--commit-hash h]` · `list [--status active\|staged\|superseded\|deleted\|all] [--limit n] [--json]` · `show  [--json]` · `diff   [--json]` · `status` · `promote ` · `delete  [--force]` | agent versions = atomic snapshots of the whole staged state; `promote` swaps the live version (**no confirmation in the CLI** — the plugin gates it); also the rollback verb. Under `--ci` (or with no TTY) `create` skips its message prompt (`-m` optional) and `delete ` skips its confirmation **even without `--force`** — it deletes at once (`src/commands/version.ts` ~439-450) | create S · promote **P** |
 | `lua persona production deploy --persona-version  [--force]` | same as `lua deploy persona` | **P** |
diff --git a/plugins/lua-agent-builder/lib/knowledge/decision-trees.md b/plugins/lua-agent-builder/lib/knowledge/decision-trees.md
index f177e1b..270b79d 100644
--- a/plugins/lua-agent-builder/lib/knowledge/decision-trees.md
+++ b/plugins/lua-agent-builder/lib/knowledge/decision-trees.md
@@ -47,7 +47,7 @@ If several apply, the agent usually needs all of them. Stage: tools → integrat
 Is it one unit of work under ~10 minutes with no human in the loop?
 ├── Yes → LuaJob (cron / interval / once) or Jobs.create for user-scheduled one-offs
 └── No → createWorkflow when ANY of: several dependent steps · needs approval / a signal / an input request ·
-         fan-out over a list (foreach) · retries with backoff and a credit budget · long Job-tier code (git workspace, `ctx.$`) ·
+         fan-out over a list (foreach) · retries with backoff and a run budget (credits, or actions on a seat plan) · long Job-tier code (git workspace, `ctx.$`) ·
          a schedule whose fires must not overlap (`concurrencyPolicy: 'forbid'` — guards scheduled fires only; manual/API/SDK starts are not checked today, workflows.md §1) · an iterative goal with a judge
 ```
 A workflow can itself be on a `schedule` (it becomes a platform Job) — prefer that over a LuaJob that calls `Workflows.start`.
@@ -128,6 +128,8 @@ Single is usually right. Split when personas must differ (customer-facing vs int
 
 Omit `model` for the platform default (`alibaba/qwen3.8-flash`). Pick from `lua models list --json` — never invent a code. Per-channel or per-request choice → a model resolver function `(req) => …`. Tune with `modelSettings` (`temperature`, `reasoning.effort`, `maxOutputTokens`).
 
+⚠ That default is the **agent's**, and a workflow **Job-tier** step does not use it: a Job step runs on its own `model`, failing that the platform's default for Job steps, failing that the organization's default — and every model reply of the attempt is billed at THAT model's multiplier (workflows.md §4). Leaving `model` off a Job step is a cost decision, not a neutral one; ⏳ lua-cli 3.37.0 or later says so with a `job-model-default` advisory at `lua workflows deploy` and an `⚙` line under `lua workflows status --steps`.
+
 **Per agent step inside a workflow** (⏳ lua-cli 3.36.0 or later; workflows.md §2):
 
 ```
diff --git a/plugins/lua-agent-builder/lib/knowledge/primitives.md b/plugins/lua-agent-builder/lib/knowledge/primitives.md
index 5221c37..d0075e2 100644
--- a/plugins/lua-agent-builder/lib/knowledge/primitives.md
+++ b/plugins/lua-agent-builder/lib/knowledge/primitives.md
@@ -1,4 +1,4 @@
-# Lua SDK primitive reference (lua-cli 3.33.0 base · 3.36.0 additions marked ⏳)
+# Lua SDK primitive reference (lua-cli 3.33.0 base · 3.36.0 / 3.37.0 additions marked ⏳)
 
 Source of truth for every primitive and runtime API the plugin's agents reason about. Every shape below is read from the lua-cli 3.33.0 source (`src/types/skill.ts`, `src/types/voice.ts`, `src/types/workflow.ts`, `src/api-exports.ts`, `src/interfaces/*.ts`, `template/`) — not from the public docs, which lag in places. When this file and the live docs disagree, this file wins; when this file and the installed CLI disagree, check `lua --cli-version` (the plugin targets ≥ 3.33.0) and look the symbol up with the `mcp__plugin_lua-agent-builder_lua-docs__query_docs_filesystem_lua_cli` tool (`rg -n "" /api/`).
 
@@ -352,7 +352,7 @@ lua voice list [--json]
 
 ## 11. `LuaWorkflow` — durable multi-step orchestration
 
-`createWorkflow({...}).then(step).agentStep(...).approval(...).commit()` registered on `LuaAgent.workflows`. Pushed with `lua push workflow --name `, deployed with `lua workflows deploy  -v latest` (`lua deploy` has no workflow type), tested offline with `lua test workflow --name  --input @in.json …`. **Full reference: workflows.md.** Use a workflow when the job is multi-step, long-running, needs human approval/signals, fan-out, retries with budgets, or Job-tier code with a git workspace. Use a plain tool/job/webhook otherwise. ⏳ lua-cli 3.36.0 or later: an `agentStep` may name a `taskClass` (`classify extract transform draft research reason code judge`), ask for a class with `model: 'class/fast' | 'class/balanced' | 'class/strong'`, list `requires` traits and an `effort` (`low | medium | high` — recorded, not applied, until `lua push workflow --apply-effort`); agent-started runs above the consent ladder (15 steps · 20 credits · 1 h) park `gated` until a person consents unless the org's autonomy envelope admits them (workflows.md §2–§3).
+`createWorkflow({...}).then(step).agentStep(...).approval(...).commit()` registered on `LuaAgent.workflows`. Pushed with `lua push workflow --name `, deployed with `lua workflows deploy  -v latest` (`lua deploy` has no workflow type), tested offline with `lua test workflow --name  --input @in.json …`. **Full reference: workflows.md.** Use a workflow when the job is multi-step, long-running, needs human approval/signals, fan-out, retries with budgets, or Job-tier code with a git workspace. Use a plain tool/job/webhook otherwise. ⏳ lua-cli 3.36.0 or later: an `agentStep` may name a `taskClass` (`classify extract transform draft research reason code judge`), ask for a class with `model: 'class/fast' | 'class/balanced' | 'class/strong'`, list `requires` traits and an `effort` (`low | medium | high` — recorded, not applied, until `lua push workflow --apply-effort`); agent-started runs above the consent ladder (15 steps · 20 credits · 1 h) park `gated` until a person consents unless the org's autonomy envelope admits them (workflows.md §2–§3). ⚠ A **Job-tier** step is billed per model **reply**, not per attempt — a credit per reply on a legacy plan, actions (price band × the model's multiplier, cached tokens at the provider's fraction) on a seat plan — and it runs on its own `model`, failing that the platform's Job default, failing that the org's; size budgets from replies and pin `model` on Job steps (workflows.md §4).
 
 ---
 
@@ -404,7 +404,7 @@ Jobs.getJob(jobId) | Jobs.getAll({ includeDynamic?: boolean })
 The `execute` function is **serialised with `toString()`**: it cannot close over variables — pass everything through `metadata` and read `job.metadata` inside. Created as version 1.0.0 and activated in one call. Use for "remind me in 1 hour" / "check this basket in 3 hours". `JobInstance`: `id`, `name`, `metadata`, `activeVersion`, `data`, `updateMetadata()`, `delete()`, `user()`, `trigger()`, `activate()`, `deactivate()` — **no `job.jobId`, no `job.schedule`**.
 
 ### `Workflows` — start/inspect/steer runs from code
-`Workflows.start(nameOrId, input?, { idempotencyKey?, budget?, waitSeconds? (≤55), initialState?, correlationKey?, tags?, replyTo?, onBehalfOf?, workflowVersionId? })` (always fire-and-return; from a code step it is a DETACHED run — use `.workflow()` to wait), `.get(runId)`, `.list({...})`, `.cancel(runId, { mode?: 'request'|'force', reason? })`, `.resume(runId, stepId, resumeData)`, `.signal(runId, name, payload?, { dedupeKey? })`, `.signalByKey(...)`, `.startBatch(...)`, `.setGoal`, `.goals.*`. **All of those work in production** — `resume`, `signal`, `signalByKey`, `startBatch`, `setGoal` and `goals.*` were exercised live on 2026-09-13 and reached their real providers (`RUN_NOT_FOUND` / `CORRELATION_KEY_NOT_FOUND` / `WORKFLOW_NOT_FOUND` for bogus ids, `goals.list()` → `[]`). The `resume_unavailable` / `signal_unavailable` / `not_implemented` codes in lua-core `workflow-sandbox-bridge.ts` are thrown only when the optional provider is not injected (`!this.delegates?.resume|signal`, `!this.batches`, `!this.goals`) — a guard for platforms without it, not production's behaviour, whatever the bridge's own header comment still says. ⚠ **`Workflows.raiseBudget` is the one member that never works from the SDK**: under `lua test` it throws `WorkflowApiError{ code: 'WORKFLOWS_API_UNAVAILABLE', status: 501 }` (`src/api/workflow.api.service.ts`: `raiseBudget: unavailable('raiseBudget', 'R45')`); deployed it is `raiseBudget: notImplemented('raiseBudget')` in the bridge → 501 `not_implemented` ("Workflows.raiseBudget is not available on this server yet") — two different error codes for the same dead member, so never branch on them. Raise a parked run's budget with the CLI: `lua workflows raise-budget  --credits `. ⚠ **Deployed `list` ignores the typed `workflow` filter**: the bridge reads only `status` and an untyped `workflowId` (`workflow-sandbox-bridge.ts` ~223-230), so `Workflows.list({ workflow: 'x' })` returns every run of the agent in production (2 of 2 on the probe) while `lua test` resolves the name first — pass `workflowId` (the id from `lua workflows view  --json`; it is not in the typed options, so cast) or filter the returned runs by their `workflowId` yourself. ⚠ **`concurrencyPolicy:'forbid'` is not enforced on `Workflows.start`** (nor on `lua workflows start`, the REST start route or a trigger's `{ startWorkflow }`): `WorkflowRunService.createRun` has no overlap check (lua-core `workflow-run.service.ts` header: forbid-overlap "lands with later slices"); only the schedule dispatcher, the agent compose-tool start and batch starts check it. Two `lua workflows start` calls 2 s apart on a `forbid` workflow both ran (2026-09-13). `RUNS_IN_FLIGHT` is typed for every start path but today none of these produce it — dedupe with `idempotencyKey`, guard non-reentrant work inside the workflow (`ctx.once`, a `Data` lock row), and never rely on the policy alone. Details in workflows.md.
+`Workflows.start(nameOrId, input?, { idempotencyKey?, budget?, waitSeconds? (≤55), initialState?, correlationKey?, tags?, replyTo?, onBehalfOf?, workflowVersionId? })` (always fire-and-return; from a code step it is a DETACHED run — use `.workflow()` to wait), `.get(runId)`, `.list({...})`, `.cancel(runId, { mode?: 'request'|'force', reason? })`, `.resume(runId, stepId, resumeData)`, `.signal(runId, name, payload?, { dedupeKey? })`, `.signalByKey(...)`, `.startBatch(...)`, `.setGoal`, `.goals.*`. **All of those work in production** — `resume`, `signal`, `signalByKey`, `startBatch`, `setGoal` and `goals.*` were exercised live on 2026-09-13 and reached their real providers (`RUN_NOT_FOUND` / `CORRELATION_KEY_NOT_FOUND` / `WORKFLOW_NOT_FOUND` for bogus ids, `goals.list()` → `[]`). The `resume_unavailable` / `signal_unavailable` / `not_implemented` codes in lua-core `workflow-sandbox-bridge.ts` are thrown only when the optional provider is not injected (`!this.delegates?.resume|signal`, `!this.batches`, `!this.goals`) — a guard for platforms without it, not production's behaviour, whatever the bridge's own header comment still says. ⚠ **`Workflows.raiseBudget` is the one member that never works from the SDK**: under `lua test` it throws `WorkflowApiError{ code: 'WORKFLOWS_API_UNAVAILABLE', status: 501 }` (`src/api/workflow.api.service.ts`: `raiseBudget: unavailable('raiseBudget', 'R45')`); deployed it is `raiseBudget: notImplemented('raiseBudget')` in the bridge → 501 `not_implemented` ("Workflows.raiseBudget is not available on this server yet") — two different error codes for the same dead member, so never branch on them. Raise a parked run's budget with the CLI: `lua workflows raise-budget  --credits ` — the flag is spelled `--credits` on every plan, but `` is the new cap in the RUN's own unit (credits on legacy, **actions** on a seat plan; `lua workflows status ` says which, and ⏳ lua-cli 3.37.0 or later names it in the park hint and the confirmation). ⚠ **Deployed `list` ignores the typed `workflow` filter**: the bridge reads only `status` and an untyped `workflowId` (`workflow-sandbox-bridge.ts` ~223-230), so `Workflows.list({ workflow: 'x' })` returns every run of the agent in production (2 of 2 on the probe) while `lua test` resolves the name first — pass `workflowId` (the id from `lua workflows view  --json`; it is not in the typed options, so cast) or filter the returned runs by their `workflowId` yourself. ⚠ **`concurrencyPolicy:'forbid'` is not enforced on `Workflows.start`** (nor on `lua workflows start`, the REST start route or a trigger's `{ startWorkflow }`): `WorkflowRunService.createRun` has no overlap check (lua-core `workflow-run.service.ts` header: forbid-overlap "lands with later slices"); only the schedule dispatcher, the agent compose-tool start and batch starts check it. Two `lua workflows start` calls 2 s apart on a `forbid` workflow both ran (2026-09-13). `RUNS_IN_FLIGHT` is typed for every start path but today none of these produce it — dedupe with `idempotencyKey`, guard non-reentrant work inside the workflow (`ctx.once`, a `Data` lock row), and never rely on the policy alone. Details in workflows.md.
 
 ### `AI` — one-shot generation outside the agent's persona
 ```ts
@@ -518,6 +518,7 @@ Every production-affecting verb above is gated by this plugin: bare forms are de
 32. `lua test skill|webhook|job|…` prints `✅ … execution successful!` and exits **0 when `execute` throws** — the throw comes back as the result `{ status: 'error', error }` (`src/utils/sandbox.ts` ~463-467; `test.ts` ~390-399, ~497-501). Check the result, not the exit code. Likewise `lua push all` / `lua deploy all` exit 0 after per-item failures and `No versions … skipping` — parse the summary (cli-reference.md §4).
 33. ⏳ lua-cli 3.36.0 or later: an agent step's `taskClass` needs a `model` on a pushed definition (`task-class-without-model`, server-side at push — `lua compile` passes it); `effort` is recorded and estimated but reaches the model only after `lua push workflow --apply-effort`; the agent-level `modelSettings.reasoning.effort` scale (`off / minimal / max`) is a different thing (workflows.md §2).
 34. ⏳ lua-cli 3.36.0 or later: `lua push all` will push every workflow **and activate the pushed version** (main `push.ts`, PR #3024) — a production change the stage-all below 3.36.0 does not make (cli-reference.md §4).
+35. A Job-tier step is charged per model **reply**, not per attempt — "a Job attempt is 4 credits" holds only while the platform meters a run flat; a priced run is a credit per reply (legacy) or actions = price band × the model's multiplier per model call with cached tokens at the provider's fraction (seat), and `lua workflows raise-budget --credits ` raises a cap counted in the run's OWN unit whatever the flag is called (workflows.md §4).
 
 ---
 
diff --git a/plugins/lua-agent-builder/lib/knowledge/workflows.md b/plugins/lua-agent-builder/lib/knowledge/workflows.md
index 3ffc4e1..6ec988b 100644
--- a/plugins/lua-agent-builder/lib/knowledge/workflows.md
+++ b/plugins/lua-agent-builder/lib/knowledge/workflows.md
@@ -1,6 +1,6 @@
-# Lua Workflows reference (lua-cli 3.33.0 base · 3.36.0 additions marked ⏳)
+# Lua Workflows reference (lua-cli 3.33.0 base · 3.36.0 / 3.37.0 additions marked ⏳)
 
-Read from the lua-cli source (`src/types/workflow.ts`, `src/compiler/plugins/workflow.plugin.ts`, `src/commands/workflows.ts`, `src/commands/workflow-local-run.ts`, `src/api-exports.ts`) and the shipped examples (`template/examples/workflows/*`). Where the public docs disagree with the source, the source wins (differences are flagged ⚠). Everything marked **⏳** requires **lua-cli 3.36.0 or later** (the plugin's pinned minimum); it was read from lua-cli `main` (per-step model classes: `src/interfaces/workflow-model-classes.ts`, `src/commands/models-workflow-view.ts`, `src/commands/push-helpers.ts`, `commands/workflows.ts` `policyCore` / `clearGateCore` / `recomposeCore`) and the `feat/workflow-autonomy` branch (`src/interfaces/workflow-autonomy.ts`, `autonomyPolicyCore`, `consentLine`) — the two refs 3.36.0 is cut from. Those verbs answer exit 2 (unknown action / unknown option) below 3.36.0.
+Read from the lua-cli source (`src/types/workflow.ts`, `src/compiler/plugins/workflow.plugin.ts`, `src/commands/workflows.ts`, `src/commands/workflow-local-run.ts`, `src/api-exports.ts`) and the shipped examples (`template/examples/workflows/*`). Where the public docs disagree with the source, the source wins (differences are flagged ⚠). Everything marked **⏳** requires **lua-cli 3.36.0 or later** (the plugin's pin is **3.37.0** since 1.4.0); it was read from lua-cli `main` (per-step model classes: `src/interfaces/workflow-model-classes.ts`, `src/commands/models-workflow-view.ts`, `src/commands/push-helpers.ts`, `commands/workflows.ts` `policyCore` / `clearGateCore` / `recomposeCore`) and the `feat/workflow-autonomy` branch (`src/interfaces/workflow-autonomy.ts`, `autonomyPolicyCore`, `consentLine`) — the two refs 3.36.0 is cut from. Those verbs answer exit 2 (unknown action / unknown option) below 3.36.0. **⏳ 3.37.0** marks the Job-billing read-outs added after 3.36.0 (`commands/workflows.ts` `tokensLine`, `stepTokenCells`, `stepJobModelLine`, `budgetEngineOf`, `budgetEventDetail`, `jobModelEventDetail`, `budgetCapsLabel`): they add **no verb and no flag** — 3.37.0 changed one help string and nothing else in `src/cli/command-definitions.ts` — so every command in this file runs unchanged on 3.36.0 and only prints less. What a run is CHARGED (below, §4) is the platform's rule and is already true on 3.36.0; only the lines that show it are new.
 
 A workflow is a durable, resumable graph of steps the platform runs for you: code steps, agent steps, tool steps, approvals, signals, timers, fan-out, nested workflows, with budgets, retries, schedules and goals. Use one when a tool or job is not enough: multi-step, long-running, human-in-the-loop, or Job-tier code with a git workspace.
 
@@ -152,7 +152,16 @@ Refused **locally at push, before any POST** (`src/interfaces/workflow-model-cla
 
 **Org policy** — `lua workflows policy models get|set` (the ORGANIZATION's `models` block, `GET|PATCH /admin/orgs//workflow-policy`; orgId from `lua.skill.yaml`; needs an administrator — a 403 is printed as it came; a change reaches a composing agent within 30 s). `set` flags, each optional, only the named members are sent: `--compose on|off` (may the composer be shown the model menu) · `--max-class fast|balanced|strong` (ceiling for class requests and the class map; absent = `strong`) · `--consent-actions ` (estimated actions above which a composed run shows the consent card; platform default 60) · `--allow ` (comma-separated; narrows the approved set — `--allow ''` = all approved minus the org's excluded models) · `--class-fast|--class-balanced|--class-strong ` (ordered overrides of one class) · `--class-map =,…` · `--pins class-only|allowed` (may a composed definition pin a concrete code; default class-only) · `--fallback same-class|same-provider` (where a failed leg may hop — not the chat fallback chain; default same-class). Spelling is refused locally (exit 2, no request); `set` with no flag is exit 2; `get` prints an absent member as `— (platform default)`.
 
-**At run time**: `lua workflows start` prints the server-rendered consent card whenever the server serves one (`modelConsent.card` — per step the class or pin, the model it resolves to today, the effort and the reason, then one cost line; the CLI adds nothing), then `⏸️ The run is gated awaiting consent — approve it from the desktop` and exits 6 (`--follow` → `watch`, which exits 6 on the `run.gated` frame unless `--wait-for-human`). A step whose class cannot be resolved under the current policy **parks, never fails** (`gate.kind: 'model_policy'`): `lua workflows status ` prints `⏸️ Paused — a step's model request cannot be resolved under the current policy:` with the code and step, and `lua workflows clear-gate  --kind model_policy` (alias `ungate`; deliberately not folded into `resume`, which stays the `kind:'input'` resume) clears it by hand — the sweep clears it on its own when the switch returns, and a run not on that gate answers `ℹ️ … Nothing to clear` with exit 0. `status --steps --json` step rows carry `taskClass`, `modelRequested`, `modelResolved`, `modelReason`, `effortApplied` and `modelFallback[]` (lua-api `workflow-projection.ts`); `status` prints a `🧠 By model` roll-up (`Model · [Class] · Calls · Credits|Actions · [Fallbacks]`) from the run's `usage.byModel`, or folded from the step receipts and then marked `(derived …)`. `lua workflows logs ` shows the two model events — `step.model_resolved` as `model resolved →  ()` and `step.model_policy_warning` as `model policy warning:  …` (`WORKFLOW_LOG_EVENT_PATTERN`; `watch` prints every frame). `lua workflows recompose ` (alias `recompile`) asks the server to rewrite the stored task classes of a chat-composed definition into `class/` and publish a new version on the same parent — no agent turn, `unchanged` when nothing needs rewriting, `RECOMPOSE_NOT_APPLICABLE` (409) without an active version; `lua workflows deploy` still refuses a dynamic workflow, so `lua workflows versions ` is where you see which version is active.
+**At run time**: `lua workflows start` prints the server-rendered consent card whenever the server serves one (`modelConsent.card` — per step the class or pin, the model it resolves to today, the effort and the reason, then one cost line; the CLI adds nothing), then `⏸️ The run is gated awaiting consent — approve it from the desktop` and exits 6 (`--follow` → `watch`, which exits 6 on the `run.gated` frame unless `--wait-for-human`). A step whose class cannot be resolved under the current policy **parks, never fails** (`gate.kind: 'model_policy'`): `lua workflows status ` prints `⏸️ Paused — a step's model request cannot be resolved under the current policy:` with the code and step, and `lua workflows clear-gate  --kind model_policy` (alias `ungate`; deliberately not folded into `resume`, which stays the `kind:'input'` resume) clears it by hand — the sweep clears it on its own when the switch returns, and a run not on that gate answers `ℹ️ … Nothing to clear` with exit 0. `status --steps --json` step rows carry `taskClass`, `modelRequested`, `modelResolved`, `modelReason`, `effortApplied` and `modelFallback[]` (lua-api `workflow-projection.ts`); `status` prints a `🧠 By model` roll-up (`Model · [Class] · Calls · Credits|Actions · [Fallbacks]`) from the run's `usage.byModel`, or folded from the step receipts and then marked `(derived …)`. `lua workflows logs ` shows the model events — `step.model_resolved` as `model resolved →  ()` and `step.model_policy_warning` as `model policy warning:  …` — and ⏳ 3.37.0+ three more: `step.job_model_resolved` as `job model →  × ()`, with `— uncalibrated model, fallback rate` appended when the claim could quote no calibrated rate, and the **budget events** `run.budget_parked` (`paused on its run budget — 250 of 250 actions (step )`), `run.budget_raised` (`cap 250 → 1,000 by  — run resumed`) and `run.budget_exceeded` (`finished past the cap — 1,050 of 1,000 actions, seat (step )`). Until 3.37.0 `logs` printed **none** of the three budget events, so a run could park on its budget, be raised and finish over its cap without one line of `logs` mentioning money. The unit in those lines is whatever the gate itself chose — `actions` on a seat plan, `credits` on legacy, `steps` / `jobSeconds` unchanged — and the CLI never re-maps it. (`WORKFLOW_LOG_EVENT_PATTERN`; `watch` prints every frame.) `lua workflows recompose ` (alias `recompile`) asks the server to rewrite the stored task classes of a chat-composed definition into `class/` and publish a new version on the same parent — no agent turn, `unchanged` when nothing needs rewriting, `RECOMPOSE_NOT_APPLICABLE` (409) without an active version; `lua workflows deploy` still refuses a dynamic workflow, so `lua workflows versions ` is where you see which version is active.
+
+**Reading what a run cost** — `lua workflows status `. Every line below is a renderer of what the SERVER projected: a member the server did not send prints nothing (not a zero), so a run metered before the platform shipped these figures, or an unmetered run, shows exactly what 3.36.0 showed. Treat a missing line as "not reported", never as a defect.
+
+- `Budget:` — ` of  credits|actions spent ·  remaining ()`. ⏳ 3.37.0+ the unit word and the sentence after it are read from ONE place (the run's `usage.engine` stamp, else `budget.unit`), so they can no longer disagree about which plan priced the run; a priced run carrying neither states both rules rather than picking one. ⏳ `finished past the cap` is appended when the run crossed its cap and completed anyway — the crossing step was terminal for the run, so it finished instead of parking for a raise nobody could act on (the CLI prints it only when the server stamped it and never infers it from spent > cap). ⏳ A **seat** run that parked BEFORE its first priced call now reads the seat sentence too; on 3.36.0 it was told to raise credits its organization does not have.
+- ⏳ `Tokens:` — ` uncached in ·  cache read ·  cache write ·  out`, a run-level line (**not** gated on `--steps`, exactly as `Budget:` is not), each component only when the server projected it. These are **signals, not charges**: no figure here moved the credits or actions on the line above, and they must **never be added together** — on OpenAI-compatible providers a cache read is a SUBSET of the input figure, so a total would be a number no ledger anywhere holds. The CLI prints no total for exactly that reason.
+- ⏳ `--steps` gains three columns before `Error` — `Uncached` · `Cached` · `Output`. `Cached` folds reads and writes into one column for width only; the two stay separate on the wire and in `--json`. A step the roll-up did not name prints `—` in all three, never `0`: "nobody reported" is not "reported nothing". The columns appear only when at least one step row carries tokens.
+- ⏳ `⚙ : model  · × · chosen by ` under `--steps`, beside the `$` receipt line — a **Job-tier** row only: what that attempt ran on, the multiplier every one of its model replies was billed at, and the leg that chose it (`node.model`, `platform default`, `org default`, `run input`, `placeholder default`, `lease stamp`; an unknown spelling from a newer server prints verbatim). Each part appears only when the server sent it; a worker-tier row prints no line at all.
+- `🧠 By model` — `Model · [Class] · Calls · Credits|Actions · [Fallbacks]` (§2 above): the run's own roll-up, or a fold of the step receipts marked `(derived …)`.
+- `--json` carries all of it unfolded (`usage.tokens`, `steps[].tokens`, `steps[].job`, `budget.unit` / `reserved` / `exceeded`, `usage.engine`) — `budget.reserved` and `budget.unit` are **not** new in 3.37.0 and `reserved` has no human line at all; read it from `--json` when you need what a claim is holding.
 
 ---
 
@@ -181,11 +190,13 @@ CLI: `lua workflows policy autonomy get` — ONE request with `?effective=true`,
 ## 4. Job tier, workspaces, coding turns
 
 - Default (worker) tier: `timeoutSeconds` ≤ 600, no filesystem, no `exec`/`$`.
-- `tier: 'job'` (or any `workspace`): a Kubernetes Job per attempt with a real filesystem; code/tool steps ≤ 14 400 s, agent steps ≤ 86 400 s (as ≤ 4 h segments with checkpoints; > 14 400 s requires a `workspace`). `child_process`, code-from-strings and WebAssembly compile are refused. Flat metering: inline agent step = 1 credit, Job attempt = 4 credits at claim.
+- `tier: 'job'` (or any `workspace`): a Kubernetes Job per attempt with a real filesystem; code/tool steps ≤ 14 400 s, agent steps ≤ 86 400 s (as ≤ 4 h segments with checkpoints; > 14 400 s requires a `workspace`). `child_process`, code-from-strings and WebAssembly compile are refused.
+- **What a Job attempt costs — the attempt is not the unit, the model REPLY is.** Two regimes, and `lua workflows status ` names the one that priced the run in the sentence after its `Budget:` figures. **Flat** (a run that was not PRICED — `usage.metering` is anything but `priced`: the platform metering runs flat, or a run with no priced receipt yet): an inline agent step is 1 credit, a Job-tier attempt is 4, tokens are never metered — `status` prints that sentence verbatim for such a run. ⚠ It describes **this run**, not the organization's plan: a seat run that parked before its first priced call is not a flat-credits run, and ⏳ 3.37.0+ reads the seat sentence instead (its `budget.unit` says `actions`). **Priced**: the run was charged like chat, per model **reply**, on both tiers — a coding turn that thinks for an hour and answers two hundred times is charged two hundred times, not once. On a **legacy** plan a credit is one model reply on a Job step and one agent step off it, tokens never metered (production receipts show 50–86 replies in a SINGLE coding-turn attempt, not the 4 the flat rule implies). On a **seat** plan the unit is **actions**: the call's price band × the resolved model's multiplier, per model call, with a cached prompt token counting toward that band at the fraction of a fresh token the provider charges (a cache write at its own fraction; an uncalibrated model, or cached tokens a provider reported without a read/write split, fall back to full weight). Size a Job workflow's budget from the number of model replies it will make, never from the number of steps.
+- **Which model a Job step runs on is not the agent's model**: the step's own `model`, failing that the platform's default for Job steps, failing that the organization's default. Every reply of that attempt is billed at THAT model's multiplier, so pinning `model` on a Job step is a cost decision as much as a quality one — an unpinned step inherits whatever the platform default is that day. ⏳ 3.37.0+: a Job step that names no `model` makes `lua workflows deploy` print a `job-model-default` advisory — `  ⚠ ` under the success line, naming the step and, when the server can resolve them, the model and its multiplier (it says so instead of guessing when it cannot). **Advisory only: the deploy still succeeds**, exactly like the older `job-tier-not-enabled` advisory (the version uses the Job tier but the organization has it switched off, so `start` is refused `WORKFLOWS_DISABLED` until an administrator enables it). A step that names a `model` draws no advisory — the definition is its own audit trail.
 - Declare `workspace: { kind: 'git', repo: 'https://github.com/acme/app', ref?: 'main', credentialsRef: 'github' /* a connection id or a declared connections[].key */ }` on the workflow and `workspace: { mount: 'rw' | 'ro', isolation?: 'worktree' }` on steps. Worktree arms in `parallel` need `{ merge: { strategy: 'rebase' | 'merge', onConflict: 'fail' | 'agent' } }`. Committed work lands on branch `lua/wf-`.
 - `ctx.exec`/`ctx.$` allowlist: `git gh pnpm npm npx node yarn python3 pytest make` (today's image ships `git gh node npm npx`); argv only — no pipes, globs, `&&`, `cd`; `git push --force|--delete|--mirror|--all|--tags` refused, pre-push secret scan. `jobTools: ['gh']` mints a `GH_TOKEN` through a sidecar for `gh pr create|edit|comment` on the pinned repo.
 - Coding turns: a Job-tier `agentStep` with `harness: 'claude-code' | 'generic'`, `jobTools`, `maxTurns`, `toolScope.connectionIds` (MCP connections via a local proxy; approval-needing tools are refused inside the turn). `ro` mounts drop write/edit/git/shell tools (compile warns `ro-step-has-no-tools` if nothing is left).
-- Limits: `budget.maxCredits` over the org cap is a push blocker (`budget-exceeds-cap`); a budget-parked run resumes with `lua workflows raise-budget  --credits `; billing gates expire after 168 h. Private-network egress from code steps is `EGRESS_DENIED`.
+- Limits: `budget.maxCredits` over the org cap is a push blocker (`budget-exceeds-cap`); a budget-parked run resumes with `lua workflows raise-budget  --credits ` — ⚠ **the flag keeps its name on both plans, but `` is the new cap in the RUN's own unit**: credits on legacy, **actions** on a seat plan, and `lua workflows status ` (its `Budget:` line) says which. ⏳ 3.37.0+ the CLI says it too — the park hint reads `lua workflows raise-budget  --credits    ( is the new cap in actions)` and the confirmation `✅ budget raised to 200 actions`, where 3.36.0 always printed "credits" (`--max-steps` / `--max-job-seconds` / `--max-duration-seconds` count steps and seconds, are not money, and never take the unit). Billing gates expire after 168 h. Private-network egress from code steps is `EGRESS_DENIED`.
 
 ---
 
@@ -224,7 +235,7 @@ lua workflows status  [--steps] [--strict] [--json]        lua workflows
 lua workflows logs  [--step id] [--since 1h] [--follow]     lua workflows cancel  [--reason t]
 lua workflows resume  --step  --data '{…}'             lua workflows retry-step  --step  [--note t]
 lua workflows resolve-step  --step  --outcome skip|complete|fail [--output '{…}'] [--note t]
-lua workflows raise-budget  --credits n | --max-steps n | --max-job-seconds n | --max-duration-seconds n
+lua workflows raise-budget  --credits n | --max-steps n | --max-job-seconds n | --max-duration-seconds n   ⚠ --credits  is the new PRICED cap in the run's own unit (credits, or actions on a seat plan — `status` says which); the flag name is the same on both plans (§4)
 lua workflows approval-payload  --approval  [--path arr --limit ≤100 --cursor c]
 lua workflows approve  --approval  [--decision approve|deny] [--note t] [--edit @f --fingerprint f]
 lua workflows signal   --payload '{…}'|@file [--dedupe-key k]
@@ -254,8 +265,8 @@ Exit codes: `0` ok · `1` API refusal (4xx other than 404) · `2` usage · `3` n
 2. `lua compile` — fix build errors (§9); `WORKFLOW_UNPLACED_STEP` and `map-id-required` are warnings here but errors at push.
 3. `lua test workflow --name  --input @in.json --step-output ='{…}' --approve  --signal ='{…}' --fast-retries --ledger-out ledger.json` — exercise both sides of every predicate with different `--step-output`s; `--deny`; `--park `; `--now` for chains.
 4. `lua push workflow --name  [--set-version x.y.z] --force` (a version; not live). Check `lua workflows env-overlay  -v latest`. ⏳ 3.36.0+: add `--apply-effort` only when the steps' `effort` should actually reach the model (§2 — a plain push records it and applies nothing); a `taskClass` without a `model`, or a misspelled `class/…` / trait / effort, is refused here, not at compile.
-5. Deploy: `lua workflows deploy  -v latest` (gated by the plugin: `LUA_DEPLOY_CONFIRMED=1 …` via `/lua-deploy`; `lua deploy` itself has no workflow type). `lua workflows activate ` turns on schedules/triggers.
-6. Run on the platform: `lua workflows start  --input @in.json --follow --timeout 3600` (exit `8` when it parks — the approval id is in the output; `--wait-for-human` would instead keep streaming through the park until a human acts or the timeout fires with exit `7`); inspect `lua workflows status  --steps`; answer gates with `approve` / `signal` / `resume` / `retry-step` / `resolve-step` / `raise-budget` (⏳ and `clear-gate  --kind model_policy` for a step parked on an unresolvable model class; a consent gate is a person's from the desktop — `status` exits 6 on it under `--strict`); `lua workflows replay  --local` checks the run against your compiled artifact.
+5. Deploy: `lua workflows deploy  -v latest` (gated by the plugin: `LUA_DEPLOY_CONFIRMED=1 …` via `/lua-deploy`; `lua deploy` itself has no workflow type). Read the `  ⚠` advisory lines under the success line — they never fail the deploy: `job-tier-not-enabled` (an administrator must switch the Job tier on or `start` is refused) and ⏳ 3.37.0+ `job-model-default` (a Job step names no `model`, so it runs on the platform or org default and every reply is billed at that model's multiplier — §4). `lua workflows activate ` turns on schedules/triggers.
+6. Run on the platform: `lua workflows start  --input @in.json --follow --timeout 3600` (exit `8` when it parks — the approval id is in the output; `--wait-for-human` would instead keep streaming through the park until a human acts or the timeout fires with exit `7`); inspect `lua workflows status  --steps`; answer gates with `approve` / `signal` / `resume` / `retry-step` / `resolve-step` / `raise-budget` (⏳ and `clear-gate  --kind model_policy` for a step parked on an unresolvable model class; a consent gate is a person's from the desktop — `status` exits 6 on it under `--strict`); `lua workflows replay  --local` checks the run against your compiled artifact. For what it cost, read `status`'s `Budget:` sentence (which plan priced it and what the unit buys) and ⏳ 3.37.0+ its `Tokens:` line, the `Uncached`/`Cached`/`Output` columns and the `⚙` Job-model line (§2 "Reading what a run cost").
 7. Evidence: `lua workflows archive-runs --since 8d --out ./archive`.
 
 Chat-composed ("dynamic") workflows cannot be deployed from the CLI (`WORKFLOW_DYNAMIC`, 409) — recompose them in chat, or `lua workflows export ` to bring one into source.
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 506d32e..55678ee 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,3 @@
-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.3.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.3.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.3.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.3.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,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3NlcnZlci5tanMiLCAiLi4vc3JjL3Rvb2xzL2luZGV4Lm1qcyIsICIuLi9zcmMvcnVuLWx1YS5tanMiLCAiLi4vc3JjL3Rvb2xzL2xpc3QtYWdlbnRzLm1qcyIsICIuLi9zcmMvdG9vbHMvZ2V0LWFnZW50Lm1qcyIsICIuLi9zcmMvYXV0aC5tanMiLCAiLi4vc3JjL2FwaS1jbGllbnQubWpzIiwgIi4uL3NyYy9yZXNwb25zZS1zaGFwZXMubWpzIiwgIi4uL3NyYy90b29scy9saXN0LXByaW1pdGl2ZS12ZXJzaW9ucy5tanMiLCAiLi4vc3JjL3Rvb2xzL2dldC1kZXBsb3ltZW50LXN0YXR1cy5tanMiLCAiLi4vc3JjL3Rvb2xzL3RhaWwtbG9ncy5tanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8vIE1DUCBzdGRpbyBzZXJ2ZXIgYm9vdHN0cmFwLiBQZXIgdGVjaCBzcGVjIFx1MDBBNzguMS5cblxuaW1wb3J0IHsgU2VydmVyIH0gZnJvbSAnQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zZXJ2ZXIvaW5kZXguanMnO1xuaW1wb3J0IHsgU3RkaW9TZXJ2ZXJUcmFuc3BvcnQgfSBmcm9tICdAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NlcnZlci9zdGRpby5qcyc7XG5pbXBvcnQge1xuICBDYWxsVG9vbFJlcXVlc3RTY2hlbWEsXG4gIExpc3RUb29sc1JlcXVlc3RTY2hlbWEsXG59IGZyb20gJ0Btb2RlbGNvbnRleHRwcm90b2NvbC9zZGsvdHlwZXMuanMnO1xuaW1wb3J0ICogYXMgdG9vbHMgZnJvbSAnLi90b29scy9pbmRleC5tanMnO1xuXG5jb25zdCBUT09MX1JFR0lTVFJZID0gT2JqZWN0LnZhbHVlcyh0b29scyk7XG5cbmNvbnN0IHNlcnZlciA9IG5ldyBTZXJ2ZXIoXG4gIHsgbmFtZTogJ2x1YS1wbGF0Zm9ybScsIHZlcnNpb246ICcxLjMuMCcgfSxcbiAgeyBjYXBhYmlsaXRpZXM6IHsgdG9vbHM6IHt9IH0gfVxuKTtcblxuc2VydmVyLnNldFJlcXVlc3RIYW5kbGVyKExpc3RUb29sc1JlcXVlc3RTY2hlbWEsIGFzeW5jICgpID0+ICh7XG4gIHRvb2xzOiBUT09MX1JFR0lTVFJZLm1hcCgodCkgPT4gdC5zcGVjKSxcbn0pKTtcblxuc2VydmVyLnNldFJlcXVlc3RIYW5kbGVyKENhbGxUb29sUmVxdWVzdFNjaGVtYSwgYXN5bmMgKHJlcSkgPT4ge1xuICBjb25zdCB0b29sID0gVE9PTF9SRUdJU1RSWS5maW5kKCh0KSA9PiB0LnNwZWMubmFtZSA9PT0gcmVxLnBhcmFtcy5uYW1lKTtcbiAgaWYgKCF0b29sKSB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdG9vbDogJHtyZXEucGFyYW1zLm5hbWV9YCk7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHRvb2wuaGFuZGxlcihyZXEucGFyYW1zLmFyZ3VtZW50cyA/PyB7fSk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbeyB0eXBlOiAndGV4dCcsIHRleHQ6IGBFcnJvcjogJHtlcnIubWVzc2FnZX1gIH1dLFxuICAgICAgaXNFcnJvcjogdHJ1ZSxcbiAgICB9O1xuICB9XG59KTtcblxuLy8gXHUwMEE3MTkuNiBjcmFzaCByZXBvcnRpbmcgXHUyMDE0IG11c3QgbGFuZCBCRUZPUkUgcHJvY2VzcyBleGl0IHNvIHRoZSBldmVudCByZWFjaGVzXG4vLyB0ZWxlbWV0cnkuIFdpbmRvd3MgY2FuIGRyb3AgdGhlIGxhc3Qgc3RkZXJyIHdyaXRlIGlmIHByb2Nlc3MuZXhpdCBmaXJlc1xuLy8gc3luY2hyb25vdXNseSBhZnRlciBpdDsgc2FtZSBidWcgY2xhc3MgYXMgbGliL2hvb2stcnVudGltZS5tanMncyBleGl0KCkuXG4vLyBFeGl0IG9ubHkgaW5zaWRlIHRoZSB3cml0ZSBjYWxsYmFjayBzbyB0aGUgZmx1c2ggY29tcGxldGVzLlxuZnVuY3Rpb24gcmVwb3J0Q3Jhc2hBbmRFeGl0KHBheWxvYWQpIHtcbiAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkgKyAnXFxuJywgKCkgPT4gcHJvY2Vzcy5leGl0KDEpKTtcbn1cblxucHJvY2Vzcy5vbigndW5jYXVnaHRFeGNlcHRpb24nLCAoZXJyKSA9PiB7XG4gIHJlcG9ydENyYXNoQW5kRXhpdCh7XG4gICAgZXZlbnQ6ICdtY3Bfc2VydmVyX2NyYXNoJyxcbiAgICBraW5kOiAndW5jYXVnaHRFeGNlcHRpb24nLFxuICAgIG1lc3NhZ2U6IGVycj8ubWVzc2FnZSxcbiAgICBzdGFjazogZXJyPy5zdGFjayxcbiAgICBwbHVnaW5fdmVyc2lvbjogJzEuMy4wJyxcbiAgICBsdWFfY2xpX3ZlcnNpb246IHByb2Nlc3MuZW52LkxVQV9DTElfVkVSU0lPTiA/PyBudWxsLFxuICAgIHBsYXRmb3JtOiBwcm9jZXNzLnBsYXRmb3JtLFxuICAgIHRzOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gIH0pO1xufSk7XG5cbnByb2Nlc3Mub24oJ3VuaGFuZGxlZFJlamVjdGlvbicsIChyZWFzb24pID0+IHtcbiAgcmVwb3J0Q3Jhc2hBbmRFeGl0KHtcbiAgICBldmVudDogJ21jcF9zZXJ2ZXJfY3Jhc2gnLFxuICAgIGtpbmQ6ICd1bmhhbmRsZWRSZWplY3Rpb24nLFxuICAgIHJlYXNvbjogU3RyaW5nKHJlYXNvbiksXG4gICAgc3RhY2s6IC8qKiBAdHlwZSB7YW55fSAqLyAocmVhc29uKT8uc3RhY2ssXG4gICAgcGx1Z2luX3ZlcnNpb246ICcxLjMuMCcsXG4gICAgbHVhX2NsaV92ZXJzaW9uOiBwcm9jZXNzLmVudi5MVUFfQ0xJX1ZFUlNJT04gPz8gbnVsbCxcbiAgICBwbGF0Zm9ybTogcHJvY2Vzcy5wbGF0Zm9ybSxcbiAgICB0czogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICB9KTtcbn0pO1xuXG5hd2FpdCBzZXJ2ZXIuY29ubmVjdChuZXcgU3RkaW9TZXJ2ZXJUcmFuc3BvcnQoKSk7XG4iLCAiZXhwb3J0IHsgbGlzdEFnZW50cyB9IGZyb20gJy4vbGlzdC1hZ2VudHMubWpzJztcbmV4cG9ydCB7IGdldEFnZW50IH0gZnJvbSAnLi9nZXQtYWdlbnQubWpzJztcbmV4cG9ydCB7IGxpc3RQcmltaXRpdmVWZXJzaW9ucyB9IGZyb20gJy4vbGlzdC1wcmltaXRpdmUtdmVyc2lvbnMubWpzJztcbmV4cG9ydCB7IGdldERlcGxveW1lbnRTdGF0dXMgfSBmcm9tICcuL2dldC1kZXBsb3ltZW50LXN0YXR1cy5tanMnO1xuZXhwb3J0IHsgdGFpbExvZ3MgfSBmcm9tICcuL3RhaWwtbG9ncy5tanMnO1xuLy8gY2hlY2tfZHJpZnQgcmVtb3ZlZCBpbiB2MS4yNSBcdTIwMTQgdXNlIEJhc2gobHVhIHN5bmMgLS1jaGVjaykgZGlyZWN0bHkuIFRoZVxuLy8gTUNQIHNlcnZlciBpcyBsb2NhbCBhbmQgc28gaXMgdGhlIENMSTsgcmVpbXBsZW1lbnRpbmcgZHJpZnQgZGV0ZWN0aW9uXG4vLyBzZXJ2ZXItc2lkZSBvciBpbiB0aGUgTUNQIHdvdWxkIGR1cGxpY2F0ZSBsb2dpYyB0aGF0IGx1YS1jbGkgYWxyZWFkeSBvd25zLlxuIiwgIi8vIFNoYXJlZCBzdWJwcm9jZXNzIGhlbHBlciBmb3IgdG9vbHMgdGhhdCBzaGVsbCBvdXQgdG8gdGhlIGx1YS1jbGkgYmluYXJ5LlxuLy9cbi8vIFdoeSBzaGVsbCBvdXQgYXQgYWxsOiB0aGVyZSBpcyBubyBcImxpc3QgZXZlcnkgYWdlbnQgdGhpcyBjcmVkZW50aWFsIGNhblxuLy8gcmVhY2hcIiBSRVNUIHJvdXRlIFx1MjAxNCBgbHVhIGFnZW50cyAtLWpzb25gIGFscmVhZHkgZG9lcyB0aGUgY3JlZGVudGlhbC10by1cbi8vIGF1dGhvcml6YXRpb24tcHJvamVjdGlvbiByZXNvbHV0aW9uIChQUk8tMTcxMikgZm9yIGV2ZXJ5IGNyZWRlbnRpYWwgY2xhc3Ncbi8vIChBUEkga2V5LCB0eXBlZCBzY29wZWQga2V5LCByZW5ld2FibGUgc2Vzc2lvbikuIFJlaW1wbGVtZW50aW5nIHRoYXQgaW4gdGhlXG4vLyBNQ1Agd291bGQgZHVwbGljYXRlIGxvZ2ljIGx1YS1jbGkgb3ducy5cblxuaW1wb3J0IHsgc3Bhd24gfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnO1xuXG4vLyBgbHVhIGFnZW50c2Agd2Fsa3MgZXZlcnkgb3JnYW5pc2F0aW9uIHRoZSBjcmVkZW50aWFsIGNhbiBzZWUgYW5kLCBmb3IgYVxuLy8gc2Vzc2lvbiBsb2dpbiwgcmVmcmVzaGVzIHRoZSBzZXNzaW9uIGZpcnN0LiBNZWFzdXJlZCAyMDI2LTA5LTEyIG9uIGFcbi8vIDE0NC1vcmcgYWNjb3VudDogMThcdTIwMTMyNSBzLiBUaGUgYnVkZ2V0IG11c3QgY292ZXIgdGhhdC5cbmNvbnN0IERFRkFVTFRfVElNRU9VVF9NUyA9IDYwXzAwMDtcblxuLyoqXG4gKiBSdW4gYGx1YSA8YXJncz5gIGFuZCByZXNvbHZlIHdpdGggaXRzIHN0ZG91dC5cbiAqXG4gKiBPbiBXaW5kb3dzIHRoZSBucG0gYmluIGlzIGEgYGx1YS5jbWRgIHNoaW0sIHdoaWNoIE5vZGUgKFx1MjI2NTE4LjIwIC8gXHUyMjY1MjAuMTIpXG4gKiByZWZ1c2VzIHRvIHNwYXduIHdpdGhvdXQgYSBzaGVsbDsgdGhlIGFyZ3MgYXJlIGZpeGVkIGxpdGVyYWxzIChubyB1c2VyXG4gKiBpbnB1dCksIHNvIGBzaGVsbDogdHJ1ZWAgdGhlcmUgaXMgc2FmZS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBhcmdzXG4gKiBAcGFyYW0ge3tzcGF3bkZuPzogdHlwZW9mIHNwYXduLCB0aW1lb3V0TXM/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/OiBvYmplY3QsIHF1ZXJ5PzogUmVjb3JkPHN0cmluZyxzdHJpbmd8bnVtYmVyPiwgZmV0Y2hGbj86IHR5cGVvZiBmZXRjaCwgYmFzZVVybD86IHN0cmluZywgdGltZW91dE1zPzogbnVtYmVyfX0gW29wdHNdXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhcGlSZXF1ZXN0KHBhdGgsIHtcbiAgbWV0aG9kID0gJ0dFVCcsXG4gIGJvZHksXG4gIHF1ZXJ5LFxuICBmZXRjaEZuID0gZ2xvYmFsVGhpcy5mZXRjaCxcbiAgYmFzZVVybCA9IHByb2Nlc3MuZW52LkxVQV9BUElfVVJMIHx8IERFRkFVTFRfQkFTRV9VUkwsXG4gIHRpbWVvdXRNcyA9IERFRkFVTFRfVElNRU9VVF9NUyxcbn0gPSB7fSkge1xuICBjb25zdCBhcGlLZXkgPSBhd2FpdCByZXNvbHZlQXBpS2V5KCk7XG4gIC8vIEpvaW4gYnkgc3RyaW5nIGNvbmNhdGVuYXRpb24sIE5PVCBgbmV3IFVSTChwYXRoLCBiYXNlVXJsKWA6IHRoZSBXSEFUV0dcbiAgLy8gcmVzb2x2ZXIgdHJlYXRzIGEgbGVhZGluZy1zbGFzaCBwYXRoIGFzIGhvc3QtYWJzb2x1dGUgYW5kIHdvdWxkIGRyb3AgYW55XG4gIC8vIHBhdGggcHJlZml4IG9uIExVQV9BUElfVVJMIChodHRwczovL2hvc3QvYXBpICsgL2RldmVsb3Blci94IFx1MjE5MlxuICAvLyBodHRwczovL2hvc3QvZGV2ZWxvcGVyL3gpLiBgcGF0aGAgYWx3YXlzIHN0YXJ0cyB3aXRoICcvJywgc28gc3RyaXAgb25lXG4gIC8vIHRyYWlsaW5nIHNsYXNoIGZyb20gdGhlIGJhc2UgYW5kIGNvbmNhdGVuYXRlLlxuICBjb25zdCB1cmwgPSBuZXcgVVJMKGJhc2VVcmwucmVwbGFjZSgvXFwvJC8sICcnKSArIHBhdGgpO1xuICBpZiAocXVlcnkpIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKHF1ZXJ5KSkgdXJsLnNlYXJjaFBhcmFtcy5zZXQoaywgU3RyaW5nKHYpKTtcblxuICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4gY29udHJvbGxlci5hYm9ydCgpLCB0aW1lb3V0TXMpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgZmV0Y2hGbih1cmwudG9TdHJpbmcoKSwge1xuICAgICAgbWV0aG9kLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnQXV0aG9yaXphdGlvbic6IGBCZWFyZXIgJHthcGlLZXl9YCxcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgJ1gtTHVhLUNsaWVudCc6ICdjbGF1ZGUtcGx1Z2luLzEuMy4wJyxcbiAgICAgIH0sXG4gICAgICBib2R5OiBib2R5ID8gSlNPTi5zdHJpbmdpZnkoYm9keSkgOiB1bmRlZmluZWQsXG4gICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgIH0pO1xuXG4gICAgaWYgKHJlcy5zdGF0dXMgPT09IDQwMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnTUNQX0FVVEhfU1RBTEU6IGx1YS1hcGkgcmV0dXJuZWQgNDAxLiBUaGUgY3JlZGVudGlhbCBpcyBtaXNzaW5nLCBleHBpcmVkLCBvciB0aGUgc2Vzc2lvbiB3YXMgc2lnbmVkIG91dCAnICtcbiAgICAgICAgJyhzaWduaW5nIG91dCBvZiB0aGUgTHVhIGRhc2hib2FyZCBvciBhcHBzIGFsc28gZW5kcyBDTEkgc2Vzc2lvbnMpLiBSdW4gYGx1YSBhdXRoIGNvbmZpZ3VyZWAgaW4gYSB0ZXJtaW5hbCwgJyArXG4gICAgICAgICdvciByZS1ydW4gL2x1YS1kb2N0b3IuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHJlcy5zdGF0dXMgPT09IDQwMykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgTUNQX0ZPUkJJRERFTjogbHVhLWFwaSByZXR1cm5lZCA0MDMgZm9yICR7cGF0aH0uIFRoZSBjcmVkZW50aWFsIGNhbm5vdCBhY2Nlc3MgdGhpcyBhZ2VudCBvciBvcmcsIG9yIGl0IGxhY2tzIGAgK1xuICAgICAgICBgdGhlIHJvdXRlIHNjb3BlICgke1JPVVRFX1NDT1BFX1NVTU1BUll9IFx1MjAxNCB0eXBlZCBrZXlzIGFyZSBzY29wZWQgdG8gdGhlIGFnZW50cyBhbmQgcm9sZSBjaG9zZW4gYXQgYCArXG4gICAgICAgICdgbHVhIGF1dGggY29uZmlndXJlYCkuIFJlLXJ1biAvbHVhLWRvY3RvciBvciBjaGVjayB0aGUgTFVBX0FQSV9LRVkgZW52IHZhci4nXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIXJlcy5vaykge1xuICAgICAgLy8gVHJ5IHRvIHBhcnNlIGx1YS1hcGkncyBzdHJ1Y3R1cmVkIGVycm9yIGVudmVsb3BlOlxuICAgICAgLy8gICB7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogeyBtZXNzYWdlLCBzdGF0dXNDb2RlLCBjb2RlPywgLi4uIH0gfVxuICAgICAgLy8gRmFsbHMgYmFjayB0byByYXcgdGV4dCBvbiBwYXJzZSBmYWlsdXJlIChlLmcuIHByb3h5IDUwMiB3aXRoIEhUTUwgYm9keSkuXG4gICAgICBjb25zdCByYXcgPSBhd2FpdCByZXMudGV4dCgpO1xuICAgICAgbGV0IGZyaWVuZGx5TXNnID0gcmF3O1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShyYXcpO1xuICAgICAgICBmcmllbmRseU1zZyA9IHBhcnNlZD8uZXJyb3I/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=
+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.4.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.4.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.4.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.4.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,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3NlcnZlci5tanMiLCAiLi4vc3JjL3Rvb2xzL2luZGV4Lm1qcyIsICIuLi9zcmMvcnVuLWx1YS5tanMiLCAiLi4vc3JjL3Rvb2xzL2xpc3QtYWdlbnRzLm1qcyIsICIuLi9zcmMvdG9vbHMvZ2V0LWFnZW50Lm1qcyIsICIuLi9zcmMvYXV0aC5tanMiLCAiLi4vc3JjL2FwaS1jbGllbnQubWpzIiwgIi4uL3NyYy9yZXNwb25zZS1zaGFwZXMubWpzIiwgIi4uL3NyYy90b29scy9saXN0LXByaW1pdGl2ZS12ZXJzaW9ucy5tanMiLCAiLi4vc3JjL3Rvb2xzL2dldC1kZXBsb3ltZW50LXN0YXR1cy5tanMiLCAiLi4vc3JjL3Rvb2xzL3RhaWwtbG9ncy5tanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8vIE1DUCBzdGRpbyBzZXJ2ZXIgYm9vdHN0cmFwLiBQZXIgdGVjaCBzcGVjIFx1MDBBNzguMS5cblxuaW1wb3J0IHsgU2VydmVyIH0gZnJvbSAnQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zZXJ2ZXIvaW5kZXguanMnO1xuaW1wb3J0IHsgU3RkaW9TZXJ2ZXJUcmFuc3BvcnQgfSBmcm9tICdAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NlcnZlci9zdGRpby5qcyc7XG5pbXBvcnQge1xuICBDYWxsVG9vbFJlcXVlc3RTY2hlbWEsXG4gIExpc3RUb29sc1JlcXVlc3RTY2hlbWEsXG59IGZyb20gJ0Btb2RlbGNvbnRleHRwcm90b2NvbC9zZGsvdHlwZXMuanMnO1xuaW1wb3J0ICogYXMgdG9vbHMgZnJvbSAnLi90b29scy9pbmRleC5tanMnO1xuXG5jb25zdCBUT09MX1JFR0lTVFJZID0gT2JqZWN0LnZhbHVlcyh0b29scyk7XG5cbmNvbnN0IHNlcnZlciA9IG5ldyBTZXJ2ZXIoXG4gIHsgbmFtZTogJ2x1YS1wbGF0Zm9ybScsIHZlcnNpb246ICcxLjQuMCcgfSxcbiAgeyBjYXBhYmlsaXRpZXM6IHsgdG9vbHM6IHt9IH0gfVxuKTtcblxuc2VydmVyLnNldFJlcXVlc3RIYW5kbGVyKExpc3RUb29sc1JlcXVlc3RTY2hlbWEsIGFzeW5jICgpID0+ICh7XG4gIHRvb2xzOiBUT09MX1JFR0lTVFJZLm1hcCgodCkgPT4gdC5zcGVjKSxcbn0pKTtcblxuc2VydmVyLnNldFJlcXVlc3RIYW5kbGVyKENhbGxUb29sUmVxdWVzdFNjaGVtYSwgYXN5bmMgKHJlcSkgPT4ge1xuICBjb25zdCB0b29sID0gVE9PTF9SRUdJU1RSWS5maW5kKCh0KSA9PiB0LnNwZWMubmFtZSA9PT0gcmVxLnBhcmFtcy5uYW1lKTtcbiAgaWYgKCF0b29sKSB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdG9vbDogJHtyZXEucGFyYW1zLm5hbWV9YCk7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHRvb2wuaGFuZGxlcihyZXEucGFyYW1zLmFyZ3VtZW50cyA/PyB7fSk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbeyB0eXBlOiAndGV4dCcsIHRleHQ6IGBFcnJvcjogJHtlcnIubWVzc2FnZX1gIH1dLFxuICAgICAgaXNFcnJvcjogdHJ1ZSxcbiAgICB9O1xuICB9XG59KTtcblxuLy8gXHUwMEE3MTkuNiBjcmFzaCByZXBvcnRpbmcgXHUyMDE0IG11c3QgbGFuZCBCRUZPUkUgcHJvY2VzcyBleGl0IHNvIHRoZSBldmVudCByZWFjaGVzXG4vLyB0ZWxlbWV0cnkuIFdpbmRvd3MgY2FuIGRyb3AgdGhlIGxhc3Qgc3RkZXJyIHdyaXRlIGlmIHByb2Nlc3MuZXhpdCBmaXJlc1xuLy8gc3luY2hyb25vdXNseSBhZnRlciBpdDsgc2FtZSBidWcgY2xhc3MgYXMgbGliL2hvb2stcnVudGltZS5tanMncyBleGl0KCkuXG4vLyBFeGl0IG9ubHkgaW5zaWRlIHRoZSB3cml0ZSBjYWxsYmFjayBzbyB0aGUgZmx1c2ggY29tcGxldGVzLlxuZnVuY3Rpb24gcmVwb3J0Q3Jhc2hBbmRFeGl0KHBheWxvYWQpIHtcbiAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkgKyAnXFxuJywgKCkgPT4gcHJvY2Vzcy5leGl0KDEpKTtcbn1cblxucHJvY2Vzcy5vbigndW5jYXVnaHRFeGNlcHRpb24nLCAoZXJyKSA9PiB7XG4gIHJlcG9ydENyYXNoQW5kRXhpdCh7XG4gICAgZXZlbnQ6ICdtY3Bfc2VydmVyX2NyYXNoJyxcbiAgICBraW5kOiAndW5jYXVnaHRFeGNlcHRpb24nLFxuICAgIG1lc3NhZ2U6IGVycj8ubWVzc2FnZSxcbiAgICBzdGFjazogZXJyPy5zdGFjayxcbiAgICBwbHVnaW5fdmVyc2lvbjogJzEuNC4wJyxcbiAgICBsdWFfY2xpX3ZlcnNpb246IHByb2Nlc3MuZW52LkxVQV9DTElfVkVSU0lPTiA/PyBudWxsLFxuICAgIHBsYXRmb3JtOiBwcm9jZXNzLnBsYXRmb3JtLFxuICAgIHRzOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gIH0pO1xufSk7XG5cbnByb2Nlc3Mub24oJ3VuaGFuZGxlZFJlamVjdGlvbicsIChyZWFzb24pID0+IHtcbiAgcmVwb3J0Q3Jhc2hBbmRFeGl0KHtcbiAgICBldmVudDogJ21jcF9zZXJ2ZXJfY3Jhc2gnLFxuICAgIGtpbmQ6ICd1bmhhbmRsZWRSZWplY3Rpb24nLFxuICAgIHJlYXNvbjogU3RyaW5nKHJlYXNvbiksXG4gICAgc3RhY2s6IC8qKiBAdHlwZSB7YW55fSAqLyAocmVhc29uKT8uc3RhY2ssXG4gICAgcGx1Z2luX3ZlcnNpb246ICcxLjQuMCcsXG4gICAgbHVhX2NsaV92ZXJzaW9uOiBwcm9jZXNzLmVudi5MVUFfQ0xJX1ZFUlNJT04gPz8gbnVsbCxcbiAgICBwbGF0Zm9ybTogcHJvY2Vzcy5wbGF0Zm9ybSxcbiAgICB0czogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICB9KTtcbn0pO1xuXG5hd2FpdCBzZXJ2ZXIuY29ubmVjdChuZXcgU3RkaW9TZXJ2ZXJUcmFuc3BvcnQoKSk7XG4iLCAiZXhwb3J0IHsgbGlzdEFnZW50cyB9IGZyb20gJy4vbGlzdC1hZ2VudHMubWpzJztcbmV4cG9ydCB7IGdldEFnZW50IH0gZnJvbSAnLi9nZXQtYWdlbnQubWpzJztcbmV4cG9ydCB7IGxpc3RQcmltaXRpdmVWZXJzaW9ucyB9IGZyb20gJy4vbGlzdC1wcmltaXRpdmUtdmVyc2lvbnMubWpzJztcbmV4cG9ydCB7IGdldERlcGxveW1lbnRTdGF0dXMgfSBmcm9tICcuL2dldC1kZXBsb3ltZW50LXN0YXR1cy5tanMnO1xuZXhwb3J0IHsgdGFpbExvZ3MgfSBmcm9tICcuL3RhaWwtbG9ncy5tanMnO1xuLy8gY2hlY2tfZHJpZnQgcmVtb3ZlZCBpbiB2MS4yNSBcdTIwMTQgdXNlIEJhc2gobHVhIHN5bmMgLS1jaGVjaykgZGlyZWN0bHkuIFRoZVxuLy8gTUNQIHNlcnZlciBpcyBsb2NhbCBhbmQgc28gaXMgdGhlIENMSTsgcmVpbXBsZW1lbnRpbmcgZHJpZnQgZGV0ZWN0aW9uXG4vLyBzZXJ2ZXItc2lkZSBvciBpbiB0aGUgTUNQIHdvdWxkIGR1cGxpY2F0ZSBsb2dpYyB0aGF0IGx1YS1jbGkgYWxyZWFkeSBvd25zLlxuIiwgIi8vIFNoYXJlZCBzdWJwcm9jZXNzIGhlbHBlciBmb3IgdG9vbHMgdGhhdCBzaGVsbCBvdXQgdG8gdGhlIGx1YS1jbGkgYmluYXJ5LlxuLy9cbi8vIFdoeSBzaGVsbCBvdXQgYXQgYWxsOiB0aGVyZSBpcyBubyBcImxpc3QgZXZlcnkgYWdlbnQgdGhpcyBjcmVkZW50aWFsIGNhblxuLy8gcmVhY2hcIiBSRVNUIHJvdXRlIFx1MjAxNCBgbHVhIGFnZW50cyAtLWpzb25gIGFscmVhZHkgZG9lcyB0aGUgY3JlZGVudGlhbC10by1cbi8vIGF1dGhvcml6YXRpb24tcHJvamVjdGlvbiByZXNvbHV0aW9uIChQUk8tMTcxMikgZm9yIGV2ZXJ5IGNyZWRlbnRpYWwgY2xhc3Ncbi8vIChBUEkga2V5LCB0eXBlZCBzY29wZWQga2V5LCByZW5ld2FibGUgc2Vzc2lvbikuIFJlaW1wbGVtZW50aW5nIHRoYXQgaW4gdGhlXG4vLyBNQ1Agd291bGQgZHVwbGljYXRlIGxvZ2ljIGx1YS1jbGkgb3ducy5cblxuaW1wb3J0IHsgc3Bhd24gfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnO1xuXG4vLyBgbHVhIGFnZW50c2Agd2Fsa3MgZXZlcnkgb3JnYW5pc2F0aW9uIHRoZSBjcmVkZW50aWFsIGNhbiBzZWUgYW5kLCBmb3IgYVxuLy8gc2Vzc2lvbiBsb2dpbiwgcmVmcmVzaGVzIHRoZSBzZXNzaW9uIGZpcnN0LiBNZWFzdXJlZCAyMDI2LTA5LTEyIG9uIGFcbi8vIDE0NC1vcmcgYWNjb3VudDogMThcdTIwMTMyNSBzLiBUaGUgYnVkZ2V0IG11c3QgY292ZXIgdGhhdC5cbmNvbnN0IERFRkFVTFRfVElNRU9VVF9NUyA9IDYwXzAwMDtcblxuLyoqXG4gKiBSdW4gYGx1YSA8YXJncz5gIGFuZCByZXNvbHZlIHdpdGggaXRzIHN0ZG91dC5cbiAqXG4gKiBPbiBXaW5kb3dzIHRoZSBucG0gYmluIGlzIGEgYGx1YS5jbWRgIHNoaW0sIHdoaWNoIE5vZGUgKFx1MjI2NTE4LjIwIC8gXHUyMjY1MjAuMTIpXG4gKiByZWZ1c2VzIHRvIHNwYXduIHdpdGhvdXQgYSBzaGVsbDsgdGhlIGFyZ3MgYXJlIGZpeGVkIGxpdGVyYWxzIChubyB1c2VyXG4gKiBpbnB1dCksIHNvIGBzaGVsbDogdHJ1ZWAgdGhlcmUgaXMgc2FmZS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBhcmdzXG4gKiBAcGFyYW0ge3tzcGF3bkZuPzogdHlwZW9mIHNwYXduLCB0aW1lb3V0TXM/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/OiBvYmplY3QsIHF1ZXJ5PzogUmVjb3JkPHN0cmluZyxzdHJpbmd8bnVtYmVyPiwgZmV0Y2hGbj86IHR5cGVvZiBmZXRjaCwgYmFzZVVybD86IHN0cmluZywgdGltZW91dE1zPzogbnVtYmVyfX0gW29wdHNdXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhcGlSZXF1ZXN0KHBhdGgsIHtcbiAgbWV0aG9kID0gJ0dFVCcsXG4gIGJvZHksXG4gIHF1ZXJ5LFxuICBmZXRjaEZuID0gZ2xvYmFsVGhpcy5mZXRjaCxcbiAgYmFzZVVybCA9IHByb2Nlc3MuZW52LkxVQV9BUElfVVJMIHx8IERFRkFVTFRfQkFTRV9VUkwsXG4gIHRpbWVvdXRNcyA9IERFRkFVTFRfVElNRU9VVF9NUyxcbn0gPSB7fSkge1xuICBjb25zdCBhcGlLZXkgPSBhd2FpdCByZXNvbHZlQXBpS2V5KCk7XG4gIC8vIEpvaW4gYnkgc3RyaW5nIGNvbmNhdGVuYXRpb24sIE5PVCBgbmV3IFVSTChwYXRoLCBiYXNlVXJsKWA6IHRoZSBXSEFUV0dcbiAgLy8gcmVzb2x2ZXIgdHJlYXRzIGEgbGVhZGluZy1zbGFzaCBwYXRoIGFzIGhvc3QtYWJzb2x1dGUgYW5kIHdvdWxkIGRyb3AgYW55XG4gIC8vIHBhdGggcHJlZml4IG9uIExVQV9BUElfVVJMIChodHRwczovL2hvc3QvYXBpICsgL2RldmVsb3Blci94IFx1MjE5MlxuICAvLyBodHRwczovL2hvc3QvZGV2ZWxvcGVyL3gpLiBgcGF0aGAgYWx3YXlzIHN0YXJ0cyB3aXRoICcvJywgc28gc3RyaXAgb25lXG4gIC8vIHRyYWlsaW5nIHNsYXNoIGZyb20gdGhlIGJhc2UgYW5kIGNvbmNhdGVuYXRlLlxuICBjb25zdCB1cmwgPSBuZXcgVVJMKGJhc2VVcmwucmVwbGFjZSgvXFwvJC8sICcnKSArIHBhdGgpO1xuICBpZiAocXVlcnkpIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKHF1ZXJ5KSkgdXJsLnNlYXJjaFBhcmFtcy5zZXQoaywgU3RyaW5nKHYpKTtcblxuICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4gY29udHJvbGxlci5hYm9ydCgpLCB0aW1lb3V0TXMpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgZmV0Y2hGbih1cmwudG9TdHJpbmcoKSwge1xuICAgICAgbWV0aG9kLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnQXV0aG9yaXphdGlvbic6IGBCZWFyZXIgJHthcGlLZXl9YCxcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgJ1gtTHVhLUNsaWVudCc6ICdjbGF1ZGUtcGx1Z2luLzEuNC4wJyxcbiAgICAgIH0sXG4gICAgICBib2R5OiBib2R5ID8gSlNPTi5zdHJpbmdpZnkoYm9keSkgOiB1bmRlZmluZWQsXG4gICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgIH0pO1xuXG4gICAgaWYgKHJlcy5zdGF0dXMgPT09IDQwMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnTUNQX0FVVEhfU1RBTEU6IGx1YS1hcGkgcmV0dXJuZWQgNDAxLiBUaGUgY3JlZGVudGlhbCBpcyBtaXNzaW5nLCBleHBpcmVkLCBvciB0aGUgc2Vzc2lvbiB3YXMgc2lnbmVkIG91dCAnICtcbiAgICAgICAgJyhzaWduaW5nIG91dCBvZiB0aGUgTHVhIGRhc2hib2FyZCBvciBhcHBzIGFsc28gZW5kcyBDTEkgc2Vzc2lvbnMpLiBSdW4gYGx1YSBhdXRoIGNvbmZpZ3VyZWAgaW4gYSB0ZXJtaW5hbCwgJyArXG4gICAgICAgICdvciByZS1ydW4gL2x1YS1kb2N0b3IuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHJlcy5zdGF0dXMgPT09IDQwMykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgTUNQX0ZPUkJJRERFTjogbHVhLWFwaSByZXR1cm5lZCA0MDMgZm9yICR7cGF0aH0uIFRoZSBjcmVkZW50aWFsIGNhbm5vdCBhY2Nlc3MgdGhpcyBhZ2VudCBvciBvcmcsIG9yIGl0IGxhY2tzIGAgK1xuICAgICAgICBgdGhlIHJvdXRlIHNjb3BlICgke1JPVVRFX1NDT1BFX1NVTU1BUll9IFx1MjAxNCB0eXBlZCBrZXlzIGFyZSBzY29wZWQgdG8gdGhlIGFnZW50cyBhbmQgcm9sZSBjaG9zZW4gYXQgYCArXG4gICAgICAgICdgbHVhIGF1dGggY29uZmlndXJlYCkuIFJlLXJ1biAvbHVhLWRvY3RvciBvciBjaGVjayB0aGUgTFVBX0FQSV9LRVkgZW52IHZhci4nXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIXJlcy5vaykge1xuICAgICAgLy8gVHJ5IHRvIHBhcnNlIGx1YS1hcGkncyBzdHJ1Y3R1cmVkIGVycm9yIGVudmVsb3BlOlxuICAgICAgLy8gICB7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogeyBtZXNzYWdlLCBzdGF0dXNDb2RlLCBjb2RlPywgLi4uIH0gfVxuICAgICAgLy8gRmFsbHMgYmFjayB0byByYXcgdGV4dCBvbiBwYXJzZSBmYWlsdXJlIChlLmcuIHByb3h5IDUwMiB3aXRoIEhUTUwgYm9keSkuXG4gICAgICBjb25zdCByYXcgPSBhd2FpdCByZXMudGV4dCgpO1xuICAgICAgbGV0IGZyaWVuZGx5TXNnID0gcmF3O1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShyYXcpO1xuICAgICAgICBmcmllbmRseU1zZyA9IHBhcnNlZD8uZXJyb3I/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=
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 ca2bb2c..afd23da 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.3.0",
+  "version": "1.4.0",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "@lua/claude-plugin-mcp",
-      "version": "1.3.0",
+      "version": "1.4.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 e70d60c..d8d07f0 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.3.0",
+  "version": "1.4.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/src/api-client.mjs b/plugins/lua-agent-builder/mcp/lua-platform/src/api-client.mjs
index 4e8f5fb..b4b8317 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.3.0',
+        'X-Lua-Client': 'claude-plugin/1.4.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 c09f760..95e55a2 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.3.0' },
+  { name: 'lua-platform', version: '1.4.0' },
   { capabilities: { tools: {} } }
 );
 
@@ -46,7 +46,7 @@ process.on('uncaughtException', (err) => {
     kind: 'uncaughtException',
     message: err?.message,
     stack: err?.stack,
-    plugin_version: '1.3.0',
+    plugin_version: '1.4.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.3.0',
+    plugin_version: '1.4.0',
     lua_cli_version: process.env.LUA_CLI_VERSION ?? null,
     platform: process.platform,
     ts: new Date().toISOString(),
diff --git a/plugins/lua-agent-builder/package-lock.json b/plugins/lua-agent-builder/package-lock.json
index c3cc746..d613155 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.3.0",
+  "version": "1.4.0",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "claude-code-lua-plugin",
-      "version": "1.3.0",
+      "version": "1.4.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 dd23028..23350ef 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.3.0",
+  "version": "1.4.0",
   "description": "Plugin assets for the lua-agent-builder Claude Code plugin",
   "private": true,
   "type": "module",