@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.
Files changed (68) hide show
  1. package/lib/index.js +1705 -598
  2. package/lib/index.js.map +1 -1
  3. package/lib/src/app/appearance/icons.d.ts +2 -0
  4. package/lib/src/app/appearance/icons.d.ts.map +1 -1
  5. package/lib/src/app/log-list/LogsPanel.d.ts.map +1 -1
  6. package/lib/src/app/log-list/grid/LogListGrid.d.ts.map +1 -1
  7. package/lib/src/app/log-list/grid/columns/hooks.d.ts.map +1 -1
  8. package/lib/src/app/log-list/grid/columns/types.d.ts +1 -0
  9. package/lib/src/app/log-list/grid/columns/types.d.ts.map +1 -1
  10. package/lib/src/app/log-view/LogView.d.ts.map +1 -1
  11. package/lib/src/app/log-view/tabs/TaskTab.d.ts.map +1 -1
  12. package/lib/src/app/log-view/title-view/AutogrowText.d.ts +10 -0
  13. package/lib/src/app/log-view/title-view/AutogrowText.d.ts.map +1 -0
  14. package/lib/src/app/log-view/title-view/ChangeSummary.d.ts +9 -0
  15. package/lib/src/app/log-view/title-view/ChangeSummary.d.ts.map +1 -0
  16. package/lib/src/app/log-view/title-view/EditButton.d.ts +10 -0
  17. package/lib/src/app/log-view/title-view/EditButton.d.ts.map +1 -0
  18. package/lib/src/app/log-view/title-view/EditMetadataDialog.d.ts +47 -0
  19. package/lib/src/app/log-view/title-view/EditMetadataDialog.d.ts.map +1 -0
  20. package/lib/src/app/log-view/title-view/EditTagsDialog.d.ts +11 -0
  21. package/lib/src/app/log-view/title-view/EditTagsDialog.d.ts.map +1 -0
  22. package/lib/src/app/log-view/title-view/PrimaryBar.d.ts +1 -0
  23. package/lib/src/app/log-view/title-view/PrimaryBar.d.ts.map +1 -1
  24. package/lib/src/app/log-view/title-view/ProvenanceFields.d.ts +11 -0
  25. package/lib/src/app/log-view/title-view/ProvenanceFields.d.ts.map +1 -0
  26. package/lib/src/app/log-view/title-view/TagChip.d.ts +10 -0
  27. package/lib/src/app/log-view/title-view/TagChip.d.ts.map +1 -0
  28. package/lib/src/app/log-view/title-view/TagStrip.d.ts +40 -0
  29. package/lib/src/app/log-view/title-view/TagStrip.d.ts.map +1 -0
  30. package/lib/src/app/log-view/title-view/TagsField.d.ts +21 -0
  31. package/lib/src/app/log-view/title-view/TagsField.d.ts.map +1 -0
  32. package/lib/src/app/log-view/title-view/TitleView.d.ts +1 -0
  33. package/lib/src/app/log-view/title-view/TitleView.d.ts.map +1 -1
  34. package/lib/src/app/log-view/title-view/editErrors.d.ts +2 -0
  35. package/lib/src/app/log-view/title-view/editErrors.d.ts.map +1 -0
  36. package/lib/src/app/plan/PlanCard.d.ts.map +1 -1
  37. package/lib/src/app/samples/status/sampleStatus.d.ts.map +1 -1
  38. package/lib/src/app/samples-panel/SamplesPanel.d.ts.map +1 -1
  39. package/lib/src/app/shared/samples-grid/columns.d.ts.map +1 -1
  40. package/lib/src/client/api/client-api.d.ts.map +1 -1
  41. package/lib/src/client/api/types.d.ts +13 -0
  42. package/lib/src/client/api/types.d.ts.map +1 -1
  43. package/lib/src/client/api/view-server/api-view-server.d.ts.map +1 -1
  44. package/lib/src/client/api/view-server/request.d.ts +14 -0
  45. package/lib/src/client/api/view-server/request.d.ts.map +1 -1
  46. package/lib/src/client/api/vscode/api-vscode.d.ts.map +1 -1
  47. package/lib/src/client/api/vscode/jsonrpc.d.ts +2 -0
  48. package/lib/src/client/api/vscode/jsonrpc.d.ts.map +1 -1
  49. package/lib/src/client/database/service.d.ts +1 -0
  50. package/lib/src/client/database/service.d.ts.map +1 -1
  51. package/lib/src/client/remote/remoteLogFile.d.ts +21 -2
  52. package/lib/src/client/remote/remoteLogFile.d.ts.map +1 -1
  53. package/lib/src/components/Modal.d.ts +2 -0
  54. package/lib/src/components/Modal.d.ts.map +1 -1
  55. package/lib/src/index.d.ts +10 -0
  56. package/lib/src/index.d.ts.map +1 -1
  57. package/lib/src/state/clientEvents.d.ts +1 -2
  58. package/lib/src/state/clientEvents.d.ts.map +1 -1
  59. package/lib/src/state/clientEventsService.d.ts +2 -5
  60. package/lib/src/state/clientEventsService.d.ts.map +1 -1
  61. package/lib/src/state/hooks.d.ts +19 -0
  62. package/lib/src/state/hooks.d.ts.map +1 -1
  63. package/lib/src/state/sync/replicationService.d.ts +1 -0
  64. package/lib/src/state/sync/replicationService.d.ts.map +1 -1
  65. package/lib/src/utils/workQueue.d.ts +1 -0
  66. package/lib/src/utils/workQueue.d.ts.map +1 -1
  67. package/lib/styles/index.css +690 -77
  68. 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: "_headerContainer_gh2j2_1",
