@cartanova/qgrid-cli 2.9.2 → 2.9.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 (35) hide show
  1. package/bundle/dist/application/qgrid/qgrid.frame.js +4 -3
  2. package/bundle/dist/application/qgrid/token-death.js +6 -22
  3. package/bundle/dist/application/qgrid/token-subscriber.js +2 -1
  4. package/bundle/dist/application/token/token.model.js +22 -17
  5. package/bundle/dist/utils/providers/common/model-cost.js +21 -13
  6. package/bundle/src/application/qgrid/qgrid.frame.test.ts +20 -0
  7. package/bundle/src/application/qgrid/qgrid.frame.ts +3 -2
  8. package/bundle/src/application/qgrid/token-death.test.ts +11 -10
  9. package/bundle/src/application/qgrid/token-death.ts +9 -21
  10. package/bundle/src/application/qgrid/token-subscriber.test.ts +5 -1
  11. package/bundle/src/application/qgrid/token-subscriber.ts +1 -0
  12. package/bundle/src/application/token/token.model.test.ts +24 -5
  13. package/bundle/src/application/token/token.model.ts +30 -23
  14. package/bundle/src/utils/providers/common/effort.test.ts +8 -0
  15. package/bundle/src/utils/providers/common/model-cost.test.ts +25 -12
  16. package/bundle/src/utils/providers/common/model-cost.ts +28 -14
  17. package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +1 -0
  18. package/bundle/web-dist/client/assets/{index-DH1n8kgG.js → index-fogJvajr.js} +3 -3
  19. package/bundle/web-dist/client/assets/{logs-D36O-NET.js → logs-CsY2cqvt.js} +1 -1
  20. package/bundle/web-dist/client/assets/{monit-DhZAaz9K.js → monit-ChgaLEcD.js} +1 -1
  21. package/bundle/web-dist/client/assets/{routes-C7q1CsSv.js → routes-BvyiTnOZ.js} +2 -2
  22. package/bundle/web-dist/client/assets/{settings-M_jfoIAe.js → settings-ZR2J9rWb.js} +1 -1
  23. package/bundle/web-dist/client/assets/{show-CORjMGQs.js → show-CjwO4-So.js} +1 -1
  24. package/bundle/web-dist/client/assets/{tokens-C7-j4VXD.js → tokens-Bx-hG1gm.js} +1 -1
  25. package/bundle/web-dist/client/assets/{use-oauth-login-flow-Fi62xbBc.js → use-oauth-login-flow-Bqax_icS.js} +1 -1
  26. package/bundle/web-dist/client/index.html +1 -1
  27. package/bundle/web-dist/server/assets/{routes-CxMHXfdH.js → routes-B408iqh1.js} +29 -14
  28. package/bundle/web-dist/server/entry-server.generated.js +3 -2
  29. package/package.json +1 -1
  30. package/skills/qgrid/SKILL.md +1 -0
  31. package/skills/qgrid/references/ai-sdk-provider-contract.md +1 -1
  32. package/skills/qgrid/references/openai-codex-runtime.md +71 -0
  33. package/skills/qgrid/references/provider-runtime-differences.md +1 -1
  34. package/skills/qgrid/references/sonamu-api-web-flow.md +1 -1
  35. package/skills/qgrid/references/token-auth-quota-lifecycle.md +3 -2
@@ -198,9 +198,8 @@ var TokenModelClass = class extends BaseModelClass {
198
198
  }]);
199
199
  }
200
200
  /**
201
- * 인증 사망을 한 번만 기록하고, 다른 활성 토큰이 있으면 라우팅에서도 제외한다.
202
- * 마지막 활성 토큰은 systemic 장애 안전판 때문에 active 상태를 유지하되 재로그인
203
- * 필요 상태는 기록한다. `marked`가 공유 DB 인스턴스들의 알림 발송 게이트다.
201
+ * Record confirmed expiry and remove the token from routing atomically.
202
+ * The last active token is also deactivated; its notification is urgent.
204
203
  */
205
204
  async markReauthRequired(id, expectedCredentials) {
206
205
  return this.getPuri("w").transaction(async (trx) => {
@@ -211,38 +210,44 @@ var TokenModelClass = class extends BaseModelClass {
211
210
  }).where("id", id).forUpdate().first();
212
211
  if (!token || token.reauth_required) return {
213
212
  marked: false,
214
- keptAsLastActive: false,
213
+ wasLastActive: false,
215
214
  staleCredentials: false
216
215
  };
217
216
  if (!isDeepStrictEqual(token.credentials, expectedCredentials)) return {
218
217
  marked: false,
219
- keptAsLastActive: false,
218
+ wasLastActive: false,
220
219
  staleCredentials: true
221
220
  };
222
221
  await trx.knex.raw("SELECT pg_advisory_xact_lock(?, hashtext(?))", [TOKEN_AUTH_DEATH_LOCK_CLASS_ID, token.provider]);
223
- const marked = (await trx.knex.raw(`UPDATE tokens
222
+ const marked = (await trx.knex.raw(`WITH previous AS (
223
+ SELECT active AND NOT EXISTS (
224
+ SELECT 1 FROM tokens peer
225
+ WHERE peer.provider = tokens.provider AND peer.active
226
+ AND NOT peer.reauth_required AND peer.id <> tokens.id
227
+ ) AS was_last_active FROM tokens WHERE id = ?
228
+ )
229
+ UPDATE tokens
224
230
  SET reauth_required = true,
225
- active = CASE
226
- WHEN active AND (SELECT count(*) FROM tokens peer
227
- WHERE peer.provider = tokens.provider AND peer.active) > 1
228
- THEN false
229
- ELSE active
230
- END
231
+ active = false
231
232
  WHERE id = ? AND reauth_required = false
232
- RETURNING active`, [id])).rows[0];
233
+ RETURNING (SELECT was_last_active FROM previous) AS was_last_active`, [id, id])).rows[0];
233
234
  if (!marked) return {
234
235
  marked: false,
235
- keptAsLastActive: false,
236
+ wasLastActive: false,
236
237
  staleCredentials: false
237
238
  };
238
- if (marked.active) logger.error(`refusing to auto-deactivate token ${id}: last active provider token — systemic refresh failure suspected, keeping the pool non-empty`);
239
+ if (marked.was_last_active) logger.error(`deactivated expired token ${id}: no usable provider tokens remain`);
239
240
  return {
240
241
  marked: true,
241
- keptAsLastActive: marked.active,
242
+ wasLastActive: marked.was_last_active,
242
243
  staleCredentials: false
243
244
  };
244
245
  });
245
246
  }
