@cartanova/qgrid-cli 2.5.2 → 2.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.ko.md +7 -2
  2. package/README.md +7 -2
  3. package/bundle/dist/application/monit/monit.frame.js +3 -3
  4. package/bundle/dist/application/qgrid/oauth.js +1 -1
  5. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +41 -15
  6. package/bundle/dist/application/qgrid/qgrid.frame.js +74 -28
  7. package/bundle/dist/application/qgrid/qgrid.types.js +5 -3
  8. package/bundle/dist/application/qgrid/tool-emulation-schema.js +121 -0
  9. package/bundle/dist/application/qgrid/tool-emulation.js +116 -96
  10. package/bundle/dist/application/request-log/request-log.model.js +3 -3
  11. package/bundle/dist/application/request-log-step/request-log-step.model.js +2 -2
  12. package/bundle/dist/application/token/token.model.js +2 -2
  13. package/bundle/dist/server-error-handler.js +15 -0
  14. package/bundle/dist/sonamu.config.js +4 -7
  15. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +5 -4
  16. package/bundle/dist/utils/providers/anthropic/claude-session.js +7 -5
  17. package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +6 -4
  18. package/bundle/dist/utils/providers/common/schema-validation.js +178 -0
  19. package/bundle/dist/utils/providers/common/strictifier.js +329 -42
  20. package/bundle/dist/utils/providers/openai/codex-worker.js +16 -8
  21. package/bundle/dist/utils/providers/openai/openai-dispatcher.js +5 -37
  22. package/bundle/dist/utils/providers/openai/openai-worker-pool-config.js +37 -0
  23. package/bundle/src/application/monit/monit.frame.ts +1 -1
  24. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +103 -0
  25. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +358 -1
  26. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +50 -28
  27. package/bundle/src/application/qgrid/qgrid.frame.test.ts +629 -8
  28. package/bundle/src/application/qgrid/qgrid.frame.ts +107 -27
  29. package/bundle/src/application/qgrid/qgrid.types.ts +4 -1
  30. package/bundle/src/application/qgrid/tool-emulation-schema.test.ts +188 -0
  31. package/bundle/src/application/qgrid/tool-emulation-schema.ts +176 -0
  32. package/bundle/src/application/qgrid/tool-emulation.test.ts +285 -67
  33. package/bundle/src/application/qgrid/tool-emulation.ts +199 -102
  34. package/bundle/src/server-error-handler.ts +22 -0
  35. package/bundle/src/sonamu.config.test.ts +37 -0
  36. package/bundle/src/sonamu.config.ts +2 -5
  37. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +56 -0
  38. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +3 -3
  39. package/bundle/src/utils/providers/anthropic/claude-session.test.ts +10 -0
  40. package/bundle/src/utils/providers/anthropic/claude-session.ts +6 -1
  41. package/bundle/src/utils/providers/anthropic/stream-json-adapter.test.ts +66 -0
  42. package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +12 -3
  43. package/bundle/src/utils/providers/common/provider-dispatcher.ts +2 -0
  44. package/bundle/src/utils/providers/common/schema-validation.test.ts +284 -0
  45. package/bundle/src/utils/providers/common/schema-validation.ts +308 -0
  46. package/bundle/src/utils/providers/common/strictifier.test.ts +746 -0
  47. package/bundle/src/utils/providers/common/strictifier.ts +513 -52
  48. package/bundle/src/utils/providers/openai/codex-worker.test.ts +31 -0
  49. package/bundle/src/utils/providers/openai/codex-worker.ts +12 -4
  50. package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +6 -4
  51. package/bundle/src/utils/providers/openai/openai-dispatcher.ts +6 -79
  52. package/bundle/src/utils/providers/openai/openai-worker-pool-config.ts +80 -0
  53. package/bundle/web-dist/client/assets/{index-BQuKeBC5.js → index-DiY5V2e3.js} +3 -3
  54. package/bundle/web-dist/client/assets/{logs-BSsHMIKT.js → logs-UZ4Cvdmc.js} +1 -1
  55. package/bundle/web-dist/client/assets/{monit-D5ypGmGi.js → monit-C5cJo-HD.js} +1 -1
  56. package/bundle/web-dist/client/assets/{routes-BsCbz225.js → routes-DEKEmoQN.js} +1 -1
  57. package/bundle/web-dist/client/assets/{show-CXPhLZCl.js → show-DnX6b8KG.js} +1 -1
  58. package/bundle/web-dist/client/assets/{tokens-gEGH52O8.js → tokens-Ct0FGD4b.js} +1 -1
  59. package/bundle/web-dist/client/index.html +1 -1
  60. package/bundle/web-dist/server/entry-server.generated.js +1 -1
  61. package/package.json +1 -1
  62. package/skills/qgrid/references/ai-sdk-provider-contract.md +42 -2
  63. package/skills/qgrid/references/anthropic-claude-code-runtime.md +31 -1
  64. package/skills/qgrid/references/cli-env-and-server-boot.md +1 -1
  65. package/skills/qgrid/references/decision-rationale.md +11 -1
  66. package/skills/qgrid/references/repo-map.md +2 -1
  67. package/skills/qgrid/references/tool-calling-and-multiturn.md +33 -6
  68. package/skills/qgrid/references/verification-and-debugging.md +16 -1
package/README.ko.md CHANGED
@@ -96,10 +96,15 @@ CLI는 실행 시 npm의 최신 버전을 확인하고 patch를 포함해 설치
96
96
  | 변수 | 설명 | 기본값 |
97
97
  |------|------|--------|
98
98
  | `NODE_ENV` | Sonamu 실행 프로필. 원격 비프로덕션 배포에는 `staging` 사용 | `production` |
99
- | `QGRID_WORKERS_PER_TOKEN` | OpenAI 토큰당 codex worker 수 | `3` (최대 5) |
99
+ | `QGRID_OPENAI_AUTOSCALE` | OpenAI worker autoscaling. `false` 또는 `0`이면 고정 크기 pool 사용 | 활성 |
100
+ | `QGRID_OPENAI_MIN_WORKERS_PER_TOKEN` | autoscaling 중 OpenAI 토큰당 최소 worker 수 | `5` |
101
+ | `QGRID_OPENAI_MAX_WORKERS_PER_TOKEN` | autoscaling 중 OpenAI 토큰당 최대 worker 수 | `15` |
102
+ | `QGRID_WORKERS_PER_TOKEN` | OpenAI 최소/고정 worker 수의 legacy fallback | `5` |
100
103
  | `QGRID_PUBLIC_BASE_URL` | Anthropic OAuth callback 공개 베이스 URL. 원격 접속 환경에서 설정 | 미설정 시 `http://localhost:<port>/callback` |
101
104
  | `QGRID_OPENAI_THREAD_REUSE` | `false`로 설정 시 OpenAI thread reuse(prompt cache) 비활성화 | 활성 |
102
105
 
106
+ OpenAI worker 수는 토큰당 hard cap 20으로 제한됨. autoscaling을 끄면 pool은 설정된 최소 worker 수로 고정됨.
107
+
103
108
  ## 사전 요구사항
104
109
 
105
110
  - Node.js >= 20
@@ -115,7 +120,7 @@ CLI는 Sonamu 기반 서버를 내장 번들로 포함. 실행 시:
115
120
  1. DB 연결 확인
116
121
  2. 서버 시작 (API + 대시보드 웹 UI)
117
122
  3. DB의 등록된 토큰 로드. 이후 토큰 등록/변경은 PostgreSQL LISTEN/NOTIFY로 실행 중인 서버에 실시간 반영
118
- 4. **OpenAI 토큰**: 토큰당 persistent codex app-server 프로세스 N개 spawn (기본 3, 최대 5). JSON-RPC로 통신. 요청은 idle worker에 round-robin 라우팅, 전부 busy면 큐 대기 (최대 60초). `sessionKey` 멀티턴 요청은 같은 thread로 재라우팅되어 prompt cache 적중
123
+ 4. **OpenAI 토큰**: 토큰당 persistent codex app-server 프로세스를 5개에서 15개까지 autoscale (hard cap 20). JSON-RPC로 통신. 요청은 idle worker에 round-robin 라우팅, 전부 busy면 큐 대기 (최대 60초). `sessionKey` 멀티턴 요청은 같은 thread로 재라우팅되어 prompt cache 적중
119
124
  5. **Anthropic 토큰**: 요청마다 격리된 claude 프로세스를 fresh spawn (`stream-json` 입출력). 토큰은 least-used 우선으로 선택. OAuth 토큰 자동 refresh
120
125
  6. 토큰별 quota threshold(기본 80%)를 넘은 토큰은 라우팅에서 제외 (사용률 조회 실패 시에는 fail-open으로 통과)
121
126
 
package/README.md CHANGED
@@ -97,10 +97,15 @@ Server behavior variables:
97
97
  | Variable | Description | Default |
98
98
  |------|------|--------|
99
99
  | `NODE_ENV` | Sonamu runtime profile. Set `staging` for a remote non-production deployment | `production` |
100
- | `QGRID_WORKERS_PER_TOKEN` | codex workers per OpenAI token | `3` (max 5) |
100
+ | `QGRID_OPENAI_AUTOSCALE` | OpenAI worker autoscaling. Set to `false` or `0` to keep a fixed-size pool | enabled |
101
+ | `QGRID_OPENAI_MIN_WORKERS_PER_TOKEN` | Minimum OpenAI workers per token while autoscaling | `5` |
102
+ | `QGRID_OPENAI_MAX_WORKERS_PER_TOKEN` | Maximum OpenAI workers per token while autoscaling | `15` |
103
+ | `QGRID_WORKERS_PER_TOKEN` | Legacy fallback for the OpenAI minimum/fixed worker count | `5` |
101
104
  | `QGRID_PUBLIC_BASE_URL` | Public base URL for the Anthropic OAuth callback. Set it when the server is accessed remotely | `http://localhost:<port>/callback` when unset |
102
105
  | `QGRID_OPENAI_THREAD_REUSE` | Set to `false` to disable OpenAI thread reuse (prompt caching) | enabled |
103
106
 
107
+ OpenAI worker counts are clamped to a hard cap of 20 per token. With autoscaling disabled, the pool stays at the configured minimum.
108
+
104
109
  ## Prerequisites
105
110
 
106
111
  - Node.js >= 20
@@ -116,7 +121,7 @@ The CLI ships the Sonamu-based server as a built-in bundle. On launch:
116
121
  1. Verify the DB connection
117
122
  2. Start the server (API + dashboard web UI)
118
123
  3. Load registered tokens from the DB. Later token additions/changes propagate to the running server in real time via PostgreSQL LISTEN/NOTIFY
119
- 4. **OpenAI tokens**: spawn N persistent codex app-server processes per token (default 3, max 5), communicating over JSON-RPC. Requests are routed round-robin across idle workers; when all are busy they queue (up to 60 seconds). Multi-turn requests carrying a `sessionKey` are routed back to the same thread for prompt-cache hits
124
+ 4. **OpenAI tokens**: autoscale persistent codex app-server processes per token from 5 to 15 (hard cap 20), communicating over JSON-RPC. Requests are routed round-robin across idle workers; when all are busy they queue (up to 60 seconds). Multi-turn requests carrying a `sessionKey` are routed back to the same thread for prompt-cache hits
120
125
  5. **Anthropic tokens**: spawn a fresh, isolated claude process per request (`stream-json` in/out). Tokens are selected least-used-first. OAuth tokens are refreshed automatically
121
126
  6. Tokens over their quota threshold (default 80%) are excluded from routing (usage-lookup failures fail open)
122
127
 
@@ -1,8 +1,8 @@
1
1
  import { monitLogBuffer } from "./log-buffer.js";
2
+ import { resolveOpenAIWorkerPoolConfig } from "../../utils/providers/openai/openai-worker-pool-config.js";
3
+ import { QgridDispatcher } from "../qgrid/qgrid.dispatcher.js";
2
4
  import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorateMetadata.js";
3
5
  import __decorate from "../../_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorate.js";
4
- import { resolveOpenAIWorkerPoolConfig } from "../../utils/providers/openai/openai-dispatcher.js";
5
- import { QgridDispatcher } from "../qgrid/qgrid.dispatcher.js";
6
6
  import { BaseFrameClass, DB, api } from "sonamu";
7
7
  //#region src/application/monit/monit.frame.ts