10204
- headerModern: "_headerModern_gh2j2_11",
10205
- headerIcon: "_headerIcon_gh2j2_18",
10206
- headerIconEmpty: "_headerIconEmpty_gh2j2_18",
10207
- body: "_body_gh2j2_22",
10208
- card: "_card_gh2j2_27",
10209
- noPadding: "_noPadding_gh2j2_34"
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$7(message, cause) {
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$3(value) {
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$3)}]` : isRegExp$1(value) ? value + "" : objectKey(value);
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$3(value[k])}`;
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$3(v);
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$3(v);
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$7("ntile num must be greater than zero.");
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$7("nth_value nth must be greater than zero.");
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$3 = [];
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$3;
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$2(state, startLine, endLine, silent) {
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$2,
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$6(type) {
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$6("not-basic");
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$6("invalid-input");
35301
+ if (index >= inputLength) error$7("invalid-input");
35302
35302
  const digit = basicToDigit(input.charCodeAt(index++));
35303
- if (digit >= base$1) error$6("invalid-input");
35304
- if (digit > floor((maxInt - i) / w)) error$6("overflow");
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$6("overflow");
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$6("overflow");
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$6("overflow");
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$6("overflow");
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$1, DexieYProvider } = Dexie;
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
- const previewTasks = [];
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
- const previewTasks = [...toInvalidate];
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 refreshPendingLogFiles() {
50668
+ async refreshLogFiles(reason) {
50639
50669
  if (this.isRefreshing || !this.onRefreshCallback) return;
50640
- do
50641
- try {
50642
- const logFiles = [...this.pendingLogs];
50643
- this.pendingLogs.clear();
50644
- this.isRefreshing = true;
50645
- await this.onRefreshCallback(logFiles);
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(logs, api) {
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(logs);
50672
- if (pollingCount++ % 10 === 0) await this.refreshLogFiles(logs);
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$3 = createLogger("hooks");
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$3.debug("clear message (eval)", id);
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$3.debug("clear message (sample)", id);
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$3.debug("visibility", id, visible);
54935
+ log$2.debug("visibility", id, visible);
54860
54936
  const set = (visible) => {
54861
- log$3.debug("set visiblity", id);
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$3.error("Error loading logs", e);
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 { loadLogOverviews, loadAllLogOverviews } = useLogs();
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
- const loadHeaders = async () => {
103882
- const filesToLoad = logFiles.filter((file) => !logPreviews[file.name]);
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(watchedLogs);
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: `Task: ${subagentType}`,
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 isNonTaskTool = message.role === "tool" && message.function !== "Task" && message.function !== "task";
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: isNonTaskTool ? /* @__PURE__ */ jsx(ToolOutput, { output: typeof message.content === "string" ? message.content : message.content.filter((c) => c.type === "text" || c.type === "image") }) : /* @__PURE__ */ jsx(MessageContents, {
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 ? "ok" : "running";
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
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Card, { children: [/* @__PURE__ */ jsx(CardHeader, { label: "Summary" }), /* @__PURE__ */ jsx(CardBody, {
124047
- id: "task-plan-card-body",
124048
- children: /* @__PURE__ */ jsx(PlanDetailView, {
124049
- evaluation: evalSpec,
124050
- plan: evalPlan,
124051
- scores
124052
- })
124053
- })] }), Object.keys(metadata).length > 0 && /* @__PURE__ */ jsxs(Card, { children: [/* @__PURE__ */ jsx(CardHeader, { label: "Metadata" }), /* @__PURE__ */ jsx(CardBody, {
124054
- id: "task-metadata`",
124055
- children: /* @__PURE__ */ jsx(RecordTree, {
124056
- id: "plan-md-metadata",
124057
- record: metadata,
124058
- scrollRef
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 TaskTab_module_default = { grid: "_grid_er9fb_1" };
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 (tags && tags.length > 0) taskInformation["tags"] = tags.join(", ");
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: "_container_17txe_1",
151763
- wrapper: "_wrapper_17txe_8",
151764
- toggle: "_toggle_17txe_14",
151765
- body: "_body_17txe_21",
151766
- bodyContainer: "_bodyContainer_17txe_27",
151767
- taskTitle: "_taskTitle_17txe_33",
151768
- taskModel: "_taskModel_17txe_38",
151769
- taskStatus: "_taskStatus_17txe_42",
151770
- secondaryContainer: "_secondaryContainer_17txe_49",
151771
- buttonGroup: "_buttonGroup_17txe_58"
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: [/* @__PURE__ */ jsx("div", {
151862
- id: "task-title",
151863
- className: clsx("task-title", "text-truncate", PrimaryBar_module_default.taskTitle),
151864
- title: evalSpec?.task,
151865
- children: evalSpec?.task
151866
- }), evalSpec?.model && evalSpec.model !== "none/none" ? /* @__PURE__ */ jsx("div", {
151867
- id: "task-model",
151868
- className: clsx("task-model", "text-truncate", PrimaryBar_module_default.taskModel, "text-size-base"),
151869
- title: evalSpec?.model,
151870
- children: evalSpec?.model
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
- if (previousSamplesPath !== void 0 && previousSamplesPath !== samplesPath) {
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 gridState;
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 ?? false,
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", 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