@cartanova/qgrid-cli 2.10.6 → 2.10.8
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.
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +3 -1
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +7 -7
- package/bundle/dist/application/qgrid/qgrid.frame.js +2 -2
- package/bundle/dist/application/request-log/request-log.model.js +3 -1
- package/bundle/dist/application/sonamu.generated.js +4 -1
- package/bundle/dist/application/sonamu.generated.sso.js +3 -1
- package/bundle/dist/i18n/sd.generated.js +2 -1
- package/bundle/dist/migrations/20261016155350_alter_request_logs_add1_alter1.js +15 -0
- package/bundle/dist/utils/providers/common/model-cost.js +14 -3
- package/bundle/dist/utils/providers/openai/openai-direct-client.js +1 -2
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +18 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +2 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +24 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +31 -19
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +2 -1
- package/bundle/src/application/qgrid/qgrid.frame.ts +1 -1
- package/bundle/src/application/request-log/request-log.entity.json +9 -0
- package/bundle/src/application/request-log/request-log.model.ts +4 -0
- package/bundle/src/application/sonamu.generated.sso.ts +2 -0
- package/bundle/src/application/sonamu.generated.ts +4 -0
- package/bundle/src/i18n/sd.generated.ts +1 -0
- package/bundle/src/migrations/20261016155350_alter_request_logs_add1_alter1.ts +15 -0
- package/bundle/src/utils/providers/common/model-cost.test.ts +28 -0
- package/bundle/src/utils/providers/common/model-cost.ts +19 -2
- package/bundle/src/utils/providers/openai/openai-direct-client.test.ts +47 -6
- package/bundle/src/utils/providers/openai/openai-direct-client.ts +2 -1
- package/bundle/web-dist/client/assets/index-Bw2s88Ot.css +1 -0
- package/bundle/web-dist/client/assets/{index-D9ryIyL-.js → index-DmCLKefs.js} +4 -4
- package/bundle/web-dist/client/assets/logs-BedgCqdB.js +1 -0
- package/bundle/web-dist/client/assets/{monit-DojxOLj6.js → monit-76gLIcaG.js} +1 -1
- package/bundle/web-dist/client/assets/request-model-CojtinqK.js +1 -0
- package/bundle/web-dist/client/assets/{routes-DXJhNvbI.js → routes-BcU0zD8h.js} +1 -1
- package/bundle/web-dist/client/assets/{services.generated-DqFYgWsY.js → services.generated-BsieU37H.js} +1 -1
- package/bundle/web-dist/client/assets/{settings-bopyz9pa.js → settings-DNVHSTQH.js} +1 -1
- package/bundle/web-dist/client/assets/show-dZPDC-qz.js +2 -0
- package/bundle/web-dist/client/assets/{tokens-2-AIi9sZ.js → tokens-BaQQcYUT.js} +1 -1
- package/bundle/web-dist/client/assets/{use-oauth-login-flow-CnqTWs_H.js → use-oauth-login-flow-D1jlq9ha.js} +1 -1
- package/bundle/web-dist/client/assets/{use-update-token-mutation-Cxb9K0fM.js → use-update-token-mutation-DAq0F8p-.js} +1 -1
- package/bundle/web-dist/client/index.html +3 -3
- package/bundle/web-dist/server/assets/{lazyRouteComponent-Bi0fYGLs.js → lazyRouteComponent-Dtd0NR4r.js} +2 -2
- package/bundle/web-dist/server/assets/{logs-CIVFxfoi.js → logs-l91avYif.js} +26 -15
- package/bundle/web-dist/server/assets/{monit-DBXezg7R.js → monit-DvzribSE.js} +3 -3
- package/bundle/web-dist/server/assets/{plus-BH-t4cm_.js → plus-KZrECewT.js} +1 -1
- package/bundle/web-dist/server/assets/{react-dom-CZ2eynd8.js → react-dom-B4a6-uuR.js} +1 -1
- package/bundle/web-dist/server/assets/{refresh-cw-CosAdcz0.js → refresh-cw-BND93JrF.js} +1 -1
- package/bundle/web-dist/server/assets/{request-model-CnCeaNLE.js → request-model-CbqfnQOJ.js} +19 -1
- package/bundle/web-dist/server/assets/{routes-COWYIvA-.js → routes-BAPWTizT.js} +4 -4
- package/bundle/web-dist/server/assets/{services.generated-607iwhMI.js → services.generated-CEbGjsI0.js} +1 -0
- package/bundle/web-dist/server/assets/{settings-C_6dpK5p.js → settings-BZR5HSAL.js} +3 -3
- package/bundle/web-dist/server/assets/{show-DY396-LD.js → show-CxVZTAdv.js} +11 -3
- package/bundle/web-dist/server/assets/{tokens-COvV7qUP.js → tokens-D1hb4eKk.js} +4 -4
- package/bundle/web-dist/server/assets/{use-oauth-login-flow-VYCYf3uv.js → use-oauth-login-flow-Cvdy0zF8.js} +1 -1
- package/bundle/web-dist/server/assets/{use-update-token-mutation-D8XYV5of.js → use-update-token-mutation-CfYmk_4_.js} +1 -1
- package/bundle/web-dist/server/entry-server.generated.js +13 -10
- package/package.json +1 -1
- package/skills/qgrid/references/ai-sdk-provider-contract.md +2 -1
- package/skills/qgrid/references/openai-codex-runtime.md +1 -1
- package/skills/qgrid/references/prompt-cache-and-usage.md +3 -0
- package/skills/qgrid/references/request-log-run-lifecycle.md +10 -0
- package/bundle/web-dist/client/assets/index-CvG4UB9v.css +0 -1
- package/bundle/web-dist/client/assets/logs-CLf2VNfk.js +0 -1
- package/bundle/web-dist/client/assets/request-model-D4CZPmnG.js +0 -1
- package/bundle/web-dist/client/assets/show-DbLD3MzB.js +0 -2
|
@@ -82,7 +82,6 @@ function socketEvents(socket, signal) {
|
|
|
82
82
|
socket.off("open", onOpen);
|
|
83
83
|
socket.off("message", onMessage);
|
|
84
84
|
socket.off("close", onClose);
|
|
85
|
-
socket.off("error", onError);
|
|
86
85
|
socket.off("unexpected-response", onUnexpectedResponse);
|
|
87
86
|
records.length = 0;
|
|
88
87
|
const closed = {
|
|
@@ -353,4 +352,4 @@ var OpenAIDirectClient = class {
|
|
|
353
352
|
//#endregion
|
|
354
353
|
export { OpenAIDirectClient, OpenAIHttpsTransport, OpenAIWebSocketTransport };
|
|
355
354
|
|
|
356
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLWRpcmVjdC1jbGllbnQuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLWRpcmVjdC1jbGllbnQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNyeXB0byBmcm9tIFwibm9kZTpjcnlwdG9cIjtcblxuaW1wb3J0IFdzQ2xpZW50LCB7IHR5cGUgQ2xpZW50T3B0aW9ucywgdHlwZSBSYXdEYXRhIH0gZnJvbSBcIndzXCI7XG5cbmltcG9ydCB7XG4gIGJ1aWxkQ29kZXhJZGVudGl0eUhlYWRlcnMsXG4gIGJ1aWxkT3BlbkFJUmVzcG9uc2VzUmVxdWVzdCxcbiAgQ0hBVEdQVF9DT0RFWF9SRVNQT05TRVNfVVJMLFxuICBub3JtYWxpemVPcGVuQUlFdmVudCxcbiAgT3BlbkFJUHJvdG9jb2xFcnJvcixcbiAgdHlwZSBPcGVuQUlOb3JtYWxpemVkRXZlbnQsXG4gIHR5cGUgT3BlbkFJUmVzcG9uc2VzT3B0aW9ucyxcbiAgdHlwZSBPcGVuQUlSZXNwb25zZXNSZXF1ZXN0LFxufSBmcm9tIFwiLi9vcGVuYWktYmFja2VuZC1wcm90b2NvbFwiO1xuaW1wb3J0IHtcbiAgYnVpbGRTdGFuZGFsb25lSW1hZ2VSZXF1ZXN0LFxuICByZWFkU3RhbmRhbG9uZUltYWdlUmVzcG9uc2UsXG59IGZyb20gXCIuL29wZW5haS1pbWFnZS1nZW5lcmF0aW9uXCI7XG5pbXBvcnQgeyBub3JtYWxpemVPcGVuQUlTU0UsIHR5cGUgT3BlbkFJRXZlbnRTdHJlYW0gfSBmcm9tIFwiLi9vcGVuYWktc3NlXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3BlbkFJRGlyZWN0Q3JlZGVudGlhbHMge1xuICBhY2Nlc3NUb2tlbjogc3RyaW5nO1xuICBhY2NvdW50SWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlUcmFuc3BvcnRSZXF1ZXN0IHtcbiAgYm9keTogT3BlbkFJUmVzcG9uc2VzUmVxdWVzdDtcbiAgc2lnbmFsPzogQWJvcnRTaWduYWw7XG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICB0aHJlYWRJZDogc3RyaW5nO1xuICBjbGllbnRSZXF1ZXN0SWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlSZXNwb25zZXNUcmFuc3BvcnQge1xuICBzdHJlYW0ocmVxdWVzdDogT3BlbkFJVHJhbnNwb3J0UmVxdWVzdCk6IE9wZW5BSUV2ZW50U3RyZWFtO1xuICBjbG9zZT8oKTogdm9pZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlIdHRwc1RyYW5zcG9ydE9wdGlvbnMge1xuICBjcmVkZW50aWFsczogT3BlbkFJRGlyZWN0Q3JlZGVudGlhbHM7XG4gIGZldGNoPzogdHlwZW9mIGZldGNoO1xuICByZWZyZXNoQ3JlZGVudGlhbHM/OiAoKSA9PiBQcm9taXNlPE9wZW5BSURpcmVjdENyZWRlbnRpYWxzPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlXZWJTb2NrZXRMaWtlIHtcbiAgb24oZXZlbnQ6IFwib3BlblwiLCBsaXN0ZW5lcjogKCkgPT4gdm9pZCk6IHRoaXM7XG4gIG9uKGV2ZW50OiBcIm1lc3NhZ2VcIiwgbGlzdGVuZXI6IChkYXRhOiBSYXdEYXRhLCBpc0JpbmFyeTogYm9vbGVhbikgPT4gdm9pZCk6IHRoaXM7XG4gIG9uKGV2ZW50OiBcImNsb3NlXCIsIGxpc3RlbmVyOiAoY29kZTogbnVtYmVyLCByZWFzb246IEJ1ZmZlcikgPT4gdm9pZCk6IHRoaXM7XG4gIG9uKGV2ZW50OiBcImVycm9yXCIsIGxpc3RlbmVyOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkKTogdGhpcztcbiAgb24oXG4gICAgZXZlbnQ6IFwidW5leHBlY3RlZC1yZXNwb25zZVwiLFxuICAgIGxpc3RlbmVyOiAocmVxdWVzdDogdW5rbm93biwgcmVzcG9uc2U6IHsgc3RhdHVzQ29kZT86IG51bWJlciB9KSA9PiB2b2lkLFxuICApOiB0aGlzO1xuICBvZmYoZXZlbnQ6IHN0cmluZywgbGlzdGVuZXI6ICguLi5hcmdzOiBuZXZlcltdKSA9PiB2b2lkKTogdGhpcztcbiAgc2VuZChkYXRhOiBzdHJpbmcsIGNhbGxiYWNrPzogKGVycm9yPzogRXJyb3IpID0+IHZvaWQpOiB2b2lkO1xuICBjbG9zZShjb2RlPzogbnVtYmVyLCByZWFzb24/OiBzdHJpbmcpOiB2b2lkO1xuICB0ZXJtaW5hdGUoKTogdm9pZDtcbn1cblxuZXhwb3J0IHR5cGUgT3BlbkFJV2ViU29ja2V0RmFjdG9yeSA9ICh1cmw6IHN0cmluZywgb3B0aW9uczogQ2xpZW50T3B0aW9ucykgPT4gT3BlbkFJV2ViU29ja2V0TGlrZTtcblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlXZWJTb2NrZXRUcmFuc3BvcnRPcHRpb25zIGV4dGVuZHMgT3BlbkFJSHR0cHNUcmFuc3BvcnRPcHRpb25zIHtcbiAgd2ViU29ja2V0RmFjdG9yeT86IE9wZW5BSVdlYlNvY2tldEZhY3Rvcnk7XG59XG5cbnR5cGUgU29ja2V0UmVjb3JkID1cbiAgfCB7IGtpbmQ6IFwib3BlblwiIH1cbiAgfCB7IGtpbmQ6IFwibWVzc2FnZVwiOyBkYXRhOiBSYXdEYXRhOyBpc0JpbmFyeTogYm9vbGVhbiB9XG4gIHwgeyBraW5kOiBcImNsb3NlXCI7IGNvZGU6IG51bWJlcjsgcmVhc29uOiBzdHJpbmcgfVxuICB8IHsga2luZDogXCJlcnJvclwiOyBlcnJvcjogRXJyb3IgfVxuICB8IHsga2luZDogXCJyZWplY3RlZFwiOyBzdGF0dXM/OiBudW1iZXIgfTtcblxuY29uc3QgTUFYX0JVRkZFUkVEX1NPQ0tFVF9SRUNPUkRTID0gMTYwMDtcblxuZnVuY3Rpb24gd2Vic29ja2V0VXJsKHVybDogc3RyaW5nKTogc3RyaW5nIHtcbiAgbGV0IHBhcnNlZDogVVJMO1xuICB0cnkge1xuICAgIHBhcnNlZCA9IG5ldyBVUkwodXJsKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgT3BlbkFJUHJvdG9jb2xFcnJvcihgSW52YWxpZCBPcGVuQUkgUmVzcG9uc2VzIFVSTDogJHtTdHJpbmcoZXJyb3IpfWApO1xuICB9XG4gIHBhcnNlZC5wcm90b2NvbCA9IHBhcnNlZC5wcm90b2NvbCA9PT0gXCJodHRwczpcIiA/IFwid3NzOlwiIDogXCJ3czpcIjtcbiAgcmV0dXJuIHBhcnNlZC50b1N0cmluZygpO1xufVxuXG5mdW5jdGlvbiByYXdEYXRhVGV4dChkYXRhOiBSYXdEYXRhKTogc3RyaW5nIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkpIHJldHVybiBCdWZmZXIuY29uY2F0KGRhdGEpLnRvU3RyaW5nKCk7XG4gIGlmIChkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHJldHVybiBCdWZmZXIuZnJvbShuZXcgVWludDhBcnJheShkYXRhKSkudG9TdHJpbmcoKTtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKGRhdGEpLnRvU3RyaW5nKCk7XG59XG5cbmZ1bmN0aW9uIHNvY2tldEV2ZW50cyhzb2NrZXQ6IE9wZW5BSVdlYlNvY2tldExpa2UsIHNpZ25hbD86IEFib3J0U2lnbmFsKSB7XG4gIGNvbnN0IHJlY29yZHM6IFNvY2tldFJlY29yZFtdID0gW107XG4gIGNvbnN0IHdhaXRlcnM6IEFycmF5PChyZWNvcmQ6IFNvY2tldFJlY29yZCkgPT4gdm9pZD4gPSBbXTtcbiAgbGV0IGFjdGl2ZSA9IHRydWU7XG4gIGNvbnN0IHB1c2ggPSAocmVjb3JkOiBTb2NrZXRSZWNvcmQpID0+IHtcbiAgICBpZiAoIWFjdGl2ZSkgcmV0dXJuO1xuICAgIGNvbnN0IHdhaXRlciA9IHdhaXRlcnMuc2hpZnQoKTtcbiAgICBpZiAod2FpdGVyKSB3YWl0ZXIocmVjb3JkKTtcbiAgICBlbHNlIGlmIChyZWNvcmRzLmxlbmd0aCA8IE1BWF9CVUZGRVJFRF9TT0NLRVRfUkVDT1JEUykgcmVjb3Jkcy5wdXNoKHJlY29yZCk7XG4gICAgZWxzZSB7XG4gICAgICBhY3RpdmUgPSBmYWxzZTtcbiAgICAgIHJlY29yZHMubGVuZ3RoID0gMDtcbiAgICAgIHNvY2tldC50ZXJtaW5hdGUoKTtcbiAgICAgIGNvbnN0IG92ZXJmbG93ID0ge1xuICAgICAgICBraW5kOiBcImVycm9yXCIgYXMgY29uc3QsXG4gICAgICAgIGVycm9yOiBuZXcgT3BlbkFJUHJvdG9jb2xFcnJvcihcbiAgICAgICAgICBgT3BlbkFJIFdlYlNvY2tldCBleGNlZWRlZCB0aGUgJHtNQVhfQlVGRkVSRURfU09DS0VUX1JFQ09SRFN9LXJlY29yZCByZWNlaXZlIGJ1ZmZlcmAsXG4gICAgICAgICAgXCJ3ZWJzb2NrZXRfYmFja3ByZXNzdXJlXCIsXG4gICAgICAgICksXG4gICAgICB9O1xuICAgICAgY29uc3Qgb3ZlcmZsb3dXYWl0ZXIgPSB3YWl0ZXJzLnNoaWZ0KCk7XG4gICAgICBpZiAob3ZlcmZsb3dXYWl0ZXIpIG92ZXJmbG93V2FpdGVyKG92ZXJmbG93KTtcbiAgICAgIGVsc2UgcmVjb3Jkcy5wdXNoKG92ZXJmbG93KTtcbiAgICB9XG4gIH07XG4gIGNvbnN0IG9uT3BlbiA9ICgpID0+IHB1c2goeyBraW5kOiBcIm9wZW5cIiB9KTtcbiAgY29uc3Qgb25NZXNzYWdlID0gKGRhdGE6IFJhd0RhdGEsIGlzQmluYXJ5OiBib29sZWFuKSA9PiBwdXNoKHsga2luZDogXCJtZXNzYWdlXCIsIGRhdGEsIGlzQmluYXJ5IH0pO1xuICBjb25zdCBvbkNsb3NlID0gKGNvZGU6IG51bWJlciwgcmVhc29uOiBCdWZmZXIpID0+XG4gICAgcHVzaCh7IGtpbmQ6IFwiY2xvc2VcIiwgY29kZSwgcmVhc29uOiByZWFzb24udG9TdHJpbmcoKSB9KTtcbiAgY29uc3Qgb25FcnJvciA9IChlcnJvcjogRXJyb3IpID0+IHB1c2goeyBraW5kOiBcImVycm9yXCIsIGVycm9yIH0pO1xuICBjb25zdCBvblVuZXhwZWN0ZWRSZXNwb25zZSA9IChfcmVxdWVzdDogdW5rbm93biwgcmVzcG9uc2U6IHsgc3RhdHVzQ29kZT86IG51bWJlciB9KSA9PlxuICAgIHB1c2goeyBraW5kOiBcInJlamVjdGVkXCIsIHN0YXR1czogcmVzcG9uc2Uuc3RhdHVzQ29kZSB9KTtcbiAgc29ja2V0Lm9uKFwib3BlblwiLCBvbk9wZW4pO1xuICBzb2NrZXQub24oXCJtZXNzYWdlXCIsIG9uTWVzc2FnZSk7XG4gIHNvY2tldC5vbihcImNsb3NlXCIsIG9uQ2xvc2UpO1xuICBzb2NrZXQub24oXCJlcnJvclwiLCBvbkVycm9yKTtcbiAgc29ja2V0Lm9uKFwidW5leHBlY3RlZC1yZXNwb25zZVwiLCBvblVuZXhwZWN0ZWRSZXNwb25zZSk7XG4gIGNvbnN0IG9uQWJvcnQgPSAoKSA9PiB7XG4gICAgc29ja2V0LnRlcm1pbmF0ZSgpO1xuICAgIHB1c2goeyBraW5kOiBcImVycm9yXCIsIGVycm9yOiBhYm9ydEVycm9yKHNpZ25hbCkgfSk7XG4gIH07XG4gIHNpZ25hbD8uYWRkRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIG9uQWJvcnQsIHsgb25jZTogdHJ1ZSB9KTtcbiAgcmV0dXJuIHtcbiAgICBuZXh0OiAoKSA9PlxuICAgICAgcmVjb3Jkcy5sZW5ndGhcbiAgICAgICAgPyBQcm9taXNlLnJlc29sdmUocmVjb3Jkcy5zaGlmdCgpISlcbiAgICAgICAgOiBuZXcgUHJvbWlzZTxTb2NrZXRSZWNvcmQ+KChyZXNvbHZlKSA9PiB3YWl0ZXJzLnB1c2gocmVzb2x2ZSkpLFxuICAgIGNsZWFudXA6ICgpID0+IHtcbiAgICAgIGFjdGl2ZSA9IGZhbHNlO1xuICAgICAgc2lnbmFsPy5yZW1vdmVFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgb25BYm9ydCk7XG4gICAgICBzb2NrZXQub2ZmKFwib3BlblwiLCBvbk9wZW4pO1xuICAgICAgc29ja2V0Lm9mZihcIm1lc3NhZ2VcIiwgb25NZXNzYWdlKTtcbiAgICAgIHNvY2tldC5vZmYoXCJjbG9zZVwiLCBvbkNsb3NlKTtcbiAgICAgIHNvY2tldC5vZmYoXCJlcnJvclwiLCBvbkVycm9yKTtcbiAgICAgIHNvY2tldC5vZmYoXCJ1bmV4cGVjdGVkLXJlc3BvbnNlXCIsIG9uVW5leHBlY3RlZFJlc3BvbnNlKTtcbiAgICAgIHJlY29yZHMubGVuZ3RoID0gMDtcbiAgICAgIGNvbnN0IGNsb3NlZCA9IHtcbiAgICAgICAga2luZDogXCJlcnJvclwiIGFzIGNvbnN0LFxuICAgICAgICBlcnJvcjogbmV3IE9wZW5BSVByb3RvY29sRXJyb3IoXCJPcGVuQUkgV2ViU29ja2V0IGV2ZW50IHN0cmVhbSB3YXMgY2xvc2VkXCIpLFxuICAgICAgfTtcbiAgICAgIHdhaXRlcnMuc3BsaWNlKDApLmZvckVhY2goKHdhaXRlcikgPT4gd2FpdGVyKGNsb3NlZCkpO1xuICAgIH0sXG4gICAgZGV0YWNoQWJvcnQ6ICgpID0+IHNpZ25hbD8ucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIG9uQWJvcnQpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBhYm9ydEVycm9yKHNpZ25hbD86IEFib3J0U2lnbmFsKTogRXJyb3Ige1xuICByZXR1cm4gc2lnbmFsPy5yZWFzb24gaW5zdGFuY2VvZiBFcnJvclxuICAgID8gc2lnbmFsLnJlYXNvblxuICAgIDogbmV3IERPTUV4Y2VwdGlvbihcIkFib3J0ZWRcIiwgXCJBYm9ydEVycm9yXCIpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBuZXh0UG9vbGVkUmVjb3JkKFxuICBldmVudHM6IFJldHVyblR5cGU8dHlwZW9mIHNvY2tldEV2ZW50cz4sXG4gIHNvY2tldDogT3BlbkFJV2ViU29ja2V0TGlrZSxcbiAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4pOiBQcm9taXNlPFNvY2tldFJlY29yZD4ge1xuICBpZiAoIXNpZ25hbCkgcmV0dXJuIGV2ZW50cy5uZXh0KCk7XG4gIGlmIChzaWduYWwuYWJvcnRlZCkgdGhyb3cgYWJvcnRFcnJvcihzaWduYWwpO1xuICByZXR1cm4gbmV3IFByb21pc2U8U29ja2V0UmVjb3JkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3Qgb25BYm9ydCA9ICgpID0+IHtcbiAgICAgIHNvY2tldC50ZXJtaW5hdGUoKTtcbiAgICAgIHJlamVjdChhYm9ydEVycm9yKHNpZ25hbCkpO1xuICAgIH07XG4gICAgc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCBvbkFib3J0LCB7IG9uY2U6IHRydWUgfSk7XG4gICAgdm9pZCBldmVudHNcbiAgICAgIC5uZXh0KClcbiAgICAgIC50aGVuKHJlc29sdmUsIHJlamVjdClcbiAgICAgIC5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgc2lnbmFsLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCBvbkFib3J0KTtcbiAgICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gY2FjaGVBZmZpbml0eVV1aWQoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBoZXggPSBjcnlwdG8uY3JlYXRlSGFzaChcInNoYTI1NlwiKS51cGRhdGUoa2V5KS5kaWdlc3QoXCJoZXhcIikuc2xpY2UoMCwgMzIpLnNwbGl0KFwiXCIpO1xuICBoZXhbMTJdID0gXCI0XCI7XG4gIGhleFsxNl0gPSAoKE51bWJlci5wYXJzZUludChoZXhbMTZdISwgMTYpICYgMHgzKSB8IDB4OCkudG9TdHJpbmcoMTYpO1xuICByZXR1cm4gYCR7aGV4LnNsaWNlKDAsIDgpLmpvaW4oXCJcIil9LSR7aGV4LnNsaWNlKDgsIDEyKS5qb2luKFwiXCIpfS0ke2hleC5zbGljZSgxMiwgMTYpLmpvaW4oXCJcIil9LSR7aGV4LnNsaWNlKDE2LCAyMCkuam9pbihcIlwiKX0tJHtoZXguc2xpY2UoMjApLmpvaW4oXCJcIil9YDtcbn1cblxudHlwZSBBZmZpbml0eUNvbm5lY3Rpb24gPSB7XG4gIHNvY2tldDogT3BlbkFJV2ViU29ja2V0TGlrZTtcbiAgZXZlbnRzOiBSZXR1cm5UeXBlPHR5cGVvZiBzb2NrZXRFdmVudHM+O1xuICBjbG9zZWQ/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGNsYXNzIE9wZW5BSVdlYlNvY2tldFRyYW5zcG9ydCBpbXBsZW1lbnRzIE9wZW5BSVJlc3BvbnNlc1RyYW5zcG9ydCB7XG4gIHN0YXRpYyByZWFkb25seSBNQVhfQUZGSU5JVFlfQ09OTkVDVElPTlMgPSAxNjtcbiAgY3JlZGVudGlhbHM6IE9wZW5BSURpcmVjdENyZWRlbnRpYWxzO1xuICByZWFkb25seSByZWZyZXNoQ3JlZGVudGlhbHM/OiAoKSA9PiBQcm9taXNlPE9wZW5BSURpcmVjdENyZWRlbnRpYWxzPjtcbiAgcmVhZG9ubHkgd2ViU29ja2V0RmFjdG9yeTogT3BlbkFJV2ViU29ja2V0RmFjdG9yeTtcbiAgcmVhZG9ubHkgYWZmaW5pdHlDb25uZWN0aW9ucyA9IG5ldyBNYXA8c3RyaW5nLCBBZmZpbml0eUNvbm5lY3Rpb24+KCk7XG4gIHJlYWRvbmx5IGJ1c3lBZmZpbml0aWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogT3BlbkFJV2ViU29ja2V0VHJhbnNwb3J0T3B0aW9ucykge1xuICAgIHRoaXMuY3JlZGVudGlhbHMgPSBvcHRpb25zLmNyZWRlbnRpYWxzO1xuICAgIHRoaXMucmVmcmVzaENyZWRlbnRpYWxzID0gb3B0aW9ucy5yZWZyZXNoQ3JlZGVudGlhbHM7XG4gICAgdGhpcy53ZWJTb2NrZXRGYWN0b3J5ID1cbiAgICAgIG9wdGlvbnMud2ViU29ja2V0RmFjdG9yeSA/PyAoKHVybCwgd3NPcHRpb25zKSA9PiBuZXcgV3NDbGllbnQodXJsLCB3c09wdGlvbnMpKTtcbiAgfVxuXG4gIGNsb3NlKCk6IHZvaWQge1xuICAgIHRoaXMuYWZmaW5pdHlDb25uZWN0aW9ucy5mb3JFYWNoKCh7IHNvY2tldCwgZXZlbnRzIH0pID0+IHtcbiAgICAgIGV2ZW50cy5jbGVhbnVwKCk7XG4gICAgICBzb2NrZXQuY2xvc2UoMTAwMCwgXCJ0cmFuc3BvcnQgY2xvc2VkXCIpO1xuICAgIH0pO1xuICAgIHRoaXMuYWZmaW5pdHlDb25uZWN0aW9ucy5jbGVhcigpO1xuICAgIHRoaXMuYnVzeUFmZmluaXRpZXMuY2xlYXIoKTtcbiAgfVxuXG4gIC8vIOycoO2ctCDsl7DqsrDrp4wg7LaV7Lac7ZWc64ukLiDsoITrtoAg7IKs7JqpIOykkeydtOuptCBmYWxzZeulvCDrsJjtmZjtlbQg7J287ZqM7ISxIOyGjOy8k+ycvOuhnCDsspjrpqztlZzri6QuXG4gIHJlbWVtYmVyQWZmaW5pdHlDb25uZWN0aW9uKHRocmVhZElkOiBzdHJpbmcsIGNvbm5lY3Rpb246IEFmZmluaXR5Q29ubmVjdGlvbik6IGJvb2xlYW4ge1xuICAgIGlmIChcbiAgICAgICF0aGlzLmFmZmluaXR5Q29ubmVjdGlvbnMuaGFzKHRocmVhZElkKSAmJlxuICAgICAgdGhpcy5hZmZpbml0eUNvbm5lY3Rpb25zLnNpemUgPj0gT3BlbkFJV2ViU29ja2V0VHJhbnNwb3J0Lk1BWF9BRkZJTklUWV9DT05ORUNUSU9OU1xuICAgICkge1xuICAgICAgY29uc3QgaWRsZUtleSA9IFsuLi50aGlzLmFmZmluaXR5Q29ubmVjdGlvbnMua2V5cygpXS5maW5kKFxuICAgICAgICAoa2V5KSA9PiAhdGhpcy5idXN5QWZmaW5pdGllcy5oYXMoa2V5KSxcbiAgICAgICk7XG4gICAgICBpZiAoaWRsZUtleSA9PT0gdW5kZWZpbmVkKSByZXR1cm4gZmFsc2U7XG4gICAgICBjb25zdCBpZGxlID0gdGhpcy5hZmZpbml0eUNvbm5lY3Rpb25zLmdldChpZGxlS2V5KSE7XG4gICAgICBpZGxlLmV2ZW50cy5jbGVhbnVwKCk7XG4gICAgICBpZGxlLnNvY2tldC5jbG9zZSgxMDAwLCBcImFmZmluaXR5IGNhY2hlIGV2aWN0ZWRcIik7XG4gICAgICB0aGlzLmFmZmluaXR5Q29ubmVjdGlvbnMuZGVsZXRlKGlkbGVLZXkpO1xuICAgIH1cbiAgICB0aGlzLmFmZmluaXR5Q29ubmVjdGlvbnMuc2V0KHRocmVhZElkLCBjb25uZWN0aW9uKTtcbiAgICAvLyDsnKDtnLQg7IOB7YOc7JeQ7IScIGJhY2tlbmQg6rCAIOuBiuydgCDshozsvJPsnYQg64uk7J2MIOyalOyyreydtCDsp5HslrTrk6Tsp4Ag7JWK64+E66GdIOy6kOyLnOyXkOyEnCDsoJzqsbDtlZzri6QuXG4gICAgY29uc3QgZHJvcCA9ICgpID0+IHtcbiAgICAgIGNvbm5lY3Rpb24uY2xvc2VkID0gdHJ1ZTtcbiAgICAgIGlmICh0aGlzLmJ1c3lBZmZpbml0aWVzLmhhcyh0aHJlYWRJZCkpIHJldHVybjtcbiAgICAgIGlmICh0aGlzLmFmZmluaXR5Q29ubmVjdGlvbnMuZ2V0KHRocmVhZElkKSAhPT0gY29ubmVjdGlvbikgcmV0dXJuO1xuICAgICAgdGhpcy5hZmZpbml0eUNvbm5lY3Rpb25zLmRlbGV0ZSh0aHJlYWRJZCk7XG4gICAgICBjb25uZWN0aW9uLmV2ZW50cy5jbGVhbnVwKCk7XG4gICAgfTtcbiAgICBjb25uZWN0aW9uLnNvY2tldC5vbihcImNsb3NlXCIsIGRyb3ApO1xuICAgIGNvbm5lY3Rpb24uc29ja2V0Lm9uKFwiZXJyb3JcIiwgZHJvcCk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBhc3luYyAqc3RyZWFtKHJlcXVlc3Q6IE9wZW5BSVRyYW5zcG9ydFJlcXVlc3QpOiBBc3luY0dlbmVyYXRvcjxPcGVuQUlOb3JtYWxpemVkRXZlbnQ+IHtcbiAgICBsZXQgcmVmcmVzaGVkID0gZmFsc2U7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGlmIChyZXF1ZXN0LnNpZ25hbD8uYWJvcnRlZCkgdGhyb3cgYWJvcnRFcnJvcihyZXF1ZXN0LnNpZ25hbCk7XG4gICAgICBjb25zdCBoYXNBZmZpbml0eSA9IHJlcXVlc3QuYm9keS5wcm9tcHRfY2FjaGVfa2V5ICE9PSB1bmRlZmluZWQ7XG4gICAgICBjb25zdCByZXRhaW5Db25uZWN0aW9uID0gaGFzQWZmaW5pdHkgJiYgIXRoaXMuYnVzeUFmZmluaXRpZXMuaGFzKHJlcXVlc3QudGhyZWFkSWQpO1xuICAgICAgaWYgKHJldGFpbkNvbm5lY3Rpb24pIHRoaXMuYnVzeUFmZmluaXRpZXMuYWRkKHJlcXVlc3QudGhyZWFkSWQpO1xuICAgICAgY29uc3QgZW50cnkgPSByZXRhaW5Db25uZWN0aW9uID8gdGhpcy5hZmZpbml0eUNvbm5lY3Rpb25zLmdldChyZXF1ZXN0LnRocmVhZElkKSA6IHVuZGVmaW5lZDtcbiAgICAgIGlmIChlbnRyeT8uY2xvc2VkKSB7XG4gICAgICAgIHRoaXMuYWZmaW5pdHlDb25uZWN0aW9ucy5kZWxldGUocmVxdWVzdC50aHJlYWRJZCk7XG4gICAgICAgIGVudHJ5LmV2ZW50cy5jbGVhbnVwKCk7XG4gICAgICB9XG4gICAgICBjb25zdCBjYWNoZWQgPSBlbnRyeT8uY2xvc2VkID8gdW5kZWZpbmVkIDogZW50cnk7XG4gICAgICBsZXQgcmV0YWluZWQgPSByZXRhaW5Db25uZWN0aW9uO1xuICAgICAgY29uc3Qgc29ja2V0ID1cbiAgICAgICAgY2FjaGVkPy5zb2NrZXQgPz9cbiAgICAgICAgdGhpcy53ZWJTb2NrZXRGYWN0b3J5KHdlYnNvY2tldFVybChDSEFUR1BUX0NPREVYX1JFU1BPTlNFU19VUkwpLCB7XG4gICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgLi4uYnVpbGRDb2RleElkZW50aXR5SGVhZGVycyh0aGlzLmNyZWRlbnRpYWxzLmFjY2Vzc1Rva2VuLCB0aGlzLmNyZWRlbnRpYWxzLmFjY291bnRJZCwge1xuICAgICAgICAgICAgICBzZXNzaW9uSWQ6IHJlcXVlc3Quc2Vzc2lvbklkLFxuICAgICAgICAgICAgICB0aHJlYWRJZDogcmVxdWVzdC50aHJlYWRJZCxcbiAgICAgICAgICAgICAgY2xpZW50UmVxdWVzdElkOiByZXF1ZXN0LmNsaWVudFJlcXVlc3RJZCxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgXCJPcGVuQUktQmV0YVwiOiBcInJlc3BvbnNlc193ZWJzb2NrZXRzPTIwMjYtMDItMDZcIixcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIGNvbnN0IGV2ZW50cyA9IGNhY2hlZD8uZXZlbnRzID8/IHNvY2tldEV2ZW50cyhzb2NrZXQsIHJlcXVlc3Quc2lnbmFsKTtcbiAgICAgIGxldCBjb21wbGV0ZWQgPSBmYWxzZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmICghY2FjaGVkKSB7XG4gICAgICAgICAgY29uc3QgaGFuZHNoYWtlID0gYXdhaXQgZXZlbnRzLm5leHQoKTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBoYW5kc2hha2Uua2luZCA9PT0gXCJyZWplY3RlZFwiICYmXG4gICAgICAgICAgICBoYW5kc2hha2Uuc3RhdHVzID09PSA0MDEgJiZcbiAgICAgICAgICAgICFyZWZyZXNoZWQgJiZcbiAgICAgICAgICAgIHRoaXMucmVmcmVzaENyZWRlbnRpYWxzXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBzb2NrZXQudGVybWluYXRlKCk7XG4gICAgICAgICAgICB0aGlzLmNyZWRlbnRpYWxzID0gYXdhaXQgdGhpcy5yZWZyZXNoQ3JlZGVudGlhbHMoKTtcbiAgICAgICAgICAgIHJlZnJlc2hlZCA9IHRydWU7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGhhbmRzaGFrZS5raW5kID09PSBcInJlamVjdGVkXCIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBPcGVuQUlQcm90b2NvbEVycm9yKFxuICAgICAgICAgICAgICBgT3BlbkFJIFdlYlNvY2tldCBoYW5kc2hha2UgcmVqZWN0ZWQke2hhbmRzaGFrZS5zdGF0dXMgPyBgIHdpdGggSFRUUCAke2hhbmRzaGFrZS5zdGF0dXN9YCA6IFwiXCJ9YCxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICBoYW5kc2hha2Uuc3RhdHVzLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGhhbmRzaGFrZS5raW5kID09PSBcImVycm9yXCIpIHRocm93IGhhbmRzaGFrZS5lcnJvcjtcbiAgICAgICAgICBpZiAoaGFuZHNoYWtlLmtpbmQgIT09IFwib3BlblwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgT3BlbkFJUHJvdG9jb2xFcnJvcihcIk9wZW5BSSBXZWJTb2NrZXQgY2xvc2VkIGJlZm9yZSB0aGUgaGFuZHNoYWtlIGNvbXBsZXRlZFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHJldGFpbkNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIHJldGFpbmVkID0gdGhpcy5yZW1lbWJlckFmZmluaXR5Q29ubmVjdGlvbihyZXF1ZXN0LnRocmVhZElkLCB7IHNvY2tldCwgZXZlbnRzIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICBzb2NrZXQuc2VuZChKU09OLnN0cmluZ2lmeSh7IHR5cGU6IFwicmVzcG9uc2UuY3JlYXRlXCIsIC4uLnJlcXVlc3QuYm9keSB9KSwgKGVycm9yKSA9PlxuICAgICAgICAgICAgZXJyb3IgPyByZWplY3QoZXJyb3IpIDogcmVzb2x2ZSgpLFxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgY29uc3QgcmVjb3JkID0gY2FjaGVkXG4gICAgICAgICAgICA/IGF3YWl0IG5leHRQb29sZWRSZWNvcmQoZXZlbnRzLCBzb2NrZXQsIHJlcXVlc3Quc2lnbmFsKVxuICAgICAgICAgICAgOiBhd2FpdCBldmVudHMubmV4dCgpO1xuICAgICAgICAgIGlmIChyZWNvcmQua2luZCA9PT0gXCJtZXNzYWdlXCIpIHtcbiAgICAgICAgICAgIGlmIChyZWNvcmQuaXNCaW5hcnkpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IE9wZW5BSVByb3RvY29sRXJyb3IoXCJPcGVuQUkgV2ViU29ja2V0IHNlbnQgYW4gdW5leHBlY3RlZCBiaW5hcnkgbWVzc2FnZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByYXc6IHVua25vd247XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICByYXcgPSBKU09OLnBhcnNlKHJhd0RhdGFUZXh0KHJlY29yZC5kYXRhKSk7XG4gICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IE9wZW5BSVByb3RvY29sRXJyb3IoXCJPcGVuQUkgV2ViU29ja2V0IHNlbnQgaW52YWxpZCBKU09OXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZXZlbnQgPSBub3JtYWxpemVPcGVuQUlFdmVudChyYXcpO1xuICAgICAgICAgICAgaWYgKCFldmVudCkgY29udGludWU7XG4gICAgICAgICAgICBpZiAoZXZlbnQudHlwZSA9PT0gXCJjb21wbGV0ZWRcIikge1xuICAgICAgICAgICAgICBjb21wbGV0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICBpZiAocmV0YWluZWQpIGV2ZW50cy5kZXRhY2hBYm9ydCgpO1xuICAgICAgICAgICAgICBlbHNlIHNvY2tldC5jbG9zZSgxMDAwLCBcInJlc3BvbnNlIGNvbXBsZXRlZFwiKTtcbiAgICAgICAgICAgICAgeWllbGQgZXZlbnQ7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHlpZWxkIGV2ZW50O1xuICAgICAgICAgICAgaWYgKGV2ZW50LnR5cGUgPT09IFwiZXJyb3JcIikgdGhyb3cgZXZlbnQuZXJyb3I7XG4gICAgICAgICAgfSBlbHNlIGlmIChyZWNvcmQua2luZCA9PT0gXCJlcnJvclwiKSB7XG4gICAgICAgICAgICB0aHJvdyByZWNvcmQuZXJyb3I7XG4gICAgICAgICAgfSBlbHNlIGlmIChyZWNvcmQua2luZCA9PT0gXCJjbG9zZVwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgT3BlbkFJUHJvdG9jb2xFcnJvcihcbiAgICAgICAgICAgICAgYE9wZW5BSSBXZWJTb2NrZXQgY2xvc2VkIGJlZm9yZSBhIHRlcm1pbmFsIHJlc3BvbnNlIGV2ZW50ICgke3JlY29yZC5jb2RlfSR7cmVjb3JkLnJlYXNvbiA/IGA6ICR7cmVjb3JkLnJlYXNvbn1gIDogXCJcIn0pYCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBPcGVuQUlQcm90b2NvbEVycm9yKFwiT3BlbkFJIFdlYlNvY2tldCBlbWl0dGVkIGFuIHVuZXhwZWN0ZWQgaGFuZHNoYWtlIGV2ZW50XCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgaWYgKCFjb21wbGV0ZWQgfHwgIXJldGFpbmVkKSB7XG4gICAgICAgICAgaWYgKHJldGFpbmVkKSB0aGlzLmFmZmluaXR5Q29ubmVjdGlvbnMuZGVsZXRlKHJlcXVlc3QudGhyZWFkSWQpO1xuICAgICAgICAgIGV2ZW50cy5jbGVhbnVwKCk7XG4gICAgICAgICAgaWYgKCFjb21wbGV0ZWQpIHNvY2tldC50ZXJtaW5hdGUoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmV0YWluQ29ubmVjdGlvbikgdGhpcy5idXN5QWZmaW5pdGllcy5kZWxldGUocmVxdWVzdC50aHJlYWRJZCk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlc3BvbnNlRXJyb3IocmVzcG9uc2U6IFJlc3BvbnNlKTogUHJvbWlzZTxPcGVuQUlQcm90b2NvbEVycm9yPiB7XG4gIGNvbnN0IHRleHQgPSBhd2FpdCByZXNwb25zZS50ZXh0KCkuY2F0Y2goKCkgPT4gXCJcIik7XG4gIGxldCBtZXNzYWdlID0gdGV4dCB8fCByZXNwb25zZS5zdGF0dXNUZXh0IHx8IGBIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfWA7XG4gIGxldCBjb2RlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHRyeSB7XG4gICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZSh0ZXh0KSBhcyB7XG4gICAgICBlcnJvcj86IHsgbWVzc2FnZT86IHN0cmluZzsgY29kZT86IHN0cmluZyB9IHwgc3RyaW5nO1xuICAgICAgbWVzc2FnZT86IHN0cmluZztcbiAgICAgIGNvZGU/OiBzdHJpbmc7XG4gICAgfTtcbiAgICBjb25zdCBlcnJvciA9IHBhcnNlZC5lcnJvcjtcbiAgICBtZXNzYWdlID1cbiAgICAgICh0eXBlb2YgZXJyb3IgPT09IFwib2JqZWN0XCIgPyBlcnJvci5tZXNzYWdlIDogdW5kZWZpbmVkKSA/P1xuICAgICAgcGFyc2VkLm1lc3NhZ2UgPz9cbiAgICAgICh0eXBlb2YgZXJyb3IgPT09IFwic3RyaW5nXCIgPyBlcnJvciA6IG1lc3NhZ2UpO1xuICAgIGNvZGUgPSAodHlwZW9mIGVycm9yID09PSBcIm9iamVjdFwiID8gZXJyb3IuY29kZSA6IHVuZGVmaW5lZCkgPz8gcGFyc2VkLmNvZGU7XG4gIH0gY2F0Y2gge1xuICAgIGNvZGUgPSB1bmRlZmluZWQ7XG4gIH1cbiAgcmV0dXJuIG5ldyBPcGVuQUlQcm90b2NvbEVycm9yKG1lc3NhZ2UsIGNvZGUsIHJlc3BvbnNlLnN0YXR1cyk7XG59XG5cbmV4cG9ydCBjbGFzcyBPcGVuQUlIdHRwc1RyYW5zcG9ydCBpbXBsZW1lbnRzIE9wZW5BSVJlc3BvbnNlc1RyYW5zcG9ydCB7XG4gIGNyZWRlbnRpYWxzOiBPcGVuQUlEaXJlY3RDcmVkZW50aWFscztcbiAgcmVhZG9ubHkgZmV0Y2hJbXBsOiB0eXBlb2YgZmV0Y2g7XG4gIHJlYWRvbmx5IHJlZnJlc2hDcmVkZW50aWFscz86ICgpID0+IFByb21pc2U8T3BlbkFJRGlyZWN0Q3JlZGVudGlhbHM+O1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IE9wZW5BSUh0dHBzVHJhbnNwb3J0T3B0aW9ucykge1xuICAgIHRoaXMuY3JlZGVudGlhbHMgPSBvcHRpb25zLmNyZWRlbnRpYWxzO1xuICAgIHRoaXMuZmV0Y2hJbXBsID0gb3B0aW9ucy5mZXRjaCA/PyBmZXRjaDtcbiAgICB0aGlzLnJlZnJlc2hDcmVkZW50aWFscyA9IG9wdGlvbnMucmVmcmVzaENyZWRlbnRpYWxzO1xuICB9XG5cbiAgYXN5bmMgKnN0cmVhbShyZXF1ZXN0OiBPcGVuQUlUcmFuc3BvcnRSZXF1ZXN0KTogQXN5bmNHZW5lcmF0b3I8T3BlbkFJTm9ybWFsaXplZEV2ZW50PiB7XG4gICAgbGV0IHJlZnJlc2hlZCA9IGZhbHNlO1xuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5mZXRjaEltcGwoQ0hBVEdQVF9DT0RFWF9SRVNQT05TRVNfVVJMLCB7XG4gICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICAgIGhlYWRlcnM6IGJ1aWxkQ29kZXhJZGVudGl0eUhlYWRlcnMoXG4gICAgICAgICAgdGhpcy5jcmVkZW50aWFscy5hY2Nlc3NUb2tlbixcbiAgICAgICAgICB0aGlzLmNyZWRlbnRpYWxzLmFjY291bnRJZCxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBzZXNzaW9uSWQ6IHJlcXVlc3Quc2Vzc2lvbklkLFxuICAgICAgICAgICAgdGhyZWFkSWQ6IHJlcXVlc3QudGhyZWFkSWQsXG4gICAgICAgICAgICBjbGllbnRSZXF1ZXN0SWQ6IHJlcXVlc3QuY2xpZW50UmVxdWVzdElkLFxuICAgICAgICAgIH0sXG4gICAgICAgICksXG4gICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHJlcXVlc3QuYm9keSksXG4gICAgICAgIHNpZ25hbDogcmVxdWVzdC5zaWduYWwsXG4gICAgICB9KTtcblxuICAgICAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gNDAxICYmICFyZWZyZXNoZWQgJiYgdGhpcy5yZWZyZXNoQ3JlZGVudGlhbHMpIHtcbiAgICAgICAgYXdhaXQgcmVzcG9uc2UuYm9keT8uY2FuY2VsKCk7XG4gICAgICAgIHRoaXMuY3JlZGVudGlhbHMgPSBhd2FpdCB0aGlzLnJlZnJlc2hDcmVkZW50aWFscygpO1xuICAgICAgICByZWZyZXNoZWQgPSB0cnVlO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmICghcmVzcG9uc2Uub2spIHRocm93IGF3YWl0IHJlc3BvbnNlRXJyb3IocmVzcG9uc2UpO1xuICAgICAgaWYgKCFyZXNwb25zZS5ib2R5KSB0aHJvdyBuZXcgT3BlbkFJUHJvdG9jb2xFcnJvcihcIk9wZW5BSSByZXNwb25zZSBoYWQgbm8gYm9keVwiKTtcblxuICAgICAgZm9yIGF3YWl0IChjb25zdCBldmVudCBvZiBub3JtYWxpemVPcGVuQUlTU0UocmVzcG9uc2UuYm9keSkpIHtcbiAgICAgICAgeWllbGQgZXZlbnQ7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3BlbkFJRGlyZWN0Q2xpZW50T3B0aW9ucyBleHRlbmRzIE9wZW5BSUh0dHBzVHJhbnNwb3J0T3B0aW9ucyB7XG4gIHRyYW5zcG9ydD86IE9wZW5BSVJlc3BvbnNlc1RyYW5zcG9ydDtcbiAgdHJhbnNwb3J0S2luZD86IFwiaHR0cHNcIiB8IFwid2Vic29ja2V0XCI7XG4gIHdlYlNvY2tldEZhY3Rvcnk/OiBPcGVuQUlXZWJTb2NrZXRGYWN0b3J5O1xufVxuXG5leHBvcnQgY2xhc3MgT3BlbkFJRGlyZWN0Q2xpZW50IHtcbiAgcmVhZG9ubHkgdHJhbnNwb3J0OiBPcGVuQUlSZXNwb25zZXNUcmFuc3BvcnQ7XG4gIGltYWdlQ3JlZGVudGlhbHM6IE9wZW5BSURpcmVjdENyZWRlbnRpYWxzO1xuXG4gIGNvbnN0cnVjdG9yKHJlYWRvbmx5IG9wdGlvbnM6IE9wZW5BSURpcmVjdENsaWVudE9wdGlvbnMpIHtcbiAgICB0aGlzLmltYWdlQ3JlZGVudGlhbHMgPSBvcHRpb25zLmNyZWRlbnRpYWxzO1xuICAgIHRoaXMudHJhbnNwb3J0ID1cbiAgICAgIG9wdGlvbnMudHJhbnNwb3J0ID8/XG4gICAgICAob3B0aW9ucy50cmFuc3BvcnRLaW5kID09PSBcIndlYnNvY2tldFwiXG4gICAgICAgID8gbmV3IE9wZW5BSVdlYlNvY2tldFRyYW5zcG9ydChvcHRpb25zKVxuICAgICAgICA6IG5ldyBPcGVuQUlIdHRwc1RyYW5zcG9ydChvcHRpb25zKSk7XG4gIH1cblxuICByZXNwb25zZXMob3B0aW9uczogT3BlbkFJUmVzcG9uc2VzT3B0aW9ucywgc2lnbmFsPzogQWJvcnRTaWduYWwpOiBPcGVuQUlFdmVudFN0cmVhbSB7XG4gICAgaWYgKFxuICAgICAgb3B0aW9ucy5tb2RlbCA9PT0gXCJncHQtaW1hZ2UtMlwiIHx8XG4gICAgICAodHlwZW9mIG9wdGlvbnMuaW1hZ2VHZW5lcmF0aW9uID09PSBcIm9iamVjdFwiICYmXG4gICAgICAgIG9wdGlvbnMuaW1hZ2VHZW5lcmF0aW9uLmJhY2tncm91bmQgPT09IFwidHJhbnNwYXJlbnRcIilcbiAgICApIHtcbiAgICAgIHJldHVybiB0aGlzLnN0YW5kYWxvbmVJbWFnZXMob3B0aW9ucywgc2lnbmFsKTtcbiAgICB9XG4gICAgY29uc3QgY2xpZW50UmVxdWVzdElkID0gY3J5cHRvLnJhbmRvbVVVSUQoKTtcbiAgICBjb25zdCBhZmZpbml0eUlkID0gb3B0aW9ucy5wcm9tcHRDYWNoZUtleVxuICAgICAgPyBjYWNoZUFmZmluaXR5VXVpZChvcHRpb25zLnByb21wdENhY2hlS2V5KVxuICAgICAgOiBjbGllbnRSZXF1ZXN0SWQ7XG4gICAgcmV0dXJuIHRoaXMudHJhbnNwb3J0LnN0cmVhbSh7XG4gICAgICBib2R5OiBidWlsZE9wZW5BSVJlc3BvbnNlc1JlcXVlc3QoXG4gICAgICAgIG9wdGlvbnMucHJvbXB0Q2FjaGVLZXkgPyB7IC4uLm9wdGlvbnMsIHByb21wdENhY2hlS2V5OiBhZmZpbml0eUlkIH0gOiBvcHRpb25zLFxuICAgICAgKSxcbiAgICAgIHNpZ25hbCxcbiAgICAgIHNlc3Npb25JZDogYWZmaW5pdHlJZCxcbiAgICAgIC8vIHByb21wdENhY2hlS2V5IGlzIGFscmVhZHkgYSBvbmUtd2F5IFNESyBhZmZpbml0eSB2YWx1ZSwgbmV2ZXIgYSByYXcgc2Vzc2lvbktleS5cbiAgICAgIHRocmVhZElkOiBhZmZpbml0eUlkLFxuICAgICAgY2xpZW50UmVxdWVzdElkLFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgKnN0YW5kYWxvbmVJbWFnZXMoXG4gICAgb3B0aW9uczogT3BlbkFJUmVzcG9uc2VzT3B0aW9ucyxcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgKTogT3BlbkFJRXZlbnRTdHJlYW0ge1xuICAgIGNvbnN0IHJlcXVlc3QgPSBidWlsZFN0YW5kYWxvbmVJbWFnZVJlcXVlc3Qob3B0aW9ucyk7XG4gICAgY29uc3QgcmVxdWVzdElkID0gY3J5cHRvLnJhbmRvbVVVSUQoKTtcbiAgICBmb3IgKGxldCBhdHRlbXB0ID0gMDsgYXR0ZW1wdCA8IDI7IGF0dGVtcHQrKykge1xuICAgICAgc2lnbmFsPy50aHJvd0lmQWJvcnRlZCgpO1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCAodGhpcy5vcHRpb25zLmZldGNoID8/IGZldGNoKShyZXF1ZXN0LnVybCwge1xuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgLi4uYnVpbGRDb2RleElkZW50aXR5SGVhZGVycyhcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VDcmVkZW50aWFscy5hY2Nlc3NUb2tlbixcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VDcmVkZW50aWFscy5hY2NvdW50SWQsXG4gICAgICAgICAgKSxcbiAgICAgICAgICBBY2NlcHQ6IFwiYXBwbGljYXRpb24vanNvblwiLFxuICAgICAgICAgIFwieC1jb2RleC1pbWFnZS10dXJuLWlkXCI6IHJlcXVlc3RJZCxcbiAgICAgICAgfSxcbiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkocmVxdWVzdC5ib2R5KSxcbiAgICAgICAgc2lnbmFsLFxuICAgICAgfSk7XG4gICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSA0MDEgJiYgYXR0ZW1wdCA9PT0gMCAmJiB0aGlzLm9wdGlvbnMucmVmcmVzaENyZWRlbnRpYWxzKSB7XG4gICAgICAgIGF3YWl0IHJlc3BvbnNlLmJvZHk/LmNhbmNlbCgpO1xuICAgICAgICB0aGlzLmltYWdlQ3JlZGVudGlhbHMgPSBhd2FpdCB0aGlzLm9wdGlvbnMucmVmcmVzaENyZWRlbnRpYWxzKCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKCFyZXNwb25zZS5vaykgdGhyb3cgYXdhaXQgcmVzcG9uc2VFcnJvcihyZXNwb25zZSk7XG4gICAgICBjb25zdCBpbWFnZXMgPSBhd2FpdCByZWFkU3RhbmRhbG9uZUltYWdlUmVzcG9uc2UoXG4gICAgICAgIHJlc3BvbnNlLFxuICAgICAgICB0eXBlb2Ygb3B0aW9ucy5pbWFnZUdlbmVyYXRpb24gPT09IFwib2JqZWN0XCIgJiZcbiAgICAgICAgICBvcHRpb25zLmltYWdlR2VuZXJhdGlvbi5iYWNrZ3JvdW5kID09PSBcInRyYW5zcGFyZW50XCIsXG4gICAgICApO1xuICAgICAgc2lnbmFsPy50aHJvd0lmQWJvcnRlZCgpO1xuICAgICAgeWllbGQqIGltYWdlcztcbiAgICAgIGNvbnN0IGZpcnN0SW1hZ2UgPSBpbWFnZXNbMF07XG4gICAgICB5aWVsZCB7XG4gICAgICAgIHR5cGU6IFwiY29tcGxldGVkXCIsXG4gICAgICAgIHJlc3BvbnNlSWQ6IHJlcXVlc3RJZCxcbiAgICAgICAgbW9kZWw6IGZpcnN0SW1hZ2U/LnR5cGUgPT09IFwiaW1hZ2VcIiA/IGZpcnN0SW1hZ2UuZ2VuZXJhdGlvbj8ubW9kZWwgOiBcImdwdC1pbWFnZS0yXCIsXG4gICAgICB9O1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuXG4gIGNsb3NlKCk6IHZvaWQge1xuICAgIHRoaXMudHJhbnNwb3J0LmNsb3NlPy4oKTtcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUF3RUEsTUFBTSw4QkFBOEI7QUFFcEMsU0FBUyxhQUFhLEtBQXFCO0NBQ3pDLElBQUk7Q0FDSixJQUFJO0VBQ0YsU0FBUyxJQUFJLElBQUksR0FBRztDQUN0QixTQUFTLE9BQU87RUFDZCxNQUFNLElBQUksb0JBQW9CLGlDQUFpQyxPQUFPLEtBQUssR0FBRztDQUNoRjtDQUNBLE9BQU8sV0FBVyxPQUFPLGFBQWEsV0FBVyxTQUFTO0NBQzFELE9BQU8sT0FBTyxTQUFTO0FBQ3pCO0FBRUEsU0FBUyxZQUFZLE1BQXVCO0NBQzFDLElBQUksTUFBTSxRQUFRLElBQUks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
|
|
355
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLWRpcmVjdC1jbGllbnQuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLWRpcmVjdC1jbGllbnQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNyeXB0byBmcm9tIFwibm9kZTpjcnlwdG9cIjtcblxuaW1wb3J0IFdzQ2xpZW50LCB7IHR5cGUgQ2xpZW50T3B0aW9ucywgdHlwZSBSYXdEYXRhIH0gZnJvbSBcIndzXCI7XG5cbmltcG9ydCB7XG4gIGJ1aWxkQ29kZXhJZGVudGl0eUhlYWRlcnMsXG4gIGJ1aWxkT3BlbkFJUmVzcG9uc2VzUmVxdWVzdCxcbiAgQ0hBVEdQVF9DT0RFWF9SRVNQT05TRVNfVVJMLFxuICBub3JtYWxpemVPcGVuQUlFdmVudCxcbiAgT3BlbkFJUHJvdG9jb2xFcnJvcixcbiAgdHlwZSBPcGVuQUlOb3JtYWxpemVkRXZlbnQsXG4gIHR5cGUgT3BlbkFJUmVzcG9uc2VzT3B0aW9ucyxcbiAgdHlwZSBPcGVuQUlSZXNwb25zZXNSZXF1ZXN0LFxufSBmcm9tIFwiLi9vcGVuYWktYmFja2VuZC1wcm90b2NvbFwiO1xuaW1wb3J0IHtcbiAgYnVpbGRTdGFuZGFsb25lSW1hZ2VSZXF1ZXN0LFxuICByZWFkU3RhbmRhbG9uZUltYWdlUmVzcG9uc2UsXG59IGZyb20gXCIuL29wZW5haS1pbWFnZS1nZW5lcmF0aW9uXCI7XG5pbXBvcnQgeyBub3JtYWxpemVPcGVuQUlTU0UsIHR5cGUgT3BlbkFJRXZlbnRTdHJlYW0gfSBmcm9tIFwiLi9vcGVuYWktc3NlXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3BlbkFJRGlyZWN0Q3JlZGVudGlhbHMge1xuICBhY2Nlc3NUb2tlbjogc3RyaW5nO1xuICBhY2NvdW50SWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlUcmFuc3BvcnRSZXF1ZXN0IHtcbiAgYm9keTogT3BlbkFJUmVzcG9uc2VzUmVxdWVzdDtcbiAgc2lnbmFsPzogQWJvcnRTaWduYWw7XG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICB0aHJlYWRJZDogc3RyaW5nO1xuICBjbGllbnRSZXF1ZXN0SWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlSZXNwb25zZXNUcmFuc3BvcnQge1xuICBzdHJlYW0ocmVxdWVzdDogT3BlbkFJVHJhbnNwb3J0UmVxdWVzdCk6IE9wZW5BSUV2ZW50U3RyZWFtO1xuICBjbG9zZT8oKTogdm9pZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlIdHRwc1RyYW5zcG9ydE9wdGlvbnMge1xuICBjcmVkZW50aWFsczogT3BlbkFJRGlyZWN0Q3JlZGVudGlhbHM7XG4gIGZldGNoPzogdHlwZW9mIGZldGNoO1xuICByZWZyZXNoQ3JlZGVudGlhbHM/OiAoKSA9PiBQcm9taXNlPE9wZW5BSURpcmVjdENyZWRlbnRpYWxzPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlXZWJTb2NrZXRMaWtlIHtcbiAgb24oZXZlbnQ6IFwib3BlblwiLCBsaXN0ZW5lcjogKCkgPT4gdm9pZCk6IHRoaXM7XG4gIG9uKGV2ZW50OiBcIm1lc3NhZ2VcIiwgbGlzdGVuZXI6IChkYXRhOiBSYXdEYXRhLCBpc0JpbmFyeTogYm9vbGVhbikgPT4gdm9pZCk6IHRoaXM7XG4gIG9uKGV2ZW50OiBcImNsb3NlXCIsIGxpc3RlbmVyOiAoY29kZTogbnVtYmVyLCByZWFzb246IEJ1ZmZlcikgPT4gdm9pZCk6IHRoaXM7XG4gIG9uKGV2ZW50OiBcImVycm9yXCIsIGxpc3RlbmVyOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkKTogdGhpcztcbiAgb24oXG4gICAgZXZlbnQ6IFwidW5leHBlY3RlZC1yZXNwb25zZVwiLFxuICAgIGxpc3RlbmVyOiAocmVxdWVzdDogdW5rbm93biwgcmVzcG9uc2U6IHsgc3RhdHVzQ29kZT86IG51bWJlciB9KSA9PiB2b2lkLFxuICApOiB0aGlzO1xuICBvZmYoZXZlbnQ6IHN0cmluZywgbGlzdGVuZXI6ICguLi5hcmdzOiBuZXZlcltdKSA9PiB2b2lkKTogdGhpcztcbiAgc2VuZChkYXRhOiBzdHJpbmcsIGNhbGxiYWNrPzogKGVycm9yPzogRXJyb3IpID0+IHZvaWQpOiB2b2lkO1xuICBjbG9zZShjb2RlPzogbnVtYmVyLCByZWFzb24/OiBzdHJpbmcpOiB2b2lkO1xuICB0ZXJtaW5hdGUoKTogdm9pZDtcbn1cblxuZXhwb3J0IHR5cGUgT3BlbkFJV2ViU29ja2V0RmFjdG9yeSA9ICh1cmw6IHN0cmluZywgb3B0aW9uczogQ2xpZW50T3B0aW9ucykgPT4gT3BlbkFJV2ViU29ja2V0TGlrZTtcblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlXZWJTb2NrZXRUcmFuc3BvcnRPcHRpb25zIGV4dGVuZHMgT3BlbkFJSHR0cHNUcmFuc3BvcnRPcHRpb25zIHtcbiAgd2ViU29ja2V0RmFjdG9yeT86IE9wZW5BSVdlYlNvY2tldEZhY3Rvcnk7XG59XG5cbnR5cGUgU29ja2V0UmVjb3JkID1cbiAgfCB7IGtpbmQ6IFwib3BlblwiIH1cbiAgfCB7IGtpbmQ6IFwibWVzc2FnZVwiOyBkYXRhOiBSYXdEYXRhOyBpc0JpbmFyeTogYm9vbGVhbiB9XG4gIHwgeyBraW5kOiBcImNsb3NlXCI7IGNvZGU6IG51bWJlcjsgcmVhc29uOiBzdHJpbmcgfVxuICB8IHsga2luZDogXCJlcnJvclwiOyBlcnJvcjogRXJyb3IgfVxuICB8IHsga2luZDogXCJyZWplY3RlZFwiOyBzdGF0dXM/OiBudW1iZXIgfTtcblxuY29uc3QgTUFYX0JVRkZFUkVEX1NPQ0tFVF9SRUNPUkRTID0gMTYwMDtcblxuZnVuY3Rpb24gd2Vic29ja2V0VXJsKHVybDogc3RyaW5nKTogc3RyaW5nIHtcbiAgbGV0IHBhcnNlZDogVVJMO1xuICB0cnkge1xuICAgIHBhcnNlZCA9IG5ldyBVUkwodXJsKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgT3BlbkFJUHJvdG9jb2xFcnJvcihgSW52YWxpZCBPcGVuQUkgUmVzcG9uc2VzIFVSTDogJHtTdHJpbmcoZXJyb3IpfWApO1xuICB9XG4gIHBhcnNlZC5wcm90b2NvbCA9IHBhcnNlZC5wcm90b2NvbCA9PT0gXCJodHRwczpcIiA/IFwid3NzOlwiIDogXCJ3czpcIjtcbiAgcmV0dXJuIHBhcnNlZC50b1N0cmluZygpO1xufVxuXG5mdW5jdGlvbiByYXdEYXRhVGV4dChkYXRhOiBSYXdEYXRhKTogc3RyaW5nIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkpIHJldHVybiBCdWZmZXIuY29uY2F0KGRhdGEpLnRvU3RyaW5nKCk7XG4gIGlmIChkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHJldHVybiBCdWZmZXIuZnJvbShuZXcgVWludDhBcnJheShkYXRhKSkudG9TdHJpbmcoKTtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKGRhdGEpLnRvU3RyaW5nKCk7XG59XG5cbmZ1bmN0aW9uIHNvY2tldEV2ZW50cyhzb2NrZXQ6IE9wZW5BSVdlYlNvY2tldExpa2UsIHNpZ25hbD86IEFib3J0U2lnbmFsKSB7XG4gIGNvbnN0IHJlY29yZHM6IFNvY2tldFJlY29yZFtdID0gW107XG4gIGNvbnN0IHdhaXRlcnM6IEFycmF5PChyZWNvcmQ6IFNvY2tldFJlY29yZCkgPT4gdm9pZD4gPSBbXTtcbiAgbGV0IGFjdGl2ZSA9IHRydWU7XG4gIGNvbnN0IHB1c2ggPSAocmVjb3JkOiBTb2NrZXRSZWNvcmQpID0+IHtcbiAgICBpZiAoIWFjdGl2ZSkgcmV0dXJuO1xuICAgIGNvbnN0IHdhaXRlciA9IHdhaXRlcnMuc2hpZnQoKTtcbiAgICBpZiAod2FpdGVyKSB3YWl0ZXIocmVjb3JkKTtcbiAgICBlbHNlIGlmIChyZWNvcmRzLmxlbmd0aCA8IE1BWF9CVUZGRVJFRF9TT0NLRVRfUkVDT1JEUykgcmVjb3Jkcy5wdXNoKHJlY29yZCk7XG4gICAgZWxzZSB7XG4gICAgICBhY3RpdmUgPSBmYWxzZTtcbiAgICAgIHJlY29yZHMubGVuZ3RoID0gMDtcbiAgICAgIHNvY2tldC50ZXJtaW5hdGUoKTtcbiAgICAgIGNvbnN0IG92ZXJmbG93ID0ge1xuICAgICAgICBraW5kOiBcImVycm9yXCIgYXMgY29uc3QsXG4gICAgICAgIGVycm9yOiBuZXcgT3BlbkFJUHJvdG9jb2xFcnJvcihcbiAgICAgICAgICBgT3BlbkFJIFdlYlNvY2tldCBleGNlZWRlZCB0aGUgJHtNQVhfQlVGRkVSRURfU09DS0VUX1JFQ09SRFN9LXJlY29yZCByZWNlaXZlIGJ1ZmZlcmAsXG4gICAgICAgICAgXCJ3ZWJzb2NrZXRfYmFja3ByZXNzdXJlXCIsXG4gICAgICAgICksXG4gICAgICB9O1xuICAgICAgY29uc3Qgb3ZlcmZsb3dXYWl0ZXIgPSB3YWl0ZXJzLnNoaWZ0KCk7XG4gICAgICBpZiAob3ZlcmZsb3dXYWl0ZXIpIG92ZXJmbG93V2FpdGVyKG92ZXJmbG93KTtcbiAgICAgIGVsc2UgcmVjb3Jkcy5wdXNoKG92ZXJmbG93KTtcbiAgICB9XG4gIH07XG4gIGNvbnN0IG9uT3BlbiA9ICgpID0+IHB1c2goeyBraW5kOiBcIm9wZW5cIiB9KTtcbiAgY29uc3Qgb25NZXNzYWdlID0gKGRhdGE6IFJhd0RhdGEsIGlzQmluYXJ5OiBib29sZWFuKSA9PiBwdXNoKHsga2luZDogXCJtZXNzYWdlXCIsIGRhdGEsIGlzQmluYXJ5IH0pO1xuICBjb25zdCBvbkNsb3NlID0gKGNvZGU6IG51bWJlciwgcmVhc29uOiBCdWZmZXIpID0+XG4gICAgcHVzaCh7IGtpbmQ6IFwiY2xvc2VcIiwgY29kZSwgcmVhc29uOiByZWFzb24udG9TdHJpbmcoKSB9KTtcbiAgY29uc3Qgb25FcnJvciA9IChlcnJvcjogRXJyb3IpID0+IHB1c2goeyBraW5kOiBcImVycm9yXCIsIGVycm9yIH0pO1xuICBjb25zdCBvblVuZXhwZWN0ZWRSZXNwb25zZSA9IChfcmVxdWVzdDogdW5rbm93biwgcmVzcG9uc2U6IHsgc3RhdHVzQ29kZT86IG51bWJlciB9KSA9PlxuICAgIHB1c2goeyBraW5kOiBcInJlamVjdGVkXCIsIHN0YXR1czogcmVzcG9uc2Uuc3RhdHVzQ29kZSB9KTtcbiAgc29ja2V0Lm9uKFwib3BlblwiLCBvbk9wZW4pO1xuICBzb2NrZXQub24oXCJtZXNzYWdlXCIsIG9uTWVzc2FnZSk7XG4gIHNvY2tldC5vbihcImNsb3NlXCIsIG9uQ2xvc2UpO1xuICBzb2NrZXQub24oXCJlcnJvclwiLCBvbkVycm9yKTtcbiAgc29ja2V0Lm9uKFwidW5leHBlY3RlZC1yZXNwb25zZVwiLCBvblVuZXhwZWN0ZWRSZXNwb25zZSk7XG4gIGNvbnN0IG9uQWJvcnQgPSAoKSA9PiB7XG4gICAgc29ja2V0LnRlcm1pbmF0ZSgpO1xuICAgIHB1c2goeyBraW5kOiBcImVycm9yXCIsIGVycm9yOiBhYm9ydEVycm9yKHNpZ25hbCkgfSk7XG4gIH07XG4gIHNpZ25hbD8uYWRkRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIG9uQWJvcnQsIHsgb25jZTogdHJ1ZSB9KTtcbiAgcmV0dXJuIHtcbiAgICBuZXh0OiAoKSA9PlxuICAgICAgcmVjb3Jkcy5sZW5ndGhcbiAgICAgICAgPyBQcm9taXNlLnJlc29sdmUocmVjb3Jkcy5zaGlmdCgpISlcbiAgICAgICAgOiBuZXcgUHJvbWlzZTxTb2NrZXRSZWNvcmQ+KChyZXNvbHZlKSA9PiB3YWl0ZXJzLnB1c2gocmVzb2x2ZSkpLFxuICAgIGNsZWFudXA6ICgpID0+IHtcbiAgICAgIGFjdGl2ZSA9IGZhbHNlO1xuICAgICAgc2lnbmFsPy5yZW1vdmVFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgb25BYm9ydCk7XG4gICAgICBzb2NrZXQub2ZmKFwib3BlblwiLCBvbk9wZW4pO1xuICAgICAgc29ja2V0Lm9mZihcIm1lc3NhZ2VcIiwgb25NZXNzYWdlKTtcbiAgICAgIHNvY2tldC5vZmYoXCJjbG9zZVwiLCBvbkNsb3NlKTtcbiAgICAgIC8vIGVycm9yIOumrOyKpOuEiOuKlCDrgqjquLTri6QoYWN0aXZlPWZhbHNl6528IHB1c2jripQgbm8tb3ApLiBDT05ORUNUSU5HIOyGjOy8k+ydmCB0ZXJtaW5hdGUoKeuKlFxuICAgICAgLy8g64uk7J2MIHRpY2vsl5AgZXJyb3LrpbwgZW1pdO2VmOuvgOuhnCwg65a87Ja0IOuRkOuptCBVbmhhbmRsZWQgJ2Vycm9yJ+uhnCDtlITroZzshLjsiqTqsIAg7KO964qU64ukLlxuICAgICAgc29ja2V0Lm9mZihcInVuZXhwZWN0ZWQtcmVzcG9uc2VcIiwgb25VbmV4cGVjdGVkUmVzcG9uc2UpO1xuICAgICAgcmVjb3Jkcy5sZW5ndGggPSAwO1xuICAgICAgY29uc3QgY2xvc2VkID0ge1xuICAgICAgICBraW5kOiBcImVycm9yXCIgYXMgY29uc3QsXG4gICAgICAgIGVycm9yOiBuZXcgT3BlbkFJUHJvdG9jb2xFcnJvcihcIk9wZW5BSSBXZWJTb2NrZXQgZXZlbnQgc3RyZWFtIHdhcyBjbG9zZWRcIiksXG4gICAgICB9O1xuICAgICAgd2FpdGVycy5zcGxpY2UoMCkuZm9yRWFjaCgod2FpdGVyKSA9PiB3YWl0ZXIoY2xvc2VkKSk7XG4gICAgfSxcbiAgICBkZXRhY2hBYm9ydDogKCkgPT4gc2lnbmFsPy5yZW1vdmVFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgb25BYm9ydCksXG4gIH07XG59XG5cbmZ1bmN0aW9uIGFib3J0RXJyb3Ioc2lnbmFsPzogQWJvcnRTaWduYWwpOiBFcnJvciB7XG4gIHJldHVybiBzaWduYWw/LnJlYXNvbiBpbnN0YW5jZW9mIEVycm9yXG4gICAgPyBzaWduYWwucmVhc29uXG4gICAgOiBuZXcgRE9NRXhjZXB0aW9uKFwiQWJvcnRlZFwiLCBcIkFib3J0RXJyb3JcIik7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG5leHRQb29sZWRSZWNvcmQoXG4gIGV2ZW50czogUmV0dXJuVHlwZTx0eXBlb2Ygc29ja2V0RXZlbnRzPixcbiAgc29ja2V0OiBPcGVuQUlXZWJTb2NrZXRMaWtlLFxuICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbik6IFByb21pc2U8U29ja2V0UmVjb3JkPiB7XG4gIGlmICghc2lnbmFsKSByZXR1cm4gZXZlbnRzLm5leHQoKTtcbiAgaWYgKHNpZ25hbC5hYm9ydGVkKSB0aHJvdyBhYm9ydEVycm9yKHNpZ25hbCk7XG4gIHJldHVybiBuZXcgUHJvbWlzZTxTb2NrZXRSZWNvcmQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCBvbkFib3J0ID0gKCkgPT4ge1xuICAgICAgc29ja2V0LnRlcm1pbmF0ZSgpO1xuICAgICAgcmVqZWN0KGFib3J0RXJyb3Ioc2lnbmFsKSk7XG4gICAgfTtcbiAgICBzaWduYWwuYWRkRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIG9uQWJvcnQsIHsgb25jZTogdHJ1ZSB9KTtcbiAgICB2b2lkIGV2ZW50c1xuICAgICAgLm5leHQoKVxuICAgICAgLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KVxuICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICBzaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIG9uQWJvcnQpO1xuICAgICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjYWNoZUFmZmluaXR5VXVpZChrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGhleCA9IGNyeXB0by5jcmVhdGVIYXNoKFwic2hhMjU2XCIpLnVwZGF0ZShrZXkpLmRpZ2VzdChcImhleFwiKS5zbGljZSgwLCAzMikuc3BsaXQoXCJcIik7XG4gIGhleFsxMl0gPSBcIjRcIjtcbiAgaGV4WzE2XSA9ICgoTnVtYmVyLnBhcnNlSW50KGhleFsxNl0hLCAxNikgJiAweDMpIHwgMHg4KS50b1N0cmluZygxNik7XG4gIHJldHVybiBgJHtoZXguc2xpY2UoMCwgOCkuam9pbihcIlwiKX0tJHtoZXguc2xpY2UoOCwgMTIpLmpvaW4oXCJcIil9LSR7aGV4LnNsaWNlKDEyLCAxNikuam9pbihcIlwiKX0tJHtoZXguc2xpY2UoMTYsIDIwKS5qb2luKFwiXCIpfS0ke2hleC5zbGljZSgyMCkuam9pbihcIlwiKX1gO1xufVxuXG50eXBlIEFmZmluaXR5Q29ubmVjdGlvbiA9IHtcbiAgc29ja2V0OiBPcGVuQUlXZWJTb2NrZXRMaWtlO1xuICBldmVudHM6IFJldHVyblR5cGU8dHlwZW9mIHNvY2tldEV2ZW50cz47XG4gIGNsb3NlZD86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgY2xhc3MgT3BlbkFJV2ViU29ja2V0VHJhbnNwb3J0IGltcGxlbWVudHMgT3BlbkFJUmVzcG9uc2VzVHJhbnNwb3J0IHtcbiAgc3RhdGljIHJlYWRvbmx5IE1BWF9BRkZJTklUWV9DT05ORUNUSU9OUyA9IDE2O1xuICBjcmVkZW50aWFsczogT3BlbkFJRGlyZWN0Q3JlZGVudGlhbHM7XG4gIHJlYWRvbmx5IHJlZnJlc2hDcmVkZW50aWFscz86ICgpID0+IFByb21pc2U8T3BlbkFJRGlyZWN0Q3JlZGVudGlhbHM+O1xuICByZWFkb25seSB3ZWJTb2NrZXRGYWN0b3J5OiBPcGVuQUlXZWJTb2NrZXRGYWN0b3J5O1xuICByZWFkb25seSBhZmZpbml0eUNvbm5lY3Rpb25zID0gbmV3IE1hcDxzdHJpbmcsIEFmZmluaXR5Q29ubmVjdGlvbj4oKTtcbiAgcmVhZG9ubHkgYnVzeUFmZmluaXRpZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBPcGVuQUlXZWJTb2NrZXRUcmFuc3BvcnRPcHRpb25zKSB7XG4gICAgdGhpcy5jcmVkZW50aWFscyA9IG9wdGlvbnMuY3JlZGVudGlhbHM7XG4gICAgdGhpcy5yZWZyZXNoQ3JlZGVudGlhbHMgPSBvcHRpb25zLnJlZnJlc2hDcmVkZW50aWFscztcbiAgICB0aGlzLndlYlNvY2tldEZhY3RvcnkgPVxuICAgICAgb3B0aW9ucy53ZWJTb2NrZXRGYWN0b3J5ID8/ICgodXJsLCB3c09wdGlvbnMpID0+IG5ldyBXc0NsaWVudCh1cmwsIHdzT3B0aW9ucykpO1xuICB9XG5cbiAgY2xvc2UoKTogdm9pZCB7XG4gICAgdGhpcy5hZmZpbml0eUNvbm5lY3Rpb25zLmZvckVhY2goKHsgc29ja2V0LCBldmVudHMgfSkgPT4ge1xuICAgICAgZXZlbnRzLmNsZWFudXAoKTtcbiAgICAgIHNvY2tldC5jbG9zZSgxMDAwLCBcInRyYW5zcG9ydCBjbG9zZWRcIik7XG4gICAgfSk7XG4gICAgdGhpcy5hZmZpbml0eUNvbm5lY3Rpb25zLmNsZWFyKCk7XG4gICAgdGhpcy5idXN5QWZmaW5pdGllcy5jbGVhcigpO1xuICB9XG5cbiAgLy8g7Jyg7Zy0IOyXsOqysOunjCDstpXstpztlZzri6QuIOyghOu2gCDsgqzsmqkg7KSR7J2066m0IGZhbHNl66W8IOuwmO2ZmO2VtCDsnbztmozshLEg7IaM7LyT7Jy866GcIOyymOumrO2VnOuLpC5cbiAgcmVtZW1iZXJBZmZpbml0eUNvbm5lY3Rpb24odGhyZWFkSWQ6IHN0cmluZywgY29ubmVjdGlvbjogQWZmaW5pdHlDb25uZWN0aW9uKTogYm9vbGVhbiB7XG4gICAgaWYgKFxuICAgICAgIXRoaXMuYWZmaW5pdHlDb25uZWN0aW9ucy5oYXModGhyZWFkSWQpICYmXG4gICAgICB0aGlzLmFmZmluaXR5Q29ubmVjdGlvbnMuc2l6ZSA+PSBPcGVuQUlXZWJTb2NrZXRUcmFuc3BvcnQuTUFYX0FGRklOSVRZX0NPTk5FQ1RJT05TXG4gICAgKSB7XG4gICAgICBjb25zdCBpZGxlS2V5ID0gWy4uLnRoaXMuYWZmaW5pdHlDb25uZWN0aW9ucy5rZXlzKCldLmZpbmQoXG4gICAgICAgIChrZXkpID0+ICF0aGlzLmJ1c3lBZmZpbml0aWVzLmhhcyhrZXkpLFxuICAgICAgKTtcbiAgICAgIGlmIChpZGxlS2V5ID09PSB1bmRlZmluZWQpIHJldHVybiBmYWxzZTtcbiAgICAgIGNvbnN0IGlkbGUgPSB0aGlzLmFmZmluaXR5Q29ubmVjdGlvbnMuZ2V0KGlkbGVLZXkpITtcbiAgICAgIGlkbGUuZXZlbnRzLmNsZWFudXAoKTtcbiAgICAgIGlkbGUuc29ja2V0LmNsb3NlKDEwMDAsIFwiYWZmaW5pdHkgY2FjaGUgZXZpY3RlZFwiKTtcbiAgICAgIHRoaXMuYWZmaW5pdHlDb25uZWN0aW9ucy5kZWxldGUoaWRsZUtleSk7XG4gICAgfVxuICAgIHRoaXMuYWZmaW5pdHlDb25uZWN0aW9ucy5zZXQodGhyZWFkSWQsIGNvbm5lY3Rpb24pO1xuICAgIC8vIOycoO2ctCDsg4Htg5zsl5DshJwgYmFja2VuZCDqsIAg64GK7J2AIOyGjOy8k+ydhCDri6TsnYwg7JqU7LKt7J20IOynkeyWtOuTpOyngCDslYrrj4TroZ0g7LqQ7Iuc7JeQ7IScIOygnOqxsO2VnOuLpC5cbiAgICBjb25zdCBkcm9wID0gKCkgPT4ge1xuICAgICAgY29ubmVjdGlvbi5jbG9zZWQgPSB0cnVlO1xuICAgICAgaWYgKHRoaXMuYnVzeUFmZmluaXRpZXMuaGFzKHRocmVhZElkKSkgcmV0dXJuO1xuICAgICAgaWYgKHRoaXMuYWZmaW5pdHlDb25uZWN0aW9ucy5nZXQodGhyZWFkSWQpICE9PSBjb25uZWN0aW9uKSByZXR1cm47XG4gICAgICB0aGlzLmFmZmluaXR5Q29ubmVjdGlvbnMuZGVsZXRlKHRocmVhZElkKTtcbiAgICAgIGNvbm5lY3Rpb24uZXZlbnRzLmNsZWFudXAoKTtcbiAgICB9O1xuICAgIGNvbm5lY3Rpb24uc29ja2V0Lm9uKFwiY2xvc2VcIiwgZHJvcCk7XG4gICAgY29ubmVjdGlvbi5zb2NrZXQub24oXCJlcnJvclwiLCBkcm9wKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGFzeW5jICpzdHJlYW0ocmVxdWVzdDogT3BlbkFJVHJhbnNwb3J0UmVxdWVzdCk6IEFzeW5jR2VuZXJhdG9yPE9wZW5BSU5vcm1hbGl6ZWRFdmVudD4ge1xuICAgIGxldCByZWZyZXNoZWQgPSBmYWxzZTtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgaWYgKHJlcXVlc3Quc2lnbmFsPy5hYm9ydGVkKSB0aHJvdyBhYm9ydEVycm9yKHJlcXVlc3Quc2lnbmFsKTtcbiAgICAgIGNvbnN0IGhhc0FmZmluaXR5ID0gcmVxdWVzdC5ib2R5LnByb21wdF9jYWNoZV9rZXkgIT09IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IHJldGFpbkNvbm5lY3Rpb24gPSBoYXNBZmZpbml0eSAmJiAhdGhpcy5idXN5QWZmaW5pdGllcy5oYXMocmVxdWVzdC50aHJlYWRJZCk7XG4gICAgICBpZiAocmV0YWluQ29ubmVjdGlvbikgdGhpcy5idXN5QWZmaW5pdGllcy5hZGQocmVxdWVzdC50aHJlYWRJZCk7XG4gICAgICBjb25zdCBlbnRyeSA9IHJldGFpbkNvbm5lY3Rpb24gPyB0aGlzLmFmZmluaXR5Q29ubmVjdGlvbnMuZ2V0KHJlcXVlc3QudGhyZWFkSWQpIDogdW5kZWZpbmVkO1xuICAgICAgaWYgKGVudHJ5Py5jbG9zZWQpIHtcbiAgICAgICAgdGhpcy5hZmZpbml0eUNvbm5lY3Rpb25zLmRlbGV0ZShyZXF1ZXN0LnRocmVhZElkKTtcbiAgICAgICAgZW50cnkuZXZlbnRzLmNsZWFudXAoKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNhY2hlZCA9IGVudHJ5Py5jbG9zZWQgPyB1bmRlZmluZWQgOiBlbnRyeTtcbiAgICAgIGxldCByZXRhaW5lZCA9IHJldGFpbkNvbm5lY3Rpb247XG4gICAgICBjb25zdCBzb2NrZXQgPVxuICAgICAgICBjYWNoZWQ/LnNvY2tldCA/P1xuICAgICAgICB0aGlzLndlYlNvY2tldEZhY3Rvcnkod2Vic29ja2V0VXJsKENIQVRHUFRfQ09ERVhfUkVTUE9OU0VTX1VSTCksIHtcbiAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAuLi5idWlsZENvZGV4SWRlbnRpdHlIZWFkZXJzKHRoaXMuY3JlZGVudGlhbHMuYWNjZXNzVG9rZW4sIHRoaXMuY3JlZGVudGlhbHMuYWNjb3VudElkLCB7XG4gICAgICAgICAgICAgIHNlc3Npb25JZDogcmVxdWVzdC5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgIHRocmVhZElkOiByZXF1ZXN0LnRocmVhZElkLFxuICAgICAgICAgICAgICBjbGllbnRSZXF1ZXN0SWQ6IHJlcXVlc3QuY2xpZW50UmVxdWVzdElkLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBcIk9wZW5BSS1CZXRhXCI6IFwicmVzcG9uc2VzX3dlYnNvY2tldHM9MjAyNi0wMi0wNlwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgY29uc3QgZXZlbnRzID0gY2FjaGVkPy5ldmVudHMgPz8gc29ja2V0RXZlbnRzKHNvY2tldCwgcmVxdWVzdC5zaWduYWwpO1xuICAgICAgbGV0IGNvbXBsZXRlZCA9IGZhbHNlO1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKCFjYWNoZWQpIHtcbiAgICAgICAgICBjb25zdCBoYW5kc2hha2UgPSBhd2FpdCBldmVudHMubmV4dCgpO1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIGhhbmRzaGFrZS5raW5kID09PSBcInJlamVjdGVkXCIgJiZcbiAgICAgICAgICAgIGhhbmRzaGFrZS5zdGF0dXMgPT09IDQwMSAmJlxuICAgICAgICAgICAgIXJlZnJlc2hlZCAmJlxuICAgICAgICAgICAgdGhpcy5yZWZyZXNoQ3JlZGVudGlhbHNcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHNvY2tldC50ZXJtaW5hdGUoKTtcbiAgICAgICAgICAgIHRoaXMuY3JlZGVudGlhbHMgPSBhd2FpdCB0aGlzLnJlZnJlc2hDcmVkZW50aWFscygpO1xuICAgICAgICAgICAgcmVmcmVzaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoaGFuZHNoYWtlLmtpbmQgPT09IFwicmVqZWN0ZWRcIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IE9wZW5BSVByb3RvY29sRXJyb3IoXG4gICAgICAgICAgICAgIGBPcGVuQUkgV2ViU29ja2V0IGhhbmRzaGFrZSByZWplY3RlZCR7aGFuZHNoYWtlLnN0YXR1cyA/IGAgd2l0aCBIVFRQICR7aGFuZHNoYWtlLnN0YXR1c31gIDogXCJcIn1gLFxuICAgICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIGhhbmRzaGFrZS5zdGF0dXMsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoaGFuZHNoYWtlLmtpbmQgPT09IFwiZXJyb3JcIikgdGhyb3cgaGFuZHNoYWtlLmVycm9yO1xuICAgICAgICAgIGlmIChoYW5kc2hha2Uua2luZCAhPT0gXCJvcGVuXCIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBPcGVuQUlQcm90b2NvbEVycm9yKFwiT3BlbkFJIFdlYlNvY2tldCBjbG9zZWQgYmVmb3JlIHRoZSBoYW5kc2hha2UgY29tcGxldGVkXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocmV0YWluQ29ubmVjdGlvbikge1xuICAgICAgICAgICAgcmV0YWluZWQgPSB0aGlzLnJlbWVtYmVyQWZmaW5pdHlDb25uZWN0aW9uKHJlcXVlc3QudGhyZWFkSWQsIHsgc29ja2V0LCBldmVudHMgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgIHNvY2tldC5zZW5kKEpTT04uc3RyaW5naWZ5KHsgdHlwZTogXCJyZXNwb25zZS5jcmVhdGVcIiwgLi4ucmVxdWVzdC5ib2R5IH0pLCAoZXJyb3IpID0+XG4gICAgICAgICAgICBlcnJvciA/IHJlamVjdChlcnJvcikgOiByZXNvbHZlKCksXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICBjb25zdCByZWNvcmQgPSBjYWNoZWRcbiAgICAgICAgICAgID8gYXdhaXQgbmV4dFBvb2xlZFJlY29yZChldmVudHMsIHNvY2tldCwgcmVxdWVzdC5zaWduYWwpXG4gICAgICAgICAgICA6IGF3YWl0IGV2ZW50cy5uZXh0KCk7XG4gICAgICAgICAgaWYgKHJlY29yZC5raW5kID09PSBcIm1lc3NhZ2VcIikge1xuICAgICAgICAgICAgaWYgKHJlY29yZC5pc0JpbmFyeSkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgT3BlbkFJUHJvdG9jb2xFcnJvcihcIk9wZW5BSSBXZWJTb2NrZXQgc2VudCBhbiB1bmV4cGVjdGVkIGJpbmFyeSBtZXNzYWdlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHJhdzogdW5rbm93bjtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIHJhdyA9IEpTT04ucGFyc2UocmF3RGF0YVRleHQocmVjb3JkLmRhdGEpKTtcbiAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgT3BlbkFJUHJvdG9jb2xFcnJvcihcIk9wZW5BSSBXZWJTb2NrZXQgc2VudCBpbnZhbGlkIEpTT05cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBldmVudCA9IG5vcm1hbGl6ZU9wZW5BSUV2ZW50KHJhdyk7XG4gICAgICAgICAgICBpZiAoIWV2ZW50KSBjb250aW51ZTtcbiAgICAgICAgICAgIGlmIChldmVudC50eXBlID09PSBcImNvbXBsZXRlZFwiKSB7XG4gICAgICAgICAgICAgIGNvbXBsZXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgIGlmIChyZXRhaW5lZCkgZXZlbnRzLmRldGFjaEFib3J0KCk7XG4gICAgICAgICAgICAgIGVsc2Ugc29ja2V0LmNsb3NlKDEwMDAsIFwicmVzcG9uc2UgY29tcGxldGVkXCIpO1xuICAgICAgICAgICAgICB5aWVsZCBldmVudDtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeWllbGQgZXZlbnQ7XG4gICAgICAgICAgICBpZiAoZXZlbnQudHlwZSA9PT0gXCJlcnJvclwiKSB0aHJvdyBldmVudC5lcnJvcjtcbiAgICAgICAgICB9IGVsc2UgaWYgKHJlY29yZC5raW5kID09PSBcImVycm9yXCIpIHtcbiAgICAgICAgICAgIHRocm93IHJlY29yZC5lcnJvcjtcbiAgICAgICAgICB9IGVsc2UgaWYgKHJlY29yZC5raW5kID09PSBcImNsb3NlXCIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBPcGVuQUlQcm90b2NvbEVycm9yKFxuICAgICAgICAgICAgICBgT3BlbkFJIFdlYlNvY2tldCBjbG9zZWQgYmVmb3JlIGEgdGVybWluYWwgcmVzcG9uc2UgZXZlbnQgKCR7cmVjb3JkLmNvZGV9JHtyZWNvcmQucmVhc29uID8gYDogJHtyZWNvcmQucmVhc29ufWAgOiBcIlwifSlgLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IE9wZW5BSVByb3RvY29sRXJyb3IoXCJPcGVuQUkgV2ViU29ja2V0IGVtaXR0ZWQgYW4gdW5leHBlY3RlZCBoYW5kc2hha2UgZXZlbnRcIik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBpZiAoIWNvbXBsZXRlZCB8fCAhcmV0YWluZWQpIHtcbiAgICAgICAgICBpZiAocmV0YWluZWQpIHRoaXMuYWZmaW5pdHlDb25uZWN0aW9ucy5kZWxldGUocmVxdWVzdC50aHJlYWRJZCk7XG4gICAgICAgICAgZXZlbnRzLmNsZWFudXAoKTtcbiAgICAgICAgICBpZiAoIWNvbXBsZXRlZCkgc29ja2V0LnRlcm1pbmF0ZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXRhaW5Db25uZWN0aW9uKSB0aGlzLmJ1c3lBZmZpbml0aWVzLmRlbGV0ZShyZXF1ZXN0LnRocmVhZElkKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVzcG9uc2VFcnJvcihyZXNwb25zZTogUmVzcG9uc2UpOiBQcm9taXNlPE9wZW5BSVByb3RvY29sRXJyb3I+IHtcbiAgY29uc3QgdGV4dCA9IGF3YWl0IHJlc3BvbnNlLnRleHQoKS5jYXRjaCgoKSA9PiBcIlwiKTtcbiAgbGV0IG1lc3NhZ2UgPSB0ZXh0IHx8IHJlc3BvbnNlLnN0YXR1c1RleHQgfHwgYEhUVFAgJHtyZXNwb25zZS5zdGF0dXN9YDtcbiAgbGV0IGNvZGU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgdHJ5IHtcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKHRleHQpIGFzIHtcbiAgICAgIGVycm9yPzogeyBtZXNzYWdlPzogc3RyaW5nOyBjb2RlPzogc3RyaW5nIH0gfCBzdHJpbmc7XG4gICAgICBtZXNzYWdlPzogc3RyaW5nO1xuICAgICAgY29kZT86IHN0cmluZztcbiAgICB9O1xuICAgIGNvbnN0IGVycm9yID0gcGFyc2VkLmVycm9yO1xuICAgIG1lc3NhZ2UgPVxuICAgICAgKHR5cGVvZiBlcnJvciA9PT0gXCJvYmplY3RcIiA/IGVycm9yLm1lc3NhZ2UgOiB1bmRlZmluZWQpID8/XG4gICAgICBwYXJzZWQubWVzc2FnZSA/P1xuICAgICAgKHR5cGVvZiBlcnJvciA9PT0gXCJzdHJpbmdcIiA/IGVycm9yIDogbWVzc2FnZSk7XG4gICAgY29kZSA9ICh0eXBlb2YgZXJyb3IgPT09IFwib2JqZWN0XCIgPyBlcnJvci5jb2RlIDogdW5kZWZpbmVkKSA/PyBwYXJzZWQuY29kZTtcbiAgfSBjYXRjaCB7XG4gICAgY29kZSA9IHVuZGVmaW5lZDtcbiAgfVxuICByZXR1cm4gbmV3IE9wZW5BSVByb3RvY29sRXJyb3IobWVzc2FnZSwgY29kZSwgcmVzcG9uc2Uuc3RhdHVzKTtcbn1cblxuZXhwb3J0IGNsYXNzIE9wZW5BSUh0dHBzVHJhbnNwb3J0IGltcGxlbWVudHMgT3BlbkFJUmVzcG9uc2VzVHJhbnNwb3J0IHtcbiAgY3JlZGVudGlhbHM6IE9wZW5BSURpcmVjdENyZWRlbnRpYWxzO1xuICByZWFkb25seSBmZXRjaEltcGw6IHR5cGVvZiBmZXRjaDtcbiAgcmVhZG9ubHkgcmVmcmVzaENyZWRlbnRpYWxzPzogKCkgPT4gUHJvbWlzZTxPcGVuQUlEaXJlY3RDcmVkZW50aWFscz47XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogT3BlbkFJSHR0cHNUcmFuc3BvcnRPcHRpb25zKSB7XG4gICAgdGhpcy5jcmVkZW50aWFscyA9IG9wdGlvbnMuY3JlZGVudGlhbHM7XG4gICAgdGhpcy5mZXRjaEltcGwgPSBvcHRpb25zLmZldGNoID8/IGZldGNoO1xuICAgIHRoaXMucmVmcmVzaENyZWRlbnRpYWxzID0gb3B0aW9ucy5yZWZyZXNoQ3JlZGVudGlhbHM7XG4gIH1cblxuICBhc3luYyAqc3RyZWFtKHJlcXVlc3Q6IE9wZW5BSVRyYW5zcG9ydFJlcXVlc3QpOiBBc3luY0dlbmVyYXRvcjxPcGVuQUlOb3JtYWxpemVkRXZlbnQ+IHtcbiAgICBsZXQgcmVmcmVzaGVkID0gZmFsc2U7XG5cbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmZldGNoSW1wbChDSEFUR1BUX0NPREVYX1JFU1BPTlNFU19VUkwsIHtcbiAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgaGVhZGVyczogYnVpbGRDb2RleElkZW50aXR5SGVhZGVycyhcbiAgICAgICAgICB0aGlzLmNyZWRlbnRpYWxzLmFjY2Vzc1Rva2VuLFxuICAgICAgICAgIHRoaXMuY3JlZGVudGlhbHMuYWNjb3VudElkLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHNlc3Npb25JZDogcmVxdWVzdC5zZXNzaW9uSWQsXG4gICAgICAgICAgICB0aHJlYWRJZDogcmVxdWVzdC50aHJlYWRJZCxcbiAgICAgICAgICAgIGNsaWVudFJlcXVlc3RJZDogcmVxdWVzdC5jbGllbnRSZXF1ZXN0SWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgKSxcbiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkocmVxdWVzdC5ib2R5KSxcbiAgICAgICAgc2lnbmFsOiByZXF1ZXN0LnNpZ25hbCxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSA0MDEgJiYgIXJlZnJlc2hlZCAmJiB0aGlzLnJlZnJlc2hDcmVkZW50aWFscykge1xuICAgICAgICBhd2FpdCByZXNwb25zZS5ib2R5Py5jYW5jZWwoKTtcbiAgICAgICAgdGhpcy5jcmVkZW50aWFscyA9IGF3YWl0IHRoaXMucmVmcmVzaENyZWRlbnRpYWxzKCk7XG4gICAgICAgIHJlZnJlc2hlZCA9IHRydWU7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKCFyZXNwb25zZS5vaykgdGhyb3cgYXdhaXQgcmVzcG9uc2VFcnJvcihyZXNwb25zZSk7XG4gICAgICBpZiAoIXJlc3BvbnNlLmJvZHkpIHRocm93IG5ldyBPcGVuQUlQcm90b2NvbEVycm9yKFwiT3BlbkFJIHJlc3BvbnNlIGhhZCBubyBib2R5XCIpO1xuXG4gICAgICBmb3IgYXdhaXQgKGNvbnN0IGV2ZW50IG9mIG5vcm1hbGl6ZU9wZW5BSVNTRShyZXNwb25zZS5ib2R5KSkge1xuICAgICAgICB5aWVsZCBldmVudDtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlEaXJlY3RDbGllbnRPcHRpb25zIGV4dGVuZHMgT3BlbkFJSHR0cHNUcmFuc3BvcnRPcHRpb25zIHtcbiAgdHJhbnNwb3J0PzogT3BlbkFJUmVzcG9uc2VzVHJhbnNwb3J0O1xuICB0cmFuc3BvcnRLaW5kPzogXCJodHRwc1wiIHwgXCJ3ZWJzb2NrZXRcIjtcbiAgd2ViU29ja2V0RmFjdG9yeT86IE9wZW5BSVdlYlNvY2tldEZhY3Rvcnk7XG59XG5cbmV4cG9ydCBjbGFzcyBPcGVuQUlEaXJlY3RDbGllbnQge1xuICByZWFkb25seSB0cmFuc3BvcnQ6IE9wZW5BSVJlc3BvbnNlc1RyYW5zcG9ydDtcbiAgaW1hZ2VDcmVkZW50aWFsczogT3BlbkFJRGlyZWN0Q3JlZGVudGlhbHM7XG5cbiAgY29uc3RydWN0b3IocmVhZG9ubHkgb3B0aW9uczogT3BlbkFJRGlyZWN0Q2xpZW50T3B0aW9ucykge1xuICAgIHRoaXMuaW1hZ2VDcmVkZW50aWFscyA9IG9wdGlvbnMuY3JlZGVudGlhbHM7XG4gICAgdGhpcy50cmFuc3BvcnQgPVxuICAgICAgb3B0aW9ucy50cmFuc3BvcnQgPz9cbiAgICAgIChvcHRpb25zLnRyYW5zcG9ydEtpbmQgPT09IFwid2Vic29ja2V0XCJcbiAgICAgICAgPyBuZXcgT3BlbkFJV2ViU29ja2V0VHJhbnNwb3J0KG9wdGlvbnMpXG4gICAgICAgIDogbmV3IE9wZW5BSUh0dHBzVHJhbnNwb3J0KG9wdGlvbnMpKTtcbiAgfVxuXG4gIHJlc3BvbnNlcyhvcHRpb25zOiBPcGVuQUlSZXNwb25zZXNPcHRpb25zLCBzaWduYWw/OiBBYm9ydFNpZ25hbCk6IE9wZW5BSUV2ZW50U3RyZWFtIHtcbiAgICBpZiAoXG4gICAgICBvcHRpb25zLm1vZGVsID09PSBcImdwdC1pbWFnZS0yXCIgfHxcbiAgICAgICh0eXBlb2Ygb3B0aW9ucy5pbWFnZUdlbmVyYXRpb24gPT09IFwib2JqZWN0XCIgJiZcbiAgICAgICAgb3B0aW9ucy5pbWFnZUdlbmVyYXRpb24uYmFja2dyb3VuZCA9PT0gXCJ0cmFuc3BhcmVudFwiKVxuICAgICkge1xuICAgICAgcmV0dXJuIHRoaXMuc3RhbmRhbG9uZUltYWdlcyhvcHRpb25zLCBzaWduYWwpO1xuICAgIH1cbiAgICBjb25zdCBjbGllbnRSZXF1ZXN0SWQgPSBjcnlwdG8ucmFuZG9tVVVJRCgpO1xuICAgIGNvbnN0IGFmZmluaXR5SWQgPSBvcHRpb25zLnByb21wdENhY2hlS2V5XG4gICAgICA/IGNhY2hlQWZmaW5pdHlVdWlkKG9wdGlvbnMucHJvbXB0Q2FjaGVLZXkpXG4gICAgICA6IGNsaWVudFJlcXVlc3RJZDtcbiAgICByZXR1cm4gdGhpcy50cmFuc3BvcnQuc3RyZWFtKHtcbiAgICAgIGJvZHk6IGJ1aWxkT3BlbkFJUmVzcG9uc2VzUmVxdWVzdChcbiAgICAgICAgb3B0aW9ucy5wcm9tcHRDYWNoZUtleSA/IHsgLi4ub3B0aW9ucywgcHJvbXB0Q2FjaGVLZXk6IGFmZmluaXR5SWQgfSA6IG9wdGlvbnMsXG4gICAgICApLFxuICAgICAgc2lnbmFsLFxuICAgICAgc2Vzc2lvbklkOiBhZmZpbml0eUlkLFxuICAgICAgLy8gcHJvbXB0Q2FjaGVLZXkgaXMgYWxyZWFkeSBhIG9uZS13YXkgU0RLIGFmZmluaXR5IHZhbHVlLCBuZXZlciBhIHJhdyBzZXNzaW9uS2V5LlxuICAgICAgdGhyZWFkSWQ6IGFmZmluaXR5SWQsXG4gICAgICBjbGllbnRSZXF1ZXN0SWQsXG4gICAgfSk7XG4gIH1cblxuICBhc3luYyAqc3RhbmRhbG9uZUltYWdlcyhcbiAgICBvcHRpb25zOiBPcGVuQUlSZXNwb25zZXNPcHRpb25zLFxuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuICApOiBPcGVuQUlFdmVudFN0cmVhbSB7XG4gICAgY29uc3QgcmVxdWVzdCA9IGJ1aWxkU3RhbmRhbG9uZUltYWdlUmVxdWVzdChvcHRpb25zKTtcbiAgICBjb25zdCByZXF1ZXN0SWQgPSBjcnlwdG8ucmFuZG9tVVVJRCgpO1xuICAgIGZvciAobGV0IGF0dGVtcHQgPSAwOyBhdHRlbXB0IDwgMjsgYXR0ZW1wdCsrKSB7XG4gICAgICBzaWduYWw/LnRocm93SWZBYm9ydGVkKCk7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0ICh0aGlzLm9wdGlvbnMuZmV0Y2ggPz8gZmV0Y2gpKHJlcXVlc3QudXJsLCB7XG4gICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAuLi5idWlsZENvZGV4SWRlbnRpdHlIZWFkZXJzKFxuICAgICAgICAgICAgdGhpcy5pbWFnZUNyZWRlbnRpYWxzLmFjY2Vzc1Rva2VuLFxuICAgICAgICAgICAgdGhpcy5pbWFnZUNyZWRlbnRpYWxzLmFjY291bnRJZCxcbiAgICAgICAgICApLFxuICAgICAgICAgIEFjY2VwdDogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgICAgXCJ4LWNvZGV4LWltYWdlLXR1cm4taWRcIjogcmVxdWVzdElkLFxuICAgICAgICB9LFxuICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShyZXF1ZXN0LmJvZHkpLFxuICAgICAgICBzaWduYWwsXG4gICAgICB9KTtcbiAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgPT09IDQwMSAmJiBhdHRlbXB0ID09PSAwICYmIHRoaXMub3B0aW9ucy5yZWZyZXNoQ3JlZGVudGlhbHMpIHtcbiAgICAgICAgYXdhaXQgcmVzcG9uc2UuYm9keT8uY2FuY2VsKCk7XG4gICAgICAgIHRoaXMuaW1hZ2VDcmVkZW50aWFscyA9IGF3YWl0IHRoaXMub3B0aW9ucy5yZWZyZXNoQ3JlZGVudGlhbHMoKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAoIXJlc3BvbnNlLm9rKSB0aHJvdyBhd2FpdCByZXNwb25zZUVycm9yKHJlc3BvbnNlKTtcbiAgICAgIGNvbnN0IGltYWdlcyA9IGF3YWl0IHJlYWRTdGFuZGFsb25lSW1hZ2VSZXNwb25zZShcbiAgICAgICAgcmVzcG9uc2UsXG4gICAgICAgIHR5cGVvZiBvcHRpb25zLmltYWdlR2VuZXJhdGlvbiA9PT0gXCJvYmplY3RcIiAmJlxuICAgICAgICAgIG9wdGlvbnMuaW1hZ2VHZW5lcmF0aW9uLmJhY2tncm91bmQgPT09IFwidHJhbnNwYXJlbnRcIixcbiAgICAgICk7XG4gICAgICBzaWduYWw/LnRocm93SWZBYm9ydGVkKCk7XG4gICAgICB5aWVsZCogaW1hZ2VzO1xuICAgICAgY29uc3QgZmlyc3RJbWFnZSA9IGltYWdlc1swXTtcbiAgICAgIHlpZWxkIHtcbiAgICAgICAgdHlwZTogXCJjb21wbGV0ZWRcIixcbiAgICAgICAgcmVzcG9uc2VJZDogcmVxdWVzdElkLFxuICAgICAgICBtb2RlbDogZmlyc3RJbWFnZT8udHlwZSA9PT0gXCJpbWFnZVwiID8gZmlyc3RJbWFnZS5nZW5lcmF0aW9uPy5tb2RlbCA6IFwiZ3B0LWltYWdlLTJcIixcbiAgICAgIH07XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG5cbiAgY2xvc2UoKTogdm9pZCB7XG4gICAgdGhpcy50cmFuc3BvcnQuY2xvc2U/LigpO1xuICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQXdFQSxNQUFNLDhCQUE4QjtBQUVwQyxTQUFTLGFBQWEsS0FBcUI7Q0FDekMsSUFBSTtDQUNKLElBQUk7RUFDRixTQUFTLElBQUksSUFBSSxH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
|
|
@@ -104,6 +104,7 @@ describe("qgrid run lifecycle start", () => {
|
|
|
104
104
|
system_prompt: "system",
|
|
105
105
|
requested_model_name: "openai/gpt-5-codex",
|
|
106
106
|
effort: undefined,
|
|
107
|
+
service_tier: undefined,
|
|
107
108
|
project_name: "project",
|
|
108
109
|
history: [{ type: "message", role: "user", content: "earlier" }],
|
|
109
110
|
is_image_generation: undefined,
|
|
@@ -111,6 +112,16 @@ describe("qgrid run lifecycle start", () => {
|
|
|
111
112
|
});
|
|
112
113
|
});
|
|
113
114
|
|
|
115
|
+
it.each([
|
|
116
|
+
["openai/gpt-6-sol", "fast", "fast"],
|
|
117
|
+
["openai/gpt-6-sol", "flex", "flex"],
|
|
118
|
+
["openai/gpt-6-sol", undefined, undefined],
|
|
119
|
+
["anthropic/claude-sonnet-5-5", "fast", undefined],
|
|
120
|
+
] as const)("logs service tier for %s with %s", async (model, serviceTier, expected) => {
|
|
121
|
+
await beforeQuery({ prompt: "hi", model, serviceTier });
|
|
122
|
+
expect(createRunMock).toHaveBeenCalledWith(expect.objectContaining({ service_tier: expected }));
|
|
123
|
+
});
|
|
124
|
+
|
|
114
125
|
it.each([false, true, undefined])("does not log ignored effort when thinking is %s", async (thinking) => {
|
|
115
126
|
await beforeQuery({ prompt: "hi", model: "openai/gpt-6-sol", thinking, effort: "high" });
|
|
116
127
|
expect(createRunMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
@@ -270,6 +281,13 @@ describe("qgrid run lifecycle TTFT", () => {
|
|
|
270
281
|
);
|
|
271
282
|
});
|
|
272
283
|
|
|
284
|
+
it.each(["fast", "flex", undefined] as const)("records the final turn service tier: %s", async (serviceTier) => {
|
|
285
|
+
await afterQuery(10, 2, { prompt: "hi", model: "openai/gpt-6-sol", serviceTier }, queryOutput());
|
|
286
|
+
expect(finishRunMock).toHaveBeenCalledWith(10, expect.objectContaining({
|
|
287
|
+
service_tier: serviceTier ?? null,
|
|
288
|
+
}));
|
|
289
|
+
});
|
|
290
|
+
|
|
273
291
|
it("persists an immediate structured final answer as JSON text", async () => {
|
|
274
292
|
await afterQuery(
|
|
275
293
|
10,
|
|
@@ -89,6 +89,7 @@ export async function beforeQuery(args: QueryInput): Promise<{
|
|
|
89
89
|
system_prompt: args.system,
|
|
90
90
|
requested_model_name: args.model,
|
|
91
91
|
effort: args.thinking === false ? undefined : args.effort,
|
|
92
|
+
service_tier: args.model?.startsWith("openai/") ? args.serviceTier : undefined,
|
|
92
93
|
project_name: args.projectName,
|
|
93
94
|
history: filterHistoryForStorage(args.history),
|
|
94
95
|
tools: args.tools?.length ? args.tools : undefined,
|
|
@@ -197,6 +198,7 @@ export async function afterQuery(
|
|
|
197
198
|
requested_model_name: requestedModelName,
|
|
198
199
|
model_name: servedModelName,
|
|
199
200
|
fallback_count: agg.fallback_count,
|
|
201
|
+
service_tier: args.model?.startsWith("openai/") ? (args.serviceTier ?? null) : null,
|
|
200
202
|
cost_usd: agg.cost_usd,
|
|
201
203
|
cost_source: agg.cost_source,
|
|
202
204
|
image_cost_usd: imageCostMicroUsd,
|
|
@@ -38,6 +38,29 @@ function deeplyNestedOutputSchema(depth: number): string {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
describe("QgridDispatcherClass", () => {
|
|
41
|
+
it.each([false, true])("applies Fast pricing to OpenAI query (stream=%s)", async (stream) => {
|
|
42
|
+
const dispatcher = new QgridDispatcherClass();
|
|
43
|
+
const result = providerResult({
|
|
44
|
+
model: "gpt-6.1-sol",
|
|
45
|
+
usage: { totalTokens: 2000, inputTokens: 1000, cachedInputTokens: 500, outputTokens: 1000, reasoningOutputTokens: 0 },
|
|
46
|
+
});
|
|
47
|
+
dispatcher.openaiDispatcher = {
|
|
48
|
+
generate: vi.fn(async () => result),
|
|
49
|
+
generateStream: vi.fn(async (_req, cb) => cb.onComplete(result)),
|
|
50
|
+
} as never;
|
|
51
|
+
const input = { prompt: "hi", model: "openai/gpt-6.1-sol", serviceTier: "fast" as const };
|
|
52
|
+
let output: QueryOutput | undefined;
|
|
53
|
+
if (stream) {
|
|
54
|
+
await dispatcher.queryStream(input, {
|
|
55
|
+
onDelta: () => {}, onComplete: (value) => { output = value; }, onError: (error) => { throw error; },
|
|
56
|
+
});
|
|
57
|
+
} else {
|
|
58
|
+
output = await dispatcher.query(input);
|
|
59
|
+
}
|
|
60
|
+
expect(output?.costUsd).toBeCloseTo(0.0221, 10);
|
|
61
|
+
expect(output?.costSource).toBe("pricing_table");
|
|
62
|
+
});
|
|
63
|
+
|
|
41
64
|
it("prices only the completed chat driver from an image failure", () => {
|
|
42
65
|
const error = new ImageGenerationError("incomplete", "images unavailable");
|
|
43
66
|
error.completedDriver = providerResult({
|
|
@@ -52,6 +75,7 @@ describe("QgridDispatcherClass", () => {
|
|
|
52
75
|
content: [{ type: "text", text: "ok" }],
|
|
53
76
|
});
|
|
54
77
|
expect(result.costUsd).toBeCloseTo(0.0000191, 10);
|
|
78
|
+
expect(completedDriverFromImageFailure(error, "fast")?.costUsd).toBeCloseTo(0.0000382, 10);
|
|
55
79
|
expect(estimateImageGenerationCostMicroUsd(result, undefined)).toBeNull();
|
|
56
80
|
expect(result.runContext).toBeUndefined();
|
|
57
81
|
expect(completedDriverFromImageFailure(new Error("failed"))).toBeUndefined();
|
|
@@ -127,7 +127,7 @@ export class QgridDispatcherClass {
|
|
|
127
127
|
? undefined
|
|
128
128
|
: issueConvContext(result.threadCoord, decision, result.threadCoord.workerId);
|
|
129
129
|
|
|
130
|
-
return applyToolCallEmulation(toEmulationResult(result), input.tools, {
|
|
130
|
+
return applyToolCallEmulation(toEmulationResult(result, input.serviceTier), input.tools, {
|
|
131
131
|
threadCoord: coord,
|
|
132
132
|
images: result.images,
|
|
133
133
|
answerKind,
|
|
@@ -206,14 +206,18 @@ export class QgridDispatcherClass {
|
|
|
206
206
|
onComplete: (turnResult) => {
|
|
207
207
|
this.recordCompleted("openai", turnResult.tokenName);
|
|
208
208
|
cb.onComplete(
|
|
209
|
-
applyToolCallEmulation(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
209
|
+
applyToolCallEmulation(
|
|
210
|
+
toEmulationResult(turnResult, input.serviceTier),
|
|
211
|
+
input.tools,
|
|
212
|
+
{
|
|
213
|
+
threadCoord: issueConvContext(
|
|
214
|
+
turnResult.threadCoord,
|
|
215
|
+
decision,
|
|
216
|
+
turnResult.threadCoord.workerId,
|
|
217
|
+
),
|
|
218
|
+
answerKind,
|
|
219
|
+
},
|
|
220
|
+
),
|
|
217
221
|
);
|
|
218
222
|
},
|
|
219
223
|
onError: cb.onError,
|
|
@@ -328,9 +332,12 @@ function buildRawOutputSchema(
|
|
|
328
332
|
: callerOutputSchema;
|
|
329
333
|
}
|
|
330
334
|
|
|
331
|
-
export function completedDriverFromImageFailure(
|
|
335
|
+
export function completedDriverFromImageFailure(
|
|
336
|
+
error: unknown,
|
|
337
|
+
serviceTier?: string,
|
|
338
|
+
): QueryOutput | undefined {
|
|
332
339
|
if (!(error instanceof ImageGenerationError) || !error.completedDriver) return undefined;
|
|
333
|
-
return applyToolCallEmulation(toEmulationResult(error.completedDriver), undefined, {
|
|
340
|
+
return applyToolCallEmulation(toEmulationResult(error.completedDriver, serviceTier), undefined, {
|
|
334
341
|
answerKind: "text",
|
|
335
342
|
});
|
|
336
343
|
}
|
|
@@ -338,6 +345,7 @@ export function completedDriverFromImageFailure(error: unknown): QueryOutput | u
|
|
|
338
345
|
// Anthropic adapter 는 cache creation 을 inputTokens 에 포함해 표준화하고, 별도 필드에도 보존한다.
|
|
339
346
|
function toEmulationResult(
|
|
340
347
|
result: GenerateResult,
|
|
348
|
+
serviceTier?: string,
|
|
341
349
|
): Omit<QueryOutput, "content" | "finishReason" | "runContext"> {
|
|
342
350
|
const hasProviderCost = result.costUsd !== undefined && result.costUsd > 0;
|
|
343
351
|
return {
|
|
@@ -359,14 +367,18 @@ function toEmulationResult(
|
|
|
359
367
|
ttftMs: result.ttftMs ?? 0,
|
|
360
368
|
costUsd: hasProviderCost
|
|
361
369
|
? result.costUsd!
|
|
362
|
-
: calculateCostUsd(
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
+
: calculateCostUsd(
|
|
371
|
+
result.model,
|
|
372
|
+
{
|
|
373
|
+
inputTokens: result.usage.inputTokens,
|
|
374
|
+
outputTokens: result.usage.outputTokens,
|
|
375
|
+
cachedInputTokens: result.usage.cachedInputTokens,
|
|
376
|
+
cacheCreationInputTokens: result.usage.cacheCreationInputTokens ?? 0,
|
|
377
|
+
cacheCreationInputTokens5m: result.usage.cacheCreationInputTokens5m,
|
|
378
|
+
cacheCreationInputTokens1h: result.usage.cacheCreationInputTokens1h,
|
|
379
|
+
},
|
|
380
|
+
serviceTier,
|
|
381
|
+
),
|
|
370
382
|
costSource: hasProviderCost ? "provider" : "pricing_table",
|
|
371
383
|
};
|
|
372
384
|
}
|
|
@@ -405,6 +405,7 @@ describe("QgridFrame.query request logging", () => {
|
|
|
405
405
|
});
|
|
406
406
|
const args = {
|
|
407
407
|
prompt: "draw", model: "openai/gpt-6-luna", imageGeneration: "auto" as const,
|
|
408
|
+
serviceTier: "fast" as const,
|
|
408
409
|
...(mode === "logger-disabled" ? { logger: false } : {}),
|
|
409
410
|
};
|
|
410
411
|
await expect(QgridFrame.query(args)).rejects.toBe(error);
|
|
@@ -417,7 +418,7 @@ describe("QgridFrame.query request logging", () => {
|
|
|
417
418
|
const completedStep = expect.objectContaining({
|
|
418
419
|
stepIndex: 0,
|
|
419
420
|
result: expect.objectContaining({
|
|
420
|
-
model: "gpt-6-luna", tokenName: "one", costUsd: 0.
|
|
421
|
+
model: "gpt-6-luna", tokenName: "one", costUsd: 0.00004,
|
|
421
422
|
usage: expect.objectContaining({ input_tokens: 100, output_tokens: 20 }),
|
|
422
423
|
}),
|
|
423
424
|
});
|
|
@@ -286,7 +286,7 @@ class QgridFrameClass extends BaseFrameClass {
|
|
|
286
286
|
try {
|
|
287
287
|
result = await QgridDispatcher.query(resolvedArgs, disconnect.signal);
|
|
288
288
|
} catch (e) {
|
|
289
|
-
const completedDriver = completedDriverFromImageFailure(e);
|
|
289
|
+
const completedDriver = completedDriverFromImageFailure(e, resolvedArgs.serviceTier);
|
|
290
290
|
const completedStep = completedDriver
|
|
291
291
|
? ([{ stepIndex, result: completedDriver }] as const)
|
|
292
292
|
: ([] as const);
|
|
@@ -143,6 +143,13 @@
|
|
|
143
143
|
"nullable": true,
|
|
144
144
|
"desc": "이미지 비용 계산 방식"
|
|
145
145
|
},
|
|
146
|
+
{
|
|
147
|
+
"name": "service_tier",
|
|
148
|
+
"type": "string",
|
|
149
|
+
"length": 20,
|
|
150
|
+
"nullable": true,
|
|
151
|
+
"desc": "Requested OpenAI service tier"
|
|
152
|
+
},
|
|
146
153
|
{
|
|
147
154
|
"name": "effort",
|
|
148
155
|
"type": "string",
|
|
@@ -288,6 +295,7 @@
|
|
|
288
295
|
"image_cost_usd",
|
|
289
296
|
"image_cost_method",
|
|
290
297
|
"effort",
|
|
298
|
+
"service_tier",
|
|
291
299
|
"history",
|
|
292
300
|
"tools",
|
|
293
301
|
"status",
|
|
@@ -318,6 +326,7 @@
|
|
|
318
326
|
"image_cost_usd",
|
|
319
327
|
"image_cost_method",
|
|
320
328
|
"effort",
|
|
329
|
+
"service_tier",
|
|
321
330
|
"status",
|
|
322
331
|
"response_json_ok",
|
|
323
332
|
"tool_call_count",
|
|
@@ -481,6 +481,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
481
481
|
system_prompt?: string | null;
|
|
482
482
|
requested_model_name?: string | null;
|
|
483
483
|
effort?: string | null;
|
|
484
|
+
service_tier?: string | null;
|
|
484
485
|
project_name?: string | null;
|
|
485
486
|
history?: unknown;
|
|
486
487
|
tools?: ToolDefinitions;
|
|
@@ -496,6 +497,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
496
497
|
requested_model_name: params.requested_model_name ?? null,
|
|
497
498
|
model_name: null,
|
|
498
499
|
effort: params.effort ?? null,
|
|
500
|
+
service_tier: params.service_tier ?? null,
|
|
499
501
|
project_name: params.project_name ?? null,
|
|
500
502
|
status: "running",
|
|
501
503
|
response: "",
|
|
@@ -546,6 +548,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
546
548
|
duration_ms?: number;
|
|
547
549
|
requested_model_name?: string | null;
|
|
548
550
|
model_name?: string | null;
|
|
551
|
+
service_tier?: string | null;
|
|
549
552
|
fallback_count?: number | null;
|
|
550
553
|
cost_usd?: number | null;
|
|
551
554
|
cost_source?: string | null;
|
|
@@ -574,6 +577,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
574
577
|
"duration_ms",
|
|
575
578
|
"requested_model_name",
|
|
576
579
|
"model_name",
|
|
580
|
+
"service_tier",
|
|
577
581
|
"fallback_count",
|
|
578
582
|
"cost_usd",
|
|
579
583
|
"cost_source",
|
|
@@ -43,6 +43,7 @@ export const requestLogSubsetQueries = {
|
|
|
43
43
|
image_cost_usd: "request_logs.image_cost_usd",
|
|
44
44
|
image_cost_method: "request_logs.image_cost_method",
|
|
45
45
|
effort: "request_logs.effort",
|
|
46
|
+
service_tier: "request_logs.service_tier",
|
|
46
47
|
history: "request_logs.history",
|
|
47
48
|
tools: "request_logs.tools",
|
|
48
49
|
status: "request_logs.status",
|
|
@@ -75,6 +76,7 @@ export const requestLogSubsetQueries = {
|
|
|
75
76
|
image_cost_usd: "request_logs.image_cost_usd",
|
|
76
77
|
image_cost_method: "request_logs.image_cost_method",
|
|
77
78
|
effort: "request_logs.effort",
|
|
79
|
+
service_tier: "request_logs.service_tier",
|
|
78
80
|
status: "request_logs.status",
|
|
79
81
|
response_json_ok: "request_logs.response_json_ok",
|
|
80
82
|
tool_call_count: "request_logs.tool_call_count",
|
|
@@ -167,6 +167,7 @@ export const RequestLogBaseSchema = z.object({
|
|
|
167
167
|
cost_source: z.string().max(20).nullable(),
|
|
168
168
|
image_cost_usd: z.int().nullable(),
|
|
169
169
|
image_cost_method: z.string().max(100).nullable(),
|
|
170
|
+
service_tier: z.string().max(20).nullable(),
|
|
170
171
|
effort: z.string().max(10).nullable(),
|
|
171
172
|
history: HistoryItems.nullable(),
|
|
172
173
|
tools: ToolDefinitions.nullable(),
|
|
@@ -201,6 +202,7 @@ export type RequestLogBaseSchema = z.infer<typeof RequestLogBaseSchema> & {
|
|
|
201
202
|
"cost_source",
|
|
202
203
|
"image_cost_usd",
|
|
203
204
|
"image_cost_method",
|
|
205
|
+
"service_tier",
|
|
204
206
|
"effort",
|
|
205
207
|
"history",
|
|
206
208
|
"tools",
|
|
@@ -405,6 +407,7 @@ export const RequestLogSubsetA = z.object({
|
|
|
405
407
|
image_cost_usd: z.int().nullable(),
|
|
406
408
|
image_cost_method: z.string().max(100).nullable(),
|
|
407
409
|
effort: z.string().max(10).nullable(),
|
|
410
|
+
service_tier: z.string().max(20).nullable(),
|
|
408
411
|
history: HistoryItems.nullable(),
|
|
409
412
|
tools: ToolDefinitions.nullable(),
|
|
410
413
|
status: RequestLogStatus,
|
|
@@ -436,6 +439,7 @@ export const RequestLogSubsetP = z.object({
|
|
|
436
439
|
image_cost_usd: z.int().nullable(),
|
|
437
440
|
image_cost_method: z.string().max(100).nullable(),
|
|
438
441
|
effort: z.string().max(10).nullable(),
|
|
442
|
+
service_tier: z.string().max(20).nullable(),
|
|
439
443
|
status: RequestLogStatus,
|
|
440
444
|
response_json_ok: z.boolean().nullable(),
|
|
441
445
|
tool_call_count: z.int(),
|
|
@@ -232,6 +232,7 @@ const entityLabels = {
|
|
|
232
232
|
"entity.RequestLog.cost_source": "비용 출처(provider/pricing_table/mixed)",
|
|
233
233
|
"entity.RequestLog.image_cost_usd": "이미지 생성 비용",
|
|
234
234
|
"entity.RequestLog.image_cost_method": "이미지 비용 계산 방식",
|
|
235
|
+
"entity.RequestLog.service_tier": "Requested OpenAI service tier",
|
|
235
236
|
"entity.RequestLog.effort": "effort level",
|
|
236
237
|
"entity.RequestLog.history": "inject_items 히스토리",
|
|
237
238
|
"entity.RequestLog.tools": "요청에 장착된 tool 정의 목록",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Knex } from "knex";
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.alterTable("request_logs", (table) => {
|
|
5
|
+
// add
|
|
6
|
+
table.string("service_tier", 20).nullable();
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function down(knex: Knex): Promise<void> {
|
|
11
|
+
await knex.schema.alterTable("request_logs", (table) => {
|
|
12
|
+
// rollback - add
|
|
13
|
+
table.dropColumns("service_tier");
|
|
14
|
+
});
|
|
15
|
+
}
|
|
@@ -3,6 +3,34 @@ import { describe, expect, it } from "vitest";
|
|
|
3
3
|
import { calculateCostUsd, getModelCosts } from "./model-cost";
|
|
4
4
|
|
|
5
5
|
describe("calculateCostUsd", () => {
|
|
6
|
+
it.each([
|
|
7
|
+
["gpt-6-astra", 2.6],
|
|
8
|
+
["gpt-6.1-sol", 0.5],
|
|
9
|
+
["gpt-6-sol", 0.52],
|
|
10
|
+
["gpt-6-luna", 0.026],
|
|
11
|
+
["gpt-5.6-sol", 1.04],
|
|
12
|
+
["gpt-5.6-terra", 0.56],
|
|
13
|
+
["gpt-5.6-luna", 0.056],
|
|
14
|
+
])("prices %s fast input, cached input, cache writes and output", (model, expected) => {
|
|
15
|
+
expect(calculateCostUsd(`openai/${model}`, {
|
|
16
|
+
inputTokens: 160_000, cachedInputTokens: 100_000,
|
|
17
|
+
cacheCreationInputTokens: 40_000, outputTokens: 10_000,
|
|
18
|
+
}, "fast")).toBeCloseTo(expected, 10);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("combines Fast API rates with long-context rates, not subscription usage multipliers", () => {
|
|
22
|
+
expect(calculateCostUsd("openai/gpt-6.1-sol", {
|
|
23
|
+
inputTokens: 300_000, cachedInputTokens: 200_000, outputTokens: 10_000,
|
|
24
|
+
}, "fast")).toBeCloseTo(1.18, 10);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("keeps standard pricing for omitted/flex tiers and Anthropic", () => {
|
|
28
|
+
const usage = { inputTokens: 1_000, outputTokens: 1_000 };
|
|
29
|
+
expect(calculateCostUsd("gpt-6.1-sol", usage)).toBeCloseTo(0.012, 10);
|
|
30
|
+
expect(calculateCostUsd("gpt-6.1-sol", usage, "flex")).toBeCloseTo(0.012, 10);
|
|
31
|
+
expect(calculateCostUsd("claude-sonnet-5-5", usage, "fast")).toBeCloseTo(0.012, 10);
|
|
32
|
+
});
|
|
33
|
+
|
|
6
34
|
it.each([
|
|
7
35
|
[272_000, 2.77],
|
|
8
36
|
[272_001, 5.51502],
|
|
@@ -237,6 +237,19 @@ export function getModelCosts(model: string): ModelCosts {
|
|
|
237
237
|
return OPENAI_COSTS[normalizedModel] ?? ANTHROPIC_COSTS[normalizedModel] ?? DEFAULT_COSTS;
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
// Verified Fast API rates for the currently served Codex models (2026-10-16).
|
|
241
|
+
// Applies to all token categories and long context; not the 2.5x subscription quota multiplier.
|
|
242
|
+
// https://developers.openai.com/api/docs/pricing
|
|
243
|
+
const OPENAI_FAST_MULTIPLIERS: Record<string, number> = {
|
|
244
|
+
"gpt-6-astra": 2,
|
|
245
|
+
"gpt-6.1-sol": 2,
|
|
246
|
+
"gpt-6-sol": 2,
|
|
247
|
+
"gpt-6-luna": 2,
|
|
248
|
+
"gpt-5.6-sol": 2,
|
|
249
|
+
"gpt-5.6-terra": 2,
|
|
250
|
+
"gpt-5.6-luna": 2,
|
|
251
|
+
};
|
|
252
|
+
|
|
240
253
|
export function calculateCostUsd(
|
|
241
254
|
model: string,
|
|
242
255
|
usage: {
|
|
@@ -247,6 +260,7 @@ export function calculateCostUsd(
|
|
|
247
260
|
cacheCreationInputTokens5m?: number;
|
|
248
261
|
cacheCreationInputTokens1h?: number;
|
|
249
262
|
},
|
|
263
|
+
serviceTier?: string,
|
|
250
264
|
): number {
|
|
251
265
|
const costs = getModelCosts(model);
|
|
252
266
|
const cachedInput = usage.cachedInputTokens ?? 0;
|
|
@@ -281,12 +295,15 @@ export function calculateCostUsd(
|
|
|
281
295
|
(isLongContext ? lc.inputMultiplier : 1);
|
|
282
296
|
const outputRate = costs.outputTokens * (isLongContext ? lc.outputMultiplier : 1);
|
|
283
297
|
|
|
284
|
-
|
|
298
|
+
const standardCost =
|
|
285
299
|
(nonCachedInput / 1_000_000) * inputRate +
|
|
286
300
|
(usage.outputTokens / 1_000_000) * outputRate +
|
|
287
301
|
(cachedInput / 1_000_000) * cachedRate +
|
|
288
302
|
(unclassifiedCacheCreationInput / 1_000_000) * cacheCreationFallbackRate +
|
|
289
303
|
(classifiedCacheCreationInput5m / 1_000_000) * cacheCreation5mRate +
|
|
290
|
-
(classifiedCacheCreationInput1h / 1_000_000) * cacheCreation1hRate
|
|
304
|
+
(classifiedCacheCreationInput1h / 1_000_000) * cacheCreation1hRate;
|
|
305
|
+
const normalizedModel = model.split("/").pop() ?? model;
|
|
306
|
+
return (
|
|
307
|
+
standardCost * (serviceTier === "fast" ? (OPENAI_FAST_MULTIPLIERS[normalizedModel] ?? 1) : 1)
|
|
291
308
|
);
|
|
292
309
|
}
|