8
8
  /**
@@ -82,4 +82,4 @@ const MonitFrame = new MonitFrameClass();
82
82
  //#endregion
83
83
  export { MonitFrame };
84
84
 
85
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9uaXQuZnJhbWUuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwcGxpY2F0aW9uL21vbml0L21vbml0LmZyYW1lLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTW9uaXQg4oCUIOuMgOyLnOuztOuTnCBNb25pdCDtg63smqkg7ZSE66Gc7IS47IqkIOuhnOq3uCDqtIDsuKEgQVBJLlxuICpcbiAqIOydveq4sCDsoITsmqkuIHJpbmcgYnVmZmVyIOulvCDslofqsowg7KeB7KCRIOydveycvOupsCjrspTsmqkg7L+866asIOq4sOqzhCDsl4bsnbQpLFxuICogcmVxdWVzdCBsb2cg66W8IOuCqOq4sOyngCDslYrripTri6QuIOygkeq3vCDqsr3qs4TripQg64uk66W4IOuMgOyLnOuztOuTnCBBUEkg7JmAIOuPmeydvO2VmOuLpC5cbiAqL1xuaW1wb3J0IHsgYXBpLCBCYXNlRnJhbWVDbGFzcywgREIgfSBmcm9tIFwic29uYW11XCI7XG5cbmltcG9ydCB7IHJlc29sdmVPcGVuQUlXb3JrZXJQb29sQ29uZmlnIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLWRpc3BhdGNoZXJcIjtcbmltcG9ydCB7IFFncmlkRGlzcGF0Y2hlciB9IGZyb20gXCIuLi9xZ3JpZC9xZ3JpZC5kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBtb25pdExvZ0J1ZmZlciB9IGZyb20gXCIuL2xvZy1idWZmZXJcIjtcbmltcG9ydCB7IHR5cGUgTW9uaXRMb2dDaHVuaywgdHlwZSBNb25pdFNlcnZlckluZm8sIHR5cGUgTW9uaXRWaXRhbHMgfSBmcm9tIFwiLi9tb25pdC50eXBlc1wiO1xuXG4vLyDsnZHri7Xri7kg7JeU7Yq466asIOyDge2VnCDigJQg7Y+066eBIO2BtOudvOydtOyWuO2KuOuKlCDri6TsnYwg7Y+07JeQ7IScIOydtOyWtOyEnCDrlLDrnbzsnqHripTri6QuXG5jb25zdCBSRVNQT05TRV9FTlRSWV9MSU1JVCA9IDFfMDAwO1xuXG5jbGFzcyBNb25pdEZyYW1lQ2xhc3MgZXh0ZW5kcyBCYXNlRnJhbWVDbGFzcyB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKFwiTW9uaXRcIik7XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSB9KVxuICBhc3luYyBtb25pdExvZ3MoY3Vyc29yPzogbnVtYmVyKTogUHJvbWlzZTxNb25pdExvZ0NodW5rPiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHByb2Nlc3NTdGFydGVkQXQ6IG1vbml0TG9nQnVmZmVyLnByb2Nlc3NTdGFydGVkQXQsXG4gICAgICAuLi5tb25pdExvZ0J1ZmZlci5hZnRlcihjdXJzb3IsIFJFU1BPTlNFX0VOVFJZX0xJTUlUKSxcbiAgICAgIHZpdGFsczogY3VycmVudFZpdGFscygpLFxuICAgIH07XG4gIH1cblxuICAvLyDtlITroZzshLjsiqQg7KCV7KCBIOygleuztCDigJQg7Y+066eBIOu2iO2VhOyalCwg7Y6Y7J207KeA64u5IDHtmowg7KGw7ZqMLlxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSB9KVxuICBhc3luYyBtb25pdEluZm8oKTogUHJvbWlzZTxNb25pdFNlcnZlckluZm8+IHtcbiAgICBjb25zdCBwb29sID0gcmVzb2x2ZU9wZW5BSVdvcmtlclBvb2xDb25maWcoKTtcbiAgICBjb25zdCBob3N0ID0gcHJvY2Vzcy5lbnYuSE9TVCA/PyBcImxvY2FsaG9zdFwiO1xuICAgIGNvbnN0IHBvcnQgPSBwcm9jZXNzLmVudi5QT1JUID8/IFwiNDQ5MDBcIjtcbiAgICBjb25zdCBjb25uID0gYWN0aXZlRGJDb25uZWN0aW9uKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNlcnZlclVybDogYGh0dHA6Ly8ke2hvc3R9OiR7cG9ydH1gLFxuICAgICAgZGJIb3N0OiBjb25uLmhvc3QgPz8gXCJsb2NhbGhvc3RcIixcbiAgICAgIGRiTmFtZTogY29ubi5kYXRhYmFzZSA/PyBcInFncmlkXCIsXG4gICAgICBvcGVuYWk6IHtcbiAgICAgICAgbWluV29ya2Vyc1BlclRva2VuOiBwb29sLm1pbldvcmtlcnNQZXJUb2tlbixcbiAgICAgICAgbWF4V29ya2Vyc1BlclRva2VuOiBwb29sLm1heFdvcmtlcnNQZXJUb2tlbixcbiAgICAgICAgYXV0b3NjYWxlOiBwb29sLmF1dG9zY2FsZSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxufVxuXG4vLyBkaXNwYXRjaGVyIOuvuOy0iOq4sO2ZlCjrtoDtjIUg7KeB7ZuEKSDsi5wgMCDsnLzroZwg7J2R64u17ZWc64ukIOKAlCDqsIDrsrzsmrQg7Iqk64OF7IO37J206528IOyYpOulmOuhnCDrp4zrk6Tsp4Ag7JWK64qU64ukLlxuZnVuY3Rpb24gY3VycmVudFZpdGFscygpOiBNb25pdFZpdGFscyB7XG4gIHJldHVybiB7XG4gICAgb3BlbmFpV29ya2VyQ291bnQ6IFFncmlkRGlzcGF0Y2hlci5vcGVuYWlEaXNwYXRjaGVyPy53b3JrZXJDb3VudCA/PyAwLFxuICAgIG9wZW5haVJlYWR5V29ya2VyQ291bnQ6IFFncmlkRGlzcGF0Y2hlci5vcGVuYWlEaXNwYXRjaGVyPy5yZWFkeVdvcmtlckNvdW50ID8/IDAsXG4gICAgb3BlbmFpUXVldWVMZW5ndGg6IFFncmlkRGlzcGF0Y2hlci5vcGVuYWlEaXNwYXRjaGVyPy5xdWV1ZUxlbmd0aCA/PyAwLFxuICAgIG9wZW5haVdvcmtlcnNCeVRva2VuOiBRZ3JpZERpc3BhdGNoZXIub3BlbmFpRGlzcGF0Y2hlcj8ud29ya2VyQ291bnRzQnlUb2tlbiA/PyBbXSxcbiAgICBhbnRocm9waWNUb2tlbkNvdW50OiBRZ3JpZERpc3BhdGNoZXIuYW50aHJvcGljRGlzcGF0Y2hlcj8udG9rZW5Db3VudCA/PyAwLFxuICAgIGFudGhyb3BpY1Rva2VuTmFtZXM6IFFncmlkRGlzcGF0Y2hlci5hbnRocm9waWNEaXNwYXRjaGVyPy50b2tlbk5hbWVzID8/IFtdLFxuICB9O1xufVxuXG4vLyDsi6TsoJwg7Zmc7ISxIGtuZXgg7Jew6rKw7JeQ7IScIOydveuKlOuLpCDigJQgZGV2IOyEnOuyhOydmCDthrXtlakg7YWM7Iqk7Yq4IOufrOuEiOqwgCBwcm9jZXNzLmVudi5TT05BTVVfREJfTkFNRSDsnYRcbi8vIO2FjOyKpO2KuCBEQiDsnbTrpoTsnLzroZwg642u7Ja07JOw66+A66GcIGVudiDripQg7Iug66Kw7ZWgIOyImCDsl4bri6QuIERCIOuvuOy0iOq4sO2ZlCjrtoDtjIUg7KCEKSDsi5zsl5Drp4wgZW52IO2PtOuwsS5cbmZ1bmN0aW9uIGFjdGl2ZURiQ29ubmVjdGlvbigpOiB7IGhvc3Q/OiBzdHJpbmc7IGRhdGFiYXNlPzogc3RyaW5nIH0ge1xuICB0cnkge1xuICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBEQi5nZXREQkNvbmZpZyhcIndcIikuY29ubmVjdGlvbjtcbiAgICBpZiAodHlwZW9mIGNvbm5lY3Rpb24gPT09IFwib2JqZWN0XCIgJiYgY29ubmVjdGlvbiAhPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbm5lY3Rpb24gYXMgeyBob3N0Pzogc3RyaW5nOyBkYXRhYmFzZT86IHN0cmluZyB9O1xuICAgIH1cbiAgfSBjYXRjaCB7XG4gICAgLy8gREIgY29uZmlnIOuvuOy0iOq4sO2ZlCDigJQgZW52IO2PtOuwseycvOuhnCDsp4TtlolcbiAgfVxuICByZXR1cm4geyBob3N0OiBwcm9jZXNzLmVudi5TT05BTVVfREJfSE9TVCwgZGF0YWJhc2U6IHByb2Nlc3MuZW52LlNPTkFNVV9EQl9OQU1FIH07XG59XG5cbmV4cG9ydCBjb25zdCBNb25pdEZyYW1lID0gbmV3IE1vbml0RnJhbWVDbGFzcygpO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBY0EsTUFBTSx1QkFBdUI7QUFFN0IsSUFBTSxrQkFBTixjQUE4QixlQUFlO0NBQzNDLGNBQWM7RUFDWixNQUFNLE9BQU87Q0FDZjtDQUVBLE1BQ00sVUFBVSxRQUF5QztFQUN2RCxPQUFPO0dBQ0wsa0JBQWtCLGVBQWU7R0FDakMsR0FBRyxlQUFlLE1BQU0sUUFBUSxvQkFBb0I7R0FDcEQsUUFBUSxjQUFjO0VBQ3hCO0NBQ0Y7Q0FHQSxNQUNNLFlBQXNDO0VBQzFDLE1BQU0sT0FBTyw4QkFBOEI7RUFDM0MsTUFBTSxPQUFPLFFBQVEsSUFBSSxRQUFRO0VBQ2pDLE1BQU0sT0FBTyxRQUFRLElBQUksUUFBUTtFQUNqQyxNQUFNLE9BQU8sbUJBQW1CO0VBQ2hDLE9BQU87R0FDTCxXQUFXLFVBQVUsS0FBSyxHQUFHO0dBQzdCLFFBQVEsS0FBSyxRQUFRO0dBQ3JCLFFBQVEsS0FBSyxZQUFZO0dBQ3pCLFFBQVE7SUFDTixvQkFBb0IsS0FBSztJQUN6QixvQkFBb0IsS0FBSztJQUN6QixXQUFXLEtBQUs7R0FDbEI7RUFDRjtDQUNGO0FBQ0Y7O0NBM0JHLElBQUk7RUFBRSxZQUFZO0VBQU8sU0FBUyxDQUFDLFNBQVMsZ0JBQWdCO0NBQUUsQ0FBQzs7Ozs7O0NBVS9ELElBQUk7RUFBRSxZQUFZO0VBQU8sU0FBUyxDQUFDLFNBQVMsZ0JBQWdCO0NBQUUsQ0FBQzs7Ozs7QUFvQmxFLFNBQVMsZ0JBQTZCO0NBQ3BDLE9BQU87RUFDTCxtQkFBbUIsZ0JBQWdCLGtCQUFrQixlQUFlO0VBQ3BFLHdCQUF3QixnQkFBZ0Isa0JBQWtCLG9CQUFvQjtFQUM5RSxtQkFBbUIsZ0JBQWdCLGtCQUFrQixlQUFlO0VBQ3BFLHNCQUFzQixnQkFBZ0Isa0JBQWtCLHVCQUF1QixDQUFDO0VBQ2hGLHFCQUFxQixnQkFBZ0IscUJBQXFCLGNBQWM7RUFDeEUscUJBQXFCLGdCQUFnQixxQkFBcUIsY0FBYyxDQUFDO0NBQzNFO0FBQ0Y7QUFJQSxTQUFTLHFCQUEyRDtDQUNsRSxJQUFJO0VBQ0YsTUFBTSxhQUFhLEdBQUcsWUFBWSxHQUFHLENBQUMsQ0FBQztFQUN2QyxJQUFJLE9BQU8sZUFBZSxZQUFZLGVBQWUsTUFDbkQsT0FBTztDQUVYLFFBQVEsQ0FFUjtDQUNBLE9BQU87RUFBRSxNQUFNLFFBQVEsSUFBSTtFQUFnQixVQUFVLFFBQVEsSUFBSTtDQUFlO0FBQ2xGO0FBRUEsTUFBYSxhQUFhLElBQUksZ0JBQWdCIn0=
85
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9uaXQuZnJhbWUuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwcGxpY2F0aW9uL21vbml0L21vbml0LmZyYW1lLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTW9uaXQg4oCUIOuMgOyLnOuztOuTnCBNb25pdCDtg63smqkg7ZSE66Gc7IS47IqkIOuhnOq3uCDqtIDsuKEgQVBJLlxuICpcbiAqIOydveq4sCDsoITsmqkuIHJpbmcgYnVmZmVyIOulvCDslofqsowg7KeB7KCRIOydveycvOupsCjrspTsmqkg7L+866asIOq4sOqzhCDsl4bsnbQpLFxuICogcmVxdWVzdCBsb2cg66W8IOuCqOq4sOyngCDslYrripTri6QuIOygkeq3vCDqsr3qs4TripQg64uk66W4IOuMgOyLnOuztOuTnCBBUEkg7JmAIOuPmeydvO2VmOuLpC5cbiAqL1xuaW1wb3J0IHsgYXBpLCBCYXNlRnJhbWVDbGFzcywgREIgfSBmcm9tIFwic29uYW11XCI7XG5cbmltcG9ydCB7IHJlc29sdmVPcGVuQUlXb3JrZXJQb29sQ29uZmlnIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLXdvcmtlci1wb29sLWNvbmZpZ1wiO1xuaW1wb3J0IHsgUWdyaWREaXNwYXRjaGVyIH0gZnJvbSBcIi4uL3FncmlkL3FncmlkLmRpc3BhdGNoZXJcIjtcbmltcG9ydCB7IG1vbml0TG9nQnVmZmVyIH0gZnJvbSBcIi4vbG9nLWJ1ZmZlclwiO1xuaW1wb3J0IHsgdHlwZSBNb25pdExvZ0NodW5rLCB0eXBlIE1vbml0U2VydmVySW5mbywgdHlwZSBNb25pdFZpdGFscyB9IGZyb20gXCIuL21vbml0LnR5cGVzXCI7XG5cbi8vIOydkeuLteuLuSDsl5Ttirjrpqwg7IOB7ZWcIOKAlCDtj7Trp4Eg7YG065287J207Ja47Yq464qUIOuLpOydjCDtj7Tsl5DshJwg7J207Ja07IScIOuUsOudvOyeoeuKlOuLpC5cbmNvbnN0IFJFU1BPTlNFX0VOVFJZX0xJTUlUID0gMV8wMDA7XG5cbmNsYXNzIE1vbml0RnJhbWVDbGFzcyBleHRlbmRzIEJhc2VGcmFtZUNsYXNzIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoXCJNb25pdFwiKTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIkdFVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLXF1ZXJ5XCJdIH0pXG4gIGFzeW5jIG1vbml0TG9ncyhjdXJzb3I/OiBudW1iZXIpOiBQcm9taXNlPE1vbml0TG9nQ2h1bms+IHtcbiAgICByZXR1cm4ge1xuICAgICAgcHJvY2Vzc1N0YXJ0ZWRBdDogbW9uaXRMb2dCdWZmZXIucHJvY2Vzc1N0YXJ0ZWRBdCxcbiAgICAgIC4uLm1vbml0TG9nQnVmZmVyLmFmdGVyKGN1cnNvciwgUkVTUE9OU0VfRU5UUllfTElNSVQpLFxuICAgICAgdml0YWxzOiBjdXJyZW50Vml0YWxzKCksXG4gICAgfTtcbiAgfVxuXG4gIC8vIO2UhOuhnOyEuOyKpCDsoJXsoIEg7KCV67O0IOKAlCDtj7Trp4Eg67aI7ZWE7JqULCDtjpjsnbTsp4Dri7kgMe2ajCDsobDtmowuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIkdFVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLXF1ZXJ5XCJdIH0pXG4gIGFzeW5jIG1vbml0SW5mbygpOiBQcm9taXNlPE1vbml0U2VydmVySW5mbz4ge1xuICAgIGNvbnN0IHBvb2wgPSByZXNvbHZlT3BlbkFJV29ya2VyUG9vbENvbmZpZygpO1xuICAgIGNvbnN0IGhvc3QgPSBwcm9jZXNzLmVudi5IT1NUID8/IFwibG9jYWxob3N0XCI7XG4gICAgY29uc3QgcG9ydCA9IHByb2Nlc3MuZW52LlBPUlQgPz8gXCI0NDkwMFwiO1xuICAgIGNvbnN0IGNvbm4gPSBhY3RpdmVEYkNvbm5lY3Rpb24oKTtcbiAgICByZXR1cm4ge1xuICAgICAgc2VydmVyVXJsOiBgaHR0cDovLyR7aG9zdH06JHtwb3J0fWAsXG4gICAgICBkYkhvc3Q6IGNvbm4uaG9zdCA/PyBcImxvY2FsaG9zdFwiLFxuICAgICAgZGJOYW1lOiBjb25uLmRhdGFiYXNlID8/IFwicWdyaWRcIixcbiAgICAgIG9wZW5haToge1xuICAgICAgICBtaW5Xb3JrZXJzUGVyVG9rZW46IHBvb2wubWluV29ya2Vyc1BlclRva2VuLFxuICAgICAgICBtYXhXb3JrZXJzUGVyVG9rZW46IHBvb2wubWF4V29ya2Vyc1BlclRva2VuLFxuICAgICAgICBhdXRvc2NhbGU6IHBvb2wuYXV0b3NjYWxlLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG59XG5cbi8vIGRpc3BhdGNoZXIg66+47LSI6riw7ZmUKOu2gO2MhSDsp4Htm4QpIOyLnCAwIOycvOuhnCDsnZHri7XtlZzri6Qg4oCUIOqwgOuyvOyatCDsiqTrg4Xsg7fsnbTrnbwg7Jik66WY66GcIOunjOuTpOyngCDslYrripTri6QuXG5mdW5jdGlvbiBjdXJyZW50Vml0YWxzKCk6IE1vbml0Vml0YWxzIHtcbiAgcmV0dXJuIHtcbiAgICBvcGVuYWlXb3JrZXJDb3VudDogUWdyaWREaXNwYXRjaGVyLm9wZW5haURpc3BhdGNoZXI/LndvcmtlckNvdW50ID8/IDAsXG4gICAgb3BlbmFpUmVhZHlXb3JrZXJDb3VudDogUWdyaWREaXNwYXRjaGVyLm9wZW5haURpc3BhdGNoZXI/LnJlYWR5V29ya2VyQ291bnQgPz8gMCxcbiAgICBvcGVuYWlRdWV1ZUxlbmd0aDogUWdyaWREaXNwYXRjaGVyLm9wZW5haURpc3BhdGNoZXI/LnF1ZXVlTGVuZ3RoID8/IDAsXG4gICAgb3BlbmFpV29ya2Vyc0J5VG9rZW46IFFncmlkRGlzcGF0Y2hlci5vcGVuYWlEaXNwYXRjaGVyPy53b3JrZXJDb3VudHNCeVRva2VuID8/IFtdLFxuICAgIGFudGhyb3BpY1Rva2VuQ291bnQ6IFFncmlkRGlzcGF0Y2hlci5hbnRocm9waWNEaXNwYXRjaGVyPy50b2tlbkNvdW50ID8/IDAsXG4gICAgYW50aHJvcGljVG9rZW5OYW1lczogUWdyaWREaXNwYXRjaGVyLmFudGhyb3BpY0Rpc3BhdGNoZXI/LnRva2VuTmFtZXMgPz8gW10sXG4gIH07XG59XG5cbi8vIOyLpOygnCDtmZzshLEga25leCDsl7DqsrDsl5DshJwg7J2964qU64ukIOKAlCBkZXYg7ISc67KE7J2YIO2Gte2VqSDthYzsiqTtirgg65+s64SI6rCAIHByb2Nlc3MuZW52LlNPTkFNVV9EQl9OQU1FIOydhFxuLy8g7YWM7Iqk7Yq4IERCIOydtOumhOycvOuhnCDrja7slrTsk7Drr4DroZwgZW52IOuKlCDsi6DrorDtlaAg7IiYIOyXhuuLpC4gREIg66+47LSI6riw7ZmUKOu2gO2MhSDsoIQpIOyLnOyXkOunjCBlbnYg7Y+067CxLlxuZnVuY3Rpb24gYWN0aXZlRGJDb25uZWN0aW9uKCk6IHsgaG9zdD86IHN0cmluZzsgZGF0YWJhc2U/OiBzdHJpbmcgfSB7XG4gIHRyeSB7XG4gICAgY29uc3QgY29ubmVjdGlvbiA9IERCLmdldERCQ29uZmlnKFwid1wiKS5jb25uZWN0aW9uO1xuICAgIGlmICh0eXBlb2YgY29ubmVjdGlvbiA9PT0gXCJvYmplY3RcIiAmJiBjb25uZWN0aW9uICE9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29ubmVjdGlvbiBhcyB7IGhvc3Q/OiBzdHJpbmc7IGRhdGFiYXNlPzogc3RyaW5nIH07XG4gICAgfVxuICB9IGNhdGNoIHtcbiAgICAvLyBEQiBjb25maWcg66+47LSI6riw7ZmUIOKAlCBlbnYg7Y+067Cx7Jy866GcIOynhO2WiVxuICB9XG4gIHJldHVybiB7IGhvc3Q6IHByb2Nlc3MuZW52LlNPTkFNVV9EQl9IT1NULCBkYXRhYmFzZTogcHJvY2Vzcy5lbnYuU09OQU1VX0RCX05BTUUgfTtcbn1cblxuZXhwb3J0IGNvbnN0IE1vbml0RnJhbWUgPSBuZXcgTW9uaXRGcmFtZUNsYXNzKCk7XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFjQSxNQUFNLHVCQUF1QjtBQUU3QixJQUFNLGtCQUFOLGNBQThCLGVBQWU7Q0FDM0MsY0FBYztFQUNaLE1BQU0sT0FBTztDQUNmO0NBRUEsTUFDTSxVQUFVLFFBQXlDO0VBQ3ZELE9BQU87R0FDTCxrQkFBa0IsZUFBZTtHQUNqQyxHQUFHLGVBQWUsTUFBTSxRQUFRLG9CQUFvQjtHQUNwRCxRQUFRLGNBQWM7RUFDeEI7Q0FDRjtDQUdBLE1BQ00sWUFBc0M7RUFDMUMsTUFBTSxPQUFPLDhCQUE4QjtFQUMzQyxNQUFNLE9BQU8sUUFBUSxJQUFJLFFBQVE7RUFDakMsTUFBTSxPQUFPLFFBQVEsSUFBSSxRQUFRO0VBQ2pDLE1BQU0sT0FBTyxtQkFBbUI7RUFDaEMsT0FBTztHQUNMLFdBQVcsVUFBVSxLQUFLLEdBQUc7R0FDN0IsUUFBUSxLQUFLLFFBQVE7R0FDckIsUUFBUSxLQUFLLFlBQVk7R0FDekIsUUFBUTtJQUNOLG9CQUFvQixLQUFLO0lBQ3pCLG9CQUFvQixLQUFLO0lBQ3pCLFdBQVcsS0FBSztHQUNsQjtFQUNGO0NBQ0Y7QUFDRjs7Q0EzQkcsSUFBSTtFQUFFLFlBQVk7RUFBTyxTQUFTLENBQUMsU0FBUyxnQkFBZ0I7Q0FBRSxDQUFDOzs7Ozs7Q0FVL0QsSUFBSTtFQUFFLFlBQVk7RUFBTyxTQUFTLENBQUMsU0FBUyxnQkFBZ0I7Q0FBRSxDQUFDOzs7OztBQW9CbEUsU0FBUyxnQkFBNkI7Q0FDcEMsT0FBTztFQUNMLG1CQUFtQixnQkFBZ0Isa0JBQWtCLGVBQWU7RUFDcEUsd0JBQXdCLGdCQUFnQixrQkFBa0Isb0JBQW9CO0VBQzlFLG1CQUFtQixnQkFBZ0Isa0JBQWtCLGVBQWU7RUFDcEUsc0JBQXNCLGdCQUFnQixrQkFBa0IsdUJBQXVCLENBQUM7RUFDaEYscUJBQXFCLGdCQUFnQixxQkFBcUIsY0FBYztFQUN4RSxxQkFBcUIsZ0JBQWdCLHFCQUFxQixjQUFjLENBQUM7Q0FDM0U7QUFDRjtBQUlBLFNBQVMscUJBQTJEO0NBQ2xFLElBQUk7RUFDRixNQUFNLGFBQWEsR0FBRyxZQUFZLEdBQUcsQ0FBQyxDQUFDO0VBQ3ZDLElBQUksT0FBTyxlQUFlLFlBQVksZUFBZSxNQUNuRCxPQUFPO0NBRVgsUUFBUSxDQUVSO0NBQ0EsT0FBTztFQUFFLE1BQU0sUUFBUSxJQUFJO0VBQWdCLFVBQVUsUUFBUSxJQUFJO0NBQWU7QUFDbEY7QUFFQSxNQUFhLGFBQWEsSUFBSSxnQkFBZ0IifQ==
@@ -1,5 +1,5 @@
1
- import { getLogger } from "@logtape/logtape";
2
1
  import { createHash, randomBytes } from "node:crypto";
2
+ import { getLogger } from "@logtape/logtape";
3
3
  //#region src/application/qgrid/oauth.ts
4
4
  /**
5
5
  * OAuth 유틸 — Claude Code 소스의 OAuth 플로우 그대로 재현
@@ -1,9 +1,11 @@
1
- import { ProcessError, QuotaError, maskToken } from "./qgrid.types.js";
2
1
  import { getAccessToken } from "../../utils/providers/common/credentials.js";
3
2
  import { calculateCostUsd } from "../../utils/providers/common/model-cost.js";
3
+ import { parseAndValidateCallerSchemas, serializeAndValidateDispatchSchema } from "../../utils/providers/common/schema-validation.js";
4
4
  import { strictify } from "../../utils/providers/common/strictifier.js";
5
5
  import { decideConvRouting, issueConvContext } from "./conv-routing.js";
6
- import { applyToolCallEmulation, buildToolCallSchema } from "./tool-emulation.js";
6
+ import { ProcessError, QuotaError, maskToken } from "./qgrid.types.js";
7
+ import { applyToolCallEmulation } from "./tool-emulation.js";
8
+ import { buildToolCallSchema } from "./tool-emulation-schema.js";
7
9
  //#region src/application/qgrid/qgrid.dispatcher.ts
8
10
  var QgridDispatcherClass = class {
9
11
  tokens = /* @__PURE__ */ new Map();
