diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index a174c15..aea8ec4 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.2.2", + "version": "1.3.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 402a413..0547038 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 3.33.0 source, 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 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 | ## Quick walkthrough diff --git a/docs/USER_GUIDE.md b/docs/USER_GUIDE.md index 6dcde89..5a8d6ae 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.33.0**, 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.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. 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 3.33.0 source. +- **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). - **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.33.0** | the command shapes the plugin emits | `npm install -g lua-cli` (or `/lua-update`) | +| **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`) | | **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. +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. + --- ## Installation @@ -117,8 +119,10 @@ Workflows are durable multi-step graphs with approvals, signals, fan-out, retrie 3. `/lua-push workflow` — a server version (not live). Missing `env.template()` keys are refused at push. 4. `/lua-deploy` → target `workflow` — `LUA_DEPLOY_CONFIRMED=1 lua workflows deploy reply-approval -v latest`, plus `activate` if it has a schedule. 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. -Chat-composed workflows can't be deployed from the CLI (`WORKFLOW_DYNAMIC`); `/lua-workflow export ` brings one into source. +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. --- @@ -137,7 +141,7 @@ Chat-composed workflows can't be deployed from the CLI (`WORKFLOW_DYNAMIC`); `/l | `/lua-architect ` | subagent | plan + next-step menu | | `/lua-new [name]` | subagent → `lua compile`, `lua test` | 13 primitive types (incl. `workflow-script`) | | `/lua-test [type]` | `lua test --ci --name … --input …` | failures → debug subagent | -| `/lua-workflow ` | `lua workflows …`, `lua test workflow` | read-only verbs run at once; start/approve/signal/resume/cancel confirm once; deploy → `/lua-deploy` | +| `/lua-workflow ` | `lua workflows …`, `lua test workflow` | read-only verbs run at once (⏳ incl. `policy models\|autonomy get`, `models`); start/approve/signal/resume/cancel (⏳ `clear-gate`, `policy … set`, `recompose`) confirm once; deploy → `/lua-deploy` | | `/lua-chat` | `lua chat --ci -e … -m … -t` | always an explicit thread | | `/lua-logs` | `lua logs --ci --type … --json` | real `--type` list (`mastra` is not valid) | | `/lua-env` | `lua env --list \| -k KEY -v VALUE \| -k KEY --delete` | environment + key + value collected once; the Bash prompt is the confirmation; the value is never echoed, listings show masked values | @@ -181,7 +185,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.33.0 | +| SessionStart | `check-lua-version` | warns (never blocks) if lua-cli < 3.36.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 | @@ -233,7 +237,7 @@ The rules `/lua-doctor` merges (`lib/permissions-template.json`): - **deny** — anything with `--auto-deploy`, `lua auth configure|key|logout*`, and the alternative binaries `heylua *` / `lua-ai *` wholesale (same program; the plugin only ever emits `lua`). The bare production verbs (`lua deploy`, `lua version promote`, …) are **deliberately not in `deny` or `ask`**: Claude Code evaluates those two tiers past a leading env assignment, so a `Bash(lua deploy*)` deny would also block the confirmed `LUA_DEPLOY_CONFIRMED=1 lua deploy …` form and no deploy could ever run (this is documented at code.claude.com/docs/en/permissions and was confirmed live). The bare forms are blocked by the `confirm-deploy` hook instead — see below. - **allow** — the prefixed production verbs (`LUA_DEPLOY_CONFIRMED=1 lua deploy*`, `… lua skills|webhooks|jobs|preprocessors|postprocessors deploy*`, `… lua workflows deploy|activate*`, `… lua version promote*`, `… lua persona production deploy*`, `… lua mcp activate*`, `… lua marketplace template publish|apply*`), every read-only `lua` verb the slashes and subagents use, `lua push * --ci --force*`, `lua sync --check|--pull|--push`, `lua version create*` (a snapshot; nothing goes live until `promote`), and read-only git. -- **ask** — deletes, `lua env *`, `lua pull`, `lua chat clear`, `lua source rollback`, `lua version delete`, workflow run control (`start`, `cancel`, `approve`, `signal`, `resume`, `retry-step`, `resolve-step`, `raise-budget`, `deactivate`, `schedules`, `goals`, `export`, `archive-runs`), `lua devices enable|disable`, `lua marketplace skill publish|unpublish|unlist|transfer`, integration connects/changes, `npm install -g lua-cli`, system installs. For the workflow run-control verbs this prompt **is** the single confirmation: `/lua-workflow` shows you the exact command in the permission prompt and does not ask a second time. `/lua-env` (`lua env *` — kept in `ask` even for `--list`, because the CLI prints masked values) and `/lua-integrations` (connect/update/disconnect/convert, webhook create/pause/resume/delete, MCP activate/deactivate) rely on the same prompt. +- **ask** — deletes, `lua env *`, `lua pull`, `lua chat clear`, `lua source rollback`, `lua version delete`, workflow run control (`start`, `cancel`, `approve`, `signal`, `resume`, `retry-step`, `resolve-step`, `raise-budget`, `deactivate`, `schedules`, `goals`, `export`, `archive-runs`, ⏳ `clear-gate`, `recompose`), ⏳ the org-wide policy writes `lua workflows policy models|autonomy set` (`policy … get` is allowed), `lua devices enable|disable`, `lua marketplace skill publish|unpublish|unlist|transfer`, integration connects/changes, `npm install -g lua-cli`, system installs. For the workflow run-control verbs this prompt **is** the single confirmation: `/lua-workflow` shows you the exact command in the permission prompt and does not ask a second time. `/lua-env` (`lua env *` — kept in `ask` even for `--list`, because the CLI prints masked values) and `/lua-integrations` (connect/update/disconnect/convert, webhook create/pause/resume/delete, MCP activate/deactivate) rely on the same prompt. Precedence is deny → ask → allow. **The production gate is the `confirm-deploy` hook**: it runs on every Bash call, classifies the command with `lib/tokenizer.mjs` (every canonical spelling, every lua-cli alias — `publish`, `on`, `enable`, `submit`, `rollout`, `prod` … — and all three binaries), and blocks a bare production verb with exit 2. A hook block takes precedence over any allow rule, including a broad `Bash(lua *)` you may have in your own settings, so the gate holds even without the template. It refuses shell wrappers and pipes even with the prefix. Only the deploy pilot and `/lua-template` emit the prefix, and only after your one confirmation; the template's allow rules let that confirmed command run without a second prompt. A test (`test/lib/permissions-mirror.test.mjs`) and a lint fail if a deny/ask rule would ever shadow a confirmed form or an allow rule admit a bare one. @@ -250,7 +254,9 @@ Precedence is deny → ask → allow. **The production gate is the `confirm-depl - **Exit 9 / 10 / 11 / 12** — not authenticated / the credential's agent-or-role scope excludes this action / the Lua API is unreachable / the model provider refused (key, model, quota). - **`/lua-deploy` aborts on "server is ahead"** — someone pushed a newer version; `/lua-sync` pull, review, retry. - **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`; the debug subagent maps each to a fix (`lib/knowledge/workflows.md` §9). +- **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. +- **`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. --- @@ -268,6 +274,6 @@ 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.2.2 targets lua-cli 3.33.0. +**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). **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 ff9b56d..0e19439 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.2.2", + "version": "1.3.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 a48c6e4..f9a6f6d 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.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. + +### Per-step model classes (`workflows.md` §2, §7–§9; `cli-reference.md` §1, §4–§5; `decision-trees.md`; `primitives.md` §11, §14; `commands/lua-workflow.md`, `lua-push.md`, `lua-status.md`, `lua-logs.md`, `lua-deploy.md`; every subagent) + +- `agentStep` gains `taskClass` (`classify extract transform draft research reason code judge`), `model: 'class/fast|balanced|strong'`, `requires` (`vision structured largeContext codeExecution`), `modelReason` (≤ 160) and `effort` (`low medium high`) — `src/types/workflow.ts` `AgentStepOptions`; the default task-class map (classify/extract/transform → fast, draft/research/judge → balanced, reason/code → strong) is `@lua/shared-types` `WORKFLOW_DEFAULT_TASK_CLASS_MAP`. +- `effort` is **recorded, estimated and not applied**: a plain push keeps `luaWorkflow: 1`; only `lua push workflow --apply-effort` (`push-helpers.ts` `applyEffortMarker`, `WORKFLOW_EFFORT_MARKER = 2`; `lua push all --apply-effort` stamps every workflow) or a new compose with assignment on moves it. +- Push-time refusals: locally, before any POST, `model-class-unknown` / `task-class-unknown` / `model-trait-unknown` / `requires-invalid` / `effort-unknown` / `model-reason-invalid|-too-long` (`src/interfaces/workflow-model-classes.ts` `validateGraphModelMembers`, `workflow.handler.ts` `workflowModelMemberError`); server-side `task-class-without-model` (`@lua/workflow-graph` `validate.ts` `checkTaskClass`, static definitions only — `lua compile` calls `validateGraph` without `static`, so compile passes it) and `model-class-resolution-off` (with the CLI's hint, `push-helpers.ts`). +- `lua models list --workflows [--json]` — `Class · Model · Best for · Speed · Cost · Efforts · Notes`, footnotes for `awaiting confirmation` / `own key` / `rate not calibrated` (`src/commands/models-workflow-view.ts`, `models.ts`). +- `lua workflows policy models get|set` with `--compose on|off --max-class fast|balanced|strong --consent-actions --allow --class-fast|--class-balanced|--class-strong --class-map = --pins class-only|allowed --fallback same-class|same-provider` (`commands/workflows.ts` `buildModelsPolicyPatch`, `policyCore`; `command-definitions.ts`); `lua workflows clear-gate --kind model_policy` (alias `ungate`; `clearGateCore`) for the `model_policy` park that `status` prints as `⏸️ Paused — a step's model request cannot be resolved…`; `lua workflows recompose ` (alias `recompile`; `recomposeCore`, lua-api `workflow-model-admin.service.ts`). +- `lua workflows start` prints the server-rendered consent card (`consentCardLines`) and exits 6 on a gated start; `status` prints the `🧠 By model` roll-up (`modelRollupBlock`, from `usage.byModel` or the step receipts); `status --steps --json` rows carry `taskClass` / `modelRequested` / `modelResolved` / `modelReason` / `effortApplied` / `modelFallback[]` (lua-api `workflow-projection.ts`); `lua workflows logs` shows `step.model_resolved` / `step.model_policy_warning` (`WORKFLOW_LOG_EVENT_PATTERN`, `modelEventDetail`). The `🤖 Agent steps` block of `lua workflows view` is **not** described: lua-api projects no `agentModels` on a version, so the CLI never prints it. +- ⚠ Forward-looking: lua-cli main `push.ts` (`#3024`, `af66332ee`) adds workflows to stage-all and **always activates** the pushed version — on lua-cli 3.36.0 `lua push all` is a workflow go-live. `cli-reference.md` §4/§5, `primitives.md` §14 (34), `/lua-push`, `/lua-deploy` and the deploy pilot say so; the hook gate is unchanged (open question in the audit report). + +### Consent and the autonomy envelope (`workflows.md` §3; `decision-trees.md` "Will a workflow start without asking a person?"; `agents/lua-architect.md`, `lua-debug.md`; `commands/lua-workflow.md`, `lua-status.md`; `docs/USER_GUIDE.md`) + +- The consent ladder (lua-core `compose/workflow-consent.service.ts` `decide()`): `auto | ask | refuse` on `maxAutoSteps` 15 · `maxAutoCredits` 20 · `maxAutoDurationSeconds` 3600 (`WORKFLOW_CONSENT_DEFAULTS`; ceilings 40 / 604 800), `refuse` when `askAboveThresholds: false`; the duration input is the expected wall since H7; it runs on the agent's compose, tool and batch legs only (`decide()` call sites), not on `lua workflows start` / REST / SDK starts; the gate is `{ kind: 'start-consent', approvalLinkId, since, expiresAt }` and a person clears it — `lua workflows approve` cannot (`docs/api/Workflows.md` on main). +- H7 (`#3053`): `lua workflows status --strict` exits **6** on a gated run (`exitCodeForRunStatus`; it exited 0); H8 (`#3051`): `status --steps` prints `⇅ : approver escalated → — the initiator is excluded (maker-checker)` from `suspend.approverFallback` (`approverFallbackLine`). +- The envelope `autonomy { enabled, maxCredits, maxSteps, maxDurationSeconds, maxActions, maxRunsPerHour, forms }`: `enabled` absent ⇒ false; defaults 20 / 15 / 86 400 / the org's `models.consentActions` / 20 / `['graph','static']`; ceilings 40 / 604 800 / `caps.maxCreditsPerRun` / 200 (`LUA_WF_AUTONOMY_MAX_RUNS_PER_HOUR`) — `@lua/shared-types` `workflow-node-policy.ts`, `@lua/shared-schemas` `effectiveWorkflowAutonomy` (org narrowed by agent, clamped). The one flip — `ask` → `auto` when `enabled`, the form is admitted and every dimension fits — stamps `consent { approvedBy: 'system:policy', via: 'autonomy', envelope }` and audits `workflow.run.autonomy_applied`; `refuse` is never touched; goal and batch legs never flip (`workflow-tool-runtime.service.ts` `meter`); the hourly bucket `wf:org::autonomy:` (`workflow-autonomy-rate-limit.service.ts`) turns an over-quota flip back into `ask`, never a refuse. +- `lua workflows policy autonomy get` (one `?effective=true` request: stored + effective blocks) and `set --enabled on|off --max-credits --max-steps --max-duration --max-actions --max-runs-per-hour --forms graph,script,static --clear `; `--agent` is refused because no route writes a per-agent envelope (`autonomyPolicyCore`, `buildAutonomyPolicyPatch`, `src/interfaces/workflow-autonomy.ts`); `status` prints `Consent: auto (policy) — ≤ 20 credits · 15 steps · 1 d` for a `via: 'autonomy'` stamp and nothing otherwise (`consentLine`, D28). +- The architect composes for starting without a question (inside the ladder or the envelope, short waits, graph/static form) and writes the exact `policy autonomy set` line for an admin when a wider envelope is needed. + +### Plugin machinery + +- `lib/permissions-template.json`: allow `lua workflows policy * get*`; ask `lua workflows policy * set*`, `clear-gate` / `ungate`, `recompose` / `recompile` (all confirm once through the Bash prompt like the other run-control verbs). `test/lib/permissions-mirror.test.mjs` pins them. +- `scripts/lint-knowledge-commands.mjs`: `policy`, `clear-gate`, `recompose` join the `workflows` action list (read against a lua-cli `main` checkout). `scripts/lint-cli-flags.mjs`: denies `policy autonomy set --max-duration-seconds` and `policy autonomy set --agent`. +- Bump 1.2.2 → 1.3.0 everywhere; `mcp/lua-platform/dist/server.js` rebuilt; `PINNED_MIN_LUA_CLI` 3.33.0 → 3.36.0 (`hooks/check-lua-version.mjs`, `test/hooks/check-lua-version.test.mjs`, `/lua-init`, `/lua-update`, `/lua-doctor`, the user guide and READMEs). + ## 1.2.2 — 2026-09-13 Knowledge-only release: corrections validated against production by the system audit of 2026-09-13 (live probes on the E2E agents, re-verified in lua-core-services and lua-iac source), applied to the knowledge base, subagent prompts, slash commands, SECURITY notes and user guide. No hook, permission or MCP behaviour changed. Every line names its source. diff --git a/plugins/lua-agent-builder/README.md b/plugins/lua-agent-builder/README.md index 74945f6..53b91e4 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. +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. ## 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.33.0, auth, permission rules +/lua-doctor # Node, npm, lua-cli ≥ 3.36.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 d3d641b..ea88c36 100644 --- a/plugins/lua-agent-builder/agents/lua-architect.md +++ b/plugins/lua-agent-builder/agents/lua-architect.md @@ -47,6 +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. + - **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). 9. **Packaging**: if the agent will be installed by other orgs, plan a marketplace agent template (`lua marketplace template create/draft/publish`) with an env contract and connections. @@ -80,7 +82,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: ; budget ; Job tier? +- `` — 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) -
@@ -145,8 +147,11 @@ Under-engineering to flag: per-user state with no `User` usage; a webhook receiv
 - `lua resources list --ci`
 - `lua features list --ci`
 - `lua workflows list --ci`
