sliftutils 1.1.4 → 1.1.40

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 (53) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.cursor/rules/api-calls.mdc +16 -0
  3. package/.cursor/rules/coding-styles.mdc +50 -0
  4. package/.cursor/rules/components.mdc +44 -0
  5. package/.cursor/rules/disk-collection.mdc +31 -0
  6. package/.cursor/rules/general-guidelines.mdc +11 -0
  7. package/.cursor/rules/mobx-state.mdc +33 -0
  8. package/.cursor/rules/styling-css.mdc +99 -0
  9. package/CLAUDE.md +211 -0
  10. package/builders/hotReload.ts +23 -20
  11. package/builders/setup.ts +2 -2
  12. package/dist/test.ts.cache +13 -0
  13. package/index.d.ts +166 -14
  14. package/misc/apiKeys.d.ts +1 -0
  15. package/misc/apiKeys.tsx +7 -3
  16. package/misc/dist/apiKeys.tsx.cache +145 -0
  17. package/misc/dist/openrouter.ts.cache +119 -0
  18. package/misc/dist/yaml.ts.cache +45 -0
  19. package/misc/dist/yamlBase.ts.cache +2406 -0
  20. package/misc/https/httpsCerts.d.ts +17 -0
  21. package/misc/https/httpsCerts.ts +4 -4
  22. package/misc/openrouter.d.ts +1 -0
  23. package/misc/openrouter.ts +32 -4
  24. package/misc/zip.d.ts +2 -12
  25. package/misc/zip.ts +2 -97
  26. package/package.json +4 -3
  27. package/render-utils/InputLabel.d.ts +1 -2
  28. package/render-utils/InputLabel.tsx +1 -1
  29. package/render-utils/autoMeasure.d.ts +1 -0
  30. package/render-utils/autoMeasure.ts +43 -0
  31. package/render-utils/dist/Input.tsx.cache +319 -0
  32. package/render-utils/dist/InputLabel.tsx.cache +220 -0
  33. package/render-utils/dist/modal.tsx.cache +69 -0
  34. package/render-utils/dist/observer.tsx.cache +6 -3
  35. package/render-utils/modal.tsx +1 -1
  36. package/storage/DiskCollection.d.ts +17 -0
  37. package/storage/DiskCollection.ts +57 -5
  38. package/storage/FileFolderAPI.d.ts +3 -0
  39. package/storage/FileFolderAPI.tsx +104 -36
  40. package/storage/IStorage.d.ts +4 -0
  41. package/storage/IStorage.ts +3 -0
  42. package/storage/IndexedDBFileFolderAPI.ts +6 -0
  43. package/storage/PrivateFileSystemStorage.d.ts +4 -0
  44. package/storage/PrivateFileSystemStorage.ts +11 -0
  45. package/storage/StorageObservable.d.ts +4 -0
  46. package/storage/StorageObservable.ts +27 -2
  47. package/storage/StorageObservableAsync.d.ts +2 -0
  48. package/storage/StorageObservableAsync.ts +20 -0
  49. package/storage/backblaze.d.ts +97 -0
  50. package/storage/backblaze.ts +915 -0
  51. package/test.ts +10 -0
  52. package/yarn.lock +139 -4
  53. package/.cursorrules +0 -251
package/index.d.ts CHANGED
@@ -14,6 +14,7 @@ declare module "sliftutils/misc/apiKeys" {
14
14
  getAllKeys(): string[];
15
15
  get(key: string): Promise<string> | undefined;
16
16
  };
17
+ export declare function setAPIKey(key: string, value: string): void;
17
18
  export declare class ManageAPIKeys extends preact.Component {
18
19
  render(): string;
19
20
  }
@@ -155,6 +156,11 @@ declare module "sliftutils/misc/https/dns" {
155
156
  }
156
157
 