@@ -31,10 +33,10 @@ var QgridDispatcherClass = class {
31
33
  requests: this.countOf(r.name)
32
34
  }));
33
35
  }
34
- async query(input, timeoutMs) {
35
- if (input.tools?.length && input.jsonSchema) throw new ProcessError("tools and jsonSchema cannot be used together");
36
+ async query(input, abortSignal) {
36
37
  const route = parseProviderRoute(input.model);
37
- const outputSchema = buildStrictOutputSchema(input);
38
+ const outputSchema = buildAndValidateStrictOutputSchema(input, route.provider);
39
+ const answerMode = input.jsonSchema ? "structured" : "legacy";
38
40
  if (route.provider === "openai") {
39
41
  if (!this.openaiDispatcher) throw new QuotaError("OpenAI dispatcher not initialized");
40
42
  const decision = decideConvRouting(input);
@@ -50,11 +52,16 @@ var QgridDispatcherClass = class {
50
52
  coldHistory: decision.coldHistory,
51
53
  reuse: decision.reuse,
52
54
  reuseInput: decision.reuseInput,
55
+ abortSignal,
53
56
  imageGeneration: input.imageGeneration,
54
57
  imageGenerationOptions: input.imageGenerationOptions
55
58
  });
56
59
  const coord = input.imageGeneration ? void 0 : issueConvContext(result.threadCoord, decision);
57
- return applyToolCallEmulation(toEmulationResult(result), input.tools, coord, result.images);
60
+ return applyToolCallEmulation(toEmulationResult(result), input.tools, {
61
+ threadCoord: coord,
62
+ images: result.images,
63
+ answerMode
64
+ });
58
65
  } else if (route.provider === "anthropic") {
59
66
  if (!this.anthropicDispatcher) throw new QuotaError("Anthropic dispatcher not initialized");
60
67
  const decision = decideConvRouting(input);
@@ -63,18 +70,24 @@ var QgridDispatcherClass = class {
63
70
  systemPrompt: input.system,
64
71
  outputSchema,
65
72
  effort: input.effort,
73
+ timeoutMs: input.timeout,
74
+ abortSignal,
66
75
  coldInput: decision.coldInput,
67
76
  coldHistory: decision.coldHistory,
68
77
  imageGeneration: input.imageGeneration,
69
78
  imageGenerationOptions: input.imageGenerationOptions
70
79
  });
71
- return applyToolCallEmulation(toEmulationResult(result), input.tools, issueConvContext(result.threadCoord, decision));
80
+ return applyToolCallEmulation(toEmulationResult(result), input.tools, {
81
+ threadCoord: issueConvContext(result.threadCoord, decision),
82
+ answerMode
83
+ });
72
84
  }
73
85
  throw directLlmApiFallbackNotImplemented(input);
74
86
  }