+- `lua models list --workflows --json --ci`
+- `lua workflows policy models get --ci`
+- `lua workflows policy autonomy get --ci`
 
-Read local files with `Read`/`Glob`/`Grep`, not `cat`/`ls`/`find`. Never run anything that mutates state — the architect is read-only. `lua integrations connect` is an interactive OAuth flow the user runs in their own terminal.
+The last three need lua-cli 3.36.0 or later: on an older CLI they exit 2 (`--workflows` unknown option / `policy` unknown action) — say so in the plan and fall back to `lua models list --json --ci` and the platform defaults in workflows.md §2–§3. Read local files with `Read`/`Glob`/`Grep`, not `cat`/`ls`/`find`. Never run anything that mutates state — the architect is read-only. `lua integrations connect` is an interactive OAuth flow the user runs in their own terminal.
 
 ## When to escalate
 
diff --git a/plugins/lua-agent-builder/agents/lua-debug.md b/plugins/lua-agent-builder/agents/lua-debug.md
index a95647b..db6cc48 100644
--- a/plugins/lua-agent-builder/agents/lua-debug.md
+++ b/plugins/lua-agent-builder/agents/lua-debug.md
@@ -13,7 +13,7 @@ A `lua compile --ci`, `lua test --ci` or `lua push` invocation failed, or a work
 
 ## Diagnostic loop
 
-1. **Classify by exit code** (lua-cli 3.33.0): `1` unclassified/compile failed/a prompt hit under `--ci` · `2` usage (bad flag, unknown action, no `lua.skill.yaml`/agentId) · `3` not found · `9` auth (run `/lua-auth`) · `10` forbidden (typed key lacks the agent/role scope) · `11` Lua API unavailable (retry) · `12` model provider refused (key/model/quota) · workflows `4` run failed, `5` cancelled, `6` gated, `7` timeout, `8` parked for a human. Read the one-line `✖ : ` and the `💡` hint first. An exit `0` whose output is a rendered menu and no result means a raw prompt hit EOF (`lua test skill` without `--name`, bare `lua env`, `lua chat` without `-m`/`-e`) — a false success; re-run with complete flags. An exit `0` whose result is `{ status: 'error', error: '…' }` (usually with a stack on stderr) means the handler **threw**: `lua test` swallows the throw (`src/utils/sandbox.ts`) and prints the success banner anyway — treat it as the runtime error below.
+1. **Classify by exit code** (lua-cli 3.33.0): `1` unclassified/compile failed/a prompt hit under `--ci` · `2` usage (bad flag, unknown action, no `lua.skill.yaml`/agentId) · `3` not found · `9` auth (run `/lua-auth`) · `10` forbidden (typed key lacks the agent/role scope) · `11` Lua API unavailable (retry) · `12` model provider refused (key/model/quota) · workflows `4` run failed, `5` cancelled, `6` gated (a consent gate — a person clears it from the desktop, `lua workflows approve` cannot; ⏳ lua-cli 3.36.0 or later: `status --strict` exits 6 on a gated run too, where older CLIs exit 0 — so a poll that "succeeded" on an older CLI may be sitting on a gate), `7` timeout, `8` parked for a human. Read the one-line `✖ : ` and the `💡` hint first. An exit `0` whose output is a rendered menu and no result means a raw prompt hit EOF (`lua test skill` without `--name`, bare `lua env`, `lua chat` without `-m`/`-e`) — a false success; re-run with complete flags. An exit `0` whose result is `{ status: 'error', error: '…' }` (usually with a stack on stderr) means the handler **threw**: `lua test` swallows the throw (`src/utils/sandbox.ts`) and prints the success banner anyway — treat it as the runtime error below.
 
 2. **Re-run with detail**: `lua compile --ci --debug --verbose` (plugin-detection trace), or `lua test --ci  --name  --input '' --json` with `LUA_DEBUG=1` for a stack.
 
@@ -27,7 +27,9 @@ A `lua compile --ci`, `lua test --ci` or `lua push` invocation failed, or a work
    - **Runtime error in the VM** (`lua test` exit **0** with a stack on stderr and a `{ status: 'error', error }` result — the sandbox catches the throw and the success banner prints anyway; exit 1 only for failures outside the handler) → input doesn't match the Zod schema (check `--input`), a platform API used wrongly (`Data.get` returns `{ data, pagination }`; `AI.generate(a, b)` makes `a` the system prompt; `Jobs.create` execute can't close over variables; `User.get()` needs a userId in webhooks/jobs; `Products.getById` throws on miss), or a missing env var (`env('X')` → set it with `lua env sandbox -k X -v …`, which rewrites `.env`).
    - **`lua test` says the type is unknown** → types are `skill webhook job preprocessor postprocessor workflow`. **`lua test skill` exits 3 with `not_found: Tool "" not found`** → `--name` wants a TOOL name, not the skill name; `--input` is the tool's own fields with no `{"tool": …}` wrapper.
    - **Drift / "behind" / orphan primitives** → `lua status --json --ci` shows per-primitive `diffs[].status` and `orphans[]`; `lua sync --pull` restores from the server backup (guarded), `lua sync --check` exits 1 on drift.
-   - **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`.
+   - **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.
    - **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.
@@ -47,6 +49,7 @@ A `lua compile --ci`, `lua test --ci` or `lua push` invocation failed, or a work
 - `lua status --json --ci`
 - `lua logs --ci [args]`
 - `lua workflows status * --steps --json`
+- `lua workflows logs *`
 - `git log --oneline -20`
 - `git diff [args]`
 
diff --git a/plugins/lua-agent-builder/agents/lua-deploy-pilot.md b/plugins/lua-agent-builder/agents/lua-deploy-pilot.md
index 3a003c8..506abc8 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-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 8daf5b5..2f8235b 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`.
+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/`).
 
 ## 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 33dc8e9..e59f2e4 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)
+   - 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-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 0b198c2..5fd3c63 100644
--- a/plugins/lua-agent-builder/commands/lua-deploy.md
+++ b/plugins/lua-agent-builder/commands/lua-deploy.md
@@ -46,3 +46,4 @@ The pilot reports what was pushed, what went live, the smoke result and the exac
 - Never run a bare deploy verb (`lua deploy`, `lua workflows deploy|activate`, `lua version promote`, `lua mcp activate`, `lua * deploy`, `lua persona production deploy`) — all are denied without the `LUA_DEPLOY_CONFIRMED=1` prefix, and the pilot is the only place that emits the prefix.
 - Never include `--auto-deploy` anywhere.
 - `lua push all` and `lua deploy all --force` exit 0 even when items fail or are skipped (`No versions for … skipping`) — the pilot scans their output and aborts/reports on those lines instead of trusting the exit code (cli-reference.md §4).
+- ⏳ lua-cli 3.36.0 or later: `lua push all` also pushes every workflow **and activates the pushed version** (main `push.ts`, PR #3024). For targets `all` / `agent-version` the pilot's step-4 stage-all therefore makes workflow versions live on that CLI — the user confirmed a production change, so it is in scope, but the pilot must list those workflows under "what went live". `lua push workflow … --apply-effort` (per-step `effort` applied from that version on) is passed through only when `notes` asks for it. A 409 `WORKFLOW_DYNAMIC` stays a hard stop: `lua workflows recompose ` publishes a new version of a chat-composed definition but is not a deploy path.
diff --git a/plugins/lua-agent-builder/commands/lua-doctor.md b/plugins/lua-agent-builder/commands/lua-doctor.md
index f572096..fa15b4b 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.33.0 — the version the plugin's commands and knowledge were verified against) → 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.36.0 — the plugin's knowledge describes workflow verbs that do not exist below it) → 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 a59c7ee..ce8cff1 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.33.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.36.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 c4bab2a..638ad9e 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.
+`--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).
diff --git a/plugins/lua-agent-builder/commands/lua-push.md b/plugins/lua-agent-builder/commands/lua-push.md
index f9dd34b..3ab6960 100644
--- a/plugins/lua-agent-builder/commands/lua-push.md
+++ b/plugins/lua-agent-builder/commands/lua-push.md
@@ -32,6 +32,10 @@ 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):
+- `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`.
+
 ## Step 3 — report
 
 ⚠ Exit 0 is not success for `all` (or for a type push of several primitives): lua-cli 3.33.0 prints `❌ Failed to push : …` per item and `⚠️  N component(s) failed to push`, then `✅ Push All Complete!`, and still exits 0 (`push.ts` ~1300-1353; validated live 2026-09-13). Scan the output for `❌ Failed to push`; if present, report the failed items as a failure (the others were pushed) — never say "✓ Pushed".
