@meridianlabs/log-viewer 0.3.228 → 0.3.230
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +1705 -598
- package/lib/index.js.map +1 -1
- package/lib/src/app/appearance/icons.d.ts +2 -0
- package/lib/src/app/appearance/icons.d.ts.map +1 -1
- package/lib/src/app/log-list/LogsPanel.d.ts.map +1 -1
- package/lib/src/app/log-list/grid/LogListGrid.d.ts.map +1 -1
- package/lib/src/app/log-list/grid/columns/hooks.d.ts.map +1 -1
- package/lib/src/app/log-list/grid/columns/types.d.ts +1 -0
- package/lib/src/app/log-list/grid/columns/types.d.ts.map +1 -1
- package/lib/src/app/log-view/LogView.d.ts.map +1 -1
- package/lib/src/app/log-view/tabs/TaskTab.d.ts.map +1 -1
- package/lib/src/app/log-view/title-view/AutogrowText.d.ts +10 -0
- package/lib/src/app/log-view/title-view/AutogrowText.d.ts.map +1 -0
- package/lib/src/app/log-view/title-view/ChangeSummary.d.ts +9 -0
- package/lib/src/app/log-view/title-view/ChangeSummary.d.ts.map +1 -0
- package/lib/src/app/log-view/title-view/EditButton.d.ts +10 -0
- package/lib/src/app/log-view/title-view/EditButton.d.ts.map +1 -0
- package/lib/src/app/log-view/title-view/EditMetadataDialog.d.ts +47 -0
- package/lib/src/app/log-view/title-view/EditMetadataDialog.d.ts.map +1 -0
- package/lib/src/app/log-view/title-view/EditTagsDialog.d.ts +11 -0
- package/lib/src/app/log-view/title-view/EditTagsDialog.d.ts.map +1 -0
- package/lib/src/app/log-view/title-view/PrimaryBar.d.ts +1 -0
- package/lib/src/app/log-view/title-view/PrimaryBar.d.ts.map +1 -1
- package/lib/src/app/log-view/title-view/ProvenanceFields.d.ts +11 -0
- package/lib/src/app/log-view/title-view/ProvenanceFields.d.ts.map +1 -0
- package/lib/src/app/log-view/title-view/TagChip.d.ts +10 -0
- package/lib/src/app/log-view/title-view/TagChip.d.ts.map +1 -0
- package/lib/src/app/log-view/title-view/TagStrip.d.ts +40 -0
- package/lib/src/app/log-view/title-view/TagStrip.d.ts.map +1 -0
- package/lib/src/app/log-view/title-view/TagsField.d.ts +21 -0
- package/lib/src/app/log-view/title-view/TagsField.d.ts.map +1 -0
- package/lib/src/app/log-view/title-view/TitleView.d.ts +1 -0
- package/lib/src/app/log-view/title-view/TitleView.d.ts.map +1 -1
- package/lib/src/app/log-view/title-view/editErrors.d.ts +2 -0
- package/lib/src/app/log-view/title-view/editErrors.d.ts.map +1 -0
- package/lib/src/app/plan/PlanCard.d.ts.map +1 -1
- package/lib/src/app/samples/status/sampleStatus.d.ts.map +1 -1
- package/lib/src/app/samples-panel/SamplesPanel.d.ts.map +1 -1
- package/lib/src/app/shared/samples-grid/columns.d.ts.map +1 -1
- package/lib/src/client/api/client-api.d.ts.map +1 -1
- package/lib/src/client/api/types.d.ts +13 -0
- package/lib/src/client/api/types.d.ts.map +1 -1
- package/lib/src/client/api/view-server/api-view-server.d.ts.map +1 -1
- package/lib/src/client/api/view-server/request.d.ts +14 -0
- package/lib/src/client/api/view-server/request.d.ts.map +1 -1
- package/lib/src/client/api/vscode/api-vscode.d.ts.map +1 -1
- package/lib/src/client/api/vscode/jsonrpc.d.ts +2 -0
- package/lib/src/client/api/vscode/jsonrpc.d.ts.map +1 -1
- package/lib/src/client/database/service.d.ts +1 -0
- package/lib/src/client/database/service.d.ts.map +1 -1
- package/lib/src/client/remote/remoteLogFile.d.ts +21 -2
- package/lib/src/client/remote/remoteLogFile.d.ts.map +1 -1
- package/lib/src/components/Modal.d.ts +2 -0
- package/lib/src/components/Modal.d.ts.map +1 -1
- package/lib/src/index.d.ts +10 -0
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/state/clientEvents.d.ts +1 -2
- package/lib/src/state/clientEvents.d.ts.map +1 -1
- package/lib/src/state/clientEventsService.d.ts +2 -5
- package/lib/src/state/clientEventsService.d.ts.map +1 -1
- package/lib/src/state/hooks.d.ts +19 -0
- package/lib/src/state/hooks.d.ts.map +1 -1
- package/lib/src/state/sync/replicationService.d.ts +1 -0
- package/lib/src/state/sync/replicationService.d.ts.map +1 -1
- package/lib/src/utils/workQueue.d.ts +1 -0
- package/lib/src/utils/workQueue.d.ts.map +1 -1
- package/lib/styles/index.css +690 -77
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -10200,13 +10200,13 @@ var AppErrorBoundary = class extends Component {
|
|
|
10200
10200
|
}
|
|
10201
10201
|
};
|
|
10202
10202
|
var Card_module_default = {
|
|
10203
|
-
headerContainer: "
|
|
10204
|
-
headerModern: "
|
|
10205
|
-
headerIcon: "
|
|
10206
|
-
headerIconEmpty: "
|
|
10207
|
-
body: "
|
|
10208
|
-
card: "
|
|
10209
|
-
noPadding: "
|
|
10203
|
+
headerContainer: "_headerContainer_19525_1",
|
|
10204
|
+
headerModern: "_headerModern_19525_17",
|
|
10205
|
+
headerIcon: "_headerIcon_19525_24",
|
|
10206
|
+
headerIconEmpty: "_headerIconEmpty_19525_24",
|
|
10207
|
+
body: "_body_19525_28",
|
|
10208
|
+
card: "_card_19525_33",
|
|
10209
|
+
noPadding: "_noPadding_19525_40"
|
|
10210
10210
|
};
|
|
10211
10211
|
//#endregion
|
|
10212
10212
|
//#region ../../packages/react/src/components/Card.tsx
|
|
@@ -23302,7 +23302,7 @@ function toString$1(v) {
|
|
|
23302
23302
|
{ ...functions });
|
|
23303
23303
|
//#endregion
|
|
23304
23304
|
//#region ../../node_modules/.pnpm/arquero@8.0.3/node_modules/arquero/src/util/error.js
|
|
23305
|
-
function error$
|
|
23305
|
+
function error$8(message, cause) {
|
|
23306
23306
|
throw Error(message, { cause });
|
|
23307
23307
|
}
|
|
23308
23308
|
//#endregion
|
|
@@ -23347,16 +23347,16 @@ function bins(min, max, maxbins = 15, nice = true, minstep = 0, step) {
|
|
|
23347
23347
|
}
|
|
23348
23348
|
//#endregion
|
|
23349
23349
|
//#region ../../node_modules/.pnpm/arquero@8.0.3/node_modules/arquero/src/util/key-function.js
|
|
23350
|
-
function key$
|
|
23350
|
+
function key$4(value) {
|
|
23351
23351
|
const type = typeof value;
|
|
23352
|
-
return type === "string" ? `"${value}"` : type !== "object" || !value ? value : isDate(value) ? +value : isArray$2(value) || isTypedArray(value) ? `[${value.map(key$
|
|
23352
|
+
return type === "string" ? `"${value}"` : type !== "object" || !value ? value : isDate(value) ? +value : isArray$2(value) || isTypedArray(value) ? `[${value.map(key$4)}]` : isRegExp$1(value) ? value + "" : objectKey(value);
|
|
23353
23353
|
}
|
|
23354
23354
|
function objectKey(value) {
|
|
23355
23355
|
let s = "{";
|
|
23356
23356
|
let i = -1;
|
|
23357
23357
|
for (const k in value) {
|
|
23358
23358
|
if (++i > 0) s += ",";
|
|
23359
|
-
s += `"${k}":${key$
|
|
23359
|
+
s += `"${k}":${key$4(value[k])}`;
|
|
23360
23360
|
}
|
|
23361
23361
|
s += "}";
|
|
23362
23362
|
return s;
|
|
@@ -23373,7 +23373,7 @@ function distinctMap() {
|
|
|
23373
23373
|
return Array.from(map.values(), (_) => _.v);
|
|
23374
23374
|
},
|
|
23375
23375
|
increment(v) {
|
|
23376
|
-
const k = key$
|
|
23376
|
+
const k = key$4(v);
|
|
23377
23377
|
const e = map.get(k);
|
|
23378
23378
|
e ? ++e.n : map.set(k, {
|
|
23379
23379
|
v,
|
|
@@ -23381,7 +23381,7 @@ function distinctMap() {
|
|
|
23381
23381
|
});
|
|
23382
23382
|
},
|
|
23383
23383
|
decrement(v) {
|
|
23384
|
-
const k = key$
|
|
23384
|
+
const k = key$4(v);
|
|
23385
23385
|
const e = map.get(k);
|
|
23386
23386
|
e.n === 1 ? map.delete(k) : --e.n;
|
|
23387
23387
|
},
|
|
@@ -23865,7 +23865,7 @@ var windowFunctions = {
|
|
|
23865
23865
|
ntile: {
|
|
23866
23866
|
create(num) {
|
|
23867
23867
|
num = +num;
|
|
23868
|
-
if (!(num > 0)) error$
|
|
23868
|
+
if (!(num > 0)) error$8("ntile num must be greater than zero.");
|
|
23869
23869
|
const { init, value } = cume_dist.create();
|
|
23870
23870
|
return {
|
|
23871
23871
|
init,
|
|
@@ -23926,7 +23926,7 @@ var windowFunctions = {
|
|
|
23926
23926
|
nth_value: {
|
|
23927
23927
|
create(nth) {
|
|
23928
23928
|
nth = +nth;
|
|
23929
|
-
if (!(nth > 0)) error$
|
|
23929
|
+
if (!(nth > 0)) error$8("nth_value nth must be greater than zero.");
|
|
23930
23930
|
return {
|
|
23931
23931
|
init: noop,
|
|
23932
23932
|
value: (w, f) => {
|
|
@@ -27225,7 +27225,7 @@ pp$5.parseParenItem = function(item) {
|
|
|
27225
27225
|
pp$5.parseParenArrowList = function(startPos, startLoc, exprList, forInit) {
|
|
27226
27226
|
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, false, forInit);
|
|
27227
27227
|
};
|
|
27228
|
-
var empty$
|
|
27228
|
+
var empty$5 = [];
|
|
27229
27229
|
pp$5.parseNew = function() {
|
|
27230
27230
|
if (this.containsEsc) this.raiseRecoverable(this.start, "Escape sequence in keyword new");
|
|
27231
27231
|
var node = this.startNode();
|
|
@@ -27245,7 +27245,7 @@ pp$5.parseNew = function() {
|
|
|
27245
27245
|
var startPos = this.start, startLoc = this.startLoc;
|
|
27246
27246
|
node.callee = this.parseSubscripts(this.parseExprAtom(null, false, true), startPos, startLoc, true, false);
|
|
27247
27247
|
if (this.eat(types$1.parenL)) node.arguments = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false);
|
|
27248
|
-
else node.arguments = empty$
|
|
27248
|
+
else node.arguments = empty$5;
|
|
27249
27249
|
return this.finishNode(node, "NewExpression");
|
|
27250
27250
|
};
|
|
27251
27251
|
pp$5.parseTemplateElement = function(ref) {
|
|
@@ -32821,7 +32821,7 @@ function escapedSplit(str) {
|
|
|
32821
32821
|
result.push(current + str.substring(lastPos));
|
|
32822
32822
|
return result;
|
|
32823
32823
|
}
|
|
32824
|
-
function table$
|
|
32824
|
+
function table$3(state, startLine, endLine, silent) {
|
|
32825
32825
|
if (startLine + 2 > endLine) return false;
|
|
32826
32826
|
let nextLine = startLine + 1;
|
|
32827
32827
|
if (state.sCount[nextLine] < state.blkIndent) return false;
|
|
@@ -33665,7 +33665,7 @@ function paragraph(state, startLine, endLine) {
|
|
|
33665
33665
|
var _rules$1 = [
|
|
33666
33666
|
[
|
|
33667
33667
|
"table",
|
|
33668
|
-
table$
|
|
33668
|
+
table$3,
|
|
33669
33669
|
["paragraph", "reference"]
|
|
33670
33670
|
],
|
|
33671
33671
|
["code", code$5],
|
|
@@ -34177,7 +34177,7 @@ var emphasis_default = {
|
|
|
34177
34177
|
};
|
|
34178
34178
|
//#endregion
|
|
34179
34179
|
//#region ../../node_modules/.pnpm/markdown-it@14.1.1/node_modules/markdown-it/lib/rules_inline/link.mjs
|
|
34180
|
-
function link(state, silent) {
|
|
34180
|
+
function link$1(state, silent) {
|
|
34181
34181
|
let code, label, res, ref;
|
|
34182
34182
|
let href = "";
|
|
34183
34183
|
let title = "";
|
|
@@ -34548,7 +34548,7 @@ var _rules = [
|
|
|
34548
34548
|
["backticks", backtick],
|
|
34549
34549
|
["strikethrough", strikethrough_default.tokenize],
|
|
34550
34550
|
["emphasis", emphasis_default.tokenize],
|
|
34551
|
-
["link", link],
|
|
34551
|
+
["link", link$1],
|
|
34552
34552
|
["image", image$1],
|
|
34553
34553
|
["autolink", autolink],
|
|
34554
34554
|
["html_inline", html_inline],
|
|
@@ -35158,7 +35158,7 @@ var stringFromCharCode = String.fromCharCode;
|
|
|
35158
35158
|
* @param {String} type The error type.
|
|
35159
35159
|
* @returns {Error} Throws a `RangeError` with the applicable error message.
|
|
35160
35160
|
*/
|
|
35161
|
-
function error$
|
|
35161
|
+
function error$7(type) {
|
|
35162
35162
|
throw new RangeError(errors$1[type]);
|
|
35163
35163
|
}
|
|
35164
35164
|
/**
|
|
@@ -35292,26 +35292,26 @@ var decode = function(input) {
|
|
|
35292
35292
|
let basic = input.lastIndexOf(delimiter);
|
|
35293
35293
|
if (basic < 0) basic = 0;
|
|
35294
35294
|
for (let j = 0; j < basic; ++j) {
|
|
35295
|
-
if (input.charCodeAt(j) >= 128) error$
|
|
35295
|
+
if (input.charCodeAt(j) >= 128) error$7("not-basic");
|
|
35296
35296
|
output.push(input.charCodeAt(j));
|
|
35297
35297
|
}
|
|
35298
35298
|
for (let index = basic > 0 ? basic + 1 : 0; index < inputLength;) {
|
|
35299
35299
|
const oldi = i;
|
|
35300
35300
|
for (let w = 1, k = base$1;; k += base$1) {
|
|
35301
|
-
if (index >= inputLength) error$
|
|
35301
|
+
if (index >= inputLength) error$7("invalid-input");
|
|
35302
35302
|
const digit = basicToDigit(input.charCodeAt(index++));
|
|
35303
|
-
if (digit >= base$1) error$
|
|
35304
|
-
if (digit > floor((maxInt - i) / w)) error$
|
|
35303
|
+
if (digit >= base$1) error$7("invalid-input");
|
|
35304
|
+
if (digit > floor((maxInt - i) / w)) error$7("overflow");
|
|
35305
35305
|
i += digit * w;
|
|
35306
35306
|
const t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
|
|
35307
35307
|
if (digit < t) break;
|
|
35308
35308
|
const baseMinusT = base$1 - t;
|
|
35309
|
-
if (w > floor(maxInt / baseMinusT)) error$
|
|
35309
|
+
if (w > floor(maxInt / baseMinusT)) error$7("overflow");
|
|
35310
35310
|
w *= baseMinusT;
|
|
35311
35311
|
}
|
|
35312
35312
|
const out = output.length + 1;
|
|
35313
35313
|
bias = adapt(i - oldi, out, oldi == 0);
|
|
35314
|
-
if (floor(i / out) > maxInt - n) error$
|
|
35314
|
+
if (floor(i / out) > maxInt - n) error$7("overflow");
|
|
35315
35315
|
n += floor(i / out);
|
|
35316
35316
|
i %= out;
|
|
35317
35317
|
output.splice(i++, 0, n);
|
|
@@ -35340,11 +35340,11 @@ var encode = function(input) {
|
|
|
35340
35340
|
let m = maxInt;
|
|
35341
35341
|
for (const currentValue of input) if (currentValue >= n && currentValue < m) m = currentValue;
|
|
35342
35342
|
const handledCPCountPlusOne = handledCPCount + 1;
|
|
35343
|
-
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) error$
|
|
35343
|
+
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) error$7("overflow");
|
|
35344
35344
|
delta += (m - n) * handledCPCountPlusOne;
|
|
35345
35345
|
n = m;
|
|
35346
35346
|
for (const currentValue of input) {
|
|
35347
|
-
if (currentValue < n && ++delta > maxInt) error$
|
|
35347
|
+
if (currentValue < n && ++delta > maxInt) error$7("overflow");
|
|
35348
35348
|
if (currentValue === n) {
|
|
35349
35349
|
let q = delta;
|
|
35350
35350
|
for (let k = base$1;; k += base$1) {
|
|
@@ -47808,7 +47808,7 @@ var import_dexie_min = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((
|
|
|
47808
47808
|
var DexieSymbol = Symbol.for("Dexie");
|
|
47809
47809
|
var Dexie = globalThis[DexieSymbol] || (globalThis[DexieSymbol] = import_dexie_min.default);
|
|
47810
47810
|
if (import_dexie_min.default.semVer !== Dexie.semVer) throw new Error(`Two different versions of Dexie loaded in the same app: ${import_dexie_min.default.semVer} and ${Dexie.semVer}`);
|
|
47811
|
-
var { liveQuery, mergeRanges, rangesOverlap, RangeSet: RangeSet$1, cmp, Entity, PropModification, replacePrefix, add: add$1, remove: remove$
|
|
47811
|
+
var { liveQuery, mergeRanges, rangesOverlap, RangeSet: RangeSet$1, cmp, Entity, PropModification, replacePrefix, add: add$1, remove: remove$2, DexieYProvider } = Dexie;
|
|
47812
47812
|
function resolveDBName(databaseHandle) {
|
|
47813
47813
|
return `InspectAI_${databaseHandle.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
47814
47814
|
}
|
|
@@ -48174,6 +48174,9 @@ var DatabaseService = class {
|
|
|
48174
48174
|
db.log_details.where("file_path").equals(filePath).delete()
|
|
48175
48175
|
]);
|
|
48176
48176
|
}
|
|
48177
|
+
async clearPreviewForFile(filePath) {
|
|
48178
|
+
await this.getDb().log_previews.where("file_path").equals(filePath).delete();
|
|
48179
|
+
}
|
|
48177
48180
|
/**
|
|
48178
48181
|
* Get cache statistics.
|
|
48179
48182
|
*/
|
|
@@ -50083,6 +50086,9 @@ var WorkQueue = class {
|
|
|
50083
50086
|
clear() {
|
|
50084
50087
|
this.itemsById.clear();
|
|
50085
50088
|
}
|
|
50089
|
+
removeByIds(ids) {
|
|
50090
|
+
for (const id of ids) this.itemsById.delete(id);
|
|
50091
|
+
}
|
|
50086
50092
|
get size() {
|
|
50087
50093
|
return this.itemsById.size;
|
|
50088
50094
|
}
|
|
@@ -50273,6 +50279,8 @@ var ReplicationService = class {
|
|
|
50273
50279
|
}
|
|
50274
50280
|
if (invalidate) {
|
|
50275
50281
|
for (const file of logFiles) this._database?.clearCacheForFile(file.name);
|
|
50282
|
+
this._previewQueue.clear();
|
|
50283
|
+
this._detailQueue.clear();
|
|
50276
50284
|
this._applicationContext?.setLogHandles(serverLogs.files);
|
|
50277
50285
|
this.queueLogDetails(serverLogs.files);
|
|
50278
50286
|
this.queueLogPreviews(serverLogs.files);
|
|
@@ -50280,10 +50288,7 @@ var ReplicationService = class {
|
|
|
50280
50288
|
return serverLogs.files;
|
|
50281
50289
|
} else {
|
|
50282
50290
|
this._applicationContext?.setLogHandles(logFiles);
|
|
50283
|
-
|
|
50284
|
-
const previews = await this._database.findMissingPreviews(logFiles);
|
|
50285
|
-
for (const p of previews) if (!previewTasks.find((t) => t.name === p.name)) previewTasks.push(p);
|
|
50286
|
-
this.queueLogPreviews(previewTasks);
|
|
50291
|
+
await this.queueMissingOrStartedPreviews(logFiles);
|
|
50287
50292
|
const detailTasks = [];
|
|
50288
50293
|
const details = await this._database.findMissingDetails(logFiles);
|
|
50289
50294
|
for (const d of details) if (!detailTasks.find((t) => t.name === d.name)) detailTasks.push(d);
|
|
@@ -50299,6 +50304,11 @@ var ReplicationService = class {
|
|
|
50299
50304
|
return !updatedLogs.find((f) => f.name === current.name);
|
|
50300
50305
|
});
|
|
50301
50306
|
for (const file of deletedFiles) this._database?.clearCacheForFile(file.name);
|
|
50307
|
+
if (deletedFiles.length > 0) {
|
|
50308
|
+
const deletedNames = deletedFiles.map((f) => f.name);
|
|
50309
|
+
this._previewQueue.removeByIds(deletedNames);
|
|
50310
|
+
this._detailQueue.removeByIds(deletedNames);
|
|
50311
|
+
}
|
|
50302
50312
|
}
|
|
50303
50313
|
const toInvalidate = updatedLogs.filter((remoteLog) => {
|
|
50304
50314
|
const localCopy = logFiles.find((f) => f.name === remoteLog.name);
|
|
@@ -50310,11 +50320,7 @@ var ReplicationService = class {
|
|
|
50310
50320
|
await this._database.writeLogs(updatedLogs);
|
|
50311
50321
|
const allLogHandles = await this._database.readLogs() || [];
|
|
50312
50322
|
this._applicationContext?.setLogHandles(allLogHandles);
|
|
50313
|
-
|
|
50314
|
-
const previews = await this._database.findMissingPreviews(allLogHandles);
|
|
50315
|
-
for (const p of previews) if (!previewTasks.find((t) => t.name === p.name)) previewTasks.push(p);
|
|
50316
|
-
this.queueLogPreviews(previewTasks.slice(0, 25), WorkPriority.High);
|
|
50317
|
-
this.queueLogPreviews(previewTasks.slice(25), WorkPriority.Medium);
|
|
50323
|
+
await this.queueMissingOrStartedPreviews(allLogHandles, toInvalidate);
|
|
50318
50324
|
const detailTasks = [...toInvalidate];
|
|
50319
50325
|
const details = await this._database.findMissingDetails(allLogHandles);
|
|
50320
50326
|
for (const d of details) if (!detailTasks.find((t) => t.name === d.name)) detailTasks.push(d);
|
|
@@ -50348,6 +50354,29 @@ var ReplicationService = class {
|
|
|
50348
50354
|
this._database?.clearAllCaches();
|
|
50349
50355
|
this.updateDbStats();
|
|
50350
50356
|
}
|
|
50357
|
+
async queueMissingOrStartedPreviews(logHandles, extraHandles = [], priority = WorkPriority.High) {
|
|
50358
|
+
if (!this._database) return;
|
|
50359
|
+
const tasks = [...extraHandles];
|
|
50360
|
+
const seen = new Set(tasks.map((t) => t.name));
|
|
50361
|
+
const missing = await this._database.findMissingPreviews(logHandles);
|
|
50362
|
+
for (const m of missing) if (!seen.has(m.name)) {
|
|
50363
|
+
seen.add(m.name);
|
|
50364
|
+
tasks.push(m);
|
|
50365
|
+
}
|
|
50366
|
+
const cached = await this._database.readLogPreviews(logHandles);
|
|
50367
|
+
for (const handle of logHandles) {
|
|
50368
|
+
if (seen.has(handle.name)) continue;
|
|
50369
|
+
if (cached[handle.name]?.status === "started") {
|
|
50370
|
+
seen.add(handle.name);
|
|
50371
|
+
await this._database.clearPreviewForFile(handle.name);
|
|
50372
|
+
tasks.push(handle);
|
|
50373
|
+
}
|
|
50374
|
+
}
|
|
50375
|
+
if (tasks.length > 0) {
|
|
50376
|
+
this.queueLogPreviews(tasks.slice(0, 25), priority);
|
|
50377
|
+
this.queueLogPreviews(tasks.slice(25), WorkPriority.Medium);
|
|
50378
|
+
}
|
|
50379
|
+
}
|
|
50351
50380
|
queueLogPreviews(logs, priority = WorkPriority.Medium) {
|
|
50352
50381
|
this._previewQueue.enqueue(logs, priority);
|
|
50353
50382
|
}
|
|
@@ -50605,6 +50634,8 @@ var ApplicationIcons = {
|
|
|
50605
50634
|
},
|
|
50606
50635
|
turns: "bi bi-chat-left-text",
|
|
50607
50636
|
usage: "bi bi-stopwatch",
|
|
50637
|
+
pencil: "bi bi-pencil",
|
|
50638
|
+
trash: "bi bi-trash",
|
|
50608
50639
|
fork: "bi bi-signpost-split",
|
|
50609
50640
|
pendingTask: "bi bi-clock",
|
|
50610
50641
|
columns: "bi bi-layout-three-columns",
|
|
@@ -50630,29 +50661,20 @@ var ClientEventsService = class {
|
|
|
50630
50661
|
currentPolling = null;
|
|
50631
50662
|
abortController = null;
|
|
50632
50663
|
isRefreshing = false;
|
|
50633
|
-
pendingLogs = /* @__PURE__ */ new Set();
|
|
50634
50664
|
onRefreshCallback = null;
|
|
50635
50665
|
setRefreshCallback(callback) {
|
|
50636
50666
|
this.onRefreshCallback = callback;
|
|
50637
50667
|
}
|
|
50638
|
-
async
|
|
50668
|
+
async refreshLogFiles(reason) {
|
|
50639
50669
|
if (this.isRefreshing || !this.onRefreshCallback) return;
|
|
50640
|
-
|
|
50641
|
-
|
|
50642
|
-
|
|
50643
|
-
|
|
50644
|
-
|
|
50645
|
-
|
|
50646
|
-
} finally {
|
|
50647
|
-
this.isRefreshing = false;
|
|
50648
|
-
}
|
|
50649
|
-
while (this.pendingLogs.size > 0);
|
|
50650
|
-
}
|
|
50651
|
-
async refreshLogFiles(logs) {
|
|
50652
|
-
logs.forEach((file) => this.pendingLogs.add(file));
|
|
50653
|
-
await this.refreshPendingLogFiles();
|
|
50670
|
+
this.isRefreshing = true;
|
|
50671
|
+
try {
|
|
50672
|
+
await this.onRefreshCallback(reason);
|
|
50673
|
+
} finally {
|
|
50674
|
+
this.isRefreshing = false;
|
|
50675
|
+
}
|
|
50654
50676
|
}
|
|
50655
|
-
startPolling(
|
|
50677
|
+
startPolling(api) {
|
|
50656
50678
|
this.stopPolling();
|
|
50657
50679
|
this.abortController = new AbortController();
|
|
50658
50680
|
let pollingCount = 1;
|
|
@@ -50668,8 +50690,8 @@ var ClientEventsService = class {
|
|
|
50668
50690
|
log$4.debug(`Polling aborted, stopping poll for client events`);
|
|
50669
50691
|
return false;
|
|
50670
50692
|
}
|
|
50671
|
-
if ((events || []).includes(kRefreshEvent)) await this.refreshLogFiles(
|
|
50672
|
-
if (pollingCount++ % 10 === 0) await this.refreshLogFiles(
|
|
50693
|
+
if ((events || []).includes(kRefreshEvent)) await this.refreshLogFiles("event");
|
|
50694
|
+
if (pollingCount++ % 10 === 0) await this.refreshLogFiles("periodic");
|
|
50673
50695
|
return true;
|
|
50674
50696
|
}, {
|
|
50675
50697
|
maxRetries: kRetries,
|
|
@@ -50690,12 +50712,44 @@ var ClientEventsService = class {
|
|
|
50690
50712
|
cleanup() {
|
|
50691
50713
|
log$4.debug(`Cleanup`);
|
|
50692
50714
|
this.stopPolling();
|
|
50693
|
-
this.pendingLogs.clear();
|
|
50694
50715
|
this.onRefreshCallback = null;
|
|
50695
50716
|
}
|
|
50696
50717
|
};
|
|
50697
50718
|
var clientEventsService = new ClientEventsService();
|
|
50698
50719
|
//#endregion
|
|
50720
|
+
//#region src/state/clientEvents.ts
|
|
50721
|
+
var log$3 = createLogger("Client-Events");
|
|
50722
|
+
function useClientEvents() {
|
|
50723
|
+
const syncLogs = useStore((state) => state.logsActions.syncLogs);
|
|
50724
|
+
const api = useApi();
|
|
50725
|
+
const refreshCallback = useCallback(async (_reason) => {
|
|
50726
|
+
log$3.debug(`Refresh Log Files (${_reason})`);
|
|
50727
|
+
await syncLogs();
|
|
50728
|
+
}, [syncLogs]);
|
|
50729
|
+
useEffect(() => {
|
|
50730
|
+
clientEventsService.setRefreshCallback(refreshCallback);
|
|
50731
|
+
}, [refreshCallback]);
|
|
50732
|
+
const startPolling = useCallback(() => {
|
|
50733
|
+
clientEventsService.startPolling(api);
|
|
50734
|
+
}, [api]);
|
|
50735
|
+
const stopPolling = useCallback(() => {
|
|
50736
|
+
clientEventsService.stopPolling();
|
|
50737
|
+
}, []);
|
|
50738
|
+
const cleanup = useCallback(() => {
|
|
50739
|
+
clientEventsService.cleanup();
|
|
50740
|
+
}, []);
|
|
50741
|
+
useEffect(() => {
|
|
50742
|
+
return () => {
|
|
50743
|
+
cleanup();
|
|
50744
|
+
};
|
|
50745
|
+
}, [cleanup]);
|
|
50746
|
+
return {
|
|
50747
|
+
startPolling,
|
|
50748
|
+
stopPolling,
|
|
50749
|
+
cleanup
|
|
50750
|
+
};
|
|
50751
|
+
}
|
|
50752
|
+
//#endregion
|
|
50699
50753
|
//#region src/app/samples/error/error.ts
|
|
50700
50754
|
/**
|
|
50701
50755
|
* Extracts the error type from a given message.
|
|
@@ -51139,6 +51193,7 @@ var contentRenderers = (icons, renderObject, externalRenderers) => {
|
|
|
51139
51193
|
//#region ../../packages/inspect-components/src/content/MetaDataGrid.tsx
|
|
51140
51194
|
var isPlainObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
51141
51195
|
var isNonEmptyObject = (v) => isPlainObject(v) && Object.keys(v).length > 0;
|
|
51196
|
+
var hasHtmlEscape = (v) => isPlainObject(v) && "_html" in v && v._html != null;
|
|
51142
51197
|
/**
|
|
51143
51198
|
* Renders structured metadata as a grid with section cards.
|
|
51144
51199
|
*
|
|
@@ -51149,8 +51204,8 @@ var isNonEmptyObject = (v) => isPlainObject(v) && Object.keys(v).length > 0;
|
|
|
51149
51204
|
var MetaDataGrid = ({ id, entries, className, references, style, maxRows, options, depth = 0 }) => {
|
|
51150
51205
|
const baseId = id ?? "metadata-grid";
|
|
51151
51206
|
const allEntries = entryRecords(entries);
|
|
51152
|
-
const scalars = allEntries.filter((e) => !isNonEmptyObject(e.value));
|
|
51153
|
-
const groups = allEntries.filter((e) => isNonEmptyObject(e.value));
|
|
51207
|
+
const scalars = allEntries.filter((e) => !isNonEmptyObject(e.value) || hasHtmlEscape(e.value));
|
|
51208
|
+
const groups = allEntries.filter((e) => isNonEmptyObject(e.value) && !hasHtmlEscape(e.value));
|
|
51154
51209
|
const [expanded, setExpanded] = useState(false);
|
|
51155
51210
|
const isCollapsible = maxRows != null && scalars.length > maxRows;
|
|
51156
51211
|
const visibleScalars = isCollapsible && !expanded ? scalars.slice(0, maxRows) : scalars;
|
|
@@ -54656,7 +54711,7 @@ var useEvalScorePanelSort = () => {
|
|
|
54656
54711
|
};
|
|
54657
54712
|
}, [stored]);
|
|
54658
54713
|
};
|
|
54659
|
-
var log$
|
|
54714
|
+
var log$2 = createLogger("hooks");
|
|
54660
54715
|
var useEvalSpec = () => {
|
|
54661
54716
|
return useStore((state) => state.log.selectedLogDetails)?.eval;
|
|
54662
54717
|
};
|
|
@@ -54680,6 +54735,27 @@ var useRefreshLog = () => {
|
|
|
54680
54735
|
setLoading
|
|
54681
54736
|
]);
|
|
54682
54737
|
};
|
|
54738
|
+
/**
|
|
54739
|
+
* Capability + plumbing for an edit-the-current-log surface (tag, metadata,
|
|
54740
|
+
* score, …). Each edit dialog kind reads this and renders its own dialog
|
|
54741
|
+
* with its own payload — but the gate and the refresh wiring are shared.
|
|
54742
|
+
*
|
|
54743
|
+
* The in-progress gate mirrors the server: the edit API returns 409 while
|
|
54744
|
+
* the recorder still owns the file, so offering the action and failing
|
|
54745
|
+
* on save is worse than not offering it.
|
|
54746
|
+
*/
|
|
54747
|
+
var useLogEditAffordance = () => {
|
|
54748
|
+
const api = useApi();
|
|
54749
|
+
const hasEditApi = Boolean(api.edit_log);
|
|
54750
|
+
const selectedLogFile = useStore((s) => s.logs.selectedLogFile);
|
|
54751
|
+
const logStatus = useStore((s) => s.log.selectedLogDetails?.status);
|
|
54752
|
+
const refreshLog = useRefreshLog();
|
|
54753
|
+
return {
|
|
54754
|
+
canEdit: hasEditApi && !!selectedLogFile && !(logStatus === "started"),
|
|
54755
|
+
selectedLogFile,
|
|
54756
|
+
refreshOnSave: refreshLog
|
|
54757
|
+
};
|
|
54758
|
+
};
|
|
54683
54759
|
var useSampleSummaries = () => {
|
|
54684
54760
|
const selectedLogDetails = useStore((state) => state.log.selectedLogDetails);
|
|
54685
54761
|
const pendingSampleSummaries = useStore((state) => state.log.pendingSampleSummaries);
|
|
@@ -54836,7 +54912,7 @@ var useMessageVisibility = (id, scope) => {
|
|
|
54836
54912
|
isFirstRender.current = false;
|
|
54837
54913
|
return;
|
|
54838
54914
|
}
|
|
54839
|
-
log$
|
|
54915
|
+
log$2.debug("clear message (eval)", id);
|
|
54840
54916
|
clearVisible(id);
|
|
54841
54917
|
}, [
|
|
54842
54918
|
useStore((state) => state.logs.selectedLogFile),
|
|
@@ -54846,7 +54922,7 @@ var useMessageVisibility = (id, scope) => {
|
|
|
54846
54922
|
useEffect(() => {
|
|
54847
54923
|
if (isFirstRender.current) return;
|
|
54848
54924
|
if (scope === "sample") {
|
|
54849
|
-
log$
|
|
54925
|
+
log$2.debug("clear message (sample)", id);
|
|
54850
54926
|
clearVisible(id);
|
|
54851
54927
|
}
|
|
54852
54928
|
}, [
|
|
@@ -54856,9 +54932,9 @@ var useMessageVisibility = (id, scope) => {
|
|
|
54856
54932
|
scope
|
|
54857
54933
|
]);
|
|
54858
54934
|
return useMemo(() => {
|
|
54859
|
-
log$
|
|
54935
|
+
log$2.debug("visibility", id, visible);
|
|
54860
54936
|
const set = (visible) => {
|
|
54861
|
-
log$
|
|
54937
|
+
log$2.debug("set visiblity", id);
|
|
54862
54938
|
setVisible(id, visible);
|
|
54863
54939
|
};
|
|
54864
54940
|
return [visible, set];
|
|
@@ -54881,7 +54957,7 @@ var useLogs = () => {
|
|
|
54881
54957
|
const setLoading = useStore((state) => state.appActions.setLoading);
|
|
54882
54958
|
const loadLogs = useCallback(async (logPath) => {
|
|
54883
54959
|
await Promise.all([syncEvalSetInfo(logPath), syncLogs()]).catch((e) => {
|
|
54884
|
-
log$
|
|
54960
|
+
log$2.error("Error loading logs", e);
|
|
54885
54961
|
setLoading(false, e);
|
|
54886
54962
|
});
|
|
54887
54963
|
}, [
|
|
@@ -54977,54 +55053,6 @@ var useLogsWithretried = () => {
|
|
|
54977
55053
|
return useMemo(() => computeLogsWithRetried(logs, logPreviews), [logs, logPreviews]);
|
|
54978
55054
|
};
|
|
54979
55055
|
//#endregion
|
|
54980
|
-
//#region src/state/clientEvents.ts
|
|
54981
|
-
var log$2 = createLogger("Client-Events");
|
|
54982
|
-
function useClientEvents() {
|
|
54983
|
-
const syncLogs = useStore((state) => state.logsActions.syncLogs);
|
|
54984
|
-
const logPreviews = useStore((state) => state.logs.logPreviews);
|
|
54985
|
-
const api = useApi();
|
|
54986
|
-
const { loadLogOverviews } = useLogs();
|
|
54987
|
-
const refreshCallback = useCallback(async (logs) => {
|
|
54988
|
-
log$2.debug("Refresh Log Files");
|
|
54989
|
-
await syncLogs();
|
|
54990
|
-
const toRefresh = [];
|
|
54991
|
-
for (const log of logs) {
|
|
54992
|
-
const header = logPreviews[log.name];
|
|
54993
|
-
if (!header || header.status === "started") toRefresh.push(log);
|
|
54994
|
-
}
|
|
54995
|
-
if (toRefresh.length > 0) {
|
|
54996
|
-
log$2.debug(`Refreshing ${toRefresh.length} log files`, toRefresh);
|
|
54997
|
-
await loadLogOverviews(toRefresh);
|
|
54998
|
-
}
|
|
54999
|
-
}, [
|
|
55000
|
-
logPreviews,
|
|
55001
|
-
syncLogs,
|
|
55002
|
-
loadLogOverviews
|
|
55003
|
-
]);
|
|
55004
|
-
useEffect(() => {
|
|
55005
|
-
clientEventsService.setRefreshCallback(refreshCallback);
|
|
55006
|
-
}, [refreshCallback]);
|
|
55007
|
-
const startPolling = useCallback((logs) => {
|
|
55008
|
-
clientEventsService.startPolling(logs, api);
|
|
55009
|
-
}, [api]);
|
|
55010
|
-
const stopPolling = useCallback(() => {
|
|
55011
|
-
clientEventsService.stopPolling();
|
|
55012
|
-
}, []);
|
|
55013
|
-
const cleanup = useCallback(() => {
|
|
55014
|
-
clientEventsService.cleanup();
|
|
55015
|
-
}, []);
|
|
55016
|
-
useEffect(() => {
|
|
55017
|
-
return () => {
|
|
55018
|
-
cleanup();
|
|
55019
|
-
};
|
|
55020
|
-
}, [cleanup]);
|
|
55021
|
-
return {
|
|
55022
|
-
startPolling,
|
|
55023
|
-
stopPolling,
|
|
55024
|
-
cleanup
|
|
55025
|
-
};
|
|
55026
|
-
}
|
|
55027
|
-
//#endregion
|
|
55028
55056
|
//#region src/app/routing/url.ts
|
|
55029
55057
|
/**
|
|
55030
55058
|
* Decodes a URL parameter that may be URL-encoded.
|
|
@@ -56514,6 +56542,19 @@ var useLogListColumns = (mode = "logs", scopePrefix, viewMode = "by-metric") =>
|
|
|
56514
56542
|
return /* @__PURE__ */ jsx("div", { children: formatNumber$1(params.value) });
|
|
56515
56543
|
}
|
|
56516
56544
|
},
|
|
56545
|
+
{
|
|
56546
|
+
field: "sampleLimits",
|
|
56547
|
+
headerName: "Sample Limits",
|
|
56548
|
+
initialWidth: 140,
|
|
56549
|
+
minWidth: 80,
|
|
56550
|
+
sortable: true,
|
|
56551
|
+
filter: true,
|
|
56552
|
+
resizable: true,
|
|
56553
|
+
cellRenderer: (params) => {
|
|
56554
|
+
if (!params.value) return /* @__PURE__ */ jsx(EmptyCell$1, {});
|
|
56555
|
+
return /* @__PURE__ */ jsx("div", { children: params.value });
|
|
56556
|
+
}
|
|
56557
|
+
},
|
|
56517
56558
|
{
|
|
56518
56559
|
field: "errorMessage",
|
|
56519
56560
|
headerName: "Error",
|
|
@@ -56653,6 +56694,7 @@ var useLogListColumns = (mode = "logs", scopePrefix, viewMode = "by-metric") =>
|
|
|
56653
56694
|
"completedSamples",
|
|
56654
56695
|
"percentCompleted",
|
|
56655
56696
|
"sampleErrors",
|
|
56697
|
+
"sampleLimits",
|
|
56656
56698
|
"totalTokens",
|
|
56657
56699
|
"duration",
|
|
56658
56700
|
"errorMessage",
|
|
@@ -56679,6 +56721,13 @@ var useLogListColumns = (mode = "logs", scopePrefix, viewMode = "by-metric") =>
|
|
|
56679
56721
|
}
|
|
56680
56722
|
return allCols;
|
|
56681
56723
|
}, [scorerMap, mode]);
|
|
56724
|
+
const hasSampleLimits = useMemo(() => {
|
|
56725
|
+
for (const [logName, details] of Object.entries(logDetails)) {
|
|
56726
|
+
if (scopePrefix && !logName.startsWith(scopePrefix)) continue;
|
|
56727
|
+
if (details.sampleSummaries?.some((s) => s.limit)) return true;
|
|
56728
|
+
}
|
|
56729
|
+
return false;
|
|
56730
|
+
}, [logDetails, scopePrefix]);
|
|
56682
56731
|
const defaultHiddenFields = useMemo(() => {
|
|
56683
56732
|
const hidden = /* @__PURE__ */ new Set();
|
|
56684
56733
|
if (mode === "tasks") {
|
|
@@ -56695,9 +56744,10 @@ var useLogListColumns = (mode = "logs", scopePrefix, viewMode = "by-metric") =>
|
|
|
56695
56744
|
}
|
|
56696
56745
|
hidden.add("percentCompleted");
|
|
56697
56746
|
hidden.add("sampleErrors");
|
|
56747
|
+
if (!hasSampleLimits) hidden.add("sampleLimits");
|
|
56698
56748
|
hidden.add("errorMessage");
|
|
56699
56749
|
return hidden;
|
|
56700
|
-
}, [mode]);
|
|
56750
|
+
}, [mode, hasSampleLimits]);
|
|
56701
56751
|
const matchesActiveMode = (field) => {
|
|
56702
56752
|
if (field.startsWith("score_")) return viewMode === "per-scorer";
|
|
56703
56753
|
if (field.startsWith("metric_")) return viewMode === "by-metric";
|
|
@@ -103755,11 +103805,10 @@ function useApplyColumnVisibility(gridRef, columnDefs, visibility) {
|
|
|
103755
103805
|
var LogListGrid = ({ items, currentPath, scopeKey, gridRef: externalGridRef, mode = "logs" }) => {
|
|
103756
103806
|
const { gridStateByScope, setGridState, setFilteredCount } = useLogsListing();
|
|
103757
103807
|
const gridState = scopeKey ? gridStateByScope[scopeKey] : void 0;
|
|
103758
|
-
const {
|
|
103808
|
+
const { loadAllLogOverviews } = useLogs();
|
|
103759
103809
|
const loading = useStore((state) => state.app.status.loading);
|
|
103760
103810
|
const syncing = useStore((state) => state.app.status.syncing);
|
|
103761
103811
|
const setWatchedLogs = useStore((state) => state.logsActions.setWatchedLogs);
|
|
103762
|
-
const logPreviews = useStore((state) => state.logs.logPreviews);
|
|
103763
103812
|
const logDetails = useStore((state) => state.logs.logDetails);
|
|
103764
103813
|
const navigate = useNavigate();
|
|
103765
103814
|
const internalGridRef = useRef(null);
|
|
@@ -103813,6 +103862,12 @@ var LogListGrid = ({ items, currentPath, scopeKey, gridRef: externalGridRef, mod
|
|
|
103813
103862
|
if (total && total > 0 && completed !== void 0) percentCompleted = completed / total * 100;
|
|
103814
103863
|
let sampleErrors;
|
|
103815
103864
|
if (details?.sampleSummaries) sampleErrors = details.sampleSummaries.filter((s) => s.error).length;
|
|
103865
|
+
let sampleLimits;
|
|
103866
|
+
if (details?.sampleSummaries) {
|
|
103867
|
+
const limits = /* @__PURE__ */ new Set();
|
|
103868
|
+
for (const s of details.sampleSummaries) if (s.limit) limits.add(s.limit);
|
|
103869
|
+
if (limits.size > 0) sampleLimits = Array.from(limits).sort().join(", ");
|
|
103870
|
+
}
|
|
103816
103871
|
const row = {
|
|
103817
103872
|
id: item.id,
|
|
103818
103873
|
name: item.name,
|
|
@@ -103839,6 +103894,7 @@ var LogListGrid = ({ items, currentPath, scopeKey, gridRef: externalGridRef, mod
|
|
|
103839
103894
|
tags: details?.tags,
|
|
103840
103895
|
percentCompleted,
|
|
103841
103896
|
sampleErrors,
|
|
103897
|
+
sampleLimits,
|
|
103842
103898
|
errorMessage: details?.error?.message
|
|
103843
103899
|
};
|
|
103844
103900
|
if (details?.results?.scores) {
|
|
@@ -103878,18 +103934,8 @@ var LogListGrid = ({ items, currentPath, scopeKey, gridRef: externalGridRef, mod
|
|
|
103878
103934
|
}, [handleKeyDown]);
|
|
103879
103935
|
const handleCellMouseDown = useCallback((_e) => {}, []);
|
|
103880
103936
|
useEffect(() => {
|
|
103881
|
-
|
|
103882
|
-
|
|
103883
|
-
if (filesToLoad.length > 0) await loadLogOverviews(filesToLoad);
|
|
103884
|
-
setWatchedLogs(logFiles);
|
|
103885
|
-
};
|
|
103886
|
-
loadHeaders();
|
|
103887
|
-
}, [
|
|
103888
|
-
logFiles,
|
|
103889
|
-
loadLogOverviews,
|
|
103890
|
-
setWatchedLogs,
|
|
103891
|
-
logPreviews
|
|
103892
|
-
]);
|
|
103937
|
+
setWatchedLogs(logFiles);
|
|
103938
|
+
}, [logFiles, setWatchedLogs]);
|
|
103893
103939
|
const applyVisibility = useApplyColumnVisibility(gridRef, columns, visibility);
|
|
103894
103940
|
const handleGridReady = useCallback((e) => {
|
|
103895
103941
|
applyVisibility();
|
|
@@ -104170,7 +104216,7 @@ var LogsPanel = ({ maybeShowSingleLog, mode = "logs" }) => {
|
|
|
104170
104216
|
useEffect(() => {
|
|
104171
104217
|
if ((watchedLogs?.map((log) => log.name).sort().join(",") || "") !== (previousWatchedLogs.current === void 0 ? void 0 : previousWatchedLogs.current?.map((log) => log.name).sort().join(",") || "")) {
|
|
104172
104218
|
stopPolling();
|
|
104173
|
-
if (watchedLogs !== void 0) startPolling(
|
|
104219
|
+
if (watchedLogs !== void 0) startPolling();
|
|
104174
104220
|
previousWatchedLogs.current = watchedLogs;
|
|
104175
104221
|
}
|
|
104176
104222
|
}, [
|
|
@@ -105289,17 +105335,24 @@ var resolveToolInput = (fn, toolArgs) => {
|
|
|
105289
105335
|
const inputDescriptor = extractInputMetadata(toolName);
|
|
105290
105336
|
const { input, description, args } = extractInput(toolArgs, inputDescriptor);
|
|
105291
105337
|
const functionCall = args.length > 0 ? `${toolName}(${args.join(", ")})` : toolName;
|
|
105292
|
-
if ((fn === "Task" || fn === "task") && typeof toolArgs.subagent_type === "string") {
|
|
105338
|
+
if ((fn === "Task" || fn === "task" || fn === "Agent" || fn === "agent") && typeof toolArgs.subagent_type === "string") {
|
|
105293
105339
|
const subagentType = toolArgs.subagent_type;
|
|
105294
105340
|
return {
|
|
105295
105341
|
name: fn,
|
|
105296
|
-
functionCall:
|
|
105342
|
+
functionCall: `${fn}: ${subagentType}`,
|
|
105297
105343
|
title: `${fn}: ${subagentType}`,
|
|
105298
105344
|
input,
|
|
105299
105345
|
description,
|
|
105300
105346
|
contentType: "markdown"
|
|
105301
105347
|
};
|
|
105302
105348
|
}
|
|
105349
|
+
if (fn === "agent_status" || fn === "agent_wait" || fn === "agent_cancel" || fn === "agent_list") return {
|
|
105350
|
+
name: fn,
|
|
105351
|
+
functionCall,
|
|
105352
|
+
input,
|
|
105353
|
+
description,
|
|
105354
|
+
contentType: "markdown"
|
|
105355
|
+
};
|
|
105303
105356
|
return {
|
|
105304
105357
|
name: fn,
|
|
105305
105358
|
functionCall,
|
|
@@ -105350,12 +105403,12 @@ var extractInputMetadata = (toolName) => {
|
|
|
105350
105403
|
inputArg: "todos",
|
|
105351
105404
|
contentType: kToolTodoContentType
|
|
105352
105405
|
};
|
|
105353
|
-
else if (toolName === "Task") return {
|
|
105406
|
+
else if (toolName === "Task" || toolName === "Agent") return {
|
|
105354
105407
|
inputArg: "prompt",
|
|
105355
105408
|
descriptionArg: "description",
|
|
105356
105409
|
contentType: "markdown"
|
|
105357
105410
|
};
|
|
105358
|
-
else if (toolName === "task") return {
|
|
105411
|
+
else if (toolName === "task" || toolName === "agent") return {
|
|
105359
105412
|
inputArg: "prompt",
|
|
105360
105413
|
descriptionArg: "task_description",
|
|
105361
105414
|
contentType: "markdown"
|
|
@@ -106346,7 +106399,7 @@ var ChatMessage = memo(function ChatMessage({ id, message, display, linking, ref
|
|
|
106346
106399
|
const linkIcon = linking?.icon ?? "bi bi-link-45deg";
|
|
106347
106400
|
const messageUrl = getMessageUrl?.(message.id || "");
|
|
106348
106401
|
const [mouseOver, setMouseOver] = useState(false);
|
|
106349
|
-
const
|
|
106402
|
+
const isNonSubagentTool = message.role === "tool" && message.function !== "Task" && message.function !== "task" && message.function !== "Agent" && message.function !== "agent";
|
|
106350
106403
|
const collapse = message.role === "system" || message.role === "user" || message.role === "assistant" || message.role === "tool";
|
|
106351
106404
|
const hideRole = unlabeledRoles?.includes(message.role) ?? false;
|
|
106352
106405
|
if (hideRole) {
|
|
@@ -106381,7 +106434,7 @@ var ChatMessage = memo(function ChatMessage({ id, message, display, linking, ref
|
|
|
106381
106434
|
id: `${id}-message`,
|
|
106382
106435
|
collapse,
|
|
106383
106436
|
lines: message.role === "tool" ? 30 : message.role === "assistant" ? 25 : collapse ? 15 : 25,
|
|
106384
|
-
children:
|
|
106437
|
+
children: isNonSubagentTool ? /* @__PURE__ */ jsx(ToolOutput, { output: typeof message.content === "string" ? message.content : message.content.filter((c) => c.type === "text" || c.type === "image") }) : /* @__PURE__ */ jsx(MessageContents, {
|
|
106385
106438
|
message,
|
|
106386
106439
|
references
|
|
106387
106440
|
}, `${id}-contents`)
|
|
@@ -107437,6 +107490,7 @@ var TimelineSpan = class {
|
|
|
107437
107490
|
branchedFrom;
|
|
107438
107491
|
description;
|
|
107439
107492
|
utility;
|
|
107493
|
+
toolInvoked;
|
|
107440
107494
|
agentResult;
|
|
107441
107495
|
outline;
|
|
107442
107496
|
constructor(props) {
|
|
@@ -107448,6 +107502,7 @@ var TimelineSpan = class {
|
|
|
107448
107502
|
this.branchedFrom = props.branchedFrom ?? null;
|
|
107449
107503
|
this.description = props.description;
|
|
107450
107504
|
this.utility = props.utility ?? false;
|
|
107505
|
+
this.toolInvoked = props.toolInvoked ?? false;
|
|
107451
107506
|
this.agentResult = props.agentResult;
|
|
107452
107507
|
this.outline = props.outline;
|
|
107453
107508
|
}
|
|
@@ -107501,6 +107556,7 @@ function pruneEmptyBranches(span) {
|
|
|
107501
107556
|
branchedFrom: span.branchedFrom,
|
|
107502
107557
|
description: span.description,
|
|
107503
107558
|
utility: span.utility,
|
|
107559
|
+
toolInvoked: span.toolInvoked,
|
|
107504
107560
|
agentResult: span.agentResult,
|
|
107505
107561
|
outline: span.outline
|
|
107506
107562
|
});
|
|
@@ -107532,6 +107588,7 @@ function createBranchSpan(branch, label) {
|
|
|
107532
107588
|
branchedFrom: branch.branchedFrom,
|
|
107533
107589
|
description: branch.description,
|
|
107534
107590
|
utility: branch.utility,
|
|
107591
|
+
toolInvoked: branch.toolInvoked,
|
|
107535
107592
|
agentResult: branch.agentResult,
|
|
107536
107593
|
outline: branch.outline
|
|
107537
107594
|
});
|
|
@@ -107595,6 +107652,7 @@ function convertServerSpan(server, lookup) {
|
|
|
107595
107652
|
branches,
|
|
107596
107653
|
description: server.description ?? void 0,
|
|
107597
107654
|
utility: server.utility,
|
|
107655
|
+
toolInvoked: server.tool_invoked,
|
|
107598
107656
|
agentResult: server.agent_result ?? void 0,
|
|
107599
107657
|
outline: server.outline ?? void 0
|
|
107600
107658
|
});
|
|
@@ -107837,6 +107895,7 @@ function eventToNode(event) {
|
|
|
107837
107895
|
const nestedContent = nestedEvents.map((e) => eventToNode(e));
|
|
107838
107896
|
if (nestedContent.length > 0) {
|
|
107839
107897
|
const span = createTimelineSpan(`tool-agent-${event.id}`, agentName, "agent", nestedContent);
|
|
107898
|
+
span.toolInvoked = true;
|
|
107840
107899
|
const agentResult = extractToolEventResult(event.result);
|
|
107841
107900
|
if (agentResult) span.agentResult = agentResult;
|
|
107842
107901
|
return span;
|
|
@@ -107974,10 +108033,12 @@ function buildAgentFromTree(tree) {
|
|
|
107974
108033
|
*/
|
|
107975
108034
|
function unrollSpan(span, into) {
|
|
107976
108035
|
into.push(createTimelineEvent(span.beginEvent));
|
|
108036
|
+
const parentIsTool = span.type === "tool";
|
|
107977
108037
|
for (const child of span.children) if (isSpanNode(child)) if (isAgentSpan(child)) {
|
|
107978
108038
|
const node = treeItemToNode(child);
|
|
107979
108039
|
if (node === null) continue;
|
|
107980
108040
|
if (node.type === "span" && node.content.length === 0) continue;
|
|
108041
|
+
if (parentIsTool && node.type === "span") node.toolInvoked = true;
|
|
107981
108042
|
into.push(node);
|
|
107982
108043
|
} else unrollSpan(child, into);
|
|
107983
108044
|
else into.push(eventToNode(child));
|
|
@@ -108216,7 +108277,7 @@ function isSingleTurn(span) {
|
|
|
108216
108277
|
*/
|
|
108217
108278
|
function classifyUtilityAgents(node, parentSystemPrompt = null) {
|
|
108218
108279
|
const agentSystemPrompt = getSystemPrompt(node);
|
|
108219
|
-
if (parentSystemPrompt !== null && agentSystemPrompt !== null) {
|
|
108280
|
+
if (parentSystemPrompt !== null && agentSystemPrompt !== null && !node.toolInvoked) {
|
|
108220
108281
|
if (agentSystemPrompt !== parentSystemPrompt && isSingleTurn(node)) node.utility = true;
|
|
108221
108282
|
}
|
|
108222
108283
|
const effectivePrompt = agentSystemPrompt ?? parentSystemPrompt;
|
|
@@ -119544,7 +119605,7 @@ var sampleStatus_module_default = {
|
|
|
119544
119605
|
//#region src/app/samples/status/sampleStatus.tsx
|
|
119545
119606
|
var sampleStatus = (completed, error) => {
|
|
119546
119607
|
if (error) return errorType(error) === "CancelledError" ? "cancelled" : "error";
|
|
119547
|
-
return completed ? "
|
|
119608
|
+
return completed === false ? "running" : "ok";
|
|
119548
119609
|
};
|
|
119549
119610
|
var isCancelled = (sample) => {
|
|
119550
119611
|
if ("error" in sample && sample.error) {
|
|
@@ -123881,6 +123942,944 @@ var MessageBand = ({ id, message, type, scope = "eval" }) => {
|
|
|
123881
123942
|
]
|
|
123882
123943
|
});
|
|
123883
123944
|
};
|
|
123945
|
+
var EditButton_module_default = {
|
|
123946
|
+
button: "_button_u0dz8_2",
|
|
123947
|
+
link: "_link_u0dz8_1",
|
|
123948
|
+
pill: "_pill_u0dz8_1"
|
|
123949
|
+
};
|
|
123950
|
+
//#endregion
|
|
123951
|
+
//#region src/app/log-view/title-view/EditButton.tsx
|
|
123952
|
+
var EditButton = ({ onClick, title, variant = "link", children }) => /* @__PURE__ */ jsxs("button", {
|
|
123953
|
+
type: "button",
|
|
123954
|
+
className: clsx(EditButton_module_default.button, variant === "pill" ? EditButton_module_default.pill : EditButton_module_default.link, "text-size-smallest"),
|
|
123955
|
+
onClick,
|
|
123956
|
+
title: title ?? "edit",
|
|
123957
|
+
children: [/* @__PURE__ */ jsx("i", { className: ApplicationIcons.pencil }), children ?? "edit"]
|
|
123958
|
+
});
|
|
123959
|
+
var Modal_module_default = {
|
|
123960
|
+
modal: "_modal_8i1ew_1",
|
|
123961
|
+
header: "_header_8i1ew_21",
|
|
123962
|
+
modalTitle: "_modalTitle_8i1ew_26",
|
|
123963
|
+
btnClose: "_btnClose_8i1ew_30",
|
|
123964
|
+
backdrop: "_backdrop_8i1ew_36",
|
|
123965
|
+
overflowVisible: "_overflowVisible_8i1ew_48",
|
|
123966
|
+
overflowHidden: "_overflowHidden_8i1ew_52",
|
|
123967
|
+
overflowScroll: "_overflowScroll_8i1ew_56",
|
|
123968
|
+
overflowAuto: "_overflowAuto_8i1ew_60",
|
|
123969
|
+
noPadding: "_noPadding_8i1ew_64",
|
|
123970
|
+
footerSlot: "_footerSlot_8i1ew_73"
|
|
123971
|
+
};
|
|
123972
|
+
//#endregion
|
|
123973
|
+
//#region src/components/Modal.tsx
|
|
123974
|
+
var Modal = ({ id, title, showing, setShowing, children, className, overflow = "visible", padded = true, footer, width }) => {
|
|
123975
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [showing && /* @__PURE__ */ jsx("div", {
|
|
123976
|
+
className: Modal_module_default.backdrop,
|
|
123977
|
+
onClick: () => setShowing(false)
|
|
123978
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
123979
|
+
id,
|
|
123980
|
+
className: clsx("modal", "fade", showing ? "show" : "", className),
|
|
123981
|
+
tabIndex: -1,
|
|
123982
|
+
style: { display: showing ? "block" : "none" },
|
|
123983
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
123984
|
+
className: clsx("modal-dialog", Modal_module_default.modal),
|
|
123985
|
+
style: width ? { maxWidth: width } : void 0,
|
|
123986
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
123987
|
+
className: "modal-content",
|
|
123988
|
+
children: [
|
|
123989
|
+
/* @__PURE__ */ jsxs("div", {
|
|
123990
|
+
className: clsx("modal-header", Modal_module_default.header),
|
|
123991
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
123992
|
+
className: clsx("modal-title", "text-size-base", Modal_module_default.modalTitle),
|
|
123993
|
+
children: title
|
|
123994
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
123995
|
+
type: "button",
|
|
123996
|
+
className: clsx("btn-close", "text-size-smaller", Modal_module_default.btnClose),
|
|
123997
|
+
"data-bs-dismiss": "modal",
|
|
123998
|
+
"aria-label": "Close",
|
|
123999
|
+
onClick: () => {
|
|
124000
|
+
setShowing(!showing);
|
|
124001
|
+
}
|
|
124002
|
+
})]
|
|
124003
|
+
}),
|
|
124004
|
+
/* @__PURE__ */ jsx("div", {
|
|
124005
|
+
className: clsx("modal-body", !padded && Modal_module_default.noPadding, overflow === "auto" ? Modal_module_default.overflowAuto : overflow === "hidden" ? Modal_module_default.overflowHidden : overflow === "scroll" ? Modal_module_default.overflowScroll : Modal_module_default.overflowVisible),
|
|
124006
|
+
children
|
|
124007
|
+
}),
|
|
124008
|
+
/* @__PURE__ */ jsx("div", {
|
|
124009
|
+
className: clsx("modal-footer", footer && Modal_module_default.footerSlot),
|
|
124010
|
+
children: footer ?? /* @__PURE__ */ jsx("button", {
|
|
124011
|
+
type: "button",
|
|
124012
|
+
className: "btn btn-secondary",
|
|
124013
|
+
"data-bs-dismiss": "modal",
|
|
124014
|
+
onClick: () => {
|
|
124015
|
+
setShowing(!showing);
|
|
124016
|
+
},
|
|
124017
|
+
children: "Close"
|
|
124018
|
+
})
|
|
124019
|
+
})
|
|
124020
|
+
]
|
|
124021
|
+
})
|
|
124022
|
+
})
|
|
124023
|
+
})] });
|
|
124024
|
+
};
|
|
124025
|
+
var AutogrowText_module_default = { textarea: "_textarea_8mbr9_1" };
|
|
124026
|
+
//#endregion
|
|
124027
|
+
//#region src/app/log-view/title-view/AutogrowText.tsx
|
|
124028
|
+
var AutogrowText = ({ value, onChange, disabled, maxHeightPx }) => {
|
|
124029
|
+
const ref = useRef(null);
|
|
124030
|
+
useEffect(() => {
|
|
124031
|
+
const el = ref.current;
|
|
124032
|
+
if (!el) return;
|
|
124033
|
+
let lastApplied = "";
|
|
124034
|
+
const measure = () => {
|
|
124035
|
+
el.style.height = "0px";
|
|
124036
|
+
const target = maxHeightPx != null ? `${Math.min(el.scrollHeight, maxHeightPx)}px` : `${el.scrollHeight}px`;
|
|
124037
|
+
if (target !== lastApplied) {
|
|
124038
|
+
lastApplied = target;
|
|
124039
|
+
el.style.height = target;
|
|
124040
|
+
} else el.style.height = lastApplied;
|
|
124041
|
+
};
|
|
124042
|
+
measure();
|
|
124043
|
+
const ro = new ResizeObserver(measure);
|
|
124044
|
+
ro.observe(el);
|
|
124045
|
+
return () => ro.disconnect();
|
|
124046
|
+
}, [value, maxHeightPx]);
|
|
124047
|
+
return /* @__PURE__ */ jsx("textarea", {
|
|
124048
|
+
ref,
|
|
124049
|
+
className: clsx("form-control", AutogrowText_module_default.textarea),
|
|
124050
|
+
value,
|
|
124051
|
+
onChange: (e) => onChange(e.target.value),
|
|
124052
|
+
disabled,
|
|
124053
|
+
spellCheck: false,
|
|
124054
|
+
rows: 1
|
|
124055
|
+
});
|
|
124056
|
+
};
|
|
124057
|
+
var ChangeSummary_module_default = {
|
|
124058
|
+
container: "_container_13ofn_1",
|
|
124059
|
+
line: "_line_13ofn_18",
|
|
124060
|
+
label: "_label_13ofn_24",
|
|
124061
|
+
items: "_items_13ofn_29",
|
|
124062
|
+
accentAdding: "_accentAdding_13ofn_33",
|
|
124063
|
+
accentEditing: "_accentEditing_13ofn_37",
|
|
124064
|
+
accentRemoving: "_accentRemoving_13ofn_41"
|
|
124065
|
+
};
|
|
124066
|
+
//#endregion
|
|
124067
|
+
//#region src/app/log-view/title-view/ChangeSummary.tsx
|
|
124068
|
+
var ChangeSummary = ({ adding = [], editing = [], removing = [] }) => {
|
|
124069
|
+
if (adding.length === 0 && editing.length === 0 && removing.length === 0) return null;
|
|
124070
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
124071
|
+
className: clsx(ChangeSummary_module_default.container, "text-size-smaller"),
|
|
124072
|
+
children: [
|
|
124073
|
+
adding.length > 0 && /* @__PURE__ */ jsx(Line$1, {
|
|
124074
|
+
label: "Adding",
|
|
124075
|
+
accent: ChangeSummary_module_default.accentAdding,
|
|
124076
|
+
items: adding
|
|
124077
|
+
}),
|
|
124078
|
+
editing.length > 0 && /* @__PURE__ */ jsx(Line$1, {
|
|
124079
|
+
label: "Editing",
|
|
124080
|
+
accent: ChangeSummary_module_default.accentEditing,
|
|
124081
|
+
items: editing
|
|
124082
|
+
}),
|
|
124083
|
+
removing.length > 0 && /* @__PURE__ */ jsx(Line$1, {
|
|
124084
|
+
label: "Removing",
|
|
124085
|
+
accent: ChangeSummary_module_default.accentRemoving,
|
|
124086
|
+
items: removing
|
|
124087
|
+
})
|
|
124088
|
+
]
|
|
124089
|
+
});
|
|
124090
|
+
};
|
|
124091
|
+
var Line$1 = ({ label, accent, items }) => {
|
|
124092
|
+
const joined = items.join(", ");
|
|
124093
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
124094
|
+
className: ChangeSummary_module_default.line,
|
|
124095
|
+
title: `${label}: ${joined}`,
|
|
124096
|
+
children: [
|
|
124097
|
+
/* @__PURE__ */ jsxs("span", {
|
|
124098
|
+
className: clsx(ChangeSummary_module_default.label, accent),
|
|
124099
|
+
children: [label, ":"]
|
|
124100
|
+
}),
|
|
124101
|
+
" ",
|
|
124102
|
+
/* @__PURE__ */ jsx("span", {
|
|
124103
|
+
className: ChangeSummary_module_default.items,
|
|
124104
|
+
children: joined
|
|
124105
|
+
})
|
|
124106
|
+
]
|
|
124107
|
+
});
|
|
124108
|
+
};
|
|
124109
|
+
var EditAnnotationsDialog_module_default = {
|
|
124110
|
+
body: "_body_13gwg_3",
|
|
124111
|
+
section: "_section_13gwg_9",
|
|
124112
|
+
labelRow: "_labelRow_13gwg_15",
|
|
124113
|
+
label: "_label_13gwg_15",
|
|
124114
|
+
hint: "_hint_13gwg_27",
|
|
124115
|
+
required: "_required_13gwg_36",
|
|
124116
|
+
divider: "_divider_13gwg_41",
|
|
124117
|
+
provenance: "_provenance_13gwg_47",
|
|
124118
|
+
error: "_error_13gwg_53",
|
|
124119
|
+
footer: "_footer_13gwg_62",
|
|
124120
|
+
footerActions: "_footerActions_13gwg_62"
|
|
124121
|
+
};
|
|
124122
|
+
//#endregion
|
|
124123
|
+
//#region src/utils/json-worker.ts
|
|
124124
|
+
var JsonWorkerPool = class {
|
|
124125
|
+
encoder = new TextEncoder();
|
|
124126
|
+
decoder = new TextDecoder();
|
|
124127
|
+
workers = [];
|
|
124128
|
+
blobURL = null;
|
|
124129
|
+
nextRequestId = 0;
|
|
124130
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
124131
|
+
poolSize = 4;
|
|
124132
|
+
ensureWorkers() {
|
|
124133
|
+
if (this.workers.length === 0) {
|
|
124134
|
+
const blob = new Blob([kWorkerCode], { type: "application/javascript" });
|
|
124135
|
+
this.blobURL = URL.createObjectURL(blob);
|
|
124136
|
+
for (let i = 0; i < this.poolSize; i++) {
|
|
124137
|
+
const worker = new Worker(this.blobURL);
|
|
124138
|
+
worker.onmessage = (e) => this.handleMessage(e);
|
|
124139
|
+
worker.onerror = (error) => this.handleError(error);
|
|
124140
|
+
this.workers.push(worker);
|
|
124141
|
+
worker.postMessage({
|
|
124142
|
+
type: "init",
|
|
124143
|
+
scriptContent: kJson5ScriptBase64
|
|
124144
|
+
});
|
|
124145
|
+
}
|
|
124146
|
+
}
|
|
124147
|
+
}
|
|
124148
|
+
handleMessage(e) {
|
|
124149
|
+
const { requestId, success, serialized, result, error, stack } = e.data;
|
|
124150
|
+
const pending = this.pendingRequests.get(requestId);
|
|
124151
|
+
if (!pending) return;
|
|
124152
|
+
this.pendingRequests.delete(requestId);
|
|
124153
|
+
if (success) if (serialized) {
|
|
124154
|
+
const resultString = this.decoder.decode(result);
|
|
124155
|
+
pending.resolve(JSON.parse(resultString));
|
|
124156
|
+
} else pending.resolve(result);
|
|
124157
|
+
else {
|
|
124158
|
+
const err = new Error(error);
|
|
124159
|
+
if (stack) err.stack = stack;
|
|
124160
|
+
pending.reject(err);
|
|
124161
|
+
}
|
|
124162
|
+
}
|
|
124163
|
+
handleError(error) {
|
|
124164
|
+
const err = /* @__PURE__ */ new Error(`Worker error: ${error.message}`);
|
|
124165
|
+
for (const pending of this.pendingRequests.values()) pending.reject(err);
|
|
124166
|
+
this.pendingRequests.clear();
|
|
124167
|
+
}
|
|
124168
|
+
async parse(text) {
|
|
124169
|
+
this.ensureWorkers();
|
|
124170
|
+
const encodedText = this.encoder.encode(text);
|
|
124171
|
+
const requestId = this.nextRequestId++;
|
|
124172
|
+
return new Promise((resolve, reject) => {
|
|
124173
|
+
this.pendingRequests.set(requestId, {
|
|
124174
|
+
resolve,
|
|
124175
|
+
reject
|
|
124176
|
+
});
|
|
124177
|
+
this.workers[requestId % this.workers.length]?.postMessage({
|
|
124178
|
+
type: "parse",
|
|
124179
|
+
requestId,
|
|
124180
|
+
encodedText
|
|
124181
|
+
}, [encodedText.buffer]);
|
|
124182
|
+
});
|
|
124183
|
+
}
|
|
124184
|
+
async parseBytes(data) {
|
|
124185
|
+
this.ensureWorkers();
|
|
124186
|
+
const requestId = this.nextRequestId++;
|
|
124187
|
+
const ownedData = data.byteOffset === 0 && data.byteLength === data.buffer.byteLength ? data : data.slice();
|
|
124188
|
+
return new Promise((resolve, reject) => {
|
|
124189
|
+
this.pendingRequests.set(requestId, {
|
|
124190
|
+
resolve,
|
|
124191
|
+
reject
|
|
124192
|
+
});
|
|
124193
|
+
this.workers[requestId % this.workers.length]?.postMessage({
|
|
124194
|
+
type: "parse",
|
|
124195
|
+
requestId,
|
|
124196
|
+
encodedText: ownedData
|
|
124197
|
+
}, [ownedData.buffer]);
|
|
124198
|
+
});
|
|
124199
|
+
}
|
|
124200
|
+
terminate() {
|
|
124201
|
+
this.workers.forEach((w) => w.terminate());
|
|
124202
|
+
this.workers = [];
|
|
124203
|
+
if (this.blobURL) {
|
|
124204
|
+
URL.revokeObjectURL(this.blobURL);
|
|
124205
|
+
this.blobURL = null;
|
|
124206
|
+
}
|
|
124207
|
+
this.pendingRequests.clear();
|
|
124208
|
+
}
|
|
124209
|
+
};
|
|
124210
|
+
var workerPool = new JsonWorkerPool();
|
|
124211
|
+
var asyncJsonParse = async (text) => {
|
|
124212
|
+
if (text.length < 5e4) {
|
|
124213
|
+
let result = void 0;
|
|
124214
|
+
try {
|
|
124215
|
+
result = JSON.parse(text);
|
|
124216
|
+
} catch {
|
|
124217
|
+
result = import_dist.default.parse(text);
|
|
124218
|
+
}
|
|
124219
|
+
return Promise.resolve(result);
|
|
124220
|
+
} else return workerPool.parse(text);
|
|
124221
|
+
};
|
|
124222
|
+
/**
|
|
124223
|
+
* Parse JSON from raw UTF-8 bytes, avoiding redundant main-thread
|
|
124224
|
+
* string allocation for large payloads.
|
|
124225
|
+
*
|
|
124226
|
+
* For small data (<50KB) decodes and parses on the main thread.
|
|
124227
|
+
* For large data, transfers the bytes directly to a Web Worker,
|
|
124228
|
+
* skipping the main-thread TextDecoder.decode + TextEncoder.encode
|
|
124229
|
+
* round-trip that asyncJsonParse(string) would require.
|
|
124230
|
+
*/
|
|
124231
|
+
var asyncJsonParseBytes = async (data) => {
|
|
124232
|
+
if (data.length < 5e4) return jsonParse(new TextDecoder("utf-8").decode(data));
|
|
124233
|
+
else return workerPool.parseBytes(data);
|
|
124234
|
+
};
|
|
124235
|
+
var jsonParse = (text) => {
|
|
124236
|
+
try {
|
|
124237
|
+
return JSON.parse(text);
|
|
124238
|
+
} catch {
|
|
124239
|
+
return import_dist.default.parse(text);
|
|
124240
|
+
}
|
|
124241
|
+
};
|
|
124242
|
+
var kWorkerCode = `
|
|
124243
|
+
// Store the JSON5 parser once loaded
|
|
124244
|
+
let JSON5 = null;
|
|
124245
|
+
const decoder = new TextDecoder();
|
|
124246
|
+
const encoder = new TextEncoder();
|
|
124247
|
+
|
|
124248
|
+
self.onmessage = function (e) {
|
|
124249
|
+
const { type } = e.data || {};
|
|
124250
|
+
|
|
124251
|
+
if (type === 'init') {
|
|
124252
|
+
const { scriptContent } = e.data;
|
|
124253
|
+
try {
|
|
124254
|
+
if (!JSON5) {
|
|
124255
|
+
const script = atob(scriptContent);
|
|
124256
|
+
new Function(script)();
|
|
124257
|
+
if (typeof self.JSON5 !== 'object' || typeof self.JSON5.parse !== 'function') {
|
|
124258
|
+
throw new Error('Failed to initialize JSON5 parser');
|
|
124259
|
+
}
|
|
124260
|
+
JSON5 = self.JSON5;
|
|
124261
|
+
}
|
|
124262
|
+
} catch (err) {
|
|
124263
|
+
// nothing to respond to yet; worker will fail on first parse if init failed
|
|
124264
|
+
console.error('JSON5 init error in worker', err);
|
|
124265
|
+
}
|
|
124266
|
+
return;
|
|
124267
|
+
}
|
|
124268
|
+
|
|
124269
|
+
if (type === 'parse') {
|
|
124270
|
+
const { requestId, encodedText, scriptContent } = e.data;
|
|
124271
|
+
|
|
124272
|
+
try {
|
|
124273
|
+
|
|
124274
|
+
// Decode the text using TextDecoder
|
|
124275
|
+
const text = decoder.decode(encodedText);
|
|
124276
|
+
|
|
124277
|
+
// Parse with JSON/JSON5
|
|
124278
|
+
let result = undefined;
|
|
124279
|
+
try {
|
|
124280
|
+
// Optimistically, try a regular JSON parse first (this is much faster)
|
|
124281
|
+
result = JSON.parse(text);
|
|
124282
|
+
} catch {
|
|
124283
|
+
result = JSON5.parse(text);
|
|
124284
|
+
}
|
|
124285
|
+
|
|
124286
|
+
if (result && typeof result === 'object' &&
|
|
124287
|
+
(Array.isArray(result) ? result.length > 10000 : Object.keys(result).length > 10000)) {
|
|
124288
|
+
|
|
124289
|
+
// Large result, use transferrable object
|
|
124290
|
+
const resultString = JSON.stringify(result);
|
|
124291
|
+
const serialized = encoder.encode(resultString);
|
|
124292
|
+
|
|
124293
|
+
postMessage({
|
|
124294
|
+
requestId,
|
|
124295
|
+
success: true,
|
|
124296
|
+
serialized: true,
|
|
124297
|
+
result: serialized
|
|
124298
|
+
}, [serialized.buffer]);
|
|
124299
|
+
} else {
|
|
124300
|
+
// Small results, send directly
|
|
124301
|
+
postMessage({
|
|
124302
|
+
requestId,
|
|
124303
|
+
success: true,
|
|
124304
|
+
serialized: false,
|
|
124305
|
+
result: result
|
|
124306
|
+
});
|
|
124307
|
+
}
|
|
124308
|
+
} catch (err) {
|
|
124309
|
+
postMessage({
|
|
124310
|
+
requestId,
|
|
124311
|
+
success: false,
|
|
124312
|
+
error: err.message,
|
|
124313
|
+
stack: err.stack || ''
|
|
124314
|
+
});
|
|
124315
|
+
}
|
|
124316
|
+
}
|
|
124317
|
+
};`;
|
|
124318
|
+
var kJson5ScriptBase64 = `IWZ1bmN0aW9uKHUsRCl7Im9iamVjdCI9PXR5cGVvZiBleHBvcnRzJiYidW5kZWZpbmVkIiE9dHlwZW9mIG1vZHVsZT9tb2R1bGUuZXhwb3J0cz1EKCk6ImZ1bmN0aW9uIj09dHlwZW9mIGRlZmluZSYmZGVmaW5lLmFtZD9kZWZpbmUoRCk6dS5KU09ONT1EKCl9KHRoaXMsZnVuY3Rpb24oKXsidXNlIHN0cmljdCI7ZnVuY3Rpb24gdSh1LEQpe3JldHVybiB1KEQ9e2V4cG9ydHM6e319LEQuZXhwb3J0cyksRC5leHBvcnRzfXZhciBEPXUoZnVuY3Rpb24odSl7dmFyIEQ9dS5leHBvcnRzPSJ1bmRlZmluZWQiIT10eXBlb2Ygd2luZG93JiZ3aW5kb3cuTWF0aD09TWF0aD93aW5kb3c6InVuZGVmaW5lZCIhPXR5cGVvZiBzZWxmJiZzZWxmLk1hdGg9PU1hdGg/c2VsZjpGdW5jdGlvbigicmV0dXJuIHRoaXMiKSgpOyJudW1iZXIiPT10eXBlb2YgX19nJiYoX19nPUQpfSksZT11KGZ1bmN0aW9uKHUpe3ZhciBEPXUuZXhwb3J0cz17dmVyc2lvbjoiMi42LjUifTsibnVtYmVyIj09dHlwZW9mIF9fZSYmKF9fZT1EKX0pLHI9KGUudmVyc2lvbixmdW5jdGlvbih1KXtyZXR1cm4ib2JqZWN0Ij09dHlwZW9mIHU/bnVsbCE9PXU6ImZ1bmN0aW9uIj09dHlwZW9mIHV9KSx0PWZ1bmN0aW9uKHUpe2lmKCFyKHUpKXRocm93IFR5cGVFcnJvcih1KyIgaXMgbm90IGFuIG9iamVjdCEiKTtyZXR1cm4gdX0sbj1mdW5jdGlvbih1KXt0cnl7cmV0dXJuISF1KCl9Y2F0Y2godSl7cmV0dXJuITB9fSxGPSFuKGZ1bmN0aW9uKCl7cmV0dXJuIDchPU9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwiYSIse2dldDpmdW5jdGlvbigpe3JldHVybiA3fX0pLmF9KSxDPUQuZG9jdW1lbnQsQT1yKEMpJiZyKEMuY3JlYXRlRWxlbWVudCksaT0hRiYmIW4oZnVuY3Rpb24oKXtyZXR1cm4gNyE9T2JqZWN0LmRlZmluZVByb3BlcnR5KCh1PSJkaXYiLEE/Qy5jcmVhdGVFbGVtZW50KHUpOnt9KSwiYSIse2dldDpmdW5jdGlvbigpe3JldHVybiA3fX0pLmE7dmFyIHV9KSxFPU9iamVjdC5kZWZpbmVQcm9wZXJ0eSxvPXtmOkY/T2JqZWN0LmRlZmluZVByb3BlcnR5OmZ1bmN0aW9uKHUsRCxlKXtpZih0KHUpLEQ9ZnVuY3Rpb24odSxEKXtpZighcih1KSlyZXR1cm4gdTt2YXIgZSx0O2lmKEQmJiJmdW5jdGlvbiI9PXR5cGVvZihlPXUudG9TdHJpbmcpJiYhcih0PWUuY2FsbCh1KSkpcmV0dXJuIHQ7aWYoImZ1bmN0aW9uIj09dHlwZW9mKGU9dS52YWx1ZU9mKSYmIXIodD1lLmNhbGwodSkpKXJldHVybiB0O2lmKCFEJiYiZnVuY3Rpb24iPT10eXBlb2YoZT11LnRvU3RyaW5nKSYmIXIodD1lLmNhbGwodSkpKXJldHVybiB0O3Rocm93IFR5cGVFcnJvcigiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlIil9KEQsITApLHQoZSksaSl0cnl7cmV0dXJuIEUodSxELGUpfWNhdGNoKHUpe31pZigiZ2V0ImluIGV8fCJzZXQiaW4gZSl0aHJvdyBUeXBlRXJyb3IoIkFjY2Vzc29ycyBub3Qgc3VwcG9ydGVkISIpO3JldHVybiJ2YWx1ZSJpbiBlJiYodVtEXT1lLnZhbHVlKSx1fX0sYT1GP2Z1bmN0aW9uKHUsRCxlKXtyZXR1cm4gby5mKHUsRCxmdW5jdGlvbih1LEQpe3JldHVybntlbnVtZXJhYmxlOiEoMSZ1KSxjb25maWd1cmFibGU6ISgyJnUpLHdyaXRhYmxlOiEoNCZ1KSx2YWx1ZTpEfX0oMSxlKSl9OmZ1bmN0aW9uKHUsRCxlKXtyZXR1cm4gdVtEXT1lLHV9LGM9e30uaGFzT3duUHJvcGVydHksQj1mdW5jdGlvbih1LEQpe3JldHVybiBjLmNhbGwodSxEKX0scz0wLGY9TWF0aC5yYW5kb20oKSxsPXUoZnVuY3Rpb24odSl7dmFyIHI9RFsiX19jb3JlLWpzX3NoYXJlZF9fIl18fChEWyJfX2NvcmUtanNfc2hhcmVkX18iXT17fSk7KHUuZXhwb3J0cz1mdW5jdGlvbih1LEQpe3JldHVybiByW3VdfHwoclt1XT12b2lkIDAhPT1EP0Q6e30pfSkoInZlcnNpb25zIixbXSkucHVzaCh7dmVyc2lvbjplLnZlcnNpb24sbW9kZToiZ2xvYmFsIixjb3B5cmlnaHQ6IsKpIDIwMTkgRGVuaXMgUHVzaGthcmV2ICh6bG9pcm9jay5ydSkifSl9KSgibmF0aXZlLWZ1bmN0aW9uLXRvLXN0cmluZyIsRnVuY3Rpb24udG9TdHJpbmcpLGQ9dShmdW5jdGlvbih1KXt2YXIgcix0PSJTeW1ib2woIi5jb25jYXQodm9pZCAwPT09KHI9InNyYyIpPyIiOnIsIilfIiwoKytzK2YpLnRvU3RyaW5nKDM2KSksbj0oIiIrbCkuc3BsaXQoInRvU3RyaW5nIik7ZS5pbnNwZWN0U291cmNlPWZ1bmN0aW9uKHUpe3JldHVybiBsLmNhbGwodSl9LCh1LmV4cG9ydHM9ZnVuY3Rpb24odSxlLHIsRil7dmFyIEM9ImZ1bmN0aW9uIj09dHlwZW9mIHI7QyYmKEIociwibmFtZSIpfHxhKHIsIm5hbWUiLGUpKSx1W2VdIT09ciYmKEMmJihCKHIsdCl8fGEocix0LHVbZV0/IiIrdVtlXTpuLmpvaW4oU3RyaW5nKGUpKSkpLHU9PT1EP3VbZV09cjpGP3VbZV0/dVtlXT1yOmEodSxlLHIpOihkZWxldGUgdVtlXSxhKHUsZSxyKSkpfSkoRnVuY3Rpb24ucHJvdG90eXBlLCJ0b1N0cmluZyIsZnVuY3Rpb24oKXtyZXR1cm4iZnVuY3Rpb24iPT10eXBlb2YgdGhpcyYmdGhpc1t0XXx8bC5jYWxsKHRoaXMpfSl9KSx2PWZ1bmN0aW9uKHUsRCxlKXtpZihmdW5jdGlvbih1KXtpZigiZnVuY3Rpb24iIT10eXBlb2YgdSl0aHJvdyBUeXBlRXJyb3IodSsiIGlzIG5vdCBhIGZ1bmN0aW9uISIpfSh1KSx2b2lkIDA9PT1EKXJldHVybiB1O3N3aXRjaChlKXtjYXNlIDE6cmV0dXJuIGZ1bmN0aW9uKGUpe3JldHVybiB1LmNhbGwoRCxlKX07Y2FzZSAyOnJldHVybiBmdW5jdGlvbihlLHIpe3JldHVybiB1LmNhbGwoRCxlLHIpfTtjYXNlIDM6cmV0dXJuIGZ1bmN0aW9uKGUscix0KXtyZXR1cm4gdS5jYWxsKEQsZSxyLHQpfX1yZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdS5hcHBseShELGFyZ3VtZW50cyl9fSxwPWZ1bmN0aW9uKHUscix0KXt2YXIgbixGLEMsQSxpPXUmcC5GLEU9dSZwLkcsbz11JnAuUyxjPXUmcC5QLEI9dSZwLkIscz1FP0Q6bz9EW3JdfHwoRFtyXT17fSk6KERbcl18fHt9KS5wcm90b3R5cGUsZj1FP2U6ZVtyXXx8KGVbcl09e30pLGw9Zi5wcm90b3R5cGV8fChmLnByb3RvdHlwZT17fSk7Zm9yKG4gaW4gRSYmKHQ9ciksdClDPSgoRj0haSYmcyYmdm9pZCAwIT09c1tuXSk/czp0KVtuXSxBPUImJkY/dihDLEQpOmMmJiJmdW5jdGlvbiI9PXR5cGVvZiBDP3YoRnVuY3Rpb24uY2FsbCxDKTpDLHMmJmQocyxuLEMsdSZwLlUpLGZbbl0hPUMmJmEoZixuLEEpLGMmJmxbbl0hPUMmJihsW25dPUMpfTtELmNvcmU9ZSxwLkY9MSxwLkc9MixwLlM9NCxwLlA9OCxwLkI9MTYscC5XPTMyLHAuVT02NCxwLlI9MTI4O3ZhciBoLG09cCxnPU1hdGguY2VpbCx5PU1hdGguZmxvb3Isdz1mdW5jdGlvbih1KXtyZXR1cm4gaXNOYU4odT0rdSk/MDoodT4wP3k6ZykodSl9LGI9KGg9ITEsZnVuY3Rpb24odSxEKXt2YXIgZSxyLHQ9U3RyaW5nKGZ1bmN0aW9uKHUpe2lmKG51bGw9PXUpdGhyb3cgVHlwZUVycm9yKCJDYW4ndCBjYWxsIG1ldGhvZCBvbiAgIit1KTtyZXR1cm4gdX0odSkpLG49dyhEKSxGPXQubGVuZ3RoO3JldHVybiBuPDB8fG4+PUY/aD8iIjp2b2lkIDA6KGU9dC5jaGFyQ29kZUF0KG4pKTw1NTI5Nnx8ZT41NjMxOXx8bisxPT09Rnx8KHI9dC5jaGFyQ29kZUF0KG4rMSkpPDU2MzIwfHxyPjU3MzQzP2g/dC5jaGFyQXQobik6ZTpoP3Quc2xpY2UobixuKzIpOnItNTYzMjArKGUtNTUyOTY8PDEwKSs2NTUzNn0pO20obS5QLCJTdHJpbmciLHtjb2RlUG9pbnRBdDpmdW5jdGlvbih1KXtyZXR1cm4gYih0aGlzLHUpfX0pO2UuU3RyaW5nLmNvZGVQb2ludEF0O3ZhciBTPU1hdGgubWF4LHg9TWF0aC5taW4sTj1TdHJpbmcuZnJvbUNoYXJDb2RlLFA9U3RyaW5nLmZyb21Db2RlUG9pbnQ7bShtLlMrbS5GKighIVAmJjEhPVAubGVuZ3RoKSwiU3RyaW5nIix7ZnJvbUNvZGVQb2ludDpmdW5jdGlvbih1KXtmb3IodmFyIEQsZSxyLHQ9YXJndW1lbnRzLG49W10sRj1hcmd1bWVudHMubGVuZ3RoLEM9MDtGPkM7KXtpZihEPSt0W0MrK10scj0xMTE0MTExLCgoZT13KGU9RCkpPDA/UyhlK3IsMCk6eChlLHIpKSE9PUQpdGhyb3cgUmFuZ2VFcnJvcihEKyIgaXMgbm90IGEgdmFsaWQgY29kZSBwb2ludCIpO24ucHVzaChEPDY1NTM2P04oRCk6Tig1NTI5NisoKEQtPTY1NTM2KT4+MTApLEQlMTAyNCs1NjMyMCkpfXJldHVybiBuLmpvaW4oIiIpfX0pO2UuU3RyaW5nLmZyb21Db2RlUG9pbnQ7dmFyIF8sTyxqLEksVixKLE0sayxMLFQseixILCQsUixHPXtTcGFjZV9TZXBhcmF0b3I6L1tcdTE2ODBcdTIwMDAtXHUyMDBBXHUyMDJGXHUyMDVGXHUzMDAwXS8sSURfU3RhcnQ6L1tceEFBXHhCNVx4QkFceEMwLVx4RDZceEQ4LVx4RjZceEY4LVx1MDJDMVx1MDJDNi1cdTAyRDFcdTAyRTAtXHUwMkU0XHUwMkVDXHUwMkVFXHUwMzcwLVx1MDM3NFx1MDM3Nlx1MDM3N1x1MDM3QS1cdTAzN0RcdTAzN0ZcdTAzODZcdTAzODgtXHUwMzhBXHUwMzhDXHUwMzhFLVx1MDNBMVx1MDNBMy1cdTAzRjVcdTAzRjctXHUwNDgxXHUwNDhBLVx1MDUyRlx1MDUzMS1cdTA1NTZcdTA1NTlcdTA1NjEtXHUwNTg3XHUwNUQwLVx1MDVFQVx1MDVGMC1cdTA1RjJcdTA2MjAtXHUwNjRBXHUwNjZFXHUwNjZGXHUwNjcxLVx1MDZEM1x1MDZENVx1MDZFNVx1MDZFNlx1MDZFRVx1MDZFRlx1MDZGQS1cdTA2RkNcdTA2RkZcdTA3MTBcdTA3MTItXHUwNzJGXHUwNzRELVx1MDdBNVx1MDdCMVx1MDdDQS1cdTA3RUFcdTA3RjRcdTA3RjVcdTA3RkFcdTA4MDAtXHUwODE1XHUwODFBXHUwODI0XHUwODI4XHUwODQwLVx1MDg1OFx1MDg2MC1cdTA4NkFcdTA4QTAtXHUwOEI0XHUwOEI2LVx1MDhCRFx1MDkwNC1cdTA5MzlcdTA5M0RcdTA5NTBcdTA5NTgtXHUwOTYxXHUwOTcxLVx1MDk4MFx1MDk4NS1cdTA5OENcdTA5OEZcdTA5OTBcdTA5OTMtXHUwOUE4XHUwOUFBLVx1MDlCMFx1MDlCMlx1MDlCNi1cdTA5QjlcdTA5QkRcdTA5Q0VcdTA5RENcdTA5RERcdTA5REYtXHUwOUUxXHUwOUYwXHUwOUYxXHUwOUZDXHUwQTA1LVx1MEEwQVx1MEEwRlx1MEExMFx1MEExMy1cdTBBMjhcdTBBMkEtXHUwQTMwXHUwQTMyXHUwQTMzXHUwQTM1XHUwQTM2XHUwQTM4XHUwQTM5XHUwQTU5LVx1MEE1Q1x1MEE1RVx1MEE3Mi1cdTBBNzRcdTBBODUtXHUwQThEXHUwQThGLVx1MEE5MVx1MEE5My1cdTBBQThcdTBBQUEtXHUwQUIwXHUwQUIyXHUwQUIzXHUwQUI1LVx1MEFCOVx1MEFCRFx1MEFEMFx1MEFFMFx1MEFFMVx1MEFGOVx1MEIwNS1cdTBCMENcdTBCMEZcdTBCMTBcdTBCMTMtXHUwQjI4XHUwQjJBLVx1MEIzMFx1MEIzMlx1MEIzM1x1MEIzNS1cdTBCMzlcdTBCM0RcdTBCNUNcdTBCNURcdTBCNUYtXHUwQjYxXHUwQjcxXHUwQjgzXHUwQjg1LVx1MEI4QVx1MEI4RS1cdTBCOTBcdTBCOTItXHUwQjk1XHUwQjk5XHUwQjlBXHUwQjlDXHUwQjlFXHUwQjlGXHUwQkEzXHUwQkE0XHUwQkE4LVx1MEJBQVx1MEJBRS1cdTBCQjlcdTBCRDBcdTBDMDUtXHUwQzBDXHUwQzBFLVx1MEMxMFx1MEMxMi1cdTBDMjhcdTBDMkEtXHUwQzM5XHUwQzNEXHUwQzU4LVx1MEM1QVx1MEM2MFx1MEM2MVx1MEM4MFx1MEM4NS1cdTBDOENcdTBDOEUtXHUwQzkwXHUwQzkyLVx1MENBOFx1MENBQS1cdTBDQjNcdTBDQjUtXHUwQ0I5XHUwQ0JEXHUwQ0RFXHUwQ0UwXHUwQ0UxXHUwQ0YxXHUwQ0YyXHUwRDA1LVx1MEQwQ1x1MEQwRS1cdTBEMTBcdTBEMTItXHUwRDNBXHUwRDNEXHUwRDRFXHUwRDU0LVx1MEQ1Nlx1MEQ1Ri1cdTBENjFcdTBEN0EtXHUwRDdGXHUwRDg1LVx1MEQ5Nlx1MEQ5QS1cdTBEQjFcdTBEQjMtXHUwREJCXHUwREJEXHUwREMwLVx1MERDNlx1MEUwMS1cdTBFMzBcdTBFMzJcdTBFMzNcdTBFNDAtXHUwRTQ2XHUwRTgxXHUwRTgyXHUwRTg0XHUwRTg3XHUwRTg4XHUwRThBXHUwRThEXHUwRTk0LVx1MEU5N1x1MEU5OS1cdTBFOUZcdTBFQTEtXHUwRUEzXHUwRUE1XHUwRUE3XHUwRUFBXHUwRUFCXHUwRUFELVx1MEVCMFx1MEVCMlx1MEVCM1x1MEVCRFx1MEVDMC1cdTBFQzRcdTBFQzZcdTBFREMtXHUwRURGXHUwRjAwXHUwRjQwLVx1MEY0N1x1MEY0OS1cdTBGNkNcdTBGODgtXHUwRjhDXHUxMDAwLVx1MTAyQVx1MTAzRlx1MTA1MC1cdTEwNTVcdTEwNUEtXHUxMDVEXHUxMDYxXHUxMDY1XHUxMDY2XHUxMDZFLVx1MTA3MFx1MTA3NS1cdTEwODFcdTEwOEVcdTEwQTAtXHUxMEM1XHUxMEM3XHUxMENEXHUxMEQwLVx1MTBGQVx1MTBGQy1cdTEyNDhcdTEyNEEtXHUxMjREXHUxMjUwLVx1MTI1Nlx1MTI1OFx1MTI1QS1cdTEyNURcdTEyNjAtXHUxMjg4XHUxMjhBLVx1MTI4RFx1MTI5MC1cdTEyQjBcdTEyQjItXHUxMkI1XHUxMkI4LVx1MTJCRVx1MTJDMFx1MTJDMi1cdTEyQzVcdTEyQzgtXHUxMkQ2XHUxMkQ4LVx1MTMxMFx1MTMxMi1cdTEzMTVcdTEzMTgtXHUxMzVBXHUxMzgwLVx1MTM4Rlx1MTNBMC1cdTEzRjVcdTEzRjgtXHUxM0ZEXHUxNDAxLVx1MTY2Q1x1MTY2Ri1cdTE2N0ZcdTE2ODEtXHUxNjlBXHUxNkEwLVx1MTZFQVx1MTZFRS1cdTE2RjhcdTE3MDAtXHUxNzBDXHUxNzBFLVx1MTcxMVx1MTcyMC1cdTE3MzFcdTE3NDAtXHUxNzUxXHUxNzYwLVx1MTc2Q1x1MTc2RS1cdTE3NzBcdTE3ODAtXHUxN0IzXHUxN0Q3XHUxN0RDXHUxODIwLVx1MTg3N1x1MTg4MC1cdTE4ODRcdTE4ODctXHUxOEE4XHUxOEFBXHUxOEIwLVx1MThGNVx1MTkwMC1cdTE5MUVcdTE5NTAtXHUxOTZEXHUxOTcwLVx1MTk3NFx1MTk4MC1cdTE5QUJcdTE5QjAtXHUxOUM5XHUxQTAwLVx1MUExNlx1MUEyMC1cdTFBNTRcdTFBQTdcdTFCMDUtXHUxQjMzXHUxQjQ1LVx1MUI0Qlx1MUI4My1cdTFCQTBcdTFCQUVcdTFCQUZcdTFCQkEtXHUxQkU1XHUxQzAwLVx1MUMyM1x1MUM0RC1cdTFDNEZcdTFDNUEtXHUxQzdEXHUxQzgwLVx1MUM4OFx1MUNFOS1cdTFDRUNcdTFDRUUtXHUxQ0YxXHUxQ0Y1XHUxQ0Y2XHUxRDAwLVx1MURCRlx1MUUwMC1cdTFGMTVcdTFGMTgtXHUxRjFEXHUxRjIwLVx1MUY0NVx1MUY0OC1cdTFGNERcdTFGNTAtXHUxRjU3XHUxRjU5XHUxRjVCXHUxRjVEXHUxRjVGLVx1MUY3RFx1MUY4MC1cdTFGQjRcdTFGQjYtXHUxRkJDXHUxRkJFXHUxRkMyLVx1MUZDNFx1MUZDNi1cdTFGQ0NcdTFGRDAtXHUxRkQzXHUxRkQ2LVx1MUZEQlx1MUZFMC1cdTFGRUNcdTFGRjItXHUxRkY0XHUxRkY2LVx1MUZGQ1x1MjA3MVx1MjA3Rlx1MjA5MC1cdTIwOUNcdTIxMDJcdTIxMDdcdTIxMEEtXHUyMTEzXHUyMTE1XHUyMTE5LVx1MjExRFx1MjEyNFx1MjEyNlx1MjEyOFx1MjEyQS1cdTIxMkRcdTIxMkYtXHUyMTM5XHUyMTNDLVx1MjEzRlx1MjE0NS1cdTIxNDlcdTIxNEVcdTIxNjAtXHUyMTg4XHUyQzAwLVx1MkMyRVx1MkMzMC1cdTJDNUVcdTJDNjAtXHUyQ0U0XHUyQ0VCLVx1MkNFRVx1MkNGMlx1MkNGM1x1MkQwMC1cdTJEMjVcdTJEMjdcdTJEMkRcdTJEMzAtXHUyRDY3XHUyRDZGXHUyRDgwLVx1MkQ5Nlx1MkRBMC1cdTJEQTZcdTJEQTgtXHUyREFFXHUyREIwLVx1MkRCNlx1MkRCOC1cdTJEQkVcdTJEQzAtXHUyREM2XHUyREM4LVx1MkRDRVx1MkREMC1cdTJERDZcdTJERDgtXHUyRERFXHUyRTJGXHUzMDA1LVx1MzAwN1x1MzAyMS1cdTMwMjlcdTMwMzEtXHUzMDM1XHUzMDM4LVx1MzAzQ1x1MzA0MS1cdTMwOTZcdTMwOUQtXHUzMDlGXHUzMEExLVx1MzBGQVx1MzBGQy1cdTMwRkZcdTMxMDUtXHUzMTJFXHUzMTMxLVx1MzE4RVx1MzFBMC1cdTMxQkFcdTMxRjAtXHUzMUZGXHUzNDAwLVx1NERCNVx1NEUwMC1cdTlGRUFcdUEwMDAtXHVBNDhDXHVBNEQwLVx1QTRGRFx1QTUwMC1cdUE2MENcdUE2MTAtXHVBNjFGXHVBNjJBXHVBNjJCXHVBNjQwLVx1QTY2RVx1QTY3Ri1cdUE2OURcdUE2QTAtXHVBNkVGXHVBNzE3LVx1QTcxRlx1QTcyMi1cdUE3ODhcdUE3OEItXHVBN0FFXHVBN0IwLVx1QTdCN1x1QTdGNy1cdUE4MDFcdUE4MDMtXHVBODA1XHVBODA3LVx1QTgwQVx1QTgwQy1cdUE4MjJcdUE4NDAtXHVBODczXHVBODgyLVx1QThCM1x1QThGMi1cdUE4RjdcdUE4RkJcdUE4RkRcdUE5MEEtXHVBOTI1XHVBOTMwLVx1QTk0Nlx1QTk2MC1cdUE5N0NcdUE5ODQtXHVBOUIyXHVBOUNGXHVBOUUwLVx1QTlFNFx1QTlFNi1cdUE5RUZcdUE5RkEtXHVBOUZFXHVBQTAwLVx1QUEyOFx1QUE0MC1cdUFBNDJcdUFBNDQtXHVBQTRCXHVBQTYwLVx1QUE3Nlx1QUE3QVx1QUE3RS1cdUFBQUZcdUFBQjFcdUFBQjVcdUFBQjZcdUFBQjktXHVBQUJEXHVBQUMwXHVBQUMyXHVBQURCLVx1QUFERFx1QUFFMC1cdUFBRUFcdUFBRjItXHVBQUY0XHVBQjAxLVx1QUIwNlx1QUIwOS1cdUFCMEVcdUFCMTEtXHVBQjE2XHVBQjIwLVx1QUIyNlx1QUIyOC1cdUFCMkVcdUFCMzAtXHVBQjVBXHVBQjVDLVx1QUI2NVx1QUI3MC1cdUFCRTJcdUFDMDAtXHVEN0EzXHVEN0IwLVx1RDdDNlx1RDdDQi1cdUQ3RkJcdUY5MDAtXHVGQTZEXHVGQTcwLVx1RkFEOVx1RkIwMC1cdUZCMDZcdUZCMTMtXHVGQjE3XHVGQjFEXHVGQjFGLVx1RkIyOFx1RkIyQS1cdUZCMzZcdUZCMzgtXHVGQjNDXHVGQjNFXHVGQjQwXHVGQjQxXHVGQjQzXHVGQjQ0XHVGQjQ2LVx1RkJCMVx1RkJEMy1cdUZEM0RcdUZENTAtXHVGRDhGXHVGRDkyLVx1RkRDN1x1RkRGMC1cdUZERkJcdUZFNzAtXHVGRTc0XHVGRTc2LVx1RkVGQ1x1RkYyMS1cdUZGM0FcdUZGNDEtXHVGRjVBXHVGRjY2LVx1RkZCRVx1RkZDMi1cdUZGQzdcdUZGQ0EtXHVGRkNGXHVGRkQyLVx1RkZEN1x1RkZEQS1cdUZGRENdfFx1RDgwMFtcdURDMDAtXHVEQzBCXHVEQzBELVx1REMyNlx1REMyOC1cdURDM0FcdURDM0NcdURDM0RcdURDM0YtXHVEQzREXHVEQzUwLVx1REM1RFx1REM4MC1cdURDRkFcdURENDAtXHVERDc0XHVERTgwLVx1REU5Q1x1REVBMC1cdURFRDBcdURGMDAtXHVERjFGXHVERjJELVx1REY0QVx1REY1MC1cdURGNzVcdURGODAtXHVERjlEXHVERkEwLVx1REZDM1x1REZDOC1cdURGQ0ZcdURGRDEtXHVERkQ1XXxcdUQ4MDFbXHVEQzAwLVx1REM5RFx1RENCMC1cdURDRDNcdURDRDgtXHVEQ0ZCXHVERDAwLVx1REQyN1x1REQzMC1cdURENjNcdURFMDAtXHVERjM2XHVERjQwLVx1REY1NVx1REY2MC1cdURGNjddfFx1RDgwMltcdURDMDAtXHVEQzA1XHVEQzA4XHVEQzBBLVx1REMzNVx1REMzN1x1REMzOFx1REMzQ1x1REMzRi1cdURDNTVcdURDNjAtXHVEQzc2XHVEQzgwLVx1REM5RVx1RENFMC1cdURDRjJcdURDRjRcdURDRjVcdUREMDAtXHVERDE1XHVERDIwLVx1REQzOVx1REQ4MC1cdUREQjdcdUREQkVcdUREQkZcdURFMDBcdURFMTAtXHVERTEzXHVERTE1LVx1REUxN1x1REUxOS1cdURFMzNcdURFNjAtXHVERTdDXHVERTgwLVx1REU5Q1x1REVDMC1cdURFQzdcdURFQzktXHVERUU0XHVERjAwLVx1REYzNVx1REY0MC1cdURGNTVcdURGNjAtXHVERjcyXHVERjgwLVx1REY5MV18XHVEODAzW1x1REMwMC1cdURDNDhcdURDODAtXHVEQ0IyXHVEQ0MwLVx1RENGMl18XHVEODA0W1x1REMwMy1cdURDMzdcdURDODMtXHVEQ0FGXHVEQ0QwLVx1RENFOFx1REQwMy1cdUREMjZcdURENTAtXHVERDcyXHVERDc2XHVERDgzLVx1RERCMlx1RERDMS1cdUREQzRcdUREREFcdURERENcdURFMDAtXHVERTExXHVERTEzLVx1REUyQlx1REU4MC1cdURFODZcdURFODhcdURFOEEtXHVERThEXHVERThGLVx1REU5RFx1REU5Ri1cdURFQThcdURFQjAtXHVERURFXHVERjA1LVx1REYwQ1x1REYwRlx1REYxMFx1REYxMy1cdURGMjhcdURGMkEtXHVERjMwXHVERjMyXHVERjMzXHVERjM1LVx1REYzOVx1REYzRFx1REY1MFx1REY1RC1cdURGNjFdfFx1RDgwNVtcdURDMDAtXHVEQzM0XHVEQzQ3LVx1REM0QVx1REM4MC1cdURDQUZcdURDQzRcdURDQzVcdURDQzdcdUREODAtXHVEREFFXHVEREQ4LVx1REREQlx1REUwMC1cdURFMkZcdURFNDRcdURFODAtXHVERUFBXHVERjAwLVx1REYxOV18XHVEODA2W1x1RENBMC1cdURDREZcdURDRkZcdURFMDBcdURFMEItXHVERTMyXHVERTNBXHVERTUwXHVERTVDLVx1REU4M1x1REU4Ni1cdURFODlcdURFQzAtXHVERUY4XXxcdUQ4MDdbXHVEQzAwLVx1REMwOFx1REMwQS1cdURDMkVcdURDNDBcdURDNzItXHVEQzhGXHVERDAwLVx1REQwNlx1REQwOFx1REQwOVx1REQwQi1cdUREMzBcdURENDZdfFx1RDgwOFtcdURDMDAtXHVERjk5XXxcdUQ4MDlbXHVEQzAwLVx1REM2RVx1REM4MC1cdURENDNdfFtcdUQ4MENcdUQ4MUMtXHVEODIwXHVEODQwLVx1RDg2OFx1RDg2QS1cdUQ4NkNcdUQ4NkYtXHVEODcyXHVEODc0LVx1RDg3OV1bXHVEQzAwLVx1REZGRl18XHVEODBEW1x1REMwMC1cdURDMkVdfFx1RDgxMVtcdURDMDAtXHVERTQ2XXxcdUQ4MUFbXHVEQzAwLVx1REUzOFx1REU0MC1cdURFNUVcdURFRDAtXHVERUVEXHVERjAwLVx1REYyRlx1REY0MC1cdURGNDNcdURGNjMtXHVERjc3XHVERjdELVx1REY4Rl18XHVEODFCW1x1REYwMC1cdURGNDRcdURGNTBcdURGOTMtXHVERjlGXHVERkUwXHVERkUxXXxcdUQ4MjFbXHVEQzAwLVx1REZFQ118XHVEODIyW1x1REMwMC1cdURFRjJdfFx1RDgyQ1tcdURDMDAtXHVERDFFXHVERDcwLVx1REVGQl18XHVEODJGW1x1REMwMC1cdURDNkFcdURDNzAtXHVEQzdDXHVEQzgwLVx1REM4OFx1REM5MC1cdURDOTldfFx1RDgzNVtcdURDMDAtXHVEQzU0XHVEQzU2LVx1REM5Q1x1REM5RVx1REM5Rlx1RENBMlx1RENBNVx1RENBNlx1RENBOS1cdURDQUNcdURDQUUtXHVEQ0I5XHVEQ0JCXHVEQ0JELVx1RENDM1x1RENDNS1cdUREMDVcdUREMDctXHVERDBBXHVERDBELVx1REQxNFx1REQxNi1cdUREMUNcdUREMUUtXHVERDM5XHVERDNCLVx1REQzRVx1REQ0MC1cdURENDRcdURENDZcdURENEEtXHVERDUwXHVERDUyLVx1REVBNVx1REVBOC1cdURFQzBcdURFQzItXHVERURBXHVERURDLVx1REVGQVx1REVGQy1cdURGMTRcdURGMTYtXHVERjM0XHVERjM2LVx1REY0RVx1REY1MC1cdURGNkVcdURGNzAtXHVERjg4XHVERjhBLVx1REZBOFx1REZBQS1cdURGQzJcdURGQzQtXHVERkNCXXxcdUQ4M0FbXHVEQzAwLVx1RENDNFx1REQwMC1cdURENDNdfFx1RDgzQltcdURFMDAtXHVERTAzXHVERTA1LVx1REUxRlx1REUyMVx1REUyMlx1REUyNFx1REUyN1x1REUyOS1cdURFMzJcdURFMzQtXHVERTM3XHVERTM5XHVERTNCXHVERTQyXHVERTQ3XHVERTQ5XHVERTRCXHVERTRELVx1REU0Rlx1REU1MVx1REU1Mlx1REU1NFx1REU1N1x1REU1OVx1REU1Qlx1REU1RFx1REU1Rlx1REU2MVx1REU2Mlx1REU2NFx1REU2Ny1cdURFNkFcdURFNkMtXHVERTcyXHVERTc0LVx1REU3N1x1REU3OS1cdURFN0NcdURFN0VcdURFODAtXHVERTg5XHVERThCLVx1REU5Qlx1REVBMS1cdURFQTNcdURFQTUtXHVERUE5XHVERUFCLVx1REVCQl18XHVEODY5W1x1REMwMC1cdURFRDZcdURGMDAtXHVERkZGXXxcdUQ4NkRbXHVEQzAwLVx1REYzNFx1REY0MC1cdURGRkZdfFx1RDg2RVtcdURDMDAtXHVEQzFEXHVEQzIwLVx1REZGRl18XHVEODczW1x1REMwMC1cdURFQTFcdURFQjAtXHVERkZGXXxcdUQ4N0FbXHVEQzAwLVx1REZFMF18XHVEODdFW1x1REMwMC1cdURFMURdLyxJRF9Db250aW51ZTovW1x4QUFceEI1XHhCQVx4QzAtXHhENlx4RDgtXHhGNlx4RjgtXHUwMkMxXHUwMkM2LVx1MDJEMVx1MDJFMC1cdTAyRTRcdTAyRUNcdTAyRUVcdTAzMDAtXHUwMzc0XHUwMzc2XHUwMzc3XHUwMzdBLVx1MDM3RFx1MDM3Rlx1MDM4Nlx1MDM4OC1cdTAzOEFcdTAzOENcdTAzOEUtXHUwM0ExXHUwM0EzLVx1MDNGNVx1MDNGNy1cdTA0ODFcdTA0ODMtXHUwNDg3XHUwNDhBLVx1MDUyRlx1MDUzMS1cdTA1NTZcdTA1NTlcdTA1NjEtXHUwNTg3XHUwNTkxLVx1MDVCRFx1MDVCRlx1MDVDMVx1MDVDMlx1MDVDNFx1MDVDNVx1MDVDN1x1MDVEMC1cdTA1RUFcdTA1RjAtXHUwNUYyXHUwNjEwLVx1MDYxQVx1MDYyMC1cdTA2NjlcdTA2NkUtXHUwNkQzXHUwNkQ1LVx1MDZEQ1x1MDZERi1cdTA2RThcdTA2RUEtXHUwNkZDXHUwNkZGXHUwNzEwLVx1MDc0QVx1MDc0RC1cdTA3QjFcdTA3QzAtXHUwN0Y1XHUwN0ZBXHUwODAwLVx1MDgyRFx1MDg0MC1cdTA4NUJcdTA4NjAtXHUwODZBXHUwOEEwLVx1MDhCNFx1MDhCNi1cdTA4QkRcdTA4RDQtXHUwOEUxXHUwOEUzLVx1MDk2M1x1MDk2Ni1cdTA5NkZcdTA5NzEtXHUwOTgzXHUwOTg1LVx1MDk4Q1x1MDk4Rlx1MDk5MFx1MDk5My1cdTA5QThcdTA5QUEtXHUwOUIwXHUwOUIyXHUwOUI2LVx1MDlCOVx1MDlCQy1cdTA5QzRcdTA5QzdcdTA5QzhcdTA5Q0ItXHUwOUNFXHUwOUQ3XHUwOURDXHUwOUREXHUwOURGLVx1MDlFM1x1MDlFNi1cdTA5RjFcdTA5RkNcdTBBMDEtXHUwQTAzXHUwQTA1LVx1MEEwQVx1MEEwRlx1MEExMFx1MEExMy1cdTBBMjhcdTBBMkEtXHUwQTMwXHUwQTMyXHUwQTMzXHUwQTM1XHUwQTM2XHUwQTM4XHUwQTM5XHUwQTNDXHUwQTNFLVx1MEE0Mlx1MEE0N1x1MEE0OFx1MEE0Qi1cdTBBNERcdTBBNTFcdTBBNTktXHUwQTVDXHUwQTVFXHUwQTY2LVx1MEE3NVx1MEE4MS1cdTBBODNcdTBBODUtXHUwQThEXHUwQThGLVx1MEE5MVx1MEE5My1cdTBBQThcdTBBQUEtXHUwQUIwXHUwQUIyXHUwQUIzXHUwQUI1LVx1MEFCOVx1MEFCQy1cdTBBQzVcdTBBQzctXHUwQUM5XHUwQUNCLVx1MEFDRFx1MEFEMFx1MEFFMC1cdTBBRTNcdTBBRTYtXHUwQUVGXHUwQUY5LVx1MEFGRlx1MEIwMS1cdTBCMDNcdTBCMDUtXHUwQjBDXHUwQjBGXHUwQjEwXHUwQjEzLVx1MEIyOFx1MEIyQS1cdTBCMzBcdTBCMzJcdTBCMzNcdTBCMzUtXHUwQjM5XHUwQjNDLVx1MEI0NFx1MEI0N1x1MEI0OFx1MEI0Qi1cdTBCNERcdTBCNTZcdTBCNTdcdTBCNUNcdTBCNURcdTBCNUYtXHUwQjYzXHUwQjY2LVx1MEI2Rlx1MEI3MVx1MEI4Mlx1MEI4M1x1MEI4NS1cdTBCOEFcdTBCOEUtXHUwQjkwXHUwQjkyLVx1MEI5NVx1MEI5OVx1MEI5QVx1MEI5Q1x1MEI5RVx1MEI5Rlx1MEJBM1x1MEJBNFx1MEJBOC1cdTBCQUFcdTBCQUUtXHUwQkI5XHUwQkJFLVx1MEJDMlx1MEJDNi1cdTBCQzhcdTBCQ0EtXHUwQkNEXHUwQkQwXHUwQkQ3XHUwQkU2LVx1MEJFRlx1MEMwMC1cdTBDMDNcdTBDMDUtXHUwQzBDXHUwQzBFLVx1MEMxMFx1MEMxMi1cdTBDMjhcdTBDMkEtXHUwQzM5XHUwQzNELVx1MEM0NFx1MEM0Ni1cdTBDNDhcdTBDNEEtXHUwQzREXHUwQzU1XHUwQzU2XHUwQzU4LVx1MEM1QVx1MEM2MC1cdTBDNjNcdTBDNjYtXHUwQzZGXHUwQzgwLVx1MEM4M1x1MEM4NS1cdTBDOENcdTBDOEUtXHUwQzkwXHUwQzkyLVx1MENBOFx1MENBQS1cdTBDQjNcdTBDQjUtXHUwQ0I5XHUwQ0JDLVx1MENDNFx1MENDNi1cdTBDQzhcdTBDQ0EtXHUwQ0NEXHUwQ0Q1XHUwQ0Q2XHUwQ0RFXHUwQ0UwLVx1MENFM1x1MENFNi1cdTBDRUZcdTBDRjFcdTBDRjJcdTBEMDAtXHUwRDAzXHUwRDA1LVx1MEQwQ1x1MEQwRS1cdTBEMTBcdTBEMTItXHUwRDQ0XHUwRDQ2LVx1MEQ0OFx1MEQ0QS1cdTBENEVcdTBENTQtXHUwRDU3XHUwRDVGLVx1MEQ2M1x1MEQ2Ni1cdTBENkZcdTBEN0EtXHUwRDdGXHUwRDgyXHUwRDgzXHUwRDg1LVx1MEQ5Nlx1MEQ5QS1cdTBEQjFcdTBEQjMtXHUwREJCXHUwREJEXHUwREMwLVx1MERDNlx1MERDQVx1MERDRi1cdTBERDRcdTBERDZcdTBERDgtXHUwRERGXHUwREU2LVx1MERFRlx1MERGMlx1MERGM1x1MEUwMS1cdTBFM0FcdTBFNDAtXHUwRTRFXHUwRTUwLVx1MEU1OVx1MEU4MVx1MEU4Mlx1MEU4NFx1MEU4N1x1MEU4OFx1MEU4QVx1MEU4RFx1MEU5NC1cdTBFOTdcdTBFOTktXHUwRTlGXHUwRUExLVx1MEVBM1x1MEVBNVx1MEVBN1x1MEVBQVx1MEVBQlx1MEVBRC1cdTBFQjlcdTBFQkItXHUwRUJEXHUwRUMwLVx1MEVDNFx1MEVDNlx1MEVDOC1cdTBFQ0RcdTBFRDAtXHUwRUQ5XHUwRURDLVx1MEVERlx1MEYwMFx1MEYxOFx1MEYxOVx1MEYyMC1cdTBGMjlcdTBGMzVcdTBGMzdcdTBGMzlcdTBGM0UtXHUwRjQ3XHUwRjQ5LVx1MEY2Q1x1MEY3MS1cdTBGODRcdTBGODYtXHUwRjk3XHUwRjk5LVx1MEZCQ1x1MEZDNlx1MTAwMC1cdTEwNDlcdTEwNTAtXHUxMDlEXHUxMEEwLVx1MTBDNVx1MTBDN1x1MTBDRFx1MTBEMC1cdTEwRkFcdTEwRkMtXHUxMjQ4XHUxMjRBLVx1MTI0RFx1MTI1MC1cdTEyNTZcdTEyNThcdTEyNUEtXHUxMjVEXHUxMjYwLVx1MTI4OFx1MTI4QS1cdTEyOERcdTEyOTAtXHUxMkIwXHUxMkIyLVx1MTJCNVx1MTJCOC1cdTEyQkVcdTEyQzBcdTEyQzItXHUxMkM1XHUxMkM4LVx1MTJENlx1MTJEOC1cdTEzMTBcdTEzMTItXHUxMzE1XHUxMzE4LVx1MTM1QVx1MTM1RC1cdTEzNUZcdTEzODAtXHUxMzhGXHUxM0EwLVx1MTNGNVx1MTNGOC1cdTEzRkRcdTE0MDEtXHUxNjZDXHUxNjZGLVx1MTY3Rlx1MTY4MS1cdTE2OUFcdTE2QTAtXHUxNkVBXHUxNkVFLVx1MTZGOFx1MTcwMC1cdTE3MENcdTE3MEUtXHUxNzE0XHUxNzIwLVx1MTczNFx1MTc0MC1cdTE3NTNcdTE3NjAtXHUxNzZDXHUxNzZFLVx1MTc3MFx1MTc3Mlx1MTc3M1x1MTc4MC1cdTE3RDNcdTE3RDdcdTE3RENcdTE3RERcdTE3RTAtXHUxN0U5XHUxODBCLVx1MTgwRFx1MTgxMC1cdTE4MTlcdTE4MjAtXHUxODc3XHUxODgwLVx1MThBQVx1MThCMC1cdTE4RjVcdTE5MDAtXHUxOTFFXHUxOTIwLVx1MTkyQlx1MTkzMC1cdTE5M0JcdTE5NDYtXHUxOTZEXHUxOTcwLVx1MTk3NFx1MTk4MC1cdTE5QUJcdTE5QjAtXHUxOUM5XHUxOUQwLVx1MTlEOVx1MUEwMC1cdTFBMUJcdTFBMjAtXHUxQTVFXHUxQTYwLVx1MUE3Q1x1MUE3Ri1cdTFBODlcdTFBOTAtXHUxQTk5XHUxQUE3XHUxQUIwLVx1MUFCRFx1MUIwMC1cdTFCNEJcdTFCNTAtXHUxQjU5XHUxQjZCLVx1MUI3M1x1MUI4MC1cdTFCRjNcdTFDMDAtXHUxQzM3XHUxQzQwLVx1MUM0OVx1MUM0RC1cdTFDN0RcdTFDODAtXHUxQzg4XHUxQ0QwLVx1MUNEMlx1MUNENC1cdTFDRjlcdTFEMDAtXHUxREY5XHUxREZCLVx1MUYxNVx1MUYxOC1cdTFGMURcdTFGMjAtXHUxRjQ1XHUxRjQ4LVx1MUY0RFx1MUY1MC1cdTFGNTdcdTFGNTlcdTFGNUJcdTFGNURcdTFGNUYtXHUxRjdEXHUxRjgwLVx1MUZCNFx1MUZCNi1cdTFGQkNcdTFGQkVcdTFGQzItXHUxRkM0XHUxRkM2LVx1MUZDQ1x1MUZEMC1cdTFGRDNcdTFGRDYtXHUxRkRCXHUxRkUwLVx1MUZFQ1x1MUZGMi1cdTFGRjRcdTFGRjYtXHUxRkZDXHUyMDNGXHUyMDQwXHUyMDU0XHUyMDcxXHUyMDdGXHUyMDkwLVx1MjA5Q1x1MjBEMC1cdTIwRENcdTIwRTFcdTIwRTUtXHUyMEYwXHUyMTAyXHUyMTA3XHUyMTBBLVx1MjExM1x1MjExNVx1MjExOS1cdTIxMURcdTIxMjRcdTIxMjZcdTIxMjhcdTIxMkEtXHUyMTJEXHUyMTJGLVx1MjEzOVx1MjEzQy1cdTIxM0ZcdTIxNDUtXHUyMTQ5XHUyMTRFXHUyMTYwLVx1MjE4OFx1MkMwMC1cdTJDMkVcdTJDMzAtXHUyQzVFXHUyQzYwLVx1MkNFNFx1MkNFQi1cdTJDRjNcdTJEMDAtXHUyRDI1XHUyRDI3XHUyRDJEXHUyRDMwLVx1MkQ2N1x1MkQ2Rlx1MkQ3Ri1cdTJEOTZcdTJEQTAtXHUyREE2XHUyREE4LVx1MkRBRVx1MkRCMC1cdTJEQjZcdTJEQjgtXHUyREJFXHUyREMwLVx1MkRDNlx1MkRDOC1cdTJEQ0VcdTJERDAtXHUyREQ2XHUyREQ4LVx1MkRERVx1MkRFMC1cdTJERkZcdTJFMkZcdTMwMDUtXHUzMDA3XHUzMDIxLVx1MzAyRlx1MzAzMS1cdTMwMzVcdTMwMzgtXHUzMDNDXHUzMDQxLVx1MzA5Nlx1MzA5OVx1MzA5QVx1MzA5RC1cdTMwOUZcdTMwQTEtXHUzMEZBXHUzMEZDLVx1MzBGRlx1MzEwNS1cdTMxMkVcdTMxMzEtXHUzMThFXHUzMUEwLVx1MzFCQVx1MzFGMC1cdTMxRkZcdTM0MDAtXHU0REI1XHU0RTAwLVx1OUZFQVx1QTAwMC1cdUE0OENcdUE0RDAtXHVBNEZEXHVBNTAwLVx1QTYwQ1x1QTYxMC1cdUE2MkJcdUE2NDAtXHVBNjZGXHVBNjc0LVx1QTY3RFx1QTY3Ri1cdUE2RjFcdUE3MTctXHVBNzFGXHVBNzIyLVx1QTc4OFx1QTc4Qi1cdUE3QUVcdUE3QjAtXHVBN0I3XHVBN0Y3LVx1QTgyN1x1QTg0MC1cdUE4NzNcdUE4ODAtXHVBOEM1XHVBOEQwLVx1QThEOVx1QThFMC1cdUE4RjdcdUE4RkJcdUE4RkRcdUE5MDAtXHVBOTJEXHVBOTMwLVx1QTk1M1x1QTk2MC1cdUE5N0NcdUE5ODAtXHVBOUMwXHVBOUNGLVx1QTlEOVx1QTlFMC1cdUE5RkVcdUFBMDAtXHVBQTM2XHVBQTQwLVx1QUE0RFx1QUE1MC1cdUFBNTlcdUFBNjAtXHVBQTc2XHVBQTdBLVx1QUFDMlx1QUFEQi1cdUFBRERcdUFBRTAtXHVBQUVGXHVBQUYyLVx1QUFGNlx1QUIwMS1cdUFCMDZcdUFCMDktXHVBQjBFXHVBQjExLVx1QUIxNlx1QUIyMC1cdUFCMjZcdUFCMjgtXHVBQjJFXHVBQjMwLVx1QUI1QVx1QUI1Qy1cdUFCNjVcdUFCNzAtXHVBQkVBXHVBQkVDXHVBQkVEXHVBQkYwLVx1QUJGOVx1QUMwMC1cdUQ3QTNcdUQ3QjAtXHVEN0M2XHVEN0NCLVx1RDdGQlx1RjkwMC1cdUZBNkRcdUZBNzAtXHVGQUQ5XHVGQjAwLVx1RkIwNlx1RkIxMy1cdUZCMTdcdUZCMUQtXHVGQjI4XHVGQjJBLVx1RkIzNlx1RkIzOC1cdUZCM0NcdUZCM0VcdUZCNDBcdUZCNDFcdUZCNDNcdUZCNDRcdUZCNDYtXHVGQkIxXHVGQkQzLVx1RkQzRFx1RkQ1MC1cdUZEOEZcdUZEOTItXHVGREM3XHVGREYwLVx1RkRGQlx1RkUwMC1cdUZFMEZcdUZFMjAtXHVGRTJGXHVGRTMzXHVGRTM0XHVGRTRELVx1RkU0Rlx1RkU3MC1cdUZFNzRcdUZFNzYtXHVGRUZDXHVGRjEwLVx1RkYxOVx1RkYyMS1cdUZGM0FcdUZGM0ZcdUZGNDEtXHVGRjVBXHVGRjY2LVx1RkZCRVx1RkZDMi1cdUZGQzdcdUZGQ0EtXHVGRkNGXHVGRkQyLVx1RkZEN1x1RkZEQS1cdUZGRENdfFx1RDgwMFtcdURDMDAtXHVEQzBCXHVEQzBELVx1REMyNlx1REMyOC1cdURDM0FcdURDM0NcdURDM0RcdURDM0YtXHVEQzREXHVEQzUwLVx1REM1RFx1REM4MC1cdURDRkFcdURENDAtXHVERDc0XHVEREZEXHVERTgwLVx1REU5Q1x1REVBMC1cdURFRDBcdURFRTBcdURGMDAtXHVERjFGXHVERjJELVx1REY0QVx1REY1MC1cdURGN0FcdURGODAtXHVERjlEXHVERkEwLVx1REZDM1x1REZDOC1cdURGQ0ZcdURGRDEtXHVERkQ1XXxcdUQ4MDFbXHVEQzAwLVx1REM5RFx1RENBMC1cdURDQTlcdURDQjAtXHVEQ0QzXHVEQ0Q4LVx1RENGQlx1REQwMC1cdUREMjdcdUREMzAtXHVERDYzXHVERTAwLVx1REYzNlx1REY0MC1cdURGNTVcdURGNjAtXHVERjY3XXxcdUQ4MDJbXHVEQzAwLVx1REMwNVx1REMwOFx1REMwQS1cdURDMzVcdURDMzdcdURDMzhcdURDM0NcdURDM0YtXHVEQzU1XHVEQzYwLVx1REM3Nlx1REM4MC1cdURDOUVcdURDRTAtXHVEQ0YyXHVEQ0Y0XHVEQ0Y1XHVERDAwLVx1REQxNVx1REQyMC1cdUREMzlcdUREODAtXHVEREI3XHVEREJFXHVEREJGXHVERTAwLVx1REUwM1x1REUwNVx1REUwNlx1REUwQy1cdURFMTNcdURFMTUtXHVERTE3XHVERTE5LVx1REUzM1x1REUzOC1cdURFM0FcdURFM0ZcdURFNjAtXHVERTdDXHVERTgwLVx1REU5Q1x1REVDMC1cdURFQzdcdURFQzktXHVERUU2XHVERjAwLVx1REYzNVx1REY0MC1cdURGNTVcdURGNjAtXHVERjcyXHVERjgwLVx1REY5MV18XHVEODAzW1x1REMwMC1cdURDNDhcdURDODAtXHVEQ0IyXHVEQ0MwLVx1RENGMl18XHVEODA0W1x1REMwMC1cdURDNDZcdURDNjYtXHVEQzZGXHVEQzdGLVx1RENCQVx1RENEMC1cdURDRThcdURDRjAtXHVEQ0Y5XHVERDAwLVx1REQzNFx1REQzNi1cdUREM0ZcdURENTAtXHVERDczXHVERDc2XHVERDgwLVx1RERDNFx1RERDQS1cdUREQ0NcdURERDAtXHVERERBXHVERERDXHVERTAwLVx1REUxMVx1REUxMy1cdURFMzdcdURFM0VcdURFODAtXHVERTg2XHVERTg4XHVERThBLVx1REU4RFx1REU4Ri1cdURFOURcdURFOUYtXHVERUE4XHVERUIwLVx1REVFQVx1REVGMC1cdURFRjlcdURGMDAtXHVERjAzXHVERjA1LVx1REYwQ1x1REYwRlx1REYxMFx1REYxMy1cdURGMjhcdURGMkEtXHVERjMwXHVERjMyXHVERjMzXHVERjM1LVx1REYzOVx1REYzQy1cdURGNDRcdURGNDdcdURGNDhcdURGNEItXHVERjREXHVERjUwXHVERjU3XHVERjVELVx1REY2M1x1REY2Ni1cdURGNkNcdURGNzAtXHVERjc0XXxcdUQ4MDVbXHVEQzAwLVx1REM0QVx1REM1MC1cdURDNTlcdURDODAtXHVEQ0M1XHVEQ0M3XHVEQ0QwLVx1RENEOVx1REQ4MC1cdUREQjVcdUREQjgtXHVEREMwXHVEREQ4LVx1RERERFx1REUwMC1cdURFNDBcdURFNDRcdURFNTAtXHVERTU5XHVERTgwLVx1REVCN1x1REVDMC1cdURFQzlcdURGMDAtXHVERjE5XHVERjFELVx1REYyQlx1REYzMC1cdURGMzldfFx1RDgwNltcdURDQTAtXHVEQ0U5XHVEQ0ZGXHVERTAwLVx1REUzRVx1REU0N1x1REU1MC1cdURFODNcdURFODYtXHVERTk5XHVERUMwLVx1REVGOF18XHVEODA3W1x1REMwMC1cdURDMDhcdURDMEEtXHVEQzM2XHVEQzM4LVx1REM0MFx1REM1MC1cdURDNTlcdURDNzItXHVEQzhGXHVEQzkyLVx1RENBN1x1RENBOS1cdURDQjZcdUREMDAtXHVERDA2XHVERDA4XHVERDA5XHVERDBCLVx1REQzNlx1REQzQVx1REQzQ1x1REQzRFx1REQzRi1cdURENDdcdURENTAtXHVERDU5XXxcdUQ4MDhbXHVEQzAwLVx1REY5OV18XHVEODA5W1x1REMwMC1cdURDNkVcdURDODAtXHVERDQzXXxbXHVEODBDXHVEODFDLVx1RDgyMFx1RDg0MC1cdUQ4NjhcdUQ4NkEtXHVEODZDXHVEODZGLVx1RDg3Mlx1RDg3NC1cdUQ4NzldW1x1REMwMC1cdURGRkZdfFx1RDgwRFtcdURDMDAtXHVEQzJFXXxcdUQ4MTFbXHVEQzAwLVx1REU0Nl18XHVEODFBW1x1REMwMC1cdURFMzhcdURFNDAtXHVERTVFXHVERTYwLVx1REU2OVx1REVEMC1cdURFRURcdURFRjAtXHVERUY0XHVERjAwLVx1REYzNlx1REY0MC1cdURGNDNcdURGNTAtXHVERjU5XHVERjYzLVx1REY3N1x1REY3RC1cdURGOEZdfFx1RDgxQltcdURGMDAtXHVERjQ0XHVERjUwLVx1REY3RVx1REY4Ri1cdURGOUZcdURGRTBcdURGRTFdfFx1RDgyMVtcdURDMDAtXHVERkVDXXxcdUQ4MjJbXHVEQzAwLVx1REVGMl18XHVEODJDW1x1REMwMC1cdUREMUVcdURENzAtXHVERUZCXXxcdUQ4MkZbXHVEQzAwLVx1REM2QVx1REM3MC1cdURDN0NcdURDODAtXHVEQzg4XHVEQzkwLVx1REM5OVx1REM5RFx1REM5RV18XHVEODM0W1x1REQ2NS1cdURENjlcdURENkQtXHVERDcyXHVERDdCLVx1REQ4Mlx1REQ4NS1cdUREOEJcdUREQUEtXHVEREFEXHVERTQyLVx1REU0NF18XHVEODM1W1x1REMwMC1cdURDNTRcdURDNTYtXHVEQzlDXHVEQzlFXHVEQzlGXHVEQ0EyXHVEQ0E1XHVEQ0E2XHVEQ0E5LVx1RENBQ1x1RENBRS1cdURDQjlcdURDQkJcdURDQkQtXHVEQ0MzXHVEQ0M1LVx1REQwNVx1REQwNy1cdUREMEFcdUREMEQtXHVERDE0XHVERDE2LVx1REQxQ1x1REQxRS1cdUREMzlcdUREM0ItXHVERDNFXHVERDQwLVx1REQ0NFx1REQ0Nlx1REQ0QS1cdURENTBcdURENTItXHVERUE1XHVERUE4LVx1REVDMFx1REVDMi1cdURFREFcdURFREMtXHVERUZBXHVERUZDLVx1REYxNFx1REYxNi1cdURGMzRcdURGMzYtXHVERjRFXHVERjUwLVx1REY2RVx1REY3MC1cdURGODhcdURGOEEtXHVERkE4XHVERkFBLVx1REZDMlx1REZDNC1cdURGQ0JcdURGQ0UtXHVERkZGXXxcdUQ4MzZbXHVERTAwLVx1REUzNlx1REUzQi1cdURFNkNcdURFNzVcdURFODRcdURFOUItXHVERTlGXHVERUExLVx1REVBRl18XHVEODM4W1x1REMwMC1cdURDMDZcdURDMDgtXHVEQzE4XHVEQzFCLVx1REMyMVx1REMyM1x1REMyNFx1REMyNi1cdURDMkFdfFx1RDgzQVtcdURDMDAtXHVEQ0M0XHVEQ0QwLVx1RENENlx1REQwMC1cdURENEFcdURENTAtXHVERDU5XXxcdUQ4M0JbXHVERTAwLVx1REUwM1x1REUwNS1cdURFMUZcdURFMjFcdURFMjJcdURFMjRcdURFMjdcdURFMjktXHVERTMyXHVERTM0LVx1REUzN1x1REUzOVx1REUzQlx1REU0Mlx1REU0N1x1REU0OVx1REU0Qlx1REU0RC1cdURFNEZcdURFNTFcdURFNTJcdURFNTRcdURFNTdcdURFNTlcdURFNUJcdURFNURcdURFNUZcdURFNjFcdURFNjJcdURFNjRcdURFNjctXHVERTZBXHVERTZDLVx1REU3Mlx1REU3NC1cdURFNzdcdURFNzktXHVERTdDXHVERTdFXHVERTgwLVx1REU4OVx1REU4Qi1cdURFOUJcdURFQTEtXHVERUEzXHVERUE1LVx1REVBOVx1REVBQi1cdURFQkJdfFx1RDg2OVtcdURDMDAtXHVERUQ2XHVERjAwLVx1REZGRl18XHVEODZEW1x1REMwMC1cdURGMzRcdURGNDAtXHVERkZGXXxcdUQ4NkVbXHVEQzAwLVx1REMxRFx1REMyMC1cdURGRkZdfFx1RDg3M1tcdURDMDAtXHVERUExXHVERUIwLVx1REZGRl18XHVEODdBW1x1REMwMC1cdURGRTBdfFx1RDg3RVtcdURDMDAtXHVERTFEXXxcdURCNDBbXHVERDAwLVx1RERFRl0vfSxVPXtpc1NwYWNlU2VwYXJhdG9yOmZ1bmN0aW9uKHUpe3JldHVybiJzdHJpbmciPT10eXBlb2YgdSYmRy5TcGFjZV9TZXBhcmF0b3IudGVzdCh1KX0saXNJZFN0YXJ0Q2hhcjpmdW5jdGlvbih1KXtyZXR1cm4ic3RyaW5nIj09dHlwZW9mIHUmJih1Pj0iYSImJnU8PSJ6Inx8dT49IkEiJiZ1PD0iWiJ8fCIkIj09PXV8fCJfIj09PXV8fEcuSURfU3RhcnQudGVzdCh1KSl9LGlzSWRDb250aW51ZUNoYXI6ZnVuY3Rpb24odSl7cmV0dXJuInN0cmluZyI9PXR5cGVvZiB1JiYodT49ImEiJiZ1PD0ieiJ8fHU+PSJBIiYmdTw9IloifHx1Pj0iMCImJnU8PSI5Inx8IiQiPT09dXx8Il8iPT09dXx8IuKAjCI9PT11fHwi4oCNIj09PXV8fEcuSURfQ29udGludWUudGVzdCh1KSl9LGlzRGlnaXQ6ZnVuY3Rpb24odSl7cmV0dXJuInN0cmluZyI9PXR5cGVvZiB1JiYvWzAtOV0vLnRlc3QodSl9LGlzSGV4RGlnaXQ6ZnVuY3Rpb24odSl7cmV0dXJuInN0cmluZyI9PXR5cGVvZiB1JiYvWzAtOUEtRmEtZl0vLnRlc3QodSl9fTtmdW5jdGlvbiBaKCl7Zm9yKFQ9ImRlZmF1bHQiLHo9IiIsSD0hMSwkPTE7Oyl7Uj1xKCk7dmFyIHU9WFtUXSgpO2lmKHUpcmV0dXJuIHV9fWZ1bmN0aW9uIHEoKXtpZihfW0ldKXJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChfLmNvZGVQb2ludEF0KEkpKX1mdW5jdGlvbiBXKCl7dmFyIHU9cSgpO3JldHVybiJcbiI9PT11PyhWKyssSj0wKTp1P0orPXUubGVuZ3RoOkorKyx1JiYoSSs9dS5sZW5ndGgpLHV9dmFyIFg9e2RlZmF1bHQ6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSJcdCI6Y2FzZSJcdiI6Y2FzZSJcZiI6Y2FzZSIgIjpjYXNlIiAiOmNhc2UiXHVmZWZmIjpjYXNlIlxuIjpjYXNlIlxyIjpjYXNlIlx1MjAyOCI6Y2FzZSJcdTIwMjkiOnJldHVybiB2b2lkIFcoKTtjYXNlIi8iOnJldHVybiBXKCksdm9pZChUPSJjb21tZW50Iik7Y2FzZSB2b2lkIDA6cmV0dXJuIFcoKSxLKCJlb2YiKX1pZighVS5pc1NwYWNlU2VwYXJhdG9yKFIpKXJldHVybiBYW09dKCk7VygpfSxjb21tZW50OmZ1bmN0aW9uKCl7c3dpdGNoKFIpe2Nhc2UiKiI6cmV0dXJuIFcoKSx2b2lkKFQ9Im11bHRpTGluZUNvbW1lbnQiKTtjYXNlIi8iOnJldHVybiBXKCksdm9pZChUPSJzaW5nbGVMaW5lQ29tbWVudCIpfXRocm93IHJ1KFcoKSl9LG11bHRpTGluZUNvbW1lbnQ6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSIqIjpyZXR1cm4gVygpLHZvaWQoVD0ibXVsdGlMaW5lQ29tbWVudEFzdGVyaXNrIik7Y2FzZSB2b2lkIDA6dGhyb3cgcnUoVygpKX1XKCl9LG11bHRpTGluZUNvbW1lbnRBc3RlcmlzazpmdW5jdGlvbigpe3N3aXRjaChSKXtjYXNlIioiOnJldHVybiB2b2lkIFcoKTtjYXNlIi8iOnJldHVybiBXKCksdm9pZChUPSJkZWZhdWx0Iik7Y2FzZSB2b2lkIDA6dGhyb3cgcnUoVygpKX1XKCksVD0ibXVsdGlMaW5lQ29tbWVudCJ9LHNpbmdsZUxpbmVDb21tZW50OmZ1bmN0aW9uKCl7c3dpdGNoKFIpe2Nhc2UiXG4iOmNhc2UiXHIiOmNhc2UiXHUyMDI4IjpjYXNlIlx1MjAyOSI6cmV0dXJuIFcoKSx2b2lkKFQ9ImRlZmF1bHQiKTtjYXNlIHZvaWQgMDpyZXR1cm4gVygpLEsoImVvZiIpfVcoKX0sdmFsdWU6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSJ7IjpjYXNlIlsiOnJldHVybiBLKCJwdW5jdHVhdG9yIixXKCkpO2Nhc2UibiI6cmV0dXJuIFcoKSxRKCJ1bGwiKSxLKCJudWxsIixudWxsKTtjYXNlInQiOnJldHVybiBXKCksUSgicnVlIiksSygiYm9vbGVhbiIsITApO2Nhc2UiZiI6cmV0dXJuIFcoKSxRKCJhbHNlIiksSygiYm9vbGVhbiIsITEpO2Nhc2UiLSI6Y2FzZSIrIjpyZXR1cm4iLSI9PT1XKCkmJigkPS0xKSx2b2lkKFQ9InNpZ24iKTtjYXNlIi4iOnJldHVybiB6PVcoKSx2b2lkKFQ9ImRlY2ltYWxQb2ludExlYWRpbmciKTtjYXNlIjAiOnJldHVybiB6PVcoKSx2b2lkKFQ9Inplcm8iKTtjYXNlIjEiOmNhc2UiMiI6Y2FzZSIzIjpjYXNlIjQiOmNhc2UiNSI6Y2FzZSI2IjpjYXNlIjciOmNhc2UiOCI6Y2FzZSI5IjpyZXR1cm4gej1XKCksdm9pZChUPSJkZWNpbWFsSW50ZWdlciIpO2Nhc2UiSSI6cmV0dXJuIFcoKSxRKCJuZmluaXR5IiksSygibnVtZXJpYyIsMS8wKTtjYXNlIk4iOnJldHVybiBXKCksUSgiYU4iKSxLKCJudW1lcmljIixOYU4pO2Nhc2UnIic6Y2FzZSInIjpyZXR1cm4gSD0nIic9PT1XKCksej0iIix2b2lkKFQ9InN0cmluZyIpfXRocm93IHJ1KFcoKSl9LGlkZW50aWZpZXJOYW1lU3RhcnRFc2NhcGU6ZnVuY3Rpb24oKXtpZigidSIhPT1SKXRocm93IHJ1KFcoKSk7VygpO3ZhciB1PVkoKTtzd2l0Y2godSl7Y2FzZSIkIjpjYXNlIl8iOmJyZWFrO2RlZmF1bHQ6aWYoIVUuaXNJZFN0YXJ0Q2hhcih1KSl0aHJvdyBudSgpfXorPXUsVD0iaWRlbnRpZmllck5hbWUifSxpZGVudGlmaWVyTmFtZTpmdW5jdGlvbigpe3N3aXRjaChSKXtjYXNlIiQiOmNhc2UiXyI6Y2FzZSLigIwiOmNhc2Ui4oCNIjpyZXR1cm4gdm9pZCh6Kz1XKCkpO2Nhc2UiXFwiOnJldHVybiBXKCksdm9pZChUPSJpZGVudGlmaWVyTmFtZUVzY2FwZSIpfWlmKCFVLmlzSWRDb250aW51ZUNoYXIoUikpcmV0dXJuIEsoImlkZW50aWZpZXIiLHopO3orPVcoKX0saWRlbnRpZmllck5hbWVFc2NhcGU6ZnVuY3Rpb24oKXtpZigidSIhPT1SKXRocm93IHJ1KFcoKSk7VygpO3ZhciB1PVkoKTtzd2l0Y2godSl7Y2FzZSIkIjpjYXNlIl8iOmNhc2Ui4oCMIjpjYXNlIuKAjSI6YnJlYWs7ZGVmYXVsdDppZighVS5pc0lkQ29udGludWVDaGFyKHUpKXRocm93IG51KCl9eis9dSxUPSJpZGVudGlmaWVyTmFtZSJ9LHNpZ246ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSIuIjpyZXR1cm4gej1XKCksdm9pZChUPSJkZWNpbWFsUG9pbnRMZWFkaW5nIik7Y2FzZSIwIjpyZXR1cm4gej1XKCksdm9pZChUPSJ6ZXJvIik7Y2FzZSIxIjpjYXNlIjIiOmNhc2UiMyI6Y2FzZSI0IjpjYXNlIjUiOmNhc2UiNiI6Y2FzZSI3IjpjYXNlIjgiOmNhc2UiOSI6cmV0dXJuIHo9VygpLHZvaWQoVD0iZGVjaW1hbEludGVnZXIiKTtjYXNlIkkiOnJldHVybiBXKCksUSgibmZpbml0eSIpLEsoIm51bWVyaWMiLCQqKDEvMCkpO2Nhc2UiTiI6cmV0dXJuIFcoKSxRKCJhTiIpLEsoIm51bWVyaWMiLE5hTil9dGhyb3cgcnUoVygpKX0semVybzpmdW5jdGlvbigpe3N3aXRjaChSKXtjYXNlIi4iOnJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsUG9pbnQiKTtjYXNlImUiOmNhc2UiRSI6cmV0dXJuIHorPVcoKSx2b2lkKFQ9ImRlY2ltYWxFeHBvbmVudCIpO2Nhc2UieCI6Y2FzZSJYIjpyZXR1cm4geis9VygpLHZvaWQoVD0iaGV4YWRlY2ltYWwiKX1yZXR1cm4gSygibnVtZXJpYyIsMCokKX0sZGVjaW1hbEludGVnZXI6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSIuIjpyZXR1cm4geis9VygpLHZvaWQoVD0iZGVjaW1hbFBvaW50Iik7Y2FzZSJlIjpjYXNlIkUiOnJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsRXhwb25lbnQiKX1pZighVS5pc0RpZ2l0KFIpKXJldHVybiBLKCJudW1lcmljIiwkKk51bWJlcih6KSk7eis9VygpfSxkZWNpbWFsUG9pbnRMZWFkaW5nOmZ1bmN0aW9uKCl7aWYoVS5pc0RpZ2l0KFIpKXJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsRnJhY3Rpb24iKTt0aHJvdyBydShXKCkpfSxkZWNpbWFsUG9pbnQ6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSJlIjpjYXNlIkUiOnJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsRXhwb25lbnQiKX1yZXR1cm4gVS5pc0RpZ2l0KFIpPyh6Kz1XKCksdm9pZChUPSJkZWNpbWFsRnJhY3Rpb24iKSk6SygibnVtZXJpYyIsJCpOdW1iZXIoeikpfSxkZWNpbWFsRnJhY3Rpb246ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSJlIjpjYXNlIkUiOnJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsRXhwb25lbnQiKX1pZighVS5pc0RpZ2l0KFIpKXJldHVybiBLKCJudW1lcmljIiwkKk51bWJlcih6KSk7eis9VygpfSxkZWNpbWFsRXhwb25lbnQ6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSIrIjpjYXNlIi0iOnJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsRXhwb25lbnRTaWduIil9aWYoVS5pc0RpZ2l0KFIpKXJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsRXhwb25lbnRJbnRlZ2VyIik7dGhyb3cgcnUoVygpKX0sZGVjaW1hbEV4cG9uZW50U2lnbjpmdW5jdGlvbigpe2lmKFUuaXNEaWdpdChSKSlyZXR1cm4geis9VygpLHZvaWQoVD0iZGVjaW1hbEV4cG9uZW50SW50ZWdlciIpO3Rocm93IHJ1KFcoKSl9LGRlY2ltYWxFeHBvbmVudEludGVnZXI6ZnVuY3Rpb24oKXtpZighVS5pc0RpZ2l0KFIpKXJldHVybiBLKCJudW1lcmljIiwkKk51bWJlcih6KSk7eis9VygpfSxoZXhhZGVjaW1hbDpmdW5jdGlvbigpe2lmKFUuaXNIZXhEaWdpdChSKSlyZXR1cm4geis9VygpLHZvaWQoVD0iaGV4YWRlY2ltYWxJbnRlZ2VyIik7dGhyb3cgcnUoVygpKX0saGV4YWRlY2ltYWxJbnRlZ2VyOmZ1bmN0aW9uKCl7aWYoIVUuaXNIZXhEaWdpdChSKSlyZXR1cm4gSygibnVtZXJpYyIsJCpOdW1iZXIoeikpO3orPVcoKX0sc3RyaW5nOmZ1bmN0aW9uKCl7c3dpdGNoKFIpe2Nhc2UiXFwiOnJldHVybiBXKCksdm9pZCh6Kz1mdW5jdGlvbigpe3N3aXRjaChxKCkpe2Nhc2UiYiI6cmV0dXJuIFcoKSwiXGIiO2Nhc2UiZiI6cmV0dXJuIFcoKSwiXGYiO2Nhc2UibiI6cmV0dXJuIFcoKSwiXG4iO2Nhc2UiciI6cmV0dXJuIFcoKSwiXHIiO2Nhc2UidCI6cmV0dXJuIFcoKSwiXHQiO2Nhc2UidiI6cmV0dXJuIFcoKSwiXHYiO2Nhc2UiMCI6aWYoVygpLFUuaXNEaWdpdChxKCkpKXRocm93IHJ1KFcoKSk7cmV0dXJuIlwwIjtjYXNlIngiOnJldHVybiBXKCksZnVuY3Rpb24oKXt2YXIgdT0iIixEPXEoKTtpZighVS5pc0hleERpZ2l0KEQpKXRocm93IHJ1KFcoKSk7aWYodSs9VygpLEQ9cSgpLCFVLmlzSGV4RGlnaXQoRCkpdGhyb3cgcnUoVygpKTtyZXR1cm4gdSs9VygpLFN0cmluZy5mcm9tQ29kZVBvaW50KHBhcnNlSW50KHUsMTYpKX0oKTtjYXNlInUiOnJldHVybiBXKCksWSgpO2Nhc2UiXG4iOmNhc2UiXHUyMDI4IjpjYXNlIlx1MjAyOSI6cmV0dXJuIFcoKSwiIjtjYXNlIlxyIjpyZXR1cm4gVygpLCJcbiI9PT1xKCkmJlcoKSwiIjtjYXNlIjEiOmNhc2UiMiI6Y2FzZSIzIjpjYXNlIjQiOmNhc2UiNSI6Y2FzZSI2IjpjYXNlIjciOmNhc2UiOCI6Y2FzZSI5IjpjYXNlIHZvaWQgMDp0aHJvdyBydShXKCkpfXJldHVybiBXKCl9KCkpO2Nhc2UnIic6cmV0dXJuIEg/KFcoKSxLKCJzdHJpbmciLHopKTp2b2lkKHorPVcoKSk7Y2FzZSInIjpyZXR1cm4gSD92b2lkKHorPVcoKSk6KFcoKSxLKCJzdHJpbmciLHopKTtjYXNlIlxuIjpjYXNlIlxyIjp0aHJvdyBydShXKCkpO2Nhc2UiXHUyMDI4IjpjYXNlIlx1MjAyOSI6IWZ1bmN0aW9uKHUpe2NvbnNvbGUud2FybigiSlNPTjU6ICciK0Z1KHUpKyInIGluIHN0cmluZ3MgaXMgbm90IHZhbGlkIEVDTUFTY3JpcHQ7IGNvbnNpZGVyIGVzY2FwaW5nIil9KFIpO2JyZWFrO2Nhc2Ugdm9pZCAwOnRocm93IHJ1KFcoKSl9eis9VygpfSxzdGFydDpmdW5jdGlvbigpe3N3aXRjaChSKXtjYXNlInsiOmNhc2UiWyI6cmV0dXJuIEsoInB1bmN0dWF0b3IiLFcoKSl9VD0idmFsdWUifSxiZWZvcmVQcm9wZXJ0eU5hbWU6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSIkIjpjYXNlIl8iOnJldHVybiB6PVcoKSx2b2lkKFQ9ImlkZW50aWZpZXJOYW1lIik7Y2FzZSJcXCI6cmV0dXJuIFcoKSx2b2lkKFQ9ImlkZW50aWZpZXJOYW1lU3RhcnRFc2NhcGUiKTtjYXNlIn0iOnJldHVybiBLKCJwdW5jdHVhdG9yIixXKCkpO2Nhc2UnIic6Y2FzZSInIjpyZXR1cm4gSD0nIic9PT1XKCksdm9pZChUPSJzdHJpbmciKX1pZihVLmlzSWRTdGFydENoYXIoUikpcmV0dXJuIHorPVcoKSx2b2lkKFQ9ImlkZW50aWZpZXJOYW1lIik7dGhyb3cgcnUoVygpKX0sYWZ0ZXJQcm9wZXJ0eU5hbWU6ZnVuY3Rpb24oKXtpZigiOiI9PT1SKXJldHVybiBLKCJwdW5jdHVhdG9yIixXKCkpO3Rocm93IHJ1KFcoKSl9LGJlZm9yZVByb3BlcnR5VmFsdWU6ZnVuY3Rpb24oKXtUPSJ2YWx1ZSJ9LGFmdGVyUHJvcGVydHlWYWx1ZTpmdW5jdGlvbigpe3N3aXRjaChSKXtjYXNlIiwiOmNhc2UifSI6cmV0dXJuIEsoInB1bmN0dWF0b3IiLFcoKSl9dGhyb3cgcnUoVygpKX0sYmVmb3JlQXJyYXlWYWx1ZTpmdW5jdGlvbigpe2lmKCJdIj09PVIpcmV0dXJuIEsoInB1bmN0dWF0b3IiLFcoKSk7VD0idmFsdWUifSxhZnRlckFycmF5VmFsdWU6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSIsIjpjYXNlIl0iOnJldHVybiBLKCJwdW5jdHVhdG9yIixXKCkpfXRocm93IHJ1KFcoKSl9LGVuZDpmdW5jdGlvbigpe3Rocm93IHJ1KFcoKSl9fTtmdW5jdGlvbiBLKHUsRCl7cmV0dXJue3R5cGU6dSx2YWx1ZTpELGxpbmU6Vixjb2x1bW46Sn19ZnVuY3Rpb24gUSh1KXtmb3IodmFyIEQ9MCxlPXU7RDxlLmxlbmd0aDtEKz0xKXt2YXIgcj1lW0RdO2lmKHEoKSE9PXIpdGhyb3cgcnUoVygpKTtXKCl9fWZ1bmN0aW9uIFkoKXtmb3IodmFyIHU9IiIsRD00O0QtLSA+MDspe3ZhciBlPXEoKTtpZighVS5pc0hleERpZ2l0KGUpKXRocm93IHJ1KFcoKSk7dSs9VygpfXJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChwYXJzZUludCh1LDE2KSl9dmFyIHV1PXtzdGFydDpmdW5jdGlvbigpe2lmKCJlb2YiPT09TS50eXBlKXRocm93IHR1KCk7RHUoKX0sYmVmb3JlUHJvcGVydHlOYW1lOmZ1bmN0aW9uKCl7c3dpdGNoKE0udHlwZSl7Y2FzZSJpZGVudGlmaWVyIjpjYXNlInN0cmluZyI6cmV0dXJuIGs9TS52YWx1ZSx2b2lkKE89ImFmdGVyUHJvcGVydHlOYW1lIik7Y2FzZSJwdW5jdHVhdG9yIjpyZXR1cm4gdm9pZCBldSgpO2Nhc2UiZW9mIjp0aHJvdyB0dSgpfX0sYWZ0ZXJQcm9wZXJ0eU5hbWU6ZnVuY3Rpb24oKXtpZigiZW9mIj09PU0udHlwZSl0aHJvdyB0dSgpO089ImJlZm9yZVByb3BlcnR5VmFsdWUifSxiZWZvcmVQcm9wZXJ0eVZhbHVlOmZ1bmN0aW9uKCl7aWYoImVvZiI9PT1NLnR5cGUpdGhyb3cgdHUoKTtEdSgpfSxiZWZvcmVBcnJheVZhbHVlOmZ1bmN0aW9uKCl7aWYoImVvZiI9PT1NLnR5cGUpdGhyb3cgdHUoKTsicHVuY3R1YXRvciIhPT1NLnR5cGV8fCJdIiE9PU0udmFsdWU/RHUoKTpldSgpfSxhZnRlclByb3BlcnR5VmFsdWU6ZnVuY3Rpb24oKXtpZigiZW9mIj09PU0udHlwZSl0aHJvdyB0dSgpO3N3aXRjaChNLnZhbHVlKXtjYXNlIiwiOnJldHVybiB2b2lkKE89ImJlZm9yZVByb3BlcnR5TmFtZSIpO2Nhc2UifSI6ZXUoKX19LGFmdGVyQXJyYXlWYWx1ZTpmdW5jdGlvbigpe2lmKCJlb2YiPT09TS50eXBlKXRocm93IHR1KCk7c3dpdGNoKE0udmFsdWUpe2Nhc2UiLCI6cmV0dXJuIHZvaWQoTz0iYmVmb3JlQXJyYXlWYWx1ZSIpO2Nhc2UiXSI6ZXUoKX19LGVuZDpmdW5jdGlvbigpe319O2Z1bmN0aW9uIER1KCl7dmFyIHU7c3dpdGNoKE0udHlwZSl7Y2FzZSJwdW5jdHVhdG9yIjpzd2l0Y2goTS52YWx1ZSl7Y2FzZSJ7Ijp1PXt9O2JyZWFrO2Nhc2UiWyI6dT1bXX1icmVhaztjYXNlIm51bGwiOmNhc2UiYm9vbGVhbiI6Y2FzZSJudW1lcmljIjpjYXNlInN0cmluZyI6dT1NLnZhbHVlfWlmKHZvaWQgMD09PUwpTD11O2Vsc2V7dmFyIEQ9altqLmxlbmd0aC0xXTtBcnJheS5pc0FycmF5KEQpP0QucHVzaCh1KTpPYmplY3QuZGVmaW5lUHJvcGVydHkoRCxrLHt2YWx1ZTp1LHdyaXRhYmxlOiEwLGVudW1lcmFibGU6ITAsY29uZmlndXJhYmxlOiEwfSl9aWYobnVsbCE9PXUmJiJvYmplY3QiPT10eXBlb2YgdSlqLnB1c2godSksTz1BcnJheS5pc0FycmF5KHUpPyJiZWZvcmVBcnJheVZhbHVlIjoiYmVmb3JlUHJvcGVydHlOYW1lIjtlbHNle3ZhciBlPWpbai5sZW5ndGgtMV07Tz1udWxsPT1lPyJlbmQiOkFycmF5LmlzQXJyYXkoZSk/ImFmdGVyQXJyYXlWYWx1ZSI6ImFmdGVyUHJvcGVydHlWYWx1ZSJ9fWZ1bmN0aW9uIGV1KCl7ai5wb3AoKTt2YXIgdT1qW2oubGVuZ3RoLTFdO089bnVsbD09dT8iZW5kIjpBcnJheS5pc0FycmF5KHUpPyJhZnRlckFycmF5VmFsdWUiOiJhZnRlclByb3BlcnR5VmFsdWUifWZ1bmN0aW9uIHJ1KHUpe3JldHVybiBDdSh2b2lkIDA9PT11PyJKU09ONTogaW52YWxpZCBlbmQgb2YgaW5wdXQgYXQgIitWKyI6IitKOiJKU09ONTogaW52YWxpZCBjaGFyYWN0ZXIgJyIrRnUodSkrIicgYXQgIitWKyI6IitKKX1mdW5jdGlvbiB0dSgpe3JldHVybiBDdSgiSlNPTjU6IGludmFsaWQgZW5kIG9mIGlucHV0IGF0ICIrVisiOiIrSil9ZnVuY3Rpb24gbnUoKXtyZXR1cm4gQ3UoIkpTT041OiBpbnZhbGlkIGlkZW50aWZpZXIgY2hhcmFjdGVyIGF0ICIrVisiOiIrKEotPTUpKX1mdW5jdGlvbiBGdSh1KXt2YXIgRD17IiciOiJcXCciLCciJzonXFwiJywiXFwiOiJcXFxcIiwiXGIiOiJcXGIiLCJcZiI6IlxcZiIsIlxuIjoiXFxuIiwiXHIiOiJcXHIiLCJcdCI6IlxcdCIsIlx2IjoiXFx2IiwiXDAiOiJcXDAiLCJcdTIwMjgiOiJcXHUyMDI4IiwiXHUyMDI5IjoiXFx1MjAyOSJ9O2lmKERbdV0pcmV0dXJuIERbdV07aWYodTwiICIpe3ZhciBlPXUuY2hhckNvZGVBdCgwKS50b1N0cmluZygxNik7cmV0dXJuIlxceCIrKCIwMCIrZSkuc3Vic3RyaW5nKGUubGVuZ3RoKX1yZXR1cm4gdX1mdW5jdGlvbiBDdSh1KXt2YXIgRD1uZXcgU3ludGF4RXJyb3IodSk7cmV0dXJuIEQubGluZU51bWJlcj1WLEQuY29sdW1uTnVtYmVyPUosRH1yZXR1cm57cGFyc2U6ZnVuY3Rpb24odSxEKXtfPVN0cmluZyh1KSxPPSJzdGFydCIsaj1bXSxJPTAsVj0xLEo9MCxNPXZvaWQgMCxrPXZvaWQgMCxMPXZvaWQgMDtkb3tNPVooKSx1dVtPXSgpfXdoaWxlKCJlb2YiIT09TS50eXBlKTtyZXR1cm4iZnVuY3Rpb24iPT10eXBlb2YgRD9mdW5jdGlvbiB1KEQsZSxyKXt2YXIgdD1EW2VdO2lmKG51bGwhPXQmJiJvYmplY3QiPT10eXBlb2YgdClpZihBcnJheS5pc0FycmF5KHQpKWZvcih2YXIgbj0wO248dC5sZW5ndGg7bisrKXt2YXIgRj1TdHJpbmcobiksQz11KHQsRixyKTt2b2lkIDA9PT1DP2RlbGV0ZSB0W0ZdOk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LEYse3ZhbHVlOkMsd3JpdGFibGU6ITAsZW51bWVyYWJsZTohMCxjb25maWd1cmFibGU6ITB9KX1lbHNlIGZvcih2YXIgQSBpbiB0KXt2YXIgaT11KHQsQSxyKTt2b2lkIDA9PT1pP2RlbGV0ZSB0W0FdOk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LEEse3ZhbHVlOmksd3JpdGFibGU6ITAsZW51bWVyYWJsZTohMCxjb25maWd1cmFibGU6ITB9KX1yZXR1cm4gci5jYWxsKEQsZSx0KX0oeyIiOkx9LCIiLEQpOkx9LHN0cmluZ2lmeTpmdW5jdGlvbih1LEQsZSl7dmFyIHIsdCxuLEY9W10sQz0iIixBPSIiO2lmKG51bGw9PUR8fCJvYmplY3QiIT10eXBlb2YgRHx8QXJyYXkuaXNBcnJheShEKXx8KGU9RC5zcGFjZSxuPUQucXVvdGUsRD1ELnJlcGxhY2VyKSwiZnVuY3Rpb24iPT10eXBlb2YgRCl0PUQ7ZWxzZSBpZihBcnJheS5pc0FycmF5KEQpKXtyPVtdO2Zvcih2YXIgaT0wLEU9RDtpPEUubGVuZ3RoO2krPTEpe3ZhciBvPUVbaV0sYT12b2lkIDA7InN0cmluZyI9PXR5cGVvZiBvP2E9bzooIm51bWJlciI9PXR5cGVvZiBvfHxvIGluc3RhbmNlb2YgU3RyaW5nfHxvIGluc3RhbmNlb2YgTnVtYmVyKSYmKGE9U3RyaW5nKG8pKSx2b2lkIDAhPT1hJiZyLmluZGV4T2YoYSk8MCYmci5wdXNoKGEpfX1yZXR1cm4gZSBpbnN0YW5jZW9mIE51bWJlcj9lPU51bWJlcihlKTplIGluc3RhbmNlb2YgU3RyaW5nJiYoZT1TdHJpbmcoZSkpLCJudW1iZXIiPT10eXBlb2YgZT9lPjAmJihlPU1hdGgubWluKDEwLE1hdGguZmxvb3IoZSkpLEE9IiAgICAgICAgICAiLnN1YnN0cigwLGUpKToic3RyaW5nIj09dHlwZW9mIGUmJihBPWUuc3Vic3RyKDAsMTApKSxjKCIiLHsiIjp1fSk7ZnVuY3Rpb24gYyh1LEQpe3ZhciBlPURbdV07c3dpdGNoKG51bGwhPWUmJigiZnVuY3Rpb24iPT10eXBlb2YgZS50b0pTT041P2U9ZS50b0pTT041KHUpOiJmdW5jdGlvbiI9PXR5cGVvZiBlLnRvSlNPTiYmKGU9ZS50b0pTT04odSkpKSx0JiYoZT10LmNhbGwoRCx1LGUpKSxlIGluc3RhbmNlb2YgTnVtYmVyP2U9TnVtYmVyKGUpOmUgaW5zdGFuY2VvZiBTdHJpbmc/ZT1TdHJpbmcoZSk6ZSBpbnN0YW5jZW9mIEJvb2xlYW4mJihlPWUudmFsdWVPZigpKSxlKXtjYXNlIG51bGw6cmV0dXJuIm51bGwiO2Nhc2UhMDpyZXR1cm4idHJ1ZSI7Y2FzZSExOnJldHVybiJmYWxzZSJ9cmV0dXJuInN0cmluZyI9PXR5cGVvZiBlP0IoZSk6Im51bWJlciI9PXR5cGVvZiBlP1N0cmluZyhlKToib2JqZWN0Ij09dHlwZW9mIGU/QXJyYXkuaXNBcnJheShlKT9mdW5jdGlvbih1KXtpZihGLmluZGV4T2YodSk+PTApdGhyb3cgVHlwZUVycm9yKCJDb252ZXJ0aW5nIGNpcmN1bGFyIHN0cnVjdHVyZSB0byBKU09ONSIpO0YucHVzaCh1KTt2YXIgRD1DO0MrPUE7Zm9yKHZhciBlLHI9W10sdD0wO3Q8dS5sZW5ndGg7dCsrKXt2YXIgbj1jKFN0cmluZyh0KSx1KTtyLnB1c2godm9pZCAwIT09bj9uOiJudWxsIil9aWYoMD09PXIubGVuZ3RoKWU9IltdIjtlbHNlIGlmKCIiPT09QSl7dmFyIGk9ci5qb2luKCIsIik7ZT0iWyIraSsiXSJ9ZWxzZXt2YXIgRT0iLFxuIitDLG89ci5qb2luKEUpO2U9IltcbiIrQytvKyIsXG4iK0QrIl0ifXJldHVybiBGLnBvcCgpLEM9RCxlfShlKTpmdW5jdGlvbih1KXtpZihGLmluZGV4T2YodSk+PTApdGhyb3cgVHlwZUVycm9yKCJDb252ZXJ0aW5nIGNpcmN1bGFyIHN0cnVjdHVyZSB0byBKU09ONSIpO0YucHVzaCh1KTt2YXIgRD1DO0MrPUE7Zm9yKHZhciBlLHQsbj1yfHxPYmplY3Qua2V5cyh1KSxpPVtdLEU9MCxvPW47RTxvLmxlbmd0aDtFKz0xKXt2YXIgYT1vW0VdLEI9YyhhLHUpO2lmKHZvaWQgMCE9PUIpe3ZhciBmPXMoYSkrIjoiOyIiIT09QSYmKGYrPSIgIiksZis9QixpLnB1c2goZil9fWlmKDA9PT1pLmxlbmd0aCllPSJ7fSI7ZWxzZSBpZigiIj09PUEpdD1pLmpvaW4oIiwiKSxlPSJ7Iit0KyJ9IjtlbHNle3ZhciBsPSIsXG4iK0M7dD1pLmpvaW4obCksZT0ie1xuIitDK3QrIixcbiIrRCsifSJ9cmV0dXJuIEYucG9wKCksQz1ELGV9KGUpOnZvaWQgMH1mdW5jdGlvbiBCKHUpe2Zvcih2YXIgRD17IiciOi4xLCciJzouMn0sZT17IiciOiJcXCciLCciJzonXFwiJywiXFwiOiJcXFxcIiwiXGIiOiJcXGIiLCJcZiI6IlxcZiIsIlxuIjoiXFxuIiwiXHIiOiJcXHIiLCJcdCI6IlxcdCIsIlx2IjoiXFx2IiwiXDAiOiJcXDAiLCJcdTIwMjgiOiJcXHUyMDI4IiwiXHUyMDI5IjoiXFx1MjAyOSJ9LHI9IiIsdD0wO3Q8dS5sZW5ndGg7dCsrKXt2YXIgRj11W3RdO3N3aXRjaChGKXtjYXNlIiciOmNhc2UnIic6RFtGXSsrLHIrPUY7Y29udGludWU7Y2FzZSJcMCI6aWYoVS5pc0RpZ2l0KHVbdCsxXSkpe3IrPSJcXHgwMCI7Y29udGludWV9fWlmKGVbRl0pcis9ZVtGXTtlbHNlIGlmKEY8IiAiKXt2YXIgQz1GLmNoYXJDb2RlQXQoMCkudG9TdHJpbmcoMTYpO3IrPSJcXHgiKygiMDAiK0MpLnN1YnN0cmluZyhDLmxlbmd0aCl9ZWxzZSByKz1GfXZhciBBPW58fE9iamVjdC5rZXlzKEQpLnJlZHVjZShmdW5jdGlvbih1LGUpe3JldHVybiBEW3VdPERbZV0/dTplfSk7cmV0dXJuIEErKHI9ci5yZXBsYWNlKG5ldyBSZWdFeHAoQSwiZyIpLGVbQV0pKStBfWZ1bmN0aW9uIHModSl7aWYoMD09PXUubGVuZ3RoKXJldHVybiBCKHUpO3ZhciBEPVN0cmluZy5mcm9tQ29kZVBvaW50KHUuY29kZVBvaW50QXQoMCkpO2lmKCFVLmlzSWRTdGFydENoYXIoRCkpcmV0dXJuIEIodSk7Zm9yKHZhciBlPUQubGVuZ3RoO2U8dS5sZW5ndGg7ZSsrKWlmKCFVLmlzSWRDb250aW51ZUNoYXIoU3RyaW5nLmZyb21Db2RlUG9pbnQodS5jb2RlUG9pbnRBdChlKSkpKXJldHVybiBCKHUpO3JldHVybiB1fX19fSk7`;
|
|
124319
|
+
//#endregion
|
|
124320
|
+
//#region src/client/api/view-server/request.ts
|
|
124321
|
+
var ApiError = class extends Error {
|
|
124322
|
+
status;
|
|
124323
|
+
constructor(status, message) {
|
|
124324
|
+
super(message);
|
|
124325
|
+
this.status = status;
|
|
124326
|
+
}
|
|
124327
|
+
};
|
|
124328
|
+
/**
|
|
124329
|
+
* Unwrap a FastAPI `HTTPException` body — wire-encoded as
|
|
124330
|
+
* `{"detail": "..."}` — into the bare detail string.
|
|
124331
|
+
*
|
|
124332
|
+
* Returns the input unchanged when:
|
|
124333
|
+
* - the body isn't valid JSON (e.g. the server sent plain text), or
|
|
124334
|
+
* - the JSON has no top-level `detail` string (older endpoints,
|
|
124335
|
+
* custom error shapes).
|
|
124336
|
+
*
|
|
124337
|
+
* Used by callers that build their own `ApiError` from a non-OK
|
|
124338
|
+
* response so the dialog renders e.g. `Empty tag is not allowed`
|
|
124339
|
+
* instead of `{"detail": "Empty tag is not allowed"}`.
|
|
124340
|
+
*/
|
|
124341
|
+
function unwrapFastapiDetail(body) {
|
|
124342
|
+
if (!body) return body;
|
|
124343
|
+
try {
|
|
124344
|
+
const parsed = JSON.parse(body);
|
|
124345
|
+
if (parsed && typeof parsed === "object" && "detail" in parsed && typeof parsed.detail === "string") return parsed.detail;
|
|
124346
|
+
} catch {}
|
|
124347
|
+
return body;
|
|
124348
|
+
}
|
|
124349
|
+
function serverRequestApi(baseUrl, getHeaders) {
|
|
124350
|
+
const apiUrl = baseUrl || "";
|
|
124351
|
+
function buildApiUrl(path) {
|
|
124352
|
+
if (!apiUrl) return path;
|
|
124353
|
+
return (apiUrl.endsWith("/") ? apiUrl.slice(0, -1) : apiUrl) + (path.startsWith("/") ? path : `/${path}`);
|
|
124354
|
+
}
|
|
124355
|
+
function isApiCrossOrigin() {
|
|
124356
|
+
try {
|
|
124357
|
+
return Boolean(apiUrl && new URL(apiUrl).origin !== window.location.origin);
|
|
124358
|
+
} catch (error) {
|
|
124359
|
+
return false;
|
|
124360
|
+
}
|
|
124361
|
+
}
|
|
124362
|
+
const fetchType = async (method, path, request) => {
|
|
124363
|
+
const url = buildApiUrl(path);
|
|
124364
|
+
const responseHeaders = {
|
|
124365
|
+
Accept: "application/json",
|
|
124366
|
+
Pragma: "no-cache",
|
|
124367
|
+
Expires: "0",
|
|
124368
|
+
"Cache-Control": "no-cache",
|
|
124369
|
+
...request.headers
|
|
124370
|
+
};
|
|
124371
|
+
if (getHeaders) {
|
|
124372
|
+
const globalHeaders = await getHeaders();
|
|
124373
|
+
Object.assign(responseHeaders, globalHeaders);
|
|
124374
|
+
}
|
|
124375
|
+
if (request.body) responseHeaders["Content-Type"] = "application/json";
|
|
124376
|
+
const response = await fetch(url, {
|
|
124377
|
+
method,
|
|
124378
|
+
headers: responseHeaders,
|
|
124379
|
+
body: request.body,
|
|
124380
|
+
credentials: isApiCrossOrigin() ? "include" : "same-origin"
|
|
124381
|
+
});
|
|
124382
|
+
if (!response.ok) {
|
|
124383
|
+
const errorResponse = request.handleError?.(response.status);
|
|
124384
|
+
if (errorResponse) return {
|
|
124385
|
+
raw: response.statusText,
|
|
124386
|
+
parsed: errorResponse
|
|
124387
|
+
};
|
|
124388
|
+
const message = await response.text() || response.statusText;
|
|
124389
|
+
throw new ApiError(response.status, `API Error ${response.status}: ${message}`);
|
|
124390
|
+
}
|
|
124391
|
+
const text = await response.text();
|
|
124392
|
+
return {
|
|
124393
|
+
parsed: await (request.parse || asyncJsonParse)(text),
|
|
124394
|
+
raw: text
|
|
124395
|
+
};
|
|
124396
|
+
};
|
|
124397
|
+
const fetchString = async (method, path, headers, body) => {
|
|
124398
|
+
const url = buildApiUrl(path);
|
|
124399
|
+
const requestHeaders = {
|
|
124400
|
+
Accept: "application/json",
|
|
124401
|
+
Pragma: "no-cache",
|
|
124402
|
+
Expires: "0",
|
|
124403
|
+
"Cache-Control": "no-cache",
|
|
124404
|
+
...headers
|
|
124405
|
+
};
|
|
124406
|
+
if (getHeaders) {
|
|
124407
|
+
const globalHeaders = await getHeaders();
|
|
124408
|
+
Object.assign(requestHeaders, globalHeaders);
|
|
124409
|
+
}
|
|
124410
|
+
if (body) requestHeaders["Content-Type"] = "application/json";
|
|
124411
|
+
const response = await fetch(url, {
|
|
124412
|
+
method,
|
|
124413
|
+
headers: requestHeaders,
|
|
124414
|
+
body,
|
|
124415
|
+
credentials: isApiCrossOrigin() ? "include" : "same-origin"
|
|
124416
|
+
});
|
|
124417
|
+
if (response.ok) {
|
|
124418
|
+
const text = await response.text();
|
|
124419
|
+
return {
|
|
124420
|
+
parsed: await asyncJsonParse(text),
|
|
124421
|
+
raw: text
|
|
124422
|
+
};
|
|
124423
|
+
}
|
|
124424
|
+
const message = await response.text() || response.statusText;
|
|
124425
|
+
throw new ApiError(response.status, `HTTP ${response.status}: ${message}`);
|
|
124426
|
+
};
|
|
124427
|
+
const fetchBytes = async (method, path) => {
|
|
124428
|
+
const url = buildApiUrl(path);
|
|
124429
|
+
const headers = {
|
|
124430
|
+
Accept: "application/octet-stream",
|
|
124431
|
+
Pragma: "no-cache",
|
|
124432
|
+
Expires: "0",
|
|
124433
|
+
"Cache-Control": "no-cache"
|
|
124434
|
+
};
|
|
124435
|
+
if (getHeaders) {
|
|
124436
|
+
const globalHeaders = await getHeaders();
|
|
124437
|
+
Object.assign(headers, globalHeaders);
|
|
124438
|
+
}
|
|
124439
|
+
const response = await fetch(url, {
|
|
124440
|
+
method,
|
|
124441
|
+
headers,
|
|
124442
|
+
credentials: isApiCrossOrigin() ? "include" : "same-origin"
|
|
124443
|
+
});
|
|
124444
|
+
if (!response.ok) {
|
|
124445
|
+
const message = await response.text() || response.statusText;
|
|
124446
|
+
throw new ApiError(response.status, `HTTP ${response.status}: ${message}`);
|
|
124447
|
+
}
|
|
124448
|
+
const buffer = await response.arrayBuffer();
|
|
124449
|
+
return new Uint8Array(buffer);
|
|
124450
|
+
};
|
|
124451
|
+
return {
|
|
124452
|
+
fetchString,
|
|
124453
|
+
fetchBytes,
|
|
124454
|
+
fetchType
|
|
124455
|
+
};
|
|
124456
|
+
}
|
|
124457
|
+
//#endregion
|
|
124458
|
+
//#region src/app/log-view/title-view/editErrors.ts
|
|
124459
|
+
function formatEditError(err) {
|
|
124460
|
+
if (err instanceof ApiError) {
|
|
124461
|
+
if (err.status === 412) return "This log was modified by someone else. Please reload and try again.";
|
|
124462
|
+
return err.message;
|
|
124463
|
+
}
|
|
124464
|
+
if (err instanceof TypeError) return "Connection lost — view server unreachable.";
|
|
124465
|
+
if (err instanceof Error) return err.message;
|
|
124466
|
+
return String(err);
|
|
124467
|
+
}
|
|
124468
|
+
var EditMetadataDialog_module_default = {
|
|
124469
|
+
tableScroll: "_tableScroll_1i84k_5",
|
|
124470
|
+
table: "_table_1i84k_5",
|
|
124471
|
+
empty: "_empty_1i84k_23",
|
|
124472
|
+
row: "_row_1i84k_30",
|
|
124473
|
+
rowDivider: "_rowDivider_1i84k_37",
|
|
124474
|
+
rowNew: "_rowNew_1i84k_41",
|
|
124475
|
+
key: "_key_1i84k_54",
|
|
124476
|
+
value: "_value_1i84k_51",
|
|
124477
|
+
remove: "_remove_1i84k_54",
|
|
124478
|
+
addRow: "_addRow_1i84k_87",
|
|
124479
|
+
addKeyInput: "_addKeyInput_1i84k_94",
|
|
124480
|
+
typeSelect: "_typeSelect_1i84k_98",
|
|
124481
|
+
addButton: "_addButton_1i84k_102"
|
|
124482
|
+
};
|
|
124483
|
+
//#endregion
|
|
124484
|
+
//#region src/app/log-view/title-view/ProvenanceFields.tsx
|
|
124485
|
+
var ProvenanceFields = ({ author, setAuthor, reason, setReason, disabled }) => /* @__PURE__ */ jsxs("div", {
|
|
124486
|
+
className: EditAnnotationsDialog_module_default.provenance,
|
|
124487
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
124488
|
+
className: EditAnnotationsDialog_module_default.section,
|
|
124489
|
+
children: [/* @__PURE__ */ jsxs("label", {
|
|
124490
|
+
className: clsx("text-size-smaller", EditAnnotationsDialog_module_default.label),
|
|
124491
|
+
htmlFor: "edit-annotations-author",
|
|
124492
|
+
children: ["Author ", /* @__PURE__ */ jsx("span", {
|
|
124493
|
+
className: EditAnnotationsDialog_module_default.required,
|
|
124494
|
+
children: "*"
|
|
124495
|
+
})]
|
|
124496
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
124497
|
+
id: "edit-annotations-author",
|
|
124498
|
+
type: "text",
|
|
124499
|
+
className: clsx("form-control", "text-size-smaller"),
|
|
124500
|
+
placeholder: "Your name or username",
|
|
124501
|
+
value: author,
|
|
124502
|
+
onChange: (e) => setAuthor(e.target.value),
|
|
124503
|
+
disabled,
|
|
124504
|
+
"aria-required": "true"
|
|
124505
|
+
})]
|
|
124506
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
124507
|
+
className: EditAnnotationsDialog_module_default.section,
|
|
124508
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
124509
|
+
className: EditAnnotationsDialog_module_default.labelRow,
|
|
124510
|
+
children: [/* @__PURE__ */ jsx("label", {
|
|
124511
|
+
className: clsx("text-size-smaller", EditAnnotationsDialog_module_default.label),
|
|
124512
|
+
htmlFor: "edit-annotations-reason",
|
|
124513
|
+
children: "Reason"
|
|
124514
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
124515
|
+
className: clsx("text-size-smaller", EditAnnotationsDialog_module_default.hint),
|
|
124516
|
+
children: "optional"
|
|
124517
|
+
})]
|
|
124518
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
124519
|
+
id: "edit-annotations-reason",
|
|
124520
|
+
type: "text",
|
|
124521
|
+
className: clsx("form-control", "text-size-smaller"),
|
|
124522
|
+
value: reason,
|
|
124523
|
+
onChange: (e) => setReason(e.target.value),
|
|
124524
|
+
disabled
|
|
124525
|
+
})]
|
|
124526
|
+
})]
|
|
124527
|
+
});
|
|
124528
|
+
//#endregion
|
|
124529
|
+
//#region src/app/log-view/title-view/EditMetadataDialog.tsx
|
|
124530
|
+
var toEditableString = (v) => {
|
|
124531
|
+
if (typeof v === "string") return v;
|
|
124532
|
+
return JSON.stringify(v, null, 2);
|
|
124533
|
+
};
|
|
124534
|
+
/**
|
|
124535
|
+
* Thrown by {@link serializeEntry} when a non-string entry's text
|
|
124536
|
+
* isn't well-formed JSON. The dialog's save handler catches this and
|
|
124537
|
+
* surfaces a per-key error message so the user knows which row needs
|
|
124538
|
+
* to be fixed.
|
|
124539
|
+
*/
|
|
124540
|
+
var MetadataParseError = class extends Error {
|
|
124541
|
+
key;
|
|
124542
|
+
text;
|
|
124543
|
+
cause;
|
|
124544
|
+
constructor(key, text, cause) {
|
|
124545
|
+
super(`Invalid JSON for "${key}"`);
|
|
124546
|
+
this.key = key;
|
|
124547
|
+
this.text = text;
|
|
124548
|
+
this.cause = cause;
|
|
124549
|
+
this.name = "MetadataParseError";
|
|
124550
|
+
}
|
|
124551
|
+
};
|
|
124552
|
+
var looksLikeJsonSyntax = (text) => {
|
|
124553
|
+
const trimmed = text.trim();
|
|
124554
|
+
return trimmed.startsWith("{") || trimmed.startsWith("[") || trimmed.startsWith("\"");
|
|
124555
|
+
};
|
|
124556
|
+
/**
|
|
124557
|
+
* Convert a dialog entry to its on-the-wire value, honoring the user's
|
|
124558
|
+
* chosen type *unless* the text carries JSON syntax (a leading `{`,
|
|
124559
|
+
* `[`, or `"`), in which case the structured intent wins:
|
|
124560
|
+
*
|
|
124561
|
+
* - String-typed rows are saved verbatim when the text doesn't look
|
|
124562
|
+
* structural. So a `string` row whose text is `43`, `approved`, or
|
|
124563
|
+
* `true` round-trips as the string `"43"` / `"approved"` / `"true"`.
|
|
124564
|
+
* - Anything else (other types, or string-typed but JSON-looking)
|
|
124565
|
+
* goes through `JSON.parse`. Well-formed input lands as the proper
|
|
124566
|
+
* JS value (`true`, `42`, `[1,2,3]`, `{"a": 1}`, `null`); malformed
|
|
124567
|
+
* input throws {@link MetadataParseError} so the dialog can show a
|
|
124568
|
+
* per-key message instead of saving garbage.
|
|
124569
|
+
*
|
|
124570
|
+
* Exported for unit testing.
|
|
124571
|
+
*/
|
|
124572
|
+
var serializeEntry = (entry) => {
|
|
124573
|
+
if (entry.isString && !looksLikeJsonSyntax(entry.text)) return entry.text;
|
|
124574
|
+
try {
|
|
124575
|
+
return JSON.parse(entry.text);
|
|
124576
|
+
} catch (e) {
|
|
124577
|
+
throw new MetadataParseError(entry.key, entry.text, e);
|
|
124578
|
+
}
|
|
124579
|
+
};
|
|
124580
|
+
var seedFor = (type) => {
|
|
124581
|
+
switch (type) {
|
|
124582
|
+
case "string": return "";
|
|
124583
|
+
case "number": return 0;
|
|
124584
|
+
case "boolean": return false;
|
|
124585
|
+
case "object": return {};
|
|
124586
|
+
case "array": return [];
|
|
124587
|
+
case "null": return null;
|
|
124588
|
+
}
|
|
124589
|
+
};
|
|
124590
|
+
var EditMetadataDialog = ({ showing, setShowing, currentMetadata, logFile, onSaved }) => {
|
|
124591
|
+
const api = useApi();
|
|
124592
|
+
const initialEntries = useMemo(() => Object.entries(currentMetadata).map(([key, value]) => ({
|
|
124593
|
+
key,
|
|
124594
|
+
text: toEditableString(value),
|
|
124595
|
+
isString: typeof value === "string"
|
|
124596
|
+
})), [currentMetadata]);
|
|
124597
|
+
const [entries, setEntries] = useState(initialEntries);
|
|
124598
|
+
const [removed, setRemoved] = useState([]);
|
|
124599
|
+
const [newKey, setNewKey] = useState("");
|
|
124600
|
+
const [newType, setNewType] = useState("string");
|
|
124601
|
+
const [author, setAuthor] = useState("");
|
|
124602
|
+
const [reason, setReason] = useState("");
|
|
124603
|
+
const [submitting, setSubmitting] = useState(false);
|
|
124604
|
+
const [error, setError] = useState();
|
|
124605
|
+
const [pendingFocusKey, setPendingFocusKey] = useState(null);
|
|
124606
|
+
useEffect(() => {
|
|
124607
|
+
if (!showing) return;
|
|
124608
|
+
setEntries(initialEntries);
|
|
124609
|
+
setRemoved([]);
|
|
124610
|
+
setNewKey("");
|
|
124611
|
+
setNewType("string");
|
|
124612
|
+
setAuthor("");
|
|
124613
|
+
setReason("");
|
|
124614
|
+
setSubmitting(false);
|
|
124615
|
+
setError(void 0);
|
|
124616
|
+
let cancelled = false;
|
|
124617
|
+
if (api?.get_user_info) api.get_user_info().then((info) => {
|
|
124618
|
+
if (!cancelled && info.name) setAuthor((current) => current || info.name || "");
|
|
124619
|
+
}).catch(() => {});
|
|
124620
|
+
return () => {
|
|
124621
|
+
cancelled = true;
|
|
124622
|
+
};
|
|
124623
|
+
}, [
|
|
124624
|
+
showing,
|
|
124625
|
+
initialEntries,
|
|
124626
|
+
api
|
|
124627
|
+
]);
|
|
124628
|
+
const existingKeys = useMemo(() => new Set(entries.map((e) => e.key)), [entries]);
|
|
124629
|
+
const adding = entries.filter((e) => e.isNew).map((e) => e.key);
|
|
124630
|
+
const editing = entries.filter((e) => e.dirty && !e.isNew).map((e) => e.key);
|
|
124631
|
+
const hasChanges = adding.length > 0 || editing.length > 0 || removed.length > 0;
|
|
124632
|
+
const updateValue = useCallback((key, text) => {
|
|
124633
|
+
setEntries((prev) => prev.map((e) => e.key === key ? {
|
|
124634
|
+
...e,
|
|
124635
|
+
text,
|
|
124636
|
+
dirty: true
|
|
124637
|
+
} : e));
|
|
124638
|
+
}, []);
|
|
124639
|
+
const removeKey = useCallback((key) => {
|
|
124640
|
+
setEntries((prev) => {
|
|
124641
|
+
const entry = prev.find((e) => e.key === key);
|
|
124642
|
+
if (!entry) return prev;
|
|
124643
|
+
if (!entry.isNew) setRemoved((r) => r.includes(key) ? r : [...r, key]);
|
|
124644
|
+
return prev.filter((e) => e.key !== key);
|
|
124645
|
+
});
|
|
124646
|
+
}, []);
|
|
124647
|
+
const addKey = () => {
|
|
124648
|
+
const k = newKey.trim();
|
|
124649
|
+
if (!k) return;
|
|
124650
|
+
if (existingKeys.has(k)) {
|
|
124651
|
+
setNewKey("");
|
|
124652
|
+
return;
|
|
124653
|
+
}
|
|
124654
|
+
if (removed.includes(k)) setRemoved((r) => r.filter((x) => x !== k));
|
|
124655
|
+
setEntries((prev) => [...prev, {
|
|
124656
|
+
key: k,
|
|
124657
|
+
text: toEditableString(seedFor(newType)),
|
|
124658
|
+
isString: newType === "string",
|
|
124659
|
+
isNew: true,
|
|
124660
|
+
dirty: true
|
|
124661
|
+
}]);
|
|
124662
|
+
setNewKey("");
|
|
124663
|
+
setNewType("string");
|
|
124664
|
+
setPendingFocusKey(k);
|
|
124665
|
+
};
|
|
124666
|
+
useEffect(() => {
|
|
124667
|
+
if (pendingFocusKey == null) return;
|
|
124668
|
+
const selector = `[data-meta-key="${CSS.escape(pendingFocusKey)}"]`;
|
|
124669
|
+
const textarea = document.querySelector(selector)?.querySelector("textarea");
|
|
124670
|
+
if (textarea) {
|
|
124671
|
+
textarea.scrollIntoView({
|
|
124672
|
+
behavior: "smooth",
|
|
124673
|
+
block: "nearest"
|
|
124674
|
+
});
|
|
124675
|
+
textarea.focus();
|
|
124676
|
+
}
|
|
124677
|
+
setPendingFocusKey(null);
|
|
124678
|
+
}, [pendingFocusKey]);
|
|
124679
|
+
const handleNewKeyDown = (e) => {
|
|
124680
|
+
if (e.key === "Enter") {
|
|
124681
|
+
e.preventDefault();
|
|
124682
|
+
addKey();
|
|
124683
|
+
}
|
|
124684
|
+
};
|
|
124685
|
+
const canSave = !submitting && hasChanges && author.trim().length > 0 && !!api?.edit_log;
|
|
124686
|
+
const inFlightRef = useRef(false);
|
|
124687
|
+
const handleSave = async () => {
|
|
124688
|
+
if (!canSave || inFlightRef.current || !api?.edit_log) return;
|
|
124689
|
+
inFlightRef.current = true;
|
|
124690
|
+
const indicatorTimer = window.setTimeout(() => setSubmitting(true), 200);
|
|
124691
|
+
try {
|
|
124692
|
+
const metadata_set = {};
|
|
124693
|
+
for (const entry of entries) if (entry.isNew || entry.dirty) metadata_set[entry.key] = serializeEntry(entry);
|
|
124694
|
+
const edit = {
|
|
124695
|
+
type: "metadata",
|
|
124696
|
+
metadata_set,
|
|
124697
|
+
metadata_remove: removed
|
|
124698
|
+
};
|
|
124699
|
+
await api.edit_log(logFile, {
|
|
124700
|
+
edits: [edit],
|
|
124701
|
+
provenance: {
|
|
124702
|
+
author: author.trim(),
|
|
124703
|
+
reason: reason.trim() || void 0,
|
|
124704
|
+
metadata: {},
|
|
124705
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
124706
|
+
}
|
|
124707
|
+
});
|
|
124708
|
+
setShowing(false);
|
|
124709
|
+
onSaved?.();
|
|
124710
|
+
} catch (err) {
|
|
124711
|
+
if (err instanceof MetadataParseError) setError(`Invalid JSON for "${err.key}". Use JSON syntax — quote keys and strings, e.g. {"a": 1} or "yes".`);
|
|
124712
|
+
else setError(formatEditError(err));
|
|
124713
|
+
} finally {
|
|
124714
|
+
window.clearTimeout(indicatorTimer);
|
|
124715
|
+
setSubmitting(false);
|
|
124716
|
+
inFlightRef.current = false;
|
|
124717
|
+
}
|
|
124718
|
+
};
|
|
124719
|
+
return /* @__PURE__ */ jsx(Modal, {
|
|
124720
|
+
id: "edit-metadata-dialog",
|
|
124721
|
+
showing,
|
|
124722
|
+
setShowing,
|
|
124723
|
+
title: "Edit metadata",
|
|
124724
|
+
width: "820px",
|
|
124725
|
+
footer: /* @__PURE__ */ jsxs("div", {
|
|
124726
|
+
className: EditAnnotationsDialog_module_default.footer,
|
|
124727
|
+
children: [/* @__PURE__ */ jsx(ChangeSummary, {
|
|
124728
|
+
adding,
|
|
124729
|
+
editing,
|
|
124730
|
+
removing: removed
|
|
124731
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
124732
|
+
className: EditAnnotationsDialog_module_default.footerActions,
|
|
124733
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
124734
|
+
type: "button",
|
|
124735
|
+
className: clsx("btn", "btn-secondary", "text-size-smaller"),
|
|
124736
|
+
onClick: () => setShowing(false),
|
|
124737
|
+
disabled: submitting,
|
|
124738
|
+
children: "Cancel"
|
|
124739
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
124740
|
+
type: "button",
|
|
124741
|
+
className: clsx("btn", "btn-primary", "text-size-smaller"),
|
|
124742
|
+
onClick: handleSave,
|
|
124743
|
+
disabled: !canSave,
|
|
124744
|
+
children: submitting ? "Saving…" : "Save"
|
|
124745
|
+
})]
|
|
124746
|
+
})]
|
|
124747
|
+
}),
|
|
124748
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
124749
|
+
className: EditAnnotationsDialog_module_default.body,
|
|
124750
|
+
children: [
|
|
124751
|
+
/* @__PURE__ */ jsxs("div", {
|
|
124752
|
+
className: EditAnnotationsDialog_module_default.section,
|
|
124753
|
+
children: [
|
|
124754
|
+
/* @__PURE__ */ jsxs("div", {
|
|
124755
|
+
className: EditAnnotationsDialog_module_default.labelRow,
|
|
124756
|
+
children: [/* @__PURE__ */ jsx("label", {
|
|
124757
|
+
className: clsx("text-size-smaller", EditAnnotationsDialog_module_default.label),
|
|
124758
|
+
children: "Metadata"
|
|
124759
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
124760
|
+
className: clsx("text-size-smaller", EditAnnotationsDialog_module_default.hint),
|
|
124761
|
+
children: "Values are edited as plain text. Use JSON syntax for nested values."
|
|
124762
|
+
})]
|
|
124763
|
+
}),
|
|
124764
|
+
/* @__PURE__ */ jsx("div", {
|
|
124765
|
+
className: EditMetadataDialog_module_default.tableScroll,
|
|
124766
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
124767
|
+
className: EditMetadataDialog_module_default.table,
|
|
124768
|
+
children: [entries.length === 0 && /* @__PURE__ */ jsx("div", {
|
|
124769
|
+
className: clsx("text-size-smaller", EditMetadataDialog_module_default.empty),
|
|
124770
|
+
children: "No metadata yet — add a key below."
|
|
124771
|
+
}), entries.map((entry, idx) => /* @__PURE__ */ jsx(MetaRow, {
|
|
124772
|
+
entry,
|
|
124773
|
+
first: idx === 0,
|
|
124774
|
+
onChange: (text) => updateValue(entry.key, text),
|
|
124775
|
+
onRemove: () => removeKey(entry.key),
|
|
124776
|
+
disabled: submitting
|
|
124777
|
+
}, entry.key))]
|
|
124778
|
+
})
|
|
124779
|
+
}),
|
|
124780
|
+
/* @__PURE__ */ jsxs("div", {
|
|
124781
|
+
className: EditMetadataDialog_module_default.addRow,
|
|
124782
|
+
children: [
|
|
124783
|
+
/* @__PURE__ */ jsx("input", {
|
|
124784
|
+
type: "text",
|
|
124785
|
+
className: clsx("form-control", "text-size-smaller", EditMetadataDialog_module_default.addKeyInput),
|
|
124786
|
+
placeholder: "Add a key…",
|
|
124787
|
+
value: newKey,
|
|
124788
|
+
onChange: (e) => setNewKey(e.target.value),
|
|
124789
|
+
onKeyDown: handleNewKeyDown,
|
|
124790
|
+
disabled: submitting
|
|
124791
|
+
}),
|
|
124792
|
+
/* @__PURE__ */ jsxs("select", {
|
|
124793
|
+
className: clsx("form-select", "text-size-smaller", EditMetadataDialog_module_default.typeSelect),
|
|
124794
|
+
value: newType,
|
|
124795
|
+
onChange: (e) => setNewType(e.target.value),
|
|
124796
|
+
"aria-label": "Type for new key",
|
|
124797
|
+
disabled: submitting,
|
|
124798
|
+
children: [
|
|
124799
|
+
/* @__PURE__ */ jsx("option", {
|
|
124800
|
+
value: "string",
|
|
124801
|
+
children: "string"
|
|
124802
|
+
}),
|
|
124803
|
+
/* @__PURE__ */ jsx("option", {
|
|
124804
|
+
value: "number",
|
|
124805
|
+
children: "number"
|
|
124806
|
+
}),
|
|
124807
|
+
/* @__PURE__ */ jsx("option", {
|
|
124808
|
+
value: "boolean",
|
|
124809
|
+
children: "boolean"
|
|
124810
|
+
}),
|
|
124811
|
+
/* @__PURE__ */ jsx("option", {
|
|
124812
|
+
value: "object",
|
|
124813
|
+
children: "object"
|
|
124814
|
+
}),
|
|
124815
|
+
/* @__PURE__ */ jsx("option", {
|
|
124816
|
+
value: "array",
|
|
124817
|
+
children: "array"
|
|
124818
|
+
}),
|
|
124819
|
+
/* @__PURE__ */ jsx("option", {
|
|
124820
|
+
value: "null",
|
|
124821
|
+
children: "null"
|
|
124822
|
+
})
|
|
124823
|
+
]
|
|
124824
|
+
}),
|
|
124825
|
+
/* @__PURE__ */ jsxs("button", {
|
|
124826
|
+
type: "button",
|
|
124827
|
+
className: clsx("btn", newKey.trim() ? "btn-primary" : "btn-secondary", "text-size-smaller", EditMetadataDialog_module_default.addButton),
|
|
124828
|
+
onClick: addKey,
|
|
124829
|
+
disabled: submitting || !newKey.trim(),
|
|
124830
|
+
children: [/* @__PURE__ */ jsx("i", { className: ApplicationIcons.changes.add }), " Add key"]
|
|
124831
|
+
})
|
|
124832
|
+
]
|
|
124833
|
+
})
|
|
124834
|
+
]
|
|
124835
|
+
}),
|
|
124836
|
+
/* @__PURE__ */ jsx("hr", { className: EditAnnotationsDialog_module_default.divider }),
|
|
124837
|
+
/* @__PURE__ */ jsx(ProvenanceFields, {
|
|
124838
|
+
author,
|
|
124839
|
+
setAuthor,
|
|
124840
|
+
reason,
|
|
124841
|
+
setReason,
|
|
124842
|
+
disabled: submitting
|
|
124843
|
+
}),
|
|
124844
|
+
error && /* @__PURE__ */ jsx("div", {
|
|
124845
|
+
className: clsx("text-size-smaller", EditAnnotationsDialog_module_default.error),
|
|
124846
|
+
children: error
|
|
124847
|
+
})
|
|
124848
|
+
]
|
|
124849
|
+
})
|
|
124850
|
+
});
|
|
124851
|
+
};
|
|
124852
|
+
var MetaRow = ({ entry, first, onChange, onRemove, disabled }) => /* @__PURE__ */ jsxs("div", {
|
|
124853
|
+
className: clsx(EditMetadataDialog_module_default.row, !first && EditMetadataDialog_module_default.rowDivider, entry.isNew && EditMetadataDialog_module_default.rowNew),
|
|
124854
|
+
"data-meta-key": entry.key,
|
|
124855
|
+
children: [
|
|
124856
|
+
/* @__PURE__ */ jsx("span", {
|
|
124857
|
+
className: clsx("text-size-smaller", EditMetadataDialog_module_default.key),
|
|
124858
|
+
children: entry.key
|
|
124859
|
+
}),
|
|
124860
|
+
/* @__PURE__ */ jsx("div", {
|
|
124861
|
+
className: EditMetadataDialog_module_default.value,
|
|
124862
|
+
children: /* @__PURE__ */ jsx(AutogrowText, {
|
|
124863
|
+
value: entry.text,
|
|
124864
|
+
onChange,
|
|
124865
|
+
disabled
|
|
124866
|
+
})
|
|
124867
|
+
}),
|
|
124868
|
+
/* @__PURE__ */ jsx("button", {
|
|
124869
|
+
type: "button",
|
|
124870
|
+
className: EditMetadataDialog_module_default.remove,
|
|
124871
|
+
onClick: onRemove,
|
|
124872
|
+
title: `Remove ${entry.key}`,
|
|
124873
|
+
"aria-label": `Remove ${entry.key}`,
|
|
124874
|
+
disabled,
|
|
124875
|
+
children: /* @__PURE__ */ jsx("i", { className: ApplicationIcons.trash })
|
|
124876
|
+
})
|
|
124877
|
+
]
|
|
124878
|
+
});
|
|
124879
|
+
var PlanCard_module_default = {
|
|
124880
|
+
headerActions: "_headerActions_1fn25_1",
|
|
124881
|
+
emptyMetadata: "_emptyMetadata_1fn25_10"
|
|
124882
|
+
};
|
|
123884
124883
|
var DatasetDetailView_module_default = { item: "_item_1uzhd_1" };
|
|
123885
124884
|
//#endregion
|
|
123886
124885
|
//#region src/app/plan/DatasetDetailView.tsx
|
|
@@ -124043,21 +125042,46 @@ var PlanColumn = ({ title, className, children }) => {
|
|
|
124043
125042
|
*/
|
|
124044
125043
|
var PlanCard = ({ evalSpec, evalPlan, scores, metadata: metadataProp, scrollRef }) => {
|
|
124045
125044
|
const metadata = metadataProp || {};
|
|
124046
|
-
|
|
124047
|
-
|
|
124048
|
-
|
|
124049
|
-
|
|
124050
|
-
|
|
124051
|
-
|
|
124052
|
-
|
|
124053
|
-
|
|
124054
|
-
|
|
124055
|
-
|
|
124056
|
-
|
|
124057
|
-
|
|
124058
|
-
|
|
125045
|
+
const hasMetadata = Object.keys(metadata).length > 0;
|
|
125046
|
+
const { canEdit, selectedLogFile, refreshOnSave } = useLogEditAffordance();
|
|
125047
|
+
const [editingMetadata, setEditingMetadata] = useState(false);
|
|
125048
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
125049
|
+
/* @__PURE__ */ jsxs(Card, { children: [/* @__PURE__ */ jsx(CardHeader, { label: "Summary" }), /* @__PURE__ */ jsx(CardBody, {
|
|
125050
|
+
id: "task-plan-card-body",
|
|
125051
|
+
children: /* @__PURE__ */ jsx(PlanDetailView, {
|
|
125052
|
+
evaluation: evalSpec,
|
|
125053
|
+
plan: evalPlan,
|
|
125054
|
+
scores
|
|
125055
|
+
})
|
|
125056
|
+
})] }),
|
|
125057
|
+
(hasMetadata || canEdit) && /* @__PURE__ */ jsxs(Card, { children: [/* @__PURE__ */ jsx(CardHeader, {
|
|
125058
|
+
label: "Metadata",
|
|
125059
|
+
children: canEdit && /* @__PURE__ */ jsx("span", {
|
|
125060
|
+
className: PlanCard_module_default.headerActions,
|
|
125061
|
+
children: /* @__PURE__ */ jsx(EditButton, {
|
|
125062
|
+
onClick: () => setEditingMetadata(true),
|
|
125063
|
+
title: "Edit metadata"
|
|
125064
|
+
})
|
|
125065
|
+
})
|
|
125066
|
+
}), /* @__PURE__ */ jsx(CardBody, {
|
|
125067
|
+
id: "task-metadata",
|
|
125068
|
+
children: hasMetadata ? /* @__PURE__ */ jsx(RecordTree, {
|
|
125069
|
+
id: "plan-md-metadata",
|
|
125070
|
+
record: metadata,
|
|
125071
|
+
scrollRef
|
|
125072
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
125073
|
+
className: clsx("text-size-smaller", PlanCard_module_default.emptyMetadata),
|
|
125074
|
+
children: "No metadata — click Edit to add a key."
|
|
125075
|
+
})
|
|
125076
|
+
})] }),
|
|
125077
|
+
selectedLogFile && /* @__PURE__ */ jsx(EditMetadataDialog, {
|
|
125078
|
+
showing: editingMetadata,
|
|
125079
|
+
setShowing: setEditingMetadata,
|
|
125080
|
+
currentMetadata: metadata,
|
|
125081
|
+
logFile: selectedLogFile,
|
|
125082
|
+
onSaved: refreshOnSave
|
|
124059
125083
|
})
|
|
124060
|
-
|
|
125084
|
+
] });
|
|
124061
125085
|
};
|
|
124062
125086
|
//#endregion
|
|
124063
125087
|
//#region src/app/log-view/tabs/InfoTab.tsx
|
|
@@ -147492,7 +148516,7 @@ var SearchCursor = class {
|
|
|
147492
148516
|
if (typeof Symbol != "undefined") SearchCursor.prototype[Symbol.iterator] = function() {
|
|
147493
148517
|
return this;
|
|
147494
148518
|
};
|
|
147495
|
-
var empty = {
|
|
148519
|
+
var empty$1 = {
|
|
147496
148520
|
from: -1,
|
|
147497
148521
|
to: -1,
|
|
147498
148522
|
match: /* @__PURE__ */ /.*/.exec("")
|
|
@@ -147523,7 +148547,7 @@ var RegExpCursor = class {
|
|
|
147523
148547
|
match object when [`next`](https://codemirror.net/6/docs/ref/#search.RegExpCursor.next)
|
|
147524
148548
|
sucessfully finds a match.
|
|
147525
148549
|
*/
|
|
147526
|
-
this.value = empty;
|
|
148550
|
+
this.value = empty$1;
|
|
147527
148551
|
if (/\\[sWDnr]|\n|\r|\[\^/.test(query)) return new MultilineRegExpCursor(text, query, options, from, to);
|
|
147528
148552
|
this.re = new RegExp(query, baseFlags + ((options === null || options === void 0 ? void 0 : options.ignoreCase) ? "i" : ""));
|
|
147529
148553
|
this.test = options === null || options === void 0 ? void 0 : options.test;
|
|
@@ -147609,7 +148633,7 @@ var MultilineRegExpCursor = class {
|
|
|
147609
148633
|
this.text = text;
|
|
147610
148634
|
this.to = to;
|
|
147611
148635
|
this.done = false;
|
|
147612
|
-
this.value = empty;
|
|
148636
|
+
this.value = empty$1;
|
|
147613
148637
|
this.matchPos = toCharEnd(text, from);
|
|
147614
148638
|
this.re = new RegExp(query, baseFlags + ((options === null || options === void 0 ? void 0 : options.ignoreCase) ? "i" : ""));
|
|
147615
148639
|
this.test = options === null || options === void 0 ? void 0 : options.test;
|
|
@@ -150116,6 +151140,25 @@ function buildSampleColumns(ctx) {
|
|
|
150116
151140
|
filter: true,
|
|
150117
151141
|
resizable: true,
|
|
150118
151142
|
valueFormatter: (params) => filename(params.value)
|
|
151143
|
+
}, {
|
|
151144
|
+
colId: "completed_at",
|
|
151145
|
+
headerName: "Completed",
|
|
151146
|
+
initialWidth: 140,
|
|
151147
|
+
minWidth: 80,
|
|
151148
|
+
maxWidth: 160,
|
|
151149
|
+
sortable: true,
|
|
151150
|
+
filter: true,
|
|
151151
|
+
resizable: true,
|
|
151152
|
+
cellDataType: "date",
|
|
151153
|
+
valueGetter: (params) => params.data?.data?.completed_at ?? void 0,
|
|
151154
|
+
filterValueGetter: (params) => {
|
|
151155
|
+
const v = params.data?.data?.completed_at;
|
|
151156
|
+
if (!v) return void 0;
|
|
151157
|
+
const d = new Date(v);
|
|
151158
|
+
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
151159
|
+
},
|
|
151160
|
+
valueFormatter: (params) => params.value ? formatDateTime(new Date(params.value)) : "",
|
|
151161
|
+
comparator: comparators.date
|
|
150119
151162
|
});
|
|
150120
151163
|
cols.push({
|
|
150121
151164
|
colId: "sampleId",
|
|
@@ -150261,25 +151304,6 @@ function buildSampleColumns(ctx) {
|
|
|
150261
151304
|
cellRenderer: (params) => params.value === void 0 || params.value === null ? /* @__PURE__ */ jsx(EmptyCell, {}) : /* @__PURE__ */ jsx("div", { children: formatTime(params.value) }),
|
|
150262
151305
|
tooltipValueGetter: (params) => params.value === void 0 || params.value === null ? void 0 : formatTime(params.value)
|
|
150263
151306
|
});
|
|
150264
|
-
cols.push(...buildScoreColumns(ctx));
|
|
150265
|
-
if (multiLog) cols.push({
|
|
150266
|
-
colId: "created",
|
|
150267
|
-
field: "created",
|
|
150268
|
-
headerName: "Created",
|
|
150269
|
-
initialWidth: 130,
|
|
150270
|
-
minWidth: 80,
|
|
150271
|
-
maxWidth: 140,
|
|
150272
|
-
sortable: true,
|
|
150273
|
-
filter: true,
|
|
150274
|
-
resizable: true,
|
|
150275
|
-
cellDataType: "date",
|
|
150276
|
-
filterValueGetter: (params) => {
|
|
150277
|
-
if (!params.data?.created) return void 0;
|
|
150278
|
-
const d = new Date(params.data.created);
|
|
150279
|
-
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
150280
|
-
},
|
|
150281
|
-
valueFormatter: (params) => params.value ? formatDateTime(new Date(params.value)) : ""
|
|
150282
|
-
});
|
|
150283
151307
|
cols.push({
|
|
150284
151308
|
colId: "error",
|
|
150285
151309
|
field: "error",
|
|
@@ -150325,6 +151349,25 @@ function buildSampleColumns(ctx) {
|
|
|
150325
151349
|
comparator: comparators.number,
|
|
150326
151350
|
valueGetter: (params) => params.data?.retries ?? params.data?.data?.retries
|
|
150327
151351
|
});
|
|
151352
|
+
cols.push(...buildScoreColumns(ctx));
|
|
151353
|
+
if (multiLog) cols.push({
|
|
151354
|
+
colId: "created",
|
|
151355
|
+
field: "created",
|
|
151356
|
+
headerName: "Eval Created",
|
|
151357
|
+
initialWidth: 140,
|
|
151358
|
+
minWidth: 80,
|
|
151359
|
+
maxWidth: 160,
|
|
151360
|
+
sortable: true,
|
|
151361
|
+
filter: true,
|
|
151362
|
+
resizable: true,
|
|
151363
|
+
cellDataType: "date",
|
|
151364
|
+
filterValueGetter: (params) => {
|
|
151365
|
+
if (!params.data?.created) return void 0;
|
|
151366
|
+
const d = new Date(params.data.created);
|
|
151367
|
+
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
151368
|
+
},
|
|
151369
|
+
valueFormatter: (params) => params.value ? formatDateTime(new Date(params.value)) : ""
|
|
151370
|
+
});
|
|
150328
151371
|
if (ctx.compactScores) cols.push({
|
|
150329
151372
|
colId: "compactSpacer",
|
|
150330
151373
|
headerName: "",
|
|
@@ -150936,7 +151979,352 @@ var SamplesTab = ({ running, scrollRef, showColumnSelector, setShowColumnSelecto
|
|
|
150936
151979
|
}) : null
|
|
150937
151980
|
] });
|
|
150938
151981
|
};
|
|
150939
|
-
var
|
|
151982
|
+
var EditTagsDialog_module_default = {
|
|
151983
|
+
chipBox: "_chipBox_yxwie_1",
|
|
151984
|
+
empty: "_empty_yxwie_12",
|
|
151985
|
+
addRow: "_addRow_yxwie_17",
|
|
151986
|
+
input: "_input_yxwie_23",
|
|
151987
|
+
addButton: "_addButton_yxwie_27"
|
|
151988
|
+
};
|
|
151989
|
+
var TagChip_module_default = {
|
|
151990
|
+
chip: "_chip_17zs5_1",
|
|
151991
|
+
chipLabel: "_chipLabel_17zs5_31",
|
|
151992
|
+
chipNew: "_chipNew_17zs5_40",
|
|
151993
|
+
chipClickable: "_chipClickable_17zs5_48",
|
|
151994
|
+
chipRemove: "_chipRemove_17zs5_61"
|
|
151995
|
+
};
|
|
151996
|
+
//#endregion
|
|
151997
|
+
//#region src/app/log-view/title-view/TagChip.tsx
|
|
151998
|
+
var TagChip = ({ label, isNew, onRemove, onClick }) => {
|
|
151999
|
+
const className = clsx(TagChip_module_default.chip, isNew && TagChip_module_default.chipNew, onClick && TagChip_module_default.chipClickable, "text-size-smallest");
|
|
152000
|
+
const labelNode = /* @__PURE__ */ jsx("span", {
|
|
152001
|
+
className: TagChip_module_default.chipLabel,
|
|
152002
|
+
children: label
|
|
152003
|
+
});
|
|
152004
|
+
if (onClick) return /* @__PURE__ */ jsx("button", {
|
|
152005
|
+
type: "button",
|
|
152006
|
+
className,
|
|
152007
|
+
title: label,
|
|
152008
|
+
"aria-label": `Edit tags (${label})`,
|
|
152009
|
+
onClick,
|
|
152010
|
+
children: labelNode
|
|
152011
|
+
});
|
|
152012
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
152013
|
+
className,
|
|
152014
|
+
title: label,
|
|
152015
|
+
children: [labelNode, onRemove && /* @__PURE__ */ jsx("button", {
|
|
152016
|
+
type: "button",
|
|
152017
|
+
className: TagChip_module_default.chipRemove,
|
|
152018
|
+
"aria-label": `Remove ${label}`,
|
|
152019
|
+
onClick: onRemove,
|
|
152020
|
+
children: /* @__PURE__ */ jsx("i", { className: ApplicationIcons.close })
|
|
152021
|
+
})]
|
|
152022
|
+
});
|
|
152023
|
+
};
|
|
152024
|
+
//#endregion
|
|
152025
|
+
//#region src/app/log-view/title-view/EditTagsDialog.tsx
|
|
152026
|
+
var EditTagsDialog = ({ showing, setShowing, currentTags, logFile, onSaved }) => {
|
|
152027
|
+
const api = useApi();
|
|
152028
|
+
const [tags, setTags] = useState(currentTags);
|
|
152029
|
+
const [pending, setPending] = useState("");
|
|
152030
|
+
const [author, setAuthor] = useState("");
|
|
152031
|
+
const [reason, setReason] = useState("");
|
|
152032
|
+
const [submitting, setSubmitting] = useState(false);
|
|
152033
|
+
const [error, setError] = useState();
|
|
152034
|
+
useEffect(() => {
|
|
152035
|
+
if (!showing) return;
|
|
152036
|
+
setTags(currentTags);
|
|
152037
|
+
setPending("");
|
|
152038
|
+
setAuthor("");
|
|
152039
|
+
setReason("");
|
|
152040
|
+
setError(void 0);
|
|
152041
|
+
setSubmitting(false);
|
|
152042
|
+
let cancelled = false;
|
|
152043
|
+
if (api?.get_user_info) api.get_user_info().then((info) => {
|
|
152044
|
+
if (!cancelled && info.name) setAuthor((current) => current || info.name || "");
|
|
152045
|
+
}).catch(() => {});
|
|
152046
|
+
return () => {
|
|
152047
|
+
cancelled = true;
|
|
152048
|
+
};
|
|
152049
|
+
}, [
|
|
152050
|
+
showing,
|
|
152051
|
+
currentTags,
|
|
152052
|
+
api
|
|
152053
|
+
]);
|
|
152054
|
+
const initialSet = useMemo(() => new Set(currentTags), [currentTags]);
|
|
152055
|
+
const currentSet = useMemo(() => new Set(tags), [tags]);
|
|
152056
|
+
const tagsAdd = useMemo(() => tags.filter((t) => !initialSet.has(t)), [tags, initialSet]);
|
|
152057
|
+
const tagsRemove = useMemo(() => currentTags.filter((t) => !currentSet.has(t)), [currentTags, currentSet]);
|
|
152058
|
+
const hasChanges = tagsAdd.length > 0 || tagsRemove.length > 0;
|
|
152059
|
+
const addPendingTag = () => {
|
|
152060
|
+
const next = pending.trim();
|
|
152061
|
+
if (!next) return;
|
|
152062
|
+
if (currentSet.has(next)) {
|
|
152063
|
+
setPending("");
|
|
152064
|
+
return;
|
|
152065
|
+
}
|
|
152066
|
+
setTags((prev) => [...prev, next]);
|
|
152067
|
+
setPending("");
|
|
152068
|
+
};
|
|
152069
|
+
const handleInputKeyDown = (e) => {
|
|
152070
|
+
if (e.key === "Enter") {
|
|
152071
|
+
e.preventDefault();
|
|
152072
|
+
addPendingTag();
|
|
152073
|
+
} else if (e.key === "," && pending.trim()) {
|
|
152074
|
+
e.preventDefault();
|
|
152075
|
+
addPendingTag();
|
|
152076
|
+
}
|
|
152077
|
+
};
|
|
152078
|
+
const removeTag = (tag) => {
|
|
152079
|
+
setTags((prev) => prev.filter((t) => t !== tag));
|
|
152080
|
+
};
|
|
152081
|
+
const canSave = !submitting && hasChanges && author.trim().length > 0 && !!api?.edit_log;
|
|
152082
|
+
const inFlightRef = useRef(false);
|
|
152083
|
+
const handleSave = async () => {
|
|
152084
|
+
if (!canSave || inFlightRef.current || !api?.edit_log) return;
|
|
152085
|
+
inFlightRef.current = true;
|
|
152086
|
+
const indicatorTimer = window.setTimeout(() => setSubmitting(true), 200);
|
|
152087
|
+
try {
|
|
152088
|
+
const edit = {
|
|
152089
|
+
type: "tags",
|
|
152090
|
+
tags_add: tagsAdd,
|
|
152091
|
+
tags_remove: tagsRemove
|
|
152092
|
+
};
|
|
152093
|
+
await api.edit_log(logFile, {
|
|
152094
|
+
edits: [edit],
|
|
152095
|
+
provenance: {
|
|
152096
|
+
author: author.trim(),
|
|
152097
|
+
reason: reason.trim() || void 0,
|
|
152098
|
+
metadata: {},
|
|
152099
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
152100
|
+
}
|
|
152101
|
+
});
|
|
152102
|
+
setShowing(false);
|
|
152103
|
+
onSaved?.();
|
|
152104
|
+
} catch (err) {
|
|
152105
|
+
setError(formatEditError(err));
|
|
152106
|
+
} finally {
|
|
152107
|
+
window.clearTimeout(indicatorTimer);
|
|
152108
|
+
setSubmitting(false);
|
|
152109
|
+
inFlightRef.current = false;
|
|
152110
|
+
}
|
|
152111
|
+
};
|
|
152112
|
+
return /* @__PURE__ */ jsx(Modal, {
|
|
152113
|
+
id: "edit-tags-dialog",
|
|
152114
|
+
showing,
|
|
152115
|
+
setShowing,
|
|
152116
|
+
title: "Edit tags",
|
|
152117
|
+
width: "580px",
|
|
152118
|
+
footer: /* @__PURE__ */ jsxs("div", {
|
|
152119
|
+
className: EditAnnotationsDialog_module_default.footer,
|
|
152120
|
+
children: [/* @__PURE__ */ jsx(ChangeSummary, {
|
|
152121
|
+
adding: tagsAdd,
|
|
152122
|
+
removing: tagsRemove
|
|
152123
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
152124
|
+
className: EditAnnotationsDialog_module_default.footerActions,
|
|
152125
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
152126
|
+
type: "button",
|
|
152127
|
+
className: clsx("btn", "btn-secondary", "text-size-smaller"),
|
|
152128
|
+
onClick: () => setShowing(false),
|
|
152129
|
+
disabled: submitting,
|
|
152130
|
+
children: "Cancel"
|
|
152131
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
152132
|
+
type: "button",
|
|
152133
|
+
className: clsx("btn", "btn-primary", "text-size-smaller"),
|
|
152134
|
+
onClick: handleSave,
|
|
152135
|
+
disabled: !canSave,
|
|
152136
|
+
children: submitting ? "Saving…" : "Save"
|
|
152137
|
+
})]
|
|
152138
|
+
})]
|
|
152139
|
+
}),
|
|
152140
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
152141
|
+
className: EditAnnotationsDialog_module_default.body,
|
|
152142
|
+
children: [
|
|
152143
|
+
/* @__PURE__ */ jsxs("div", {
|
|
152144
|
+
className: EditAnnotationsDialog_module_default.section,
|
|
152145
|
+
children: [
|
|
152146
|
+
/* @__PURE__ */ jsx("label", {
|
|
152147
|
+
className: clsx("text-size-smaller", EditAnnotationsDialog_module_default.label),
|
|
152148
|
+
children: "Tags"
|
|
152149
|
+
}),
|
|
152150
|
+
/* @__PURE__ */ jsxs("div", {
|
|
152151
|
+
className: EditTagsDialog_module_default.chipBox,
|
|
152152
|
+
children: [tags.length === 0 && /* @__PURE__ */ jsx("span", {
|
|
152153
|
+
className: clsx("text-size-smaller", EditTagsDialog_module_default.empty),
|
|
152154
|
+
children: "No tags yet — add one below."
|
|
152155
|
+
}), tags.map((tag) => /* @__PURE__ */ jsx(TagChip, {
|
|
152156
|
+
label: tag,
|
|
152157
|
+
isNew: !initialSet.has(tag),
|
|
152158
|
+
onRemove: () => removeTag(tag)
|
|
152159
|
+
}, tag))]
|
|
152160
|
+
}),
|
|
152161
|
+
/* @__PURE__ */ jsxs("div", {
|
|
152162
|
+
className: EditTagsDialog_module_default.addRow,
|
|
152163
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
152164
|
+
type: "text",
|
|
152165
|
+
className: clsx("form-control", "text-size-smaller", EditTagsDialog_module_default.input),
|
|
152166
|
+
placeholder: "Add a tag and press Enter",
|
|
152167
|
+
value: pending,
|
|
152168
|
+
onChange: (e) => setPending(e.target.value),
|
|
152169
|
+
onKeyDown: handleInputKeyDown,
|
|
152170
|
+
disabled: submitting,
|
|
152171
|
+
autoFocus: true
|
|
152172
|
+
}), /* @__PURE__ */ jsxs("button", {
|
|
152173
|
+
type: "button",
|
|
152174
|
+
className: clsx("btn", pending.trim() ? "btn-primary" : "btn-secondary", "text-size-smaller", EditTagsDialog_module_default.addButton),
|
|
152175
|
+
onClick: addPendingTag,
|
|
152176
|
+
disabled: submitting || !pending.trim(),
|
|
152177
|
+
children: [/* @__PURE__ */ jsx("i", { className: ApplicationIcons.changes.add }), " Add"]
|
|
152178
|
+
})]
|
|
152179
|
+
})
|
|
152180
|
+
]
|
|
152181
|
+
}),
|
|
152182
|
+
/* @__PURE__ */ jsx("hr", { className: EditAnnotationsDialog_module_default.divider }),
|
|
152183
|
+
/* @__PURE__ */ jsx(ProvenanceFields, {
|
|
152184
|
+
author,
|
|
152185
|
+
setAuthor,
|
|
152186
|
+
reason,
|
|
152187
|
+
setReason,
|
|
152188
|
+
disabled: submitting
|
|
152189
|
+
}),
|
|
152190
|
+
error && /* @__PURE__ */ jsx("div", {
|
|
152191
|
+
className: clsx("text-size-smaller", EditAnnotationsDialog_module_default.error),
|
|
152192
|
+
children: error
|
|
152193
|
+
})
|
|
152194
|
+
]
|
|
152195
|
+
})
|
|
152196
|
+
});
|
|
152197
|
+
};
|
|
152198
|
+
var TagStrip_module_default = { tagRow: "_tagRow_pg3wd_4" };
|
|
152199
|
+
//#endregion
|
|
152200
|
+
//#region src/app/log-view/title-view/TagStrip.tsx
|
|
152201
|
+
var MAX_ROWS = 2;
|
|
152202
|
+
/**
|
|
152203
|
+
* Wrap-aware chip row: tag chips followed by the Edit pill as the
|
|
152204
|
+
* last item, so when chips wrap to additional lines the Edit pill
|
|
152205
|
+
* follows the last chip onto whichever line it lands on. Layout
|
|
152206
|
+
* context (alignment, margin, shrink) is supplied by the consumer via
|
|
152207
|
+
* `className`.
|
|
152208
|
+
*
|
|
152209
|
+
* With {@link TagStripProps.collapseOnWrap} on, the strip allows up to
|
|
152210
|
+
* {@link MAX_ROWS} rows of chips; if they would spill onto a third
|
|
152211
|
+
* row, it surfaces a "…" overflow pill (with a tooltip listing the
|
|
152212
|
+
* hidden tags) before the Edit pill. Sizing is measured via
|
|
152213
|
+
* ResizeObserver — when the row widens, the strip restarts from the
|
|
152214
|
+
* full set and re-trims, so growth actually surfaces more chips. The
|
|
152215
|
+
* same restart happens on tag-set changes (so saving in the edit
|
|
152216
|
+
* dialog re-runs the layout against the new tags).
|
|
152217
|
+
*/
|
|
152218
|
+
var TagStrip = ({ tags, showEdit, onEdit, className, collapseOnWrap = false }) => {
|
|
152219
|
+
const rowRef = useRef(null);
|
|
152220
|
+
const [visibleCount, setVisibleCount] = useState(tags.length);
|
|
152221
|
+
const lastTagsRef = useRef(tags);
|
|
152222
|
+
const enableCollapse = collapseOnWrap && showEdit;
|
|
152223
|
+
if (lastTagsRef.current !== tags) {
|
|
152224
|
+
lastTagsRef.current = tags;
|
|
152225
|
+
if (visibleCount !== tags.length) setVisibleCount(tags.length);
|
|
152226
|
+
}
|
|
152227
|
+
useLayoutEffect(() => {
|
|
152228
|
+
if (!enableCollapse || !rowRef.current) return;
|
|
152229
|
+
const el = rowRef.current;
|
|
152230
|
+
const kids = Array.from(el.children);
|
|
152231
|
+
if (kids.length < 2) return;
|
|
152232
|
+
const tops = /* @__PURE__ */ new Set();
|
|
152233
|
+
for (const k of kids) tops.add(k.offsetTop);
|
|
152234
|
+
if (tops.size > MAX_ROWS && visibleCount > 0) setVisibleCount((c) => Math.max(0, c - 1));
|
|
152235
|
+
}, [
|
|
152236
|
+
enableCollapse,
|
|
152237
|
+
visibleCount,
|
|
152238
|
+
tags,
|
|
152239
|
+
showEdit
|
|
152240
|
+
]);
|
|
152241
|
+
useLayoutEffect(() => {
|
|
152242
|
+
if (!enableCollapse || !rowRef.current) return;
|
|
152243
|
+
const el = rowRef.current;
|
|
152244
|
+
let lastWidth = el.clientWidth;
|
|
152245
|
+
const ro = new ResizeObserver(() => {
|
|
152246
|
+
const w = el.clientWidth;
|
|
152247
|
+
if (Math.abs(w - lastWidth) > 1) {
|
|
152248
|
+
lastWidth = w;
|
|
152249
|
+
setVisibleCount(tags.length);
|
|
152250
|
+
}
|
|
152251
|
+
});
|
|
152252
|
+
ro.observe(el);
|
|
152253
|
+
return () => ro.disconnect();
|
|
152254
|
+
}, [enableCollapse, tags.length]);
|
|
152255
|
+
if (tags.length === 0 && !showEdit) return null;
|
|
152256
|
+
const effectiveCount = Math.min(visibleCount, tags.length);
|
|
152257
|
+
const hiddenTags = tags.slice(effectiveCount);
|
|
152258
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
152259
|
+
ref: rowRef,
|
|
152260
|
+
className: clsx(TagStrip_module_default.tagRow, className),
|
|
152261
|
+
children: [
|
|
152262
|
+
tags.slice(0, effectiveCount).map((tag) => /* @__PURE__ */ jsx(TagChip, {
|
|
152263
|
+
label: tag,
|
|
152264
|
+
onClick: showEdit ? onEdit : void 0
|
|
152265
|
+
}, tag)),
|
|
152266
|
+
hiddenTags.length > 0 && /* @__PURE__ */ jsx(OverflowPill, {
|
|
152267
|
+
hiddenTags,
|
|
152268
|
+
onClick: onEdit
|
|
152269
|
+
}),
|
|
152270
|
+
showEdit && /* @__PURE__ */ jsx(EditButton, {
|
|
152271
|
+
onClick: onEdit,
|
|
152272
|
+
title: "Edit tags",
|
|
152273
|
+
variant: "pill",
|
|
152274
|
+
children: tags.length === 0 ? "Tags" : "edit"
|
|
152275
|
+
})
|
|
152276
|
+
]
|
|
152277
|
+
});
|
|
152278
|
+
};
|
|
152279
|
+
/**
|
|
152280
|
+
* Outline pill rendered in place of overflowed chips. Matches the
|
|
152281
|
+
* Edit pill's visual via composed EditButton styles; the tooltip
|
|
152282
|
+
* reveals the hidden tag names. Clicking opens the same edit dialog
|
|
152283
|
+
* the Edit pill does, so the full list is one click away.
|
|
152284
|
+
*/
|
|
152285
|
+
var OverflowPill = ({ hiddenTags, onClick }) => {
|
|
152286
|
+
const count = hiddenTags.length;
|
|
152287
|
+
const title = `${count} more tag${count === 1 ? "" : "s"}: ${hiddenTags.join(", ")}`;
|
|
152288
|
+
return /* @__PURE__ */ jsx("button", {
|
|
152289
|
+
type: "button",
|
|
152290
|
+
className: clsx(EditButton_module_default.button, EditButton_module_default.pill, "text-size-smaller"),
|
|
152291
|
+
onClick,
|
|
152292
|
+
title,
|
|
152293
|
+
"aria-label": title,
|
|
152294
|
+
children: "…"
|
|
152295
|
+
});
|
|
152296
|
+
};
|
|
152297
|
+
//#endregion
|
|
152298
|
+
//#region src/app/log-view/title-view/TagsField.tsx
|
|
152299
|
+
/**
|
|
152300
|
+
* The full editable-tags surface: chip strip + Edit pill + dialog.
|
|
152301
|
+
*
|
|
152302
|
+
* Edit gating, target log, and post-save refresh come from
|
|
152303
|
+
* `useLogEditAffordance`; this component owns only the open/close state
|
|
152304
|
+
* for its dialog. Consumers pass the tag list and an optional className
|
|
152305
|
+
* for layout context.
|
|
152306
|
+
*/
|
|
152307
|
+
var TagsField = ({ tags, className, collapseOnWrap }) => {
|
|
152308
|
+
const { canEdit, selectedLogFile, refreshOnSave } = useLogEditAffordance();
|
|
152309
|
+
const [editingTags, setEditingTags] = useState(false);
|
|
152310
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(TagStrip, {
|
|
152311
|
+
tags,
|
|
152312
|
+
showEdit: canEdit,
|
|
152313
|
+
onEdit: () => setEditingTags(true),
|
|
152314
|
+
className,
|
|
152315
|
+
collapseOnWrap
|
|
152316
|
+
}), selectedLogFile && /* @__PURE__ */ jsx(EditTagsDialog, {
|
|
152317
|
+
showing: editingTags,
|
|
152318
|
+
setShowing: setEditingTags,
|
|
152319
|
+
currentTags: tags,
|
|
152320
|
+
logFile: selectedLogFile,
|
|
152321
|
+
onSaved: refreshOnSave
|
|
152322
|
+
})] });
|
|
152323
|
+
};
|
|
152324
|
+
var TaskTab_module_default = {
|
|
152325
|
+
grid: "_grid_q7chi_1",
|
|
152326
|
+
tagPillAlign: "_tagPillAlign_q7chi_11"
|
|
152327
|
+
};
|
|
150940
152328
|
//#endregion
|
|
150941
152329
|
//#region src/app/log-view/tabs/TaskTab.tsx
|
|
150942
152330
|
var useTaskTabConfig = (evalSpec, evalStats, earlyStopping, tags) => {
|
|
@@ -150961,6 +152349,9 @@ var useTaskTabConfig = (evalSpec, evalStats, earlyStopping, tags) => {
|
|
|
150961
152349
|
]);
|
|
150962
152350
|
};
|
|
150963
152351
|
var TaskTab = ({ evalSpec, evalStats, earlyStopping, tags }) => {
|
|
152352
|
+
const api = useApi();
|
|
152353
|
+
const canEditTags = Boolean(api.edit_log);
|
|
152354
|
+
const tagList = tags ?? [];
|
|
150964
152355
|
const config = {};
|
|
150965
152356
|
Object.entries(evalSpec?.config || {}).forEach((entry) => {
|
|
150966
152357
|
const key = entry[0];
|
|
@@ -150983,7 +152374,10 @@ var TaskTab = ({ evalSpec, evalStats, earlyStopping, tags }) => {
|
|
|
150983
152374
|
if (names.length === 1) taskInformation["Inspect"] = names[0];
|
|
150984
152375
|
else taskInformation["Inspect"] = names;
|
|
150985
152376
|
}
|
|
150986
|
-
if (
|
|
152377
|
+
if (tagList.length > 0 || canEditTags) taskInformation["tags"] = { _html: /* @__PURE__ */ jsx(TagsField, {
|
|
152378
|
+
tags: tagList,
|
|
152379
|
+
className: TaskTab_module_default.tagPillAlign
|
|
152380
|
+
}) };
|
|
150987
152381
|
if (evalSpec?.sandbox) if (Array.isArray(evalSpec?.sandbox)) {
|
|
150988
152382
|
taskInformation["sandbox"] = evalSpec.sandbox[0];
|
|
150989
152383
|
if (evalSpec.sandbox[1]) taskInformation["sandbox_config"] = evalSpec.sandbox[1];
|
|
@@ -151053,70 +152447,6 @@ var LinkButton = ({ id, text, icon, className, onClick }) => {
|
|
|
151053
152447
|
}) : void 0]
|
|
151054
152448
|
});
|
|
151055
152449
|
};
|
|
151056
|
-
var Modal_module_default = {
|
|
151057
|
-
modal: "_modal_1tj8p_1",
|
|
151058
|
-
header: "_header_1tj8p_14",
|
|
151059
|
-
modalTitle: "_modalTitle_1tj8p_18",
|
|
151060
|
-
btnClose: "_btnClose_1tj8p_22",
|
|
151061
|
-
backdrop: "_backdrop_1tj8p_28",
|
|
151062
|
-
overflowVisible: "_overflowVisible_1tj8p_40",
|
|
151063
|
-
overflowHidden: "_overflowHidden_1tj8p_44",
|
|
151064
|
-
overflowScroll: "_overflowScroll_1tj8p_48",
|
|
151065
|
-
overflowAuto: "_overflowAuto_1tj8p_52",
|
|
151066
|
-
noPadding: "_noPadding_1tj8p_56"
|
|
151067
|
-
};
|
|
151068
|
-
//#endregion
|
|
151069
|
-
//#region src/components/Modal.tsx
|
|
151070
|
-
var Modal = ({ id, title, showing, setShowing, children, className, overflow = "visible", padded = true }) => {
|
|
151071
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [showing && /* @__PURE__ */ jsx("div", {
|
|
151072
|
-
className: Modal_module_default.backdrop,
|
|
151073
|
-
onClick: () => setShowing(false)
|
|
151074
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
151075
|
-
id,
|
|
151076
|
-
className: clsx("modal", "fade", showing ? "show" : "", className),
|
|
151077
|
-
tabIndex: -1,
|
|
151078
|
-
style: { display: showing ? "block" : "none" },
|
|
151079
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
151080
|
-
className: clsx("modal-dialog", Modal_module_default.modal),
|
|
151081
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
151082
|
-
className: "modal-content",
|
|
151083
|
-
children: [
|
|
151084
|
-
/* @__PURE__ */ jsxs("div", {
|
|
151085
|
-
className: clsx("modal-header", Modal_module_default.header),
|
|
151086
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
151087
|
-
className: clsx("modal-title", "text-size-base", Modal_module_default.modalTitle),
|
|
151088
|
-
children: title
|
|
151089
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
151090
|
-
type: "button",
|
|
151091
|
-
className: clsx("btn-close", "text-size-smaller", Modal_module_default.btnClose),
|
|
151092
|
-
"data-bs-dismiss": "modal",
|
|
151093
|
-
"aria-label": "Close",
|
|
151094
|
-
onClick: () => {
|
|
151095
|
-
setShowing(!showing);
|
|
151096
|
-
}
|
|
151097
|
-
})]
|
|
151098
|
-
}),
|
|
151099
|
-
/* @__PURE__ */ jsx("div", {
|
|
151100
|
-
className: clsx("modal-body", !padded && Modal_module_default.noPadding, overflow === "auto" ? Modal_module_default.overflowAuto : overflow === "hidden" ? Modal_module_default.overflowHidden : overflow === "scroll" ? Modal_module_default.overflowScroll : Modal_module_default.overflowVisible),
|
|
151101
|
-
children
|
|
151102
|
-
}),
|
|
151103
|
-
/* @__PURE__ */ jsx("div", {
|
|
151104
|
-
className: "modal-footer",
|
|
151105
|
-
children: /* @__PURE__ */ jsx("button", {
|
|
151106
|
-
type: "button",
|
|
151107
|
-
className: "btn btn-secondary",
|
|
151108
|
-
"data-bs-dismiss": "modal",
|
|
151109
|
-
onClick: () => {
|
|
151110
|
-
setShowing(!showing);
|
|
151111
|
-
},
|
|
151112
|
-
children: "Close"
|
|
151113
|
-
})
|
|
151114
|
-
})
|
|
151115
|
-
]
|
|
151116
|
-
})
|
|
151117
|
-
})
|
|
151118
|
-
})] });
|
|
151119
|
-
};
|
|
151120
152450
|
//#endregion
|
|
151121
152451
|
//#region src/scoring/metrics.ts
|
|
151122
152452
|
var metricDisplayName = (metric) => {
|
|
@@ -151759,16 +153089,17 @@ var ModelRolesView = ({ roles }) => {
|
|
|
151759
153089
|
}) : void 0;
|
|
151760
153090
|
};
|
|
151761
153091
|
var PrimaryBar_module_default = {
|
|
151762
|
-
container: "
|
|
151763
|
-
wrapper: "
|
|
151764
|
-
toggle: "
|
|
151765
|
-
body: "
|
|
151766
|
-
bodyContainer: "
|
|
151767
|
-
|
|
151768
|
-
|
|
151769
|
-
|
|
151770
|
-
|
|
151771
|
-
|
|
153092
|
+
container: "_container_1x0td_1",
|
|
153093
|
+
wrapper: "_wrapper_1x0td_15",
|
|
153094
|
+
toggle: "_toggle_1x0td_21",
|
|
153095
|
+
body: "_body_1x0td_28",
|
|
153096
|
+
bodyContainer: "_bodyContainer_1x0td_40",
|
|
153097
|
+
tagRowHeader: "_tagRowHeader_1x0td_61",
|
|
153098
|
+
taskTitle: "_taskTitle_1x0td_66",
|
|
153099
|
+
taskModel: "_taskModel_1x0td_73",
|
|
153100
|
+
taskStatus: "_taskStatus_1x0td_77",
|
|
153101
|
+
secondaryContainer: "_secondaryContainer_1x0td_84",
|
|
153102
|
+
buttonGroup: "_buttonGroup_1x0td_93"
|
|
151772
153103
|
};
|
|
151773
153104
|
var RunningStatusPanel_module_default = {
|
|
151774
153105
|
statusContainer: "_statusContainer_1sckj_1",
|
|
@@ -151833,7 +153164,7 @@ var StatusPanel = ({ icon, status, sampleCount }) => {
|
|
|
151833
153164
|
};
|
|
151834
153165
|
//#endregion
|
|
151835
153166
|
//#region src/app/log-view/title-view/PrimaryBar.tsx
|
|
151836
|
-
var PrimaryBar = ({ status, evalResults, runningMetrics, evalSpec, sampleCount }) => {
|
|
153167
|
+
var PrimaryBar = ({ status, evalResults, runningMetrics, evalSpec, sampleCount, tags }) => {
|
|
151837
153168
|
const streamSamples = useStore((state) => state.capabilities.streamSamples);
|
|
151838
153169
|
const downloadLogs = useStore((state) => state.capabilities.downloadLogs);
|
|
151839
153170
|
const absLogDir = useStore((state) => state.logs.absLogDir);
|
|
@@ -151841,6 +153172,7 @@ var PrimaryBar = ({ status, evalResults, runningMetrics, evalSpec, sampleCount }
|
|
|
151841
153172
|
const logDir = useStore((state) => state.logs.logDir);
|
|
151842
153173
|
const logFileName = selectedLogFile ? filename(selectedLogFile) : "";
|
|
151843
153174
|
const isEvalFile = selectedLogFile?.endsWith(".eval");
|
|
153175
|
+
const tagList = tags ?? [];
|
|
151844
153176
|
const copyValue = (() => {
|
|
151845
153177
|
if (!absLogDir || !selectedLogFile || !logDir) return selectedLogFile;
|
|
151846
153178
|
const prefix = logDir + "/";
|
|
@@ -151858,17 +153190,25 @@ var PrimaryBar = ({ status, evalResults, runningMetrics, evalSpec, sampleCount }
|
|
|
151858
153190
|
children: [
|
|
151859
153191
|
/* @__PURE__ */ jsxs("div", {
|
|
151860
153192
|
className: PrimaryBar_module_default.bodyContainer,
|
|
151861
|
-
children: [
|
|
151862
|
-
|
|
151863
|
-
|
|
151864
|
-
|
|
151865
|
-
|
|
151866
|
-
|
|
151867
|
-
|
|
151868
|
-
|
|
151869
|
-
|
|
151870
|
-
|
|
151871
|
-
|
|
153193
|
+
children: [
|
|
153194
|
+
/* @__PURE__ */ jsx("div", {
|
|
153195
|
+
id: "task-title",
|
|
153196
|
+
className: clsx("task-title", PrimaryBar_module_default.taskTitle),
|
|
153197
|
+
title: evalSpec?.task,
|
|
153198
|
+
children: evalSpec?.task
|
|
153199
|
+
}),
|
|
153200
|
+
evalSpec?.model && evalSpec.model !== "none/none" ? /* @__PURE__ */ jsx("div", {
|
|
153201
|
+
id: "task-model",
|
|
153202
|
+
className: clsx("task-model", "text-truncate", PrimaryBar_module_default.taskModel, "text-size-base"),
|
|
153203
|
+
title: evalSpec?.model,
|
|
153204
|
+
children: evalSpec?.model
|
|
153205
|
+
}) : "",
|
|
153206
|
+
/* @__PURE__ */ jsx(TagsField, {
|
|
153207
|
+
tags: tagList,
|
|
153208
|
+
className: PrimaryBar_module_default.tagRowHeader,
|
|
153209
|
+
collapseOnWrap: true
|
|
153210
|
+
})
|
|
153211
|
+
]
|
|
151872
153212
|
}),
|
|
151873
153213
|
evalSpec?.model_roles ? /* @__PURE__ */ jsx(ModelRolesView, { roles: evalSpec.model_roles }) : void 0,
|
|
151874
153214
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -152074,7 +153414,7 @@ var TitleView_module_default = {
|
|
|
152074
153414
|
/**
|
|
152075
153415
|
* Renders the Navbar
|
|
152076
153416
|
*/
|
|
152077
|
-
var TitleView = ({ evalSpec, evalPlan, evalResults, evalStats, status, runningMetrics, collapsed }) => {
|
|
153417
|
+
var TitleView = ({ evalSpec, evalPlan, evalResults, evalStats, status, runningMetrics, tags, collapsed }) => {
|
|
152078
153418
|
const totalSampleCount = useTotalSampleCount();
|
|
152079
153419
|
return /* @__PURE__ */ jsxs("nav", {
|
|
152080
153420
|
className: clsx("navbar", "sticky-top", TitleView_module_default.navbarWrapper, collapsed ? TitleView_module_default.collapsed : TitleView_module_default.expanded),
|
|
@@ -152088,7 +153428,8 @@ var TitleView = ({ evalSpec, evalPlan, evalResults, evalStats, status, runningMe
|
|
|
152088
153428
|
evalResults,
|
|
152089
153429
|
status,
|
|
152090
153430
|
runningMetrics,
|
|
152091
|
-
sampleCount: totalSampleCount
|
|
153431
|
+
sampleCount: totalSampleCount,
|
|
153432
|
+
tags
|
|
152092
153433
|
}), /* @__PURE__ */ jsx(SecondaryBar, {
|
|
152093
153434
|
evalSpec,
|
|
152094
153435
|
evalPlan,
|
|
@@ -152168,6 +153509,7 @@ var LogView = () => {
|
|
|
152168
153509
|
runningMetrics,
|
|
152169
153510
|
evalStats: selectedLogDetails?.stats,
|
|
152170
153511
|
status: selectedLogDetails?.status,
|
|
153512
|
+
tags: selectedLogDetails?.tags,
|
|
152171
153513
|
collapsed: titleCollapsed
|
|
152172
153514
|
}), /* @__PURE__ */ jsx("div", {
|
|
152173
153515
|
ref: divRef,
|
|
@@ -152759,7 +154101,7 @@ var SamplesPanel = () => {
|
|
|
152759
154101
|
const logDetails = useStore((state) => state.logs.logDetails);
|
|
152760
154102
|
const { startPolling, stopPolling } = useClientEvents();
|
|
152761
154103
|
useEffect(() => {
|
|
152762
|
-
startPolling(
|
|
154104
|
+
startPolling();
|
|
152763
154105
|
return () => {
|
|
152764
154106
|
stopPolling();
|
|
152765
154107
|
};
|
|
@@ -152853,12 +154195,19 @@ var SamplesPanel = () => {
|
|
|
152853
154195
|
return v;
|
|
152854
154196
|
}, [allColumns, columnVisibility]);
|
|
152855
154197
|
const initialState = useMemo(() => {
|
|
152856
|
-
|
|
154198
|
+
const base = previousSamplesPath !== void 0 && previousSamplesPath !== samplesPath ? (() => {
|
|
152857
154199
|
const result = { ...gridState };
|
|
152858
154200
|
delete result?.filter;
|
|
152859
154201
|
return result;
|
|
152860
|
-
}
|
|
152861
|
-
return
|
|
154202
|
+
})() : gridState;
|
|
154203
|
+
if (!base?.sort?.sortModel?.length) return {
|
|
154204
|
+
...base,
|
|
154205
|
+
sort: { sortModel: [{
|
|
154206
|
+
colId: "completed_at",
|
|
154207
|
+
sort: "desc"
|
|
154208
|
+
}] }
|
|
154209
|
+
};
|
|
154210
|
+
return base;
|
|
152862
154211
|
}, [
|
|
152863
154212
|
previousSamplesPath,
|
|
152864
154213
|
samplesPath,
|
|
@@ -152901,7 +154250,7 @@ var SamplesPanel = () => {
|
|
|
152901
154250
|
error: sample.error,
|
|
152902
154251
|
limit: sample.limit,
|
|
152903
154252
|
retries: sample.retries,
|
|
152904
|
-
completed: sample.completed
|
|
154253
|
+
completed: sample.completed,
|
|
152905
154254
|
tokens,
|
|
152906
154255
|
duration: sample.total_time ?? void 0
|
|
152907
154256
|
};
|
|
@@ -153337,203 +154686,6 @@ function clearLargeEventsArray(data) {
|
|
|
153337
154686
|
return result;
|
|
153338
154687
|
}
|
|
153339
154688
|
//#endregion
|
|
153340
|
-
//#region src/utils/json-worker.ts
|
|
153341
|
-
var JsonWorkerPool = class {
|
|
153342
|
-
encoder = new TextEncoder();
|
|
153343
|
-
decoder = new TextDecoder();
|
|
153344
|
-
workers = [];
|
|
153345
|
-
blobURL = null;
|
|
153346
|
-
nextRequestId = 0;
|
|
153347
|
-
pendingRequests = /* @__PURE__ */ new Map();
|
|
153348
|
-
poolSize = 4;
|
|
153349
|
-
ensureWorkers() {
|
|
153350
|
-
if (this.workers.length === 0) {
|
|
153351
|
-
const blob = new Blob([kWorkerCode], { type: "application/javascript" });
|
|
153352
|
-
this.blobURL = URL.createObjectURL(blob);
|
|
153353
|
-
for (let i = 0; i < this.poolSize; i++) {
|
|
153354
|
-
const worker = new Worker(this.blobURL);
|
|
153355
|
-
worker.onmessage = (e) => this.handleMessage(e);
|
|
153356
|
-
worker.onerror = (error) => this.handleError(error);
|
|
153357
|
-
this.workers.push(worker);
|
|
153358
|
-
worker.postMessage({
|
|
153359
|
-
type: "init",
|
|
153360
|
-
scriptContent: kJson5ScriptBase64
|
|
153361
|
-
});
|
|
153362
|
-
}
|
|
153363
|
-
}
|
|
153364
|
-
}
|
|
153365
|
-
handleMessage(e) {
|
|
153366
|
-
const { requestId, success, serialized, result, error, stack } = e.data;
|
|
153367
|
-
const pending = this.pendingRequests.get(requestId);
|
|
153368
|
-
if (!pending) return;
|
|
153369
|
-
this.pendingRequests.delete(requestId);
|
|
153370
|
-
if (success) if (serialized) {
|
|
153371
|
-
const resultString = this.decoder.decode(result);
|
|
153372
|
-
pending.resolve(JSON.parse(resultString));
|
|
153373
|
-
} else pending.resolve(result);
|
|
153374
|
-
else {
|
|
153375
|
-
const err = new Error(error);
|
|
153376
|
-
if (stack) err.stack = stack;
|
|
153377
|
-
pending.reject(err);
|
|
153378
|
-
}
|
|
153379
|
-
}
|
|
153380
|
-
handleError(error) {
|
|
153381
|
-
const err = /* @__PURE__ */ new Error(`Worker error: ${error.message}`);
|
|
153382
|
-
for (const pending of this.pendingRequests.values()) pending.reject(err);
|
|
153383
|
-
this.pendingRequests.clear();
|
|
153384
|
-
}
|
|
153385
|
-
async parse(text) {
|
|
153386
|
-
this.ensureWorkers();
|
|
153387
|
-
const encodedText = this.encoder.encode(text);
|
|
153388
|
-
const requestId = this.nextRequestId++;
|
|
153389
|
-
return new Promise((resolve, reject) => {
|
|
153390
|
-
this.pendingRequests.set(requestId, {
|
|
153391
|
-
resolve,
|
|
153392
|
-
reject
|
|
153393
|
-
});
|
|
153394
|
-
this.workers[requestId % this.workers.length]?.postMessage({
|
|
153395
|
-
type: "parse",
|
|
153396
|
-
requestId,
|
|
153397
|
-
encodedText
|
|
153398
|
-
}, [encodedText.buffer]);
|
|
153399
|
-
});
|
|
153400
|
-
}
|
|
153401
|
-
async parseBytes(data) {
|
|
153402
|
-
this.ensureWorkers();
|
|
153403
|
-
const requestId = this.nextRequestId++;
|
|
153404
|
-
const ownedData = data.byteOffset === 0 && data.byteLength === data.buffer.byteLength ? data : data.slice();
|
|
153405
|
-
return new Promise((resolve, reject) => {
|
|
153406
|
-
this.pendingRequests.set(requestId, {
|
|
153407
|
-
resolve,
|
|
153408
|
-
reject
|
|
153409
|
-
});
|
|
153410
|
-
this.workers[requestId % this.workers.length]?.postMessage({
|
|
153411
|
-
type: "parse",
|
|
153412
|
-
requestId,
|
|
153413
|
-
encodedText: ownedData
|
|
153414
|
-
}, [ownedData.buffer]);
|
|
153415
|
-
});
|
|
153416
|
-
}
|
|
153417
|
-
terminate() {
|
|
153418
|
-
this.workers.forEach((w) => w.terminate());
|
|
153419
|
-
this.workers = [];
|
|
153420
|
-
if (this.blobURL) {
|
|
153421
|
-
URL.revokeObjectURL(this.blobURL);
|
|
153422
|
-
this.blobURL = null;
|
|
153423
|
-
}
|
|
153424
|
-
this.pendingRequests.clear();
|
|
153425
|
-
}
|
|
153426
|
-
};
|
|
153427
|
-
var workerPool = new JsonWorkerPool();
|
|
153428
|
-
var asyncJsonParse = async (text) => {
|
|
153429
|
-
if (text.length < 5e4) {
|
|
153430
|
-
let result = void 0;
|
|
153431
|
-
try {
|
|
153432
|
-
result = JSON.parse(text);
|
|
153433
|
-
} catch {
|
|
153434
|
-
result = import_dist.default.parse(text);
|
|
153435
|
-
}
|
|
153436
|
-
return Promise.resolve(result);
|
|
153437
|
-
} else return workerPool.parse(text);
|
|
153438
|
-
};
|
|
153439
|
-
/**
|
|
153440
|
-
* Parse JSON from raw UTF-8 bytes, avoiding redundant main-thread
|
|
153441
|
-
* string allocation for large payloads.
|
|
153442
|
-
*
|
|
153443
|
-
* For small data (<50KB) decodes and parses on the main thread.
|
|
153444
|
-
* For large data, transfers the bytes directly to a Web Worker,
|
|
153445
|
-
* skipping the main-thread TextDecoder.decode + TextEncoder.encode
|
|
153446
|
-
* round-trip that asyncJsonParse(string) would require.
|
|
153447
|
-
*/
|
|
153448
|
-
var asyncJsonParseBytes = async (data) => {
|
|
153449
|
-
if (data.length < 5e4) return jsonParse(new TextDecoder("utf-8").decode(data));
|
|
153450
|
-
else return workerPool.parseBytes(data);
|
|
153451
|
-
};
|
|
153452
|
-
var jsonParse = (text) => {
|
|
153453
|
-
try {
|
|
153454
|
-
return JSON.parse(text);
|
|
153455
|
-
} catch {
|
|
153456
|
-
return import_dist.default.parse(text);
|
|
153457
|
-
}
|
|
153458
|
-
};
|
|
153459
|
-
var kWorkerCode = `
|
|
153460
|
-
// Store the JSON5 parser once loaded
|
|
153461
|
-
let JSON5 = null;
|
|
153462
|
-
const decoder = new TextDecoder();
|
|
153463
|
-
const encoder = new TextEncoder();
|
|
153464
|
-
|
|
153465
|
-
self.onmessage = function (e) {
|
|
153466
|
-
const { type } = e.data || {};
|
|
153467
|
-
|
|
153468
|
-
if (type === 'init') {
|
|
153469
|
-
const { scriptContent } = e.data;
|
|
153470
|
-
try {
|
|
153471
|
-
if (!JSON5) {
|
|
153472
|
-
const script = atob(scriptContent);
|
|
153473
|
-
new Function(script)();
|
|
153474
|
-
if (typeof self.JSON5 !== 'object' || typeof self.JSON5.parse !== 'function') {
|
|
153475
|
-
throw new Error('Failed to initialize JSON5 parser');
|
|
153476
|
-
}
|
|
153477
|
-
JSON5 = self.JSON5;
|
|
153478
|
-
}
|
|
153479
|
-
} catch (err) {
|
|
153480
|
-
// nothing to respond to yet; worker will fail on first parse if init failed
|
|
153481
|
-
console.error('JSON5 init error in worker', err);
|
|
153482
|
-
}
|
|
153483
|
-
return;
|
|
153484
|
-
}
|
|
153485
|
-
|
|
153486
|
-
if (type === 'parse') {
|
|
153487
|
-
const { requestId, encodedText, scriptContent } = e.data;
|
|
153488
|
-
|
|
153489
|
-
try {
|
|
153490
|
-
|
|
153491
|
-
// Decode the text using TextDecoder
|
|
153492
|
-
const text = decoder.decode(encodedText);
|
|
153493
|
-
|
|
153494
|
-
// Parse with JSON/JSON5
|
|
153495
|
-
let result = undefined;
|
|
153496
|
-
try {
|
|
153497
|
-
// Optimistically, try a regular JSON parse first (this is much faster)
|
|
153498
|
-
result = JSON.parse(text);
|
|
153499
|
-
} catch {
|
|
153500
|
-
result = JSON5.parse(text);
|
|
153501
|
-
}
|
|
153502
|
-
|
|
153503
|
-
if (result && typeof result === 'object' &&
|
|
153504
|
-
(Array.isArray(result) ? result.length > 10000 : Object.keys(result).length > 10000)) {
|
|
153505
|
-
|
|
153506
|
-
// Large result, use transferrable object
|
|
153507
|
-
const resultString = JSON.stringify(result);
|
|
153508
|
-
const serialized = encoder.encode(resultString);
|
|
153509
|
-
|
|
153510
|
-
postMessage({
|
|
153511
|
-
requestId,
|
|
153512
|
-
success: true,
|
|
153513
|
-
serialized: true,
|
|
153514
|
-
result: serialized
|
|
153515
|
-
}, [serialized.buffer]);
|
|
153516
|
-
} else {
|
|
153517
|
-
// Small results, send directly
|
|
153518
|
-
postMessage({
|
|
153519
|
-
requestId,
|
|
153520
|
-
success: true,
|
|
153521
|
-
serialized: false,
|
|
153522
|
-
result: result
|
|
153523
|
-
});
|
|
153524
|
-
}
|
|
153525
|
-
} catch (err) {
|
|
153526
|
-
postMessage({
|
|
153527
|
-
requestId,
|
|
153528
|
-
success: false,
|
|
153529
|
-
error: err.message,
|
|
153530
|
-
stack: err.stack || ''
|
|
153531
|
-
});
|
|
153532
|
-
}
|
|
153533
|
-
}
|
|
153534
|
-
};`;
|
|
153535
|
-
var kJson5ScriptBase64 = `IWZ1bmN0aW9uKHUsRCl7Im9iamVjdCI9PXR5cGVvZiBleHBvcnRzJiYidW5kZWZpbmVkIiE9dHlwZW9mIG1vZHVsZT9tb2R1bGUuZXhwb3J0cz1EKCk6ImZ1bmN0aW9uIj09dHlwZW9mIGRlZmluZSYmZGVmaW5lLmFtZD9kZWZpbmUoRCk6dS5KU09ONT1EKCl9KHRoaXMsZnVuY3Rpb24oKXsidXNlIHN0cmljdCI7ZnVuY3Rpb24gdSh1LEQpe3JldHVybiB1KEQ9e2V4cG9ydHM6e319LEQuZXhwb3J0cyksRC5leHBvcnRzfXZhciBEPXUoZnVuY3Rpb24odSl7dmFyIEQ9dS5leHBvcnRzPSJ1bmRlZmluZWQiIT10eXBlb2Ygd2luZG93JiZ3aW5kb3cuTWF0aD09TWF0aD93aW5kb3c6InVuZGVmaW5lZCIhPXR5cGVvZiBzZWxmJiZzZWxmLk1hdGg9PU1hdGg/c2VsZjpGdW5jdGlvbigicmV0dXJuIHRoaXMiKSgpOyJudW1iZXIiPT10eXBlb2YgX19nJiYoX19nPUQpfSksZT11KGZ1bmN0aW9uKHUpe3ZhciBEPXUuZXhwb3J0cz17dmVyc2lvbjoiMi42LjUifTsibnVtYmVyIj09dHlwZW9mIF9fZSYmKF9fZT1EKX0pLHI9KGUudmVyc2lvbixmdW5jdGlvbih1KXtyZXR1cm4ib2JqZWN0Ij09dHlwZW9mIHU/bnVsbCE9PXU6ImZ1bmN0aW9uIj09dHlwZW9mIHV9KSx0PWZ1bmN0aW9uKHUpe2lmKCFyKHUpKXRocm93IFR5cGVFcnJvcih1KyIgaXMgbm90IGFuIG9iamVjdCEiKTtyZXR1cm4gdX0sbj1mdW5jdGlvbih1KXt0cnl7cmV0dXJuISF1KCl9Y2F0Y2godSl7cmV0dXJuITB9fSxGPSFuKGZ1bmN0aW9uKCl7cmV0dXJuIDchPU9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwiYSIse2dldDpmdW5jdGlvbigpe3JldHVybiA3fX0pLmF9KSxDPUQuZG9jdW1lbnQsQT1yKEMpJiZyKEMuY3JlYXRlRWxlbWVudCksaT0hRiYmIW4oZnVuY3Rpb24oKXtyZXR1cm4gNyE9T2JqZWN0LmRlZmluZVByb3BlcnR5KCh1PSJkaXYiLEE/Qy5jcmVhdGVFbGVtZW50KHUpOnt9KSwiYSIse2dldDpmdW5jdGlvbigpe3JldHVybiA3fX0pLmE7dmFyIHV9KSxFPU9iamVjdC5kZWZpbmVQcm9wZXJ0eSxvPXtmOkY/T2JqZWN0LmRlZmluZVByb3BlcnR5OmZ1bmN0aW9uKHUsRCxlKXtpZih0KHUpLEQ9ZnVuY3Rpb24odSxEKXtpZighcih1KSlyZXR1cm4gdTt2YXIgZSx0O2lmKEQmJiJmdW5jdGlvbiI9PXR5cGVvZihlPXUudG9TdHJpbmcpJiYhcih0PWUuY2FsbCh1KSkpcmV0dXJuIHQ7aWYoImZ1bmN0aW9uIj09dHlwZW9mKGU9dS52YWx1ZU9mKSYmIXIodD1lLmNhbGwodSkpKXJldHVybiB0O2lmKCFEJiYiZnVuY3Rpb24iPT10eXBlb2YoZT11LnRvU3RyaW5nKSYmIXIodD1lLmNhbGwodSkpKXJldHVybiB0O3Rocm93IFR5cGVFcnJvcigiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlIil9KEQsITApLHQoZSksaSl0cnl7cmV0dXJuIEUodSxELGUpfWNhdGNoKHUpe31pZigiZ2V0ImluIGV8fCJzZXQiaW4gZSl0aHJvdyBUeXBlRXJyb3IoIkFjY2Vzc29ycyBub3Qgc3VwcG9ydGVkISIpO3JldHVybiJ2YWx1ZSJpbiBlJiYodVtEXT1lLnZhbHVlKSx1fX0sYT1GP2Z1bmN0aW9uKHUsRCxlKXtyZXR1cm4gby5mKHUsRCxmdW5jdGlvbih1LEQpe3JldHVybntlbnVtZXJhYmxlOiEoMSZ1KSxjb25maWd1cmFibGU6ISgyJnUpLHdyaXRhYmxlOiEoNCZ1KSx2YWx1ZTpEfX0oMSxlKSl9OmZ1bmN0aW9uKHUsRCxlKXtyZXR1cm4gdVtEXT1lLHV9LGM9e30uaGFzT3duUHJvcGVydHksQj1mdW5jdGlvbih1LEQpe3JldHVybiBjLmNhbGwodSxEKX0scz0wLGY9TWF0aC5yYW5kb20oKSxsPXUoZnVuY3Rpb24odSl7dmFyIHI9RFsiX19jb3JlLWpzX3NoYXJlZF9fIl18fChEWyJfX2NvcmUtanNfc2hhcmVkX18iXT17fSk7KHUuZXhwb3J0cz1mdW5jdGlvbih1LEQpe3JldHVybiByW3VdfHwoclt1XT12b2lkIDAhPT1EP0Q6e30pfSkoInZlcnNpb25zIixbXSkucHVzaCh7dmVyc2lvbjplLnZlcnNpb24sbW9kZToiZ2xvYmFsIixjb3B5cmlnaHQ6IsKpIDIwMTkgRGVuaXMgUHVzaGthcmV2ICh6bG9pcm9jay5ydSkifSl9KSgibmF0aXZlLWZ1bmN0aW9uLXRvLXN0cmluZyIsRnVuY3Rpb24udG9TdHJpbmcpLGQ9dShmdW5jdGlvbih1KXt2YXIgcix0PSJTeW1ib2woIi5jb25jYXQodm9pZCAwPT09KHI9InNyYyIpPyIiOnIsIilfIiwoKytzK2YpLnRvU3RyaW5nKDM2KSksbj0oIiIrbCkuc3BsaXQoInRvU3RyaW5nIik7ZS5pbnNwZWN0U291cmNlPWZ1bmN0aW9uKHUpe3JldHVybiBsLmNhbGwodSl9LCh1LmV4cG9ydHM9ZnVuY3Rpb24odSxlLHIsRil7dmFyIEM9ImZ1bmN0aW9uIj09dHlwZW9mIHI7QyYmKEIociwibmFtZSIpfHxhKHIsIm5hbWUiLGUpKSx1W2VdIT09ciYmKEMmJihCKHIsdCl8fGEocix0LHVbZV0/IiIrdVtlXTpuLmpvaW4oU3RyaW5nKGUpKSkpLHU9PT1EP3VbZV09cjpGP3VbZV0/dVtlXT1yOmEodSxlLHIpOihkZWxldGUgdVtlXSxhKHUsZSxyKSkpfSkoRnVuY3Rpb24ucHJvdG90eXBlLCJ0b1N0cmluZyIsZnVuY3Rpb24oKXtyZXR1cm4iZnVuY3Rpb24iPT10eXBlb2YgdGhpcyYmdGhpc1t0XXx8bC5jYWxsKHRoaXMpfSl9KSx2PWZ1bmN0aW9uKHUsRCxlKXtpZihmdW5jdGlvbih1KXtpZigiZnVuY3Rpb24iIT10eXBlb2YgdSl0aHJvdyBUeXBlRXJyb3IodSsiIGlzIG5vdCBhIGZ1bmN0aW9uISIpfSh1KSx2b2lkIDA9PT1EKXJldHVybiB1O3N3aXRjaChlKXtjYXNlIDE6cmV0dXJuIGZ1bmN0aW9uKGUpe3JldHVybiB1LmNhbGwoRCxlKX07Y2FzZSAyOnJldHVybiBmdW5jdGlvbihlLHIpe3JldHVybiB1LmNhbGwoRCxlLHIpfTtjYXNlIDM6cmV0dXJuIGZ1bmN0aW9uKGUscix0KXtyZXR1cm4gdS5jYWxsKEQsZSxyLHQpfX1yZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdS5hcHBseShELGFyZ3VtZW50cyl9fSxwPWZ1bmN0aW9uKHUscix0KXt2YXIgbixGLEMsQSxpPXUmcC5GLEU9dSZwLkcsbz11JnAuUyxjPXUmcC5QLEI9dSZwLkIscz1FP0Q6bz9EW3JdfHwoRFtyXT17fSk6KERbcl18fHt9KS5wcm90b3R5cGUsZj1FP2U6ZVtyXXx8KGVbcl09e30pLGw9Zi5wcm90b3R5cGV8fChmLnByb3RvdHlwZT17fSk7Zm9yKG4gaW4gRSYmKHQ9ciksdClDPSgoRj0haSYmcyYmdm9pZCAwIT09c1tuXSk/czp0KVtuXSxBPUImJkY/dihDLEQpOmMmJiJmdW5jdGlvbiI9PXR5cGVvZiBDP3YoRnVuY3Rpb24uY2FsbCxDKTpDLHMmJmQocyxuLEMsdSZwLlUpLGZbbl0hPUMmJmEoZixuLEEpLGMmJmxbbl0hPUMmJihsW25dPUMpfTtELmNvcmU9ZSxwLkY9MSxwLkc9MixwLlM9NCxwLlA9OCxwLkI9MTYscC5XPTMyLHAuVT02NCxwLlI9MTI4O3ZhciBoLG09cCxnPU1hdGguY2VpbCx5PU1hdGguZmxvb3Isdz1mdW5jdGlvbih1KXtyZXR1cm4gaXNOYU4odT0rdSk/MDoodT4wP3k6ZykodSl9LGI9KGg9ITEsZnVuY3Rpb24odSxEKXt2YXIgZSxyLHQ9U3RyaW5nKGZ1bmN0aW9uKHUpe2lmKG51bGw9PXUpdGhyb3cgVHlwZUVycm9yKCJDYW4ndCBjYWxsIG1ldGhvZCBvbiAgIit1KTtyZXR1cm4gdX0odSkpLG49dyhEKSxGPXQubGVuZ3RoO3JldHVybiBuPDB8fG4+PUY/aD8iIjp2b2lkIDA6KGU9dC5jaGFyQ29kZUF0KG4pKTw1NTI5Nnx8ZT41NjMxOXx8bisxPT09Rnx8KHI9dC5jaGFyQ29kZUF0KG4rMSkpPDU2MzIwfHxyPjU3MzQzP2g/dC5jaGFyQXQobik6ZTpoP3Quc2xpY2UobixuKzIpOnItNTYzMjArKGUtNTUyOTY8PDEwKSs2NTUzNn0pO20obS5QLCJTdHJpbmciLHtjb2RlUG9pbnRBdDpmdW5jdGlvbih1KXtyZXR1cm4gYih0aGlzLHUpfX0pO2UuU3RyaW5nLmNvZGVQb2ludEF0O3ZhciBTPU1hdGgubWF4LHg9TWF0aC5taW4sTj1TdHJpbmcuZnJvbUNoYXJDb2RlLFA9U3RyaW5nLmZyb21Db2RlUG9pbnQ7bShtLlMrbS5GKighIVAmJjEhPVAubGVuZ3RoKSwiU3RyaW5nIix7ZnJvbUNvZGVQb2ludDpmdW5jdGlvbih1KXtmb3IodmFyIEQsZSxyLHQ9YXJndW1lbnRzLG49W10sRj1hcmd1bWVudHMubGVuZ3RoLEM9MDtGPkM7KXtpZihEPSt0W0MrK10scj0xMTE0MTExLCgoZT13KGU9RCkpPDA/UyhlK3IsMCk6eChlLHIpKSE9PUQpdGhyb3cgUmFuZ2VFcnJvcihEKyIgaXMgbm90IGEgdmFsaWQgY29kZSBwb2ludCIpO24ucHVzaChEPDY1NTM2P04oRCk6Tig1NTI5NisoKEQtPTY1NTM2KT4+MTApLEQlMTAyNCs1NjMyMCkpfXJldHVybiBuLmpvaW4oIiIpfX0pO2UuU3RyaW5nLmZyb21Db2RlUG9pbnQ7dmFyIF8sTyxqLEksVixKLE0sayxMLFQseixILCQsUixHPXtTcGFjZV9TZXBhcmF0b3I6L1tcdTE2ODBcdTIwMDAtXHUyMDBBXHUyMDJGXHUyMDVGXHUzMDAwXS8sSURfU3RhcnQ6L1tceEFBXHhCNVx4QkFceEMwLVx4RDZceEQ4LVx4RjZceEY4LVx1MDJDMVx1MDJDNi1cdTAyRDFcdTAyRTAtXHUwMkU0XHUwMkVDXHUwMkVFXHUwMzcwLVx1MDM3NFx1MDM3Nlx1MDM3N1x1MDM3QS1cdTAzN0RcdTAzN0ZcdTAzODZcdTAzODgtXHUwMzhBXHUwMzhDXHUwMzhFLVx1MDNBMVx1MDNBMy1cdTAzRjVcdTAzRjctXHUwNDgxXHUwNDhBLVx1MDUyRlx1MDUzMS1cdTA1NTZcdTA1NTlcdTA1NjEtXHUwNTg3XHUwNUQwLVx1MDVFQVx1MDVGMC1cdTA1RjJcdTA2MjAtXHUwNjRBXHUwNjZFXHUwNjZGXHUwNjcxLVx1MDZEM1x1MDZENVx1MDZFNVx1MDZFNlx1MDZFRVx1MDZFRlx1MDZGQS1cdTA2RkNcdTA2RkZcdTA3MTBcdTA3MTItXHUwNzJGXHUwNzRELVx1MDdBNVx1MDdCMVx1MDdDQS1cdTA3RUFcdTA3RjRcdTA3RjVcdTA3RkFcdTA4MDAtXHUwODE1XHUwODFBXHUwODI0XHUwODI4XHUwODQwLVx1MDg1OFx1MDg2MC1cdTA4NkFcdTA4QTAtXHUwOEI0XHUwOEI2LVx1MDhCRFx1MDkwNC1cdTA5MzlcdTA5M0RcdTA5NTBcdTA5NTgtXHUwOTYxXHUwOTcxLVx1MDk4MFx1MDk4NS1cdTA5OENcdTA5OEZcdTA5OTBcdTA5OTMtXHUwOUE4XHUwOUFBLVx1MDlCMFx1MDlCMlx1MDlCNi1cdTA5QjlcdTA5QkRcdTA5Q0VcdTA5RENcdTA5RERcdTA5REYtXHUwOUUxXHUwOUYwXHUwOUYxXHUwOUZDXHUwQTA1LVx1MEEwQVx1MEEwRlx1MEExMFx1MEExMy1cdTBBMjhcdTBBMkEtXHUwQTMwXHUwQTMyXHUwQTMzXHUwQTM1XHUwQTM2XHUwQTM4XHUwQTM5XHUwQTU5LVx1MEE1Q1x1MEE1RVx1MEE3Mi1cdTBBNzRcdTBBODUtXHUwQThEXHUwQThGLVx1MEE5MVx1MEE5My1cdTBBQThcdTBBQUEtXHUwQUIwXHUwQUIyXHUwQUIzXHUwQUI1LVx1MEFCOVx1MEFCRFx1MEFEMFx1MEFFMFx1MEFFMVx1MEFGOVx1MEIwNS1cdTBCMENcdTBCMEZcdTBCMTBcdTBCMTMtXHUwQjI4XHUwQjJBLVx1MEIzMFx1MEIzMlx1MEIzM1x1MEIzNS1cdTBCMzlcdTBCM0RcdTBCNUNcdTBCNURcdTBCNUYtXHUwQjYxXHUwQjcxXHUwQjgzXHUwQjg1LVx1MEI4QVx1MEI4RS1cdTBCOTBcdTBCOTItXHUwQjk1XHUwQjk5XHUwQjlBXHUwQjlDXHUwQjlFXHUwQjlGXHUwQkEzXHUwQkE0XHUwQkE4LVx1MEJBQVx1MEJBRS1cdTBCQjlcdTBCRDBcdTBDMDUtXHUwQzBDXHUwQzBFLVx1MEMxMFx1MEMxMi1cdTBDMjhcdTBDMkEtXHUwQzM5XHUwQzNEXHUwQzU4LVx1MEM1QVx1MEM2MFx1MEM2MVx1MEM4MFx1MEM4NS1cdTBDOENcdTBDOEUtXHUwQzkwXHUwQzkyLVx1MENBOFx1MENBQS1cdTBDQjNcdTBDQjUtXHUwQ0I5XHUwQ0JEXHUwQ0RFXHUwQ0UwXHUwQ0UxXHUwQ0YxXHUwQ0YyXHUwRDA1LVx1MEQwQ1x1MEQwRS1cdTBEMTBcdTBEMTItXHUwRDNBXHUwRDNEXHUwRDRFXHUwRDU0LVx1MEQ1Nlx1MEQ1Ri1cdTBENjFcdTBEN0EtXHUwRDdGXHUwRDg1LVx1MEQ5Nlx1MEQ5QS1cdTBEQjFcdTBEQjMtXHUwREJCXHUwREJEXHUwREMwLVx1MERDNlx1MEUwMS1cdTBFMzBcdTBFMzJcdTBFMzNcdTBFNDAtXHUwRTQ2XHUwRTgxXHUwRTgyXHUwRTg0XHUwRTg3XHUwRTg4XHUwRThBXHUwRThEXHUwRTk0LVx1MEU5N1x1MEU5OS1cdTBFOUZcdTBFQTEtXHUwRUEzXHUwRUE1XHUwRUE3XHUwRUFBXHUwRUFCXHUwRUFELVx1MEVCMFx1MEVCMlx1MEVCM1x1MEVCRFx1MEVDMC1cdTBFQzRcdTBFQzZcdTBFREMtXHUwRURGXHUwRjAwXHUwRjQwLVx1MEY0N1x1MEY0OS1cdTBGNkNcdTBGODgtXHUwRjhDXHUxMDAwLVx1MTAyQVx1MTAzRlx1MTA1MC1cdTEwNTVcdTEwNUEtXHUxMDVEXHUxMDYxXHUxMDY1XHUxMDY2XHUxMDZFLVx1MTA3MFx1MTA3NS1cdTEwODFcdTEwOEVcdTEwQTAtXHUxMEM1XHUxMEM3XHUxMENEXHUxMEQwLVx1MTBGQVx1MTBGQy1cdTEyNDhcdTEyNEEtXHUxMjREXHUxMjUwLVx1MTI1Nlx1MTI1OFx1MTI1QS1cdTEyNURcdTEyNjAtXHUxMjg4XHUxMjhBLVx1MTI4RFx1MTI5MC1cdTEyQjBcdTEyQjItXHUxMkI1XHUxMkI4LVx1MTJCRVx1MTJDMFx1MTJDMi1cdTEyQzVcdTEyQzgtXHUxMkQ2XHUxMkQ4LVx1MTMxMFx1MTMxMi1cdTEzMTVcdTEzMTgtXHUxMzVBXHUxMzgwLVx1MTM4Rlx1MTNBMC1cdTEzRjVcdTEzRjgtXHUxM0ZEXHUxNDAxLVx1MTY2Q1x1MTY2Ri1cdTE2N0ZcdTE2ODEtXHUxNjlBXHUxNkEwLVx1MTZFQVx1MTZFRS1cdTE2RjhcdTE3MDAtXHUxNzBDXHUxNzBFLVx1MTcxMVx1MTcyMC1cdTE3MzFcdTE3NDAtXHUxNzUxXHUxNzYwLVx1MTc2Q1x1MTc2RS1cdTE3NzBcdTE3ODAtXHUxN0IzXHUxN0Q3XHUxN0RDXHUxODIwLVx1MTg3N1x1MTg4MC1cdTE4ODRcdTE4ODctXHUxOEE4XHUxOEFBXHUxOEIwLVx1MThGNVx1MTkwMC1cdTE5MUVcdTE5NTAtXHUxOTZEXHUxOTcwLVx1MTk3NFx1MTk4MC1cdTE5QUJcdTE5QjAtXHUxOUM5XHUxQTAwLVx1MUExNlx1MUEyMC1cdTFBNTRcdTFBQTdcdTFCMDUtXHUxQjMzXHUxQjQ1LVx1MUI0Qlx1MUI4My1cdTFCQTBcdTFCQUVcdTFCQUZcdTFCQkEtXHUxQkU1XHUxQzAwLVx1MUMyM1x1MUM0RC1cdTFDNEZcdTFDNUEtXHUxQzdEXHUxQzgwLVx1MUM4OFx1MUNFOS1cdTFDRUNcdTFDRUUtXHUxQ0YxXHUxQ0Y1XHUxQ0Y2XHUxRDAwLVx1MURCRlx1MUUwMC1cdTFGMTVcdTFGMTgtXHUxRjFEXHUxRjIwLVx1MUY0NVx1MUY0OC1cdTFGNERcdTFGNTAtXHUxRjU3XHUxRjU5XHUxRjVCXHUxRjVEXHUxRjVGLVx1MUY3RFx1MUY4MC1cdTFGQjRcdTFGQjYtXHUxRkJDXHUxRkJFXHUxRkMyLVx1MUZDNFx1MUZDNi1cdTFGQ0NcdTFGRDAtXHUxRkQzXHUxRkQ2LVx1MUZEQlx1MUZFMC1cdTFGRUNcdTFGRjItXHUxRkY0XHUxRkY2LVx1MUZGQ1x1MjA3MVx1MjA3Rlx1MjA5MC1cdTIwOUNcdTIxMDJcdTIxMDdcdTIxMEEtXHUyMTEzXHUyMTE1XHUyMTE5LVx1MjExRFx1MjEyNFx1MjEyNlx1MjEyOFx1MjEyQS1cdTIxMkRcdTIxMkYtXHUyMTM5XHUyMTNDLVx1MjEzRlx1MjE0NS1cdTIxNDlcdTIxNEVcdTIxNjAtXHUyMTg4XHUyQzAwLVx1MkMyRVx1MkMzMC1cdTJDNUVcdTJDNjAtXHUyQ0U0XHUyQ0VCLVx1MkNFRVx1MkNGMlx1MkNGM1x1MkQwMC1cdTJEMjVcdTJEMjdcdTJEMkRcdTJEMzAtXHUyRDY3XHUyRDZGXHUyRDgwLVx1MkQ5Nlx1MkRBMC1cdTJEQTZcdTJEQTgtXHUyREFFXHUyREIwLVx1MkRCNlx1MkRCOC1cdTJEQkVcdTJEQzAtXHUyREM2XHUyREM4LVx1MkRDRVx1MkREMC1cdTJERDZcdTJERDgtXHUyRERFXHUyRTJGXHUzMDA1LVx1MzAwN1x1MzAyMS1cdTMwMjlcdTMwMzEtXHUzMDM1XHUzMDM4LVx1MzAzQ1x1MzA0MS1cdTMwOTZcdTMwOUQtXHUzMDlGXHUzMEExLVx1MzBGQVx1MzBGQy1cdTMwRkZcdTMxMDUtXHUzMTJFXHUzMTMxLVx1MzE4RVx1MzFBMC1cdTMxQkFcdTMxRjAtXHUzMUZGXHUzNDAwLVx1NERCNVx1NEUwMC1cdTlGRUFcdUEwMDAtXHVBNDhDXHVBNEQwLVx1QTRGRFx1QTUwMC1cdUE2MENcdUE2MTAtXHVBNjFGXHVBNjJBXHVBNjJCXHVBNjQwLVx1QTY2RVx1QTY3Ri1cdUE2OURcdUE2QTAtXHVBNkVGXHVBNzE3LVx1QTcxRlx1QTcyMi1cdUE3ODhcdUE3OEItXHVBN0FFXHVBN0IwLVx1QTdCN1x1QTdGNy1cdUE4MDFcdUE4MDMtXHVBODA1XHVBODA3LVx1QTgwQVx1QTgwQy1cdUE4MjJcdUE4NDAtXHVBODczXHVBODgyLVx1QThCM1x1QThGMi1cdUE4RjdcdUE4RkJcdUE4RkRcdUE5MEEtXHVBOTI1XHVBOTMwLVx1QTk0Nlx1QTk2MC1cdUE5N0NcdUE5ODQtXHVBOUIyXHVBOUNGXHVBOUUwLVx1QTlFNFx1QTlFNi1cdUE5RUZcdUE5RkEtXHVBOUZFXHVBQTAwLVx1QUEyOFx1QUE0MC1cdUFBNDJcdUFBNDQtXHVBQTRCXHVBQTYwLVx1QUE3Nlx1QUE3QVx1QUE3RS1cdUFBQUZcdUFBQjFcdUFBQjVcdUFBQjZcdUFBQjktXHVBQUJEXHVBQUMwXHVBQUMyXHVBQURCLVx1QUFERFx1QUFFMC1cdUFBRUFcdUFBRjItXHVBQUY0XHVBQjAxLVx1QUIwNlx1QUIwOS1cdUFCMEVcdUFCMTEtXHVBQjE2XHVBQjIwLVx1QUIyNlx1QUIyOC1cdUFCMkVcdUFCMzAtXHVBQjVBXHVBQjVDLVx1QUI2NVx1QUI3MC1cdUFCRTJcdUFDMDAtXHVEN0EzXHVEN0IwLVx1RDdDNlx1RDdDQi1cdUQ3RkJcdUY5MDAtXHVGQTZEXHVGQTcwLVx1RkFEOVx1RkIwMC1cdUZCMDZcdUZCMTMtXHVGQjE3XHVGQjFEXHVGQjFGLVx1RkIyOFx1RkIyQS1cdUZCMzZcdUZCMzgtXHVGQjNDXHVGQjNFXHVGQjQwXHVGQjQxXHVGQjQzXHVGQjQ0XHVGQjQ2LVx1RkJCMVx1RkJEMy1cdUZEM0RcdUZENTAtXHVGRDhGXHVGRDkyLVx1RkRDN1x1RkRGMC1cdUZERkJcdUZFNzAtXHVGRTc0XHVGRTc2LVx1RkVGQ1x1RkYyMS1cdUZGM0FcdUZGNDEtXHVGRjVBXHVGRjY2LVx1RkZCRVx1RkZDMi1cdUZGQzdcdUZGQ0EtXHVGRkNGXHVGRkQyLVx1RkZEN1x1RkZEQS1cdUZGRENdfFx1RDgwMFtcdURDMDAtXHVEQzBCXHVEQzBELVx1REMyNlx1REMyOC1cdURDM0FcdURDM0NcdURDM0RcdURDM0YtXHVEQzREXHVEQzUwLVx1REM1RFx1REM4MC1cdURDRkFcdURENDAtXHVERDc0XHVERTgwLVx1REU5Q1x1REVBMC1cdURFRDBcdURGMDAtXHVERjFGXHVERjJELVx1REY0QVx1REY1MC1cdURGNzVcdURGODAtXHVERjlEXHVERkEwLVx1REZDM1x1REZDOC1cdURGQ0ZcdURGRDEtXHVERkQ1XXxcdUQ4MDFbXHVEQzAwLVx1REM5RFx1RENCMC1cdURDRDNcdURDRDgtXHVEQ0ZCXHVERDAwLVx1REQyN1x1REQzMC1cdURENjNcdURFMDAtXHVERjM2XHVERjQwLVx1REY1NVx1REY2MC1cdURGNjddfFx1RDgwMltcdURDMDAtXHVEQzA1XHVEQzA4XHVEQzBBLVx1REMzNVx1REMzN1x1REMzOFx1REMzQ1x1REMzRi1cdURDNTVcdURDNjAtXHVEQzc2XHVEQzgwLVx1REM5RVx1RENFMC1cdURDRjJcdURDRjRcdURDRjVcdUREMDAtXHVERDE1XHVERDIwLVx1REQzOVx1REQ4MC1cdUREQjdcdUREQkVcdUREQkZcdURFMDBcdURFMTAtXHVERTEzXHVERTE1LVx1REUxN1x1REUxOS1cdURFMzNcdURFNjAtXHVERTdDXHVERTgwLVx1REU5Q1x1REVDMC1cdURFQzdcdURFQzktXHVERUU0XHVERjAwLVx1REYzNVx1REY0MC1cdURGNTVcdURGNjAtXHVERjcyXHVERjgwLVx1REY5MV18XHVEODAzW1x1REMwMC1cdURDNDhcdURDODAtXHVEQ0IyXHVEQ0MwLVx1RENGMl18XHVEODA0W1x1REMwMy1cdURDMzdcdURDODMtXHVEQ0FGXHVEQ0QwLVx1RENFOFx1REQwMy1cdUREMjZcdURENTAtXHVERDcyXHVERDc2XHVERDgzLVx1RERCMlx1RERDMS1cdUREQzRcdUREREFcdURERENcdURFMDAtXHVERTExXHVERTEzLVx1REUyQlx1REU4MC1cdURFODZcdURFODhcdURFOEEtXHVERThEXHVERThGLVx1REU5RFx1REU5Ri1cdURFQThcdURFQjAtXHVERURFXHVERjA1LVx1REYwQ1x1REYwRlx1REYxMFx1REYxMy1cdURGMjhcdURGMkEtXHVERjMwXHVERjMyXHVERjMzXHVERjM1LVx1REYzOVx1REYzRFx1REY1MFx1REY1RC1cdURGNjFdfFx1RDgwNVtcdURDMDAtXHVEQzM0XHVEQzQ3LVx1REM0QVx1REM4MC1cdURDQUZcdURDQzRcdURDQzVcdURDQzdcdUREODAtXHVEREFFXHVEREQ4LVx1REREQlx1REUwMC1cdURFMkZcdURFNDRcdURFODAtXHVERUFBXHVERjAwLVx1REYxOV18XHVEODA2W1x1RENBMC1cdURDREZcdURDRkZcdURFMDBcdURFMEItXHVERTMyXHVERTNBXHVERTUwXHVERTVDLVx1REU4M1x1REU4Ni1cdURFODlcdURFQzAtXHVERUY4XXxcdUQ4MDdbXHVEQzAwLVx1REMwOFx1REMwQS1cdURDMkVcdURDNDBcdURDNzItXHVEQzhGXHVERDAwLVx1REQwNlx1REQwOFx1REQwOVx1REQwQi1cdUREMzBcdURENDZdfFx1RDgwOFtcdURDMDAtXHVERjk5XXxcdUQ4MDlbXHVEQzAwLVx1REM2RVx1REM4MC1cdURENDNdfFtcdUQ4MENcdUQ4MUMtXHVEODIwXHVEODQwLVx1RDg2OFx1RDg2QS1cdUQ4NkNcdUQ4NkYtXHVEODcyXHVEODc0LVx1RDg3OV1bXHVEQzAwLVx1REZGRl18XHVEODBEW1x1REMwMC1cdURDMkVdfFx1RDgxMVtcdURDMDAtXHVERTQ2XXxcdUQ4MUFbXHVEQzAwLVx1REUzOFx1REU0MC1cdURFNUVcdURFRDAtXHVERUVEXHVERjAwLVx1REYyRlx1REY0MC1cdURGNDNcdURGNjMtXHVERjc3XHVERjdELVx1REY4Rl18XHVEODFCW1x1REYwMC1cdURGNDRcdURGNTBcdURGOTMtXHVERjlGXHVERkUwXHVERkUxXXxcdUQ4MjFbXHVEQzAwLVx1REZFQ118XHVEODIyW1x1REMwMC1cdURFRjJdfFx1RDgyQ1tcdURDMDAtXHVERDFFXHVERDcwLVx1REVGQl18XHVEODJGW1x1REMwMC1cdURDNkFcdURDNzAtXHVEQzdDXHVEQzgwLVx1REM4OFx1REM5MC1cdURDOTldfFx1RDgzNVtcdURDMDAtXHVEQzU0XHVEQzU2LVx1REM5Q1x1REM5RVx1REM5Rlx1RENBMlx1RENBNVx1RENBNlx1RENBOS1cdURDQUNcdURDQUUtXHVEQ0I5XHVEQ0JCXHVEQ0JELVx1RENDM1x1RENDNS1cdUREMDVcdUREMDctXHVERDBBXHVERDBELVx1REQxNFx1REQxNi1cdUREMUNcdUREMUUtXHVERDM5XHVERDNCLVx1REQzRVx1REQ0MC1cdURENDRcdURENDZcdURENEEtXHVERDUwXHVERDUyLVx1REVBNVx1REVBOC1cdURFQzBcdURFQzItXHVERURBXHVERURDLVx1REVGQVx1REVGQy1cdURGMTRcdURGMTYtXHVERjM0XHVERjM2LVx1REY0RVx1REY1MC1cdURGNkVcdURGNzAtXHVERjg4XHVERjhBLVx1REZBOFx1REZBQS1cdURGQzJcdURGQzQtXHVERkNCXXxcdUQ4M0FbXHVEQzAwLVx1RENDNFx1REQwMC1cdURENDNdfFx1RDgzQltcdURFMDAtXHVERTAzXHVERTA1LVx1REUxRlx1REUyMVx1REUyMlx1REUyNFx1REUyN1x1REUyOS1cdURFMzJcdURFMzQtXHVERTM3XHVERTM5XHVERTNCXHVERTQyXHVERTQ3XHVERTQ5XHVERTRCXHVERTRELVx1REU0Rlx1REU1MVx1REU1Mlx1REU1NFx1REU1N1x1REU1OVx1REU1Qlx1REU1RFx1REU1Rlx1REU2MVx1REU2Mlx1REU2NFx1REU2Ny1cdURFNkFcdURFNkMtXHVERTcyXHVERTc0LVx1REU3N1x1REU3OS1cdURFN0NcdURFN0VcdURFODAtXHVERTg5XHVERThCLVx1REU5Qlx1REVBMS1cdURFQTNcdURFQTUtXHVERUE5XHVERUFCLVx1REVCQl18XHVEODY5W1x1REMwMC1cdURFRDZcdURGMDAtXHVERkZGXXxcdUQ4NkRbXHVEQzAwLVx1REYzNFx1REY0MC1cdURGRkZdfFx1RDg2RVtcdURDMDAtXHVEQzFEXHVEQzIwLVx1REZGRl18XHVEODczW1x1REMwMC1cdURFQTFcdURFQjAtXHVERkZGXXxcdUQ4N0FbXHVEQzAwLVx1REZFMF18XHVEODdFW1x1REMwMC1cdURFMURdLyxJRF9Db250aW51ZTovW1x4QUFceEI1XHhCQVx4QzAtXHhENlx4RDgtXHhGNlx4RjgtXHUwMkMxXHUwMkM2LVx1MDJEMVx1MDJFMC1cdTAyRTRcdTAyRUNcdTAyRUVcdTAzMDAtXHUwMzc0XHUwMzc2XHUwMzc3XHUwMzdBLVx1MDM3RFx1MDM3Rlx1MDM4Nlx1MDM4OC1cdTAzOEFcdTAzOENcdTAzOEUtXHUwM0ExXHUwM0EzLVx1MDNGNVx1MDNGNy1cdTA0ODFcdTA0ODMtXHUwNDg3XHUwNDhBLVx1MDUyRlx1MDUzMS1cdTA1NTZcdTA1NTlcdTA1NjEtXHUwNTg3XHUwNTkxLVx1MDVCRFx1MDVCRlx1MDVDMVx1MDVDMlx1MDVDNFx1MDVDNVx1MDVDN1x1MDVEMC1cdTA1RUFcdTA1RjAtXHUwNUYyXHUwNjEwLVx1MDYxQVx1MDYyMC1cdTA2NjlcdTA2NkUtXHUwNkQzXHUwNkQ1LVx1MDZEQ1x1MDZERi1cdTA2RThcdTA2RUEtXHUwNkZDXHUwNkZGXHUwNzEwLVx1MDc0QVx1MDc0RC1cdTA3QjFcdTA3QzAtXHUwN0Y1XHUwN0ZBXHUwODAwLVx1MDgyRFx1MDg0MC1cdTA4NUJcdTA4NjAtXHUwODZBXHUwOEEwLVx1MDhCNFx1MDhCNi1cdTA4QkRcdTA4RDQtXHUwOEUxXHUwOEUzLVx1MDk2M1x1MDk2Ni1cdTA5NkZcdTA5NzEtXHUwOTgzXHUwOTg1LVx1MDk4Q1x1MDk4Rlx1MDk5MFx1MDk5My1cdTA5QThcdTA5QUEtXHUwOUIwXHUwOUIyXHUwOUI2LVx1MDlCOVx1MDlCQy1cdTA5QzRcdTA5QzdcdTA5QzhcdTA5Q0ItXHUwOUNFXHUwOUQ3XHUwOURDXHUwOUREXHUwOURGLVx1MDlFM1x1MDlFNi1cdTA5RjFcdTA5RkNcdTBBMDEtXHUwQTAzXHUwQTA1LVx1MEEwQVx1MEEwRlx1MEExMFx1MEExMy1cdTBBMjhcdTBBMkEtXHUwQTMwXHUwQTMyXHUwQTMzXHUwQTM1XHUwQTM2XHUwQTM4XHUwQTM5XHUwQTNDXHUwQTNFLVx1MEE0Mlx1MEE0N1x1MEE0OFx1MEE0Qi1cdTBBNERcdTBBNTFcdTBBNTktXHUwQTVDXHUwQTVFXHUwQTY2LVx1MEE3NVx1MEE4MS1cdTBBODNcdTBBODUtXHUwQThEXHUwQThGLVx1MEE5MVx1MEE5My1cdTBBQThcdTBBQUEtXHUwQUIwXHUwQUIyXHUwQUIzXHUwQUI1LVx1MEFCOVx1MEFCQy1cdTBBQzVcdTBBQzctXHUwQUM5XHUwQUNCLVx1MEFDRFx1MEFEMFx1MEFFMC1cdTBBRTNcdTBBRTYtXHUwQUVGXHUwQUY5LVx1MEFGRlx1MEIwMS1cdTBCMDNcdTBCMDUtXHUwQjBDXHUwQjBGXHUwQjEwXHUwQjEzLVx1MEIyOFx1MEIyQS1cdTBCMzBcdTBCMzJcdTBCMzNcdTBCMzUtXHUwQjM5XHUwQjNDLVx1MEI0NFx1MEI0N1x1MEI0OFx1MEI0Qi1cdTBCNERcdTBCNTZcdTBCNTdcdTBCNUNcdTBCNURcdTBCNUYtXHUwQjYzXHUwQjY2LVx1MEI2Rlx1MEI3MVx1MEI4Mlx1MEI4M1x1MEI4NS1cdTBCOEFcdTBCOEUtXHUwQjkwXHUwQjkyLVx1MEI5NVx1MEI5OVx1MEI5QVx1MEI5Q1x1MEI5RVx1MEI5Rlx1MEJBM1x1MEJBNFx1MEJBOC1cdTBCQUFcdTBCQUUtXHUwQkI5XHUwQkJFLVx1MEJDMlx1MEJDNi1cdTBCQzhcdTBCQ0EtXHUwQkNEXHUwQkQwXHUwQkQ3XHUwQkU2LVx1MEJFRlx1MEMwMC1cdTBDMDNcdTBDMDUtXHUwQzBDXHUwQzBFLVx1MEMxMFx1MEMxMi1cdTBDMjhcdTBDMkEtXHUwQzM5XHUwQzNELVx1MEM0NFx1MEM0Ni1cdTBDNDhcdTBDNEEtXHUwQzREXHUwQzU1XHUwQzU2XHUwQzU4LVx1MEM1QVx1MEM2MC1cdTBDNjNcdTBDNjYtXHUwQzZGXHUwQzgwLVx1MEM4M1x1MEM4NS1cdTBDOENcdTBDOEUtXHUwQzkwXHUwQzkyLVx1MENBOFx1MENBQS1cdTBDQjNcdTBDQjUtXHUwQ0I5XHUwQ0JDLVx1MENDNFx1MENDNi1cdTBDQzhcdTBDQ0EtXHUwQ0NEXHUwQ0Q1XHUwQ0Q2XHUwQ0RFXHUwQ0UwLVx1MENFM1x1MENFNi1cdTBDRUZcdTBDRjFcdTBDRjJcdTBEMDAtXHUwRDAzXHUwRDA1LVx1MEQwQ1x1MEQwRS1cdTBEMTBcdTBEMTItXHUwRDQ0XHUwRDQ2LVx1MEQ0OFx1MEQ0QS1cdTBENEVcdTBENTQtXHUwRDU3XHUwRDVGLVx1MEQ2M1x1MEQ2Ni1cdTBENkZcdTBEN0EtXHUwRDdGXHUwRDgyXHUwRDgzXHUwRDg1LVx1MEQ5Nlx1MEQ5QS1cdTBEQjFcdTBEQjMtXHUwREJCXHUwREJEXHUwREMwLVx1MERDNlx1MERDQVx1MERDRi1cdTBERDRcdTBERDZcdTBERDgtXHUwRERGXHUwREU2LVx1MERFRlx1MERGMlx1MERGM1x1MEUwMS1cdTBFM0FcdTBFNDAtXHUwRTRFXHUwRTUwLVx1MEU1OVx1MEU4MVx1MEU4Mlx1MEU4NFx1MEU4N1x1MEU4OFx1MEU4QVx1MEU4RFx1MEU5NC1cdTBFOTdcdTBFOTktXHUwRTlGXHUwRUExLVx1MEVBM1x1MEVBNVx1MEVBN1x1MEVBQVx1MEVBQlx1MEVBRC1cdTBFQjlcdTBFQkItXHUwRUJEXHUwRUMwLVx1MEVDNFx1MEVDNlx1MEVDOC1cdTBFQ0RcdTBFRDAtXHUwRUQ5XHUwRURDLVx1MEVERlx1MEYwMFx1MEYxOFx1MEYxOVx1MEYyMC1cdTBGMjlcdTBGMzVcdTBGMzdcdTBGMzlcdTBGM0UtXHUwRjQ3XHUwRjQ5LVx1MEY2Q1x1MEY3MS1cdTBGODRcdTBGODYtXHUwRjk3XHUwRjk5LVx1MEZCQ1x1MEZDNlx1MTAwMC1cdTEwNDlcdTEwNTAtXHUxMDlEXHUxMEEwLVx1MTBDNVx1MTBDN1x1MTBDRFx1MTBEMC1cdTEwRkFcdTEwRkMtXHUxMjQ4XHUxMjRBLVx1MTI0RFx1MTI1MC1cdTEyNTZcdTEyNThcdTEyNUEtXHUxMjVEXHUxMjYwLVx1MTI4OFx1MTI4QS1cdTEyOERcdTEyOTAtXHUxMkIwXHUxMkIyLVx1MTJCNVx1MTJCOC1cdTEyQkVcdTEyQzBcdTEyQzItXHUxMkM1XHUxMkM4LVx1MTJENlx1MTJEOC1cdTEzMTBcdTEzMTItXHUxMzE1XHUxMzE4LVx1MTM1QVx1MTM1RC1cdTEzNUZcdTEzODAtXHUxMzhGXHUxM0EwLVx1MTNGNVx1MTNGOC1cdTEzRkRcdTE0MDEtXHUxNjZDXHUxNjZGLVx1MTY3Rlx1MTY4MS1cdTE2OUFcdTE2QTAtXHUxNkVBXHUxNkVFLVx1MTZGOFx1MTcwMC1cdTE3MENcdTE3MEUtXHUxNzE0XHUxNzIwLVx1MTczNFx1MTc0MC1cdTE3NTNcdTE3NjAtXHUxNzZDXHUxNzZFLVx1MTc3MFx1MTc3Mlx1MTc3M1x1MTc4MC1cdTE3RDNcdTE3RDdcdTE3RENcdTE3RERcdTE3RTAtXHUxN0U5XHUxODBCLVx1MTgwRFx1MTgxMC1cdTE4MTlcdTE4MjAtXHUxODc3XHUxODgwLVx1MThBQVx1MThCMC1cdTE4RjVcdTE5MDAtXHUxOTFFXHUxOTIwLVx1MTkyQlx1MTkzMC1cdTE5M0JcdTE5NDYtXHUxOTZEXHUxOTcwLVx1MTk3NFx1MTk4MC1cdTE5QUJcdTE5QjAtXHUxOUM5XHUxOUQwLVx1MTlEOVx1MUEwMC1cdTFBMUJcdTFBMjAtXHUxQTVFXHUxQTYwLVx1MUE3Q1x1MUE3Ri1cdTFBODlcdTFBOTAtXHUxQTk5XHUxQUE3XHUxQUIwLVx1MUFCRFx1MUIwMC1cdTFCNEJcdTFCNTAtXHUxQjU5XHUxQjZCLVx1MUI3M1x1MUI4MC1cdTFCRjNcdTFDMDAtXHUxQzM3XHUxQzQwLVx1MUM0OVx1MUM0RC1cdTFDN0RcdTFDODAtXHUxQzg4XHUxQ0QwLVx1MUNEMlx1MUNENC1cdTFDRjlcdTFEMDAtXHUxREY5XHUxREZCLVx1MUYxNVx1MUYxOC1cdTFGMURcdTFGMjAtXHUxRjQ1XHUxRjQ4LVx1MUY0RFx1MUY1MC1cdTFGNTdcdTFGNTlcdTFGNUJcdTFGNURcdTFGNUYtXHUxRjdEXHUxRjgwLVx1MUZCNFx1MUZCNi1cdTFGQkNcdTFGQkVcdTFGQzItXHUxRkM0XHUxRkM2LVx1MUZDQ1x1MUZEMC1cdTFGRDNcdTFGRDYtXHUxRkRCXHUxRkUwLVx1MUZFQ1x1MUZGMi1cdTFGRjRcdTFGRjYtXHUxRkZDXHUyMDNGXHUyMDQwXHUyMDU0XHUyMDcxXHUyMDdGXHUyMDkwLVx1MjA5Q1x1MjBEMC1cdTIwRENcdTIwRTFcdTIwRTUtXHUyMEYwXHUyMTAyXHUyMTA3XHUyMTBBLVx1MjExM1x1MjExNVx1MjExOS1cdTIxMURcdTIxMjRcdTIxMjZcdTIxMjhcdTIxMkEtXHUyMTJEXHUyMTJGLVx1MjEzOVx1MjEzQy1cdTIxM0ZcdTIxNDUtXHUyMTQ5XHUyMTRFXHUyMTYwLVx1MjE4OFx1MkMwMC1cdTJDMkVcdTJDMzAtXHUyQzVFXHUyQzYwLVx1MkNFNFx1MkNFQi1cdTJDRjNcdTJEMDAtXHUyRDI1XHUyRDI3XHUyRDJEXHUyRDMwLVx1MkQ2N1x1MkQ2Rlx1MkQ3Ri1cdTJEOTZcdTJEQTAtXHUyREE2XHUyREE4LVx1MkRBRVx1MkRCMC1cdTJEQjZcdTJEQjgtXHUyREJFXHUyREMwLVx1MkRDNlx1MkRDOC1cdTJEQ0VcdTJERDAtXHUyREQ2XHUyREQ4LVx1MkRERVx1MkRFMC1cdTJERkZcdTJFMkZcdTMwMDUtXHUzMDA3XHUzMDIxLVx1MzAyRlx1MzAzMS1cdTMwMzVcdTMwMzgtXHUzMDNDXHUzMDQxLVx1MzA5Nlx1MzA5OVx1MzA5QVx1MzA5RC1cdTMwOUZcdTMwQTEtXHUzMEZBXHUzMEZDLVx1MzBGRlx1MzEwNS1cdTMxMkVcdTMxMzEtXHUzMThFXHUzMUEwLVx1MzFCQVx1MzFGMC1cdTMxRkZcdTM0MDAtXHU0REI1XHU0RTAwLVx1OUZFQVx1QTAwMC1cdUE0OENcdUE0RDAtXHVBNEZEXHVBNTAwLVx1QTYwQ1x1QTYxMC1cdUE2MkJcdUE2NDAtXHVBNjZGXHVBNjc0LVx1QTY3RFx1QTY3Ri1cdUE2RjFcdUE3MTctXHVBNzFGXHVBNzIyLVx1QTc4OFx1QTc4Qi1cdUE3QUVcdUE3QjAtXHVBN0I3XHVBN0Y3LVx1QTgyN1x1QTg0MC1cdUE4NzNcdUE4ODAtXHVBOEM1XHVBOEQwLVx1QThEOVx1QThFMC1cdUE4RjdcdUE4RkJcdUE4RkRcdUE5MDAtXHVBOTJEXHVBOTMwLVx1QTk1M1x1QTk2MC1cdUE5N0NcdUE5ODAtXHVBOUMwXHVBOUNGLVx1QTlEOVx1QTlFMC1cdUE5RkVcdUFBMDAtXHVBQTM2XHVBQTQwLVx1QUE0RFx1QUE1MC1cdUFBNTlcdUFBNjAtXHVBQTc2XHVBQTdBLVx1QUFDMlx1QUFEQi1cdUFBRERcdUFBRTAtXHVBQUVGXHVBQUYyLVx1QUFGNlx1QUIwMS1cdUFCMDZcdUFCMDktXHVBQjBFXHVBQjExLVx1QUIxNlx1QUIyMC1cdUFCMjZcdUFCMjgtXHVBQjJFXHVBQjMwLVx1QUI1QVx1QUI1Qy1cdUFCNjVcdUFCNzAtXHVBQkVBXHVBQkVDXHVBQkVEXHVBQkYwLVx1QUJGOVx1QUMwMC1cdUQ3QTNcdUQ3QjAtXHVEN0M2XHVEN0NCLVx1RDdGQlx1RjkwMC1cdUZBNkRcdUZBNzAtXHVGQUQ5XHVGQjAwLVx1RkIwNlx1RkIxMy1cdUZCMTdcdUZCMUQtXHVGQjI4XHVGQjJBLVx1RkIzNlx1RkIzOC1cdUZCM0NcdUZCM0VcdUZCNDBcdUZCNDFcdUZCNDNcdUZCNDRcdUZCNDYtXHVGQkIxXHVGQkQzLVx1RkQzRFx1RkQ1MC1cdUZEOEZcdUZEOTItXHVGREM3XHVGREYwLVx1RkRGQlx1RkUwMC1cdUZFMEZcdUZFMjAtXHVGRTJGXHVGRTMzXHVGRTM0XHVGRTRELVx1RkU0Rlx1RkU3MC1cdUZFNzRcdUZFNzYtXHVGRUZDXHVGRjEwLVx1RkYxOVx1RkYyMS1cdUZGM0FcdUZGM0ZcdUZGNDEtXHVGRjVBXHVGRjY2LVx1RkZCRVx1RkZDMi1cdUZGQzdcdUZGQ0EtXHVGRkNGXHVGRkQyLVx1RkZEN1x1RkZEQS1cdUZGRENdfFx1RDgwMFtcdURDMDAtXHVEQzBCXHVEQzBELVx1REMyNlx1REMyOC1cdURDM0FcdURDM0NcdURDM0RcdURDM0YtXHVEQzREXHVEQzUwLVx1REM1RFx1REM4MC1cdURDRkFcdURENDAtXHVERDc0XHVEREZEXHVERTgwLVx1REU5Q1x1REVBMC1cdURFRDBcdURFRTBcdURGMDAtXHVERjFGXHVERjJELVx1REY0QVx1REY1MC1cdURGN0FcdURGODAtXHVERjlEXHVERkEwLVx1REZDM1x1REZDOC1cdURGQ0ZcdURGRDEtXHVERkQ1XXxcdUQ4MDFbXHVEQzAwLVx1REM5RFx1RENBMC1cdURDQTlcdURDQjAtXHVEQ0QzXHVEQ0Q4LVx1RENGQlx1REQwMC1cdUREMjdcdUREMzAtXHVERDYzXHVERTAwLVx1REYzNlx1REY0MC1cdURGNTVcdURGNjAtXHVERjY3XXxcdUQ4MDJbXHVEQzAwLVx1REMwNVx1REMwOFx1REMwQS1cdURDMzVcdURDMzdcdURDMzhcdURDM0NcdURDM0YtXHVEQzU1XHVEQzYwLVx1REM3Nlx1REM4MC1cdURDOUVcdURDRTAtXHVEQ0YyXHVEQ0Y0XHVEQ0Y1XHVERDAwLVx1REQxNVx1REQyMC1cdUREMzlcdUREODAtXHVEREI3XHVEREJFXHVEREJGXHVERTAwLVx1REUwM1x1REUwNVx1REUwNlx1REUwQy1cdURFMTNcdURFMTUtXHVERTE3XHVERTE5LVx1REUzM1x1REUzOC1cdURFM0FcdURFM0ZcdURFNjAtXHVERTdDXHVERTgwLVx1REU5Q1x1REVDMC1cdURFQzdcdURFQzktXHVERUU2XHVERjAwLVx1REYzNVx1REY0MC1cdURGNTVcdURGNjAtXHVERjcyXHVERjgwLVx1REY5MV18XHVEODAzW1x1REMwMC1cdURDNDhcdURDODAtXHVEQ0IyXHVEQ0MwLVx1RENGMl18XHVEODA0W1x1REMwMC1cdURDNDZcdURDNjYtXHVEQzZGXHVEQzdGLVx1RENCQVx1RENEMC1cdURDRThcdURDRjAtXHVEQ0Y5XHVERDAwLVx1REQzNFx1REQzNi1cdUREM0ZcdURENTAtXHVERDczXHVERDc2XHVERDgwLVx1RERDNFx1RERDQS1cdUREQ0NcdURERDAtXHVERERBXHVERERDXHVERTAwLVx1REUxMVx1REUxMy1cdURFMzdcdURFM0VcdURFODAtXHVERTg2XHVERTg4XHVERThBLVx1REU4RFx1REU4Ri1cdURFOURcdURFOUYtXHVERUE4XHVERUIwLVx1REVFQVx1REVGMC1cdURFRjlcdURGMDAtXHVERjAzXHVERjA1LVx1REYwQ1x1REYwRlx1REYxMFx1REYxMy1cdURGMjhcdURGMkEtXHVERjMwXHVERjMyXHVERjMzXHVERjM1LVx1REYzOVx1REYzQy1cdURGNDRcdURGNDdcdURGNDhcdURGNEItXHVERjREXHVERjUwXHVERjU3XHVERjVELVx1REY2M1x1REY2Ni1cdURGNkNcdURGNzAtXHVERjc0XXxcdUQ4MDVbXHVEQzAwLVx1REM0QVx1REM1MC1cdURDNTlcdURDODAtXHVEQ0M1XHVEQ0M3XHVEQ0QwLVx1RENEOVx1REQ4MC1cdUREQjVcdUREQjgtXHVEREMwXHVEREQ4LVx1RERERFx1REUwMC1cdURFNDBcdURFNDRcdURFNTAtXHVERTU5XHVERTgwLVx1REVCN1x1REVDMC1cdURFQzlcdURGMDAtXHVERjE5XHVERjFELVx1REYyQlx1REYzMC1cdURGMzldfFx1RDgwNltcdURDQTAtXHVEQ0U5XHVEQ0ZGXHVERTAwLVx1REUzRVx1REU0N1x1REU1MC1cdURFODNcdURFODYtXHVERTk5XHVERUMwLVx1REVGOF18XHVEODA3W1x1REMwMC1cdURDMDhcdURDMEEtXHVEQzM2XHVEQzM4LVx1REM0MFx1REM1MC1cdURDNTlcdURDNzItXHVEQzhGXHVEQzkyLVx1RENBN1x1RENBOS1cdURDQjZcdUREMDAtXHVERDA2XHVERDA4XHVERDA5XHVERDBCLVx1REQzNlx1REQzQVx1REQzQ1x1REQzRFx1REQzRi1cdURENDdcdURENTAtXHVERDU5XXxcdUQ4MDhbXHVEQzAwLVx1REY5OV18XHVEODA5W1x1REMwMC1cdURDNkVcdURDODAtXHVERDQzXXxbXHVEODBDXHVEODFDLVx1RDgyMFx1RDg0MC1cdUQ4NjhcdUQ4NkEtXHVEODZDXHVEODZGLVx1RDg3Mlx1RDg3NC1cdUQ4NzldW1x1REMwMC1cdURGRkZdfFx1RDgwRFtcdURDMDAtXHVEQzJFXXxcdUQ4MTFbXHVEQzAwLVx1REU0Nl18XHVEODFBW1x1REMwMC1cdURFMzhcdURFNDAtXHVERTVFXHVERTYwLVx1REU2OVx1REVEMC1cdURFRURcdURFRjAtXHVERUY0XHVERjAwLVx1REYzNlx1REY0MC1cdURGNDNcdURGNTAtXHVERjU5XHVERjYzLVx1REY3N1x1REY3RC1cdURGOEZdfFx1RDgxQltcdURGMDAtXHVERjQ0XHVERjUwLVx1REY3RVx1REY4Ri1cdURGOUZcdURGRTBcdURGRTFdfFx1RDgyMVtcdURDMDAtXHVERkVDXXxcdUQ4MjJbXHVEQzAwLVx1REVGMl18XHVEODJDW1x1REMwMC1cdUREMUVcdURENzAtXHVERUZCXXxcdUQ4MkZbXHVEQzAwLVx1REM2QVx1REM3MC1cdURDN0NcdURDODAtXHVEQzg4XHVEQzkwLVx1REM5OVx1REM5RFx1REM5RV18XHVEODM0W1x1REQ2NS1cdURENjlcdURENkQtXHVERDcyXHVERDdCLVx1REQ4Mlx1REQ4NS1cdUREOEJcdUREQUEtXHVEREFEXHVERTQyLVx1REU0NF18XHVEODM1W1x1REMwMC1cdURDNTRcdURDNTYtXHVEQzlDXHVEQzlFXHVEQzlGXHVEQ0EyXHVEQ0E1XHVEQ0E2XHVEQ0E5LVx1RENBQ1x1RENBRS1cdURDQjlcdURDQkJcdURDQkQtXHVEQ0MzXHVEQ0M1LVx1REQwNVx1REQwNy1cdUREMEFcdUREMEQtXHVERDE0XHVERDE2LVx1REQxQ1x1REQxRS1cdUREMzlcdUREM0ItXHVERDNFXHVERDQwLVx1REQ0NFx1REQ0Nlx1REQ0QS1cdURENTBcdURENTItXHVERUE1XHVERUE4LVx1REVDMFx1REVDMi1cdURFREFcdURFREMtXHVERUZBXHVERUZDLVx1REYxNFx1REYxNi1cdURGMzRcdURGMzYtXHVERjRFXHVERjUwLVx1REY2RVx1REY3MC1cdURGODhcdURGOEEtXHVERkE4XHVERkFBLVx1REZDMlx1REZDNC1cdURGQ0JcdURGQ0UtXHVERkZGXXxcdUQ4MzZbXHVERTAwLVx1REUzNlx1REUzQi1cdURFNkNcdURFNzVcdURFODRcdURFOUItXHVERTlGXHVERUExLVx1REVBRl18XHVEODM4W1x1REMwMC1cdURDMDZcdURDMDgtXHVEQzE4XHVEQzFCLVx1REMyMVx1REMyM1x1REMyNFx1REMyNi1cdURDMkFdfFx1RDgzQVtcdURDMDAtXHVEQ0M0XHVEQ0QwLVx1RENENlx1REQwMC1cdURENEFcdURENTAtXHVERDU5XXxcdUQ4M0JbXHVERTAwLVx1REUwM1x1REUwNS1cdURFMUZcdURFMjFcdURFMjJcdURFMjRcdURFMjdcdURFMjktXHVERTMyXHVERTM0LVx1REUzN1x1REUzOVx1REUzQlx1REU0Mlx1REU0N1x1REU0OVx1REU0Qlx1REU0RC1cdURFNEZcdURFNTFcdURFNTJcdURFNTRcdURFNTdcdURFNTlcdURFNUJcdURFNURcdURFNUZcdURFNjFcdURFNjJcdURFNjRcdURFNjctXHVERTZBXHVERTZDLVx1REU3Mlx1REU3NC1cdURFNzdcdURFNzktXHVERTdDXHVERTdFXHVERTgwLVx1REU4OVx1REU4Qi1cdURFOUJcdURFQTEtXHVERUEzXHVERUE1LVx1REVBOVx1REVBQi1cdURFQkJdfFx1RDg2OVtcdURDMDAtXHVERUQ2XHVERjAwLVx1REZGRl18XHVEODZEW1x1REMwMC1cdURGMzRcdURGNDAtXHVERkZGXXxcdUQ4NkVbXHVEQzAwLVx1REMxRFx1REMyMC1cdURGRkZdfFx1RDg3M1tcdURDMDAtXHVERUExXHVERUIwLVx1REZGRl18XHVEODdBW1x1REMwMC1cdURGRTBdfFx1RDg3RVtcdURDMDAtXHVERTFEXXxcdURCNDBbXHVERDAwLVx1RERFRl0vfSxVPXtpc1NwYWNlU2VwYXJhdG9yOmZ1bmN0aW9uKHUpe3JldHVybiJzdHJpbmciPT10eXBlb2YgdSYmRy5TcGFjZV9TZXBhcmF0b3IudGVzdCh1KX0saXNJZFN0YXJ0Q2hhcjpmdW5jdGlvbih1KXtyZXR1cm4ic3RyaW5nIj09dHlwZW9mIHUmJih1Pj0iYSImJnU8PSJ6Inx8dT49IkEiJiZ1PD0iWiJ8fCIkIj09PXV8fCJfIj09PXV8fEcuSURfU3RhcnQudGVzdCh1KSl9LGlzSWRDb250aW51ZUNoYXI6ZnVuY3Rpb24odSl7cmV0dXJuInN0cmluZyI9PXR5cGVvZiB1JiYodT49ImEiJiZ1PD0ieiJ8fHU+PSJBIiYmdTw9IloifHx1Pj0iMCImJnU8PSI5Inx8IiQiPT09dXx8Il8iPT09dXx8IuKAjCI9PT11fHwi4oCNIj09PXV8fEcuSURfQ29udGludWUudGVzdCh1KSl9LGlzRGlnaXQ6ZnVuY3Rpb24odSl7cmV0dXJuInN0cmluZyI9PXR5cGVvZiB1JiYvWzAtOV0vLnRlc3QodSl9LGlzSGV4RGlnaXQ6ZnVuY3Rpb24odSl7cmV0dXJuInN0cmluZyI9PXR5cGVvZiB1JiYvWzAtOUEtRmEtZl0vLnRlc3QodSl9fTtmdW5jdGlvbiBaKCl7Zm9yKFQ9ImRlZmF1bHQiLHo9IiIsSD0hMSwkPTE7Oyl7Uj1xKCk7dmFyIHU9WFtUXSgpO2lmKHUpcmV0dXJuIHV9fWZ1bmN0aW9uIHEoKXtpZihfW0ldKXJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChfLmNvZGVQb2ludEF0KEkpKX1mdW5jdGlvbiBXKCl7dmFyIHU9cSgpO3JldHVybiJcbiI9PT11PyhWKyssSj0wKTp1P0orPXUubGVuZ3RoOkorKyx1JiYoSSs9dS5sZW5ndGgpLHV9dmFyIFg9e2RlZmF1bHQ6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSJcdCI6Y2FzZSJcdiI6Y2FzZSJcZiI6Y2FzZSIgIjpjYXNlIiAiOmNhc2UiXHVmZWZmIjpjYXNlIlxuIjpjYXNlIlxyIjpjYXNlIlx1MjAyOCI6Y2FzZSJcdTIwMjkiOnJldHVybiB2b2lkIFcoKTtjYXNlIi8iOnJldHVybiBXKCksdm9pZChUPSJjb21tZW50Iik7Y2FzZSB2b2lkIDA6cmV0dXJuIFcoKSxLKCJlb2YiKX1pZighVS5pc1NwYWNlU2VwYXJhdG9yKFIpKXJldHVybiBYW09dKCk7VygpfSxjb21tZW50OmZ1bmN0aW9uKCl7c3dpdGNoKFIpe2Nhc2UiKiI6cmV0dXJuIFcoKSx2b2lkKFQ9Im11bHRpTGluZUNvbW1lbnQiKTtjYXNlIi8iOnJldHVybiBXKCksdm9pZChUPSJzaW5nbGVMaW5lQ29tbWVudCIpfXRocm93IHJ1KFcoKSl9LG11bHRpTGluZUNvbW1lbnQ6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSIqIjpyZXR1cm4gVygpLHZvaWQoVD0ibXVsdGlMaW5lQ29tbWVudEFzdGVyaXNrIik7Y2FzZSB2b2lkIDA6dGhyb3cgcnUoVygpKX1XKCl9LG11bHRpTGluZUNvbW1lbnRBc3RlcmlzazpmdW5jdGlvbigpe3N3aXRjaChSKXtjYXNlIioiOnJldHVybiB2b2lkIFcoKTtjYXNlIi8iOnJldHVybiBXKCksdm9pZChUPSJkZWZhdWx0Iik7Y2FzZSB2b2lkIDA6dGhyb3cgcnUoVygpKX1XKCksVD0ibXVsdGlMaW5lQ29tbWVudCJ9LHNpbmdsZUxpbmVDb21tZW50OmZ1bmN0aW9uKCl7c3dpdGNoKFIpe2Nhc2UiXG4iOmNhc2UiXHIiOmNhc2UiXHUyMDI4IjpjYXNlIlx1MjAyOSI6cmV0dXJuIFcoKSx2b2lkKFQ9ImRlZmF1bHQiKTtjYXNlIHZvaWQgMDpyZXR1cm4gVygpLEsoImVvZiIpfVcoKX0sdmFsdWU6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSJ7IjpjYXNlIlsiOnJldHVybiBLKCJwdW5jdHVhdG9yIixXKCkpO2Nhc2UibiI6cmV0dXJuIFcoKSxRKCJ1bGwiKSxLKCJudWxsIixudWxsKTtjYXNlInQiOnJldHVybiBXKCksUSgicnVlIiksSygiYm9vbGVhbiIsITApO2Nhc2UiZiI6cmV0dXJuIFcoKSxRKCJhbHNlIiksSygiYm9vbGVhbiIsITEpO2Nhc2UiLSI6Y2FzZSIrIjpyZXR1cm4iLSI9PT1XKCkmJigkPS0xKSx2b2lkKFQ9InNpZ24iKTtjYXNlIi4iOnJldHVybiB6PVcoKSx2b2lkKFQ9ImRlY2ltYWxQb2ludExlYWRpbmciKTtjYXNlIjAiOnJldHVybiB6PVcoKSx2b2lkKFQ9Inplcm8iKTtjYXNlIjEiOmNhc2UiMiI6Y2FzZSIzIjpjYXNlIjQiOmNhc2UiNSI6Y2FzZSI2IjpjYXNlIjciOmNhc2UiOCI6Y2FzZSI5IjpyZXR1cm4gej1XKCksdm9pZChUPSJkZWNpbWFsSW50ZWdlciIpO2Nhc2UiSSI6cmV0dXJuIFcoKSxRKCJuZmluaXR5IiksSygibnVtZXJpYyIsMS8wKTtjYXNlIk4iOnJldHVybiBXKCksUSgiYU4iKSxLKCJudW1lcmljIixOYU4pO2Nhc2UnIic6Y2FzZSInIjpyZXR1cm4gSD0nIic9PT1XKCksej0iIix2b2lkKFQ9InN0cmluZyIpfXRocm93IHJ1KFcoKSl9LGlkZW50aWZpZXJOYW1lU3RhcnRFc2NhcGU6ZnVuY3Rpb24oKXtpZigidSIhPT1SKXRocm93IHJ1KFcoKSk7VygpO3ZhciB1PVkoKTtzd2l0Y2godSl7Y2FzZSIkIjpjYXNlIl8iOmJyZWFrO2RlZmF1bHQ6aWYoIVUuaXNJZFN0YXJ0Q2hhcih1KSl0aHJvdyBudSgpfXorPXUsVD0iaWRlbnRpZmllck5hbWUifSxpZGVudGlmaWVyTmFtZTpmdW5jdGlvbigpe3N3aXRjaChSKXtjYXNlIiQiOmNhc2UiXyI6Y2FzZSLigIwiOmNhc2Ui4oCNIjpyZXR1cm4gdm9pZCh6Kz1XKCkpO2Nhc2UiXFwiOnJldHVybiBXKCksdm9pZChUPSJpZGVudGlmaWVyTmFtZUVzY2FwZSIpfWlmKCFVLmlzSWRDb250aW51ZUNoYXIoUikpcmV0dXJuIEsoImlkZW50aWZpZXIiLHopO3orPVcoKX0saWRlbnRpZmllck5hbWVFc2NhcGU6ZnVuY3Rpb24oKXtpZigidSIhPT1SKXRocm93IHJ1KFcoKSk7VygpO3ZhciB1PVkoKTtzd2l0Y2godSl7Y2FzZSIkIjpjYXNlIl8iOmNhc2Ui4oCMIjpjYXNlIuKAjSI6YnJlYWs7ZGVmYXVsdDppZighVS5pc0lkQ29udGludWVDaGFyKHUpKXRocm93IG51KCl9eis9dSxUPSJpZGVudGlmaWVyTmFtZSJ9LHNpZ246ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSIuIjpyZXR1cm4gej1XKCksdm9pZChUPSJkZWNpbWFsUG9pbnRMZWFkaW5nIik7Y2FzZSIwIjpyZXR1cm4gej1XKCksdm9pZChUPSJ6ZXJvIik7Y2FzZSIxIjpjYXNlIjIiOmNhc2UiMyI6Y2FzZSI0IjpjYXNlIjUiOmNhc2UiNiI6Y2FzZSI3IjpjYXNlIjgiOmNhc2UiOSI6cmV0dXJuIHo9VygpLHZvaWQoVD0iZGVjaW1hbEludGVnZXIiKTtjYXNlIkkiOnJldHVybiBXKCksUSgibmZpbml0eSIpLEsoIm51bWVyaWMiLCQqKDEvMCkpO2Nhc2UiTiI6cmV0dXJuIFcoKSxRKCJhTiIpLEsoIm51bWVyaWMiLE5hTil9dGhyb3cgcnUoVygpKX0semVybzpmdW5jdGlvbigpe3N3aXRjaChSKXtjYXNlIi4iOnJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsUG9pbnQiKTtjYXNlImUiOmNhc2UiRSI6cmV0dXJuIHorPVcoKSx2b2lkKFQ9ImRlY2ltYWxFeHBvbmVudCIpO2Nhc2UieCI6Y2FzZSJYIjpyZXR1cm4geis9VygpLHZvaWQoVD0iaGV4YWRlY2ltYWwiKX1yZXR1cm4gSygibnVtZXJpYyIsMCokKX0sZGVjaW1hbEludGVnZXI6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSIuIjpyZXR1cm4geis9VygpLHZvaWQoVD0iZGVjaW1hbFBvaW50Iik7Y2FzZSJlIjpjYXNlIkUiOnJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsRXhwb25lbnQiKX1pZighVS5pc0RpZ2l0KFIpKXJldHVybiBLKCJudW1lcmljIiwkKk51bWJlcih6KSk7eis9VygpfSxkZWNpbWFsUG9pbnRMZWFkaW5nOmZ1bmN0aW9uKCl7aWYoVS5pc0RpZ2l0KFIpKXJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsRnJhY3Rpb24iKTt0aHJvdyBydShXKCkpfSxkZWNpbWFsUG9pbnQ6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSJlIjpjYXNlIkUiOnJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsRXhwb25lbnQiKX1yZXR1cm4gVS5pc0RpZ2l0KFIpPyh6Kz1XKCksdm9pZChUPSJkZWNpbWFsRnJhY3Rpb24iKSk6SygibnVtZXJpYyIsJCpOdW1iZXIoeikpfSxkZWNpbWFsRnJhY3Rpb246ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSJlIjpjYXNlIkUiOnJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsRXhwb25lbnQiKX1pZighVS5pc0RpZ2l0KFIpKXJldHVybiBLKCJudW1lcmljIiwkKk51bWJlcih6KSk7eis9VygpfSxkZWNpbWFsRXhwb25lbnQ6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSIrIjpjYXNlIi0iOnJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsRXhwb25lbnRTaWduIil9aWYoVS5pc0RpZ2l0KFIpKXJldHVybiB6Kz1XKCksdm9pZChUPSJkZWNpbWFsRXhwb25lbnRJbnRlZ2VyIik7dGhyb3cgcnUoVygpKX0sZGVjaW1hbEV4cG9uZW50U2lnbjpmdW5jdGlvbigpe2lmKFUuaXNEaWdpdChSKSlyZXR1cm4geis9VygpLHZvaWQoVD0iZGVjaW1hbEV4cG9uZW50SW50ZWdlciIpO3Rocm93IHJ1KFcoKSl9LGRlY2ltYWxFeHBvbmVudEludGVnZXI6ZnVuY3Rpb24oKXtpZighVS5pc0RpZ2l0KFIpKXJldHVybiBLKCJudW1lcmljIiwkKk51bWJlcih6KSk7eis9VygpfSxoZXhhZGVjaW1hbDpmdW5jdGlvbigpe2lmKFUuaXNIZXhEaWdpdChSKSlyZXR1cm4geis9VygpLHZvaWQoVD0iaGV4YWRlY2ltYWxJbnRlZ2VyIik7dGhyb3cgcnUoVygpKX0saGV4YWRlY2ltYWxJbnRlZ2VyOmZ1bmN0aW9uKCl7aWYoIVUuaXNIZXhEaWdpdChSKSlyZXR1cm4gSygibnVtZXJpYyIsJCpOdW1iZXIoeikpO3orPVcoKX0sc3RyaW5nOmZ1bmN0aW9uKCl7c3dpdGNoKFIpe2Nhc2UiXFwiOnJldHVybiBXKCksdm9pZCh6Kz1mdW5jdGlvbigpe3N3aXRjaChxKCkpe2Nhc2UiYiI6cmV0dXJuIFcoKSwiXGIiO2Nhc2UiZiI6cmV0dXJuIFcoKSwiXGYiO2Nhc2UibiI6cmV0dXJuIFcoKSwiXG4iO2Nhc2UiciI6cmV0dXJuIFcoKSwiXHIiO2Nhc2UidCI6cmV0dXJuIFcoKSwiXHQiO2Nhc2UidiI6cmV0dXJuIFcoKSwiXHYiO2Nhc2UiMCI6aWYoVygpLFUuaXNEaWdpdChxKCkpKXRocm93IHJ1KFcoKSk7cmV0dXJuIlwwIjtjYXNlIngiOnJldHVybiBXKCksZnVuY3Rpb24oKXt2YXIgdT0iIixEPXEoKTtpZighVS5pc0hleERpZ2l0KEQpKXRocm93IHJ1KFcoKSk7aWYodSs9VygpLEQ9cSgpLCFVLmlzSGV4RGlnaXQoRCkpdGhyb3cgcnUoVygpKTtyZXR1cm4gdSs9VygpLFN0cmluZy5mcm9tQ29kZVBvaW50KHBhcnNlSW50KHUsMTYpKX0oKTtjYXNlInUiOnJldHVybiBXKCksWSgpO2Nhc2UiXG4iOmNhc2UiXHUyMDI4IjpjYXNlIlx1MjAyOSI6cmV0dXJuIFcoKSwiIjtjYXNlIlxyIjpyZXR1cm4gVygpLCJcbiI9PT1xKCkmJlcoKSwiIjtjYXNlIjEiOmNhc2UiMiI6Y2FzZSIzIjpjYXNlIjQiOmNhc2UiNSI6Y2FzZSI2IjpjYXNlIjciOmNhc2UiOCI6Y2FzZSI5IjpjYXNlIHZvaWQgMDp0aHJvdyBydShXKCkpfXJldHVybiBXKCl9KCkpO2Nhc2UnIic6cmV0dXJuIEg/KFcoKSxLKCJzdHJpbmciLHopKTp2b2lkKHorPVcoKSk7Y2FzZSInIjpyZXR1cm4gSD92b2lkKHorPVcoKSk6KFcoKSxLKCJzdHJpbmciLHopKTtjYXNlIlxuIjpjYXNlIlxyIjp0aHJvdyBydShXKCkpO2Nhc2UiXHUyMDI4IjpjYXNlIlx1MjAyOSI6IWZ1bmN0aW9uKHUpe2NvbnNvbGUud2FybigiSlNPTjU6ICciK0Z1KHUpKyInIGluIHN0cmluZ3MgaXMgbm90IHZhbGlkIEVDTUFTY3JpcHQ7IGNvbnNpZGVyIGVzY2FwaW5nIil9KFIpO2JyZWFrO2Nhc2Ugdm9pZCAwOnRocm93IHJ1KFcoKSl9eis9VygpfSxzdGFydDpmdW5jdGlvbigpe3N3aXRjaChSKXtjYXNlInsiOmNhc2UiWyI6cmV0dXJuIEsoInB1bmN0dWF0b3IiLFcoKSl9VD0idmFsdWUifSxiZWZvcmVQcm9wZXJ0eU5hbWU6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSIkIjpjYXNlIl8iOnJldHVybiB6PVcoKSx2b2lkKFQ9ImlkZW50aWZpZXJOYW1lIik7Y2FzZSJcXCI6cmV0dXJuIFcoKSx2b2lkKFQ9ImlkZW50aWZpZXJOYW1lU3RhcnRFc2NhcGUiKTtjYXNlIn0iOnJldHVybiBLKCJwdW5jdHVhdG9yIixXKCkpO2Nhc2UnIic6Y2FzZSInIjpyZXR1cm4gSD0nIic9PT1XKCksdm9pZChUPSJzdHJpbmciKX1pZihVLmlzSWRTdGFydENoYXIoUikpcmV0dXJuIHorPVcoKSx2b2lkKFQ9ImlkZW50aWZpZXJOYW1lIik7dGhyb3cgcnUoVygpKX0sYWZ0ZXJQcm9wZXJ0eU5hbWU6ZnVuY3Rpb24oKXtpZigiOiI9PT1SKXJldHVybiBLKCJwdW5jdHVhdG9yIixXKCkpO3Rocm93IHJ1KFcoKSl9LGJlZm9yZVByb3BlcnR5VmFsdWU6ZnVuY3Rpb24oKXtUPSJ2YWx1ZSJ9LGFmdGVyUHJvcGVydHlWYWx1ZTpmdW5jdGlvbigpe3N3aXRjaChSKXtjYXNlIiwiOmNhc2UifSI6cmV0dXJuIEsoInB1bmN0dWF0b3IiLFcoKSl9dGhyb3cgcnUoVygpKX0sYmVmb3JlQXJyYXlWYWx1ZTpmdW5jdGlvbigpe2lmKCJdIj09PVIpcmV0dXJuIEsoInB1bmN0dWF0b3IiLFcoKSk7VD0idmFsdWUifSxhZnRlckFycmF5VmFsdWU6ZnVuY3Rpb24oKXtzd2l0Y2goUil7Y2FzZSIsIjpjYXNlIl0iOnJldHVybiBLKCJwdW5jdHVhdG9yIixXKCkpfXRocm93IHJ1KFcoKSl9LGVuZDpmdW5jdGlvbigpe3Rocm93IHJ1KFcoKSl9fTtmdW5jdGlvbiBLKHUsRCl7cmV0dXJue3R5cGU6dSx2YWx1ZTpELGxpbmU6Vixjb2x1bW46Sn19ZnVuY3Rpb24gUSh1KXtmb3IodmFyIEQ9MCxlPXU7RDxlLmxlbmd0aDtEKz0xKXt2YXIgcj1lW0RdO2lmKHEoKSE9PXIpdGhyb3cgcnUoVygpKTtXKCl9fWZ1bmN0aW9uIFkoKXtmb3IodmFyIHU9IiIsRD00O0QtLSA+MDspe3ZhciBlPXEoKTtpZighVS5pc0hleERpZ2l0KGUpKXRocm93IHJ1KFcoKSk7dSs9VygpfXJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChwYXJzZUludCh1LDE2KSl9dmFyIHV1PXtzdGFydDpmdW5jdGlvbigpe2lmKCJlb2YiPT09TS50eXBlKXRocm93IHR1KCk7RHUoKX0sYmVmb3JlUHJvcGVydHlOYW1lOmZ1bmN0aW9uKCl7c3dpdGNoKE0udHlwZSl7Y2FzZSJpZGVudGlmaWVyIjpjYXNlInN0cmluZyI6cmV0dXJuIGs9TS52YWx1ZSx2b2lkKE89ImFmdGVyUHJvcGVydHlOYW1lIik7Y2FzZSJwdW5jdHVhdG9yIjpyZXR1cm4gdm9pZCBldSgpO2Nhc2UiZW9mIjp0aHJvdyB0dSgpfX0sYWZ0ZXJQcm9wZXJ0eU5hbWU6ZnVuY3Rpb24oKXtpZigiZW9mIj09PU0udHlwZSl0aHJvdyB0dSgpO089ImJlZm9yZVByb3BlcnR5VmFsdWUifSxiZWZvcmVQcm9wZXJ0eVZhbHVlOmZ1bmN0aW9uKCl7aWYoImVvZiI9PT1NLnR5cGUpdGhyb3cgdHUoKTtEdSgpfSxiZWZvcmVBcnJheVZhbHVlOmZ1bmN0aW9uKCl7aWYoImVvZiI9PT1NLnR5cGUpdGhyb3cgdHUoKTsicHVuY3R1YXRvciIhPT1NLnR5cGV8fCJdIiE9PU0udmFsdWU/RHUoKTpldSgpfSxhZnRlclByb3BlcnR5VmFsdWU6ZnVuY3Rpb24oKXtpZigiZW9mIj09PU0udHlwZSl0aHJvdyB0dSgpO3N3aXRjaChNLnZhbHVlKXtjYXNlIiwiOnJldHVybiB2b2lkKE89ImJlZm9yZVByb3BlcnR5TmFtZSIpO2Nhc2UifSI6ZXUoKX19LGFmdGVyQXJyYXlWYWx1ZTpmdW5jdGlvbigpe2lmKCJlb2YiPT09TS50eXBlKXRocm93IHR1KCk7c3dpdGNoKE0udmFsdWUpe2Nhc2UiLCI6cmV0dXJuIHZvaWQoTz0iYmVmb3JlQXJyYXlWYWx1ZSIpO2Nhc2UiXSI6ZXUoKX19LGVuZDpmdW5jdGlvbigpe319O2Z1bmN0aW9uIER1KCl7dmFyIHU7c3dpdGNoKE0udHlwZSl7Y2FzZSJwdW5jdHVhdG9yIjpzd2l0Y2goTS52YWx1ZSl7Y2FzZSJ7Ijp1PXt9O2JyZWFrO2Nhc2UiWyI6dT1bXX1icmVhaztjYXNlIm51bGwiOmNhc2UiYm9vbGVhbiI6Y2FzZSJudW1lcmljIjpjYXNlInN0cmluZyI6dT1NLnZhbHVlfWlmKHZvaWQgMD09PUwpTD11O2Vsc2V7dmFyIEQ9altqLmxlbmd0aC0xXTtBcnJheS5pc0FycmF5KEQpP0QucHVzaCh1KTpPYmplY3QuZGVmaW5lUHJvcGVydHkoRCxrLHt2YWx1ZTp1LHdyaXRhYmxlOiEwLGVudW1lcmFibGU6ITAsY29uZmlndXJhYmxlOiEwfSl9aWYobnVsbCE9PXUmJiJvYmplY3QiPT10eXBlb2YgdSlqLnB1c2godSksTz1BcnJheS5pc0FycmF5KHUpPyJiZWZvcmVBcnJheVZhbHVlIjoiYmVmb3JlUHJvcGVydHlOYW1lIjtlbHNle3ZhciBlPWpbai5sZW5ndGgtMV07Tz1udWxsPT1lPyJlbmQiOkFycmF5LmlzQXJyYXkoZSk/ImFmdGVyQXJyYXlWYWx1ZSI6ImFmdGVyUHJvcGVydHlWYWx1ZSJ9fWZ1bmN0aW9uIGV1KCl7ai5wb3AoKTt2YXIgdT1qW2oubGVuZ3RoLTFdO089bnVsbD09dT8iZW5kIjpBcnJheS5pc0FycmF5KHUpPyJhZnRlckFycmF5VmFsdWUiOiJhZnRlclByb3BlcnR5VmFsdWUifWZ1bmN0aW9uIHJ1KHUpe3JldHVybiBDdSh2b2lkIDA9PT11PyJKU09ONTogaW52YWxpZCBlbmQgb2YgaW5wdXQgYXQgIitWKyI6IitKOiJKU09ONTogaW52YWxpZCBjaGFyYWN0ZXIgJyIrRnUodSkrIicgYXQgIitWKyI6IitKKX1mdW5jdGlvbiB0dSgpe3JldHVybiBDdSgiSlNPTjU6IGludmFsaWQgZW5kIG9mIGlucHV0IGF0ICIrVisiOiIrSil9ZnVuY3Rpb24gbnUoKXtyZXR1cm4gQ3UoIkpTT041OiBpbnZhbGlkIGlkZW50aWZpZXIgY2hhcmFjdGVyIGF0ICIrVisiOiIrKEotPTUpKX1mdW5jdGlvbiBGdSh1KXt2YXIgRD17IiciOiJcXCciLCciJzonXFwiJywiXFwiOiJcXFxcIiwiXGIiOiJcXGIiLCJcZiI6IlxcZiIsIlxuIjoiXFxuIiwiXHIiOiJcXHIiLCJcdCI6IlxcdCIsIlx2IjoiXFx2IiwiXDAiOiJcXDAiLCJcdTIwMjgiOiJcXHUyMDI4IiwiXHUyMDI5IjoiXFx1MjAyOSJ9O2lmKERbdV0pcmV0dXJuIERbdV07aWYodTwiICIpe3ZhciBlPXUuY2hhckNvZGVBdCgwKS50b1N0cmluZygxNik7cmV0dXJuIlxceCIrKCIwMCIrZSkuc3Vic3RyaW5nKGUubGVuZ3RoKX1yZXR1cm4gdX1mdW5jdGlvbiBDdSh1KXt2YXIgRD1uZXcgU3ludGF4RXJyb3IodSk7cmV0dXJuIEQubGluZU51bWJlcj1WLEQuY29sdW1uTnVtYmVyPUosRH1yZXR1cm57cGFyc2U6ZnVuY3Rpb24odSxEKXtfPVN0cmluZyh1KSxPPSJzdGFydCIsaj1bXSxJPTAsVj0xLEo9MCxNPXZvaWQgMCxrPXZvaWQgMCxMPXZvaWQgMDtkb3tNPVooKSx1dVtPXSgpfXdoaWxlKCJlb2YiIT09TS50eXBlKTtyZXR1cm4iZnVuY3Rpb24iPT10eXBlb2YgRD9mdW5jdGlvbiB1KEQsZSxyKXt2YXIgdD1EW2VdO2lmKG51bGwhPXQmJiJvYmplY3QiPT10eXBlb2YgdClpZihBcnJheS5pc0FycmF5KHQpKWZvcih2YXIgbj0wO248dC5sZW5ndGg7bisrKXt2YXIgRj1TdHJpbmcobiksQz11KHQsRixyKTt2b2lkIDA9PT1DP2RlbGV0ZSB0W0ZdOk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LEYse3ZhbHVlOkMsd3JpdGFibGU6ITAsZW51bWVyYWJsZTohMCxjb25maWd1cmFibGU6ITB9KX1lbHNlIGZvcih2YXIgQSBpbiB0KXt2YXIgaT11KHQsQSxyKTt2b2lkIDA9PT1pP2RlbGV0ZSB0W0FdOk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LEEse3ZhbHVlOmksd3JpdGFibGU6ITAsZW51bWVyYWJsZTohMCxjb25maWd1cmFibGU6ITB9KX1yZXR1cm4gci5jYWxsKEQsZSx0KX0oeyIiOkx9LCIiLEQpOkx9LHN0cmluZ2lmeTpmdW5jdGlvbih1LEQsZSl7dmFyIHIsdCxuLEY9W10sQz0iIixBPSIiO2lmKG51bGw9PUR8fCJvYmplY3QiIT10eXBlb2YgRHx8QXJyYXkuaXNBcnJheShEKXx8KGU9RC5zcGFjZSxuPUQucXVvdGUsRD1ELnJlcGxhY2VyKSwiZnVuY3Rpb24iPT10eXBlb2YgRCl0PUQ7ZWxzZSBpZihBcnJheS5pc0FycmF5KEQpKXtyPVtdO2Zvcih2YXIgaT0wLEU9RDtpPEUubGVuZ3RoO2krPTEpe3ZhciBvPUVbaV0sYT12b2lkIDA7InN0cmluZyI9PXR5cGVvZiBvP2E9bzooIm51bWJlciI9PXR5cGVvZiBvfHxvIGluc3RhbmNlb2YgU3RyaW5nfHxvIGluc3RhbmNlb2YgTnVtYmVyKSYmKGE9U3RyaW5nKG8pKSx2b2lkIDAhPT1hJiZyLmluZGV4T2YoYSk8MCYmci5wdXNoKGEpfX1yZXR1cm4gZSBpbnN0YW5jZW9mIE51bWJlcj9lPU51bWJlcihlKTplIGluc3RhbmNlb2YgU3RyaW5nJiYoZT1TdHJpbmcoZSkpLCJudW1iZXIiPT10eXBlb2YgZT9lPjAmJihlPU1hdGgubWluKDEwLE1hdGguZmxvb3IoZSkpLEE9IiAgICAgICAgICAiLnN1YnN0cigwLGUpKToic3RyaW5nIj09dHlwZW9mIGUmJihBPWUuc3Vic3RyKDAsMTApKSxjKCIiLHsiIjp1fSk7ZnVuY3Rpb24gYyh1LEQpe3ZhciBlPURbdV07c3dpdGNoKG51bGwhPWUmJigiZnVuY3Rpb24iPT10eXBlb2YgZS50b0pTT041P2U9ZS50b0pTT041KHUpOiJmdW5jdGlvbiI9PXR5cGVvZiBlLnRvSlNPTiYmKGU9ZS50b0pTT04odSkpKSx0JiYoZT10LmNhbGwoRCx1LGUpKSxlIGluc3RhbmNlb2YgTnVtYmVyP2U9TnVtYmVyKGUpOmUgaW5zdGFuY2VvZiBTdHJpbmc/ZT1TdHJpbmcoZSk6ZSBpbnN0YW5jZW9mIEJvb2xlYW4mJihlPWUudmFsdWVPZigpKSxlKXtjYXNlIG51bGw6cmV0dXJuIm51bGwiO2Nhc2UhMDpyZXR1cm4idHJ1ZSI7Y2FzZSExOnJldHVybiJmYWxzZSJ9cmV0dXJuInN0cmluZyI9PXR5cGVvZiBlP0IoZSk6Im51bWJlciI9PXR5cGVvZiBlP1N0cmluZyhlKToib2JqZWN0Ij09dHlwZW9mIGU/QXJyYXkuaXNBcnJheShlKT9mdW5jdGlvbih1KXtpZihGLmluZGV4T2YodSk+PTApdGhyb3cgVHlwZUVycm9yKCJDb252ZXJ0aW5nIGNpcmN1bGFyIHN0cnVjdHVyZSB0byBKU09ONSIpO0YucHVzaCh1KTt2YXIgRD1DO0MrPUE7Zm9yKHZhciBlLHI9W10sdD0wO3Q8dS5sZW5ndGg7dCsrKXt2YXIgbj1jKFN0cmluZyh0KSx1KTtyLnB1c2godm9pZCAwIT09bj9uOiJudWxsIil9aWYoMD09PXIubGVuZ3RoKWU9IltdIjtlbHNlIGlmKCIiPT09QSl7dmFyIGk9ci5qb2luKCIsIik7ZT0iWyIraSsiXSJ9ZWxzZXt2YXIgRT0iLFxuIitDLG89ci5qb2luKEUpO2U9IltcbiIrQytvKyIsXG4iK0QrIl0ifXJldHVybiBGLnBvcCgpLEM9RCxlfShlKTpmdW5jdGlvbih1KXtpZihGLmluZGV4T2YodSk+PTApdGhyb3cgVHlwZUVycm9yKCJDb252ZXJ0aW5nIGNpcmN1bGFyIHN0cnVjdHVyZSB0byBKU09ONSIpO0YucHVzaCh1KTt2YXIgRD1DO0MrPUE7Zm9yKHZhciBlLHQsbj1yfHxPYmplY3Qua2V5cyh1KSxpPVtdLEU9MCxvPW47RTxvLmxlbmd0aDtFKz0xKXt2YXIgYT1vW0VdLEI9YyhhLHUpO2lmKHZvaWQgMCE9PUIpe3ZhciBmPXMoYSkrIjoiOyIiIT09QSYmKGYrPSIgIiksZis9QixpLnB1c2goZil9fWlmKDA9PT1pLmxlbmd0aCllPSJ7fSI7ZWxzZSBpZigiIj09PUEpdD1pLmpvaW4oIiwiKSxlPSJ7Iit0KyJ9IjtlbHNle3ZhciBsPSIsXG4iK0M7dD1pLmpvaW4obCksZT0ie1xuIitDK3QrIixcbiIrRCsifSJ9cmV0dXJuIEYucG9wKCksQz1ELGV9KGUpOnZvaWQgMH1mdW5jdGlvbiBCKHUpe2Zvcih2YXIgRD17IiciOi4xLCciJzouMn0sZT17IiciOiJcXCciLCciJzonXFwiJywiXFwiOiJcXFxcIiwiXGIiOiJcXGIiLCJcZiI6IlxcZiIsIlxuIjoiXFxuIiwiXHIiOiJcXHIiLCJcdCI6IlxcdCIsIlx2IjoiXFx2IiwiXDAiOiJcXDAiLCJcdTIwMjgiOiJcXHUyMDI4IiwiXHUyMDI5IjoiXFx1MjAyOSJ9LHI9IiIsdD0wO3Q8dS5sZW5ndGg7dCsrKXt2YXIgRj11W3RdO3N3aXRjaChGKXtjYXNlIiciOmNhc2UnIic6RFtGXSsrLHIrPUY7Y29udGludWU7Y2FzZSJcMCI6aWYoVS5pc0RpZ2l0KHVbdCsxXSkpe3IrPSJcXHgwMCI7Y29udGludWV9fWlmKGVbRl0pcis9ZVtGXTtlbHNlIGlmKEY8IiAiKXt2YXIgQz1GLmNoYXJDb2RlQXQoMCkudG9TdHJpbmcoMTYpO3IrPSJcXHgiKygiMDAiK0MpLnN1YnN0cmluZyhDLmxlbmd0aCl9ZWxzZSByKz1GfXZhciBBPW58fE9iamVjdC5rZXlzKEQpLnJlZHVjZShmdW5jdGlvbih1LGUpe3JldHVybiBEW3VdPERbZV0/dTplfSk7cmV0dXJuIEErKHI9ci5yZXBsYWNlKG5ldyBSZWdFeHAoQSwiZyIpLGVbQV0pKStBfWZ1bmN0aW9uIHModSl7aWYoMD09PXUubGVuZ3RoKXJldHVybiBCKHUpO3ZhciBEPVN0cmluZy5mcm9tQ29kZVBvaW50KHUuY29kZVBvaW50QXQoMCkpO2lmKCFVLmlzSWRTdGFydENoYXIoRCkpcmV0dXJuIEIodSk7Zm9yKHZhciBlPUQubGVuZ3RoO2U8dS5sZW5ndGg7ZSsrKWlmKCFVLmlzSWRDb250aW51ZUNoYXIoU3RyaW5nLmZyb21Db2RlUG9pbnQodS5jb2RlUG9pbnRBdChlKSkpKXJldHVybiBCKHUpO3JldHVybiB1fX19fSk7`;
|
|
153536
|
-
//#endregion
|
|
153537
154689
|
//#region ../../node_modules/.pnpm/fflate@0.8.3/node_modules/fflate/esm/browser.js
|
|
153538
154690
|
var ch2 = {};
|
|
153539
154691
|
var wk = (function(c, id, msg, transfer, cb) {
|
|
@@ -155109,12 +156261,33 @@ var SampleNotFoundError = class SampleNotFoundError extends Error {
|
|
|
155109
156261
|
}
|
|
155110
156262
|
};
|
|
155111
156263
|
/**
|
|
156264
|
+
* Synthesize an EvalHeader from a `_journal/start.json` payload.
|
|
156265
|
+
*
|
|
156266
|
+
* `header.json` is only written at end-of-eval, so while a log is in
|
|
156267
|
+
* progress the viewer falls back to `start.json` (which carries the
|
|
156268
|
+
* EvalSpec + EvalPlan). The Python side does the analogous lift via
|
|
156269
|
+
* `EvalLog.recompute_tags_and_metadata` on the model validator —
|
|
156270
|
+
* `log.tags` / `log.metadata` derive from `eval.tags` / `eval.metadata`
|
|
156271
|
+
* until `log_updates` adds edits on top. Mirror that here so a running
|
|
156272
|
+
* log's chips and metadata still render in the viewer.
|
|
156273
|
+
*
|
|
156274
|
+
* Exported for unit testing.
|
|
156275
|
+
*/
|
|
156276
|
+
var headerFromLogStart = (start) => ({
|
|
156277
|
+
status: "started",
|
|
156278
|
+
eval: start.eval,
|
|
156279
|
+
plan: start.plan,
|
|
156280
|
+
tags: start.eval?.tags ?? [],
|
|
156281
|
+
metadata: start.eval?.metadata ?? {}
|
|
156282
|
+
});
|
|
156283
|
+
/**
|
|
155112
156284
|
* Opens a remote log file and provides methods to read its contents.
|
|
155113
156285
|
*/
|
|
155114
156286
|
var openRemoteLogFile = async (api, url, concurrency) => {
|
|
155115
156287
|
const queue = new AsyncQueue(concurrency);
|
|
155116
156288
|
const logInfo = await api.get_log_info(url);
|
|
155117
156289
|
const directUrl = logInfo.direct_url;
|
|
156290
|
+
const initialEtag = logInfo.etag ?? void 0;
|
|
155118
156291
|
const fetchBytes = async (_url, start, end) => {
|
|
155119
156292
|
if (directUrl) try {
|
|
155120
156293
|
return await fetchRange(directUrl, start, end);
|
|
@@ -155174,14 +156347,7 @@ var openRemoteLogFile = async (api, url, concurrency) => {
|
|
|
155174
156347
|
*/
|
|
155175
156348
|
const readHeader = async () => {
|
|
155176
156349
|
if (remoteZipFile.centralDirectory.has("header.json")) return await readJSONFile("header.json");
|
|
155177
|
-
else
|
|
155178
|
-
const evalSpec = await readJSONFile("_journal/start.json");
|
|
155179
|
-
return {
|
|
155180
|
-
status: "started",
|
|
155181
|
-
eval: evalSpec.eval,
|
|
155182
|
-
plan: evalSpec.plan
|
|
155183
|
-
};
|
|
155184
|
-
}
|
|
156350
|
+
else return headerFromLogStart(await readJSONFile("_journal/start.json"));
|
|
155185
156351
|
};
|
|
155186
156352
|
const readEvalBasicInfo = async () => {
|
|
155187
156353
|
return toLogPreview(await readHeader());
|
|
@@ -155225,7 +156391,8 @@ var openRemoteLogFile = async (api, url, concurrency) => {
|
|
|
155225
156391
|
tags: header.tags,
|
|
155226
156392
|
metadata: header.metadata,
|
|
155227
156393
|
log_updates: header.log_updates,
|
|
155228
|
-
sampleSummaries
|
|
156394
|
+
sampleSummaries,
|
|
156395
|
+
etag: initialEtag
|
|
155229
156396
|
};
|
|
155230
156397
|
},
|
|
155231
156398
|
readSample,
|
|
@@ -155438,6 +156605,7 @@ var clientApi = (api, log_file, debug = false) => {
|
|
|
155438
156605
|
return api.eval_pending_samples(log_file, etag);
|
|
155439
156606
|
};
|
|
155440
156607
|
const sampleDataPathByLog = /* @__PURE__ */ new Map();
|
|
156608
|
+
const editEtagByLog = /* @__PURE__ */ new Map();
|
|
155441
156609
|
const get_log_sample_data = async (log_file, id, epoch, last_event, last_attachment, last_message_pool, last_call_pool) => {
|
|
155442
156610
|
if (!api.eval_log_sample_data) throw new Error("API doesn't supported streamed sample data");
|
|
155443
156611
|
let path = sampleDataPathByLog.get(log_file);
|
|
@@ -155477,7 +156645,11 @@ var clientApi = (api, log_file, debug = false) => {
|
|
|
155477
156645
|
return api.get_flow(dir);
|
|
155478
156646
|
}),
|
|
155479
156647
|
get_log_summaries: middleware("get_log_summaries", get_log_summaries),
|
|
155480
|
-
get_log_details: middleware("get_log_details",
|
|
156648
|
+
get_log_details: middleware("get_log_details", async (log_file, cached) => {
|
|
156649
|
+
const result = await get_log_details(log_file, cached);
|
|
156650
|
+
if (result.etag) editEtagByLog.set(log_file, result.etag);
|
|
156651
|
+
return result;
|
|
156652
|
+
}),
|
|
155481
156653
|
get_log_sample: middleware("get_log_sample", get_log_sample),
|
|
155482
156654
|
open_log_file: middleware("open_log_file", (log_file, log_dir) => {
|
|
155483
156655
|
return api.open_log_file(log_file, log_dir);
|
|
@@ -155492,7 +156664,22 @@ var clientApi = (api, log_file, debug = false) => {
|
|
|
155492
156664
|
return api.log_message(log_file, message);
|
|
155493
156665
|
}),
|
|
155494
156666
|
get_log_pending_samples: api.eval_pending_samples ? middleware("get_log_pending_samples", get_log_pending_samples) : void 0,
|
|
155495
|
-
get_log_sample_data: api.eval_log_sample_data ? middleware("get_log_sample_data", get_log_sample_data) : void 0
|
|
156667
|
+
get_log_sample_data: api.eval_log_sample_data ? middleware("get_log_sample_data", get_log_sample_data) : void 0,
|
|
156668
|
+
get_user_info: api.get_user_info ? middleware("get_user_info", () => api.get_user_info()) : void 0,
|
|
156669
|
+
edit_log: api.edit_log ? middleware("edit_log", async (log_file, update, if_match_etag) => {
|
|
156670
|
+
const effective = if_match_etag ?? editEtagByLog.get(log_file);
|
|
156671
|
+
const result = await api.edit_log(log_file, update, effective);
|
|
156672
|
+
if (result.etag) editEtagByLog.set(log_file, result.etag);
|
|
156673
|
+
if (current_path === log_file) {
|
|
156674
|
+
current_log = void 0;
|
|
156675
|
+
current_path = void 0;
|
|
156676
|
+
}
|
|
156677
|
+
if (loadedEvalFile.file === log_file) {
|
|
156678
|
+
loadedEvalFile.file = void 0;
|
|
156679
|
+
loadedEvalFile.remoteLog = void 0;
|
|
156680
|
+
}
|
|
156681
|
+
return result;
|
|
156682
|
+
}) : void 0
|
|
155496
156683
|
};
|
|
155497
156684
|
};
|
|
155498
156685
|
var debugMiddleware = (name, _fn, args, result) => {
|
|
@@ -155759,123 +156946,6 @@ function staticHttpApiForLog(logInfo) {
|
|
|
155759
156946
|
};
|
|
155760
156947
|
}
|
|
155761
156948
|
//#endregion
|
|
155762
|
-
//#region src/client/api/view-server/request.ts
|
|
155763
|
-
var ApiError = class extends Error {
|
|
155764
|
-
status;
|
|
155765
|
-
constructor(status, message) {
|
|
155766
|
-
super(message);
|
|
155767
|
-
this.status = status;
|
|
155768
|
-
}
|
|
155769
|
-
};
|
|
155770
|
-
function serverRequestApi(baseUrl, getHeaders) {
|
|
155771
|
-
const apiUrl = baseUrl || "";
|
|
155772
|
-
function buildApiUrl(path) {
|
|
155773
|
-
if (!apiUrl) return path;
|
|
155774
|
-
return (apiUrl.endsWith("/") ? apiUrl.slice(0, -1) : apiUrl) + (path.startsWith("/") ? path : `/${path}`);
|
|
155775
|
-
}
|
|
155776
|
-
function isApiCrossOrigin() {
|
|
155777
|
-
try {
|
|
155778
|
-
return Boolean(apiUrl && new URL(apiUrl).origin !== window.location.origin);
|
|
155779
|
-
} catch (error) {
|
|
155780
|
-
return false;
|
|
155781
|
-
}
|
|
155782
|
-
}
|
|
155783
|
-
const fetchType = async (method, path, request) => {
|
|
155784
|
-
const url = buildApiUrl(path);
|
|
155785
|
-
const responseHeaders = {
|
|
155786
|
-
Accept: "application/json",
|
|
155787
|
-
Pragma: "no-cache",
|
|
155788
|
-
Expires: "0",
|
|
155789
|
-
"Cache-Control": "no-cache",
|
|
155790
|
-
...request.headers
|
|
155791
|
-
};
|
|
155792
|
-
if (getHeaders) {
|
|
155793
|
-
const globalHeaders = await getHeaders();
|
|
155794
|
-
Object.assign(responseHeaders, globalHeaders);
|
|
155795
|
-
}
|
|
155796
|
-
if (request.body) responseHeaders["Content-Type"] = "application/json";
|
|
155797
|
-
const response = await fetch(url, {
|
|
155798
|
-
method,
|
|
155799
|
-
headers: responseHeaders,
|
|
155800
|
-
body: request.body,
|
|
155801
|
-
credentials: isApiCrossOrigin() ? "include" : "same-origin"
|
|
155802
|
-
});
|
|
155803
|
-
if (!response.ok) {
|
|
155804
|
-
const errorResponse = request.handleError?.(response.status);
|
|
155805
|
-
if (errorResponse) return {
|
|
155806
|
-
raw: response.statusText,
|
|
155807
|
-
parsed: errorResponse
|
|
155808
|
-
};
|
|
155809
|
-
const message = await response.text() || response.statusText;
|
|
155810
|
-
throw new ApiError(response.status, `API Error ${response.status}: ${message}`);
|
|
155811
|
-
}
|
|
155812
|
-
const text = await response.text();
|
|
155813
|
-
return {
|
|
155814
|
-
parsed: await (request.parse || asyncJsonParse)(text),
|
|
155815
|
-
raw: text
|
|
155816
|
-
};
|
|
155817
|
-
};
|
|
155818
|
-
const fetchString = async (method, path, headers, body) => {
|
|
155819
|
-
const url = buildApiUrl(path);
|
|
155820
|
-
const requestHeaders = {
|
|
155821
|
-
Accept: "application/json",
|
|
155822
|
-
Pragma: "no-cache",
|
|
155823
|
-
Expires: "0",
|
|
155824
|
-
"Cache-Control": "no-cache",
|
|
155825
|
-
...headers
|
|
155826
|
-
};
|
|
155827
|
-
if (getHeaders) {
|
|
155828
|
-
const globalHeaders = await getHeaders();
|
|
155829
|
-
Object.assign(requestHeaders, globalHeaders);
|
|
155830
|
-
}
|
|
155831
|
-
if (body) requestHeaders["Content-Type"] = "application/json";
|
|
155832
|
-
const response = await fetch(url, {
|
|
155833
|
-
method,
|
|
155834
|
-
headers: requestHeaders,
|
|
155835
|
-
body,
|
|
155836
|
-
credentials: isApiCrossOrigin() ? "include" : "same-origin"
|
|
155837
|
-
});
|
|
155838
|
-
if (response.ok) {
|
|
155839
|
-
const text = await response.text();
|
|
155840
|
-
return {
|
|
155841
|
-
parsed: await asyncJsonParse(text),
|
|
155842
|
-
raw: text
|
|
155843
|
-
};
|
|
155844
|
-
}
|
|
155845
|
-
const message = await response.text() || response.statusText;
|
|
155846
|
-
throw new ApiError(response.status, `HTTP ${response.status}: ${message}`);
|
|
155847
|
-
};
|
|
155848
|
-
const fetchBytes = async (method, path) => {
|
|
155849
|
-
const url = buildApiUrl(path);
|
|
155850
|
-
const headers = {
|
|
155851
|
-
Accept: "application/octet-stream",
|
|
155852
|
-
Pragma: "no-cache",
|
|
155853
|
-
Expires: "0",
|
|
155854
|
-
"Cache-Control": "no-cache"
|
|
155855
|
-
};
|
|
155856
|
-
if (getHeaders) {
|
|
155857
|
-
const globalHeaders = await getHeaders();
|
|
155858
|
-
Object.assign(headers, globalHeaders);
|
|
155859
|
-
}
|
|
155860
|
-
const response = await fetch(url, {
|
|
155861
|
-
method,
|
|
155862
|
-
headers,
|
|
155863
|
-
credentials: isApiCrossOrigin() ? "include" : "same-origin"
|
|
155864
|
-
});
|
|
155865
|
-
if (!response.ok) {
|
|
155866
|
-
const message = await response.text() || response.statusText;
|
|
155867
|
-
throw new ApiError(response.status, `HTTP ${response.status}: ${message}`);
|
|
155868
|
-
}
|
|
155869
|
-
const buffer = await response.arrayBuffer();
|
|
155870
|
-
return new Uint8Array(buffer);
|
|
155871
|
-
};
|
|
155872
|
-
return {
|
|
155873
|
-
fetchString,
|
|
155874
|
-
fetchBytes,
|
|
155875
|
-
fetchType
|
|
155876
|
-
};
|
|
155877
|
-
}
|
|
155878
|
-
//#endregion
|
|
155879
156949
|
//#region src/client/remote/remotePendingSampleData.ts
|
|
155880
156950
|
var SEGMENT_CAP_PER_CALL = 25;
|
|
155881
156951
|
/**
|
|
@@ -156114,6 +157184,41 @@ function viewServerApi(options = {}) {
|
|
|
156114
157184
|
has_more: direct.has_more
|
|
156115
157185
|
};
|
|
156116
157186
|
};
|
|
157187
|
+
const edit_log = async (log_file, update, if_match_etag) => {
|
|
157188
|
+
const baseUrl = apiBaseUrl || "/api";
|
|
157189
|
+
const path = `/log-edit/${encodeURIComponent(log_file)}`;
|
|
157190
|
+
const url = baseUrl ? `${baseUrl.replace(/\/$/, "")}${path}` : path;
|
|
157191
|
+
const headers = {
|
|
157192
|
+
Accept: "application/json",
|
|
157193
|
+
"Content-Type": "application/json"
|
|
157194
|
+
};
|
|
157195
|
+
if (if_match_etag) headers["If-Match"] = if_match_etag;
|
|
157196
|
+
if (headerProvider) Object.assign(headers, await headerProvider());
|
|
157197
|
+
const isCrossOrigin = Boolean(apiBaseUrl && (() => {
|
|
157198
|
+
try {
|
|
157199
|
+
return new URL(apiBaseUrl).origin !== window.location.origin;
|
|
157200
|
+
} catch {
|
|
157201
|
+
return false;
|
|
157202
|
+
}
|
|
157203
|
+
})());
|
|
157204
|
+
const response = await fetch(url, {
|
|
157205
|
+
method: "POST",
|
|
157206
|
+
headers,
|
|
157207
|
+
body: JSON.stringify(update),
|
|
157208
|
+
credentials: isCrossOrigin ? "include" : "same-origin"
|
|
157209
|
+
});
|
|
157210
|
+
if (!response.ok) {
|
|
157211
|
+
const message = unwrapFastapiDetail(await response.text()) || response.statusText;
|
|
157212
|
+
throw new ApiError(response.status, message);
|
|
157213
|
+
}
|
|
157214
|
+
return {
|
|
157215
|
+
log: await asyncJsonParse(await response.text()),
|
|
157216
|
+
etag: response.headers.get("ETag") ?? void 0
|
|
157217
|
+
};
|
|
157218
|
+
};
|
|
157219
|
+
const get_user_info = async () => {
|
|
157220
|
+
return (await requestApi.fetchString("GET", "/user-info")).parsed ?? {};
|
|
157221
|
+
};
|
|
156117
157222
|
const download_log = async (log_file) => {
|
|
156118
157223
|
const url = `${apiBaseUrl || "/api"}/log-download/${encodeURIComponent(log_file)}`;
|
|
156119
157224
|
const link = document.createElement("a");
|
|
@@ -156140,10 +157245,12 @@ function viewServerApi(options = {}) {
|
|
|
156140
157245
|
open_log_file: async () => {},
|
|
156141
157246
|
eval_pending_samples,
|
|
156142
157247
|
eval_log_sample_data,
|
|
156143
|
-
eval_log_sample_data_direct
|
|
157248
|
+
eval_log_sample_data_direct,
|
|
157249
|
+
edit_log,
|
|
157250
|
+
get_user_info
|
|
156144
157251
|
};
|
|
156145
157252
|
}
|
|
156146
157253
|
//#endregion
|
|
156147
|
-
export { App, clientApi, viewServerApi as createViewServerApi, initializeStore, staticHttpApi as simpleHttpApi, useLogSelection, useSelectedSampleSummary, useSelectedScores };
|
|
157254
|
+
export { App, clientApi, viewServerApi as createViewServerApi, initializeStore, staticHttpApi as simpleHttpApi, useLogSelection, useScrollDirection, useSelectedSampleSummary, useSelectedScores };
|
|
156148
157255
|
|
|
156149
157256
|
//# sourceMappingURL=index.js.map
|