75
87
  async queryStream(input, cb, abortSignal) {
76
88
  const route = parseProviderRoute(input.model);
77
- const outputSchema = buildStrictOutputSchema(input);
89
+ const outputSchema = buildAndValidateStrictOutputSchema(input, route.provider);
90
+ const answerMode = input.jsonSchema ? "structured" : "legacy";
78
91
  if (route.provider === "openai") {
79
92
  if (!this.openaiDispatcher) throw new QuotaError("OpenAI dispatcher not initialized");
80
93
  const decision = decideConvRouting(input);
@@ -98,7 +111,10 @@ var QgridDispatcherClass = class {
98
111
  onThreadId: cb.onThreadId,
99
112
  onTurnId: cb.onTurnId,
100
113
  onComplete: (turnResult) => {
101
- cb.onComplete(applyToolCallEmulation(toEmulationResult(turnResult), input.tools, issueConvContext(turnResult.threadCoord, decision)));
114
+ cb.onComplete(applyToolCallEmulation(toEmulationResult(turnResult), input.tools, {
115
+ threadCoord: issueConvContext(turnResult.threadCoord, decision),
116
+ answerMode
117
+ }));
102
118
  },
103
119
  onError: cb.onError
104
120
  });
@@ -113,6 +129,7 @@ var QgridDispatcherClass = class {
113
129
  effort: input.effort,
114
130
  coldInput: decision.coldInput,
115
131
  coldHistory: decision.coldHistory,
132
+ timeoutMs: input.timeout,
116
133
  abortSignal,
117
134
  imageGeneration: input.imageGeneration,
118
135
  imageGenerationOptions: input.imageGenerationOptions
@@ -121,7 +138,10 @@ var QgridDispatcherClass = class {
121
138
  onThreadId: cb.onThreadId,
122
139
  onComplete: (turnResult) => {
123
140
  const issuedCoord = issueConvContext(turnResult.threadCoord, decision);
124
- cb.onComplete(applyToolCallEmulation(toEmulationResult(turnResult), input.tools, issuedCoord));
141
+ cb.onComplete(applyToolCallEmulation(toEmulationResult(turnResult), input.tools, {
142
+ threadCoord: issuedCoord,
143
+ answerMode
144
+ }));
125
145
  },
126
146
  onError: cb.onError
127
147
  });
@@ -142,12 +162,18 @@ function parseProviderRoute(model) {
142
162
  function directLlmApiFallbackNotImplemented(input) {
143
163
  return new ProcessError(`Direct LLM API fallback not implemented for model: ${input.model ?? "<default>"}`);
144
164
  }
145
- function buildStrictOutputSchema(input) {
165
+ function buildStrictOutputSchema(input, provider) {
146
166
  const outputSchema = buildRawOutputSchema(input);
147
- return outputSchema ? strictify(outputSchema) : void 0;
167
+ return outputSchema ? strictify(outputSchema, { provider }) : void 0;
168
+ }
169
+ function buildAndValidateStrictOutputSchema(input, provider = parseProviderRoute(input.model).provider) {
170
+ const outputSchema = buildStrictOutputSchema(input, provider);
171
+ serializeAndValidateDispatchSchema(outputSchema, provider);
172
+ return outputSchema;
148
173
  }
149
174
  function buildRawOutputSchema(input) {
150
- return input.tools?.length ? buildToolCallSchema(input.tools) : input.jsonSchema ? JSON.parse(input.jsonSchema) : void 0;
175
+ const callerOutputSchema = parseAndValidateCallerSchemas(input);
176
+ return input.tools?.length ? buildToolCallSchema(input.tools, callerOutputSchema) : callerOutputSchema;
151
177
  }
152
178
  function toEmulationResult(result) {
153
179
  const hasProviderCost = result.costUsd !== void 0 && result.costUsd > 0;
@@ -180,6 +206,6 @@ function toEmulationResult(result) {
180
206
  }
181
207
  const QgridDispatcher = new QgridDispatcherClass();
182
208
  //#endregion
183
- export { QgridDispatcher, QgridDispatcherClass, buildStrictOutputSchema };
209
+ export { QgridDispatcher, QgridDispatcherClass, buildAndValidateStrictOutputSchema, buildStrictOutputSchema };
184
210
 
185
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicWdyaWQuZGlzcGF0Y2hlci5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBwbGljYXRpb24vcWdyaWQvcWdyaWQuZGlzcGF0Y2hlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFFncmlkRGlzcGF0Y2hlciDigJQgcHJvdmlkZXIgZGlzcGF0Y2hlciDrnbzsmrDtjIUgKyDthqDtgbAg7LqQ7IucL+2GteqzhCDsi7HquIDthLQuXG4gKlxuICogLSDrqZTrqqjrpqwg7LqQ7IucIChNYXA8aWQsIFRva2VuU3Vic2V0QT4pIOuKlCBUb2tlblN1YnNjcmliZXIg6rCAIHBnIExJU1RFTi9OT1RJRlkg66GcIOqwseyLoFxuICogLSBPcGVuQUkvQW50aHJvcGljIOyalOyyreydgCDqsIEgcHJvdmlkZXIgZGlzcGF0Y2hlciDroZzrp4wg7Iuk7ZaJXG4gKiAtIFF1b3RhRXJyb3Ig64qUIOq3uOuMgOuhnCDsg4HsnIQg7KCE7YyMXG4gKi9cblxuaW1wb3J0IHsgdHlwZSBKc29uVmFsdWUgfSBmcm9tIFwiLi4vLi4vY29kZXgtcHJvdG9jb2wvc2VyZGVfanNvbi9Kc29uVmFsdWVcIjtcbmltcG9ydCB7IHR5cGUgQW50aHJvcGljRGlzcGF0Y2hlciB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvYW50aHJvcGljL2FudGhyb3BpYy1kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBnZXRBY2Nlc3NUb2tlbiB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL2NyZWRlbnRpYWxzXCI7XG5pbXBvcnQgeyBjYWxjdWxhdGVDb3N0VXNkIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3Byb3ZpZGVycy9jb21tb24vbW9kZWwtY29zdFwiO1xuaW1wb3J0IHtcbiAgdHlwZSBHZW5lcmF0ZVJlc3VsdCxcbiAgdHlwZSBTdHJlYW1DYWxsYmFja3MsXG59IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL3Byb3ZpZGVyLWRpc3BhdGNoZXJcIjtcbmltcG9ydCB7IHN0cmljdGlmeSB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL3N0cmljdGlmaWVyXCI7XG5pbXBvcnQgeyB0eXBlIE9wZW5BSURpc3BhdGNoZXIgfSBmcm9tIFwiLi4vLi4vdXRpbHMvcHJvdmlkZXJzL29wZW5haS9vcGVuYWktZGlzcGF0Y2hlclwiO1xuaW1wb3J0IHsgdHlwZSBUb2tlblN1YnNldEEgfSBmcm9tIFwiLi4vc29uYW11LmdlbmVyYXRlZFwiO1xuaW1wb3J0IHsgZGVjaWRlQ29udlJvdXRpbmcsIGlzc3VlQ29udkNvbnRleHQgfSBmcm9tIFwiLi9jb252LXJvdXRpbmdcIjtcbmltcG9ydCB7IHR5cGUgUXVlcnlJbnB1dCwgdHlwZSBRdWVyeU91dHB1dCwgdHlwZSBUb2tlblN0YXRzIH0gZnJvbSBcIi4vcWdyaWQudHlwZXNcIjtcbmltcG9ydCB7IG1hc2tUb2tlbiwgUHJvY2Vzc0Vycm9yLCBRdW90YUVycm9yIH0gZnJvbSBcIi4vcWdyaWQudHlwZXNcIjtcbmltcG9ydCB7IHR5cGUgVG9rZW5TdWJzY3JpYmVyIH0gZnJvbSBcIi4vdG9rZW4tc3Vic2NyaWJlclwiO1xuaW1wb3J0IHsgYXBwbHlUb29sQ2FsbEVtdWxhdGlvbiwgYnVpbGRUb29sQ2FsbFNjaGVtYSB9IGZyb20gXCIuL3Rvb2wtZW11bGF0aW9uXCI7XG5cbmV4cG9ydCBjbGFzcyBRZ3JpZERpc3BhdGNoZXJDbGFzcyB7XG4gIHRva2VucyA9IG5ldyBNYXA8bnVtYmVyLCBUb2tlblN1YnNldEE+KCk7XG5cbiAgLy8gVG9rZW5TdGF0cyBzaGFwZSDrs7TsobTsmqkuIOyLpOygnCBwcm92aWRlciDsmpTssq0g7Lm07Jq07YyF7J2AIOqwgSBkaXNwYXRjaGVyIOuhnCDsnbTrj5ntlojri6QuXG4gIHJlcXVlc3RDb3VudHMgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuXG4gIC8vIHNvbmFtdS5jb25maWcgb25TdGFydCDsl5DshJwg7LKY66as7ZWY64qUIOuzgOyImFxuICBzdWJzY3JpYmVyOiBUb2tlblN1YnNjcmliZXIgfCBudWxsID0gbnVsbDtcbiAgb3BlbmFpRGlzcGF0Y2hlcjogT3BlbkFJRGlzcGF0Y2hlciB8IG51bGwgPSBudWxsO1xuICBhbnRocm9waWNEaXNwYXRjaGVyOiBBbnRocm9waWNEaXNwYXRjaGVyIHwgbnVsbCA9IG51bGw7XG5cbiAgY291bnRPZihuYW1lOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnJlcXVlc3RDb3VudHMuZ2V0KG5hbWUpID8/IDA7XG4gIH1cblxuICAvLyBUb2tlblN1YnNjcmliZXIg7L2c67CxIOKAlCDsupDsi5wgbXV0YXRpb25cbiAgdXBzZXJ0Q2FjaGUoaWQ6IG51bWJlciwgcm93OiBUb2tlblN1YnNldEEpOiB2b2lkIHtcbiAgICB0aGlzLnRva2Vucy5zZXQoaWQsIHJvdyk7XG4gIH1cblxuICByZW1vdmVDYWNoZShpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy50b2tlbnMuZGVsZXRlKGlkKTtcbiAgfVxuXG4gIHJlcGxhY2VDYWNoZShyb3dzOiBUb2tlblN1YnNldEFbXSk6IHZvaWQge1xuICAgIHRoaXMudG9rZW5zID0gbmV3IE1hcChyb3dzLm1hcCgocikgPT4gW3IuaWQsIHJdKSk7XG4gIH1cblxuICBnZXRTdGF0cygpOiBUb2tlblN0YXRzW10ge1xuICAgIHJldHVybiBbLi4udGhpcy50b2tlbnMudmFsdWVzKCldLm1hcCgocikgPT4gKHtcbiAgICAgIHRva2VuOiBtYXNrVG9rZW4oZ2V0QWNjZXNzVG9rZW4oci5jcmVkZW50aWFscykpLFxuICAgICAgbmFtZTogci5uYW1lLFxuICAgICAgcHJvdmlkZXI6IHIucHJvdmlkZXIsXG4gICAgICByZXF1ZXN0czogdGhpcy5jb3VudE9mKHIubmFtZSksXG4gICAgfSkpO1xuICB9XG5cbiAgYXN5bmMgcXVlcnkoaW5wdXQ6IFF1ZXJ5SW5wdXQsIHRpbWVvdXRNcz86IG51bWJlcik6IFByb21pc2U8UXVlcnlPdXRwdXQ+IHtcbiAgICB2b2lkIHRpbWVvdXRNcztcblxuICAgIGlmIChpbnB1dC50b29scz8ubGVuZ3RoICYmIGlucHV0Lmpzb25TY2hlbWEpIHtcbiAgICAgIHRocm93IG5ldyBQcm9jZXNzRXJyb3IoXCJ0b29scyBhbmQganNvblNjaGVtYSBjYW5ub3QgYmUgdXNlZCB0b2dldGhlclwiKTtcbiAgICB9XG5cbiAgICBjb25zdCByb3V0ZSA9IHBhcnNlUHJvdmlkZXJSb3V0ZShpbnB1dC5tb2RlbCk7XG4gICAgY29uc3Qgb3V0cHV0U2NoZW1hID0gYnVpbGRTdHJpY3RPdXRwdXRTY2hlbWEoaW5wdXQpO1xuXG4gICAgLy8gcHJvdmlkZXIgcHJlZml4IHJvdXRpbmc6ICdvcGVuYWkvZ3B0LTUuNCcg4oaSIE9wZW5BSURpc3BhdGNoZXJcbiAgICBpZiAocm91dGUucHJvdmlkZXIgPT09IFwib3BlbmFpXCIpIHtcbiAgICAgIGlmICghdGhpcy5vcGVuYWlEaXNwYXRjaGVyKSB0aHJvdyBuZXcgUXVvdGFFcnJvcihcIk9wZW5BSSBkaXNwYXRjaGVyIG5vdCBpbml0aWFsaXplZFwiKTtcblxuICAgICAgY29uc3QgZGVjaXNpb24gPSBkZWNpZGVDb252Um91dGluZyhpbnB1dCk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLm9wZW5haURpc3BhdGNoZXIuZ2VuZXJhdGUoe1xuICAgICAgICBtb2RlbDogcm91dGUubW9kZWwsXG4gICAgICAgIHN5c3RlbVByb21wdDogaW5wdXQuc3lzdGVtLFxuICAgICAgICBvdXRwdXRTY2hlbWEsXG4gICAgICAgIGVmZm9ydDogaW5wdXQuZWZmb3J0LFxuICAgICAgICB2ZXJib3NpdHk6IGlucHV0LnZlcmJvc2l0eSxcbiAgICAgICAgcmVhc29uaW5nU3VtbWFyeTogaW5wdXQucmVhc29uaW5nU3VtbWFyeSxcbiAgICAgICAgc2VydmljZVRpZXI6IGlucHV0LnNlcnZpY2VUaWVyLFxuICAgICAgICBjb2xkSW5wdXQ6IGRlY2lzaW9uLmNvbGRJbnB1dCxcbiAgICAgICAgY29sZEhpc3Rvcnk6IGRlY2lzaW9uLmNvbGRIaXN0b3J5LFxuICAgICAgICByZXVzZTogZGVjaXNpb24ucmV1c2UsXG4gICAgICAgIHJldXNlSW5wdXQ6IGRlY2lzaW9uLnJldXNlSW5wdXQsXG4gICAgICAgIGltYWdlR2VuZXJhdGlvbjogaW5wdXQuaW1hZ2VHZW5lcmF0aW9uLFxuICAgICAgICBpbWFnZUdlbmVyYXRpb25PcHRpb25zOiBpbnB1dC5pbWFnZUdlbmVyYXRpb25PcHRpb25zLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIOydtOuvuOyngCDsmpTssq3snYAgY29sZC1vbmx5KFI4KeudvCDsnqzsgqzsmqkg7KKM7ZGc66W8IOuwnOq4ie2VmOyngCDslYrripTri6QuIOyijO2RnOulvCDsi6TsnLzrqbRcbiAgICAgIC8vIHNlc3Npb25LZXkg7IaM67mE7J6Q7J2YIHdhcm0g7KKM7ZGc66W8IOyjveydgCDsooztkZzroZwg642u7Ja07I2oIOuLpOydjCDthY3siqTtirggdHVybiDsnbQgY29sZCDroZwg65ao7Ja07KeE64ukLlxuICAgICAgY29uc3QgY29vcmQgPSBpbnB1dC5pbWFnZUdlbmVyYXRpb25cbiAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgOiBpc3N1ZUNvbnZDb250ZXh0KHJlc3VsdC50aHJlYWRDb29yZCwgZGVjaXNpb24pO1xuXG4gICAgICByZXR1cm4gYXBwbHlUb29sQ2FsbEVtdWxhdGlvbih0b0VtdWxhdGlvblJlc3VsdChyZXN1bHQpLCBpbnB1dC50b29scywgY29vcmQsIHJlc3VsdC5pbWFnZXMpO1xuICAgIH0gZWxzZSBpZiAocm91dGUucHJvdmlkZXIgPT09IFwiYW50aHJvcGljXCIpIHtcbiAgICAgIGlmICghdGhpcy5hbnRocm9waWNEaXNwYXRjaGVyKSB0aHJvdyBuZXcgUXVvdGFFcnJvcihcIkFudGhyb3BpYyBkaXNwYXRjaGVyIG5vdCBpbml0aWFsaXplZFwiKTtcblxuICAgICAgY29uc3QgZGVjaXNpb24gPSBkZWNpZGVDb252Um91dGluZyhpbnB1dCk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmFudGhyb3BpY0Rpc3BhdGNoZXIuZ2VuZXJhdGUoe1xuICAgICAgICAvLyBBbnRocm9waWNEaXNwYXRjaGVyIOuCtOu2gOyXkOyEnCDslYzslYTshJwgcHJvdmlkZXIgcHJlZml4IOulvCBjYW5vbmljYWwgbW9kZWwg66GcIOygleq3nO2ZlO2VqFxuICAgICAgICBtb2RlbDogaW5wdXQubW9kZWwsXG4gICAgICAgIHN5c3RlbVByb21wdDogaW5wdXQuc3lzdGVtLFxuICAgICAgICBvdXRwdXRTY2hlbWEsXG4gICAgICAgIGVmZm9ydDogaW5wdXQuZWZmb3J0LFxuICAgICAgICBjb2xkSW5wdXQ6IGRlY2lzaW9uLmNvbGRJbnB1dCxcbiAgICAgICAgY29sZEhpc3Rvcnk6IGRlY2lzaW9uLmNvbGRIaXN0b3J5LFxuICAgICAgICBpbWFnZUdlbmVyYXRpb246IGlucHV0LmltYWdlR2VuZXJhdGlvbixcbiAgICAgICAgaW1hZ2VHZW5lcmF0aW9uT3B0aW9uczogaW5wdXQuaW1hZ2VHZW5lcmF0aW9uT3B0aW9ucyxcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gYXBwbHlUb29sQ2FsbEVtdWxhdGlvbihcbiAgICAgICAgdG9FbXVsYXRpb25SZXN1bHQocmVzdWx0KSxcbiAgICAgICAgaW5wdXQudG9vbHMsXG4gICAgICAgIGlzc3VlQ29udkNvbnRleHQocmVzdWx0LnRocmVhZENvb3JkLCBkZWNpc2lvbiksXG4gICAgICApO1xuICAgIH1cblxuICAgIHRocm93IGRpcmVjdExsbUFwaUZhbGxiYWNrTm90SW1wbGVtZW50ZWQoaW5wdXQpO1xuICB9XG5cbiAgYXN5bmMgcXVlcnlTdHJlYW0oXG4gICAgaW5wdXQ6IFF1ZXJ5SW5wdXQsXG4gICAgY2I6IFN0cmVhbUNhbGxiYWNrczxRdWVyeU91dHB1dD4sXG4gICAgYWJvcnRTaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgcm91dGUgPSBwYXJzZVByb3ZpZGVyUm91dGUoaW5wdXQubW9kZWwpO1xuICAgIGNvbnN0IG91dHB1dFNjaGVtYSA9IGJ1aWxkU3RyaWN0T3V0cHV0U2NoZW1hKGlucHV0KTtcblxuICAgIGlmIChyb3V0ZS5wcm92aWRlciA9PT0gXCJvcGVuYWlcIikge1xuICAgICAgaWYgKCF0aGlzLm9wZW5haURpc3BhdGNoZXIpIHRocm93IG5ldyBRdW90YUVycm9yKFwiT3BlbkFJIGRpc3BhdGNoZXIgbm90IGluaXRpYWxpemVkXCIpO1xuXG4gICAgICBjb25zdCBkZWNpc2lvbiA9IGRlY2lkZUNvbnZSb3V0aW5nKGlucHV0KTtcbiAgICAgIGF3YWl0IHRoaXMub3BlbmFpRGlzcGF0Y2hlci5nZW5lcmF0ZVN0cmVhbShcbiAgICAgICAge1xuICAgICAgICAgIG1vZGVsOiByb3V0ZS5tb2RlbCxcbiAgICAgICAgICBzeXN0ZW1Qcm9tcHQ6IGlucHV0LnN5c3RlbSxcbiAgICAgICAgICBvdXRwdXRTY2hlbWEsXG4gICAgICAgICAgZWZmb3J0OiBpbnB1dC5lZmZvcnQsXG4gICAgICAgICAgdmVyYm9zaXR5OiBpbnB1dC52ZXJib3NpdHksXG4gICAgICAgICAgcmVhc29uaW5nU3VtbWFyeTogaW5wdXQucmVhc29uaW5nU3VtbWFyeSxcbiAgICAgICAgICBzZXJ2aWNlVGllcjogaW5wdXQuc2VydmljZVRpZXIsXG4gICAgICAgICAgY29sZElucHV0OiBkZWNpc2lvbi5jb2xkSW5wdXQsXG4gICAgICAgICAgY29sZEhpc3Rvcnk6IGRlY2lzaW9uLmNvbGRIaXN0b3J5LFxuICAgICAgICAgIHJldXNlOiBkZWNpc2lvbi5yZXVzZSxcbiAgICAgICAgICByZXVzZUlucHV0OiBkZWNpc2lvbi5yZXVzZUlucHV0LFxuICAgICAgICAgIGFib3J0U2lnbmFsLFxuICAgICAgICAgIC8vIOydtOuvuOyngCDtlIzrnpjqt7jrpbwg7KCE64us7ZW07JW8IGdlbmVyYXRlU3RyZWFtIOydmCBub24tc3RyZWFtIOyghOyaqSDqsbDrtoAoUjIp6rCAIOuwnOuPme2VnOuLpC5cbiAgICAgICAgICBpbWFnZUdlbmVyYXRpb246IGlucHV0LmltYWdlR2VuZXJhdGlvbixcbiAgICAgICAgICBpbWFnZUdlbmVyYXRpb25PcHRpb25zOiBpbnB1dC5pbWFnZUdlbmVyYXRpb25PcHRpb25zLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgb25EZWx0YTogY2Iub25EZWx0YSxcbiAgICAgICAgICBvblRocmVhZElkOiBjYi5vblRocmVhZElkLFxuICAgICAgICAgIG9uVHVybklkOiBjYi5vblR1cm5JZCxcbiAgICAgICAgICBvbkNvbXBsZXRlOiAodHVyblJlc3VsdCkgPT4ge1xuICAgICAgICAgICAgY2Iub25Db21wbGV0ZShcbiAgICAgICAgICAgICAgYXBwbHlUb29sQ2FsbEVtdWxhdGlvbihcbiAgICAgICAgICAgICAgICB0b0VtdWxhdGlvblJlc3VsdCh0dXJuUmVzdWx0KSxcbiAgICAgICAgICAgICAgICBpbnB1dC50b29scyxcbiAgICAgICAgICAgICAgICBpc3N1ZUNvbnZDb250ZXh0KHR1cm5SZXN1bHQudGhyZWFkQ29vcmQsIGRlY2lzaW9uKSxcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBvbkVycm9yOiBjYi5vbkVycm9yLFxuICAgICAgICB9LFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9IGVsc2UgaWYgKHJvdXRlLnByb3ZpZGVyID09PSBcImFudGhyb3BpY1wiKSB7XG4gICAgICBpZiAoIXRoaXMuYW50aHJvcGljRGlzcGF0Y2hlcikgdGhyb3cgbmV3IFF1b3RhRXJyb3IoXCJBbnRocm9waWMgZGlzcGF0Y2hlciBub3QgaW5pdGlhbGl6ZWRcIik7XG5cbiAgICAgIGNvbnN0IGRlY2lzaW9uID0gZGVjaWRlQ29udlJvdXRpbmcoaW5wdXQpO1xuICAgICAgYXdhaXQgdGhpcy5hbnRocm9waWNEaXNwYXRjaGVyLmdlbmVyYXRlU3RyZWFtKFxuICAgICAgICB7XG4gICAgICAgICAgbW9kZWw6IGlucHV0Lm1vZGVsLFxuICAgICAgICAgIHN5c3RlbVByb21wdDogaW5wdXQuc3lzdGVtLFxuICAgICAgICAgIG91dHB1dFNjaGVtYSxcbiAgICAgICAgICBlZmZvcnQ6IGlucHV0LmVmZm9ydCxcbiAgICAgICAgICBjb2xkSW5wdXQ6IGRlY2lzaW9uLmNvbGRJbnB1dCxcbiAgICAgICAgICBjb2xkSGlzdG9yeTogZGVjaXNpb24uY29sZEhpc3RvcnksXG4gICAgICAgICAgYWJvcnRTaWduYWwsXG4gICAgICAgICAgaW1hZ2VHZW5lcmF0aW9uOiBpbnB1dC5pbWFnZUdlbmVyYXRpb24sXG4gICAgICAgICAgaW1hZ2VHZW5lcmF0aW9uT3B0aW9uczogaW5wdXQuaW1hZ2VHZW5lcmF0aW9uT3B0aW9ucyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG9uRGVsdGE6IGNiLm9uRGVsdGEsXG4gICAgICAgICAgb25UaHJlYWRJZDogY2Iub25UaHJlYWRJZCxcbiAgICAgICAgICBvbkNvbXBsZXRlOiAodHVyblJlc3VsdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgaXNzdWVkQ29vcmQgPSBpc3N1ZUNvbnZDb250ZXh0KHR1cm5SZXN1bHQudGhyZWFkQ29vcmQsIGRlY2lzaW9uKTtcbiAgICAgICAgICAgIGNiLm9uQ29tcGxldGUoXG4gICAgICAgICAgICAgIGFwcGx5VG9vbENhbGxFbXVsYXRpb24odG9FbXVsYXRpb25SZXN1bHQodHVyblJlc3VsdCksIGlucHV0LnRvb2xzLCBpc3N1ZWRDb29yZCksXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgb25FcnJvcjogY2Iub25FcnJvcixcbiAgICAgICAgfSxcbiAgICAgICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhyb3cgZGlyZWN0TGxtQXBpRmFsbGJhY2tOb3RJbXBsZW1lbnRlZChpbnB1dCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcGFyc2VQcm92aWRlclJvdXRlKG1vZGVsOiBzdHJpbmcgfCB1bmRlZmluZWQpOiB7IHByb3ZpZGVyPzogc3RyaW5nOyBtb2RlbDogc3RyaW5nIH0ge1xuICBpZiAoIW1vZGVsPy5pbmNsdWRlcyhcIi9cIikpIHtcbiAgICByZXR1cm4geyBtb2RlbDogbW9kZWwgPz8gXCJcIiB9O1xuICB9XG5cbiAgY29uc3QgW3Byb3ZpZGVyLCByb3V0ZWRNb2RlbF0gPSBtb2RlbC5zcGxpdChcIi9cIiwgMik7XG4gIGlmICghcHJvdmlkZXIgfHwgIXJvdXRlZE1vZGVsKSB0aHJvdyBuZXcgUHJvY2Vzc0Vycm9yKFwidW5rbm93biBtb2RlbFwiKTtcbiAgcmV0dXJuIHsgcHJvdmlkZXIsIG1vZGVsOiByb3V0ZWRNb2RlbCB9O1xufVxuXG4vLyBxZ3JpZCBwcm92aWRlciBkaXNwYXRjaGVyIOyXkOyEnCDsspjrpqztlZjsp4Ag7JWK64qUIOuqqOuNuOydgCDtlqXtm4Qg7KeB7KCRIExMTSBBUEkg7Zi47LacIOyngOygkOycvOuhnCDrs7Trgrjri6QuXG5mdW5jdGlvbiBkaXJlY3RMbG1BcGlGYWxsYmFja05vdEltcGxlbWVudGVkKGlucHV0OiBRdWVyeUlucHV0KTogUHJvY2Vzc0Vycm9yIHtcbiAgcmV0dXJuIG5ldyBQcm9jZXNzRXJyb3IoXG4gICAgYERpcmVjdCBMTE0gQVBJIGZhbGxiYWNrIG5vdCBpbXBsZW1lbnRlZCBmb3IgbW9kZWw6ICR7aW5wdXQubW9kZWwgPz8gXCI8ZGVmYXVsdD5cIn1gLFxuICApO1xufVxuXG4vLyDrqqjrk6AgcHJvdmlkZXIoT3BlbkFJL0FudGhyb3BpYynqsIAg64+Z7J287ZWY6rKMIHN0cmljdCBvdXRwdXQgc2NoZW1hIOulvCDsk7Tri6QuXG4vL1xuLy8gU09OLTQ5NSDqtZDtm4g6IO2VnOuVjCBBbnRocm9waWMgcm91dGUg66eMIHJlcXVpcmVkIOulvCDsoJzqsbAob3B0aW9uYWxpemUp7ZW0IHBhcnRpYWwvcmVqZWN0ZWQgYXR0ZW1wdCDqsIBcbi8vIOyEnuyXrOuPhCDthrXqs7ztlZjqsowg7ZaI7Jy864KYLCDsi6TsuKEg6rKw6rO8IOq3uOqyjCDsmKTtnojroKQgXCLrqqjrjbjsnbQg67mE64qUIO2VhOuTnOulvCDtgqTsp7gg7IOd6561XCLtlZjrj4TroZ0g7Jyg64+E7ZaI64ukXG4vLyAocmVxdWlyZWQg7IK066awIHNjaGVtYSDripQg64iE6529IDAsIGxvb3NlIOuKlCDriITrnb0g64uk67CcKS4gc3RyaWN0IOuhnCDrkZDrqbQg66qo64247J20IOu5oOynkOyXhuydtCDssYTsmrDqs6AsXG4vLyDrk5zrrLzqsowg7Ja06rKo64+EIHJldHJ5PTEgKyDruYTsoJXsg4Eg7KKF66OM64qUIOygleynge2VnCDsl5Drn6woc3RyZWFtLWpzb24tYWRhcHRlcinroZwg67Cb7JWE7KSA64ukLlxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkU3RyaWN0T3V0cHV0U2NoZW1hKFxuICBpbnB1dDogUGljazxRdWVyeUlucHV0LCBcInRvb2xzXCIgfCBcImpzb25TY2hlbWFcIj4sXG4pOiBKc29uVmFsdWUgfCB1bmRlZmluZWQge1xuICBjb25zdCBvdXRwdXRTY2hlbWEgPSBidWlsZFJhd091dHB1dFNjaGVtYShpbnB1dCk7XG5cbiAgcmV0dXJuIG91dHB1dFNjaGVtYVxuICAgID8gKHN0cmljdGlmeShvdXRwdXRTY2hlbWEgYXMgUGFyYW1ldGVyczx0eXBlb2Ygc3RyaWN0aWZ5PlswXSkgYXMgSnNvblZhbHVlKVxuICAgIDogdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBidWlsZFJhd091dHB1dFNjaGVtYShcbiAgaW5wdXQ6IFBpY2s8UXVlcnlJbnB1dCwgXCJ0b29sc1wiIHwgXCJqc29uU2NoZW1hXCI+LFxuKTogSnNvblZhbHVlIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIGlucHV0LnRvb2xzPy5sZW5ndGhcbiAgICA/IGJ1aWxkVG9vbENhbGxTY2hlbWEoaW5wdXQudG9vbHMpXG4gICAgOiBpbnB1dC5qc29uU2NoZW1hXG4gICAgICA/IChKU09OLnBhcnNlKGlucHV0Lmpzb25TY2hlbWEpIGFzIEpzb25WYWx1ZSlcbiAgICAgIDogdW5kZWZpbmVkO1xufVxuXG4vLyBHZW5lcmF0ZVJlc3VsdChwcm92aWRlciBkaXNwYXRjaGVyIOydkeuLtSnrpbwgYXBwbHlUb29sQ2FsbEVtdWxhdGlvbiDsnoXroKUgc2hhcGUg66GcIOunpO2Vke2VnOuLpC5cbi8vIE9wZW5BSS9BbnRocm9waWMsIHF1ZXJ5L3F1ZXJ5U3RyZWFtIDQg6rK966Gc6rCAIOuPmeydvO2VmOqyjCDsk7Tri6QuXG4vLyBBbnRocm9waWMgYWRhcHRlciDripQgY2FjaGUgY3JlYXRpb24g7J2EIGlucHV0VG9rZW5zIOyXkCDtj6ztlajtlbQg7ZGc7KSA7ZmU7ZWY6rOgLCDrs4Trj4Qg7ZWE65Oc7JeQ64+EIOuztOyhtO2VnOuLpC5cbi8vIHBlci1yZXF1ZXN0IGNvc3Qg64qUIHByb3ZpZGVyIOqwgCDspIAg6rCS7J2EIOyasOyEoCDsgqzsmqntlZjqs6AsIOyXhuycvOuptCDqs7XthrUgY29zdCDtlajsiJjrpbwg7JO064ukLlxuZnVuY3Rpb24gdG9FbXVsYXRpb25SZXN1bHQoXG4gIHJlc3VsdDogR2VuZXJhdGVSZXN1bHQsXG4pOiBPbWl0PFF1ZXJ5T3V0cHV0LCBcImNvbnRlbnRcIiB8IFwiZmluaXNoUmVhc29uXCIgfCBcInJ1bkNvbnRleHRcIj4ge1xuICBjb25zdCBoYXNQcm92aWRlckNvc3QgPSByZXN1bHQuY29zdFVzZCAhPT0gdW5kZWZpbmVkICYmIHJlc3VsdC5jb3N0VXNkID4gMDtcbiAgcmV0dXJuIHtcbiAgICB0ZXh0OiByZXN1bHQudGV4dCxcbiAgICB0b2tlbk5hbWU6IHJlc3VsdC50b2tlbk5hbWUsXG4gICAgbW9kZWw6IHJlc3VsdC5tb2RlbCxcbiAgICByZXF1ZXN0ZWRNb2RlbDogcmVzdWx0LnJlcXVlc3RlZE1vZGVsLFxuICAgIG1vZGVsRmFsbGJhY2tzOiByZXN1bHQubW9kZWxGYWxsYmFja3MsXG4gICAgdXNhZ2U6IHtcbiAgICAgIGlucHV0X3Rva2VuczogcmVzdWx0LnVzYWdlLmlucHV0VG9rZW5zLFxuICAgICAgb3V0cHV0X3Rva2VuczogcmVzdWx0LnVzYWdlLm91dHB1dFRva2VucyxcbiAgICAgIGNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2VuczogcmVzdWx0LnVzYWdlLmNhY2hlQ3JlYXRpb25JbnB1dFRva2VucyA/PyAwLFxuICAgICAgY2FjaGVfY3JlYXRpb25fNW1faW5wdXRfdG9rZW5zOiByZXN1bHQudXNhZ2UuY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zNW0sXG4gICAgICBjYWNoZV9jcmVhdGlvbl8xaF9pbnB1dF90b2tlbnM6IHJlc3VsdC51c2FnZS5jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMxaCxcbiAgICAgIGNhY2hlX3JlYWRfaW5wdXRfdG9rZW5zOiByZXN1bHQudXNhZ2UuY2FjaGVkSW5wdXRUb2tlbnMsXG4gICAgfSxcbiAgICBkdXJhdGlvbk1zOiByZXN1bHQuZHVyYXRpb25NcyxcbiAgICB0dGZ0TXM6IHJlc3VsdC50dGZ0TXMgPz8gMCxcbiAgICBjb3N0VXNkOiBoYXNQcm92aWRlckNvc3RcbiAgICAgID8gcmVzdWx0LmNvc3RVc2QhXG4gICAgICA6IGNhbGN1bGF0ZUNvc3RVc2QocmVzdWx0Lm1vZGVsLCB7XG4gICAgICAgICAgaW5wdXRUb2tlbnM6IHJlc3VsdC51c2FnZS5pbnB1dFRva2VucyxcbiAgICAgICAgICBvdXRwdXRUb2tlbnM6IHJlc3VsdC51c2FnZS5vdXRwdXRUb2tlbnMsXG4gICAgICAgICAgY2FjaGVkSW5wdXRUb2tlbnM6IHJlc3VsdC51c2FnZS5jYWNoZWRJbnB1dFRva2VucyxcbiAgICAgICAgICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM6IHJlc3VsdC51c2FnZS5jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMgPz8gMCxcbiAgICAgICAgICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM1bTogcmVzdWx0LnVzYWdlLmNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczVtLFxuICAgICAgICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczFoOiByZXN1bHQudXNhZ2UuY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zMWgsXG4gICAgICAgIH0pLFxuICAgIGNvc3RTb3VyY2U6IGhhc1Byb3ZpZGVyQ29zdCA/IFwicHJvdmlkZXJcIiA6IFwicHJpY2luZ190YWJsZVwiLFxuICB9O1xufVxuXG5leHBvcnQgY29uc3QgUWdyaWREaXNwYXRjaGVyID0gbmV3IFFncmlkRGlzcGF0Y2hlckNsYXNzKCk7XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUF5QkEsSUFBYSx1QkFBYixNQUFrQztDQUNoQyx5QkFBUyxJQUFJLElBQTBCO0NBR3ZDLGdDQUFnQixJQUFJLElBQW9CO0NBR3hDLGFBQXFDO0NBQ3JDLG1CQUE0QztDQUM1QyxzQkFBa0Q7Q0FFbEQsUUFBUSxNQUFzQjtFQUM1QixPQUFPLEtBQUssY0FBYyxJQUFJLElBQUksS0FBSztDQUN6QztDQUdBLFlBQVksSUFBWSxLQUF5QjtFQUMvQyxLQUFLLE9BQU8sSUFBSSxJQUFJLEdBQUc7Q0FDekI7Q0FFQSxZQUFZLElBQWtCO0VBQzVCLEtBQUssT0FBTyxPQUFPLEVBQUU7Q0FDdkI7Q0FFQSxhQUFhLE1BQTRCO0VBQ3ZDLEtBQUssU0FBUyxJQUFJLElBQUksS0FBSyxLQUFLLE1BQU0sQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7Q0FDbEQ7Q0FFQSxXQUF5QjtFQUN2QixPQUFPLENBQUMsR0FBRyxLQUFLLE9BQU8sT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLE9BQU87R0FDM0MsT0FBTyxVQUFVLGVBQWUsRUFBRSxXQUFXLENBQUM7R0FDOUMsTUFBTSxFQUFFO0dBQ1IsVUFBVSxFQUFFO0dBQ1osVUFBVSxLQUFLLFFBQVEsRUFBRSxJQUFJO0VBQy9CLEVBQUU7Q0FDSjtDQUVBLE1BQU0sTUFBTSxPQUFtQixXQUEwQztFQUd2RSxJQUFJLE1BQU0sT0FBTyxVQUFVLE1BQU0sWUFDL0IsTUFBTSxJQUFJLGFBQWEsOENBQThDO0VBR3ZFLE1BQU0sUUFBUSxtQkFBbUIsTUFBTSxLQUFLO0VBQzVDLE1BQU0sZUFBZSx3QkFBd0IsS0FBSztFQUdsRCxJQUFJLE1BQU0sYUFBYSxV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
211
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicWdyaWQuZGlzcGF0Y2hlci5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBwbGljYXRpb24vcWdyaWQvcWdyaWQuZGlzcGF0Y2hlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFFncmlkRGlzcGF0Y2hlciDigJQgcHJvdmlkZXIgZGlzcGF0Y2hlciDrnbzsmrDtjIUgKyDthqDtgbAg7LqQ7IucL+2GteqzhCDsi7HquIDthLQuXG4gKlxuICogLSDrqZTrqqjrpqwg7LqQ7IucIChNYXA8aWQsIFRva2VuU3Vic2V0QT4pIOuKlCBUb2tlblN1YnNjcmliZXIg6rCAIHBnIExJU1RFTi9OT1RJRlkg66GcIOqwseyLoFxuICogLSBPcGVuQUkvQW50aHJvcGljIOyalOyyreydgCDqsIEgcHJvdmlkZXIgZGlzcGF0Y2hlciDroZzrp4wg7Iuk7ZaJXG4gKiAtIFF1b3RhRXJyb3Ig64qUIOq3uOuMgOuhnCDsg4HsnIQg7KCE7YyMXG4gKi9cblxuaW1wb3J0IHsgdHlwZSBKc29uVmFsdWUgfSBmcm9tIFwiLi4vLi4vY29kZXgtcHJvdG9jb2wvc2VyZGVfanNvbi9Kc29uVmFsdWVcIjtcbmltcG9ydCB7IHR5cGUgQW50aHJvcGljRGlzcGF0Y2hlciB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvYW50aHJvcGljL2FudGhyb3BpYy1kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBnZXRBY2Nlc3NUb2tlbiB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL2NyZWRlbnRpYWxzXCI7XG5pbXBvcnQgeyBjYWxjdWxhdGVDb3N0VXNkIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3Byb3ZpZGVycy9jb21tb24vbW9kZWwtY29zdFwiO1xuaW1wb3J0IHtcbiAgdHlwZSBHZW5lcmF0ZVJlc3VsdCxcbiAgdHlwZSBTdHJlYW1DYWxsYmFja3MsXG59IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL3Byb3ZpZGVyLWRpc3BhdGNoZXJcIjtcbmltcG9ydCB7XG4gIHBhcnNlQW5kVmFsaWRhdGVDYWxsZXJTY2hlbWFzLFxuICBzZXJpYWxpemVBbmRWYWxpZGF0ZURpc3BhdGNoU2NoZW1hLFxufSBmcm9tIFwiLi4vLi4vdXRpbHMvcHJvdmlkZXJzL2NvbW1vbi9zY2hlbWEtdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgc3RyaWN0aWZ5IH0gZnJvbSBcIi4uLy4uL3V0aWxzL3Byb3ZpZGVycy9jb21tb24vc3RyaWN0aWZpZXJcIjtcbmltcG9ydCB7IHR5cGUgT3BlbkFJRGlzcGF0Y2hlciB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvb3BlbmFpL29wZW5haS1kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyB0eXBlIFRva2VuU3Vic2V0QSB9IGZyb20gXCIuLi9zb25hbXUuZ2VuZXJhdGVkXCI7XG5pbXBvcnQgeyBkZWNpZGVDb252Um91dGluZywgaXNzdWVDb252Q29udGV4dCB9IGZyb20gXCIuL2NvbnYtcm91dGluZ1wiO1xuaW1wb3J0IHsgdHlwZSBRdWVyeUlucHV0LCB0eXBlIFF1ZXJ5T3V0cHV0LCB0eXBlIFRva2VuU3RhdHMgfSBmcm9tIFwiLi9xZ3JpZC50eXBlc1wiO1xuaW1wb3J0IHsgbWFza1Rva2VuLCBQcm9jZXNzRXJyb3IsIFF1b3RhRXJyb3IgfSBmcm9tIFwiLi9xZ3JpZC50eXBlc1wiO1xuaW1wb3J0IHsgdHlwZSBUb2tlblN1YnNjcmliZXIgfSBmcm9tIFwiLi90b2tlbi1zdWJzY3JpYmVyXCI7XG5pbXBvcnQgeyBhcHBseVRvb2xDYWxsRW11bGF0aW9uIH0gZnJvbSBcIi4vdG9vbC1lbXVsYXRpb25cIjtcbmltcG9ydCB7IGJ1aWxkVG9vbENhbGxTY2hlbWEgfSBmcm9tIFwiLi90b29sLWVtdWxhdGlvbi1zY2hlbWFcIjtcblxuZXhwb3J0IGNsYXNzIFFncmlkRGlzcGF0Y2hlckNsYXNzIHtcbiAgdG9rZW5zID0gbmV3IE1hcDxudW1iZXIsIFRva2VuU3Vic2V0QT4oKTtcblxuICAvLyBUb2tlblN0YXRzIHNoYXBlIOuztOyhtOyaqS4g7Iuk7KCcIHByb3ZpZGVyIOyalOyyrSDsubTsmrTtjIXsnYAg6rCBIGRpc3BhdGNoZXIg66GcIOydtOuPme2WiOuLpC5cbiAgcmVxdWVzdENvdW50cyA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG5cbiAgLy8gc29uYW11LmNvbmZpZyBvblN0YXJ0IOyXkOyEnCDsspjrpqztlZjripQg67OA7IiYXG4gIHN1YnNjcmliZXI6IFRva2VuU3Vic2NyaWJlciB8IG51bGwgPSBudWxsO1xuICBvcGVuYWlEaXNwYXRjaGVyOiBPcGVuQUlEaXNwYXRjaGVyIHwgbnVsbCA9IG51bGw7XG4gIGFudGhyb3BpY0Rpc3BhdGNoZXI6IEFudGhyb3BpY0Rpc3BhdGNoZXIgfCBudWxsID0gbnVsbDtcblxuICBjb3VudE9mKG5hbWU6IHN0cmluZyk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdENvdW50cy5nZXQobmFtZSkgPz8gMDtcbiAgfVxuXG4gIC8vIFRva2VuU3Vic2NyaWJlciDsvZzrsLEg4oCUIOy6kOyLnCBtdXRhdGlvblxuICB1cHNlcnRDYWNoZShpZDogbnVtYmVyLCByb3c6IFRva2VuU3Vic2V0QSk6IHZvaWQge1xuICAgIHRoaXMudG9rZW5zLnNldChpZCwgcm93KTtcbiAgfVxuXG4gIHJlbW92ZUNhY2hlKGlkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnRva2Vucy5kZWxldGUoaWQpO1xuICB9XG5cbiAgcmVwbGFjZUNhY2hlKHJvd3M6IFRva2VuU3Vic2V0QVtdKTogdm9pZCB7XG4gICAgdGhpcy50b2tlbnMgPSBuZXcgTWFwKHJvd3MubWFwKChyKSA9PiBbci5pZCwgcl0pKTtcbiAgfVxuXG4gIGdldFN0YXRzKCk6IFRva2VuU3RhdHNbXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLnRva2Vucy52YWx1ZXMoKV0ubWFwKChyKSA9PiAoe1xuICAgICAgdG9rZW46IG1hc2tUb2tlbihnZXRBY2Nlc3NUb2tlbihyLmNyZWRlbnRpYWxzKSksXG4gICAgICBuYW1lOiByLm5hbWUsXG4gICAgICBwcm92aWRlcjogci5wcm92aWRlcixcbiAgICAgIHJlcXVlc3RzOiB0aGlzLmNvdW50T2Yoci5uYW1lKSxcbiAgICB9KSk7XG4gIH1cblxuICBhc3luYyBxdWVyeShpbnB1dDogUXVlcnlJbnB1dCwgYWJvcnRTaWduYWw/OiBBYm9ydFNpZ25hbCk6IFByb21pc2U8UXVlcnlPdXRwdXQ+IHtcbiAgICBjb25zdCByb3V0ZSA9IHBhcnNlUHJvdmlkZXJSb3V0ZShpbnB1dC5tb2RlbCk7XG4gICAgY29uc3Qgb3V0cHV0U2NoZW1hID0gYnVpbGRBbmRWYWxpZGF0ZVN0cmljdE91dHB1dFNjaGVtYShpbnB1dCwgcm91dGUucHJvdmlkZXIpO1xuICAgIC8vIHRvb2xzK2pzb25TY2hlbWEg7ZWp7ISxIOyLnCBzdHJ1Y3R1cmVkIGVudmVsb3BlIOuUlOy9lOuNlOulvCDsk7Tri6QuIDTqsJwg67Cp7LacIOyngOygkOydtCDqs7XsnKDtlZjripQg64uo7J28IO2MkOyglS5cbiAgICBjb25zdCBhbnN3ZXJNb2RlID0gaW5wdXQuanNvblNjaGVtYSA/IChcInN0cnVjdHVyZWRcIiBhcyBjb25zdCkgOiAoXCJsZWdhY3lcIiBhcyBjb25zdCk7XG5cbiAgICAvLyBwcm92aWRlciBwcmVmaXggcm91dGluZzogJ29wZW5haS9ncHQtNS40JyDihpIgT3BlbkFJRGlzcGF0Y2hlclxuICAgIGlmIChyb3V0ZS5wcm92aWRlciA9PT0gXCJvcGVuYWlcIikge1xuICAgICAgaWYgKCF0aGlzLm9wZW5haURpc3BhdGNoZXIpIHRocm93IG5ldyBRdW90YUVycm9yKFwiT3BlbkFJIGRpc3BhdGNoZXIgbm90IGluaXRpYWxpemVkXCIpO1xuXG4gICAgICBjb25zdCBkZWNpc2lvbiA9IGRlY2lkZUNvbnZSb3V0aW5nKGlucHV0KTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMub3BlbmFpRGlzcGF0Y2hlci5nZW5lcmF0ZSh7XG4gICAgICAgIG1vZGVsOiByb3V0ZS5tb2RlbCxcbiAgICAgICAgc3lzdGVtUHJvbXB0OiBpbnB1dC5zeXN0ZW0sXG4gICAgICAgIG91dHB1dFNjaGVtYSxcbiAgICAgICAgZWZmb3J0OiBpbnB1dC5lZmZvcnQsXG4gICAgICAgIHZlcmJvc2l0eTogaW5wdXQudmVyYm9zaXR5LFxuICAgICAgICByZWFzb25pbmdTdW1tYXJ5OiBpbnB1dC5yZWFzb25pbmdTdW1tYXJ5LFxuICAgICAgICBzZXJ2aWNlVGllcjogaW5wdXQuc2VydmljZVRpZXIsXG4gICAgICAgIGNvbGRJbnB1dDogZGVjaXNpb24uY29sZElucHV0LFxuICAgICAgICBjb2xkSGlzdG9yeTogZGVjaXNpb24uY29sZEhpc3RvcnksXG4gICAgICAgIHJldXNlOiBkZWNpc2lvbi5yZXVzZSxcbiAgICAgICAgcmV1c2VJbnB1dDogZGVjaXNpb24ucmV1c2VJbnB1dCxcbiAgICAgICAgYWJvcnRTaWduYWwsXG4gICAgICAgIGltYWdlR2VuZXJhdGlvbjogaW5wdXQuaW1hZ2VHZW5lcmF0aW9uLFxuICAgICAgICBpbWFnZUdlbmVyYXRpb25PcHRpb25zOiBpbnB1dC5pbWFnZUdlbmVyYXRpb25PcHRpb25zLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIOydtOuvuOyngCDsmpTssq3snYAgY29sZC1vbmx5KFI4KeudvCDsnqzsgqzsmqkg7KKM7ZGc66W8IOuwnOq4ie2VmOyngCDslYrripTri6QuIOyijO2RnOulvCDsi6TsnLzrqbRcbiAgICAgIC8vIHNlc3Npb25LZXkg7IaM67mE7J6Q7J2YIHdhcm0g7KKM7ZGc66W8IOyjveydgCDsooztkZzroZwg642u7Ja07I2oIOuLpOydjCDthY3siqTtirggdHVybiDsnbQgY29sZCDroZwg65ao7Ja07KeE64ukLlxuICAgICAgY29uc3QgY29vcmQgPSBpbnB1dC5pbWFnZUdlbmVyYXRpb25cbiAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgOiBpc3N1ZUNvbnZDb250ZXh0KHJlc3VsdC50aHJlYWRDb29yZCwgZGVjaXNpb24pO1xuXG4gICAgICByZXR1cm4gYXBwbHlUb29sQ2FsbEVtdWxhdGlvbih0b0VtdWxhdGlvblJlc3VsdChyZXN1bHQpLCBpbnB1dC50b29scywge1xuICAgICAgICB0aHJlYWRDb29yZDogY29vcmQsXG4gICAgICAgIGltYWdlczogcmVzdWx0LmltYWdlcyxcbiAgICAgICAgYW5zd2VyTW9kZSxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAocm91dGUucHJvdmlkZXIgPT09IFwiYW50aHJvcGljXCIpIHtcbiAgICAgIGlmICghdGhpcy5hbnRocm9waWNEaXNwYXRjaGVyKSB0aHJvdyBuZXcgUXVvdGFFcnJvcihcIkFudGhyb3BpYyBkaXNwYXRjaGVyIG5vdCBpbml0aWFsaXplZFwiKTtcblxuICAgICAgY29uc3QgZGVjaXNpb24gPSBkZWNpZGVDb252Um91dGluZyhpbnB1dCk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmFudGhyb3BpY0Rpc3BhdGNoZXIuZ2VuZXJhdGUoe1xuICAgICAgICAvLyBBbnRocm9waWNEaXNwYXRjaGVyIOuCtOu2gOyXkOyEnCDslYzslYTshJwgcHJvdmlkZXIgcHJlZml4IOulvCBjYW5vbmljYWwgbW9kZWwg66GcIOygleq3nO2ZlO2VqFxuICAgICAgICBtb2RlbDogaW5wdXQubW9kZWwsXG4gICAgICAgIHN5c3RlbVByb21wdDogaW5wdXQuc3lzdGVtLFxuICAgICAgICBvdXRwdXRTY2hlbWEsXG4gICAgICAgIGVmZm9ydDogaW5wdXQuZWZmb3J0LFxuICAgICAgICB0aW1lb3V0TXM6IGlucHV0LnRpbWVvdXQsXG4gICAgICAgIGFib3J0U2lnbmFsLFxuICAgICAgICBjb2xkSW5wdXQ6IGRlY2lzaW9uLmNvbGRJbnB1dCxcbiAgICAgICAgY29sZEhpc3Rvcnk6IGRlY2lzaW9uLmNvbGRIaXN0b3J5LFxuICAgICAgICBpbWFnZUdlbmVyYXRpb246IGlucHV0LmltYWdlR2VuZXJhdGlvbixcbiAgICAgICAgaW1hZ2VHZW5lcmF0aW9uT3B0aW9uczogaW5wdXQuaW1hZ2VHZW5lcmF0aW9uT3B0aW9ucyxcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gYXBwbHlUb29sQ2FsbEVtdWxhdGlvbih0b0VtdWxhdGlvblJlc3VsdChyZXN1bHQpLCBpbnB1dC50b29scywge1xuICAgICAgICB0aHJlYWRDb29yZDogaXNzdWVDb252Q29udGV4dChyZXN1bHQudGhyZWFkQ29vcmQsIGRlY2lzaW9uKSxcbiAgICAgICAgYW5zd2VyTW9kZSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRocm93IGRpcmVjdExsbUFwaUZhbGxiYWNrTm90SW1wbGVtZW50ZWQoaW5wdXQpO1xuICB9XG5cbiAgYXN5bmMgcXVlcnlTdHJlYW0oXG4gICAgaW5wdXQ6IFF1ZXJ5SW5wdXQsXG4gICAgY2I6IFN0cmVhbUNhbGxiYWNrczxRdWVyeU91dHB1dD4sXG4gICAgYWJvcnRTaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgcm91dGUgPSBwYXJzZVByb3ZpZGVyUm91dGUoaW5wdXQubW9kZWwpO1xuICAgIGNvbnN0IG91dHB1dFNjaGVtYSA9IGJ1aWxkQW5kVmFsaWRhdGVTdHJpY3RPdXRwdXRTY2hlbWEoaW5wdXQsIHJvdXRlLnByb3ZpZGVyKTtcbiAgICAvLyB0b29scytqc29uU2NoZW1hIO2VqeyEsSDsi5wgc3RydWN0dXJlZCBlbnZlbG9wZSDrlJTsvZTrjZTrpbwg7JO064ukLiA06rCcIOuwqey2nCDsp4DsoJDsnbQg6rO17Jyg7ZWY64qUIOuLqOydvCDtjJDsoJUuXG4gICAgY29uc3QgYW5zd2VyTW9kZSA9IGlucHV0Lmpzb25TY2hlbWEgPyAoXCJzdHJ1Y3R1cmVkXCIgYXMgY29uc3QpIDogKFwibGVnYWN5XCIgYXMgY29uc3QpO1xuXG4gICAgaWYgKHJvdXRlLnByb3ZpZGVyID09PSBcIm9wZW5haVwiKSB7XG4gICAgICBpZiAoIXRoaXMub3BlbmFpRGlzcGF0Y2hlcikgdGhyb3cgbmV3IFF1b3RhRXJyb3IoXCJPcGVuQUkgZGlzcGF0Y2hlciBub3QgaW5pdGlhbGl6ZWRcIik7XG5cbiAgICAgIGNvbnN0IGRlY2lzaW9uID0gZGVjaWRlQ29udlJvdXRpbmcoaW5wdXQpO1xuICAgICAgYXdhaXQgdGhpcy5vcGVuYWlEaXNwYXRjaGVyLmdlbmVyYXRlU3RyZWFtKFxuICAgICAgICB7XG4gICAgICAgICAgbW9kZWw6IHJvdXRlLm1vZGVsLFxuICAgICAgICAgIHN5c3RlbVByb21wdDogaW5wdXQuc3lzdGVtLFxuICAgICAgICAgIG91dHB1dFNjaGVtYSxcbiAgICAgICAgICBlZmZvcnQ6IGlucHV0LmVmZm9ydCxcbiAgICAgICAgICB2ZXJib3NpdHk6IGlucHV0LnZlcmJvc2l0eSxcbiAgICAgICAgICByZWFzb25pbmdTdW1tYXJ5OiBpbnB1dC5yZWFzb25pbmdTdW1tYXJ5LFxuICAgICAgICAgIHNlcnZpY2VUaWVyOiBpbnB1dC5zZXJ2aWNlVGllcixcbiAgICAgICAgICBjb2xkSW5wdXQ6IGRlY2lzaW9uLmNvbGRJbnB1dCxcbiAgICAgICAgICBjb2xkSGlzdG9yeTogZGVjaXNpb24uY29sZEhpc3RvcnksXG4gICAgICAgICAgcmV1c2U6IGRlY2lzaW9uLnJldXNlLFxuICAgICAgICAgIHJldXNlSW5wdXQ6IGRlY2lzaW9uLnJldXNlSW5wdXQsXG4gICAgICAgICAgYWJvcnRTaWduYWwsXG4gICAgICAgICAgLy8g7J2066+47KeAIO2UjOuemOq3uOulvCDsoITri6ztlbTslbwgZ2VuZXJhdGVTdHJlYW0g7J2YIG5vbi1zdHJlYW0g7KCE7JqpIOqxsOu2gChSMinqsIAg67Cc64+Z7ZWc64ukLlxuICAgICAgICAgIGltYWdlR2VuZXJhdGlvbjogaW5wdXQuaW1hZ2VHZW5lcmF0aW9uLFxuICAgICAgICAgIGltYWdlR2VuZXJhdGlvbk9wdGlvbnM6IGlucHV0LmltYWdlR2VuZXJhdGlvbk9wdGlvbnMsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBvbkRlbHRhOiBjYi5vbkRlbHRhLFxuICAgICAgICAgIG9uVGhyZWFkSWQ6IGNiLm9uVGhyZWFkSWQsXG4gICAgICAgICAgb25UdXJuSWQ6IGNiLm9uVHVybklkLFxuICAgICAgICAgIG9uQ29tcGxldGU6ICh0dXJuUmVzdWx0KSA9PiB7XG4gICAgICAgICAgICBjYi5vbkNvbXBsZXRlKFxuICAgICAgICAgICAgICBhcHBseVRvb2xDYWxsRW11bGF0aW9uKHRvRW11bGF0aW9uUmVzdWx0KHR1cm5SZXN1bHQpLCBpbnB1dC50b29scywge1xuICAgICAgICAgICAgICAgIHRocmVhZENvb3JkOiBpc3N1ZUNvbnZDb250ZXh0KHR1cm5SZXN1bHQudGhyZWFkQ29vcmQsIGRlY2lzaW9uKSxcbiAgICAgICAgICAgICAgICBhbnN3ZXJNb2RlLFxuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBvbkVycm9yOiBjYi5vbkVycm9yLFxuICAgICAgICB9LFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9IGVsc2UgaWYgKHJvdXRlLnByb3ZpZGVyID09PSBcImFudGhyb3BpY1wiKSB7XG4gICAgICBpZiAoIXRoaXMuYW50aHJvcGljRGlzcGF0Y2hlcikgdGhyb3cgbmV3IFF1b3RhRXJyb3IoXCJBbnRocm9waWMgZGlzcGF0Y2hlciBub3QgaW5pdGlhbGl6ZWRcIik7XG5cbiAgICAgIGNvbnN0IGRlY2lzaW9uID0gZGVjaWRlQ29udlJvdXRpbmcoaW5wdXQpO1xuICAgICAgYXdhaXQgdGhpcy5hbnRocm9waWNEaXNwYXRjaGVyLmdlbmVyYXRlU3RyZWFtKFxuICAgICAgICB7XG4gICAgICAgICAgbW9kZWw6IGlucHV0Lm1vZGVsLFxuICAgICAgICAgIHN5c3RlbVByb21wdDogaW5wdXQuc3lzdGVtLFxuICAgICAgICAgIG91dHB1dFNjaGVtYSxcbiAgICAgICAgICBlZmZvcnQ6IGlucHV0LmVmZm9ydCxcbiAgICAgICAgICBjb2xkSW5wdXQ6IGRlY2lzaW9uLmNvbGRJbnB1dCxcbiAgICAgICAgICBjb2xkSGlzdG9yeTogZGVjaXNpb24uY29sZEhpc3RvcnksXG4gICAgICAgICAgdGltZW91dE1zOiBpbnB1dC50aW1lb3V0LFxuICAgICAgICAgIGFib3J0U2lnbmFsLFxuICAgICAgICAgIGltYWdlR2VuZXJhdGlvbjogaW5wdXQuaW1hZ2VHZW5lcmF0aW9uLFxuICAgICAgICAgIGltYWdlR2VuZXJhdGlvbk9wdGlvbnM6IGlucHV0LmltYWdlR2VuZXJhdGlvbk9wdGlvbnMsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBvbkRlbHRhOiBjYi5vbkRlbHRhLFxuICAgICAgICAgIG9uVGhyZWFkSWQ6IGNiLm9uVGhyZWFkSWQsXG4gICAgICAgICAgb25Db21wbGV0ZTogKHR1cm5SZXN1bHQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGlzc3VlZENvb3JkID0gaXNzdWVDb252Q29udGV4dCh0dXJuUmVzdWx0LnRocmVhZENvb3JkLCBkZWNpc2lvbik7XG4gICAgICAgICAgICBjYi5vbkNvbXBsZXRlKFxuICAgICAgICAgICAgICBhcHBseVRvb2xDYWxsRW11bGF0aW9uKHRvRW11bGF0aW9uUmVzdWx0KHR1cm5SZXN1bHQpLCBpbnB1dC50b29scywge1xuICAgICAgICAgICAgICAgIHRocmVhZENvb3JkOiBpc3N1ZWRDb29yZCxcbiAgICAgICAgICAgICAgICBhbnN3ZXJNb2RlLFxuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBvbkVycm9yOiBjYi5vbkVycm9yLFxuICAgICAgICB9LFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aHJvdyBkaXJlY3RMbG1BcGlGYWxsYmFja05vdEltcGxlbWVudGVkKGlucHV0KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3ZpZGVyUm91dGUobW9kZWw6IHN0cmluZyB8IHVuZGVmaW5lZCk6IHsgcHJvdmlkZXI/OiBzdHJpbmc7IG1vZGVsOiBzdHJpbmcgfSB7XG4gIGlmICghbW9kZWw/LmluY2x1ZGVzKFwiL1wiKSkge1xuICAgIHJldHVybiB7IG1vZGVsOiBtb2RlbCA/PyBcIlwiIH07XG4gIH1cblxuICBjb25zdCBbcHJvdmlkZXIsIHJvdXRlZE1vZGVsXSA9IG1vZGVsLnNwbGl0KFwiL1wiLCAyKTtcbiAgaWYgKCFwcm92aWRlciB8fCAhcm91dGVkTW9kZWwpIHRocm93IG5ldyBQcm9jZXNzRXJyb3IoXCJ1bmtub3duIG1vZGVsXCIpO1xuICByZXR1cm4geyBwcm92aWRlciwgbW9kZWw6IHJvdXRlZE1vZGVsIH07XG59XG5cbi8vIHFncmlkIHByb3ZpZGVyIGRpc3BhdGNoZXIg7JeQ7IScIOyymOumrO2VmOyngCDslYrripQg66qo64247J2AIO2Wpe2bhCDsp4HsoJEgTExNIEFQSSDtmLjstpwg7KeA7KCQ7Jy866GcIOuztOuCuOuLpC5cbmZ1bmN0aW9uIGRpcmVjdExsbUFwaUZhbGxiYWNrTm90SW1wbGVtZW50ZWQoaW5wdXQ6IFF1ZXJ5SW5wdXQpOiBQcm9jZXNzRXJyb3Ige1xuICByZXR1cm4gbmV3IFByb2Nlc3NFcnJvcihcbiAgICBgRGlyZWN0IExMTSBBUEkgZmFsbGJhY2sgbm90IGltcGxlbWVudGVkIGZvciBtb2RlbDogJHtpbnB1dC5tb2RlbCA/PyBcIjxkZWZhdWx0PlwifWAsXG4gICk7XG59XG5cbi8vIOuqqOuToCBwcm92aWRlcihPcGVuQUkvQW50aHJvcGljKeqwgCDrj5nsnbztlZjqsowgc3RyaWN0IG91dHB1dCBzY2hlbWEg66W8IOyTtOuLpC5cbi8vXG4vLyBTT04tNDk1IOq1kO2biDog7ZWc65WMIEFudGhyb3BpYyByb3V0ZSDrp4wgcmVxdWlyZWQg66W8IOygnOqxsChvcHRpb25hbGl6ZSntlbQgcGFydGlhbC9yZWplY3RlZCBhdHRlbXB0IOqwgFxuLy8g7ISe7Jes64+EIO2GteqzvO2VmOqyjCDtlojsnLzrgpgsIOyLpOy4oSDqsrDqs7wg6re46rKMIOyYpO2eiOugpCBcIuuqqOuNuOydtCDruYTripQg7ZWE65Oc66W8IO2CpOynuCDsg53rnrVcIu2VmOuPhOuhnSDsnKDrj4Ttlojri6Rcbi8vIChyZXF1aXJlZCDsgrTrprAgc2NoZW1hIOuKlCDriITrnb0gMCwgbG9vc2Ug64qUIOuIhOudvSDri6TrsJwpLiBzdHJpY3Qg66GcIOuRkOuptCDrqqjrjbjsnbQg67mg7KeQ7JeG7J20IOyxhOyasOqzoCxcbi8vIOuTnOusvOqyjCDslrTqsqggcHJvdmlkZXIgcmV0cnkg7JiI7IKw7J2EIOyGjOynhO2VnCDruYTsoJXsg4Eg7KKF66OM64+EIOygleynge2VnCDsl5Drn6zroZwg67Cb7JWE7KSA64ukLlxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkU3RyaWN0T3V0cHV0U2NoZW1hKFxuICBpbnB1dDogUGljazxRdWVyeUlucHV0LCBcInRvb2xzXCIgfCBcImpzb25TY2hlbWFcIj4sXG4gIHByb3ZpZGVyPzogc3RyaW5nLFxuKTogSnNvblZhbHVlIHwgdW5kZWZpbmVkIHtcbiAgY29uc3Qgb3V0cHV0U2NoZW1hID0gYnVpbGRSYXdPdXRwdXRTY2hlbWEoaW5wdXQpO1xuXG4gIHJldHVybiBvdXRwdXRTY2hlbWFcbiAgICA/IChzdHJpY3RpZnkob3V0cHV0U2NoZW1hIGFzIFBhcmFtZXRlcnM8dHlwZW9mIHN0cmljdGlmeT5bMF0sIHsgcHJvdmlkZXIgfSkgYXMgSnNvblZhbHVlKVxuICAgIDogdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRBbmRWYWxpZGF0ZVN0cmljdE91dHB1dFNjaGVtYShcbiAgaW5wdXQ6IFBpY2s8UXVlcnlJbnB1dCwgXCJtb2RlbFwiIHwgXCJ0b29sc1wiIHwgXCJqc29uU2NoZW1hXCI+LFxuICBwcm92aWRlciA9IHBhcnNlUHJvdmlkZXJSb3V0ZShpbnB1dC5tb2RlbCkucHJvdmlkZXIsXG4pOiBKc29uVmFsdWUgfCB1bmRlZmluZWQge1xuICBjb25zdCBvdXRwdXRTY2hlbWEgPSBidWlsZFN0cmljdE91dHB1dFNjaGVtYShpbnB1dCwgcHJvdmlkZXIpO1xuICBzZXJpYWxpemVBbmRWYWxpZGF0ZURpc3BhdGNoU2NoZW1hKG91dHB1dFNjaGVtYSwgcHJvdmlkZXIpO1xuICByZXR1cm4gb3V0cHV0U2NoZW1hO1xufVxuXG5mdW5jdGlvbiBidWlsZFJhd091dHB1dFNjaGVtYShcbiAgaW5wdXQ6IFBpY2s8UXVlcnlJbnB1dCwgXCJ0b29sc1wiIHwgXCJqc29uU2NoZW1hXCI+LFxuKTogSnNvblZhbHVlIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgY2FsbGVyT3V0cHV0U2NoZW1hID0gcGFyc2VBbmRWYWxpZGF0ZUNhbGxlclNjaGVtYXMoaW5wdXQpO1xuXG4gIHJldHVybiBpbnB1dC50b29scz8ubGVuZ3RoXG4gICAgPyBidWlsZFRvb2xDYWxsU2NoZW1hKGlucHV0LnRvb2xzLCBjYWxsZXJPdXRwdXRTY2hlbWEpXG4gICAgOiBjYWxsZXJPdXRwdXRTY2hlbWE7XG59XG5cbi8vIEdlbmVyYXRlUmVzdWx0KHByb3ZpZGVyIGRpc3BhdGNoZXIg7J2R64u1KeulvCBhcHBseVRvb2xDYWxsRW11bGF0aW9uIOyeheugpSBzaGFwZSDroZwg66ek7ZWR7ZWc64ukLlxuLy8gT3BlbkFJL0FudGhyb3BpYywgcXVlcnkvcXVlcnlTdHJlYW0gNCDqsr3roZzqsIAg64+Z7J287ZWY6rKMIOyTtOuLpC5cbi8vIEFudGhyb3BpYyBhZGFwdGVyIOuKlCBjYWNoZSBjcmVhdGlvbiDsnYQgaW5wdXRUb2tlbnMg7JeQIO2PrO2VqO2VtCDtkZzspIDtmZTtlZjqs6AsIOuzhOuPhCDtlYTrk5zsl5Drj4Qg67O07KG07ZWc64ukLlxuLy8gcGVyLXJlcXVlc3QgY29zdCDripQgcHJvdmlkZXIg6rCAIOykgCDqsJLsnYQg7Jqw7ISgIOyCrOyaqe2VmOqzoCwg7JeG7Jy866m0IOqzte2GtSBjb3N0IO2VqOyImOulvCDsk7Tri6QuXG5mdW5jdGlvbiB0b0VtdWxhdGlvblJlc3VsdChcbiAgcmVzdWx0OiBHZW5lcmF0ZVJlc3VsdCxcbik6IE9taXQ8UXVlcnlPdXRwdXQsIFwiY29udGVudFwiIHwgXCJmaW5pc2hSZWFzb25cIiB8IFwicnVuQ29udGV4dFwiPiB7XG4gIGNvbnN0IGhhc1Byb3ZpZGVyQ29zdCA9IHJlc3VsdC5jb3N0VXNkICE9PSB1bmRlZmluZWQgJiYgcmVzdWx0LmNvc3RVc2QgPiAwO1xuICByZXR1cm4ge1xuICAgIHRleHQ6IHJlc3VsdC50ZXh0LFxuICAgIHRva2VuTmFtZTogcmVzdWx0LnRva2VuTmFtZSxcbiAgICBtb2RlbDogcmVzdWx0Lm1vZGVsLFxuICAgIHJlcXVlc3RlZE1vZGVsOiByZXN1bHQucmVxdWVzdGVkTW9kZWwsXG4gICAgbW9kZWxGYWxsYmFja3M6IHJlc3VsdC5tb2RlbEZhbGxiYWNrcyxcbiAgICB1c2FnZToge1xuICAgICAgaW5wdXRfdG9rZW5zOiByZXN1bHQudXNhZ2UuaW5wdXRUb2tlbnMsXG4gICAgICBvdXRwdXRfdG9rZW5zOiByZXN1bHQudXNhZ2Uub3V0cHV0VG9rZW5zLFxuICAgICAgY2FjaGVfY3JlYXRpb25faW5wdXRfdG9rZW5zOiByZXN1bHQudXNhZ2UuY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zID8/IDAsXG4gICAgICBjYWNoZV9jcmVhdGlvbl81bV9pbnB1dF90b2tlbnM6IHJlc3VsdC51c2FnZS5jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM1bSxcbiAgICAgIGNhY2hlX2NyZWF0aW9uXzFoX2lucHV0X3Rva2VuczogcmVzdWx0LnVzYWdlLmNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczFoLFxuICAgICAgY2FjaGVfcmVhZF9pbnB1dF90b2tlbnM6IHJlc3VsdC51c2FnZS5jYWNoZWRJbnB1dFRva2VucyxcbiAgICB9LFxuICAgIGR1cmF0aW9uTXM6IHJlc3VsdC5kdXJhdGlvbk1zLFxuICAgIHR0ZnRNczogcmVzdWx0LnR0ZnRNcyA/PyAwLFxuICAgIGNvc3RVc2Q6IGhhc1Byb3ZpZGVyQ29zdFxuICAgICAgPyByZXN1bHQuY29zdFVzZCFcbiAgICAgIDogY2FsY3VsYXRlQ29zdFVzZChyZXN1bHQubW9kZWwsIHtcbiAgICAgICAgICBpbnB1dFRva2VuczogcmVzdWx0LnVzYWdlLmlucHV0VG9rZW5zLFxuICAgICAgICAgIG91dHB1dFRva2VuczogcmVzdWx0LnVzYWdlLm91dHB1dFRva2VucyxcbiAgICAgICAgICBjYWNoZWRJbnB1dFRva2VuczogcmVzdWx0LnVzYWdlLmNhY2hlZElucHV0VG9rZW5zLFxuICAgICAgICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczogcmVzdWx0LnVzYWdlLmNhY2hlQ3JlYXRpb25JbnB1dFRva2VucyA/PyAwLFxuICAgICAgICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczVtOiByZXN1bHQudXNhZ2UuY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zNW0sXG4gICAgICAgICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zMWg6IHJlc3VsdC51c2FnZS5jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMxaCxcbiAgICAgICAgfSksXG4gICAgY29zdFNvdXJjZTogaGFzUHJvdmlkZXJDb3N0ID8gXCJwcm92aWRlclwiIDogXCJwcmljaW5nX3RhYmxlXCIsXG4gIH07XG59XG5cbmV4cG9ydCBjb25zdCBRZ3JpZERpc3BhdGNoZXIgPSBuZXcgUWdyaWREaXNwYXRjaGVyQ2xhc3MoKTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBOEJBLElBQWEsdUJBQWIsTUFBa0M7Q0FDaEMseUJBQVMsSUFBSSxJQUEwQjtDQUd2QyxnQ0FBZ0IsSUFBSSxJQUFvQjtDQUd4QyxhQUFxQztDQUNyQyxtQkFBNEM7Q0FDNUMsc0JBQWtEO0NBRWxELFFBQVEsTUFBc0I7RUFDNUIsT0FBTyxLQUFLLGNBQWMsSUFBSSxJQUFJLEtBQUs7Q0FDekM7Q0FHQSxZQUFZLElBQVksS0FBeUI7RUFDL0MsS0FBSyxPQUFPLElBQUksSUFBSSxHQUFHO0NBQ3pCO0NBRUEsWUFBWSxJQUFrQjtFQUM1QixLQUFLLE9BQU8sT0FBTyxFQUFFO0NBQ3ZCO0NBRUEsYUFBYSxNQUE0QjtFQUN2QyxLQUFLLFNBQVMsSUFBSSxJQUFJLEtBQUssS0FBSyxNQUFNLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0NBQ2xEO0NBRUEsV0FBeUI7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