@@ -40,4 +44,4 @@ On success: "✓ Pushed `:` v`` (server version created; no
 
 If the output contains `Model configuration cleared`, `Model settings cleared`, `Batching config cleared` or `Voices cleared` (types `all` / `agent`), say so plainly: the agent push overwrites those server fields with whatever `src/index.ts` declares, so a model chosen in the dashboard is now gone. Point at the fix: set `model` (or `modelSettings` / `batching`) on the `LuaAgent` — `lua models set --model ` writes it for you — and push `agent` again.
 
-On failure surface the CLI line verbatim. Common refusals: `unplaced_step` / `tool_unbundled` / `env-template-missing` (workflows — set the env key first), `WORKFLOW_NAME_TAKEN`, exit 9 (auth), exit 10 (scope). Do not retry without user input.
+On failure surface the CLI line verbatim. Common refusals: `unplaced_step` / `tool_unbundled` / `env-template-missing` (workflows — set the env key first), `WORKFLOW_NAME_TAKEN`, exit 9 (auth), exit 10 (scope); ⏳ lua-cli 3.36.0 or later workflow refusals: `model-class-unknown` / `task-class-unknown` / `model-trait-unknown` / `effort-unknown` / `model-reason-too-long` (a value outside the vocabulary, refused before anything is sent — `issues[]` names the step), `task-class-without-model` (server: a `taskClass` needs `model: 'class/fast|balanced|strong'` or an approved code), `model-class-resolution-off` (this environment has model classes off — pin a code or drop `model`). Do not retry without user input.
diff --git a/plugins/lua-agent-builder/commands/lua-status.md b/plugins/lua-agent-builder/commands/lua-status.md
index 9d20028..ccd9e5b 100644
--- a/plugins/lua-agent-builder/commands/lua-status.md
+++ b/plugins/lua-agent-builder/commands/lua-status.md
@@ -21,3 +21,7 @@ Render:
 5. `warnings[]` verbatim and `hints[]` as "Try: `` — ".
 
 For what is live on any agent (not just this project) the `mcp__plugin_lua-agent-builder_lua-platform__get_deployment_status` tool gives the same picture from the server side.
+
+## 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.
diff --git a/plugins/lua-agent-builder/commands/lua-update.md b/plugins/lua-agent-builder/commands/lua-update.md
index cc7a4aa..208f8a8 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.33.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.36.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 dc2547a..c0039d8 100644
--- a/plugins/lua-agent-builder/commands/lua-workflow.md
+++ b/plugins/lua-agent-builder/commands/lua-workflow.md
@@ -14,7 +14,8 @@ 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`, `nextAction`, `budget`
+- `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
+- ⏳ `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 )`
 - `run ` (offline — the local driver, no platform call) → build the command from the user's text: `Bash(lua workflows run  --input '|@file' --agents fake --fast-retries [--step-output ='' …] [--approve [=@file]] [--deny ] [--signal =''] [--now ] [--park ] [--from-run ] [--env KEY=value] [--ledger-out ledger.json] --json)`. Exit `0` completed · `2` flag/schema problem · `3` unknown workflow · `4` a step failed · `5` fixture missing. On `4`, read the failing step from the `--json` output (`steps[].error.code`), and offer two follow-ups: re-run with `--from-run ` if a platform run exists (the offline driver seeds step outputs from that run's ledger so only the failing step re-executes), or hand the command and output to the `lua-debug` subagent via the Agent tool (`subagent_type: "lua-debug"`).