157
158
  declare module "sliftutils/misc/https/httpsCerts" {
159
+ /// <reference path="node-forge-ed25519.d.ts" />
160
+ /// <reference path="../../storage/storage.d.ts" />
161
+ /// <reference types="node" />
162
+ /// <reference types="node" />
163
+ import * as forge from "node-forge";
158
164
  /** NOTE: We also generate the domain *.domain */
159
165
  export declare const getHTTPSCert: {
160
166
  (key: string): Promise<{
@@ -173,6 +179,18 @@ declare module "sliftutils/misc/https/httpsCerts" {
173
179
  cert: string;
174
180
  }> | undefined;
175
181
  };
182
+ export declare const getAccountKey: (domain: string) => Promise<string>;
183
+ export declare function parseCert(PEMorDER: string | Buffer): forge.pki.Certificate;
184
+ export declare function normalizeCertToPEM(PEMorDER: string | Buffer): string;
185
+ export declare function generateCert(config: {
186
+ accountKey: string;
187
+ domain: string;
188
+ altDomains?: string[];
189
+ }): Promise<{
190
+ domains: string[];
191
+ key: string;
192
+ cert: string;
193
+ }>;
176
194
 
177
195
  }
178
196
 
@@ -228,6 +246,7 @@ declare module "sliftutils/misc/openrouter" {
228
246
  }[];
229
247
  export declare function getTotalCost(): number;
230
248
  type OpenRouterOptions = {
249
+ apiKey?: string;
231
250
  provider?: {
232
251
  sort?: "throughput" | "price" | "latency";
233
252
  order?: string[];
@@ -291,18 +310,8 @@ declare module "sliftutils/misc/yamlBase" {
291
310
  }
292
311
 
293
312
  declare module "sliftutils/misc/zip" {
294
- /// <reference types="node" />
295
- /// <reference types="node" />
296
- import { MaybePromise } from "socket-function/src/types";
297
- export declare class Zip {
298
- static gzip(buffer: Buffer, level?: number): Promise<Buffer>;
299
- static gunzip(buffer: Buffer): MaybePromise<Buffer>;
300
- static gunzipAsyncBase(buffer: Buffer): Promise<Buffer>;
301
- static gunzipUntracked(buffer: Buffer): Promise<Buffer>;
302
- static gunzipSync(buffer: Buffer): Buffer;
303
- private static gunzipUntrackedSync;
304
- static gunzipBatch(buffers: Buffer[]): Promise<Buffer[]>;
305
- }
313
+ import { Zip } from "socket-function/src/Zip";
314
+ export { Zip };
306
315
 
307
316
  }
308
317
 
@@ -452,7 +461,7 @@ declare module "sliftutils/render-utils/Input" {
452
461
 
453
462
  declare module "sliftutils/render-utils/InputLabel" {
454
463
  import preact from "preact";
455
- type InputProps = (preact.JSX.HTMLAttributes<HTMLInputElement> & {
464
+ export type InputProps = (preact.JSX.HTMLAttributes<HTMLInputElement> & {
456
465
  /** ONLY throttles onChangeValue */
457
466
  throttle?: number;
458
467
  flavor?: "large" | "small" | "none";
@@ -512,7 +521,6 @@ declare module "sliftutils/render-utils/InputLabel" {
512
521
  }> {
513
522
  render(): preact.JSX.Element;
514
523
  }
515
- export {};
516
524
 
517
525
  }
518
526
 
@@ -690,6 +698,11 @@ declare module "sliftutils/render-utils/asyncObservable" {
690
698
 
691
699
  }
692
700
 
701
+ declare module "sliftutils/render-utils/autoMeasure" {
702
+ export declare function runAutoMeasure(): void;
703
+
704
+ }
705
+
693
706
  declare module "sliftutils/render-utils/colors" {
694
707
  export declare const redButton: string;
695
708
  export declare const yellowButton: string;
@@ -802,6 +815,8 @@ declare module "sliftutils/storage/DiskCollection" {
802
815
  export declare class DiskCollection<T> implements IStorageSync<T> {
803
816
  private collectionName;
804
817
  private config?;
818
+ static getForceNoPrompt(): boolean;
819
+ static setForceNoPrompt(forceNoPrompt: boolean): void;
805
820
  constructor(collectionName: string, config?: {
806
821
  writeDelay?: number | undefined;
807
822
  cbor?: boolean | undefined;
@@ -863,6 +878,21 @@ declare module "sliftutils/storage/DiskCollection" {
863
878
  } | undefined>;
864
879
  reset(): Promise<void>;
865
880
  }
881
+ export declare class DiskCollectionRawSynced {
882
+ private collectionName;
883
+ constructor(collectionName: string);
884
+ initStorage(): Promise<IStorage<Buffer>>;
885
+ private synced;
886
+ get(key: string): Buffer | undefined;
887
+ getPromise(key: string): Promise<Buffer | undefined>;
888
+ set(key: string, value: Buffer): void;
889
+ getKeys(): Promise<string[]>;
890
+ getInfo(key: string): Promise<{
891
+ size: number;
892
+ lastModified: number;
893
+ } | undefined>;
894
+ reset(): Promise<void>;
895
+ }
866
896
  export declare class DiskCollectionRawBrowser {
867
897
  private collectionName;
868
898
  constructor(collectionName: string);
@@ -918,6 +948,9 @@ declare module "sliftutils/storage/FileFolderAPI" {
918
948
  size: number;
919
949
  lastModified: number;
920
950
  arrayBuffer(): Promise<ArrayBuffer>;
951
+ slice(start: number, end: number): {
952
+ arrayBuffer(): Promise<ArrayBuffer>;
953
+ };
921
954
  }>;
922
955
  createWritable(config?: {
923
956
  keepExistingData?: boolean;
@@ -1015,6 +1048,10 @@ declare module "sliftutils/storage/IStorage" {
1015
1048
  };
1016
1049
  export type IStorageRaw = {
1017
1050
  get(key: string): Promise<Buffer | undefined>;
1051
+ getRange(key: string, config: {
1052
+ start: number;
1053
+ end: number;
1054
+ }): Promise<Buffer | undefined>;
1018
1055
  append(key: string, value: Buffer): Promise<void>;
1019
1056
  set(key: string, value: Buffer): Promise<void>;
1020
1057
  remove(key: string): Promise<void>;
@@ -1106,6 +1143,10 @@ declare module "sliftutils/storage/PrivateFileSystemStorage" {
1106
1143
  private getFileHandle;
1107
1144
  private fileExists;
1108
1145
  get(key: string): Promise<Buffer | undefined>;
1146
+ getRange(key: string, config: {
1147
+ start: number;
1148
+ end: number;
1149
+ }): Promise<Buffer | undefined>;
1109
1150
  set(key: string, value: Buffer): Promise<void>;
1110
1151
  append(key: string, value: Buffer): Promise<void>;
1111
1152
  remove(key: string): Promise<void>;
@@ -1121,6 +1162,9 @@ declare module "sliftutils/storage/PrivateFileSystemStorage" {
1121
1162
 
1122
1163
  declare module "sliftutils/storage/StorageObservable" {
1123
1164
  import { IStorage, IStorageSync } from "./IStorage";
1165
+ export declare const storagePendingAccesses: {
1166
+ value: number;
1167
+ };
1124
1168
  export declare class StorageSync<T> implements IStorageSync<T> {
1125
1169
  storage: IStorage<T>;
1126
1170
  private config?;
@@ -1160,6 +1204,13 @@ declare module "sliftutils/storage/StorageObservable" {
1160
1204
  reloadKey(key: string): void;
1161
1205
  reset(): Promise<void>;
1162
1206
  }
1207
+ export declare function waitUntilNextLoad(): Promise<void>;
1208
+
1209
+ }
1210
+
1211
+ declare module "sliftutils/storage/StorageObservableAsync" {
1212
+ /** Reruns the code until all StorageSyncs accessed have loaded their values. Not efficient,although will usually be O(values accessed), just due to how loading works (it won't be quadratic). */
1213
+ export declare function rerunCodeUntilAllLoaded<T>(code: () => T): Promise<T>;
1163
1214
 
1164
1215
  }
1165
1216
 
@@ -1219,6 +1270,107 @@ declare module "sliftutils/storage/TransactionStorage" {
1219
1270
 
1220
1271
  }
1221
1272
 
1273
+ declare module "sliftutils/storage/backblaze" {
1274
+ /// <reference types="node" />
1275
+ /// <reference types="node" />
1276
+ export declare class ArchivesBackblaze {
1277
+ private config;
1278
+ constructor(config: {
1279
+ bucketName: string;
1280
+ public?: boolean;
1281
+ immutable?: boolean;
1282
+ cacheTime?: number;
1283
+ });
1284
+ private bucketName;
1285
+ private bucketId;
1286
+ private logging;
1287
+ enableLogging(): void;
1288
+ private log;
1289
+ getDebugName(): string;
1290
+ private getBucketAPI;
1291
+ private last503Reset;
1292
+ private apiRetryLogic;
1293
+ get(fileName: string, config?: {
1294
+ range?: {
1295
+ start: number;
1296
+ end: number;
1297
+ };
1298
+ retryCount?: number;
1299
+ }): Promise<Buffer | undefined>;
1300
+ set(fileName: string, data: Buffer): Promise<void>;
1301
+ del(fileName: string): Promise<void>;
1302
+ setLargeFile(config: {
1303
+ path: string;
1304
+ getNextData(): Promise<Buffer | undefined>;
1305
+ }): Promise<void>;
1306
+ getInfo(fileName: string): Promise<{
1307
+ writeTime: number;
1308
+ size: number;
1309
+ } | undefined>;
1310
+ find(prefix: string, config?: {
1311
+ shallow?: boolean;
1312
+ type: "files" | "folders";
1313
+ }): Promise<string[]>;
1314
+ findInfo(prefix: string, config?: {
1315
+ shallow?: boolean;
1316
+ type: "files" | "folders";
1317
+ }): Promise<{
1318
+ path: string;
1319
+ createTime: number;
1320
+ size: number;
1321
+ }[]>;
1322
+ assertPathValid(path: string): Promise<void>;
1323
+ getURL(path: string): Promise<string>;
1324
+ getDownloadAuthorization(config: {
1325
+ fileNamePrefix?: string;
1326
+ validDurationInSeconds: number;
1327
+ b2ContentDisposition?: string;
1328
+ b2ContentLanguage?: string;
1329
+ b2Expires?: string;
1330
+ b2CacheControl?: string;
1331
+ b2ContentEncoding?: string;
1332
+ b2ContentType?: string;
1333
+ }): Promise<{
1334
+ bucketId: string;
1335
+ fileNamePrefix: string;
1336
+ authorizationToken: string;
1337
+ }>;
1338
+ }
1339
+ export declare const getArchivesBackblaze: {
1340
+ (key: string): ArchivesBackblaze;
1341
+ clear(key: string): void;
1342
+ clearAll(): void;
1343
+ forceSet(key: string, value: ArchivesBackblaze): void;
1344
+ getAllKeys(): string[];
1345
+ get(key: string): ArchivesBackblaze | undefined;
1346
+ };
1347
+ export declare const getArchivesBackblazePrivateImmutable: {
1348
+ (key: string): ArchivesBackblaze;
1349
+ clear(key: string): void;
1350
+ clearAll(): void;
1351
+ forceSet(key: string, value: ArchivesBackblaze): void;
1352
+ getAllKeys(): string[];
1353
+ get(key: string): ArchivesBackblaze | undefined;
1354
+ };
1355
+ export declare const getArchivesBackblazePublicImmutable: {
1356
+ (key: string): ArchivesBackblaze;
1357
+ clear(key: string): void;
1358
+ clearAll(): void;
1359
+ forceSet(key: string, value: ArchivesBackblaze): void;
1360
+ getAllKeys(): string[];
1361
+ get(key: string): ArchivesBackblaze | undefined;
1362
+ };
1363
+ export declare const getArchivesBackblazePublic: {
1364
+ (key: string): ArchivesBackblaze;
1365
+ clear(key: string): void;
1366
+ clearAll(): void;
1367
+ forceSet(key: string, value: ArchivesBackblaze): void;
1368
+ getAllKeys(): string[];
1369
+ get(key: string): ArchivesBackblaze | undefined;
1370
+ };
1371
+
1372
+ }
1373
+
1222
1374
  declare module "sliftutils/storage/fileSystemPointer" {
1223
1375
  export type FileSystemPointer = string;
1224
1376
  export declare function storeFileSystemPointer(config: {
package/misc/apiKeys.d.ts CHANGED
@@ -10,6 +10,7 @@ export declare const getAPIKey: {
10
10
  getAllKeys(): string[];
11
11
  get(key: string): Promise<string> | undefined;
12
12
  };
13
+ export declare function setAPIKey(key: string, value: string): void;
13
14
  export declare class ManageAPIKeys extends preact.Component {
14
15
  render(): string;
15
16
  }
package/misc/apiKeys.tsx CHANGED
@@ -128,15 +128,19 @@ export const getAPIKey = cache(async function getAPIKey(key: string): Promise<st
128
128
  try {
129
129
  let value = await promise;
130
130
 
131
- getStorage().setItem(keyKey, value);
132
- state.keys.push(key);
133
- getStorage().setItem(getStorageKey("__keys"), JSON.stringify(state.keys));
131
+ setAPIKey(key, value);
134
132
  return value;
135
133
  } finally {
136
134
  obj.close();
137
135
  }
138
136
  });
139
137
 
138
+ export function setAPIKey(key: string, value: string) {
139
+ getStorage().setItem(getStorageKey(key), value);
140
+ state.keys.push(key);
141
+ getStorage().setItem(getStorageKey("__keys"), JSON.stringify(state.keys));
142
+ }
143
+
140
144
  @observer
141
145
  export class ManageAPIKeys extends preact.Component {
142
146
  render() {
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
12
+ //exports.ManageAPIKeys = exports.setAPIKey = exports.getAPIKey = exports.APIKeysControl = void 0;
13
+ const preact_1 = __importDefault(require("preact"));
14
+ const caching_1 = require("socket-function/src/caching");
15
+ const typesafecss_1 = require("typesafecss");
16
+ const fs_1 = __importDefault(require("fs"));
17
+ const os_1 = __importDefault(require("os"));
18
+ const mobx_1 = require("mobx");
19
+ const InputLabel_1 = require("../render-utils/InputLabel");
20
+ const modal_1 = require("../render-utils/modal");
21
+ const observer_1 = require("../render-utils/observer");
22
+ let DirectoryPrompter = class DirectoryPrompter extends preact_1.default.Component {
23
+ constructor() {
24
+ super(...arguments);
25
+ this.synced = (0, mobx_1.observable)({
26
+ value: "",
27
+ });
28
+ }
29
+ render() {
30
+ const { valueKey, onDone } = this.props;
31
+ const { value } = this.synced;
32
+ return (preact_1.default.createElement("div", { className: typesafecss_1.css.position("fixed").pos(0, 0).size("100vw", "100vh")
33
+ .zIndex(1)
34
+ .hsla(0, 0, 20, 0.5)
35
+ .center
36
+ .fontSize(40) },
37
+ preact_1.default.createElement(InputLabel_1.InputLabel, { label: valueKey, value: value, onChangeValue: value => this.synced.value = value }),
38
+ preact_1.default.createElement("button", { onClick: () => onDone(value) }, "Done")));
39
+ }
40
+ };
41
+ DirectoryPrompter = __decorate([
42
+ observer_1.observer
43
+ ], DirectoryPrompter);
44
+ function getStorageKey(key) {
45
+ if ((0, typesafecss_1.isNode)())
46
+ return os_1.default.homedir() + "/" + key;
47
+ return `apiKeys.ts_${key}`;
48
+ }
49
+ let state = (0, mobx_1.observable)({
50
+ keys: [],
51
+ });
52
+ if (!(0, typesafecss_1.isNode)()) {
53
+ try {
54
+ let newKeys = JSON.parse(localStorage.getItem(getStorageKey("__keys")));
55
+ if (Array.isArray(newKeys)) {
56
+ state.keys = newKeys;
57
+ }
58
+ }
59
+ catch (_a) { }
60
+ }
61
+ let APIKeysControl = class APIKeysControl extends preact_1.default.Component {
62
+ render() {
63
+ return (preact_1.default.createElement("label", { className: typesafecss_1.css.hbox(4) },
64
+ preact_1.default.createElement("span", null, "Keys:"),
65
+ preact_1.default.createElement("select", null, state.keys.map(key => preact_1.default.createElement("option", null, key))),
66
+ preact_1.default.createElement("button", { onClick: () => {
67
+ let key = state.keys[0];
68
+ state.keys = state.keys.filter(k => k !== key);
69
+ localStorage.setItem(getStorageKey("__keys"), JSON.stringify(state.keys));
70
+ localStorage.removeItem(getStorageKey(key));
71
+ } }, "Delete")));
72
+ }
73
+ };
74
+ exports.APIKeysControl = APIKeysControl;
75
+ exports.APIKeysControl = APIKeysControl = __decorate([
76
+ observer_1.observer
77
+ ], APIKeysControl);
78
+ let getStorage = (0, caching_1.lazy)(() => {
79
+ if (!(0, typesafecss_1.isNode)())
80
+ return localStorage;
81
+ return {
82
+ getItem: (key) => {
83
+ if (!fs_1.default.existsSync(key))
84
+ return null;
85
+ return fs_1.default.readFileSync(key, "utf-8");
86
+ },
87
+ setItem: (key, value) => {
88
+ fs_1.default.writeFileSync(key, value);
89
+ },
90
+ };
91
+ });
92
+ exports.getAPIKey = (0, caching_1.cache)(async function getAPIKey(key) {
93
+ let innerKey = "key";
94
+ if ((0, typesafecss_1.isNode)()) {
95
+ if (key.includes(".json.")) {
96
+ let [baseKey, innerKeyPart] = key.split(".json.");
97
+ baseKey += ".json";
98
+ innerKey = innerKeyPart;
99
+ key = baseKey;
100
+ }
101
+ }
102
+ let keyKey = getStorageKey(key);
103
+ let localStorageValue = getStorage().getItem(keyKey);
104
+ if (localStorageValue === null || localStorageValue === void 0 ? void 0 : localStorageValue.startsWith("{")) {
105
+ try {
106
+ localStorageValue = JSON.parse(localStorageValue)[innerKey];
107
+ }
108
+ catch (_a) { }
109
+ }
110
+ if (localStorageValue) {
111
+ return localStorageValue;
112
+ }
113
+ if ((0, typesafecss_1.isNode)())
114
+ throw new Error(`Add an api key to ${keyKey}`);
115
+ let onDone = (value) => { };
116
+ let promise = new Promise(resolve => {
117
+ onDone = resolve;
118
+ });
119
+ let obj = (0, modal_1.showModal)({ contents: preact_1.default.createElement(DirectoryPrompter, { valueKey: key, onDone: onDone }) });
120
+ try {
121
+ let value = await promise;
122
+ setAPIKey(key, value);
123
+ return value;
124
+ }
125
+ finally {
126
+ obj.close();
127
+ }
128
+ });
129
+ function setAPIKey(key, value) {
130
+ getStorage().setItem(getStorageKey(key), value);
131
+ state.keys.push(key);
132
+ getStorage().setItem(getStorageKey("__keys"), JSON.stringify(state.keys));
133
+ }
134
+ exports.setAPIKey = setAPIKey;
135
+ let ManageAPIKeys = class ManageAPIKeys extends preact_1.default.Component {
136
+ render() {
137
+ return "ManageAPIKeys";
138
+ }
139
+ };
140
+ exports.ManageAPIKeys = ManageAPIKeys;
141
+ exports.ManageAPIKeys = ManageAPIKeys = __decorate([
142
+ observer_1.observer
143
+ ], ManageAPIKeys);
144
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpS2V5cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImFwaUtleXMudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUFBLG9EQUE0QjtBQUM1Qix5REFBMEQ7QUFDMUQsNkNBQTBDO0FBQzFDLDRDQUFvQjtBQUNwQiw0Q0FBb0I7QUFDcEIsK0JBQWtDO0FBQ2xDLDJEQUF3RDtBQUN4RCxpREFBa0Q7QUFDbEQsdURBQW9EO0FBR3BELElBQU0saUJBQWlCLEdBQXZCLE1BQU0saUJBQWtCLFNBQVEsZ0JBQU0sQ0FBQyxTQUdyQztJQUhGOztRQUlJLFdBQU0sR0FBRyxJQUFBLGlCQUFVLEVBQUM7WUFDaEIsS0FBSyxFQUFFLEVBQUU7U0FDWixDQUFDLENBQUM7SUF1QlAsQ0FBQztJQXRCRyxNQUFNO1FBQ0YsTUFBTSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQ3hDLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBQzlCLE9BQU8sQ0FDSCx3Q0FBSyxTQUFTLEVBQ1YsaUJBQUcsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQztpQkFDakQsTUFBTSxDQUFDLENBQUMsQ0FBQztpQkFDVCxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFDO2lCQUNuQixNQUFNO2lCQUNOLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFFakIsK0JBQUMsdUJBQVUsSUFDUCxLQUFLLEVBQUUsUUFBUSxFQUNmLEtBQUssRUFBRSxLQUFLLEVBQ1osYUFBYSxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEdBQUcsS0FBSyxHQUNuRDtZQUNGLDJDQUFRLE9BQU8sRUFBRSxH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QUFJLEdBQUcsR0FBRyxJQUFBLGlCQUFTLEVBQUMsRUFBRSxRQUFRLEVBQUUsK0JBQUMsaUJBQWlCLElBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSxHQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3hGLElBQUksQ0FBQztRQUNELElBQUksS0FBSyxHQUFHLE1BQU0sT0FBTyxDQUFDO1FBRTFCLFNBQVMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdEIsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztZQUFTLENBQUM7UUFDUCxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDaEIsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDO0FBRUgsU0FBZ0IsU0FBUyxDQUFDLEdBQVcsRUFBRSxLQUFhO0lBQ2hELFVBQVUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEQsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDckIsVUFBVSxFQUFFLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQzlFLENBQUM7QUFKRCw4QkFJQztBQUdNLElBQU0sYUFBYSxHQUFuQixNQUFNLGFBQWMsU0FBUSxnQkFBTSxDQUFDLFNBQVM7SUFDL0MsTUFBTTtRQUNGLE9BQU8sZUFBZSxDQUFDO0lBQzNCLENBQUM7Q0FDSixDQUFBO0FBSlksc0NBQWE7d0JBQWIsYUFBYTtJQUR6QixtQkFBUTtHQUNJLGFBQWEsQ0FJekIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcHJlYWN0IGZyb20gXCJwcmVhY3RcIjtcbmltcG9ydCB7IGNhY2hlLCBsYXp5IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvY2FjaGluZ1wiO1xuaW1wb3J0IHsgY3NzLCBpc05vZGUgfSBmcm9tIFwidHlwZXNhZmVjc3NcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCBvcyBmcm9tIFwib3NcIjtcbmltcG9ydCB7IG9ic2VydmFibGUgfSBmcm9tIFwibW9ieFwiO1xuaW1wb3J0IHsgSW5wdXRMYWJlbCB9IGZyb20gXCIuLi9yZW5kZXItdXRpbHMvSW5wdXRMYWJlbFwiO1xuaW1wb3J0IHsgc2hvd01vZGFsIH0gZnJvbSBcIi4uL3JlbmRlci11dGlscy9tb2RhbFwiO1xuaW1wb3J0IHsgb2JzZXJ2ZXIgfSBmcm9tIFwiLi4vcmVuZGVyLXV0aWxzL29ic2VydmVyXCI7XG5cbkBvYnNlcnZlclxuY2xhc3MgRGlyZWN0b3J5UHJvbXB0ZXIgZXh0ZW5kcyBwcmVhY3QuQ29tcG9uZW50PHtcbiAgICB2YWx1ZUtleTogc3RyaW5nO1xuICAgIG9uRG9uZTogKHZhbHVlOiBzdHJpbmcpID0+IHZvaWQ7XG59PiB7XG4gICAgc3luY2VkID0gb2JzZXJ2YWJsZSh7XG4gICAgICAgIHZhbHVlOiBcIlwiLFxuICAgIH0pO1xuICAgIHJlbmRlcigpIHtcbiAgICAgICAgY29uc3QgeyB2YWx1ZUtleSwgb25Eb25lIH0gPSB0aGlzLnByb3BzO1xuICAgICAgICBjb25zdCB7IHZhbHVlIH0gPSB0aGlzLnN5bmNlZDtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPXtcbiAgICAgICAgICAgICAgICBjc3MucG9zaXRpb24oXCJmaXhlZFwiKS5wb3MoMCwgMCkuc2l6ZShcIjEwMHZ3XCIsIFwiMTAwdmhcIilcbiAgICAgICAgICAgICAgICAgICAgLnpJbmRleCgxKVxuICAgICAgICAgICAgICAgICAgICAuaHNsYSgwLCAwLCAyMCwgMC41KVxuICAgICAgICAgICAgICAgICAgICAuY2VudGVyXG4gICAgICAgICAgICAgICAgICAgIC5mb250U2l6ZSg0MClcbiAgICAgICAgICAgIH0+XG4gICAgICAgICAgICAgICAgPElucHV0TGFiZWxcbiAgICAgICAgICAgICAgICAgICAgbGFiZWw9e3ZhbHVlS2V5fVxuICAgICAgICAgICAgICAgICAgICB2YWx1ZT17dmFsdWV9XG4gICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlVmFsdWU9e3ZhbHVlID0+IHRoaXMuc3luY2VkLnZhbHVlID0gdmFsdWV9XG4gICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICA8YnV0dG9uIG9uQ2xpY2s9eygpID0+IG9uRG9uZSh2YWx1ZSl9PlxuICAgICAgICAgICAgICAgICAgICBEb25lXG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgKTtcbiAgICB9XG59XG5cblxuZnVuY3Rpb24gZ2V0U3RvcmFnZUtleShrZXk6IHN0cmluZykge1xuICAgIGlmIChpc05vZGUoKSkgcmV0dXJuIG9zLmhvbWVkaXIoKSArIFwiL1wiICsga2V5O1xuICAgIHJldHVybiBgYXBpS2V5cy50c18ke2tleX1gO1xufVxuXG5sZXQgc3RhdGUgPSBvYnNlcnZhYmxlKHtcbiAgICBrZXlzOiBbXSBhcyBzdHJpbmdbXSxcbn0pO1xuaWYgKCFpc05vZGUoKSkge1xuICAgIHRyeSB7XG4gICAgICAgIGxldCBuZXdLZXlzID0gSlNPTi5wYXJzZShsb2NhbFN0b3JhZ2UuZ2V0SXRlbShnZXRTdG9yYWdlS2V5KFwiX19rZXlzXCIpKSEpO1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShuZXdLZXlzKSkge1xuICAgICAgICAgICAgc3RhdGUua2V5cyA9IG5ld0tleXM7XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIHsgfVxufVxuXG5Ab2JzZXJ2ZXJcbmV4cG9ydCBjbGFzcyBBUElLZXlzQ29udHJvbCBleHRlbmRzIHByZWFjdC5Db21wb25lbnQge1xuICAgIHJlbmRlcigpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxsYWJlbCBjbGFzc05hbWU9e2Nzcy5oYm94KDQpfT5cbiAgICAgICAgICAgICAgICA8c3Bhbj5LZXlzOjwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8c2VsZWN0PlxuICAgICAgICAgICAgICAgICAgICB7c3RhdGUua2V5cy5tYXAoa2V5ID0+XG4gICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uPntrZXl9PC9vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICl9XG4gICAgICAgICAgICAgICAgPC9zZWxlY3Q+XG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBvbkNsaWNrPXsoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBrZXkgPSBzdGF0ZS5rZXlzWzBdO1xuICAgICAgICAgICAgICAgICAgICBzdGF0ZS5rZXlzID0gc3RhdGUua2V5cy5maWx0ZXIoayA9PiBrICE9PSBrZXkpO1xuICAgICAgICAgICAgICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShnZXRTdG9yYWdlS2V5KFwiX19rZXlzXCIpLCBKU09OLnN0cmluZ2lmeShzdGF0ZS5rZXlzKSk7XG4gICAgICAgICAgICAgICAgICAgIGxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKGdldFN0b3JhZ2VLZXkoa2V5KSk7XG4gICAgICAgICAgICAgICAgfX0+XG4gICAgICAgICAgICAgICAgICAgIERlbGV0ZVxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgKTtcbiAgICB9XG59XG5cbmxldCBnZXRTdG9yYWdlID0gbGF6eSgoKToge1xuICAgIGdldEl0ZW06IChrZXk6IHN0cmluZykgPT4gc3RyaW5nIHwgbnVsbDtcbiAgICBzZXRJdGVtOiAoa2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpID0+IHZvaWQ7XG59ID0+IHtcbiAgICBpZiAoIWlzTm9kZSgpKSByZXR1cm4gbG9jYWxTdG9yYWdlO1xuICAgIHJldHVybiB7XG4gICAgICAgIGdldEl0ZW06IChrZXkpID0+IHtcbiAgICAgICAgICAgIGlmICghZnMuZXhpc3RzU3luYyhrZXkpKSByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIHJldHVybiBmcy5yZWFkRmlsZVN5bmMoa2V5LCBcInV0Zi04XCIpO1xuICAgICAgICB9LFxuICAgICAgICBzZXRJdGVtOiAoa2V5LCB2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgZnMud3JpdGVGaWxlU3luYyhrZXksIHZhbHVlKTtcbiAgICAgICAgfSxcbiAgICB9O1xufSk7XG5cbmV4cG9ydCBjb25zdCBnZXRBUElLZXkgPSBjYWNoZShhc3luYyBmdW5jdGlvbiBnZXRBUElLZXkoa2V5OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGxldCBpbm5lcktleSA9IFwia2V5XCI7XG4gICAgaWYgKGlzTm9kZSgpKSB7XG4gICAgICAgIGlmIChrZXkuaW5jbHVkZXMoXCIuanNvbi5cIikpIHtcbiAgICAgICAgICAgIGxldCBbYmFzZUtleSwgaW5uZXJLZXlQYXJ0XSA9IGtleS5zcGxpdChcIi5qc29uLlwiKTtcbiAgICAgICAgICAgIGJhc2VLZXkgKz0gXCIuanNvblwiO1xuICAgICAgICAgICAgaW5uZXJLZXkgPSBpbm5lcktleVBhcnQ7XG4gICAgICAgICAgICBrZXkgPSBiYXNlS2V5O1xuICAgICAgICB9XG4gICAgfVxuICAgIGxldCBrZXlLZXkgPSBnZXRTdG9yYWdlS2V5KGtleSk7XG4gICAgbGV0IGxvY2FsU3RvcmFnZVZhbHVlID0gZ2V0U3RvcmFnZSgpLmdldEl0ZW0oa2V5S2V5KTtcbiAgICBpZiAobG9jYWxTdG9yYWdlVmFsdWU/LnN0YXJ0c1dpdGgoXCJ7XCIpKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsb2NhbFN0b3JhZ2VWYWx1ZSA9IEpTT04ucGFyc2UobG9jYWxTdG9yYWdlVmFsdWUpW2lubmVyS2V5XTtcbiAgICAgICAgfSBjYXRjaCB7IH1cbiAgICB9XG4gICAgaWYgKGxvY2FsU3RvcmFnZVZhbHVlKSB7XG4gICAgICAgIHJldHVybiBsb2NhbFN0b3JhZ2VWYWx1ZTtcbiAgICB9XG4gICAgaWYgKGlzTm9kZSgpKSB0aHJvdyBuZXcgRXJyb3IoYEFkZCBhbiBhcGkga2V5IHRvICR7a2V5S2V5fWApO1xuXG4gICAgbGV0IG9uRG9uZSA9ICh2YWx1ZTogc3RyaW5nKSA9PiB7IH07XG4gICAgbGV0IHByb21pc2UgPSBuZXcgUHJvbWlzZTxzdHJpbmc+KHJlc29sdmUgPT4ge1xuICAgICAgICBvbkRvbmUgPSByZXNvbHZlO1xuICAgIH0pO1xuICAgIGxldCBvYmogPSBzaG93TW9kYWwoeyBjb250ZW50czogPERpcmVjdG9yeVByb21wdGVyIHZhbHVlS2V5PXtrZXl9IG9uRG9uZT17b25Eb25lfSAvPiB9KTtcbiAgICB0cnkge1xuICAgICAgICBsZXQgdmFsdWUgPSBhd2FpdCBwcm9taXNlO1xuXG4gICAgICAgIHNldEFQSUtleShrZXksIHZhbHVlKTtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0gZmluYWxseSB7XG4gICAgICAgIG9iai5jbG9zZSgpO1xuICAgIH1cbn0pO1xuXG5leHBvcnQgZnVuY3Rpb24gc2V0QVBJS2V5KGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSB7XG4gICAgZ2V0U3RvcmFnZSgpLnNldEl0ZW0oZ2V0U3RvcmFnZUtleShrZXkpLCB2YWx1ZSk7XG4gICAgc3RhdGUua2V5cy5wdXNoKGtleSk7XG4gICAgZ2V0U3RvcmFnZSgpLnNldEl0ZW0oZ2V0U3RvcmFnZUtleShcIl9fa2V5c1wiKSwgSlNPTi5zdHJpbmdpZnkoc3RhdGUua2V5cykpO1xufVxuXG5Ab2JzZXJ2ZXJcbmV4cG9ydCBjbGFzcyBNYW5hZ2VBUElLZXlzIGV4dGVuZHMgcHJlYWN0LkNvbXBvbmVudCB7XG4gICAgcmVuZGVyKCkge1xuICAgICAgICByZXR1cm4gXCJNYW5hZ2VBUElLZXlzXCI7XG4gICAgfVxufSJdfQ==
145
+ /* _JS_SOURCE_HASH = "d6ef02866d39c57a55ce88d8e6b03ddc399584de91fdd66b6aab0198cbab4c70"; */
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
3
+ //exports.openRouterCallBase = exports.openRouterCall = exports.simpleAICallTyped = exports.simpleAICall = exports.yamlOpenRouterCall = exports.getTotalCost = void 0;
4
+ const yaml_1 = require("./yaml");
5
+ const batching_1 = require("socket-function/src/batching");
6
+ const format_1 = require("socket-function/src/formatting/format");
7
+ const apiKeys_1 = require("./apiKeys");
8
+ let totalCost = 0;
9
+ function getTotalCost() {
10
+ return totalCost;
11
+ }
12
+ exports.getTotalCost = getTotalCost;
13
+ /** IMPORTANT! Make sure to tell the AI to return yaml. */
14
+ async function yamlOpenRouterCall(config) {
15
+ var _a;
16
+ let { model, messages, retries = 3, options, onCost } = config;
17
+ try {
18
+ let response = await openRouterCall({ model, messages, options, onCost, retries: 0 });
19
+ let result = (0, yaml_1.parseYAML)(response);
20
+ (_a = config.validate) === null || _a === void 0 ? void 0 : _a.call(config, result);
21
+ return result;
22
+ }
23
+ catch (error) {
24
+ if (retries > 0) {
25
+ return yamlOpenRouterCall({ model, messages, retries: retries - 1, onCost });
26
+ }
27
+ throw error;
28
+ }
29
+ }
30
+ exports.yamlOpenRouterCall = yamlOpenRouterCall;
31
+ async function simpleAICall(model, message) {
32
+ return await openRouterCallBase({
33
+ model,
34
+ messages: [{ role: "user", content: message }],
35
+ });
36
+ }
37
+ exports.simpleAICall = simpleAICall;
38
+ /** The message must request the result to be returned in YAML (we automatically parse this and return an object). */
39
+ async function simpleAICallTyped(model, message) {
40
+ return await yamlOpenRouterCall({
41
+ model,
42
+ messages: [{ role: "user", content: message }],
43
+ });
44
+ }
45
+ exports.simpleAICallTyped = simpleAICallTyped;
46
+ let pendingLog = undefined;
47
+ async function openRouterCall(config) {
48
+ return await openRouterCallBase(config);
49
+ }
50
+ exports.openRouterCall = openRouterCall;
51
+ async function openRouterCallBase(config) {
52
+ let { model, messages, options, onCost } = config;
53
+ let openrouterKey = (options === null || options === void 0 ? void 0 : options.apiKey) || await (0, apiKeys_1.getAPIKey)("openrouter.json");
54
+ console.log(`Calling ${model} with ${messages.length} messages`);
55
+ let time = Date.now();
56
+ let stillRunning = true;
57
+ // Spawn monitoring loop
58
+ void (async () => {
59
+ while (stillRunning) {
60
+ await new Promise(resolve => setTimeout(resolve, 5000));
61
+ if (stillRunning) {
62
+ console.log("OpenRouter call still running...");
63
+ }
64
+ }
65
+ })();
66
+ try {
67
+ return await (0, batching_1.retryFunctional)(async () => {
68
+ let response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
69
+ method: "POST",
70
+ headers: {
71
+ "Authorization": `Bearer ${openrouterKey}`,
72
+ "Content-Type": "application/json",
73
+ },
74
+ body: JSON.stringify({
75
+ model,
76
+ messages,
77
+ provider: {
78
+ sort: "throughput",
79
+ },
80
+ usage: { include: true },
81
+ ...options,
82
+ }),
83
+ });
84
+ // If it failed, throw
85
+ if (response.status !== 200) {
86
+ let responseText = await response.text();
87
+ throw new Error(`Failed to call OpenRouter: ${response.status} ${response.statusText} ${responseText}`);
88
+ }
89
+ let responseObj = await response.json();
90
+ let newCost = responseObj.usage.cost;
91
+ totalCost += newCost;
92
+ onCost === null || onCost === void 0 ? void 0 : onCost(newCost);
93
+ if (!pendingLog) {
94
+ pendingLog = {
95
+ count: 0,
96
+ duration: 0,
97
+ cost: 0,
98
+ };
99
+ setTimeout(() => {
100
+ let log = pendingLog;
101
+ if (!log)
102
+ return;
103
+ console.log(`Ran: ${log.count} calls at a total summed cost of ${(0, format_1.formatNumber)(1 / log.cost)}/USD`);
104
+ pendingLog = undefined;
105
+ }, 10000);
106
+ }
107
+ pendingLog.count++;
108
+ pendingLog.duration += Date.now() - time;
109
+ pendingLog.cost += newCost;
110
+ return responseObj.choices[0].message.content;
111
+ }, { maxRetries: config.retries || 3 })();
112
+ }
113
+ finally {
114
+ stillRunning = false;
115
+ }
116
+ }
117
+ exports.openRouterCallBase = openRouterCallBase;
118
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbnJvdXRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm9wZW5yb3V0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsaUNBQW1DO0FBQ25DLDJEQUErRDtBQUMvRCxrRUFBcUU7QUFDckUsdUNBQXNDO0FBZ0J0QyxJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUM7QUFDbEIsU0FBZ0IsWUFBWTtJQUN4QixPQUFPLFNBQVMsQ0FBQztBQUNyQixDQUFDO0FBRkQsb0NBRUM7QUFXRCwwREFBMEQ7QUFDbkQsS0FBSyxVQUFVLGtCQUFrQixDQUFJLE1BTzNDOztJQUNHLElBQUksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE9BQU8sR0FBRyxDQUFDLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQztJQUMvRCxJQUFJLENBQUM7UUFDRCxJQUFJLFFBQVEsR0FBRyxNQUFNLGNBQWMsQ0FBQyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN0RixJQUFJLE1BQU0sR0FBRyxJQUFBLGdCQUFTLEVBQUMsUUFBUSxDQUFNLENBQUM7UUFDdEMsTUFBQSxNQUFNLENBQUMsUUFBUSx1REFBRyxNQUFNLENBQUMsQ0FBQztRQUMxQixPQUFPLE1BQU0sQ0FBQztJQUNsQixDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNiLElBQUksT0FBTyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ2QsT0FBTyxrQkFBa0IsQ0FBSSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE9BQU8sR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUNwRixDQUFDO1FBQ0QsTUFBTSxLQUFLLENBQUM7SUFDaEIsQ0FBQztBQUNMLENBQUM7QUFwQkQsZ0RBb0JDO0FBRU0sS0FBSyxVQUFVLFlBQVksQ0FBQyxLQUFhLEVBQUUsT0FBZTtJQUM3RCxPQUFPLE1BQU0sa0JBQWtCLENBQUM7UUFDNUIsS0FBSztRQUNMLFFBQVEsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUM7S0FDakQsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQUxELG9DQUtDO0FBQ0QscUhBQXFIO0FBQzlHLEtBQUssVUFBVSxpQkFBaUIsQ0FBSSxLQUFhLEVBQUUsT0FBZTtJQUNyRSxPQUFPLE1BQU0sa0JBQWtCLENBQUM7UUFDNUIsS0FBSztRQUNMLFFBQVEsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUM7S0FDakQsQ0FBTSxDQUFDO0FBQ1osQ0FBQztBQUxELDhDQUtDO0FBRUQsSUFBSSxVQUFVLEdBSUUsU0FBUyxDQUFDO0FBRW5CLEtBQUssVUFBVSxjQUFjLENBQUMsTUFNcEM7SUFDRyxPQUFPLE1BQU0sa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDNUMsQ0FBQztBQVJELHdDQVFDO0FBRU0sS0FBSyxVQUFVLGtCQUFrQixDQUFDLE1BTXhDO0lBQ0csSUFBSSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQztJQUNsRCxJQUFJLGFBQWEsR0FBRyxDQUFBLE9BQU8sYUFBUCxPQUFPLHVCQUFQLE9BQU8sQ0FBRSxNQUFNLEtBQUksTUFBTSxJQUFBLG1CQUFTLEVBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUMxRSxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsS0FBSyxTQUFTLFFBQVEsQ0FBQyxNQUFNLFdBQVcsQ0FBQyxDQUFDO0lBQ2pFLElBQUksSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUN0QixJQUFJLFlBQVksR0FBRyxJQUFJLENBQUM7SUFFeEIsd0JBQXdCO0lBQ3hCLEtBQUssQ0FBQyxLQUFLLElBQUksRUFBRTtRQUNiLE9BQU8sWUFBWSxFQUFFLENBQUM7WUFDbEIsTUFBTSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUN4RCxJQUFJLFlBQVksRUFBRSxDQUFDO2dCQUNmLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0NBQWtDLENBQUMsQ0FBQztZQUNwRCxDQUFDO1FBQ0wsQ0FBQztJQUNMLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFFTCxJQUFJLENBQUM7UUFDRCxPQUFPLE1BQU0sSUFBQSwwQkFBZSxFQUFDLEtBQUssSUFBSSxFQUFFO1lBQ3BDLElBQUksUUFBUSxHQUFHLE1BQU0sS0FBSyxDQUFDLCtDQUErQyxFQUFFO2dCQUN4RSxNQUFNLEVBQUUsTUFBTTtnQkFDZCxPQUFPLEVBQUU7b0JBQ0wsZUFBZSxFQUFFLFVBQVUsYUFBYSxFQUFFO29CQUMxQyxjQUFjLEVBQUUsa0JBQWtCO2lCQUNyQztnQkFDRCxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQztvQkFDakIsS0FBSztvQkFDTCxRQUFRO29CQUNSLFFBQVEsRUFBRTt3QkFDTixJQUFJLEVBQUUsWUFBWTtxQkFDckI7b0JBQ0QsS0FBSyxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRTtvQkFDeEIsR0FBRyxPQUFPO2lCQUNiLENBQUM7YUFDTCxDQUFDLENBQUM7WUFFSCxzQkFBc0I7WUFDdEIsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDO2dCQUMxQixJQUFJLFlBQVksR0FBRyxNQUFNLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDekMsTUFBTSxJQUFJLEtBQUssQ0FBQyw4QkFBOEIsUUFBUSxDQUFDLE1BQU0sSUFBSSxRQUFRLENBQUMsVUFBVSxJQUFJLFlBQVksRUFBRSxDQUFDLENBQUM7WUFDNUcsQ0FBQztZQUNELElBQUksV0FBVyxHQUFHLE1BQU0sUUFBUSxDQUFDLElBQUksRUFTcEMsQ0FBQztZQUNGLElBQUksT0FBTyxHQUFHLFdBQVcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDO1lBQ3JDLFNBQVMsSUFBSSxPQUFPLENBQUM7WUFDckIsTUFBTSxhQUFOLE1BQU0sdUJBQU4sTUFBTSxDQUFHLE9BQU8sQ0FBQyxDQUFDO1lBQ2xCLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDZCxVQUFVLEdBQUc7b0JBQ1QsS0FBSyxFQUFFLENBQUM7b0JBQ1IsUUFBUSxFQUFFLENBQUM7b0JBQ1gsSUFBSSxFQUFFLENBQUM7aUJBQ1YsQ0FBQztnQkFDRixVQUFVLENBQUMsR0FBRyxFQUFFO29CQUNaLElBQUksR0FBRyxHQUFHLFVBQVUsQ0FBQztvQkFDckIsSUFBSSxDQUFDLEdBQUc7d0JBQUUsT0FBTztvQkFDakIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxLQUFLLG9DQUFvQyxJQUFBLHFCQUFZLEVBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7b0JBQ25HLFVBQVUsR0FBRyxTQUFTLENBQUM7Z0JBQzNCLENBQUMsRUFBRSxLQUFNLENBQUMsQ0FBQztZQUNmLENBQUM7WUFDRCxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbkIsVUFBVSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO1lBQ3pDLFVBQVUsQ0FBQyxJQUFJLElBQUksT0FBTyxDQUFDO1lBQzNCLE9BQU8sV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBaUIsQ0FBQztRQUM1RCxDQUFDLEVBQUUsRUFBRSxVQUFVLEVBQUUsTUFBTSxDQUFDLE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7SUFDOUMsQ0FBQztZQUFTLENBQUM7UUFDUCxZQUFZLEdBQUcsS0FBSyxDQUFDO0lBQ3pCLENBQUM7QUFDTCxDQUFDO0FBakZELGdEQWlGQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHBhcnNlWUFNTCB9IGZyb20gXCIuL3lhbWxcIjtcbmltcG9ydCB7IHJldHJ5RnVuY3Rpb25hbCB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL2JhdGNoaW5nXCI7XG5pbXBvcnQgeyBmb3JtYXROdW1iZXIgfSBmcm9tIFwic29ja2V0LWZ1bmN0aW9uL3NyYy9mb3JtYXR0aW5nL2Zvcm1hdFwiO1xuaW1wb3J0IHsgZ2V0QVBJS2V5IH0gZnJvbSBcIi4vYXBpS2V5c1wiO1xuXG5leHBvcnQgdHlwZSBNZXNzYWdlSGlzdG9yeSA9IHtcbiAgICByb2xlOiBcInN5c3RlbVwiIHwgXCJ1c2VyXCIgfCBcImFzc2lzdGFudFwiO1xuICAgIGNvbnRlbnQ6IHN0cmluZztcbn1bXTtcbmV4cG9ydCB0eXBlIE1lc3NhZ2VIaXN0b3J5MiA9IHtcbiAgICByb2xlOiBcInN5c3RlbVwiIHwgXCJ1c2VyXCIgfCBcImFzc2lzdGFudFwiO1xuICAgIGNvbnRlbnQ6IHN0cmluZyB8IHtcbiAgICAgICAgdHlwZTogXCJpbWFnZV91cmxcIjtcbiAgICAgICAgaW1hZ2VfdXJsOiB7XG4gICAgICAgICAgICB1cmw6IHN0cmluZztcbiAgICAgICAgfTtcbiAgICB9W107XG59W107XG5cbmxldCB0b3RhbENvc3QgPSAwO1xuZXhwb3J0IGZ1bmN0aW9uIGdldFRvdGFsQ29zdCgpIHtcbiAgICByZXR1cm4gdG90YWxDb3N0O1xufVxudHlwZSBPcGVuUm91dGVyT3B0aW9ucyA9IHtcbiAgICAvLyBJZiBub3QgcHJvdmlkZWQsIHdlJ2xsIHBvcCB1cCBhIG1vZGFsIHRvIGFzayB0aGUgdXNlciBmb3IgaXQsIE9yLCBpZiB3ZSdyZSBvbiB0aGUgc2VydmVyLCB3ZSdsbCB0cnkgdG8gcmVhZCBpdCBmcm9tIHRoZSB1c2VyIGZvbGRlci5cbiAgICBhcGlLZXk/OiBzdHJpbmc7XG4gICAgcHJvdmlkZXI/OiB7XG4gICAgICAgIHNvcnQ/OiBcInRocm91Z2hwdXRcIiB8IFwicHJpY2VcIiB8IFwibGF0ZW5jeVwiLFxuICAgICAgICAvLyBodHRwczovL29wZW5yb3V0ZXIuYWkvZG9jcy9mZWF0dXJlcy9wcm92aWRlci1yb3V0aW5nI29yZGVyaW5nLXNwZWNpZmljLXByb3ZpZGVyc1xuICAgICAgICBvcmRlcj86IHN0cmluZ1tdLFxuICAgIH1cbiAgICByZWFzb25pbmdFZmZvcnQ/OiBcImxvd1wiIHwgXCJtZWRpdW1cIiB8IFwiaGlnaFwiLFxufTtcbi8qKiBJTVBPUlRBTlQhIE1ha2Ugc3VyZSB0byB0ZWxsIHRoZSBBSSB0byByZXR1cm4geWFtbC4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB5YW1sT3BlblJvdXRlckNhbGw8VD4oY29uZmlnOiB7XG4gICAgbW9kZWw6IHN0cmluZztcbiAgICBtZXNzYWdlczogTWVzc2FnZUhpc3Rvcnk7XG4gICAgcmV0cmllcz86IG51bWJlcjtcbiAgICBvcHRpb25zPzogT3BlblJvdXRlck9wdGlvbnM7XG4gICAgb25Db3N0PzogKGNvc3Q6IG51bWJlcikgPT4gdm9pZDtcbiAgICB2YWxpZGF0ZT86IChyZXNwb25zZTogVCkgPT4gdm9pZDtcbn0pOiBQcm9taXNlPFQ+IHtcbiAgICBsZXQgeyBtb2RlbCwgbWVzc2FnZXMsIHJldHJpZXMgPSAzLCBvcHRpb25zLCBvbkNvc3QgfSA9IGNvbmZpZztcbiAgICB0cnkge1xuICAgICAgICBsZXQgcmVzcG9uc2UgPSBhd2FpdCBvcGVuUm91dGVyQ2FsbCh7IG1vZGVsLCBtZXNzYWdlcywgb3B0aW9ucywgb25Db3N0LCByZXRyaWVzOiAwIH0pO1xuICAgICAgICBsZXQgcmVzdWx0ID0gcGFyc2VZQU1MKHJlc3BvbnNlKSBhcyBUO1xuICAgICAgICBjb25maWcudmFsaWRhdGU/LihyZXN1bHQpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGlmIChyZXRyaWVzID4gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHlhbWxPcGVuUm91dGVyQ2FsbDxUPih7IG1vZGVsLCBtZXNzYWdlcywgcmV0cmllczogcmV0cmllcyAtIDEsIG9uQ29zdCB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzaW1wbGVBSUNhbGwobW9kZWw6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gYXdhaXQgb3BlblJvdXRlckNhbGxCYXNlKHtcbiAgICAgICAgbW9kZWwsXG4gICAgICAgIG1lc3NhZ2VzOiBbeyByb2xlOiBcInVzZXJcIiwgY29udGVudDogbWVzc2FnZSB9XSxcbiAgICB9KTtcbn1cbi8qKiBUaGUgbWVzc2FnZSBtdXN0IHJlcXVlc3QgdGhlIHJlc3VsdCB0byBiZSByZXR1cm5lZCBpbiBZQU1MICh3ZSBhdXRvbWF0aWNhbGx5IHBhcnNlIHRoaXMgYW5kIHJldHVybiBhbiBvYmplY3QpLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNpbXBsZUFJQ2FsbFR5cGVkPFQ+KG1vZGVsOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8VD4ge1xuICAgIHJldHVybiBhd2FpdCB5YW1sT3BlblJvdXRlckNhbGwoe1xuICAgICAgICBtb2RlbCxcbiAgICAgICAgbWVzc2FnZXM6IFt7IHJvbGU6IFwidXNlclwiLCBjb250ZW50OiBtZXNzYWdlIH1dLFxuICAgIH0pIGFzIFQ7XG59XG5cbmxldCBwZW5kaW5nTG9nOiB7XG4gICAgY291bnQ6IG51bWJlcjtcbiAgICBkdXJhdGlvbjogbnVtYmVyO1xuICAgIGNvc3Q6IG51bWJlcjtcbn0gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBvcGVuUm91dGVyQ2FsbChjb25maWc6IHtcbiAgICBtb2RlbDogc3RyaW5nO1xuICAgIG1lc3NhZ2VzOiBNZXNzYWdlSGlzdG9yeTtcbiAgICBvcHRpb25zPzogT3BlblJvdXRlck9wdGlvbnM7XG4gICAgb25Db3N0PzogKGNvc3Q6IG51bWJlcikgPT4gdm9pZDtcbiAgICByZXRyaWVzPzogbnVtYmVyO1xufSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIGF3YWl0IG9wZW5Sb3V0ZXJDYWxsQmFzZShjb25maWcpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gb3BlblJvdXRlckNhbGxCYXNlKGNvbmZpZzoge1xuICAgIG1vZGVsOiBzdHJpbmc7XG4gICAgbWVzc2FnZXM6IE1lc3NhZ2VIaXN0b3J5MjtcbiAgICBvcHRpb25zPzogT3BlblJvdXRlck9wdGlvbnM7XG4gICAgb25Db3N0PzogKGNvc3Q6IG51bWJlcikgPT4gdm9pZDtcbiAgICByZXRyaWVzPzogbnVtYmVyO1xufSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgbGV0IHsgbW9kZWwsIG1lc3NhZ2VzLCBvcHRpb25zLCBvbkNvc3QgfSA9IGNvbmZpZztcbiAgICBsZXQgb3BlbnJvdXRlcktleSA9IG9wdGlvbnM/LmFwaUtleSB8fCBhd2FpdCBnZXRBUElLZXkoXCJvcGVucm91dGVyLmpzb25cIik7XG4gICAgY29uc29sZS5sb2coYENhbGxpbmcgJHttb2RlbH0gd2l0aCAke21lc3NhZ2VzLmxlbmd0aH0gbWVzc2FnZXNgKTtcbiAgICBsZXQgdGltZSA9IERhdGUubm93KCk7XG4gICAgbGV0IHN0aWxsUnVubmluZyA9IHRydWU7XG5cbiAgICAvLyBTcGF3biBtb25pdG9yaW5nIGxvb3BcbiAgICB2b2lkIChhc3luYyAoKSA9PiB7XG4gICAgICAgIHdoaWxlIChzdGlsbFJ1bm5pbmcpIHtcbiAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCA1MDAwKSk7XG4gICAgICAgICAgICBpZiAoc3RpbGxSdW5uaW5nKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJPcGVuUm91dGVyIGNhbGwgc3RpbGwgcnVubmluZy4uLlwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pKCk7XG5cbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgcmV0cnlGdW5jdGlvbmFsKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGxldCByZXNwb25zZSA9IGF3YWl0IGZldGNoKFwiaHR0cHM6Ly9vcGVucm91dGVyLmFpL2FwaS92MS9jaGF0L2NvbXBsZXRpb25zXCIsIHtcbiAgICAgICAgICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgICAgICAgXCJBdXRob3JpemF0aW9uXCI6IGBCZWFyZXIgJHtvcGVucm91dGVyS2V5fWAsXG4gICAgICAgICAgICAgICAgICAgIFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICAgICBtb2RlbCxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZXMsXG4gICAgICAgICAgICAgICAgICAgIHByb3ZpZGVyOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzb3J0OiBcInRocm91Z2hwdXRcIixcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgdXNhZ2U6IHsgaW5jbHVkZTogdHJ1ZSB9LFxuICAgICAgICAgICAgICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIElmIGl0IGZhaWxlZCwgdGhyb3dcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgIT09IDIwMCkge1xuICAgICAgICAgICAgICAgIGxldCByZXNwb25zZVRleHQgPSBhd2FpdCByZXNwb25zZS50ZXh0KCk7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gY2FsbCBPcGVuUm91dGVyOiAke3Jlc3BvbnNlLnN0YXR1c30gJHtyZXNwb25zZS5zdGF0dXNUZXh0fSAke3Jlc3BvbnNlVGV4dH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCByZXNwb25zZU9iaiA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKSBhcyB7XG4gICAgICAgICAgICAgICAgdXNhZ2U6IHtcbiAgICAgICAgICAgICAgICAgICAgY29zdDogbnVtYmVyO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgY2hvaWNlczoge1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50OiBzdHJpbmc7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVtdO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGxldCBuZXdDb3N0ID0gcmVzcG9uc2VPYmoudXNhZ2UuY29zdDtcbiAgICAgICAgICAgIHRvdGFsQ29zdCArPSBuZXdDb3N0O1xuICAgICAgICAgICAgb25Db3N0Py4obmV3Q29zdCk7XG4gICAgICAgICAgICBpZiAoIXBlbmRpbmdMb2cpIHtcbiAgICAgICAgICAgICAgICBwZW5kaW5nTG9nID0ge1xuICAgICAgICAgICAgICAgICAgICBjb3VudDogMCxcbiAgICAgICAgICAgICAgICAgICAgZHVyYXRpb246IDAsXG4gICAgICAgICAgICAgICAgICAgIGNvc3Q6IDAsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGxvZyA9IHBlbmRpbmdMb2c7XG4gICAgICAgICAgICAgICAgICAgIGlmICghbG9nKSByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBSYW46ICR7bG9nLmNvdW50fSBjYWxscyBhdCBhIHRvdGFsIHN1bW1lZCBjb3N0IG9mICR7Zm9ybWF0TnVtYmVyKDEgLyBsb2cuY29zdCl9L1VTRGApO1xuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nTG9nID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH0sIDEwXzAwMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwZW5kaW5nTG9nLmNvdW50Kys7XG4gICAgICAgICAgICBwZW5kaW5nTG9nLmR1cmF0aW9uICs9IERhdGUubm93KCkgLSB0aW1lO1xuICAgICAgICAgICAgcGVuZGluZ0xvZy5jb3N0ICs9IG5ld0Nvc3Q7XG4gICAgICAgICAgICByZXR1cm4gcmVzcG9uc2VPYmouY2hvaWNlc1swXS5tZXNzYWdlLmNvbnRlbnQgYXMgc3RyaW5nO1xuICAgICAgICB9LCB7IG1heFJldHJpZXM6IGNvbmZpZy5yZXRyaWVzIHx8IDMgfSkoKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBzdGlsbFJ1bm5pbmcgPSBmYWxzZTtcbiAgICB9XG59XG4iXX0=
119
+ /* _JS_SOURCE_HASH = "29f9508fae589e294847d9f6787f804824093b8193621bf6749e0cde3607329d"; */