247
+ /** Repair rows retained by the former last-active exception before pool reconciliation. */
248
+ async deactivateExpiredTokens() {
249
+ await this.getPuri("w").table("tokens").where("reauth_required", true).where("active", true).update({ active: false });
250
+ }
246
251
  async reorder(ids) {
247
252
  await this.getPuri("w").transaction(async (trx) => {
248
253
  for (let i = 0; i < ids.length; i++) await trx.table("tokens").where("id", ids[i]).update({ ord: i });
@@ -298,4 +303,4 @@ const TokenModel = new TokenModelClass();
298
303
  //#endregion
299
304
  export { TokenModel };
300
305
 
301
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4ubW9kZWwuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwcGxpY2F0aW9uL3Rva2VuL3Rva2VuLm1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGlzRGVlcFN0cmljdEVxdWFsIH0gZnJvbSBcIm5vZGU6dXRpbFwiO1xuXG5pbXBvcnQgeyBnZXRMb2dnZXIgfSBmcm9tIFwiQGxvZ3RhcGUvbG9ndGFwZVwiO1xuaW1wb3J0IHtcbiAgYXBpLFxuICBhc0FycmF5LFxuICBCYWRSZXF1ZXN0RXhjZXB0aW9uLFxuICBCYXNlTW9kZWxDbGFzcyxcbiAgZXhoYXVzdGl2ZSxcbiAgdHlwZSBMaXN0UmVzdWx0LFxuICBOb3RGb3VuZEV4Y2VwdGlvbixcbn0gZnJvbSBcInNvbmFtdVwiO1xuXG5pbXBvcnQgeyBTRCB9IGZyb20gXCIuLi8uLi9pMThuL3NkLmdlbmVyYXRlZFwiO1xuaW1wb3J0IHsgdHlwZSBUb2tlblN1YnNldEtleSwgdHlwZSBUb2tlblN1YnNldE1hcHBpbmcgfSBmcm9tIFwiLi4vc29uYW11LmdlbmVyYXRlZFwiO1xuaW1wb3J0IHsgdG9rZW5Mb2FkZXJRdWVyaWVzLCB0b2tlblN1YnNldFF1ZXJpZXMgfSBmcm9tIFwiLi4vc29uYW11LmdlbmVyYXRlZC5zc29cIjtcbmltcG9ydCB7IHR5cGUgVG9rZW5DcmVkZW50aWFscywgdHlwZSBUb2tlbkxpc3RQYXJhbXMsIHR5cGUgVG9rZW5TYXZlUGFyYW1zIH0gZnJvbSBcIi4vdG9rZW4udHlwZXNcIjtcblxuY29uc3QgbG9nZ2VyID0gZ2V0TG9nZ2VyKFtcInFncmlkXCIsIFwidG9rZW5cIl0pO1xuXG5jb25zdCBERUZBVUxUX1FVT1RBX1RIUkVTSE9MRCA9IDgwO1xuY29uc3QgREVGQVVMVF9XRUlHSFQgPSAxO1xuY29uc3QgVE9LRU5fQVVUSF9ERUFUSF9MT0NLX0NMQVNTX0lEID0gNzE5O1xuXG5leHBvcnQgdHlwZSBUb2tlblVwZGF0ZUZpZWxkcyA9IHtcbiAgbmFtZT86IHN0cmluZztcbiAgcXVvdGFfdGhyZXNob2xkPzogbnVtYmVyIHwgbnVsbDtcbiAgd2VpZ2h0PzogbnVtYmVyO1xuICBrZWVwYWxpdmVfZW5hYmxlZD86IGJvb2xlYW47XG59O1xuXG5mdW5jdGlvbiBhcHBseUNyZWF0ZURlZmF1bHRzKHNwOiBUb2tlblNhdmVQYXJhbXMpOiBUb2tlblNhdmVQYXJhbXMge1xuICBpZiAoc3AuaWQgIT09IHVuZGVmaW5lZCkgcmV0dXJuIHNwO1xuICByZXR1cm4ge1xuICAgIC4uLnNwLFxuICAgIC4uLihzcC5xdW90YV90aHJlc2hvbGQgPT09IHVuZGVmaW5lZCA/IHsgcXVvdGFfdGhyZXNob2xkOiBERUZBVUxUX1FVT1RBX1RIUkVTSE9MRCB9IDoge30pLFxuICAgIC4uLihzcC53ZWlnaHQgPT09IHVuZGVmaW5lZCA/IHsgd2VpZ2h0OiBERUZBVUxUX1dFSUdIVCB9IDoge30pLFxuICB9O1xufVxuXG5jbGFzcyBUb2tlbk1vZGVsQ2xhc3MgZXh0ZW5kcyBCYXNlTW9kZWxDbGFzczxcbiAgVG9rZW5TdWJzZXRLZXksXG4gIFRva2VuU3Vic2V0TWFwcGluZyxcbiAgdHlwZW9mIHRva2VuU3Vic2V0UXVlcmllcyxcbiAgdHlwZW9mIHRva2VuTG9hZGVyUXVlcmllc1xuPiB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKFwiVG9rZW5cIiwgdG9rZW5TdWJzZXRRdWVyaWVzLCB0b2tlbkxvYWRlclF1ZXJpZXMpO1xuICB9XG5cbiAgQGFwaSh7IGh0dHBNZXRob2Q6IFwiR0VUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stcXVlcnlcIl0sIHJlc291cmNlTmFtZTogXCJUb2tlblwiIH0pXG4gIGFzeW5jIGZpbmRCeUlkPFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleT4oc3Vic2V0OiBULCBpZDogbnVtYmVyKTogUHJvbWlzZTxUb2tlblN1YnNldE1hcHBpbmdbVF0+IHtcbiAgICBjb25zdCB7IHJvd3MgfSA9IGF3YWl0IHRoaXMuZmluZE1hbnkoc3Vic2V0LCB7IGlkLCBudW06IDEsIHBhZ2U6IDEgfSk7XG4gICAgaWYgKCFyb3dzWzBdKSB7XG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oU0QoXCJlcnJvci5lbnRpdHlOb3RGb3VuZFwiKShcIlRva2VuXCIsIGlkKSk7XG4gICAgfVxuICAgIHJldHVybiByb3dzWzBdO1xuICB9XG5cbiAgYXN5bmMgZmluZE9uZTxUIGV4dGVuZHMgVG9rZW5TdWJzZXRLZXk+KFxuICAgIHN1YnNldDogVCxcbiAgICBsaXN0UGFyYW1zOiBUb2tlbkxpc3RQYXJhbXMsXG4gICk6IFByb21pc2U8VG9rZW5TdWJzZXRNYXBwaW5nW1RdIHwgbnVsbD4ge1xuICAgIGNvbnN0IHsgcm93cyB9ID0gYXdhaXQgdGhpcy5maW5kTWFueShzdWJzZXQsIHsgLi4ubGlzdFBhcmFtcywgbnVtOiAxLCBwYWdlOiAxIH0pO1xuICAgIHJldHVybiByb3dzWzBdID8/IG51bGw7XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSwgcmVzb3VyY2VOYW1lOiBcIlRva2Vuc1wiIH0pXG4gIGFzeW5jIGZpbmRNYW55PFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleSwgTFAgZXh0ZW5kcyBUb2tlbkxpc3RQYXJhbXM+KFxuICAgIHN1YnNldDogVCxcbiAgICByYXdQYXJhbXM/OiBMUCxcbiAgKTogUHJvbWlzZTxMaXN0UmVzdWx0PExQLCBUb2tlblN1YnNldE1hcHBpbmdbVF0+PiB7XG4gICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgbnVtOiAyNCxcbiAgICAgIHBhZ2U6IDEsXG4gICAgICBzZWFyY2g6IFwiaWRcIiBhcyBjb25zdCxcbiAgICAgIG9yZGVyQnk6IFwib3JkLWFzY1wiIGFzIGNvbnN0LFxuICAgICAgLi4ucmF3UGFyYW1zLFxuICAgIH0gc2F0aXNmaWVzIFRva2VuTGlzdFBhcmFtcztcblxuICAgIGNvbnN0IHsgcWIsIG9uU3Vic2V0OiBfIH0gPSB0aGlzLmdldFN1YnNldFF1ZXJpZXMoc3Vic2V0KTtcblxuICAgIGlmIChwYXJhbXMuaWQpIHtcbiAgICAgIHFiLndoZXJlSW4oXCJ0b2tlbnMuaWRcIiwgYXNBcnJheShwYXJhbXMuaWQpKTtcbiAgICB9XG5cbiAgICBpZiAocGFyYW1zLnNlYXJjaCAmJiBwYXJhbXMua2V5d29yZCAmJiBwYXJhbXMua2V5d29yZC5sZW5ndGggPiAwKSB7XG4gICAgICBpZiAocGFyYW1zLnNlYXJjaCA9PT0gXCJpZFwiKSB7XG4gICAgICAgIHFiLndoZXJlKFwidG9rZW5zLmlkXCIsIE51bWJlcihwYXJhbXMua2V5d29yZCkpO1xuICAgICAgfSBlbHNlIGlmIChwYXJhbXMuc2VhcmNoID09PSBcIm5hbWVcIikge1xuICAgICAgICBxYi53aGVyZShcInRva2Vucy5uYW1lXCIsIFwibGlrZVwiLCBgJSR7cGFyYW1zLmtleXdvcmR9JWApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oU0QoXCJlcnJvci51bmtub3duU2VhcmNoRmllbGRcIikocGFyYW1zLnNlYXJjaCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChwYXJhbXMub3JkZXJCeSkge1xuICAgICAgaWYgKHBhcmFtcy5vcmRlckJ5ID09PSBcImlkLWRlc2NcIikge1xuICAgICAgICBxYi5vcmRlckJ5KFwidG9rZW5zLmlkXCIsIFwiZGVzY1wiKTtcbiAgICAgIH0gZWxzZSBpZiAocGFyYW1zLm9yZGVyQnkgPT09IFwib3JkLWFzY1wiKSB7XG4gICAgICAgIHFiLm9yZGVyQnkoXCJ0b2tlbnMub3JkXCIsIFwiYXNjXCIpO1xuICAgICAgICBxYi5vcmRlckJ5KFwidG9rZW5zLmlkXCIsIFwiYXNjXCIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhoYXVzdGl2ZShwYXJhbXMub3JkZXJCeSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZW5oYW5jZXJzID0gdGhpcy5jcmVhdGVFbmhhbmNlcnMoe1xuICAgICAgQTogKHJvdykgPT4gKHsgLi4ucm93IH0pLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuZXhlY3V0ZVN1YnNldFF1ZXJ5KHsgc3Vic2V0LCBxYiwgcGFyYW1zLCBlbmhhbmNlcnMsIGRlYnVnOiBmYWxzZSB9KTtcbiAgfVxuXG4gIGFzeW5jIGZpbmRCeUFjY291bnRJZGVudGlmaWVyPFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleT4oXG4gICAgc3Vic2V0OiBULFxuICAgIHByb3ZpZGVyOiBzdHJpbmcsXG4gICAgYWNjb3VudElkOiBzdHJpbmcsXG4gICk6IFByb21pc2U8VG9rZW5TdWJzZXRNYXBwaW5nW1RdW10+IHtcbiAgICBjb25zdCB7IHFiIH0gPSB0aGlzLmdldFN1YnNldFF1ZXJpZXMoc3Vic2V0KTtcbiAgICBxYi53aGVyZShcInRva2Vucy5wcm92aWRlclwiLCBwcm92aWRlcik7XG4gICAgY29uc3QganNvbktleSA9IHByb3ZpZGVyID09PSBcImFudGhyb3BpY1wiID8gXCJhY2NvdW50VXVpZFwiIDogXCJhY2NvdW50SWRcIjtcbiAgICBxYi53aGVyZVJhdyhgdG9rZW5zLmNyZWRlbnRpYWxzLT4+JyR7anNvbktleX0nID0gP2AsIFthY2NvdW50SWRdKTtcbiAgICBjb25zdCBlbmhhbmNlcnMgPSB0aGlzLmNyZWF0ZUVuaGFuY2Vycyh7IEE6IChyb3cpID0+ICh7IC4uLnJvdyB9KSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmV4ZWN1dGVTdWJzZXRRdWVyeSh7XG4gICAgICBzdWJzZXQsXG4gICAgICBxYixcbiAgICAgIHBhcmFtczogeyBudW06IDEwMCwgcGFnZTogMSB9LFxuICAgICAgZW5oYW5jZXJzLFxuICAgICAgZGVidWc6IGZhbHNlLFxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQucm93cztcbiAgfVxuXG4gIGFzeW5jIGZpbmRBY3RpdmVCeVByb3ZpZGVyPFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleT4oXG4gICAgc3Vic2V0OiBULFxuICAgIHByb3ZpZGVyOiBzdHJpbmcsXG4gICk6IFByb21pc2U8VG9rZW5TdWJzZXRNYXBwaW5nW1RdW10+IHtcbiAgICBjb25zdCB7IHFiIH0gPSB0aGlzLmdldFN1YnNldFF1ZXJpZXMoc3Vic2V0KTtcbiAgICBxYi53aGVyZShcInRva2Vucy5hY3RpdmVcIiwgdHJ1ZSk7XG4gICAgcWIud2hlcmUoXCJ0b2tlbnMucHJvdmlkZXJcIiwgcHJvdmlkZXIpO1xuICAgIGNvbnN0IGVuaGFuY2VycyA9IHRoaXMuY3JlYXRlRW5oYW5jZXJzKHsgQTogKHJvdykgPT4gKHsgLi4ucm93IH0pIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuZXhlY3V0ZVN1YnNldFF1ZXJ5KHtcbiAgICAgIHN1YnNldCxcbiAgICAgIHFiLFxuICAgICAgcGFyYW1zOiB7IG51bTogMTAwLCBwYWdlOiAxIH0sXG4gICAgICBlbmhhbmNlcnMsXG4gICAgICBkZWJ1ZzogZmFsc2UsXG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdC5yb3dzO1xuICB9XG5cbiAgYXN5bmMgZmluZEFjdGl2ZUJ5UHJvdmlkZXJBbmROYW1lPFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleT4oXG4gICAgc3Vic2V0OiBULFxuICAgIHByb3ZpZGVyOiBzdHJpbmcsXG4gICAgbmFtZTogc3RyaW5nLFxuICApOiBQcm9taXNlPFRva2VuU3Vic2V0TWFwcGluZ1tUXSB8IHVuZGVmaW5lZD4ge1xuICAgIGNvbnN0IHsgcWIgfSA9IHRoaXMuZ2V0U3Vic2V0UXVlcmllcyhzdWJzZXQpO1xuICAgIHFiLndoZXJlKFwidG9rZW5zLmFjdGl2ZVwiLCB0cnVlKTtcbiAgICBxYi53aGVyZShcInRva2Vucy5wcm92aWRlclwiLCBwcm92aWRlcik7XG4gICAgcWIud2hlcmUoXCJ0b2tlbnMubmFtZVwiLCBuYW1lKTtcbiAgICBjb25zdCBlbmhhbmNlcnMgPSB0aGlzLmNyZWF0ZUVuaGFuY2Vycyh7IEE6IChyb3cpID0+ICh7IC4uLnJvdyB9KSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmV4ZWN1dGVTdWJzZXRRdWVyeSh7XG4gICAgICBzdWJzZXQsXG4gICAgICBxYixcbiAgICAgIHBhcmFtczogeyBudW06IDEsIHBhZ2U6IDEgfSxcbiAgICAgIGVuaGFuY2VycyxcbiAgICAgIGRlYnVnOiBmYWxzZSxcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0LnJvd3NbMF07XG4gIH1cblxuICAvKiog7Iuk7KCcIOyduOymnSDrp4zro4zqsIAg7ZmV7J2464+8IOyerOuhnOq3uOyduOydtCDtlYTsmpTtlZwg7Yag7YGw65OkLiDsiJjrj5kg67mE7Zmc7ISx7ZmU64qUIOygnOyZuO2VnOuLpC4gKi9cbiAgYXN5bmMgZmluZFJlYXV0aFJlcXVpcmVkPFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleT4oc3Vic2V0OiBUKTogUHJvbWlzZTxUb2tlblN1YnNldE1hcHBpbmdbVF1bXT4ge1xuICAgIGNvbnN0IHsgcWIgfSA9IHRoaXMuZ2V0U3Vic2V0UXVlcmllcyhzdWJzZXQpO1xuICAgIHFiLndoZXJlKFwidG9rZW5zLnJlYXV0aF9yZXF1aXJlZFwiLCB0cnVlKTtcbiAgICBxYi5vcmRlckJ5KFwidG9rZW5zLm5hbWVcIiwgXCJhc2NcIik7XG4gICAgY29uc3QgZW5oYW5jZXJzID0gdGhpcy5jcmVhdGVFbmhhbmNlcnMoeyBBOiAocm93KSA9PiAoeyAuLi5yb3cgfSkgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5leGVjdXRlU3Vic2V0UXVlcnkoe1xuICAgICAgc3Vic2V0LFxuICAgICAgcWIsXG4gICAgICBwYXJhbXM6IHsgbnVtOiAxMDAsIHBhZ2U6IDEgfSxcbiAgICAgIGVuaGFuY2VycyxcbiAgICAgIGRlYnVnOiBmYWxzZSxcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0LnJvd3M7XG4gIH1cblxuICBhc3luYyBmaW5kQWN0aXZlPFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleT4oc3Vic2V0OiBUKTogUHJvbWlzZTxUb2tlblN1YnNldE1hcHBpbmdbVF1bXT4ge1xuICAgIGNvbnN0IHsgcWIgfSA9IHRoaXMuZ2V0U3Vic2V0UXVlcmllcyhzdWJzZXQpO1xuICAgIHFiLndoZXJlKFwidG9rZW5zLmFjdGl2ZVwiLCB0cnVlKTtcbiAgICBjb25zdCBlbmhhbmNlcnMgPSB0aGlzLmNyZWF0ZUVuaGFuY2Vycyh7IEE6IChyb3cpID0+ICh7IC4uLnJvdyB9KSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmV4ZWN1dGVTdWJzZXRRdWVyeSh7XG4gICAgICBzdWJzZXQsXG4gICAgICBxYixcbiAgICAgIHBhcmFtczogeyBudW06IDEwMCwgcGFnZTogMSB9LFxuICAgICAgZW5oYW5jZXJzLFxuICAgICAgZGVidWc6IGZhbHNlLFxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQucm93cztcbiAgfVxuXG4gIGFzeW5jIHNhdmUoc3BhOiBUb2tlblNhdmVQYXJhbXNbXSk6IFByb21pc2U8bnVtYmVyW10+IHtcbiAgICBjb25zdCB3ZGIgPSB0aGlzLmdldFB1cmkoXCJ3XCIpO1xuICAgIHNwYS5mb3JFYWNoKChzcCkgPT4ge1xuICAgICAgd2RiLnViUmVnaXN0ZXIoXCJ0b2tlbnNcIiwgYXBwbHlDcmVhdGVEZWZhdWx0cyhzcCkpO1xuICAgIH0pO1xuICAgIHJldHVybiB3ZGIudHJhbnNhY3Rpb24oYXN5bmMgKHRyeCkgPT4ge1xuICAgICAgcmV0dXJuIHRyeC51YlVwc2VydChcInRva2Vuc1wiKTtcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIHVwZGF0ZUZpZWxkcyhpZDogbnVtYmVyLCBmaWVsZHM6IFRva2VuVXBkYXRlRmllbGRzKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCB3ZGIgPSB0aGlzLmdldFB1cmkoXCJ3XCIpO1xuICAgIHJldHVybiB3ZGIudHJhbnNhY3Rpb24oKHRyeCkgPT4gdHJ4LnRhYmxlKFwidG9rZW5zXCIpLndoZXJlKFwiaWRcIiwgaWQpLnVwZGF0ZShmaWVsZHMpKTtcbiAgfVxuXG4gIGFzeW5jIHRvZ2dsZUFjdGl2ZShpZDogbnVtYmVyKTogUHJvbWlzZTx7IGFjdGl2ZTogYm9vbGVhbjsgcmVhdXRoUmVxdWlyZWQ6IGJvb2xlYW4gfSB8IG51bGw+IHtcbiAgICBjb25zdCB3ZGIgPSB0aGlzLmdldFB1cmkoXCJ3XCIpO1xuICAgIHJldHVybiB3ZGIudHJhbnNhY3Rpb24oYXN5bmMgKHRyeCkgPT4ge1xuICAgICAgY29uc3QgdG9rZW4gPSBhd2FpdCB0cnhcbiAgICAgICAgLmZyb20oXCJ0b2tlbnNcIilcbiAgICAgICAgLnNlbGVjdCh7IGFjdGl2ZTogXCJhY3RpdmVcIiwgcmVhdXRoX3JlcXVpcmVkOiBcInJlYXV0aF9yZXF1aXJlZFwiIH0pXG4gICAgICAgIC53aGVyZShcImlkXCIsIGlkKVxuICAgICAgICAuZm9yVXBkYXRlKClcbiAgICAgICAgLmZpcnN0KCk7XG4gICAgICBpZiAoIXRva2VuKSByZXR1cm4gbnVsbDtcbiAgICAgIGlmICghdG9rZW4uYWN0aXZlICYmIHRva2VuLnJlYXV0aF9yZXF1aXJlZCkge1xuICAgICAgICByZXR1cm4geyBhY3RpdmU6IGZhbHNlLCByZWF1dGhSZXF1aXJlZDogdHJ1ZSB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBhY3RpdmUgPSAhdG9rZW4uYWN0aXZlO1xuICAgICAgYXdhaXQgdHJ4LmZyb20oXCJ0b2tlbnNcIikud2hlcmUoXCJpZFwiLCBpZCkudXBkYXRlKHsgYWN0aXZlIH0pO1xuICAgICAgcmV0dXJuIHsgYWN0aXZlLCByZWF1dGhSZXF1aXJlZDogZmFsc2UgfTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiDqsJnsnYAg6rOE7KCV7J2YIOq4sOyhtCDthqDtgbDsnYQg7KeA7Jqw6rOgIOyDiOuhnCDsoIDsnqXtlZzri6Qo66Gc6re47J24wrfsnqzroZzqt7jsnbgg6rO17Ya1IOqyveuhnCkuXG4gICAqXG4gICAqIHByb3ZpZGVyIOydkeuLteyXkCDqs4TsoJUg7Iud67OE7J6Q6rCAIOyXhuycvOuptCBkZWR1cCDsnpDssrTqsIAg67aI6rCA64ql7ZWY66+A66GcIOqyveqzoOunjCDrgqjquLDqs6BcbiAgICog7KSR67O1IOygnOqxsCDsl4bsnbQg7KCA7J6l7ZWc64ukKOyjveydgCByb3cg6rCAIOuCqOuKlOuLpCkuXG4gICAqL1xuICBhc3luYyByZXBsYWNlQnlBY2NvdW50KFxuICAgIHByb3ZpZGVyOiBzdHJpbmcsXG4gICAgYWNjb3VudElkOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgc2F2ZVBhcmFtczogVG9rZW5TYXZlUGFyYW1zLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQga2VlcGFsaXZlRW5hYmxlZCA9IHNhdmVQYXJhbXMua2VlcGFsaXZlX2VuYWJsZWQ7XG4gICAgaWYgKGFjY291bnRJZCkge1xuICAgICAgY29uc3Qgb2xkRW50cmllcyA9IGF3YWl0IHRoaXMuZmluZEJ5QWNjb3VudElkZW50aWZpZXIoXCJBXCIsIHByb3ZpZGVyLCBhY2NvdW50SWQpO1xuICAgICAgaWYgKGtlZXBhbGl2ZUVuYWJsZWQgPT09IHVuZGVmaW5lZCAmJiBvbGRFbnRyaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAga2VlcGFsaXZlRW5hYmxlZCA9IG9sZEVudHJpZXMuc29tZSgoZW50cnkpID0+IGVudHJ5LmtlZXBhbGl2ZV9lbmFibGVkKTtcbiAgICAgIH1cbiAgICAgIGlmIChvbGRFbnRyaWVzLmxlbmd0aCA+IDApIGF3YWl0IHRoaXMuZGVsKG9sZEVudHJpZXMubWFwKChvKSA9PiBvLmlkKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICBgJHtwcm92aWRlcn0gbG9naW4gd2l0aG91dCBhY2NvdW50IGlkZW50aWZpZXI6IGRlZHVwIHNraXBwZWQgZm9yICR7c2F2ZVBhcmFtcy5uYW1lID8/IFwidW5uYW1lZFwifWAsXG4gICAgICApO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuc2F2ZShbXG4gICAgICBrZWVwYWxpdmVFbmFibGVkID09PSB1bmRlZmluZWRcbiAgICAgICAgPyBzYXZlUGFyYW1zXG4gICAgICAgIDogeyAuLi5zYXZlUGFyYW1zLCBrZWVwYWxpdmVfZW5hYmxlZDoga2VlcGFsaXZlRW5hYmxlZCB9LFxuICAgIF0pO1xuICB9XG5cbiAgLyoqXG4gICAqIOyduOymnSDsgqzrp53snYQg7ZWcIOuyiOunjCDquLDroZ3tlZjqs6AsIOuLpOuluCDtmZzshLEg7Yag7YGw7J20IOyeiOycvOuptCDrnbzsmrDtjIXsl5DshJzrj4Qg7KCc7Jm47ZWc64ukLlxuICAgKiDrp4jsp4Drp4kg7Zmc7ISxIO2GoO2BsOydgCBzeXN0ZW1pYyDsnqXslaAg7JWI7KCE7YyQIOuVjOusuOyXkCBhY3RpdmUg7IOB7YOc66W8IOycoOyngO2VmOuQmCDsnqzroZzqt7jsnbhcbiAgICog7ZWE7JqUIOyDge2DnOuKlCDquLDroZ3tlZzri6QuIGBtYXJrZWRg6rCAIOqzteycoCBEQiDsnbjsiqTthLTsiqTrk6TsnZgg7JWM66a8IOuwnOyGoSDqsozsnbTtirjri6QuXG4gICAqL1xuICBhc3luYyBtYXJrUmVhdXRoUmVxdWlyZWQoXG4gICAgaWQ6IG51bWJlcixcbiAgICBleHBlY3RlZENyZWRlbnRpYWxzOiBUb2tlbkNyZWRlbnRpYWxzLFxuICApOiBQcm9taXNlPHsgbWFya2VkOiBib29sZWFuOyBrZXB0QXNMYXN0QWN0aXZlOiBib29sZWFuOyBzdGFsZUNyZWRlbnRpYWxzOiBib29sZWFuIH0+IHtcbiAgICBjb25zdCB3ZGIgPSB0aGlzLmdldFB1cmkoXCJ3XCIpO1xuICAgIHJldHVybiB3ZGIudHJhbnNhY3Rpb24oYXN5bmMgKHRyeCkgPT4ge1xuICAgICAgY29uc3QgdG9rZW4gPSBhd2FpdCB0cnhcbiAgICAgICAgLmZyb20oXCJ0b2tlbnNcIilcbiAgICAgICAgLnNlbGVjdCh7XG4gICAgICAgICAgcHJvdmlkZXI6IFwicHJvdmlkZXJcIixcbiAgICAgICAgICBjcmVkZW50aWFsczogXCJjcmVkZW50aWFsc1wiLFxuICAgICAgICAgIHJlYXV0aF9yZXF1aXJlZDogXCJyZWF1dGhfcmVxdWlyZWRcIixcbiAgICAgICAgfSlcbiAgICAgICAgLndoZXJlKFwiaWRcIiwgaWQpXG4gICAgICAgIC5mb3JVcGRhdGUoKVxuICAgICAgICAuZmlyc3QoKTtcbiAgICAgIGlmICghdG9rZW4gfHwgdG9rZW4ucmVhdXRoX3JlcXVpcmVkKSB7XG4gICAgICAgIHJldHVybiB7IG1hcmtlZDogZmFsc2UsIGtlcHRBc0xhc3RBY3RpdmU6IGZhbHNlLCBzdGFsZUNyZWRlbnRpYWxzOiBmYWxzZSB9O1xuICAgICAgfVxuICAgICAgaWYgKCFpc0RlZXBTdHJpY3RFcXVhbCh0b2tlbi5jcmVkZW50aWFscywgZXhwZWN0ZWRDcmVkZW50aWFscykpIHtcbiAgICAgICAgcmV0dXJuIHsgbWFya2VkOiBmYWxzZSwga2VwdEFzTGFzdEFjdGl2ZTogZmFsc2UsIHN0YWxlQ3JlZGVudGlhbHM6IHRydWUgfTtcbiAgICAgIH1cblxuICAgICAgYXdhaXQgdHJ4LmtuZXgucmF3KFwiU0VMRUNUIHBnX2Fkdmlzb3J5X3hhY3RfbG9jayg/LCBoYXNodGV4dCg/KSlcIiwgW1xuICAgICAgICBUT0tFTl9BVVRIX0RFQVRIX0xPQ0tfQ0xBU1NfSUQsXG4gICAgICAgIHRva2VuLnByb3ZpZGVyLFxuICAgICAgXSk7XG4gICAgICBjb25zdCB1cGRhdGVkID0gYXdhaXQgdHJ4LmtuZXgucmF3PHsgcm93czogeyBhY3RpdmU6IGJvb2xlYW4gfVtdIH0+KFxuICAgICAgICBgVVBEQVRFIHRva2Vuc1xuICAgICAgICAgU0VUIHJlYXV0aF9yZXF1aXJlZCA9IHRydWUsXG4gICAgICAgICAgICAgYWN0aXZlID0gQ0FTRVxuICAgICAgICAgICAgICAgV0hFTiBhY3RpdmUgQU5EIChTRUxFQ1QgY291bnQoKikgRlJPTSB0b2tlbnMgcGVlclxuICAgICAgICAgICAgICAgICBXSEVSRSBwZWVyLnByb3ZpZGVyID0gdG9rZW5zLnByb3ZpZGVyIEFORCBwZWVyLmFjdGl2ZSkgPiAxXG4gICAgICAgICAgICAgICBUSEVOIGZhbHNlXG4gICAgICAgICAgICAgICBFTFNFIGFjdGl2ZVxuICAgICAgICAgICAgIEVORFxuICAgICAgICAgV0hFUkUgaWQgPSA/IEFORCByZWF1dGhfcmVxdWlyZWQgPSBmYWxzZVxuICAgICAgICAgUkVUVVJOSU5HIGFjdGl2ZWAsXG4gICAgICAgIFtpZF0sXG4gICAgICApO1xuICAgICAgY29uc3QgbWFya2VkID0gdXBkYXRlZC5yb3dzWzBdO1xuICAgICAgaWYgKCFtYXJrZWQpIHJldHVybiB7IG1hcmtlZDogZmFsc2UsIGtlcHRBc0xhc3RBY3RpdmU6IGZhbHNlLCBzdGFsZUNyZWRlbnRpYWxzOiBmYWxzZSB9O1xuXG4gICAgICBpZiAobWFya2VkLmFjdGl2ZSkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoXG4gICAgICAgICAgYHJlZnVzaW5nIHRvIGF1dG8tZGVhY3RpdmF0ZSB0b2tlbiAke2lkfTogbGFzdCBhY3RpdmUgcHJvdmlkZXIgdG9rZW4g4oCUIGAgK1xuICAgICAgICAgICAgYHN5c3RlbWljIHJlZnJlc2ggZmFpbHVyZSBzdXNwZWN0ZWQsIGtlZXBpbmcgdGhlIHBvb2wgbm9uLWVtcHR5YCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7IG1hcmtlZDogdHJ1ZSwga2VwdEFzTGFzdEFjdGl2ZTogbWFya2VkLmFjdGl2ZSwgc3RhbGVDcmVkZW50aWFsczogZmFsc2UgfTtcbiAgICB9KTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyByZW9yZGVyKGlkczogbnVtYmVyW10pOiBQcm9taXNlPHsgZG9uZTogYm9vbGVhbiB9PiB7XG4gICAgY29uc3Qgd2RiID0gdGhpcy5nZXRQdXJpKFwid1wiKTtcbiAgICBhd2FpdCB3ZGIudHJhbnNhY3Rpb24oYXN5bmMgKHRyeCkgPT4ge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXdhaXQgdHJ4LnRhYmxlKFwidG9rZW5zXCIpLndoZXJlKFwiaWRcIiwgaWRzW2ldISkudXBkYXRlKHsgb3JkOiBpIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB7IGRvbmU6IHRydWUgfTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBkZWwoaWRzOiBudW1iZXJbXSk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3Qgd2RiID0gdGhpcy5nZXRQdXJpKFwid1wiKTtcbiAgICBhd2FpdCB3ZGIudHJhbnNhY3Rpb24oYXN5bmMgKHRyeCkgPT4ge1xuICAgICAgcmV0dXJuIHRyeC50YWJsZShcInRva2Vuc1wiKS53aGVyZUluKFwidG9rZW5zLmlkXCIsIGlkcykuZGVsZXRlKCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGlkcy5sZW5ndGg7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IFRva2VuTW9kZWwgPSBuZXcgVG9rZW5Nb2RlbENsYXNzKCk7XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBa0JBLE1BQU0sU0FBUyxVQUFVLENBQUMsU0FBUyxPQUFPLENBQUM7QUFFM0MsTUFBTSwwQkFBMEI7QUFDaEMsTUFBTSxpQkFBaUI7QUFDdkIsTUFBTSxpQ0FBaUM7QUFTdkMsU0FBUyxvQkFBb0IsSUFBc0M7Q0FDakUsSUFBSSxHQUFHLE9BQU8sUUFBVyxPQUFPO0NBQ2hDLE9BQU87RUFDTCxHQUFHO0VBQ0gsR0FBSSxHQUFHLG9CQUFvQixTQUFZLEVBQUUsaUJBQWlCLHdCQUF3QixJQUFJLENBQUM7RUFDdkYsR0FBSSxHQUFHLFdBQVcsU0FBWSxFQUFFLFFBQVEsZUFBZSxJQUFJLENBQUM7Q0FDOUQ7QUFDRjtBQUVBLElBQU0sa0JBQU4sY0FBOEIsZUFLNUI7Q0FDQSxjQUFjO0VBQ1osTUFBTSxTQUFTLG9CQUFvQixrQkFB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
306
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4ubW9kZWwuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwcGxpY2F0aW9uL3Rva2VuL3Rva2VuLm1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGlzRGVlcFN0cmljdEVxdWFsIH0gZnJvbSBcIm5vZGU6dXRpbFwiO1xuXG5pbXBvcnQgeyBnZXRMb2dnZXIgfSBmcm9tIFwiQGxvZ3RhcGUvbG9ndGFwZVwiO1xuaW1wb3J0IHtcbiAgYXBpLFxuICBhc0FycmF5LFxuICBCYWRSZXF1ZXN0RXhjZXB0aW9uLFxuICBCYXNlTW9kZWxDbGFzcyxcbiAgZXhoYXVzdGl2ZSxcbiAgdHlwZSBMaXN0UmVzdWx0LFxuICBOb3RGb3VuZEV4Y2VwdGlvbixcbn0gZnJvbSBcInNvbmFtdVwiO1xuXG5pbXBvcnQgeyBTRCB9IGZyb20gXCIuLi8uLi9pMThuL3NkLmdlbmVyYXRlZFwiO1xuaW1wb3J0IHsgdHlwZSBUb2tlblN1YnNldEtleSwgdHlwZSBUb2tlblN1YnNldE1hcHBpbmcgfSBmcm9tIFwiLi4vc29uYW11LmdlbmVyYXRlZFwiO1xuaW1wb3J0IHsgdG9rZW5Mb2FkZXJRdWVyaWVzLCB0b2tlblN1YnNldFF1ZXJpZXMgfSBmcm9tIFwiLi4vc29uYW11LmdlbmVyYXRlZC5zc29cIjtcbmltcG9ydCB7IHR5cGUgVG9rZW5DcmVkZW50aWFscywgdHlwZSBUb2tlbkxpc3RQYXJhbXMsIHR5cGUgVG9rZW5TYXZlUGFyYW1zIH0gZnJvbSBcIi4vdG9rZW4udHlwZXNcIjtcblxuY29uc3QgbG9nZ2VyID0gZ2V0TG9nZ2VyKFtcInFncmlkXCIsIFwidG9rZW5cIl0pO1xuXG5jb25zdCBERUZBVUxUX1FVT1RBX1RIUkVTSE9MRCA9IDgwO1xuY29uc3QgREVGQVVMVF9XRUlHSFQgPSAxO1xuY29uc3QgVE9LRU5fQVVUSF9ERUFUSF9MT0NLX0NMQVNTX0lEID0gNzE5O1xuXG5leHBvcnQgdHlwZSBUb2tlblVwZGF0ZUZpZWxkcyA9IHtcbiAgbmFtZT86IHN0cmluZztcbiAgcXVvdGFfdGhyZXNob2xkPzogbnVtYmVyIHwgbnVsbDtcbiAgd2VpZ2h0PzogbnVtYmVyO1xuICBrZWVwYWxpdmVfZW5hYmxlZD86IGJvb2xlYW47XG59O1xuXG5mdW5jdGlvbiBhcHBseUNyZWF0ZURlZmF1bHRzKHNwOiBUb2tlblNhdmVQYXJhbXMpOiBUb2tlblNhdmVQYXJhbXMge1xuICBpZiAoc3AuaWQgIT09IHVuZGVmaW5lZCkgcmV0dXJuIHNwO1xuICByZXR1cm4ge1xuICAgIC4uLnNwLFxuICAgIC4uLihzcC5xdW90YV90aHJlc2hvbGQgPT09IHVuZGVmaW5lZCA/IHsgcXVvdGFfdGhyZXNob2xkOiBERUZBVUxUX1FVT1RBX1RIUkVTSE9MRCB9IDoge30pLFxuICAgIC4uLihzcC53ZWlnaHQgPT09IHVuZGVmaW5lZCA/IHsgd2VpZ2h0OiBERUZBVUxUX1dFSUdIVCB9IDoge30pLFxuICB9O1xufVxuXG5jbGFzcyBUb2tlbk1vZGVsQ2xhc3MgZXh0ZW5kcyBCYXNlTW9kZWxDbGFzczxcbiAgVG9rZW5TdWJzZXRLZXksXG4gIFRva2VuU3Vic2V0TWFwcGluZyxcbiAgdHlwZW9mIHRva2VuU3Vic2V0UXVlcmllcyxcbiAgdHlwZW9mIHRva2VuTG9hZGVyUXVlcmllc1xuPiB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKFwiVG9rZW5cIiwgdG9rZW5TdWJzZXRRdWVyaWVzLCB0b2tlbkxvYWRlclF1ZXJpZXMpO1xuICB9XG5cbiAgQGFwaSh7IGh0dHBNZXRob2Q6IFwiR0VUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stcXVlcnlcIl0sIHJlc291cmNlTmFtZTogXCJUb2tlblwiIH0pXG4gIGFzeW5jIGZpbmRCeUlkPFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleT4oc3Vic2V0OiBULCBpZDogbnVtYmVyKTogUHJvbWlzZTxUb2tlblN1YnNldE1hcHBpbmdbVF0+IHtcbiAgICBjb25zdCB7IHJvd3MgfSA9IGF3YWl0IHRoaXMuZmluZE1hbnkoc3Vic2V0LCB7IGlkLCBudW06IDEsIHBhZ2U6IDEgfSk7XG4gICAgaWYgKCFyb3dzWzBdKSB7XG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oU0QoXCJlcnJvci5lbnRpdHlOb3RGb3VuZFwiKShcIlRva2VuXCIsIGlkKSk7XG4gICAgfVxuICAgIHJldHVybiByb3dzWzBdO1xuICB9XG5cbiAgYXN5bmMgZmluZE9uZTxUIGV4dGVuZHMgVG9rZW5TdWJzZXRLZXk+KFxuICAgIHN1YnNldDogVCxcbiAgICBsaXN0UGFyYW1zOiBUb2tlbkxpc3RQYXJhbXMsXG4gICk6IFByb21pc2U8VG9rZW5TdWJzZXRNYXBwaW5nW1RdIHwgbnVsbD4ge1xuICAgIGNvbnN0IHsgcm93cyB9ID0gYXdhaXQgdGhpcy5maW5kTWFueShzdWJzZXQsIHsgLi4ubGlzdFBhcmFtcywgbnVtOiAxLCBwYWdlOiAxIH0pO1xuICAgIHJldHVybiByb3dzWzBdID8/IG51bGw7XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSwgcmVzb3VyY2VOYW1lOiBcIlRva2Vuc1wiIH0pXG4gIGFzeW5jIGZpbmRNYW55PFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleSwgTFAgZXh0ZW5kcyBUb2tlbkxpc3RQYXJhbXM+KFxuICAgIHN1YnNldDogVCxcbiAgICByYXdQYXJhbXM/OiBMUCxcbiAgKTogUHJvbWlzZTxMaXN0UmVzdWx0PExQLCBUb2tlblN1YnNldE1hcHBpbmdbVF0+PiB7XG4gICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgbnVtOiAyNCxcbiAgICAgIHBhZ2U6IDEsXG4gICAgICBzZWFyY2g6IFwiaWRcIiBhcyBjb25zdCxcbiAgICAgIG9yZGVyQnk6IFwib3JkLWFzY1wiIGFzIGNvbnN0LFxuICAgICAgLi4ucmF3UGFyYW1zLFxuICAgIH0gc2F0aXNmaWVzIFRva2VuTGlzdFBhcmFtcztcblxuICAgIGNvbnN0IHsgcWIsIG9uU3Vic2V0OiBfIH0gPSB0aGlzLmdldFN1YnNldFF1ZXJpZXMoc3Vic2V0KTtcblxuICAgIGlmIChwYXJhbXMuaWQpIHtcbiAgICAgIHFiLndoZXJlSW4oXCJ0b2tlbnMuaWRcIiwgYXNBcnJheShwYXJhbXMuaWQpKTtcbiAgICB9XG5cbiAgICBpZiAocGFyYW1zLnNlYXJjaCAmJiBwYXJhbXMua2V5d29yZCAmJiBwYXJhbXMua2V5d29yZC5sZW5ndGggPiAwKSB7XG4gICAgICBpZiAocGFyYW1zLnNlYXJjaCA9PT0gXCJpZFwiKSB7XG4gICAgICAgIHFiLndoZXJlKFwidG9rZW5zLmlkXCIsIE51bWJlcihwYXJhbXMua2V5d29yZCkpO1xuICAgICAgfSBlbHNlIGlmIChwYXJhbXMuc2VhcmNoID09PSBcIm5hbWVcIikge1xuICAgICAgICBxYi53aGVyZShcInRva2Vucy5uYW1lXCIsIFwibGlrZVwiLCBgJSR7cGFyYW1zLmtleXdvcmR9JWApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oU0QoXCJlcnJvci51bmtub3duU2VhcmNoRmllbGRcIikocGFyYW1zLnNlYXJjaCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChwYXJhbXMub3JkZXJCeSkge1xuICAgICAgaWYgKHBhcmFtcy5vcmRlckJ5ID09PSBcImlkLWRlc2NcIikge1xuICAgICAgICBxYi5vcmRlckJ5KFwidG9rZW5zLmlkXCIsIFwiZGVzY1wiKTtcbiAgICAgIH0gZWxzZSBpZiAocGFyYW1zLm9yZGVyQnkgPT09IFwib3JkLWFzY1wiKSB7XG4gICAgICAgIHFiLm9yZGVyQnkoXCJ0b2tlbnMub3JkXCIsIFwiYXNjXCIpO1xuICAgICAgICBxYi5vcmRlckJ5KFwidG9rZW5zLmlkXCIsIFwiYXNjXCIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhoYXVzdGl2ZShwYXJhbXMub3JkZXJCeSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZW5oYW5jZXJzID0gdGhpcy5jcmVhdGVFbmhhbmNlcnMoe1xuICAgICAgQTogKHJvdykgPT4gKHsgLi4ucm93IH0pLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuZXhlY3V0ZVN1YnNldFF1ZXJ5KHsgc3Vic2V0LCBxYiwgcGFyYW1zLCBlbmhhbmNlcnMsIGRlYnVnOiBmYWxzZSB9KTtcbiAgfVxuXG4gIGFzeW5jIGZpbmRCeUFjY291bnRJZGVudGlmaWVyPFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleT4oXG4gICAgc3Vic2V0OiBULFxuICAgIHByb3ZpZGVyOiBzdHJpbmcsXG4gICAgYWNjb3VudElkOiBzdHJpbmcsXG4gICk6IFByb21pc2U8VG9rZW5TdWJzZXRNYXBwaW5nW1RdW10+IHtcbiAgICBjb25zdCB7IHFiIH0gPSB0aGlzLmdldFN1YnNldFF1ZXJpZXMoc3Vic2V0KTtcbiAgICBxYi53aGVyZShcInRva2Vucy5wcm92aWRlclwiLCBwcm92aWRlcik7XG4gICAgY29uc3QganNvbktleSA9IHByb3ZpZGVyID09PSBcImFudGhyb3BpY1wiID8gXCJhY2NvdW50VXVpZFwiIDogXCJhY2NvdW50SWRcIjtcbiAgICBxYi53aGVyZVJhdyhgdG9rZW5zLmNyZWRlbnRpYWxzLT4+JyR7anNvbktleX0nID0gP2AsIFthY2NvdW50SWRdKTtcbiAgICBjb25zdCBlbmhhbmNlcnMgPSB0aGlzLmNyZWF0ZUVuaGFuY2Vycyh7IEE6IChyb3cpID0+ICh7IC4uLnJvdyB9KSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmV4ZWN1dGVTdWJzZXRRdWVyeSh7XG4gICAgICBzdWJzZXQsXG4gICAgICBxYixcbiAgICAgIHBhcmFtczogeyBudW06IDEwMCwgcGFnZTogMSB9LFxuICAgICAgZW5oYW5jZXJzLFxuICAgICAgZGVidWc6IGZhbHNlLFxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQucm93cztcbiAgfVxuXG4gIGFzeW5jIGZpbmRBY3RpdmVCeVByb3ZpZGVyPFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleT4oXG4gICAgc3Vic2V0OiBULFxuICAgIHByb3ZpZGVyOiBzdHJpbmcsXG4gICk6IFByb21pc2U8VG9rZW5TdWJzZXRNYXBwaW5nW1RdW10+IHtcbiAgICBjb25zdCB7IHFiIH0gPSB0aGlzLmdldFN1YnNldFF1ZXJpZXMoc3Vic2V0KTtcbiAgICBxYi53aGVyZShcInRva2Vucy5hY3RpdmVcIiwgdHJ1ZSk7XG4gICAgcWIud2hlcmUoXCJ0b2tlbnMucHJvdmlkZXJcIiwgcHJvdmlkZXIpO1xuICAgIGNvbnN0IGVuaGFuY2VycyA9IHRoaXMuY3JlYXRlRW5oYW5jZXJzKHsgQTogKHJvdykgPT4gKHsgLi4ucm93IH0pIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuZXhlY3V0ZVN1YnNldFF1ZXJ5KHtcbiAgICAgIHN1YnNldCxcbiAgICAgIHFiLFxuICAgICAgcGFyYW1zOiB7IG51bTogMTAwLCBwYWdlOiAxIH0sXG4gICAgICBlbmhhbmNlcnMsXG4gICAgICBkZWJ1ZzogZmFsc2UsXG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdC5yb3dzO1xuICB9XG5cbiAgYXN5bmMgZmluZEFjdGl2ZUJ5UHJvdmlkZXJBbmROYW1lPFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleT4oXG4gICAgc3Vic2V0OiBULFxuICAgIHByb3ZpZGVyOiBzdHJpbmcsXG4gICAgbmFtZTogc3RyaW5nLFxuICApOiBQcm9taXNlPFRva2VuU3Vic2V0TWFwcGluZ1tUXSB8IHVuZGVmaW5lZD4ge1xuICAgIGNvbnN0IHsgcWIgfSA9IHRoaXMuZ2V0U3Vic2V0UXVlcmllcyhzdWJzZXQpO1xuICAgIHFiLndoZXJlKFwidG9rZW5zLmFjdGl2ZVwiLCB0cnVlKTtcbiAgICBxYi53aGVyZShcInRva2Vucy5wcm92aWRlclwiLCBwcm92aWRlcik7XG4gICAgcWIud2hlcmUoXCJ0b2tlbnMubmFtZVwiLCBuYW1lKTtcbiAgICBjb25zdCBlbmhhbmNlcnMgPSB0aGlzLmNyZWF0ZUVuaGFuY2Vycyh7IEE6IChyb3cpID0+ICh7IC4uLnJvdyB9KSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmV4ZWN1dGVTdWJzZXRRdWVyeSh7XG4gICAgICBzdWJzZXQsXG4gICAgICBxYixcbiAgICAgIHBhcmFtczogeyBudW06IDEsIHBhZ2U6IDEgfSxcbiAgICAgIGVuaGFuY2VycyxcbiAgICAgIGRlYnVnOiBmYWxzZSxcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0LnJvd3NbMF07XG4gIH1cblxuICAvKiog7Iuk7KCcIOyduOymnSDrp4zro4zqsIAg7ZmV7J2464+8IOyerOuhnOq3uOyduOydtCDtlYTsmpTtlZwg7Yag7YGw65OkLiDsiJjrj5kg67mE7Zmc7ISx7ZmU64qUIOygnOyZuO2VnOuLpC4gKi9cbiAgYXN5bmMgZmluZFJlYXV0aFJlcXVpcmVkPFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleT4oc3Vic2V0OiBUKTogUHJvbWlzZTxUb2tlblN1YnNldE1hcHBpbmdbVF1bXT4ge1xuICAgIGNvbnN0IHsgcWIgfSA9IHRoaXMuZ2V0U3Vic2V0UXVlcmllcyhzdWJzZXQpO1xuICAgIHFiLndoZXJlKFwidG9rZW5zLnJlYXV0aF9yZXF1aXJlZFwiLCB0cnVlKTtcbiAgICBxYi5vcmRlckJ5KFwidG9rZW5zLm5hbWVcIiwgXCJhc2NcIik7XG4gICAgY29uc3QgZW5oYW5jZXJzID0gdGhpcy5jcmVhdGVFbmhhbmNlcnMoeyBBOiAocm93KSA9PiAoeyAuLi5yb3cgfSkgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5leGVjdXRlU3Vic2V0UXVlcnkoe1xuICAgICAgc3Vic2V0LFxuICAgICAgcWIsXG4gICAgICBwYXJhbXM6IHsgbnVtOiAxMDAsIHBhZ2U6IDEgfSxcbiAgICAgIGVuaGFuY2VycyxcbiAgICAgIGRlYnVnOiBmYWxzZSxcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0LnJvd3M7XG4gIH1cblxuICBhc3luYyBmaW5kQWN0aXZlPFQgZXh0ZW5kcyBUb2tlblN1YnNldEtleT4oc3Vic2V0OiBUKTogUHJvbWlzZTxUb2tlblN1YnNldE1hcHBpbmdbVF1bXT4ge1xuICAgIGNvbnN0IHsgcWIgfSA9IHRoaXMuZ2V0U3Vic2V0UXVlcmllcyhzdWJzZXQpO1xuICAgIHFiLndoZXJlKFwidG9rZW5zLmFjdGl2ZVwiLCB0cnVlKTtcbiAgICBjb25zdCBlbmhhbmNlcnMgPSB0aGlzLmNyZWF0ZUVuaGFuY2Vycyh7IEE6IChyb3cpID0+ICh7IC4uLnJvdyB9KSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmV4ZWN1dGVTdWJzZXRRdWVyeSh7XG4gICAgICBzdWJzZXQsXG4gICAgICBxYixcbiAgICAgIHBhcmFtczogeyBudW06IDEwMCwgcGFnZTogMSB9LFxuICAgICAgZW5oYW5jZXJzLFxuICAgICAgZGVidWc6IGZhbHNlLFxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQucm93cztcbiAgfVxuXG4gIGFzeW5jIHNhdmUoc3BhOiBUb2tlblNhdmVQYXJhbXNbXSk6IFByb21pc2U8bnVtYmVyW10+IHtcbiAgICBjb25zdCB3ZGIgPSB0aGlzLmdldFB1cmkoXCJ3XCIpO1xuICAgIHNwYS5mb3JFYWNoKChzcCkgPT4ge1xuICAgICAgd2RiLnViUmVnaXN0ZXIoXCJ0b2tlbnNcIiwgYXBwbHlDcmVhdGVEZWZhdWx0cyhzcCkpO1xuICAgIH0pO1xuICAgIHJldHVybiB3ZGIudHJhbnNhY3Rpb24oYXN5bmMgKHRyeCkgPT4ge1xuICAgICAgcmV0dXJuIHRyeC51YlVwc2VydChcInRva2Vuc1wiKTtcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIHVwZGF0ZUZpZWxkcyhpZDogbnVtYmVyLCBmaWVsZHM6IFRva2VuVXBkYXRlRmllbGRzKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCB3ZGIgPSB0aGlzLmdldFB1cmkoXCJ3XCIpO1xuICAgIHJldHVybiB3ZGIudHJhbnNhY3Rpb24oKHRyeCkgPT4gdHJ4LnRhYmxlKFwidG9rZW5zXCIpLndoZXJlKFwiaWRcIiwgaWQpLnVwZGF0ZShmaWVsZHMpKTtcbiAgfVxuXG4gIGFzeW5jIHRvZ2dsZUFjdGl2ZShpZDogbnVtYmVyKTogUHJvbWlzZTx7IGFjdGl2ZTogYm9vbGVhbjsgcmVhdXRoUmVxdWlyZWQ6IGJvb2xlYW4gfSB8IG51bGw+IHtcbiAgICBjb25zdCB3ZGIgPSB0aGlzLmdldFB1cmkoXCJ3XCIpO1xuICAgIHJldHVybiB3ZGIudHJhbnNhY3Rpb24oYXN5bmMgKHRyeCkgPT4ge1xuICAgICAgY29uc3QgdG9rZW4gPSBhd2FpdCB0cnhcbiAgICAgICAgLmZyb20oXCJ0b2tlbnNcIilcbiAgICAgICAgLnNlbGVjdCh7IGFjdGl2ZTogXCJhY3RpdmVcIiwgcmVhdXRoX3JlcXVpcmVkOiBcInJlYXV0aF9yZXF1aXJlZFwiIH0pXG4gICAgICAgIC53aGVyZShcImlkXCIsIGlkKVxuICAgICAgICAuZm9yVXBkYXRlKClcbiAgICAgICAgLmZpcnN0KCk7XG4gICAgICBpZiAoIXRva2VuKSByZXR1cm4gbnVsbDtcbiAgICAgIGlmICghdG9rZW4uYWN0aXZlICYmIHRva2VuLnJlYXV0aF9yZXF1aXJlZCkge1xuICAgICAgICByZXR1cm4geyBhY3RpdmU6IGZhbHNlLCByZWF1dGhSZXF1aXJlZDogdHJ1ZSB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBhY3RpdmUgPSAhdG9rZW4uYWN0aXZlO1xuICAgICAgYXdhaXQgdHJ4LmZyb20oXCJ0b2tlbnNcIikud2hlcmUoXCJpZFwiLCBpZCkudXBkYXRlKHsgYWN0aXZlIH0pO1xuICAgICAgcmV0dXJuIHsgYWN0aXZlLCByZWF1dGhSZXF1aXJlZDogZmFsc2UgfTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiDqsJnsnYAg6rOE7KCV7J2YIOq4sOyhtCDthqDtgbDsnYQg7KeA7Jqw6rOgIOyDiOuhnCDsoIDsnqXtlZzri6Qo66Gc6re47J24wrfsnqzroZzqt7jsnbgg6rO17Ya1IOqyveuhnCkuXG4gICAqXG4gICAqIHByb3ZpZGVyIOydkeuLteyXkCDqs4TsoJUg7Iud67OE7J6Q6rCAIOyXhuycvOuptCBkZWR1cCDsnpDssrTqsIAg67aI6rCA64ql7ZWY66+A66GcIOqyveqzoOunjCDrgqjquLDqs6BcbiAgICog7KSR67O1IOygnOqxsCDsl4bsnbQg7KCA7J6l7ZWc64ukKOyjveydgCByb3cg6rCAIOuCqOuKlOuLpCkuXG4gICAqL1xuICBhc3luYyByZXBsYWNlQnlBY2NvdW50KFxuICAgIHByb3ZpZGVyOiBzdHJpbmcsXG4gICAgYWNjb3VudElkOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgc2F2ZVBhcmFtczogVG9rZW5TYXZlUGFyYW1zLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQga2VlcGFsaXZlRW5hYmxlZCA9IHNhdmVQYXJhbXMua2VlcGFsaXZlX2VuYWJsZWQ7XG4gICAgaWYgKGFjY291bnRJZCkge1xuICAgICAgY29uc3Qgb2xkRW50cmllcyA9IGF3YWl0IHRoaXMuZmluZEJ5QWNjb3VudElkZW50aWZpZXIoXCJBXCIsIHByb3ZpZGVyLCBhY2NvdW50SWQpO1xuICAgICAgaWYgKGtlZXBhbGl2ZUVuYWJsZWQgPT09IHVuZGVmaW5lZCAmJiBvbGRFbnRyaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAga2VlcGFsaXZlRW5hYmxlZCA9IG9sZEVudHJpZXMuc29tZSgoZW50cnkpID0+IGVudHJ5LmtlZXBhbGl2ZV9lbmFibGVkKTtcbiAgICAgIH1cbiAgICAgIGlmIChvbGRFbnRyaWVzLmxlbmd0aCA+IDApIGF3YWl0IHRoaXMuZGVsKG9sZEVudHJpZXMubWFwKChvKSA9PiBvLmlkKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICBgJHtwcm92aWRlcn0gbG9naW4gd2l0aG91dCBhY2NvdW50IGlkZW50aWZpZXI6IGRlZHVwIHNraXBwZWQgZm9yICR7c2F2ZVBhcmFtcy5uYW1lID8/IFwidW5uYW1lZFwifWAsXG4gICAgICApO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuc2F2ZShbXG4gICAgICBrZWVwYWxpdmVFbmFibGVkID09PSB1bmRlZmluZWRcbiAgICAgICAgPyBzYXZlUGFyYW1zXG4gICAgICAgIDogeyAuLi5zYXZlUGFyYW1zLCBrZWVwYWxpdmVfZW5hYmxlZDoga2VlcGFsaXZlRW5hYmxlZCB9LFxuICAgIF0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlY29yZCBjb25maXJtZWQgZXhwaXJ5IGFuZCByZW1vdmUgdGhlIHRva2VuIGZyb20gcm91dGluZyBhdG9taWNhbGx5LlxuICAgKiBUaGUgbGFzdCBhY3RpdmUgdG9rZW4gaXMgYWxzbyBkZWFjdGl2YXRlZDsgaXRzIG5vdGlmaWNhdGlvbiBpcyB1cmdlbnQuXG4gICAqL1xuICBhc3luYyBtYXJrUmVhdXRoUmVxdWlyZWQoXG4gICAgaWQ6IG51bWJlcixcbiAgICBleHBlY3RlZENyZWRlbnRpYWxzOiBUb2tlbkNyZWRlbnRpYWxzLFxuICApOiBQcm9taXNlPHsgbWFya2VkOiBib29sZWFuOyB3YXNMYXN0QWN0aXZlOiBib29sZWFuOyBzdGFsZUNyZWRlbnRpYWxzOiBib29sZWFuIH0+IHtcbiAgICBjb25zdCB3ZGIgPSB0aGlzLmdldFB1cmkoXCJ3XCIpO1xuICAgIHJldHVybiB3ZGIudHJhbnNhY3Rpb24oYXN5bmMgKHRyeCkgPT4ge1xuICAgICAgY29uc3QgdG9rZW4gPSBhd2FpdCB0cnhcbiAgICAgICAgLmZyb20oXCJ0b2tlbnNcIilcbiAgICAgICAgLnNlbGVjdCh7XG4gICAgICAgICAgcHJvdmlkZXI6IFwicHJvdmlkZXJcIixcbiAgICAgICAgICBjcmVkZW50aWFsczogXCJjcmVkZW50aWFsc1wiLFxuICAgICAgICAgIHJlYXV0aF9yZXF1aXJlZDogXCJyZWF1dGhfcmVxdWlyZWRcIixcbiAgICAgICAgfSlcbiAgICAgICAgLndoZXJlKFwiaWRcIiwgaWQpXG4gICAgICAgIC5mb3JVcGRhdGUoKVxuICAgICAgICAuZmlyc3QoKTtcbiAgICAgIGlmICghdG9rZW4gfHwgdG9rZW4ucmVhdXRoX3JlcXVpcmVkKSB7XG4gICAgICAgIHJldHVybiB7IG1hcmtlZDogZmFsc2UsIHdhc0xhc3RBY3RpdmU6IGZhbHNlLCBzdGFsZUNyZWRlbnRpYWxzOiBmYWxzZSB9O1xuICAgICAgfVxuICAgICAgaWYgKCFpc0RlZXBTdHJpY3RFcXVhbCh0b2tlbi5jcmVkZW50aWFscywgZXhwZWN0ZWRDcmVkZW50aWFscykpIHtcbiAgICAgICAgcmV0dXJuIHsgbWFya2VkOiBmYWxzZSwgd2FzTGFzdEFjdGl2ZTogZmFsc2UsIHN0YWxlQ3JlZGVudGlhbHM6IHRydWUgfTtcbiAgICAgIH1cblxuICAgICAgYXdhaXQgdHJ4LmtuZXgucmF3KFwiU0VMRUNUIHBnX2Fkdmlzb3J5X3hhY3RfbG9jayg/LCBoYXNodGV4dCg/KSlcIiwgW1xuICAgICAgICBUT0tFTl9BVVRIX0RFQVRIX0xPQ0tfQ0xBU1NfSUQsXG4gICAgICAgIHRva2VuLnByb3ZpZGVyLFxuICAgICAgXSk7XG4gICAgICBjb25zdCB1cGRhdGVkID0gYXdhaXQgdHJ4LmtuZXgucmF3PHsgcm93czogeyB3YXNfbGFzdF9hY3RpdmU6IGJvb2xlYW4gfVtdIH0+KFxuICAgICAgICBgV0lUSCBwcmV2aW91cyBBUyAoXG4gICAgICAgICAgIFNFTEVDVCBhY3RpdmUgQU5EIE5PVCBFWElTVFMgKFxuICAgICAgICAgICAgIFNFTEVDVCAxIEZST00gdG9rZW5zIHBlZXJcbiAgICAgICAgICAgICBXSEVSRSBwZWVyLnByb3ZpZGVyID0gdG9rZW5zLnByb3ZpZGVyIEFORCBwZWVyLmFjdGl2ZVxuICAgICAgICAgICAgICAgQU5EIE5PVCBwZWVyLnJlYXV0aF9yZXF1aXJlZCBBTkQgcGVlci5pZCA8PiB0b2tlbnMuaWRcbiAgICAgICAgICAgKSBBUyB3YXNfbGFzdF9hY3RpdmUgRlJPTSB0b2tlbnMgV0hFUkUgaWQgPSA/XG4gICAgICAgICApXG4gICAgICAgICBVUERBVEUgdG9rZW5zXG4gICAgICAgICBTRVQgcmVhdXRoX3JlcXVpcmVkID0gdHJ1ZSxcbiAgICAgICAgICAgICBhY3RpdmUgPSBmYWxzZVxuICAgICAgICAgV0hFUkUgaWQgPSA/IEFORCByZWF1dGhfcmVxdWlyZWQgPSBmYWxzZVxuICAgICAgICAgUkVUVVJOSU5HIChTRUxFQ1Qgd2FzX2xhc3RfYWN0aXZlIEZST00gcHJldmlvdXMpIEFTIHdhc19sYXN0X2FjdGl2ZWAsXG4gICAgICAgIFtpZCwgaWRdLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IG1hcmtlZCA9IHVwZGF0ZWQucm93c1swXTtcbiAgICAgIGlmICghbWFya2VkKSByZXR1cm4geyBtYXJrZWQ6IGZhbHNlLCB3YXNMYXN0QWN0aXZlOiBmYWxzZSwgc3RhbGVDcmVkZW50aWFsczogZmFsc2UgfTtcblxuICAgICAgaWYgKG1hcmtlZC53YXNfbGFzdF9hY3RpdmUpIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKGBkZWFjdGl2YXRlZCBleHBpcmVkIHRva2VuICR7aWR9OiBubyB1c2FibGUgcHJvdmlkZXIgdG9rZW5zIHJlbWFpbmApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHsgbWFya2VkOiB0cnVlLCB3YXNMYXN0QWN0aXZlOiBtYXJrZWQud2FzX2xhc3RfYWN0aXZlLCBzdGFsZUNyZWRlbnRpYWxzOiBmYWxzZSB9O1xuICAgIH0pO1xuICB9XG5cbiAgLyoqIFJlcGFpciByb3dzIHJldGFpbmVkIGJ5IHRoZSBmb3JtZXIgbGFzdC1hY3RpdmUgZXhjZXB0aW9uIGJlZm9yZSBwb29sIHJlY29uY2lsaWF0aW9uLiAqL1xuICBhc3luYyBkZWFjdGl2YXRlRXhwaXJlZFRva2VucygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLmdldFB1cmkoXCJ3XCIpXG4gICAgICAudGFibGUoXCJ0b2tlbnNcIilcbiAgICAgIC53aGVyZShcInJlYXV0aF9yZXF1aXJlZFwiLCB0cnVlKVxuICAgICAgLndoZXJlKFwiYWN0aXZlXCIsIHRydWUpXG4gICAgICAudXBkYXRlKHsgYWN0aXZlOiBmYWxzZSB9KTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyByZW9yZGVyKGlkczogbnVtYmVyW10pOiBQcm9taXNlPHsgZG9uZTogYm9vbGVhbiB9PiB7XG4gICAgY29uc3Qgd2RiID0gdGhpcy5nZXRQdXJpKFwid1wiKTtcbiAgICBhd2FpdCB3ZGIudHJhbnNhY3Rpb24oYXN5bmMgKHRyeCkgPT4ge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXdhaXQgdHJ4LnRhYmxlKFwidG9rZW5zXCIpLndoZXJlKFwiaWRcIiwgaWRzW2ldISkudXBkYXRlKHsgb3JkOiBpIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB7IGRvbmU6IHRydWUgfTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBkZWwoaWRzOiBudW1iZXJbXSk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3Qgd2RiID0gdGhpcy5nZXRQdXJpKFwid1wiKTtcbiAgICBhd2FpdCB3ZGIudHJhbnNhY3Rpb24oYXN5bmMgKHRyeCkgPT4ge1xuICAgICAgcmV0dXJuIHRyeC50YWJsZShcInRva2Vuc1wiKS53aGVyZUluKFwidG9rZW5zLmlkXCIsIGlkcykuZGVsZXRlKCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGlkcy5sZW5ndGg7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IFRva2VuTW9kZWwgPSBuZXcgVG9rZW5Nb2RlbENsYXNzKCk7XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBa0JBLE1BQU0sU0FBUyxVQUFVLENBQUMsU0FBUyxPQUFPLENBQUM7QUFFM0MsTUFBTSwwQkFBMEI7QUFDaEMsTUFBTSxpQkFBaUI7QUFDdkIsTUFBTSxpQ0FBaUM7QUFTdkMsU0FBUyxvQkFBb0IsSUFBc0M7Q0FDakUsSUFBSSxHQUFHLE9BQU8sUUFBVyxPQUFPO0NB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
@@ -6,28 +6,36 @@ const LONG_CONTEXT_272K = {
6
6
  outputMultiplier: 1.5
7
7
  };
8
8
  const OPENAI_COSTS = {
9
+ "gpt-6-astra": {
10
+ maxEffort: "ultra",
11
+ inputTokens: 10,
12
+ outputTokens: 50,
13
+ cachedInputTokens: 1,
14
+ cacheCreationInputTokens: 12.5,
15
+ longContext: LONG_CONTEXT_272K
16
+ },
9
17
  "gpt-5.6-sol": {
10
18
  maxEffort: "ultra",
11
- inputTokens: 5,
12
- outputTokens: 30,
13
- cachedInputTokens: .5,
14
- cacheCreationInputTokens: 6.25,
19
+ inputTokens: 4,
20
+ outputTokens: 20,
21
+ cachedInputTokens: .4,
22
+ cacheCreationInputTokens: 5,
15
23
  longContext: LONG_CONTEXT_272K
16
24
  },
17
25
  "gpt-5.6-terra": {
18
26
  maxEffort: "ultra",
19
- inputTokens: 2.5,
20
- outputTokens: 15,
21
- cachedInputTokens: .25,
22
- cacheCreationInputTokens: 3.125,
27
+ inputTokens: 2,
28
+ outputTokens: 12,
29
+ cachedInputTokens: .2,
30
+ cacheCreationInputTokens: 2.5,
23
31
  longContext: LONG_CONTEXT_272K
24
32
  },
25
33
  "gpt-5.6-luna": {
26
34
  maxEffort: "max",
27
- inputTokens: 1,
28
- outputTokens: 6,
29
- cachedInputTokens: .1,
30
- cacheCreationInputTokens: 1.25,
35
+ inputTokens: .2,
36
+ outputTokens: 1.2,
37
+ cachedInputTokens: .02,
38
+ cacheCreationInputTokens: .25,
31
39
  longContext: LONG_CONTEXT_272K
32
40
  },
33
41
  "gpt-5.5": {
@@ -125,4 +133,4 @@ function calculateCostUsd(model, usage) {
125
133
  //#endregion
126
134
  export { calculateCostUsd, getModelCosts, openaiModelMaxEffort };
127
135
 
128
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWwtY29zdC5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvcHJvdmlkZXJzL2NvbW1vbi9tb2RlbC1jb3N0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICog66qo642467OEIO2GoO2BsCDqsIDqsqkg7YWM7J2067iUICsgY29zdCDqs4TsgrAuXG4gKlxuICogY2xhdWRlIGNvZGUg7JmAIOuPmeydvCDtjKjthLQ6IO2BtOudvOydtOyWuO2KuOyXkOyEnCDqsIDqsqkg7YWM7J2067iU66GcIOyngeygkSDqs4TsgrAuXG4gKiDqsIDqsqkg64uo7JyEOiBVU0QgcGVyIDFNIHRva2Vucy5cbiAqXG4gKiBPcGVuQUkg66qo6424IOuqqeuhneydgCBPcGVuQUkg66qo6424IOusuOyEnOyZgCDtmITsnqwg7KeA7JuQIOuqqeuhneydhCDquLDspIDsnLzroZwg6rSA66as7ZWc64ukLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9wbGF0Zm9ybS5vcGVuYWkuY29tL2RvY3MvcHJpY2luZ1xuICogQHNlZSBodHRwczovL3BsYXRmb3JtLmNsYXVkZS5jb20vZG9jcy9lbi9hYm91dC1jbGF1ZGUvcHJpY2luZ1xuICovXG5cbmltcG9ydCB7IHR5cGUgT3BlbkFJRWZmb3J0IH0gZnJvbSBcIi4vZWZmb3J0XCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9kZWxDb3N0cyB7XG4gIGlucHV0VG9rZW5zOiBudW1iZXI7XG4gIG91dHB1dFRva2VuczogbnVtYmVyO1xuICBjYWNoZWRJbnB1dFRva2VuczogbnVtYmVyO1xuICAvKiogVFRMIGJyZWFrZG93biDsnbQg7JeG64qUIHVzYWdlIOyXkCDsoIHsmqntlaAgY2FjaGUgd3JpdGUgZmFsbGJhY2sg64uo6rCALiAqL1xuICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM/OiBudW1iZXI7XG4gIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczVtPzogbnVtYmVyO1xuICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMxaD86IG51bWJlcjtcbiAgLyoqXG4gICAqIGxvbmctY29udGV4dCDtlaDspp0uIOyghOyytCDsnoXroKUg7Yag7YGwKGlucHV0X3Rva2VucywgY2FjaGVfcmVhZCDtj6ztlagp7J20IHRocmVzaG9sZCDstIjqs7wg7IucXG4gICAqIOy0iOqzvOu2hOunjOydtCDslYTri4jrnbwg7JqU7LKtIOyghOyytChmdWxsIHNlc3Npb24p7JeQIOuwsOycqCDsoIHsmqkuXG4gICAqL1xuICBsb25nQ29udGV4dD86IHtcbiAgICB0aHJlc2hvbGQ6IG51bWJlcjtcbiAgICBpbnB1dE11bHRpcGxpZXI6IG51bWJlcjtcbiAgICBjYWNoZWRJbnB1dE11bHRpcGxpZXI6IG51bWJlcjtcbiAgICBvdXRwdXRNdWx0aXBsaWVyOiBudW1iZXI7XG4gIH07XG59XG5cbi8vIOKUgOKUgCBPcGVuQUkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4vL1xuLy8g6rCA6rKpIOy2nOyymDogaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5haS5jb20vYXBpL2RvY3MvbW9kZWxzICgyMDI2LTA3LTE4IO2ZleyduClcbi8vIOyLoOuqqOuNuCDstpzsi5zrp4jri6Qg64uo6rCA6rCAIOuwlOuAjOuvgOuhnCg1LjLihpI1LjTihpI1LjUpIOuqqOuNuCDstpTqsIAg7IucIOuwmOuTnOyLnCDqs7Xsi50g7Y6Y7J207KeAIOyerO2ZleyduO2VtOyVvO2VqFxuXG4vLyBHUFQtNS407JeQ7IScIOyymOydjCDrj4TsnoXrkJwgbG9uZy1jb250ZXh0IO2VoOymnSAoNS4yLzUuMy1jb2RleOuKlCDtlbTri7kg7JeG7J2MLCA1LjQtbWluaS9uYW5v64qUIOqzteyLnSDtkZzsl5DshJwgbG9uZy1jb250ZXh0IOuLqOqwgCDsl4bsnYwpXG4vLyAyNzJLIOy0iOqzvCDsi5wgaW5wdXQgMnggLyBjYWNoZWQgMnggLyBvdXRwdXQgMS41eCDigJQg7LSI6rO867aE66eM7J20IOyVhOuLjCDshLjshZgg7KCE7LK07JeQIOyggeyaqeuQqFxuLy8gQHNlZSBodHRwczovL2RldmVsb3BlcnMub3BlbmFpLmNvbS9hcGkvZG9jcy9tb2RlbHMvZ3B0LTUuNSAoXCJwcm9tcHRzIHdpdGggPjI3MksgaW5wdXQgdG9rZW5zXCIpXG5jb25zdCBMT05HX0NPTlRFWFRfMjcySzogTm9uTnVsbGFibGU8TW9kZWxDb3N0c1tcImxvbmdDb250ZXh0XCJdPiA9IHtcbiAgdGhyZXNob2xkOiAyNzJfMDAwLFxuICBpbnB1dE11bHRpcGxpZXI6IDIsXG4gIGNhY2hlZElucHV0TXVsdGlwbGllcjogMixcbiAgb3V0cHV0TXVsdGlwbGllcjogMS41LFxufTtcblxuLy8gT3BlbkFJIOuqqOuNuCDsubTtg4jroZzqt7guIOuLqOqwgOyZgCDtlajqu5ggQ29kZXgg67Cx7JeU65Oc6rCAIOuqqOuNuOuzhOuhnCDrsJvripQg7LWc64yAIHJlYXNvbmluZyBlZmZvcnQg66W8IO2VnCDqs7Psl5Ag65GU64ukLlxuLy8gbWF4RWZmb3J0IOy2nOyymDogfi8uY29kZXgvbW9kZWxzX2NhY2hlLmpzb24g7J2YIHN1cHBvcnRlZF9yZWFzb25pbmdfbGV2ZWxzICgyMDI2LTA5LTAyIO2ZleyduCkuXG4vLyDrr7jquLDsnqwg66qo64247J2AIHhoaWdoIOq5jOyngOunjCDrsJvripTri6QuXG50eXBlIE9wZW5BSU1vZGVsU3BlYyA9IE1vZGVsQ29zdHMgJiB7IG1heEVmZm9ydD86IE9wZW5BSUVmZm9ydCB9O1xuXG5jb25zdCBPUEVOQUlfQ09TVFM6IFJlY29yZDxzdHJpbmcsIE9wZW5BSU1vZGVsU3BlYz4gPSB7XG4gIC8vIEdQVC01LjYgU29sLCBUZXJyYSwgTHVuYS4gY2FjaGUgd3JpdGUg64uo6rCA64qUIOyZuOu2gCBsb2dnZXIvbWFudWFsIHVzYWdlIOyeheugpeydhCDsnITtlbRcbiAgLy8g7Jyg7KeA7ZWc64ukLiDtmITsnqwgT3BlbkFJIOydkeuLtSB1c2FnZSDsl5AgY2FjaGUgd3JpdGUg7Yag7YGwIO2VhOuTnOqwgCDsl4bsnLzrqbQg67mE7Jqp7J2AIDDsnLzroZwg6rOE7IKw65Cc64ukLlxuICAvLyBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuYWkuY29tL2FwaS9kb2NzL21vZGVscy9ncHQtNS42LXNvbFxuICAvLyBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuYWkuY29tL2FwaS9kb2NzL21vZGVscy9ncHQtNS42LXRlcnJhXG4gIC8vIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5haS5jb20vYXBpL2RvY3MvbW9kZWxzL2dwdC01LjYtbHVuYVxuICBcImdwdC01LjYtc29sXCI6IHtcbiAgICBtYXhFZmZvcnQ6IFwidWx0cmFcIixcbiAgICBpbnB1dFRva2VuczogNSxcbiAgICBvdXRwdXRUb2tlbnM6IDMwLFxuICAgIGNhY2hlZElucHV0VG9rZW5zOiAwLjUsXG4gICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zOiA2LjI1LFxuICAgIGxvbmdDb250ZXh0OiBMT05HX0NPTlRFWFRfMjcySyxcbiAgfSxcbiAgXCJncHQtNS42LXRlcnJhXCI6IHtcbiAgICBtYXhFZmZvcnQ6IFwidWx0cmFcIixcbiAgICBpbnB1dFRva2VuczogMi41LFxuICAgIG91dHB1dFRva2VuczogMTUsXG4gICAgY2FjaGVkSW5wdXRUb2tlbnM6IDAuMjUsXG4gICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zOiAzLjEyNSxcbiAgICBsb25nQ29udGV4dDogTE9OR19DT05URVhUXzI3MkssXG4gIH0sXG4gIFwiZ3B0LTUuNi1sdW5hXCI6IHtcbiAgICBtYXhFZmZvcnQ6IFwibWF4XCIsXG4gICAgaW5wdXRUb2tlbnM6IDEsXG4gICAgb3V0cHV0VG9rZW5zOiA2LFxuICAgIGNhY2hlZElucHV0VG9rZW5zOiAwLjEsXG4gICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zOiAxLjI1LFxuICAgIGxvbmdDb250ZXh0OiBMT05HX0NPTlRFWFRfMjcySyxcbiAgfSxcbiAgLy8gaHR0cHM6Ly9vcGVuYWkuY29tL2luZGV4L2ludHJvZHVjaW5nLWdwdC01LTUvICgyMDI2LTA0IOy2nOyLnClcbiAgXCJncHQtNS41XCI6IHtcbiAgICBpbnB1dFRva2VuczogNSxcbiAgICBvdXRwdXRUb2tlbnM6IDMwLFxuICAgIGNhY2hlZElucHV0VG9rZW5zOiAwLjUsXG4gICAgbG9uZ0NvbnRleHQ6IExPTkdfQ09OVEVYVF8yNzJLLFxuICB9LFxuICAvLyDslYTrnpggZ3B0LTUuNCAvIGdwdC01LjQtbWluaSAvIGdwdC01LjMtY29kZXggLyBncHQtNS4yIOuKlCBxZ3JpZCDqsIAg7JOw64qUIENoYXRHUFQg6rWs64+FIENvZGV4IOqyveuhnOyXkOyEnFxuICAvLyDrjZQg7J207IOBIOygnOqzteuQmOyngCDslYrripTri6QoNS40IOqzhOyXtOydgCAyMDI2LTA4LTMxIHJldGlyZWQsIOuMgOyytCBncHQtNS42LXRlcnJhIC8gZ3B0LTUuNi1sdW5hKS5cbiAgLy8g6rO86rGwIHJlcXVlc3QgbG9nIOyerOyCsOyglShjb3N0X3NvdXJjZSDsl4bripQgbGVnYWN5IO2WiSnsl5Ag7ZWE7JqU7ZWY66+A66GcIOuLqOqwgCDtlonsnYAg7Jyg7KeA7ZWc64ukLlxuICAvLyBodHRwczovL29wZW5haS5jb20vaW5kZXgvaW50cm9kdWNpbmctZ3B0LTUtNC8gKDIwMjYtMDMg7Lac7IucKVxuICBcImdwdC01LjRcIjoge1xuICAgIGlucHV0VG9rZW5zOiAyLjUsXG4gICAgb3V0cHV0VG9rZW5zOiAxNSxcbiAgICBjYWNoZWRJbnB1dFRva2VuczogMC4yNSxcbiAgICBsb25nQ29udGV4dDogTE9OR19DT05URVhUXzI3MkssXG4gIH0sXG4gIFwiZ3B0LTUuNC1taW5pXCI6IHsgaW5wdXRUb2tlbnM6IDAuNzUsIG91dHB1dFRva2VuczogNC41LCBjYWNoZWRJbnB1dFRva2VuczogMC4wNzUgfSxcbiAgLy8gZ3B0LTUuMuyZgCDrj5nsnbwg64uo6rCAIChjYWNoZWQgPSBpbnB1dOydmCAxMCUpXG4gIFwiZ3B0LTUuMy1jb2RleFwiOiB7IGlucHV0VG9rZW5zOiAxLjc1LCBvdXRwdXRUb2tlbnM6IDE0LCBjYWNoZWRJbnB1dFRva2VuczogMC4xNzUgfSxcbiAgLy8gaHR0cHM6Ly9vcGVuYWkuY29tL2luZGV4L2ludHJvZHVjaW5nLWdwdC01LTIvIChjYWNoZWQgaW5wdXQgOTAlIO2VoOyduCDrqoXsi5wpXG4gIFwiZ3B0LTUuMlwiOiB7IGlucHV0VG9rZW5zOiAxLjc1LCBvdXRwdXRUb2tlbnM6IDE0LCBjYWNoZWRJbnB1dFRva2VuczogMC4xNzUgfSxcbn07XG5cbi8vIOKUgOKUgCBBbnRocm9waWMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbmZ1bmN0aW9uIGFudGhyb3BpY0Nvc3RzKFxuICBpbnB1dFRva2VuczogbnVtYmVyLFxuICBvdXRwdXRUb2tlbnM6IG51bWJlcixcbiAgb3ZlcnJpZGVzOiBQaWNrPFBhcnRpYWw8TW9kZWxDb3N0cz4sIFwiY2FjaGVkSW5wdXRUb2tlbnNcIj4gPSB7fSxcbik6IE1vZGVsQ29zdHMge1xuICByZXR1cm4ge1xuICAgIGlucHV0VG9rZW5zLFxuICAgIG91dHB1dFRva2VucyxcbiAgICAvLyDtkZzspIAgY2FjaGUgcmVhZCDripQgYmFzZSBpbnB1dCDsnZggMC4xeC4gRmFibGUgNS4xIOyymOufvCDqs7Xsi50g7Yq566GAIOuLqOqwgOqwgCDsnojsnLzrqbQgb3ZlcnJpZGUg7ZWc64ukLlxuICAgIGNhY2hlZElucHV0VG9rZW5zOiBvdmVycmlkZXMuY2FjaGVkSW5wdXRUb2tlbnMgPz8gaW5wdXRUb2tlbnMgLyAxMCxcbiAgICAvLyBDbGF1ZGUgQ29kZSBzdWJzY3JpcHRpb24gT0F1dGgg64qUIDFoIFRUTCDsnYQg7J6Q64+ZIOyEoO2Dne2VnOuLpC4g6rWs67KE7KCE7LKY65+8IOydkeuLteyXkFxuICAgIC8vIFRUTCBicmVha2Rvd24g7J20IOyXhuydhCDrlYzrp4wg7J20IDFoIOuLqOqwgOulvCBmYWxsYmFjayDsnLzroZwg7IKs7Jqp7ZWc64ukLlxuICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczogaW5wdXRUb2tlbnMgKiAyLFxuICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczVtOiBpbnB1dFRva2VucyAqIDEuMjUsXG4gICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zMWg6IGlucHV0VG9rZW5zICogMixcbiAgfTtcbn1cblxuLy8g6rCA6rKpIOy2nOyymDogaHR0cHM6Ly9wbGF0Zm9ybS5jbGF1ZGUuY29tL2RvY3MvZW4vYWJvdXQtY2xhdWRlL3ByaWNpbmcgKDIwMjYtMDktMDIg7ZmV7J24KVxuY29uc3QgQU5USFJPUElDX0NPU1RTOiBSZWNvcmQ8c3RyaW5nLCBNb2RlbENvc3RzPiA9IHtcbiAgLy8gRmFibGUgNS4xICgyMDI2LTA5LTAxIOy2nOyLnCk6IGlucHV0L291dHB1dCDsnYAgRmFibGUgNSDsmYAg6rCZ6rOgIGNhY2hlIHJlYWQg66eMIDAuMDI1eCgkMC4yNSkg7Yq566GALlxuICAvLyBAc2VlIGh0dHBzOi8vcGxhdGZvcm0uY2xhdWRlLmNvbS9kb2NzL2VuL21vZGVscy9mYWJsZS01LTEvb3ZlcnZpZXdcbiAgXCJjbGF1ZGUtZmFibGUtNS0xXCI6IGFudGhyb3BpY0Nvc3RzKDEwLCA1MCwgeyBjYWNoZWRJbnB1dFRva2VuczogMC4yNSB9KSxcbiAgXCJjbGF1ZGUtZmFibGUtNVwiOiBhbnRocm9waWNDb3N0cygxMCwgNTApLFxuICBzb25uZXQ6IGFudGhyb3BpY0Nvc3RzKDMsIDE1KSxcbiAgXCJjbGF1ZGUtMy01LWhhaWt1XCI6IGFudGhyb3BpY0Nvc3RzKDAuOCwgNCksXG4gIFwiY2xhdWRlLWhhaWt1LTQtNVwiOiBhbnRocm9waWNDb3N0cygxLCA1KSxcbiAgXCJjbGF1ZGUtMy01LXNvbm5ldFwiOiBhbnRocm9waWNDb3N0cygzLCAxNSksXG4gIFwiY2xhdWRlLTMtNy1zb25uZXRcIjogYW50aHJvcGljQ29zdHMoMywgMTUpLFxuICBcImNsYXVkZS1zb25uZXQtNFwiOiBhbnRocm9waWNDb3N0cygzLCAxNSksXG4gIFwiY2xhdWRlLXNvbm5ldC00LTVcIjogYW50aHJvcGljQ29zdHMoMywgMTUpLFxuICBcImNsYXVkZS1zb25uZXQtNC02XCI6IGFudGhyb3BpY0Nvc3RzKDMsIDE1KSxcbiAgXCJjbGF1ZGUtc29ubmV0LTQtN1wiOiBhbnRocm9waWNDb3N0cygzLCAxNSksXG4gIFwiY2xhdWRlLW9wdXMtNFwiOiBhbnRocm9waWNDb3N0cygxNSwgNzUpLFxuICBcImNsYXVkZS1vcHVzLTQtMVwiOiBhbnRocm9waWNDb3N0cygxNSwgNzUpLFxuICBcImNsYXVkZS1vcHVzLTQtNVwiOiBhbnRocm9waWNDb3N0cyg1LCAyNSksXG4gIFwiY2xhdWRlLW9wdXMtNC02XCI6IGFudGhyb3BpY0Nvc3RzKDUsIDI1KSxcbiAgXCJjbGF1ZGUtb3B1cy00LTdcIjogYW50aHJvcGljQ29zdHMoNSwgMjUpLFxuICBcImNsYXVkZS1vcHVzLTQtOFwiOiBhbnRocm9waWNDb3N0cyg1LCAyNSksXG4gIFwiY2xhdWRlLW9wdXMtNVwiOiBhbnRocm9waWNDb3N0cyg1LCAyNSksXG4gIC8vIFNvbm5ldCA1IOydmCBpbnRyb2R1Y3RvcnkgJDIvJDEwIOydtCDsoJXsi50g64uo6rCA66GcIO2ZleygleuQkOuLpC4gMjAyNi0wOS0wMSDsl5Ag7JiI7KCV65CQ642YICQzLyQxNSDsnbjsg4HsnYBcbiAgLy8g7Leo7IaM65CQ7Jy866+A66GcIOuCoOynnCDrtoTquLAg7JeG7J20IOqzoOyglSDri6jqsIDroZwg6rOE7IKw7ZWc64ukLlxuICBcImNsYXVkZS1zb25uZXQtNVwiOiBhbnRocm9waWNDb3N0cygyLCAxMCksXG59O1xuXG4vLyBncHQtNS4zLWNvZGV4LXNwYXJrIOuKlCByZXNlYXJjaCBwcmV2aWV3IOuhnCDqs7Xsi50gdG9rZW4g64uo6rCA6rCAIOyVhOyngSBmaW5hbCDsnbQg7JWE64uI64ukLlxuLy8g7KeA7JuQIO2DgOyeheydgCDsnKDsp4DtlZjrkJgsIOqzteyLnSDri6jqsIDqsIAg6rO16rCc65CgIOuVjOq5jOyngCDslYTrnpggZ2VuZXJpYyBlc3RpbWF0ZSDroZwg6rOE7IKw7ZWc64ukLlxuLy8gQHNlZSBodHRwczovL2hlbHAub3BlbmFpLmNvbS9lbi9hcnRpY2xlcy8yMDAwMTEwNi1jb2RleC1yYXRlLWNhcmRcbmNvbnN0IERFRkFVTFRfQ09TVFM6IE1vZGVsQ29zdHMgPSB7IGlucHV0VG9rZW5zOiAzLCBvdXRwdXRUb2tlbnM6IDE1LCBjYWNoZWRJbnB1dFRva2VuczogMC4zIH07XG5cbi8qKiBDb2RleCDrsLHsl5Trk5zqsIAg7J20IOuqqOuNuOyXkCDtl4jsmqntlZjripQg7LWc64yAIGVmZm9ydC4g7Lm07YOI66Gc6re47JeQIOyXhuuKlCDrqqjrjbjsnYAgeGhpZ2gg6rmM7KeA64ukLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9wZW5haU1vZGVsTWF4RWZmb3J0KG1vZGVsOiBzdHJpbmcpOiBPcGVuQUlFZmZvcnQge1xuICByZXR1cm4gT1BFTkFJX0NPU1RTW21vZGVsXT8ubWF4RWZmb3J0ID8/IFwieGhpZ2hcIjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE1vZGVsQ29zdHMobW9kZWw6IHN0cmluZyk6IE1vZGVsQ29zdHMge1xuICBjb25zdCBub3JtYWxpemVkTW9kZWwgPSAobW9kZWwuc3BsaXQoXCIvXCIpLnBvcCgpID8/IG1vZGVsKS5yZXBsYWNlKC9cXFsxbVxcXSQvaSwgXCJcIik7XG4gIHJldHVybiBPUEVOQUlfQ09TVFNbbm9ybWFsaXplZE1vZGVsXSA/PyBBTlRIUk9QSUNfQ09TVFNbbm9ybWFsaXplZE1vZGVsXSA/PyBERUZBVUxUX0NPU1RTO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlQ29zdFVzZChcbiAgbW9kZWw6IHN0cmluZyxcbiAgdXNhZ2U6IHtcbiAgICBpbnB1dFRva2VuczogbnVtYmVyO1xuICAgIG91dHB1dFRva2VuczogbnVtYmVyO1xuICAgIGNhY2hlZElucHV0VG9rZW5zPzogbnVtYmVyO1xuICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2Vucz86IG51bWJlcjtcbiAgICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM1bT86IG51bWJlcjtcbiAgICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMxaD86IG51bWJlcjtcbiAgfSxcbik6IG51bWJlciB7XG4gIGNvbnN0IGNvc3RzID0gZ2V0TW9kZWxDb3N0cyhtb2RlbCk7XG4gIGNvbnN0IGNhY2hlZElucHV0ID0gdXNhZ2UuY2FjaGVkSW5wdXRUb2tlbnMgPz8gMDtcbiAgY29uc3QgY2FjaGVDcmVhdGlvbklucHV0NW0gPSBNYXRoLm1heCh1c2FnZS5jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM1bSA/PyAwLCAwKTtcbiAgY29uc3QgY2FjaGVDcmVhdGlvbklucHV0MWggPSBNYXRoLm1heCh1c2FnZS5jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMxaCA/PyAwLCAwKTtcbiAgY29uc3QgY2FjaGVDcmVhdGlvbklucHV0ID0gTWF0aC5tYXgoXG4gICAgdXNhZ2UuY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zID8/IDAsXG4gICAgY2FjaGVDcmVhdGlvbklucHV0NW0gKyBjYWNoZUNyZWF0aW9uSW5wdXQxaCxcbiAgKTtcbiAgY29uc3QgY2xhc3NpZmllZENhY2hlQ3JlYXRpb25JbnB1dDVtID0gTWF0aC5taW4oY2FjaGVDcmVhdGlvbklucHV0NW0sIGNhY2hlQ3JlYXRpb25JbnB1dCk7XG4gIGNvbnN0IGNsYXNzaWZpZWRDYWNoZUNyZWF0aW9uSW5wdXQxaCA9IE1hdGgubWluKFxuICAgIGNhY2hlQ3JlYXRpb25JbnB1dDFoLFxuICAgIGNhY2hlQ3JlYXRpb25JbnB1dCAtIGNsYXNzaWZpZWRDYWNoZUNyZWF0aW9uSW5wdXQ1bSxcbiAgKTtcbiAgY29uc3QgdW5jbGFzc2lmaWVkQ2FjaGVDcmVhdGlvbklucHV0ID1cbiAgICBjYWNoZUNyZWF0aW9uSW5wdXQgLSBjbGFzc2lmaWVkQ2FjaGVDcmVhdGlvbklucHV0NW0gLSBjbGFzc2lmaWVkQ2FjaGVDcmVhdGlvbklucHV0MWg7XG4gIGNvbnN0IG5vbkNhY2hlZElucHV0ID0gTWF0aC5tYXgodXNhZ2UuaW5wdXRUb2tlbnMgLSBjYWNoZWRJbnB1dCAtIGNhY2hlQ3JlYXRpb25JbnB1dCwgMCk7XG5cbiAgLy8gbG9uZy1jb250ZXh0IO2VoOymnTog7KCE7LK0IOyeheugpShpbnB1dF90b2tlbnMsIGNhY2hlIO2PrO2VqCnsnbQgdGhyZXNob2xkIOy0iOqzvCDsi5wg7JqU7LKtIOyghOyytOyXkCDrsLDsnKgg7KCB7JqpXG4gIGNvbnN0IGxjID0gY29zdHMubG9uZ0NvbnRleHQ7XG4gIGNvbnN0IGlzTG9uZ0NvbnRleHQgPSBsYyAhPT0gdW5kZWZpbmVkICYmIHVzYWdlLmlucHV0VG9rZW5zID4gbGMudGhyZXNob2xkO1xuICBjb25zdCBpbnB1dFJhdGUgPSBjb3N0cy5pbnB1dFRva2VucyAqIChpc0xvbmdDb250ZXh0ID8gbGMuaW5wdXRNdWx0aXBsaWVyIDogMSk7XG4gIGNvbnN0IGNhY2hlZFJhdGUgPSBjb3N0cy5jYWNoZWRJbnB1dFRva2VucyAqIChpc0xvbmdDb250ZXh0ID8gbGMuY2FjaGVkSW5wdXRNdWx0aXBsaWVyIDogMSk7XG4gIGNvbnN0IGNhY2hlQ3JlYXRpb25GYWxsYmFja1JhdGUgPVxuICAgIChjb3N0cy5jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMgPz8gY29zdHMuaW5wdXRUb2tlbnMpICpcbiAgICAoaXNMb25nQ29udGV4dCA/IGxjLmlucHV0TXVsdGlwbGllciA6IDEpO1xuICBjb25zdCBjYWNoZUNyZWF0aW9uNW1SYXRlID1cbiAgICAoY29zdHMuY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zNW0gPz8gY29zdHMuY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zID8/IGNvc3RzLmlucHV0VG9rZW5zKSAqXG4gICAgKGlzTG9uZ0NvbnRleHQgPyBsYy5pbnB1dE11bHRpcGxpZXIgOiAxKTtcbiAgY29uc3QgY2FjaGVDcmVhdGlvbjFoUmF0ZSA9XG4gICAgKGNvc3RzLmNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczFoID8/IGNvc3RzLmNhY2hlQ3JlYXRpb25JbnB1dFRva2VucyA/PyBjb3N0cy5pbnB1dFRva2VucykgKlxuICAgIChpc0xvbmdDb250ZXh0ID8gbGMuaW5wdXRNdWx0aXBsaWVyIDogMSk7XG4gIGNvbnN0IG91dHB1dFJhdGUgPSBjb3N0cy5vdXRwdXRUb2tlbnMgKiAoaXNMb25nQ29udGV4dCA/IGxjLm91dHB1dE11bHRpcGxpZXIgOiAxKTtcblxuICByZXR1cm4gKFxuICAgIChub25DYWNoZWRJbnB1dCAvIDFfMDAwXzAwMCkgKiBpbnB1dFJhdGUgK1xuICAgICh1c2FnZS5vdXRwdXRUb2tlbnMgLyAxXzAwMF8wMDApICogb3V0cHV0UmF0ZSArXG4gICAgKGNhY2hlZElucHV0IC8gMV8wMDBfMDAwKSAqIGNhY2hlZFJhdGUgK1xuICAgICh1bmNsYXNzaWZpZWRDYWNoZUNyZWF0aW9uSW5wdXQgLyAxXzAwMF8wMDApICogY2FjaGVDcmVhdGlvbkZhbGxiYWNrUmF0ZSArXG4gICAgKGNsYXNzaWZpZWRDYWNoZUNyZWF0aW9uSW5wdXQ1bSAvIDFfMDAwXzAwMCkgKiBjYWNoZUNyZWF0aW9uNW1SYXRlICtcbiAgICAoY2xhc3NpZmllZENhY2hlQ3JlYXRpb25JbnB1dDFoIC8gMV8wMDBfMDAwKSAqIGNhY2hlQ3JlYXRpb24xaFJhdGVcbiAgKTtcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQTBDQSxNQUFNLG9CQUE0RDtDQUNoRSxXQUFXO0NBQ1gsaUJBQWlCO0NBQ2pCLHVCQUF1QjtDQUN2QixrQkFBa0I7QUFDcEI7QUFPQSxNQUFNLGVBQWdEO0NBTXBELGVBQWU7RUFDYixXQUFXO0VBQ1gsYUFBYTtFQUNi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
136
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWwtY29zdC5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvcHJvdmlkZXJzL2NvbW1vbi9tb2RlbC1jb3N0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICog66qo642467OEIO2GoO2BsCDqsIDqsqkg7YWM7J2067iUICsgY29zdCDqs4TsgrAuXG4gKlxuICogY2xhdWRlIGNvZGUg7JmAIOuPmeydvCDtjKjthLQ6IO2BtOudvOydtOyWuO2KuOyXkOyEnCDqsIDqsqkg7YWM7J2067iU66GcIOyngeygkSDqs4TsgrAuXG4gKiDqsIDqsqkg64uo7JyEOiBVU0QgcGVyIDFNIHRva2Vucy5cbiAqXG4gKiBPcGVuQUkg66qo6424IOuqqeuhneydgCBPcGVuQUkg66qo6424IOusuOyEnOyZgCDtmITsnqwg7KeA7JuQIOuqqeuhneydhCDquLDspIDsnLzroZwg6rSA66as7ZWc64ukLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9wbGF0Zm9ybS5vcGVuYWkuY29tL2RvY3MvcHJpY2luZ1xuICogQHNlZSBodHRwczovL3BsYXRmb3JtLmNsYXVkZS5jb20vZG9jcy9lbi9hYm91dC1jbGF1ZGUvcHJpY2luZ1xuICovXG5cbmltcG9ydCB7IHR5cGUgT3BlbkFJRWZmb3J0IH0gZnJvbSBcIi4vZWZmb3J0XCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9kZWxDb3N0cyB7XG4gIGlucHV0VG9rZW5zOiBudW1iZXI7XG4gIG91dHB1dFRva2VuczogbnVtYmVyO1xuICBjYWNoZWRJbnB1dFRva2VuczogbnVtYmVyO1xuICAvKiogVFRMIGJyZWFrZG93biDsnbQg7JeG64qUIHVzYWdlIOyXkCDsoIHsmqntlaAgY2FjaGUgd3JpdGUgZmFsbGJhY2sg64uo6rCALiAqL1xuICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM/OiBudW1iZXI7XG4gIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczVtPzogbnVtYmVyO1xuICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMxaD86IG51bWJlcjtcbiAgLyoqXG4gICAqIGxvbmctY29udGV4dCDtlaDspp0uIOyghOyytCDsnoXroKUg7Yag7YGwKGlucHV0X3Rva2VucywgY2FjaGVfcmVhZCDtj6ztlagp7J20IHRocmVzaG9sZCDstIjqs7wg7IucXG4gICAqIOy0iOqzvOu2hOunjOydtCDslYTri4jrnbwg7JqU7LKtIOyghOyytChmdWxsIHNlc3Npb24p7JeQIOuwsOycqCDsoIHsmqkuXG4gICAqL1xuICBsb25nQ29udGV4dD86IHtcbiAgICB0aHJlc2hvbGQ6IG51bWJlcjtcbiAgICBpbnB1dE11bHRpcGxpZXI6IG51bWJlcjtcbiAgICBjYWNoZWRJbnB1dE11bHRpcGxpZXI6IG51bWJlcjtcbiAgICBvdXRwdXRNdWx0aXBsaWVyOiBudW1iZXI7XG4gIH07XG59XG5cbi8vIOKUgOKUgCBPcGVuQUkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4vL1xuLy8gU3RhbmRhcmQgcHJpY2luZyB2ZXJpZmllZCAyMDI2LTA5LTA3OiBodHRwczovL2RldmVsb3BlcnMub3BlbmFpLmNvbS9hcGkvZG9jcy9wcmljaW5nXG4vLyDsi6Drqqjrjbgg7Lac7Iuc66eI64ukIOuLqOqwgOqwgCDrsJTrgIzrr4DroZwoNS4y4oaSNS404oaSNS41KSDrqqjrjbgg7LaU6rCAIOyLnCDrsJjrk5zsi5wg6rO17IudIO2OmOydtOyngCDsnqztmZXsnbjtlbTslbztlahcblxuLy8gR1BULTUuNOyXkOyEnCDsspjsnYwg64+E7J6F65CcIGxvbmctY29udGV4dCDtlaDspp0gKDUuMi81LjMtY29kZXjripQg7ZW064u5IOyXhuydjCwgNS40LW1pbmkvbmFub+uKlCDqs7Xsi50g7ZGc7JeQ7IScIGxvbmctY29udGV4dCDri6jqsIAg7JeG7J2MKVxuLy8gMjcySyDstIjqs7wg7IucIGlucHV0IDJ4IC8gY2FjaGVkIDJ4IC8gb3V0cHV0IDEuNXgg4oCUIOy0iOqzvOu2hOunjOydtCDslYTri4wg7IS47IWYIOyghOyytOyXkCDsoIHsmqnrkKhcbi8vIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5haS5jb20vYXBpL2RvY3MvbW9kZWxzL2dwdC01LjUgKFwicHJvbXB0cyB3aXRoID4yNzJLIGlucHV0IHRva2Vuc1wiKVxuY29uc3QgTE9OR19DT05URVhUXzI3Mks6IE5vbk51bGxhYmxlPE1vZGVsQ29zdHNbXCJsb25nQ29udGV4dFwiXT4gPSB7XG4gIHRocmVzaG9sZDogMjcyXzAwMCxcbiAgaW5wdXRNdWx0aXBsaWVyOiAyLFxuICBjYWNoZWRJbnB1dE11bHRpcGxpZXI6IDIsXG4gIG91dHB1dE11bHRpcGxpZXI6IDEuNSxcbn07XG5cbi8vIE9wZW5BSSDrqqjrjbgg7Lm07YOI66Gc6re4LiDri6jqsIDsmYAg7ZWo6ruYIENvZGV4IOuwseyXlOuTnOqwgCDrqqjrjbjrs4TroZwg67Cb64qUIOy1nOuMgCByZWFzb25pbmcgZWZmb3J0IOulvCDtlZwg6rOz7JeQIOuRlOuLpC5cbi8vIG1heEVmZm9ydCDstpzsspg6IH4vLmNvZGV4L21vZGVsc19jYWNoZS5qc29uIOydmCBzdXBwb3J0ZWRfcmVhc29uaW5nX2xldmVscyAoMjAyNi0wOS0wNyDtmZXsnbgpLlxuLy8g66+46riw7J6sIOuqqOuNuOydgCB4aGlnaCDquYzsp4Drp4wg67Cb64qU64ukLlxudHlwZSBPcGVuQUlNb2RlbFNwZWMgPSBNb2RlbENvc3RzICYgeyBtYXhFZmZvcnQ/OiBPcGVuQUlFZmZvcnQgfTtcblxuY29uc3QgT1BFTkFJX0NPU1RTOiBSZWNvcmQ8c3RyaW5nLCBPcGVuQUlNb2RlbFNwZWM+ID0ge1xuICAvLyBHUFQtNiBBc3RyYTogU3RhbmRhcmQgQVBJLWVxdWl2YWxlbnQgcHJpY2luZywgdmVyaWZpZWQgMjAyNi0wOS0wNy5cbiAgLy8gQ29kZXggc3Vic2NyaXB0aW9uIGNhdGFsb2cgc3VwcG9ydHMgdWx0cmE7IHRoZSBwdWJsaWMgQVBJIGxpc3RzIG9ubHkgdGhyb3VnaCBtYXguXG4gIC8vIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5haS5jb20vYXBpL2RvY3MvbW9kZWxzL2dwdC02LWFzdHJhXG4gIC8vIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5haS5jb20vYXBpL2RvY3MvcHJpY2luZ1xuICBcImdwdC02LWFzdHJhXCI6IHtcbiAgICBtYXhFZmZvcnQ6IFwidWx0cmFcIixcbiAgICBpbnB1dFRva2VuczogMTAsXG4gICAgb3V0cHV0VG9rZW5zOiA1MCxcbiAgICBjYWNoZWRJbnB1dFRva2VuczogMSxcbiAgICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM6IDEyLjUsXG4gICAgbG9uZ0NvbnRleHQ6IExPTkdfQ09OVEVYVF8yNzJLLFxuICB9LFxuICAvLyBHUFQtNS42IFNvbCwgVGVycmEsIEx1bmEuIGNhY2hlIHdyaXRlIOuLqOqwgOuKlCDsmbjrtoAgbG9nZ2VyL21hbnVhbCB1c2FnZSDsnoXroKXsnYQg7JyE7ZW0XG4gIC8vIOycoOyngO2VnOuLpC4g7ZiE7J6sIE9wZW5BSSDsnZHri7UgdXNhZ2Ug7JeQIGNhY2hlIHdyaXRlIO2GoO2BsCDtlYTrk5zqsIAg7JeG7Jy866m0IOu5hOyaqeydgCAw7Jy866GcIOqzhOyCsOuQnOuLpC5cbiAgLy8gQHNlZSBodHRwczovL2RldmVsb3BlcnMub3BlbmFpLmNvbS9hcGkvZG9jcy9tb2RlbHMvZ3B0LTUuNi1zb2xcbiAgLy8gQHNlZSBodHRwczovL2RldmVsb3BlcnMub3BlbmFpLmNvbS9hcGkvZG9jcy9tb2RlbHMvZ3B0LTUuNi10ZXJyYVxuICAvLyBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuYWkuY29tL2FwaS9kb2NzL21vZGVscy9ncHQtNS42LWx1bmFcbiAgLy8gU29sIHByb21vdGlvbmFsIHJhdGVzIGFyZSBhdmFpbGFibGUgYXQgbGVhc3QgdGhyb3VnaCAyMDI2LTExLTIxLlxuICAvLyBObyBjb25maXJtZWQgZW5kIGRhdGUvcmVwbGFjZW1lbnQgcmF0ZTogcmVjaGVjayBvZmZpY2lhbCBwcmljaW5nIGluc3RlYWQgb2YgYXV0by1yZXZlcnRpbmcuXG4gIFwiZ3B0LTUuNi1zb2xcIjoge1xuICAgIG1heEVmZm9ydDogXCJ1bHRyYVwiLFxuICAgIGlucHV0VG9rZW5zOiA0LFxuICAgIG91dHB1dFRva2VuczogMjAsXG4gICAgY2FjaGVkSW5wdXRUb2tlbnM6IDAuNCxcbiAgICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM6IDUsXG4gICAgbG9uZ0NvbnRleHQ6IExPTkdfQ09OVEVYVF8yNzJLLFxuICB9LFxuICBcImdwdC01LjYtdGVycmFcIjoge1xuICAgIG1heEVmZm9ydDogXCJ1bHRyYVwiLFxuICAgIGlucHV0VG9rZW5zOiAyLFxuICAgIG91dHB1dFRva2VuczogMTIsXG4gICAgY2FjaGVkSW5wdXRUb2tlbnM6IDAuMixcbiAgICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM6IDIuNSxcbiAgICBsb25nQ29udGV4dDogTE9OR19DT05URVhUXzI3MkssXG4gIH0sXG4gIFwiZ3B0LTUuNi1sdW5hXCI6IHtcbiAgICBtYXhFZmZvcnQ6IFwibWF4XCIsXG4gICAgaW5wdXRUb2tlbnM6IDAuMixcbiAgICBvdXRwdXRUb2tlbnM6IDEuMixcbiAgICBjYWNoZWRJbnB1dFRva2VuczogMC4wMixcbiAgICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM6IDAuMjUsXG4gICAgbG9uZ0NvbnRleHQ6IExPTkdfQ09OVEVYVF8yNzJLLFxuICB9LFxuICAvLyBodHRwczovL29wZW5haS5jb20vaW5kZXgvaW50cm9kdWNpbmctZ3B0LTUtNS8gKDIwMjYtMDQg7Lac7IucKVxuICBcImdwdC01LjVcIjoge1xuICAgIGlucHV0VG9rZW5zOiA1LFxuICAgIG91dHB1dFRva2VuczogMzAsXG4gICAgY2FjaGVkSW5wdXRUb2tlbnM6IDAuNSxcbiAgICBsb25nQ29udGV4dDogTE9OR19DT05URVhUXzI3MkssXG4gIH0sXG4gIC8vIOyVhOuemCBncHQtNS40IC8gZ3B0LTUuNC1taW5pIC8gZ3B0LTUuMy1jb2RleCAvIGdwdC01LjIg64qUIHFncmlkIOqwgCDsk7DripQgQ2hhdEdQVCDqtazrj4UgQ29kZXgg6rK966Gc7JeQ7IScXG4gIC8vIOuNlCDsnbTsg4Eg7KCc6rO165CY7KeAIOyViuuKlOuLpCg1LjQg6rOE7Je07J2AIDIwMjYtMDgtMzEgcmV0aXJlZCwg64yA7LK0IGdwdC01LjYtdGVycmEgLyBncHQtNS42LWx1bmEpLlxuICAvLyDqs7zqsbAgcmVxdWVzdCBsb2cg7J6s7IKw7KCVKGNvc3Rfc291cmNlIOyXhuuKlCBsZWdhY3kg7ZaJKeyXkCDtlYTsmpTtlZjrr4DroZwg64uo6rCAIO2WieydgCDsnKDsp4DtlZzri6QuXG4gIC8vIGh0dHBzOi8vb3BlbmFpLmNvbS9pbmRleC9pbnRyb2R1Y2luZy1ncHQtNS00LyAoMjAyNi0wMyDstpzsi5wpXG4gIFwiZ3B0LTUuNFwiOiB7XG4gICAgaW5wdXRUb2tlbnM6IDIuNSxcbiAgICBvdXRwdXRUb2tlbnM6IDE1LFxuICAgIGNhY2hlZElucHV0VG9rZW5zOiAwLjI1LFxuICAgIGxvbmdDb250ZXh0OiBMT05HX0NPTlRFWFRfMjcySyxcbiAgfSxcbiAgXCJncHQtNS40LW1pbmlcIjogeyBpbnB1dFRva2VuczogMC43NSwgb3V0cHV0VG9rZW5zOiA0LjUsIGNhY2hlZElucHV0VG9rZW5zOiAwLjA3NSB9LFxuICAvLyBncHQtNS4y7JmAIOuPmeydvCDri6jqsIAgKGNhY2hlZCA9IGlucHV07J2YIDEwJSlcbiAgXCJncHQtNS4zLWNvZGV4XCI6IHsgaW5wdXRUb2tlbnM6IDEuNzUsIG91dHB1dFRva2VuczogMTQsIGNhY2hlZElucHV0VG9rZW5zOiAwLjE3NSB9LFxuICAvLyBodHRwczovL29wZW5haS5jb20vaW5kZXgvaW50cm9kdWNpbmctZ3B0LTUtMi8gKGNhY2hlZCBpbnB1dCA5MCUg7ZWg7J24IOuqheyLnClcbiAgXCJncHQtNS4yXCI6IHsgaW5wdXRUb2tlbnM6IDEuNzUsIG91dHB1dFRva2VuczogMTQsIGNhY2hlZElucHV0VG9rZW5zOiAwLjE3NSB9LFxufTtcblxuLy8g4pSA4pSAIEFudGhyb3BpYyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuZnVuY3Rpb24gYW50aHJvcGljQ29zdHMoXG4gIGlucHV0VG9rZW5zOiBudW1iZXIsXG4gIG91dHB1dFRva2VuczogbnVtYmVyLFxuICBvdmVycmlkZXM6IFBpY2s8UGFydGlhbDxNb2RlbENvc3RzPiwgXCJjYWNoZWRJbnB1dFRva2Vuc1wiPiA9IHt9LFxuKTogTW9kZWxDb3N0cyB7XG4gIHJldHVybiB7XG4gICAgaW5wdXRUb2tlbnMsXG4gICAgb3V0cHV0VG9rZW5zLFxuICAgIC8vIO2RnOykgCBjYWNoZSByZWFkIOuKlCBiYXNlIGlucHV0IOydmCAwLjF4LiBGYWJsZSA1LjEg7LKY65+8IOqzteyLnSDtirnroYAg64uo6rCA6rCAIOyeiOycvOuptCBvdmVycmlkZSDtlZzri6QuXG4gICAgY2FjaGVkSW5wdXRUb2tlbnM6IG92ZXJyaWRlcy5jYWNoZWRJbnB1dFRva2VucyA/PyBpbnB1dFRva2VucyAvIDEwLFxuICAgIC8vIENsYXVkZSBDb2RlIHN1YnNjcmlwdGlvbiBPQXV0aCDripQgMWggVFRMIOydhCDsnpDrj5kg7ISg7YOd7ZWc64ukLiDqtazrsoTsoITsspjrn7wg7J2R64u17JeQXG4gICAgLy8gVFRMIGJyZWFrZG93biDsnbQg7JeG7J2EIOuVjOunjCDsnbQgMWgg64uo6rCA66W8IGZhbGxiYWNrIOycvOuhnCDsgqzsmqntlZzri6QuXG4gICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zOiBpbnB1dFRva2VucyAqIDIsXG4gICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zNW06IGlucHV0VG9rZW5zICogMS4yNSxcbiAgICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMxaDogaW5wdXRUb2tlbnMgKiAyLFxuICB9O1xufVxuXG4vLyDqsIDqsqkg7Lac7LKYOiBodHRwczovL3BsYXRmb3JtLmNsYXVkZS5jb20vZG9jcy9lbi9hYm91dC1jbGF1ZGUvcHJpY2luZyAoMjAyNi0wOS0wMiDtmZXsnbgpXG5jb25zdCBBTlRIUk9QSUNfQ09TVFM6IFJlY29yZDxzdHJpbmcsIE1vZGVsQ29zdHM+ID0ge1xuICAvLyBGYWJsZSA1LjEgKDIwMjYtMDktMDEg7Lac7IucKTogaW5wdXQvb3V0cHV0IOydgCBGYWJsZSA1IOyZgCDqsJnqs6AgY2FjaGUgcmVhZCDrp4wgMC4wMjV4KCQwLjI1KSDtirnroYAuXG4gIC8vIEBzZWUgaHR0cHM6Ly9wbGF0Zm9ybS5jbGF1ZGUuY29tL2RvY3MvZW4vbW9kZWxzL2ZhYmxlLTUtMS9vdmVydmlld1xuICBcImNsYXVkZS1mYWJsZS01LTFcIjogYW50aHJvcGljQ29zdHMoMTAsIDUwLCB7IGNhY2hlZElucHV0VG9rZW5zOiAwLjI1IH0pLFxuICBcImNsYXVkZS1mYWJsZS01XCI6IGFudGhyb3BpY0Nvc3RzKDEwLCA1MCksXG4gIHNvbm5ldDogYW50aHJvcGljQ29zdHMoMywgMTUpLFxuICBcImNsYXVkZS0zLTUtaGFpa3VcIjogYW50aHJvcGljQ29zdHMoMC44LCA0KSxcbiAgXCJjbGF1ZGUtaGFpa3UtNC01XCI6IGFudGhyb3BpY0Nvc3RzKDEsIDUpLFxuICBcImNsYXVkZS0zLTUtc29ubmV0XCI6IGFudGhyb3BpY0Nvc3RzKDMsIDE1KSxcbiAgXCJjbGF1ZGUtMy03LXNvbm5ldFwiOiBhbnRocm9waWNDb3N0cygzLCAxNSksXG4gIFwiY2xhdWRlLXNvbm5ldC00XCI6IGFudGhyb3BpY0Nvc3RzKDMsIDE1KSxcbiAgXCJjbGF1ZGUtc29ubmV0LTQtNVwiOiBhbnRocm9waWNDb3N0cygzLCAxNSksXG4gIFwiY2xhdWRlLXNvbm5ldC00LTZcIjogYW50aHJvcGljQ29zdHMoMywgMTUpLFxuICBcImNsYXVkZS1zb25uZXQtNC03XCI6IGFudGhyb3BpY0Nvc3RzKDMsIDE1KSxcbiAgXCJjbGF1ZGUtb3B1cy00XCI6IGFudGhyb3BpY0Nvc3RzKDE1LCA3NSksXG4gIFwiY2xhdWRlLW9wdXMtNC0xXCI6IGFudGhyb3BpY0Nvc3RzKDE1LCA3NSksXG4gIFwiY2xhdWRlLW9wdXMtNC01XCI6IGFudGhyb3BpY0Nvc3RzKDUsIDI1KSxcbiAgXCJjbGF1ZGUtb3B1cy00LTZcIjogYW50aHJvcGljQ29zdHMoNSwgMjUpLFxuICBcImNsYXVkZS1vcHVzLTQtN1wiOiBhbnRocm9waWNDb3N0cyg1LCAyNSksXG4gIFwiY2xhdWRlLW9wdXMtNC04XCI6IGFudGhyb3BpY0Nvc3RzKDUsIDI1KSxcbiAgXCJjbGF1ZGUtb3B1cy01XCI6IGFudGhyb3BpY0Nvc3RzKDUsIDI1KSxcbiAgLy8gU29ubmV0IDUg7J2YIGludHJvZHVjdG9yeSAkMi8kMTAg7J20IOygleyLnSDri6jqsIDroZwg7ZmV7KCV65CQ64ukLiAyMDI2LTA5LTAxIOyXkCDsmIjsoJXrkJDrjZggJDMvJDE1IOyduOyDgeydgFxuICAvLyDst6jshozrkJDsnLzrr4DroZwg64Kg7KecIOu2hOq4sCDsl4bsnbQg6rOg7KCVIOuLqOqwgOuhnCDqs4TsgrDtlZzri6QuXG4gIFwiY2xhdWRlLXNvbm5ldC01XCI6IGFudGhyb3BpY0Nvc3RzKDIsIDEwKSxcbn07XG5cbi8vIGdwdC01LjMtY29kZXgtc3Bhcmsg64qUIHJlc2VhcmNoIHByZXZpZXcg66GcIOqzteyLnSB0b2tlbiDri6jqsIDqsIAg7JWE7KeBIGZpbmFsIOydtCDslYTri4jri6QuXG4vLyDsp4Dsm5Ag7YOA7J6F7J2AIOycoOyngO2VmOuQmCwg6rO17IudIOuLqOqwgOqwgCDqs7XqsJzrkKAg65WM6rmM7KeAIOyVhOuemCBnZW5lcmljIGVzdGltYXRlIOuhnCDqs4TsgrDtlZzri6QuXG4vLyBAc2VlIGh0dHBzOi8vaGVscC5vcGVuYWkuY29tL2VuL2FydGljbGVzLzIwMDAxMTA2LWNvZGV4LXJhdGUtY2FyZFxuY29uc3QgREVGQVVMVF9DT1NUUzogTW9kZWxDb3N0cyA9IHsgaW5wdXRUb2tlbnM6IDMsIG91dHB1dFRva2VuczogMTUsIGNhY2hlZElucHV0VG9rZW5zOiAwLjMgfTtcblxuLyoqIENvZGV4IOuwseyXlOuTnOqwgCDsnbQg66qo64247JeQIO2XiOyaqe2VmOuKlCDstZzrjIAgZWZmb3J0LiDsubTtg4jroZzqt7jsl5Ag7JeG64qUIOuqqOuNuOydgCB4aGlnaCDquYzsp4Dri6QuICovXG5leHBvcnQgZnVuY3Rpb24gb3BlbmFpTW9kZWxNYXhFZmZvcnQobW9kZWw6IHN0cmluZyk6IE9wZW5BSUVmZm9ydCB7XG4gIHJldHVybiBPUEVOQUlfQ09TVFNbbW9kZWxdPy5tYXhFZmZvcnQgPz8gXCJ4aGlnaFwiO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TW9kZWxDb3N0cyhtb2RlbDogc3RyaW5nKTogTW9kZWxDb3N0cyB7XG4gIGNvbnN0IG5vcm1hbGl6ZWRNb2RlbCA9IChtb2RlbC5zcGxpdChcIi9cIikucG9wKCkgPz8gbW9kZWwpLnJlcGxhY2UoL1xcWzFtXFxdJC9pLCBcIlwiKTtcbiAgcmV0dXJuIE9QRU5BSV9DT1NUU1tub3JtYWxpemVkTW9kZWxdID8/IEFOVEhST1BJQ19DT1NUU1tub3JtYWxpemVkTW9kZWxdID8/IERFRkFVTFRfQ09TVFM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjYWxjdWxhdGVDb3N0VXNkKFxuICBtb2RlbDogc3RyaW5nLFxuICB1c2FnZToge1xuICAgIGlucHV0VG9rZW5zOiBudW1iZXI7XG4gICAgb3V0cHV0VG9rZW5zOiBudW1iZXI7XG4gICAgY2FjaGVkSW5wdXRUb2tlbnM/OiBudW1iZXI7XG4gICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zPzogbnVtYmVyO1xuICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczVtPzogbnVtYmVyO1xuICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczFoPzogbnVtYmVyO1xuICB9LFxuKTogbnVtYmVyIHtcbiAgY29uc3QgY29zdHMgPSBnZXRNb2RlbENvc3RzKG1vZGVsKTtcbiAgY29uc3QgY2FjaGVkSW5wdXQgPSB1c2FnZS5jYWNoZWRJbnB1dFRva2VucyA/PyAwO1xuICBjb25zdCBjYWNoZUNyZWF0aW9uSW5wdXQ1bSA9IE1hdGgubWF4KHVzYWdlLmNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczVtID8/IDAsIDApO1xuICBjb25zdCBjYWNoZUNyZWF0aW9uSW5wdXQxaCA9IE1hdGgubWF4KHVzYWdlLmNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczFoID8/IDAsIDApO1xuICBjb25zdCBjYWNoZUNyZWF0aW9uSW5wdXQgPSBNYXRoLm1heChcbiAgICB1c2FnZS5jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMgPz8gMCxcbiAgICBjYWNoZUNyZWF0aW9uSW5wdXQ1bSArIGNhY2hlQ3JlYXRpb25JbnB1dDFoLFxuICApO1xuICBjb25zdCBjbGFzc2lmaWVkQ2FjaGVDcmVhdGlvbklucHV0NW0gPSBNYXRoLm1pbihjYWNoZUNyZWF0aW9uSW5wdXQ1bSwgY2FjaGVDcmVhdGlvbklucHV0KTtcbiAgY29uc3QgY2xhc3NpZmllZENhY2hlQ3JlYXRpb25JbnB1dDFoID0gTWF0aC5taW4oXG4gICAgY2FjaGVDcmVhdGlvbklucHV0MWgsXG4gICAgY2FjaGVDcmVhdGlvbklucHV0IC0gY2xhc3NpZmllZENhY2hlQ3JlYXRpb25JbnB1dDVtLFxuICApO1xuICBjb25zdCB1bmNsYXNzaWZpZWRDYWNoZUNyZWF0aW9uSW5wdXQgPVxuICAgIGNhY2hlQ3JlYXRpb25JbnB1dCAtIGNsYXNzaWZpZWRDYWNoZUNyZWF0aW9uSW5wdXQ1bSAtIGNsYXNzaWZpZWRDYWNoZUNyZWF0aW9uSW5wdXQxaDtcbiAgY29uc3Qgbm9uQ2FjaGVkSW5wdXQgPSBNYXRoLm1heCh1c2FnZS5pbnB1dFRva2VucyAtIGNhY2hlZElucHV0IC0gY2FjaGVDcmVhdGlvbklucHV0LCAwKTtcblxuICAvLyBsb25nLWNvbnRleHQg7ZWg7KadOiDsoITssrQg7J6F66ClKGlucHV0X3Rva2VucywgY2FjaGUg7Y+s7ZWoKeydtCB0aHJlc2hvbGQg7LSI6rO8IOyLnCDsmpTssq0g7KCE7LK07JeQIOuwsOycqCDsoIHsmqlcbiAgY29uc3QgbGMgPSBjb3N0cy5sb25nQ29udGV4dDtcbiAgY29uc3QgaXNMb25nQ29udGV4dCA9IGxjICE9PSB1bmRlZmluZWQgJiYgdXNhZ2UuaW5wdXRUb2tlbnMgPiBsYy50aHJlc2hvbGQ7XG4gIGNvbnN0IGlucHV0UmF0ZSA9IGNvc3RzLmlucHV0VG9rZW5zICogKGlzTG9uZ0NvbnRleHQgPyBsYy5pbnB1dE11bHRpcGxpZXIgOiAxKTtcbiAgY29uc3QgY2FjaGVkUmF0ZSA9IGNvc3RzLmNhY2hlZElucHV0VG9rZW5zICogKGlzTG9uZ0NvbnRleHQgPyBsYy5jYWNoZWRJbnB1dE11bHRpcGxpZXIgOiAxKTtcbiAgY29uc3QgY2FjaGVDcmVhdGlvbkZhbGxiYWNrUmF0ZSA9XG4gICAgKGNvc3RzLmNhY2hlQ3JlYXRpb25JbnB1dFRva2VucyA/PyBjb3N0cy5pbnB1dFRva2VucykgKlxuICAgIChpc0xvbmdDb250ZXh0ID8gbGMuaW5wdXRNdWx0aXBsaWVyIDogMSk7XG4gIGNvbnN0IGNhY2hlQ3JlYXRpb241bVJhdGUgPVxuICAgIChjb3N0cy5jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM1bSA/PyBjb3N0cy5jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMgPz8gY29zdHMuaW5wdXRUb2tlbnMpICpcbiAgICAoaXNMb25nQ29udGV4dCA/IGxjLmlucHV0TXVsdGlwbGllciA6IDEpO1xuICBjb25zdCBjYWNoZUNyZWF0aW9uMWhSYXRlID1cbiAgICAoY29zdHMuY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zMWggPz8gY29zdHMuY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zID8/IGNvc3RzLmlucHV0VG9rZW5zKSAqXG4gICAgKGlzTG9uZ0NvbnRleHQgPyBsYy5pbnB1dE11bHRpcGxpZXIgOiAxKTtcbiAgY29uc3Qgb3V0cHV0UmF0ZSA9IGNvc3RzLm91dHB1dFRva2VucyAqIChpc0xvbmdDb250ZXh0ID8gbGMub3V0cHV0TXVsdGlwbGllciA6IDEpO1xuXG4gIHJldHVybiAoXG4gICAgKG5vbkNhY2hlZElucHV0IC8gMV8wMDBfMDAwKSAqIGlucHV0UmF0ZSArXG4gICAgKHVzYWdlLm91dHB1dFRva2VucyAvIDFfMDAwXzAwMCkgKiBvdXRwdXRSYXRlICtcbiAgICAoY2FjaGVkSW5wdXQgLyAxXzAwMF8wMDApICogY2FjaGVkUmF0ZSArXG4gICAgKHVuY2xhc3NpZmllZENhY2hlQ3JlYXRpb25JbnB1dCAvIDFfMDAwXzAwMCkgKiBjYWNoZUNyZWF0aW9uRmFsbGJhY2tSYXRlICtcbiAgICAoY2xhc3NpZmllZENhY2hlQ3JlYXRpb25JbnB1dDVtIC8gMV8wMDBfMDAwKSAqIGNhY2hlQ3JlYXRpb241bVJhdGUgK1xuICAgIChjbGFzc2lmaWVkQ2FjaGVDcmVhdGlvbklucHV0MWggLyAxXzAwMF8wMDApICogY2FjaGVDcmVhdGlvbjFoUmF0ZVxuICApO1xufVxuIl0sIm1hcHBpbmdzIjoiO0FBMENBLE1BQU0sb0JBQTREO0NBQ2hFLFdBQVc7Q0FDWCxpQkFBaUI7Q0FDakIsdUJBQXVCO0NBQ3ZCLGtCQUFrQjtBQUNwQjtBQU9BLE1BQU0sZUFBZ0Q7Q0FLcEQsZUFBZTtFQUNiLFdBQVc7RUFDWCxhQUFhO0VBQ2IsY0FBYztFQUNkLG1CQUFtQjtFQUNuQiwwQkFBMEI7RUFDMUIsYUFBYTtDQUNmO0NBUUEsZUFBZTtFQUNiLFdBQVc7RUFDWCxhQUFhO0VBQ2IsY0FBYztFQUNkLG1CQUFtQjtFQUNuQiwwQkFBMEI7RUFDMUIsYUFBYTtDQUNmO0NBQ0EsaUJBQWlCO0VBQ2YsV0FBVztFQUNYLGFBQWE7RUFDYixjQUFjO0VBQ2QsbUJBQW1CO0VBQ25CLDBCQUEwQjtFQUMxQixhQUFhO0NBQ2Y7Q0FDQSxnQkFBZ0I7RUFDZCxXQUFXO0VBQ1gsYUFB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
@@ -1336,6 +1336,26 @@ describe("QgridFrame.usage", () => {
1336
1336
  getRateLimitsByTokenIdMock.mockReset();
1337
1337
  });
1338
1338
 
1339
+ it("does not fetch usage for confirmed expired tokens", async () => {
1340
+ findManyMock.mockResolvedValueOnce({
1341
+ rows: [{ ...tokenEntry, provider: "openai", active: false, reauth_required: true }],
1342
+ });
1343
+ await expect(QgridFrame.usage(1)).resolves.toEqual({ error: "re-login required" });
1344
+ expect(getRateLimitsByTokenIdMock).not.toHaveBeenCalled();
1345
+ });
1346
+
1347
+ it("does not label transient refresh failures as expired sessions", async () => {
1348
+ findManyMock.mockResolvedValueOnce({
1349
+ rows: [{ ...tokenEntry, provider: "anthropic", credentials: {
1350
+ accessToken: "access", refreshToken: "refresh", expiresAt: 0, accountUuid: "account",
1351
+ } }],
1352
+ });
1353
+ vi.spyOn(QgridFrame, "refreshToken").mockRejectedValueOnce(new Error("network timeout"));
1354
+ await expect(QgridFrame.usage(1)).resolves.toEqual({
1355
+ error: "Token refresh failed; usage is unavailable",
1356
+ });
1357
+ });
1358
+
1339
1359
  it("returns empty usage for inactive OpenAI tokens without asking for workers", async () => {
1340
1360
  findManyMock.mockResolvedValueOnce({
1341
1361
  rows: [
@@ -716,6 +716,7 @@ class QgridFrameClass extends BaseFrameClass {
716
716
  : allTokens.findLast((e) => e.active && e.provider === "anthropic");
717
717
 
718
718
  if (!entry) return { error: "NOT_FOUND" };
719
+ if (entry.reauth_required) return { error: "re-login required" };
719
720
 
720
721
  if (entry.provider === "openai") {
721
722
  if (!entry.active) {
@@ -759,7 +760,7 @@ class QgridFrameClass extends BaseFrameClass {
759
760
  accessToken = await this.refreshToken(entry);
760
761
  } catch (e) {
761
762
  oauthLogger.warn(`refresh failed for ${entry.name}: ${(e as Error).message}`);
762
- return { error: "re-login required" };
763
+ return { error: "Token refresh failed; usage is unavailable" };
763
764
  }
764
765
  }
765
766
 
@@ -772,7 +773,7 @@ class QgridFrameClass extends BaseFrameClass {
772
773
  return convertAnthropicUsage(retried);
773
774
  } catch (e) {
774
775
  oauthLogger.warn(`refresh failed for ${entry.name}: ${(e as Error).message}`);
775
- return { error: "re-login required" };
776
+ return { error: "Token refresh failed; usage is unavailable" };
776
777
  }
777
778
  }
778
779
  if (raw.error) return { error: raw.error };
@@ -39,7 +39,7 @@ describe("deactivateAuthDeadToken", () => {
39
39
  it("deactivates and notifies when the failed attempt used the current refresh token", async () => {
40
40
  deactivateMock.mockResolvedValue({
41
41
  marked: true,
42
- keptAsLastActive: false,
42
+ wasLastActive: false,
43
43
  staleCredentials: false,
44
44
  });
45
45
 
@@ -60,7 +60,7 @@ describe("deactivateAuthDeadToken", () => {
60
60
  it("skips deactivation when credentials rotated since the failed attempt", async () => {
61
61
  deactivateMock.mockResolvedValue({
62
62
  marked: false,
63
- keptAsLastActive: false,
63
+ wasLastActive: false,
64
64
  staleCredentials: true,
65
65
  });
66
66
 
@@ -73,7 +73,7 @@ describe("deactivateAuthDeadToken", () => {
73
73
  it("does not notify when another process won the deactivation race", async () => {
74
74
  deactivateMock.mockResolvedValue({
75
75
  marked: false,
76
- keptAsLastActive: false,
76
+ wasLastActive: false,
77
77
  staleCredentials: false,
78
78
  });
79
79
 
@@ -82,18 +82,19 @@ describe("deactivateAuthDeadToken", () => {
82
82
  expect(notifySlackMock).not.toHaveBeenCalled();
83
83
  });
84
84
 
85
- it("alerts instead of deactivating when the dying token is the last active one", async () => {
85
+ it("deactivates the last active token and sends an urgent expiry alert", async () => {
86
86
  deactivateMock.mockResolvedValue({
87
87
  marked: true,
88
- keptAsLastActive: true,
88
+ wasLastActive: true,
89
89
  staleCredentials: false,
90
90
  });
91
91
 
92
- await expect(deactivateAuthDeadToken(token, "anthropic:400")).resolves.toBe(false);
92
+ await expect(deactivateAuthDeadToken(token, "anthropic:400")).resolves.toBe(true);
93
93
 
94
94
  expect(notifySlackMock).toHaveBeenCalledTimes(1);
95
95
  const notification = notifySlackMock.mock.calls[0]![0] as { title: string; context: string };
96
- expect(notification.title).toContain("마지막");
96
+ expect(notification.title).toBe("세션 만료");
97
+ expect(notifySlackMock.mock.calls[0]![0]).toMatchObject({ urgent: true });
97
98
  expect(notification.context).toContain("anthropic:400");
98
99
  });
99
100
 
@@ -101,12 +102,12 @@ describe("deactivateAuthDeadToken", () => {
101
102
  deactivateMock
102
103
  .mockResolvedValueOnce({
103
104
  marked: true,
104
- keptAsLastActive: true,
105
+ wasLastActive: true,
105
106
  staleCredentials: false,
106
107
  })
107
108
  .mockResolvedValue({
108
109
  marked: false,
109
- keptAsLastActive: false,
110
+ wasLastActive: false,
110
111
  staleCredentials: false,
111
112
  });
112
113
 
@@ -120,7 +121,7 @@ describe("deactivateAuthDeadToken", () => {
120
121
  it("never puts the raw provider error body in the notification", async () => {
121
122
  deactivateMock.mockResolvedValue({
122
123
  marked: true,
123
- keptAsLastActive: false,
124
+ wasLastActive: false,
124
125
  staleCredentials: false,
125
126
  });
126
127
 
@@ -24,7 +24,7 @@ export async function deactivateAuthDeadToken(
24
24
  token: DeadTokenRef,
25
25
  reasonCode: string,
26
26
  ): Promise<boolean> {
27
- const { marked, keptAsLastActive, staleCredentials } = await TokenModel.markReauthRequired(
27
+ const { marked, wasLastActive, staleCredentials } = await TokenModel.markReauthRequired(
28
28
  token.id,
29
29
  token.credentials,
30
30
  );
@@ -35,10 +35,6 @@ export async function deactivateAuthDeadToken(
35
35
  return false;
36
36
  }
37
37
  if (!marked) return false;
38
- if (keptAsLastActive) {
39
- notifyLastActiveTokenDying(token, reasonCode);
40
- return false;
41
- }
42
38
 
43
39
  logger.warn(`token requires re-login: ${token.name}(id=${token.id}) reason=${reasonCode}`);
44
40
  // 만료 직후가 재로그인하기 가장 좋은 타이밍이다. 소유자를 멘션해 그 순간 당사자에게
@@ -47,29 +43,21 @@ export async function deactivateAuthDeadToken(
47
43
  void notifySlack({
48
44
  title: "세션 만료",
49
45
  subject: token.name,
50
- context: [mention, token.provider, reasonCode, "재로그인이 필요합니다"]
46
+ context: [
47
+ mention,
48
+ token.provider,
49
+ reasonCode,
50
+ "재로그인이 필요합니다",
51
+ wasLastActive ? "사용 가능한 토큰이 없습니다" : null,
52
+ ]
51
53
  .filter(Boolean)
52
54
  .join(" · "),
53
55
  color: SLACK_COLOR.bad,
56
+ urgent: wasLastActive,
54
57
  });
55
58
  return true;
56
59
  }
57
60
 
58
- function notifyLastActiveTokenDying(token: DeadTokenRef, reasonCode: string): void {
59
- const mention = mentionFor(token.name, getSlackUserMap());
60
- void notifySlack({
61
- title: "마지막 토큰 사망",
62
- subject: token.name,
63
- context:
64
- [mention, token.provider, reasonCode].filter(Boolean).join(" · ") +
65
- ` · 풀이 비지 않도록 유지 중입니다. ` +
66
- `전 토큰이 동시에 실패했다면 client_id 취소나 OAuth 계약 변경을 의심하세요`,
67
- color: SLACK_COLOR.bad,
68
- // provider 전체가 죽었다는 신호다. 조용 시간에 묻히면 다음 근무일까지 서비스가 멈춘다.
69
- urgent: true,
70
- });
71
- }
72
-
73
61
  /** 로그인이 완료돼 토큰이 저장됐을 때. 신규·재로그인을 가리지 않는다. */
74
62
  export function notifyTokenAdded(name: string, provider: string): void {
75
63
  logger.info(`token added: ${name} (${provider})`);
@@ -2,15 +2,17 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
2
2
 
3
3
  import { TokenSubscriber } from "./token-subscriber";
4
4
 
5
- const { findOneMock, findActiveMock } = vi.hoisted(() => ({
5
+ const { findOneMock, findActiveMock, deactivateExpiredTokensMock } = vi.hoisted(() => ({
6
6
  findOneMock: vi.fn(),
7
7
  findActiveMock: vi.fn(),
8
+ deactivateExpiredTokensMock: vi.fn(),
8
9
  }));
9
10
 
10
11
  vi.mock("../token/token.model", () => ({
11
12
  TokenModel: {
12
13
  findOne: findOneMock,
13
14
  findActive: findActiveMock,
15
+ deactivateExpiredTokens: deactivateExpiredTokensMock,
14
16
  },
15
17
  }));
16
18
 
@@ -264,6 +266,8 @@ describe("TokenSubscriber OpenAI notifications", () => {
264
266
 
265
267
  await subscriber.reconcile();
266
268
 
269
+ expect(deactivateExpiredTokensMock).toHaveBeenCalled();
270
+
267
271
  expect(anthropicDispatcher.replaceTokens).toHaveBeenCalledWith([
268
272
  expect.objectContaining({ id: 1, quotaThreshold: 80, weight: 4 }),
269
273
  ]);
@@ -271,6 +271,7 @@ export class TokenSubscriber {
271
271
  .map((row) => row.id),
272
272
  )
273
273
  : null;
274
+ await TokenModel.deactivateExpiredTokens();
274
275
  const rows = await TokenModel.findActive("A");
275
276
  this.dispatcher.replaceCache(rows);
276
277
  // NOTIFY 유실 대비: AnthropicDispatcher 풀도 DB active anthropic 토큰 기준으로 재동기화.
@@ -213,7 +213,25 @@ describe("TokenModel.markReauthRequired", () => {
213
213
  await Sonamu.initForTesting();
214
214
  });
215
215
 
216
- it("serializes provider deaths, preserves one active token, and rejects stale credentials", async () => {
216
+ it("repairs legacy active expired tokens without changing healthy or manually inactive tokens", async () => {
217
+ const ids = await TokenModel.save([
218
+ { ...baseToken, name: "legacy-expired", active: true, reauth_required: true },
219
+ { ...baseToken, name: "healthy", active: true, reauth_required: false },
220
+ { ...baseToken, name: "manual-inactive", active: false, reauth_required: false },
221
+ ]);
222
+ try {
223
+ await TokenModel.deactivateExpiredTokens();
224
+ await TokenModel.deactivateExpiredTokens();
225
+ const { rows } = await TokenModel.findMany("A", { id: ids, num: 3 });
226
+ expect(rows.find((row) => row.id === ids[0])).toMatchObject({ active: false, reauth_required: true });
227
+ expect(rows.find((row) => row.id === ids[1])).toMatchObject({ active: true, reauth_required: false });
228
+ expect(rows.find((row) => row.id === ids[2])).toMatchObject({ active: false, reauth_required: false });
229
+ } finally {
230
+ await TokenModel.del(ids);
231
+ }
232
+ });
233
+
234
+ it("deactivates every expired token and rejects stale credentials", async () => {
217
235
  const suffix = randomUUID();
218
236
  const tokens = [
219
237
  {
@@ -237,7 +255,7 @@ describe("TokenModel.markReauthRequired", () => {
237
255
  }),
238
256
  ).resolves.toEqual({
239
257
  marked: false,
240
- keptAsLastActive: false,
258
+ wasLastActive: false,
241
259
  staleCredentials: true,
242
260
  });
243
261
 
@@ -246,16 +264,17 @@ describe("TokenModel.markReauthRequired", () => {
246
264
  TokenModel.markReauthRequired(ids[1]!, tokens[1]!.credentials),
247
265
  ]);
248
266
  expect(results.every((result) => result.marked)).toBe(true);
267
+ expect(results.filter((result) => result.wasLastActive)).toHaveLength(1);
249
268
 
250
269
  const { rows } = await TokenModel.findMany("A", { id: ids, num: 2 });
251
270
  expect(rows.every((row) => row.reauth_required)).toBe(true);
252
- expect(rows.filter((row) => row.active)).toHaveLength(1);
271
+ expect(rows.filter((row) => row.active)).toHaveLength(0);
253
272
 
254
273
  await expect(
255
274
  TokenModel.markReauthRequired(ids[0]!, tokens[0]!.credentials),
256
275
  ).resolves.toEqual({
257
276
  marked: false,
258
- keptAsLastActive: false,
277
+ wasLastActive: false,
259
278
  staleCredentials: false,
260
279
  });
261
280
 
@@ -278,7 +297,7 @@ describe("TokenModel.markReauthRequired", () => {
278
297
  TokenModel.markReauthRequired(inactive.id, inactive.credentials),
279
298
  ).resolves.toEqual({
280
299
  marked: false,
281
- keptAsLastActive: false,
300
+ wasLastActive: false,
282
301
  staleCredentials: true,
283
302
  });
284
303