@@ -32,9 +33,12 @@ Run `Bash(lua models list --json --ci)` — a 1–2 s authenticated call (no pro
 - `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
+- ⏳ `clear-gate ` (lua-cli 3.36.0 or later) → `lua workflows clear-gate  --kind model_policy` — clears a step parked because its model class cannot be resolved under the org policy (`gate.kind: 'model_policy'`); a run not on that gate answers `Nothing to clear`, exit 0. Not a consent gate: that one is a person's.
+- ⏳ `policy models set …` / `policy autonomy set …` (lua-cli 3.36.0 or later) → `lua workflows policy models set [--compose on|off] [--max-class fast|balanced|strong] [--consent-actions ] [--allow ] [--class-fast|--class-balanced|--class-strong ] [--class-map =,…] [--pins class-only|allowed] [--fallback same-class|same-provider]` / `lua workflows policy autonomy set [--enabled on|off] [--max-credits ] [--max-steps ] [--max-duration ] [--max-actions ] [--max-runs-per-hour ] [--forms graph,script,static] [--clear ]` — an **organization-wide** write (administrator; a 403 is the server's verdict). Say in your one line that it applies to every agent of the org, and for `--enabled on` that agent-started runs inside the envelope will from then on start **without** a person's consent (goal and batch starts never do; `askAboveThresholds: false` still refuses). Only the named members are sent; `--clear` restores the platform default; never `--agent` (refused: nothing writes a per-agent envelope); `--max-duration` takes seconds (`--max-duration-seconds` is `raise-budget`'s flag).
+- ⏳ `recompose ` (lua-cli 3.36.0 or later) → `lua workflows recompose ` — the server rewrites a chat-composed definition's stored task classes into `class/` and publishes a **new version** on the same parent (no agent turn). Report `unchanged`, or the new version and `rewritten` count, then `lua workflows versions ` shows which version is active — a dynamic workflow has no `deploy` verb.
 
 **Production-affecting verbs are not run here**: `deploy`, `activate` → tell the user to run `/lua-deploy` (target `workflow`); it emits the `LUA_DEPLOY_CONFIRMED=1` form after its own confirmation.
 
 ## 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 (consent/quota/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). 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.
diff --git a/plugins/lua-agent-builder/hooks/check-lua-version.mjs b/plugins/lua-agent-builder/hooks/check-lua-version.mjs
index 2c02767..ae7bd35 100644
--- a/plugins/lua-agent-builder/hooks/check-lua-version.mjs
+++ b/plugins/lua-agent-builder/hooks/check-lua-version.mjs
@@ -7,16 +7,19 @@ 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.33.0 surface (workflows, triggers, devices,
-// voice, agent versions, `lua auth sessions`, the typed exit-code classes,
-// `lua test preprocessor|postprocessor|workflow`, `lua push --no-include-source`).
+// files describe the lua-cli 3.36.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`,
+// `clear-gate`, `recompose`, `models list --workflows`, `push --apply-effort`)
+// that answer exit 2 on anything older.
 // 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.33.0 was
-// published 2026-09-10), so `/lua-update` can always satisfy it; the lint at
+// 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.33.0';
+export const PINNED_MIN_LUA_CLI = '3.36.0';
 
 /**
  * Parse "X.Y.Z" into [X, Y, Z]. Returns null on garbage input.
@@ -64,7 +67,7 @@ export function decide(versionResult) {
   const minimum = parseSemver(PINNED_MIN_LUA_CLI);
   if (compareSemver(installed, minimum) < 0) {
     return {
-      warn: `Lua plugin requires lua-cli ≥${PINNED_MIN_LUA_CLI} (you have ${installed.join('.')}) — run /lua-update. The plugin will continue to work with degraded functionality until you do.`,
+      warn: `Lua plugin requires lua-cli ≥${PINNED_MIN_LUA_CLI} (you have ${installed.join('.')}) — run /lua-update or: npm i -g lua-cli@latest. The plugin will continue to work with degraded functionality until you do (the workflow policy, clear-gate and recompose verbs it describes do not exist below ${PINNED_MIN_LUA_CLI}).`,
     };
   }
 
diff --git a/plugins/lua-agent-builder/lib/knowledge/cli-reference.md b/plugins/lua-agent-builder/lib/knowledge/cli-reference.md
index 2908f85..9bdf807 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)
+# lua-cli command reference (3.33.0 base · 3.36.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 ⚠).
+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.
 
 lua-cli is a TypeScript toolchain. It has nothing to do with the Lua programming language.
 
@@ -29,7 +29,7 @@ lua-cli is a TypeScript toolchain. It has nothing to do with the Lua programming
 | 1 | error — unclassified failure, `compile_failed`, `lua sync --check` with drift, a prompt reached under `--ci`, a `lua workflows` API refusal (4xx other than 404) |
 | 2 | usage — bad args, unknown action, no `lua.skill.yaml` / missing agentId |
 | 3 | not found (404) |
-| 4 · 5 · 6 · 7 · 8 | `lua workflows` only: run failed/timed out · run cancelled · run gated (consent) · `--timeout` reached · run parked waiting for a human |
+| 4 · 5 · 6 · 7 · 8 | `lua workflows` only: run failed/timed out · run cancelled · run gated (consent) · `--timeout` reached · run parked waiting for a human. ⏳ 3.36.0+: `lua workflows status --strict` on a `gated` run exits 6 as well (`exitCodeForRunStatus`, hotfix H7 — below 3.36.0 it exits 0, so a poll loop read a consent-gated start as success); a consent gate is cleared by a person from the desktop / approvals API, never by `lua workflows approve` (workflows.md §3) |
 | 9 | auth (no credential / 401 / session signed out) |
 | 10 | forbidden (403, and other 4xx as `http_`) |
 | 11 | unavailable (5xx, network, timeout) |
@@ -79,15 +79,16 @@ Legend — **RO** read-only · **L** local write · **S** server write (staging/
 | `lua sync --pull [--force]` (`--accept` is the legacy alias) | refuses if local files changed since the last backup unless `--force` | L: restores files from the server backup |
 | `lua sync --push` | | S/P: pushes persona version (served at once — see the `lua push agent` row), name, model, governance — **not** primitives (use `lua push`) |
 | `lua agents [--json]` | `[{ orgId, name, archived, discoveredVia, agents: [{ agentId, name, visibility, displayRoles }] }]` | RO — the plugin's auth probe |
-| `lua models [list] [--json]` · `lua models set --model ` · `lua models unset` | list: `{ currentModel, models: [{ provider, code, model, description, … }] }` | RO / L+S |
+| `lua models [list] [--json]` · `lua models set --model ` · `lua models unset` · ⏳ `lua models list --workflows [--json]` | list: `{ currentModel, models: [{ provider, code, model, description, … }] }`. ⏳ `--workflows` renders the same catalog as a workflow step sees it — `Class · Model · Best for · Speed · Cost · Efforts · Notes`, cheapest class first, pin-only rows last (`src/commands/models-workflow-view.ts`; workflows.md §2); `--json` stays the server's own rows | RO / L+S |
 | `lua logs --type  [--name n] [--user-id u] [--agent-id a] [--limit n (20)] [--page n] [--json]` | `--type` accepts exactly `all skill job webhook preprocessor postprocessor mcp device device-trigger user_message agent_response agent_error runtime rag calls` (`src/utils/aliases.ts` `logs.type` plus the `all` / `calls` special cases in `src/commands/logs.ts`; aliases such as `skills jobs pre pp post mcps user response error kb knowledge devices` are accepted). Anything else — the help text's `mastra`, and the five real platform log sources the CLI never whitelisted (`trigger`, `model-resolver`, `workflow-step`, `workflow-script`, `workflow`) — is `CliError.usage` → exit 2; those five are reachable only through the `tail_logs` MCP tool (the server route applies no validation, it is a plain `metadata.logSource` filter). `all` = no source filter; `calls` = voice-call records, a different dataset. `--json` → `{ logs: LogEntry[], pagination }`; `LogEntry { id, timestamp, type: 'log'\|'metric', subType: 'error'\|'warn'\|'info'\|'debug'\|'start'\|'complete', message, duration?, metadata: { userId?, agentId?, runId?, logSource?, primitiveId?, primitiveName?, toolId?, toolName?, channel? } }` — **no `level` field, and no `environment` field**: nothing in a log entry records sandbox vs production. `metadata.channel` is the raw request channel: **`dev` marks every turn `lua chat` sent** (`src/api/chat.api.service.ts` posts `?channel=dev`, for `-e sandbox` and `-e production` alike) — it separates CLI traffic from end-user traffic, **not** sandbox from production; `pop` is the website widget, `web` other web clients. A tool `execute` that throws is logged as `subType: 'error'` under **`logSource: 'skill'`** (the whole tool site runs under that source, lua-core `execute-function.service.ts`); **`agent_error` is written only by the chat pipeline's** generate/stream error handlers (`chat.service.ts`), never by a tool | RO |
 
 ### Push & deploy
 | Command | Shape | Effect |
 |---|---|---|
-| `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 `). 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 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 | **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 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** |
 | `lua skills\|webhooks\|jobs\|preprocessors\|postprocessors deploy …` | older per-primitive spellings (`--skill-name/--skill-version`, `--webhook-name/--webhook-version`, `-i/-v` for jobs, `--preprocessor-name/--preprocessor-version`…) | **P** |
@@ -138,8 +139,8 @@ First find out whether the agent **has agent versions**: `lua version list --jso
 | persona / agent config | `agent` | **`lua push agent` is the deploy**: the pushed persona version is persisted `published` and served on the next turn (lua-agents `createPersonaVersion` → `updateAgentPersona`; lua-core reads `subAgent.persona`). `lua deploy persona --set-version  --force` re-points the served persona to an earlier version — the **rollback** verb. `lua version promote` never changes the served persona | model/modelSettings/batching/browser are live on push too — treat `lua push agent` (and the agent config inside `lua push all`) as a production change |
 | mcp-server | `mcp` | `lua mcp activate ` | non-versioned (`lua push mcp --auto-deploy` would activate too — denied) |
 | device / device-trigger / voice | `device` / `device-trigger` / `voice` | `lua version create` → `lua version promote ` | not `lua deploy` types (a single-primitive `lua push  --auto-deploy` would publish the version at once — denied) |
-| workflow | `workflow` | `lua workflows deploy  -v latest` — scoped promote; `lua workflows activate  -v ` **also deploys that version** (`src/commands/workflows.ts` ~343: `-v` routes to `deployCore`) | `lua workflows activate ` without `-v` only enables schedules/triggers; workflows are never part of `lua push all` |
-| everything | `lua push all --force` (stage-all; workflows excluded) | **versioned agent**: `lua version create` → `lua version promote ` (atomic; also the rollback path) · **unversioned**: `lua deploy all --force` (latest of every deployable primitive) | `promote` is also rollback — it rewrites the live skill pins from the snapshot, undoing any `lua deploy skill` made since (the served persona is untouched by promote; roll it back with `lua deploy persona --set-version `) |
+| workflow | `workflow` | `lua workflows deploy  -v latest` — scoped promote; `lua workflows activate  -v ` **also deploys that version** (`src/commands/workflows.ts` ~343: `-v` routes to `deployCore`) | `lua workflows activate ` without `-v` only enables schedules/triggers; workflows are never part of `lua push all` below 3.36.0 — ⏳ lua-cli 3.36.0 pushes **and activates** them in stage-all (§4 push row) |
+| everything | `lua push all --force` (stage-all; workflows excluded below 3.36.0 — ⏳ included *and activated* from 3.36.0, §4) | **versioned agent**: `lua version create` → `lua version promote ` (atomic; also the rollback path) · **unversioned**: `lua deploy all --force` (latest of every deployable primitive) | `promote` is also rollback — it rewrites the live skill pins from the snapshot, undoing any `lua deploy skill` made since (the served persona is untouched by promote; roll it back with `lua deploy persona --set-version `) |
 
 After a deploy: `lua logs --type all --limit 30 --json` and scan `subType === 'error'`; `lua status --json` shows `diffs[].status` per primitive.
 
diff --git a/plugins/lua-agent-builder/lib/knowledge/decision-trees.md b/plugins/lua-agent-builder/lib/knowledge/decision-trees.md
index 5124843..f177e1b 100644
--- a/plugins/lua-agent-builder/lib/knowledge/decision-trees.md
+++ b/plugins/lua-agent-builder/lib/knowledge/decision-trees.md
@@ -128,6 +128,42 @@ 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`).
 
+**Per agent step inside a workflow** (⏳ lua-cli 3.36.0 or later; workflows.md §2):
+
+```
+What does the step do?                                  → taskClass                  → model
+├── label / route / yes-no · pull fields · reshape data → classify · extract · transform → 'class/fast'
+├── write prose · gather and summarise · grade output   → draft · research · judge      → 'class/balanced'
+└── multi-step reasoning · write or review code         → reason · code                  → 'class/strong'
+Needs a trait the class must satisfy?                   → requires: ['structured'] (any outputSchema) · ['vision'] · ['largeContext'] · ['codeExecution']
+Must it be one exact model?                             → pin an approved code from `lua models list --workflows --json` (checked at push against the org's set); otherwise never pin
+Reasoning depth?                                        → effort 'low' (tool-heavy orchestration) · 'medium' · 'high' (reason, code) — recorded only; applied from `lua push workflow --apply-effort`
+```
+
+A pushed step that names a `taskClass` must also carry a `model` (`task-class-without-model` at push). The org's ceiling and overrides are `lua workflows policy models get` (`maxClass`, `classMap`, `allow`, `pins`).
+
+---
+
+## "Will a workflow start without asking a person?"
+
+Only agent-initiated starts are scored (the compose tool, a saved workflow the agent's tool starts, batch starts); `lua workflows start` / REST / SDK starts are not (workflows.md §3).
+
+```
+Estimate ≤ 15 steps AND ≤ 20 credits AND expected wall ≤ 1 h?
+├── Yes → auto (nobody asked; no stamp)
+└── No
+    ├── org config askAboveThresholds: false                       → refuse (autonomy never changes this)
+    ├── goal run or batch start                                    → ask (these legs never auto-start)
+    ├── org autonomy envelope enabled (⏳ `lua workflows policy autonomy get`: enabled true)
+    │   AND form admitted (default graph,static — script opts in)
+    │   AND ≤ maxSteps (15) · ≤ maxCredits (20) · ≤ maxDurationSeconds (1 d) · ≤ maxActions (org consentActions)
+    │   ├── hourly allowance left (maxRunsPerHour, default 20 per agent) → auto (policy) — `Consent: auto (policy) — ≤ …` on `status`
+    │   └── allowance spent, or the meter unreachable                  → ask (the safe answer, never refuse)
+    └── otherwise                                                  → ask: the run is `gated` (`start-consent`) until a person clears it from the desktop
+```
+
+Design for the top branch (small composed graphs, short waits — an approval or signal wait counts toward the expected wall) and put the exact `lua workflows policy autonomy set …` line in the plan when the org needs a wider envelope; it is an org-wide consent surface the plugin asks before running.
+
 ---
 
 ## "How do I handle identity / authentication for users?"
diff --git a/plugins/lua-agent-builder/lib/knowledge/primitives.md b/plugins/lua-agent-builder/lib/knowledge/primitives.md
index 73c45bc..5221c37 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)
+# Lua SDK primitive reference (lua-cli 3.33.0 base · 3.36.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.
+`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).
 
 ---
 
@@ -516,6 +516,8 @@ Every production-affecting verb above is gated by this plugin: bare forms are de
 30. `OrderStatus.FULFILLED` sends `fulfilled`; the platform's enum, filters and dashboards use `fullfilled` (two l's) and the status param is never validated — the mismatch is silent (§12).
 31. `lua chat -e sandbox` uploads the **entire shell environment** with each sandbox skill version and the runtime never reads it — run it from a clean shell (`env -i …`); `lua test` reads `.env` locally and uploads nothing (§12 `env(key)`, cli-reference.md §4).
 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).
 
 ---
 
diff --git a/plugins/lua-agent-builder/lib/knowledge/workflows.md b/plugins/lua-agent-builder/lib/knowledge/workflows.md
index e0c1063..3ffc4e1 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)
+# Lua Workflows reference (lua-cli 3.33.0 base · 3.36.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 ⚠).
+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.
 
 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.
 
@@ -88,7 +88,7 @@ Builder methods (each returns the builder; end with `.commit()`):
 .dowhile(step, predicate, { maxIterations? /*100*/, intervalSeconds? })   .dountil(...)
 .sleep(ms, { id?, businessHours? })           // literal milliseconds
 .sleepUntil(isoOrTemplate, { id?, businessHours?, round?: 'next-open' | 'next-close' })
-.agentStep(id, { agentId, prompt, outputSchema?, model?, toolScope?, systemPrompt?, timeoutSeconds?, retry?, onError?, requiredConnections?, tier?: 'job', workspace?, jobResources?, harness?, maxTurns?, maxMessages?, maxInputTokens? })
+.agentStep(id, { agentId, prompt, outputSchema?, model?, taskClass?, requires?, modelReason?, effort?, toolScope?, systemPrompt?, timeoutSeconds?, retry?, onError?, requiredConnections?, tier?: 'job', workspace?, jobResources?, harness?, maxTurns?, maxMessages?, maxInputTokens? })   // taskClass/requires/modelReason/effort ⏳ 3.36.0+ — see "Per-step model selection"
 .specialistStep(id, { role: { name, instructions (≤4000), tools: string[] } | { ref }, prompt, outputSchema?, model?, toolScope?, timeoutSeconds?, retry?, onError?, requiredConnections? })
 .toolStep(id, toolObject, { input?, timeoutSeconds?, retry?, sideEffects?, onError?, requiredConnections? })   // a LuaTool imported by identifier from its own module
 .approval(id, { title, details?, approver?, excludeInitiator?, fourEyes?, timeoutHours?, onTimeout?, onDeny?, businessHours?, editable?, editablePaths?, editedPayloadSchema?, itemsPath?, itemApprover?, itemTimeout? })
@@ -134,6 +134,26 @@ Platform APIs (`AI`, `Channels`, `Integrations`, `Workflows`, `Data`, …) are a
 
 `step(id).path('p')` / `stepOf('id').path('p')` (typed) / `init('path')` / `state('path')` produce refs; combine with `eq ne gt gte lt lte inSet notIn exists notExists truthy falsy and or not` and `lit(v)`. A function where a predicate is expected is `closure-predicate` — compute the condition in a `createStep` and reference its output.
 
+### Per-step model selection (⏳ requires lua-cli 3.36.0 or later)
+
+Four optional, purely additive members on `agentStep` (`src/types/workflow.ts` `AgentStepOptions`; the serializer fills no default, a step that sets none behaves exactly as before, and `model` itself already existed):
+
+| Member | Values | Notes |
+|---|---|---|
+| `model` | `'class/fast' \| 'class/balanced' \| 'class/strong'` — or an approved `provider/model` code, `'auto'`, or a `${initData.\|}` placeholder | a **class** is resolved to a code at dispatch through the organization's model policy (it is not a pin: `computeDeferred` no longer marks it `model-unresolved`); a **pin** is checked against the org's approved set by the server at push, and while the platform runs pin-denylist enforcement in warn-only mode an org-excluded pin runs with a `step.model_policy_warning` instead of being refused |
+| `taskClass` | `classify \| extract \| transform \| draft \| research \| reason \| code \| judge` | what the step does. Platform map (`@lua/shared-types` `WORKFLOW_DEFAULT_TASK_CLASS_MAP`; an org overrides per task class with `--class-map`): classify / extract / transform → `fast`, draft / research / judge → `balanced`, reason / code → `strong`. ⚠ On a **pushed** definition a `taskClass` with no `model` is refused by the server — `task-class-without-model` (`@lua/workflow-graph` `validate.ts` `checkTaskClass`, only under `static: true`, which lua-api's push passes and `lua compile` does not — so compile is clean and push exits 1): nothing maps a task class to a model at dispatch, write the `class/` yourself. Chat-composed definitions are exempt (the composer maps it) |
+| `requires` | `['vision' \| 'structured' \| 'largeContext' \| 'codeExecution']` | traits the resolved model must have — a step with an `outputSchema` wants `structured`, one reading images `vision`; write these instead of pinning a code that may retire |
+| `modelReason` | string ≤ 160 chars | why this class or pin; plain text, never parsed; shown on the consent card and the step rows |
+| `effort` | `'low' \| 'medium' \| 'high'` | **recorded and counted in the estimate, NOT applied** by a plain push: the envelope stays `luaWorkflow: 1` and the executor forwards effort only when the run's frozen snapshot says `2`, which only `lua push workflow --name  --apply-effort` (`push-helpers.ts` `applyEffortMarker`; prints `⚙️ --apply-effort: "" is pushed with per-step effort ENABLED`; script form untouched; `lua push all --apply-effort` stamps every workflow) or a new compose with assignment on sets. Not the agent-level `modelSettings.reasoning.effort` scale (`off / minimal / max`); inert on a model with a toggle-only ladder |
+
+Refused **locally at push, before any POST** (`src/interfaces/workflow-model-classes.ts` `validateGraphModelMembers` walks the graph — or a script's `meta` — and `workflow.handler.ts` throws exit 1 with `issues[]`): `model-class-unknown` (`class/quick`), `task-class-unknown`, `model-trait-unknown` / `requires-invalid`, `effort-unknown`, `model-reason-invalid` / `model-reason-too-long`. Everything that needs the catalog — is this code approved, does this class have an eligible row for this org, is `maxClass` exceeded — is the server's refusal, printed verbatim; a `class/…` push against an environment with class resolution switched off is refused `model-class-resolution-off` and the CLI adds the hint "pin an approved model code, or drop `model`". `lua compile` checks none of this, and `lua test workflow` / `lua workflows run` ignore all five members (the offline driver never reads them).
+
+**Catalog as a step sees it**: `lua models list --workflows [--json]` — columns `Class · Model · Best for · Speed · Cost · Efforts · Notes` (`src/commands/models-workflow-view.ts`), cheapest class first, pin-only rows last. Notes: `awaiting confirmation` (new to the catalog — pinnable by code, no class resolves to it yet), `own key` (BYOK, shown at the provider's relative rate), `rate not calibrated`, `pin only`. Cost is a multiple of a small call on the pricing baseline model — the unit a run budget counts. `--json` is the server's own rows, unchanged by the flag.
+
+**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.
+
 ---
 
 ## 3. Human in the loop
@@ -148,6 +168,14 @@ Platform APIs (`AI`, `Channels`, `Integrations`, `Workflows`, `Data`, …) are a
 
 **Reply channels** — a run started with `replyTo: { channel, threadId }` posts its outcome back when it ends (`whatsapp` is the only registered adapter today ⚠).
 
+**Consent gates** (lua-core `compose/workflow-consent.service.ts` `decide()`, pure) — an agent-initiated start is scored on three dimensions against the agent's thresholds — `maxAutoSteps` 15 · `maxAutoCredits` 20 (undiscounted `consentCredits`) · `maxAutoDurationSeconds` 3600 — and is `auto` when every one is within them, `ask` above them (the run is created `gated` with `gate: { kind: 'start-consent', approvalLinkId, since, expiresAt }`, holds no org slot and waits for a person), or `refuse` above them when the org's compose config sets `askAboveThresholds: false`. The ladder runs on the agent's legs only — the compose service (a chat-composed draft), the agent's workflow tool (a composed draft or a saved workflow it starts) and batch starts (`decide()` call sites: `workflow-compose.service.ts`, `workflow-tool-runtime.service.ts`, `workflow-batch-tool-runtime.service.ts`); a `lua workflows start` / REST / `Workflows.start()` / trigger start is not scored by it and comes back `gated` for quota or billing (and, ⏳, when the server serves a model consent card). Platform ceilings clamp an org config: 40 steps · 604 800 s. The duration input is the estimate's **expected wall** (hotfix H7, in lua-cli 3.36.0 / lua-core: it used to be the sum of validator-filled `timeoutSeconds`, so seven agent steps scored 4200 s and a 7-credit graph asked on duration alone); a `budget.maxDurationSeconds` a person declared can raise the figure, never lower it; a batch or script start with no estimate reads the 24 h default and therefore always asks. A consent gate is cleared by a **person** — from the desktop or the approvals API / inbox — and **not** by `lua workflows approve`, which needs a `--approval wfa_…` id that only an `approval` node has (`docs/api/Workflows.md` on main). `lua workflows status ` reports the gated run and, ⏳ 3.36.0+, exits **6** under `--strict` (`exitCodeForRunStatus`; it exited 0 before, so a CI poll read a consent-gated start as success); `start`, `start --follow` and `watch` exit 6 on it as well unless `--wait-for-human`.
+
+**Autonomy envelope** (platform: `feat/workflow-autonomy`, rolling to production 2026-09-18; CLI verbs ⏳ 3.36.0+) — an organization pre-consents to a bounded start so that `ask` becomes `auto`. It never turns a `refuse` into anything (`askAboveThresholds: false` still refuses) and never touches a start that was already `auto` (no stamp, no audit row). Policy block `autonomy { enabled, maxCredits, maxSteps, maxDurationSeconds, maxActions, maxRunsPerHour, forms }` (`@lua/shared-types` `WORKFLOW_AUTONOMY_DEFAULTS` / `_CEILINGS`): `enabled` absent ⇒ **false** — the one member whose absence is a value; defaults 20 credits · 15 steps · 86 400 s (sized against the ladder's duration bound, hence a day) · `maxActions` = the org's own `models.consentActions` · 20 runs/h · forms `['graph', 'static']` (`script` opts in); ceilings 40 steps · 604 800 s · `maxCredits` ≤ the org's `caps.maxCreditsPerRun` · 200 runs/h (`LUA_WF_AUTONOMY_MAX_RUNS_PER_HOUR`, read at call time) — a stored value above one is clamped when read, and every number is an integer ≥ 1. Above the block sit the platform switch `LUA_WF_AUTONOMY_ENABLED` and a sub-agent's `workflows.autonomy`, which can only narrow (`min(org, agent)`; `enabled: false` vetoes) and which **no route writes today**. The one flip (`decide()`): tier is `ask` AND `enabled` AND the envelope's `forms` lists this start's form AND `steps.max ≤ maxSteps` AND `consentCredits ≤ maxCredits` AND the same duration the ladder judged ≤ `maxDurationSeconds` AND (no actions estimate, or `consentedActions ≤ maxActions`) ⇒ `auto`, stamped on the run as `consent: { approvedBy: 'system:policy', via: 'autonomy', envelope }` and audited as `workflow.run.autonomy_applied` with `wouldHaveAsked[]`. An estimate over `maxActions` is itself an `ask` even when steps, credits and duration are inside. **Goal runs and batch starts never auto-start** — those legs do not pass the verdict to `decide()`. The hourly allowance is a token bucket per org + agent (`wf:org::autonomy:`, capacity `maxRunsPerHour`, refill `maxRunsPerHour/3600` per second), consulted only on a flip; an empty bucket — or Valkey unavailable — turns the flip **back into `ask`** (the run parks for a person and nothing is stamped), never into a refuse.
+
+CLI: `lua workflows policy autonomy get` — ONE request with `?effective=true`, printing the STORED block an administrator wrote and the EFFECTIVE envelope the server resolved (org narrowed by agent, defaults applied, ceilings clamped) side by side; `enabled` not true ⇒ "nothing is pre-consented". `lua workflows policy autonomy set --enabled on|off --max-credits  --max-steps  --max-duration  --max-actions  --max-runs-per-hour  --forms graph,script,static --clear ` — only the named members are sent; `--clear` sends `null` so the platform default applies again (naming a member on both sides is exit 2); `--max-duration` takes seconds (`--max-duration-seconds` is `raise-budget`'s flag and bounds one run, not an envelope); a ceiling is the server's to refuse (typed 400, printed verbatim); `--agent ` is registered only to be **refused** with the explanation that no route writes a per-agent envelope. `lua workflows status ` prints `Consent:  auto (policy) — ≤ 20 credits · 15 steps · 1 d` for an autonomous start (the numbers are the stamped envelope; `maxActions` / `maxRunsPerHour` / `forms` are admission rules and are not on the line) and **nothing** for a human-cleared gate, an older run or an older server; `--json` carries `consent { approvedBy, at, approvalLinkId?, via: 'human' | 'autonomy', envelope? }`.
+
+**Approver fallback** (hotfix H8; ⏳ 3.36.0+ for the line) — an `approval` node declaring `approver: 'creator'` (or none) with `excludeInitiator: true` used to fail the step `no_approver` and ask nobody; the resolution now escalates to the org's admins and stamps `suspend.approverFallback { from, to, reason }`, and `status --steps` prints `⇅ : approver escalated  →  — the initiator is excluded (maker-checker)` (only when the server projects the member).
+
 ---
 
 ## 4. Job tier, workspaces, coding turns
@@ -186,7 +214,7 @@ await Workflows.list({ workflow: 'outreach', status: 'failed', limit: 20, sort:
 ```
 lua workflows list [--all]                         lua workflows view  [--json]        lua workflows versions 
 lua workflows run  …                         ≡ lua test workflow --name  …       (offline local driver — no API call)
-lua push workflow --name  [--set-version x.y.z] [--force]   creates a version (not live); resolves env.template keys from env/.env (missing ⇒ env-template-missing, exit 1)
+lua push workflow --name  [--set-version x.y.z] [--force] [--apply-effort ⏳]   creates a version (not live); resolves env.template keys from env/.env (missing ⇒ env-template-missing, exit 1); --apply-effort stamps luaWorkflow: 2 so each agent step's `effort` is sent to the model from this version on (§2)
 lua workflows env-overlay  -v latest         presence table of env.template keys
 lua workflows deploy  -v           makes a version live   (`lua deploy` has no workflow type)
 lua workflows activate|deactivate  [-v]      enable/pause schedules + triggers (activate -v also deploys)
@@ -205,9 +233,14 @@ lua workflows delete  [--yes] [--force]                     lua workflows
 lua workflows archive-runs --since 8d --out ./archive [--until iso] [--workflow n] [--concurrency ≤5] [--no-inputs] [--no-artefacts]
 lua workflows workspace  [--release]   lua workflows jobs    lua workflows job-logs   [--attempt n] [--tail ≤2000] [--follow]
 lua workflows schedules list|create|patch|pause|resume|delete …    lua workflows goals list|get|create|edit|raise|pause|resume|close …
+⏳ requires lua-cli 3.36.0 or later (unknown action / option below it ⇒ exit 2):
+lua workflows policy models get|set [--compose on|off] [--max-class fast|balanced|strong] [--consent-actions n] [--allow codes] [--class-fast|--class-balanced|--class-strong codes] [--class-map task=class,…] [--pins class-only|allowed] [--fallback same-class|same-provider]   (§2)
+lua workflows policy autonomy get|set [--enabled on|off] [--max-credits n] [--max-steps n] [--max-duration seconds] [--max-actions n] [--max-runs-per-hour n] [--forms graph,script,static] [--clear keys]   (§3)
+lua workflows clear-gate  --kind model_policy   (alias ungate)      lua workflows recompose    (alias recompile; a new version of a chat-composed definition)
+lua models list --workflows [--json]                                     lua push workflow --name  --apply-effort
 ```
 
-Exit codes: `0` ok · `1` API refusal (4xx other than 404) · `2` usage · `3` not found · `4` run failed / timed out · `5` run cancelled · `6` run gated (consent) · `7` `--timeout` reached · `8` run parked waiting for a human (`start --follow`/`watch` exit here unless `--wait-for-human`) · `9` auth · `10` forbidden · `11` unavailable · `12` provider rejected. `--json` prints `{ success, data }` or `{ success:false, error:{ code, statusCode?, message, issues? } }`.
+Exit codes: `0` ok · `1` API refusal (4xx other than 404) · `2` usage · `3` not found · `4` run failed / timed out · `5` run cancelled · `6` run gated (consent — and ⏳ 3.36.0+ `status --strict` on a gated run, which exited 0 before) · `7` `--timeout` reached · `8` run parked waiting for a human (`start --follow`/`watch` exit here unless `--wait-for-human`) · `9` auth · `10` forbidden · `11` unavailable · `12` provider rejected. `--json` prints `{ success, data }` or `{ success:false, error:{ code, statusCode?, message, issues? } }`.
 
 ### Offline runner flags (`lua test workflow` / `lua workflows run`)
 
@@ -220,9 +253,9 @@ Exit codes: `0` ok · `1` API refusal (4xx other than 404) · `2` usage · `3` n
 1. Write `src/workflows/.ts`; export the const; register in `src/index.ts` `workflows: [...]`.
 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`.
+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`; `lua workflows replay  --local` checks the run against your compiled artifact.
+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.
 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.
@@ -259,3 +292,8 @@ Chat-composed ("dynamic") workflows cannot be deployed from the CLI (`WORKFLOW_D
 | `WORKFLOW_DYNAMIC` (409 on deploy) | chat-composed workflow — recompose in chat or export to source |
 | `RUNS_IN_FLIGHT` (409 on start) | `concurrencyPolicy:'forbid'` and a run is live — produced today only by scheduled, compose-tool and batch starts; `lua workflows start` / `Workflows.start` do not check the policy (§1) |
 | `SCRIPT_META_INVALID{…}`, `SCRIPT_NONDETERMINISM{…}`, `SCRIPT_IMPORT_FORBIDDEN` | script-form lint (§5) |
+| ⏳ `model-class-unknown` / `task-class-unknown` / `model-trait-unknown` / `requires-invalid` / `effort-unknown` / `model-reason-too-long` (push, exit 1, `issues[]`, nothing sent) | a value outside the vocabulary — classes `class/fast\|balanced\|strong`, task classes `classify extract transform draft research reason code judge`, traits `vision structured largeContext codeExecution`, efforts `low medium high`, reason ≤ 160 chars (§2) |
+| ⏳ `task-class-without-model` (push, server, static definitions only) | add `model: 'class/'` (or an approved code) to every agent step that names a `taskClass` — `lua compile` does not catch it (§2) |
+| ⏳ `model-class-resolution-off` (push, server) | this environment has model classes switched off: pin an approved code or drop `model`, or ask an administrator to enable them |
+| ⏳ run `suspended` with `gate.kind: 'model_policy'` | the class cannot be resolved under the current policy (`lua workflows policy models get` — `maxClass`, `allow`, `classes`); fix the policy or `lua workflows clear-gate  --kind model_policy` (§2) |
+| ⏳ `RECOMPOSE_NOT_APPLICABLE` (409) | `lua workflows recompose` on a definition with no active version / no graph — nothing to rewrite |
diff --git a/plugins/lua-agent-builder/lib/permissions-template.json b/plugins/lua-agent-builder/lib/permissions-template.json
index d444e2d..46b61e5 100644
--- a/plugins/lua-agent-builder/lib/permissions-template.json
+++ b/plugins/lua-agent-builder/lib/permissions-template.json
@@ -1,5 +1,5 @@
 {
-  "_comment": "Permission rules the plugin REQUIRES for the §3.7 single-permission contract to function. Plugin-level settings.json's `permissions` block is silently ignored by Claude Code, so these rules can't ship as plugin defaults. /lua-doctor offers to merge this into the user's project `.claude/settings.json` on first run; the user accepts once and the rules persist for the project. Every command shape here is verified against lua-cli 3.33.0 (its src/cli/command-definitions.ts and src/utils/aliases.ts). HOW THE PRODUCTION GATE WORKS (verified live against Claude Code on 2026-09-12 and documented at code.claude.com/docs/en/permissions: 'A deny or ask rule matches past any leading assignment' and 'Hook decisions don't bypass permission rules'): the bare production verbs (`lua deploy …`, `lua version promote …`, …) are deliberately NOT listed in `deny` or `ask` — such a rule also matches the user-confirmed form `LUA_DEPLOY_CONFIRMED=1 lua deploy …` and would make every deploy impossible. The gate for the bare forms is hooks/confirm-deploy.mjs (a PreToolUse exit-2 block wins over any allow rule, including a broad `Bash(lua *)` in your own settings); the `allow` entries below are the literal prefixed forms the deploy flow emits after your single confirmation, so they run without a second prompt. A bare verb that somehow reaches the permission layer falls to Claude Code's default (a prompt; a denial in `-p` mode). The alternative binaries `heylua` and `lua-ai` are the same program and are denied wholesale — the plugin only ever emits `lua`. test/lib/permissions-mirror.test.mjs fails if any deny/ask rule would shadow a confirmed form or any allow rule admits a bare one. Precedence is deny → ask → allow. The `ask` tier IS the single confirmation for workflow run-control verbs (start/approve/signal/cancel…): /lua-workflow relies on this prompt and does not AskUserQuestion on top. /lua-env (`lua env *` — deliberately ask even for `--list`, since the CLI prints masked values) and /lua-integrations (connect|update|disconnect|convert, webhooks create|pause|resume|delete, mcp activate|deactivate) rely on the same prompt. MCP: Claude Code names a plugin's MCP tools mcp__plugin____ (verified live 2026-09-12), so the read-only lua-platform server is allowed as mcp__plugin_lua-agent-builder_lua-platform (all five tools are GET-only) plus the two docs search tools; submit_feedback is deliberately not pre-approved. The bare mcp__lua-platform / mcp__lua-docs spellings cover a server the user registered with `claude mcp add`.",
+  "_comment": "Permission rules the plugin REQUIRES for the §3.7 single-permission contract to function. Plugin-level settings.json's `permissions` block is silently ignored by Claude Code, so these rules can't ship as plugin defaults. /lua-doctor offers to merge this into the user's project `.claude/settings.json` on first run; the user accepts once and the rules persist for the project. Every command shape here is verified against lua-cli 3.33.0 (its src/cli/command-definitions.ts and src/utils/aliases.ts); the workflows policy / clear-gate / recompose rules against lua-cli 3.36.0. HOW THE PRODUCTION GATE WORKS (verified live against Claude Code on 2026-09-12 and documented at code.claude.com/docs/en/permissions: 'A deny or ask rule matches past any leading assignment' and 'Hook decisions don't bypass permission rules'): the bare production verbs (`lua deploy …`, `lua version promote …`, …) are deliberately NOT listed in `deny` or `ask` — such a rule also matches the user-confirmed form `LUA_DEPLOY_CONFIRMED=1 lua deploy …` and would make every deploy impossible. The gate for the bare forms is hooks/confirm-deploy.mjs (a PreToolUse exit-2 block wins over any allow rule, including a broad `Bash(lua *)` in your own settings); the `allow` entries below are the literal prefixed forms the deploy flow emits after your single confirmation, so they run without a second prompt. A bare verb that somehow reaches the permission layer falls to Claude Code's default (a prompt; a denial in `-p` mode). The alternative binaries `heylua` and `lua-ai` are the same program and are denied wholesale — the plugin only ever emits `lua`. test/lib/permissions-mirror.test.mjs fails if any deny/ask rule would shadow a confirmed form or any allow rule admits a bare one. Precedence is deny → ask → allow. The `ask` tier IS the single confirmation for workflow run-control verbs (start/approve/signal/cancel…): /lua-workflow relies on this prompt and does not AskUserQuestion on top. lua-cli 3.36.0 adds `lua workflows policy models|autonomy get|set` (an ORGANIZATION-wide policy — `get` is read-only and allowed, `set` asks: `policy autonomy set --enabled on` decides which workflow starts skip the consent card), `clear-gate` (alias `ungate`; clears a `model_policy` park — run control, asks) and `recompose` (alias `recompile`; publishes a new version of a chat-composed definition — asks). /lua-env (`lua env *` — deliberately ask even for `--list`, since the CLI prints masked values) and /lua-integrations (connect|update|disconnect|convert, webhooks create|pause|resume|delete, mcp activate|deactivate) rely on the same prompt. MCP: Claude Code names a plugin's MCP tools mcp__plugin____ (verified live 2026-09-12), so the read-only lua-platform server is allowed as mcp__plugin_lua-agent-builder_lua-platform (all five tools are GET-only) plus the two docs search tools; submit_feedback is deliberately not pre-approved. The bare mcp__lua-platform / mcp__lua-docs spellings cover a server the user registered with `claude mcp add`.",
   "permissions": {
     "allow": [
       "Bash(lua --version)",
@@ -60,6 +60,7 @@
       "Bash(lua workflows schedules list*)",
       "Bash(lua workflows goals list*)",
       "Bash(lua workflows goals get *)",
+      "Bash(lua workflows policy * get*)",
       "Bash(lua version list*)",
       "Bash(lua version show *)",
       "Bash(lua version diff *)",
@@ -133,6 +134,11 @@
       "Bash(lua workflows archive-runs*)",
       "Bash(lua workflows schedules *)",
       "Bash(lua workflows goals *)",
+      "Bash(lua workflows policy * set*)",
+      "Bash(lua workflows clear-gate *)",
+      "Bash(lua workflows ungate *)",
+      "Bash(lua workflows recompose *)",
+      "Bash(lua workflows recompile *)",
       "Bash(lua jobs trigger *)",
       "Bash(lua jobs activate *)",
       "Bash(lua jobs deactivate *)",
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 237ea20..506d32e 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.2.2"},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.2.2"},{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.2.2",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.2.2",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,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3NlcnZlci5tanMiLCAiLi4vc3JjL3Rvb2xzL2luZGV4Lm1qcyIsICIuLi9zcmMvcnVuLWx1YS5tanMiLCAiLi4vc3JjL3Rvb2xzL2xpc3QtYWdlbnRzLm1qcyIsICIuLi9zcmMvdG9vbHMvZ2V0LWFnZW50Lm1qcyIsICIuLi9zcmMvYXV0aC5tanMiLCAiLi4vc3JjL2FwaS1jbGllbnQubWpzIiwgIi4uL3NyYy9yZXNwb25zZS1zaGFwZXMubWpzIiwgIi4uL3NyYy90b29scy9saXN0LXByaW1pdGl2ZS12ZXJzaW9ucy5tanMiLCAiLi4vc3JjL3Rvb2xzL2dldC1kZXBsb3ltZW50LXN0YXR1cy5tanMiLCAiLi4vc3JjL3Rvb2xzL3RhaWwtbG9ncy5tanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8vIE1DUCBzdGRpbyBzZXJ2ZXIgYm9vdHN0cmFwLiBQZXIgdGVjaCBzcGVjIFx1MDBBNzguMS5cblxuaW1wb3J0IHsgU2VydmVyIH0gZnJvbSAnQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zZXJ2ZXIvaW5kZXguanMnO1xuaW1wb3J0IHsgU3RkaW9TZXJ2ZXJUcmFuc3BvcnQgfSBmcm9tICdAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NlcnZlci9zdGRpby5qcyc7XG5pbXBvcnQge1xuICBDYWxsVG9vbFJlcXVlc3RTY2hlbWEsXG4gIExpc3RUb29sc1JlcXVlc3RTY2hlbWEsXG59IGZyb20gJ0Btb2RlbGNvbnRleHRwcm90b2NvbC9zZGsvdHlwZXMuanMnO1xuaW1wb3J0ICogYXMgdG9vbHMgZnJvbSAnLi90b29scy9pbmRleC5tanMnO1xuXG5jb25zdCBUT09MX1JFR0lTVFJZID0gT2JqZWN0LnZhbHVlcyh0b29scyk7XG5cbmNvbnN0IHNlcnZlciA9IG5ldyBTZXJ2ZXIoXG4gIHsgbmFtZTogJ2x1YS1wbGF0Zm9ybScsIHZlcnNpb246ICcxLjIuMicgfSxcbiAgeyBjYXBhYmlsaXRpZXM6IHsgdG9vbHM6IHt9IH0gfVxuKTtcblxuc2VydmVyLnNldFJlcXVlc3RIYW5kbGVyKExpc3RUb29sc1JlcXVlc3RTY2hlbWEsIGFzeW5jICgpID0+ICh7XG4gIHRvb2xzOiBUT09MX1JFR0lTVFJZLm1hcCgodCkgPT4gdC5zcGVjKSxcbn0pKTtcblxuc2VydmVyLnNldFJlcXVlc3RIYW5kbGVyKENhbGxUb29sUmVxdWVzdFNjaGVtYSwgYXN5bmMgKHJlcSkgPT4ge1xuICBjb25zdCB0b29sID0gVE9PTF9SRUdJU1RSWS5maW5kKCh0KSA9PiB0LnNwZWMubmFtZSA9PT0gcmVxLnBhcmFtcy5uYW1lKTtcbiAgaWYgKCF0b29sKSB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdG9vbDogJHtyZXEucGFyYW1zLm5hbWV9YCk7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHRvb2wuaGFuZGxlcihyZXEucGFyYW1zLmFyZ3VtZW50cyA/PyB7fSk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbeyB0eXBlOiAndGV4dCcsIHRleHQ6IGBFcnJvcjogJHtlcnIubWVzc2FnZX1gIH1dLFxuICAgICAgaXNFcnJvcjogdHJ1ZSxcbiAgICB9O1xuICB9XG59KTtcblxuLy8gXHUwMEE3MTkuNiBjcmFzaCByZXBvcnRpbmcgXHUyMDE0IG11c3QgbGFuZCBCRUZPUkUgcHJvY2VzcyBleGl0IHNvIHRoZSBldmVudCByZWFjaGVzXG4vLyB0ZWxlbWV0cnkuIFdpbmRvd3MgY2FuIGRyb3AgdGhlIGxhc3Qgc3RkZXJyIHdyaXRlIGlmIHByb2Nlc3MuZXhpdCBmaXJlc1xuLy8gc3luY2hyb25vdXNseSBhZnRlciBpdDsgc2FtZSBidWcgY2xhc3MgYXMgbGliL2hvb2stcnVudGltZS5tanMncyBleGl0KCkuXG4vLyBFeGl0IG9ubHkgaW5zaWRlIHRoZSB3cml0ZSBjYWxsYmFjayBzbyB0aGUgZmx1c2ggY29tcGxldGVzLlxuZnVuY3Rpb24gcmVwb3J0Q3Jhc2hBbmRFeGl0KHBheWxvYWQpIHtcbiAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkgKyAnXFxuJywgKCkgPT4gcHJvY2Vzcy5leGl0KDEpKTtcbn1cblxucHJvY2Vzcy5vbigndW5jYXVnaHRFeGNlcHRpb24nLCAoZXJyKSA9PiB7XG4gIHJlcG9ydENyYXNoQW5kRXhpdCh7XG4gICAgZXZlbnQ6ICdtY3Bfc2VydmVyX2NyYXNoJyxcbiAgICBraW5kOiAndW5jYXVnaHRFeGNlcHRpb24nLFxuICAgIG1lc3NhZ2U6IGVycj8ubWVzc2FnZSxcbiAgICBzdGFjazogZXJyPy5zdGFjayxcbiAgICBwbHVnaW5fdmVyc2lvbjogJzEuMi4yJyxcbiAgICBsdWFfY2xpX3ZlcnNpb246IHByb2Nlc3MuZW52LkxVQV9DTElfVkVSU0lPTiA/PyBudWxsLFxuICAgIHBsYXRmb3JtOiBwcm9jZXNzLnBsYXRmb3JtLFxuICAgIHRzOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gIH0pO1xufSk7XG5cbnByb2Nlc3Mub24oJ3VuaGFuZGxlZFJlamVjdGlvbicsIChyZWFzb24pID0+IHtcbiAgcmVwb3J0Q3Jhc2hBbmRFeGl0KHtcbiAgICBldmVudDogJ21jcF9zZXJ2ZXJfY3Jhc2gnLFxuICAgIGtpbmQ6ICd1bmhhbmRsZWRSZWplY3Rpb24nLFxuICAgIHJlYXNvbjogU3RyaW5nKHJlYXNvbiksXG4gICAgc3RhY2s6IC8qKiBAdHlwZSB7YW55fSAqLyAocmVhc29uKT8uc3RhY2ssXG4gICAgcGx1Z2luX3ZlcnNpb246ICcxLjIuMicsXG4gICAgbHVhX2NsaV92ZXJzaW9uOiBwcm9jZXNzLmVudi5MVUFfQ0xJX1ZFUlNJT04gPz8gbnVsbCxcbiAgICBwbGF0Zm9ybTogcHJvY2Vzcy5wbGF0Zm9ybSxcbiAgICB0czogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICB9KTtcbn0pO1xuXG5hd2FpdCBzZXJ2ZXIuY29ubmVjdChuZXcgU3RkaW9TZXJ2ZXJUcmFuc3BvcnQoKSk7XG4iLCAiZXhwb3J0IHsgbGlzdEFnZW50cyB9IGZyb20gJy4vbGlzdC1hZ2VudHMubWpzJztcbmV4cG9ydCB7IGdldEFnZW50IH0gZnJvbSAnLi9nZXQtYWdlbnQubWpzJztcbmV4cG9ydCB7IGxpc3RQcmltaXRpdmVWZXJzaW9ucyB9IGZyb20gJy4vbGlzdC1wcmltaXRpdmUtdmVyc2lvbnMubWpzJztcbmV4cG9ydCB7IGdldERlcGxveW1lbnRTdGF0dXMgfSBmcm9tICcuL2dldC1kZXBsb3ltZW50LXN0YXR1cy5tanMnO1xuZXhwb3J0IHsgdGFpbExvZ3MgfSBmcm9tICcuL3RhaWwtbG9ncy5tanMnO1xuLy8gY2hlY2tfZHJpZnQgcmVtb3ZlZCBpbiB2MS4yNSBcdTIwMTQgdXNlIEJhc2gobHVhIHN5bmMgLS1jaGVjaykgZGlyZWN0bHkuIFRoZVxuLy8gTUNQIHNlcnZlciBpcyBsb2NhbCBhbmQgc28gaXMgdGhlIENMSTsgcmVpbXBsZW1lbnRpbmcgZHJpZnQgZGV0ZWN0aW9uXG4vLyBzZXJ2ZXItc2lkZSBvciBpbiB0aGUgTUNQIHdvdWxkIGR1cGxpY2F0ZSBsb2dpYyB0aGF0IGx1YS1jbGkgYWxyZWFkeSBvd25zLlxuIiwgIi8vIFNoYXJlZCBzdWJwcm9jZXNzIGhlbHBlciBmb3IgdG9vbHMgdGhhdCBzaGVsbCBvdXQgdG8gdGhlIGx1YS1jbGkgYmluYXJ5LlxuLy9cbi8vIFdoeSBzaGVsbCBvdXQgYXQgYWxsOiB0aGVyZSBpcyBubyBcImxpc3QgZXZlcnkgYWdlbnQgdGhpcyBjcmVkZW50aWFsIGNhblxuLy8gcmVhY2hcIiBSRVNUIHJvdXRlIFx1MjAxNCBgbHVhIGFnZW50cyAtLWpzb25gIGFscmVhZHkgZG9lcyB0aGUgY3JlZGVudGlhbC10by1cbi8vIGF1dGhvcml6YXRpb24tcHJvamVjdGlvbiByZXNvbHV0aW9uIChQUk8tMTcxMikgZm9yIGV2ZXJ5IGNyZWRlbnRpYWwgY2xhc3Ncbi8vIChBUEkga2V5LCB0eXBlZCBzY29wZWQga2V5LCByZW5ld2FibGUgc2Vzc2lvbikuIFJlaW1wbGVtZW50aW5nIHRoYXQgaW4gdGhlXG4vLyBNQ1Agd291bGQgZHVwbGljYXRlIGxvZ2ljIGx1YS1jbGkgb3ducy5cblxuaW1wb3J0IHsgc3Bhd24gfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnO1xuXG4vLyBgbHVhIGFnZW50c2Agd2Fsa3MgZXZlcnkgb3JnYW5pc2F0aW9uIHRoZSBjcmVkZW50aWFsIGNhbiBzZWUgYW5kLCBmb3IgYVxuLy8gc2Vzc2lvbiBsb2dpbiwgcmVmcmVzaGVzIHRoZSBzZXNzaW9uIGZpcnN0LiBNZWFzdXJlZCAyMDI2LTA5LTEyIG9uIGFcbi8vIDE0NC1vcmcgYWNjb3VudDogMThcdTIwMTMyNSBzLiBUaGUgYnVkZ2V0IG11c3QgY292ZXIgdGhhdC5cbmNvbnN0IERFRkFVTFRfVElNRU9VVF9NUyA9IDYwXzAwMDtcblxuLyoqXG4gKiBSdW4gYGx1YSA8YXJncz5gIGFuZCByZXNvbHZlIHdpdGggaXRzIHN0ZG91dC5cbiAqXG4gKiBPbiBXaW5kb3dzIHRoZSBucG0gYmluIGlzIGEgYGx1YS5jbWRgIHNoaW0sIHdoaWNoIE5vZGUgKFx1MjI2NTE4LjIwIC8gXHUyMjY1MjAuMTIpXG4gKiByZWZ1c2VzIHRvIHNwYXduIHdpdGhvdXQgYSBzaGVsbDsgdGhlIGFyZ3MgYXJlIGZpeGVkIGxpdGVyYWxzIChubyB1c2VyXG4gKiBpbnB1dCksIHNvIGBzaGVsbDogdHJ1ZWAgdGhlcmUgaXMgc2FmZS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBhcmdzXG4gKiBAcGFyYW0ge3tzcGF3bkZuPzogdHlwZW9mIHNwYXduLCB0aW1lb3V0TXM/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/OiBvYmplY3QsIHF1ZXJ5PzogUmVjb3JkPHN0cmluZyxzdHJpbmd8bnVtYmVyPiwgZmV0Y2hGbj86IHR5cGVvZiBmZXRjaCwgYmFzZVVybD86IHN0cmluZywgdGltZW91dE1zPzogbnVtYmVyfX0gW29wdHNdXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhcGlSZXF1ZXN0KHBhdGgsIHtcbiAgbWV0aG9kID0gJ0dFVCcsXG4gIGJvZHksXG4gIHF1ZXJ5LFxuICBmZXRjaEZuID0gZ2xvYmFsVGhpcy5mZXRjaCxcbiAgYmFzZVVybCA9IHByb2Nlc3MuZW52LkxVQV9BUElfVVJMIHx8IERFRkFVTFRfQkFTRV9VUkwsXG4gIHRpbWVvdXRNcyA9IERFRkFVTFRfVElNRU9VVF9NUyxcbn0gPSB7fSkge1xuICBjb25zdCBhcGlLZXkgPSBhd2FpdCByZXNvbHZlQXBpS2V5KCk7XG4gIC8vIEpvaW4gYnkgc3RyaW5nIGNvbmNhdGVuYXRpb24sIE5PVCBgbmV3IFVSTChwYXRoLCBiYXNlVXJsKWA6IHRoZSBXSEFUV0dcbiAgLy8gcmVzb2x2ZXIgdHJlYXRzIGEgbGVhZGluZy1zbGFzaCBwYXRoIGFzIGhvc3QtYWJzb2x1dGUgYW5kIHdvdWxkIGRyb3AgYW55XG4gIC8vIHBhdGggcHJlZml4IG9uIExVQV9BUElfVVJMIChodHRwczovL2hvc3QvYXBpICsgL2RldmVsb3Blci94IFx1MjE5MlxuICAvLyBodHRwczovL2hvc3QvZGV2ZWxvcGVyL3gpLiBgcGF0aGAgYWx3YXlzIHN0YXJ0cyB3aXRoICcvJywgc28gc3RyaXAgb25lXG4gIC8vIHRyYWlsaW5nIHNsYXNoIGZyb20gdGhlIGJhc2UgYW5kIGNvbmNhdGVuYXRlLlxuICBjb25zdCB1cmwgPSBuZXcgVVJMKGJhc2VVcmwucmVwbGFjZSgvXFwvJC8sICcnKSArIHBhdGgpO1xuICBpZiAocXVlcnkpIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKHF1ZXJ5KSkgdXJsLnNlYXJjaFBhcmFtcy5zZXQoaywgU3RyaW5nKHYpKTtcblxuICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4gY29udHJvbGxlci5hYm9ydCgpLCB0aW1lb3V0TXMpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgZmV0Y2hGbih1cmwudG9TdHJpbmcoKSwge1xuICAgICAgbWV0aG9kLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnQXV0aG9yaXphdGlvbic6IGBCZWFyZXIgJHthcGlLZXl9YCxcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgJ1gtTHVhLUNsaWVudCc6ICdjbGF1ZGUtcGx1Z2luLzEuMi4yJyxcbiAgICAgIH0sXG4gICAgICBib2R5OiBib2R5ID8gSlNPTi5zdHJpbmdpZnkoYm9keSkgOiB1bmRlZmluZWQsXG4gICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgIH0pO1xuXG4gICAgaWYgKHJlcy5zdGF0dXMgPT09IDQwMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnTUNQX0FVVEhfU1RBTEU6IGx1YS1hcGkgcmV0dXJuZWQgNDAxLiBUaGUgY3JlZGVudGlhbCBpcyBtaXNzaW5nLCBleHBpcmVkLCBvciB0aGUgc2Vzc2lvbiB3YXMgc2lnbmVkIG91dCAnICtcbiAgICAgICAgJyhzaWduaW5nIG91dCBvZiB0aGUgTHVhIGRhc2hib2FyZCBvciBhcHBzIGFsc28gZW5kcyBDTEkgc2Vzc2lvbnMpLiBSdW4gYGx1YSBhdXRoIGNvbmZpZ3VyZWAgaW4gYSB0ZXJtaW5hbCwgJyArXG4gICAgICAgICdvciByZS1ydW4gL2x1YS1kb2N0b3IuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHJlcy5zdGF0dXMgPT09IDQwMykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgTUNQX0ZPUkJJRERFTjogbHVhLWFwaSByZXR1cm5lZCA0MDMgZm9yICR7cGF0aH0uIFRoZSBjcmVkZW50aWFsIGNhbm5vdCBhY2Nlc3MgdGhpcyBhZ2VudCBvciBvcmcsIG9yIGl0IGxhY2tzIGAgK1xuICAgICAgICBgdGhlIHJvdXRlIHNjb3BlICgke1JPVVRFX1NDT1BFX1NVTU1BUll9IFx1MjAxNCB0eXBlZCBrZXlzIGFyZSBzY29wZWQgdG8gdGhlIGFnZW50cyBhbmQgcm9sZSBjaG9zZW4gYXQgYCArXG4gICAgICAgICdgbHVhIGF1dGggY29uZmlndXJlYCkuIFJlLXJ1biAvbHVhLWRvY3RvciBvciBjaGVjayB0aGUgTFVBX0FQSV9LRVkgZW52IHZhci4nXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIXJlcy5vaykge1xuICAgICAgLy8gVHJ5IHRvIHBhcnNlIGx1YS1hcGkncyBzdHJ1Y3R1cmVkIGVycm9yIGVudmVsb3BlOlxuICAgICAgLy8gICB7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogeyBtZXNzYWdlLCBzdGF0dXNDb2RlLCBjb2RlPywgLi4uIH0gfVxuICAgICAgLy8gRmFsbHMgYmFjayB0byByYXcgdGV4dCBvbiBwYXJzZSBmYWlsdXJlIChlLmcuIHByb3h5IDUwMiB3aXRoIEhUTUwgYm9keSkuXG4gICAgICBjb25zdCByYXcgPSBhd2FpdCByZXMudGV4dCgpO1xuICAgICAgbGV0IGZyaWVuZGx5TXNnID0gcmF3O1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShyYXcpO1xuICAgICAgICBmcmllbmRseU1zZyA9IHBhcnNlZD8uZXJyb3I/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.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=
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 238ed41..ca2bb2c 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.2.2",
+  "version": "1.3.0",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "@lua/claude-plugin-mcp",
-      "version": "1.2.2",
+      "version": "1.3.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 8e1de9d..e70d60c 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.2.2",
+  "version": "1.3.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 68997df..4e8f5fb 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.2.2',
+        'X-Lua-Client': 'claude-plugin/1.3.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 7382600..c09f760 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.2.2' },
+  { name: 'lua-platform', version: '1.3.0' },
   { capabilities: { tools: {} } }
 );
 
@@ -46,7 +46,7 @@ process.on('uncaughtException', (err) => {
     kind: 'uncaughtException',
     message: err?.message,
     stack: err?.stack,
-    plugin_version: '1.2.2',
+    plugin_version: '1.3.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.2.2',
+    plugin_version: '1.3.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 d3f8204..c3cc746 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.2.2",
+  "version": "1.3.0",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "claude-code-lua-plugin",
-      "version": "1.2.2",
+      "version": "1.3.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 620c79b..dd23028 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.2.2",
+  "version": "1.3.0",
   "description": "Plugin assets for the lua-agent-builder Claude Code plugin",
   "private": true,
   "type": "module",
diff --git a/plugins/lua-agent-builder/scripts/lint-cli-flags.mjs b/plugins/lua-agent-builder/scripts/lint-cli-flags.mjs
index 64ee89c..c426017 100644
--- a/plugins/lua-agent-builder/scripts/lint-cli-flags.mjs
+++ b/plugins/lua-agent-builder/scripts/lint-cli-flags.mjs
@@ -53,6 +53,12 @@ const DENY = [
   { pattern: 'User.update(', reason: 'fetch the instance first: `(await User.get(id)).update({...})`' },
   { pattern: "type: 'cron', pattern", reason: 'JobSchedule uses `expression`, not `pattern`' },
   { pattern: 'intervalMs', reason: 'JobSchedule interval uses `seconds`' },
+  // lua-cli 3.36.0 (`policy autonomy set`, commands/workflows.ts `buildAutonomyPolicyPatch`):
+  // the envelope's duration flag is `--max-duration `; `--max-duration-seconds` belongs to
+  // `raise-budget` and bounds ONE run. `--agent` is registered only so the verb can refuse it — no
+  // route writes a per-agent envelope (the sub-agent PATCH discards `workflows`).
+  { pattern: 'policy autonomy set --max-duration-seconds', reason: 'the envelope flag is `--max-duration `; `--max-duration-seconds` is `raise-budget`\'s' },
+  { pattern: 'policy autonomy set --agent', reason: '`--agent` is refused: no route writes a per-agent autonomy envelope — set the organization\'s with `lua workflows policy autonomy set …`' },
   { pattern: 'lua auth configure --email', reason: 'email and OTP input must stay in a private terminal', authFlow: true },
   { pattern: 'lua auth configure --api-key', reason: 'credentials must stay out of the model conversation', authFlow: true },
 ];
diff --git a/plugins/lua-agent-builder/scripts/lint-knowledge-commands.mjs b/plugins/lua-agent-builder/scripts/lint-knowledge-commands.mjs
index e111865..c4d414c 100644
--- a/plugins/lua-agent-builder/scripts/lint-knowledge-commands.mjs
+++ b/plugins/lua-agent-builder/scripts/lint-knowledge-commands.mjs
@@ -52,9 +52,10 @@ function setSub(parent, set) {
   for (const s of set) SUBCOMMANDS[parent].add(s);
 }
 
-// Hand-curated from command-definitions.ts / aliases.ts (lua-cli 3.33.0); the
-// lint won't try to parse free text exhaustively (too brittle). Update when
-// commands gain/lose actions.
+// Hand-curated from command-definitions.ts / aliases.ts (lua-cli 3.33.0, plus
+// the `workflows` verbs of lua-cli 3.36.0 — `policy`, `clear-gate`,
+// `recompose`, aliases.ts `workflows.action`); the lint won't try to parse free
+// text exhaustively (too brittle). Update when commands gain/lose actions.
 setSub('auth',         ['configure', 'logout', 'key', 'sessions']);
 setSub('chat',         ['clear']);
 setSub('integrations', ['connect', 'update', 'list', 'available', 'info', 'disconnect', 'convert', 'webhooks', 'triggers', 'mcp']);
@@ -83,7 +84,11 @@ setSub('skills',       ['sandbox', 'staging', 'production', 'view', 'versions',
 setSub('workflows',    ['list', 'view', 'versions', 'deploy', 'activate', 'deactivate', 'start', 'run', 'runs', 'status',
                         'watch', 'cancel', 'resume', 'retry-step', 'resolve-step', 'raise-budget', 'approve', 'approval-payload',
                         'signal', 'replay', 'logs', 'delete', 'delete-run', 'env-overlay', 'export', 'archive-runs',
-                        'workspace', 'jobs', 'job-logs', 'goals', 'schedules']);
+                        'workspace', 'jobs', 'job-logs', 'goals', 'schedules',
+                        // lua-cli 3.36.0 (WMC-E7 / WMC-A6): the org's model and autonomy
+                        // policy (`policy models|autonomy get|set`), the `model_policy` gate, and the
+                        // deterministic rewrite of a chat-composed definition.
+                        'policy', 'clear-gate', 'recompose']);
 setSub('test',         ['skill', 'webhook', 'job', 'preprocessor', 'postprocessor', 'workflow']);
 setSub('push',         ['skill', 'agent', 'persona', 'webhook', 'trigger', 'job', 'preprocessor', 'postprocessor', 'mcp',
                         'device', 'device-trigger', 'voice', 'workflow', 'backup', 'all']);
diff --git a/plugins/lua-agent-builder/test/hooks/check-lua-version.test.mjs b/plugins/lua-agent-builder/test/hooks/check-lua-version.test.mjs
index e040639..4547c32 100644
--- a/plugins/lua-agent-builder/test/hooks/check-lua-version.test.mjs
+++ b/plugins/lua-agent-builder/test/hooks/check-lua-version.test.mjs
@@ -64,6 +64,7 @@ describe('check-lua-version decide()', () => {
     expect(result?.warn).toContain(`requires lua-cli ≥${PINNED_MIN_LUA_CLI}`);
     expect(result?.warn).toContain(`you have ${tooOld}`);
     expect(result?.warn).toContain('/lua-update');
+    expect(result?.warn).toContain('npm i -g lua-cli@latest');
   });
 
   test('warns when lua --version exits non-zero', () => {
diff --git a/plugins/lua-agent-builder/test/lib/permissions-mirror.test.mjs b/plugins/lua-agent-builder/test/lib/permissions-mirror.test.mjs
index 933f904..575764e 100644
--- a/plugins/lua-agent-builder/test/lib/permissions-mirror.test.mjs
+++ b/plugins/lua-agent-builder/test/lib/permissions-mirror.test.mjs
@@ -185,6 +185,10 @@ describe('permission layer (lib/permissions-template.json) under Claude Code sem
       'lua logs --ci --type all --limit 20 --json',
       'lua workflows run outreach --input @in.json --agents fake --fast-retries --json',
       'lua workflows watch run_1 --wait-for-human --timeout 900',
+      // lua-cli 3.36.0: the org policy READ verbs (`policy models|autonomy get`) are read-only.
+      'lua workflows policy models get --ci',
+      'lua workflows policy autonomy get --json --ci',
+      'lua models list --workflows --json --ci',
       'lua version create --ci -m "deploy via plugin"',
       'lua version list --json',
       'git status --short',
@@ -204,6 +208,13 @@ describe('permission layer (lib/permissions-template.json) under Claude Code sem
       'lua workflows resume run_1 --step s1 --data {}',
       'lua workflows deactivate outreach',
       'lua workflows off outreach',
+      // lua-cli 3.36.0: an org-wide policy write, the model_policy gate clear (and its
+      // `ungate` alias) and a recompose (publishes a new version) all confirm once via the prompt.
+      'lua workflows policy autonomy set --enabled on --max-credits 40',
+      'lua workflows policy models set --compose on --max-class strong',
+      'lua workflows clear-gate run_1 --kind model_policy',
+      'lua workflows ungate run_1 --kind model_policy',
+      'lua workflows recompose outreach',
       'lua mcp deactivate fs',
       'lua mcp off fs',
       'lua chat clear',