@swmansion/argent 0.30.2-next.14 → 0.30.2-next.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-cmds.mjs +22 -6
- package/dist/client.js +21 -5
- package/dist/installer.mjs +2 -1
- package/dist/mcp-server.mjs +30 -8
- package/dist/tool-server.cjs +261 -50
- package/package.json +1 -1
- package/skills/argent-native-profiler/SKILL.md +1 -0
- package/skills/argent-react-native-profiler/SKILL.md +2 -0
package/dist/cli-cmds.mjs
CHANGED
|
@@ -9855,6 +9855,7 @@ var FAILURE_CODES = {
|
|
|
9855
9855
|
REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
|
|
9856
9856
|
REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
|
|
9857
9857
|
REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
|
|
9858
|
+
REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
|
|
9858
9859
|
REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
|
|
9859
9860
|
REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
|
|
9860
9861
|
NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
|
|
@@ -30810,8 +30811,13 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
30810
30811
|
if (msg.event === "progress") {
|
|
30811
30812
|
progress++;
|
|
30812
30813
|
onProgress(msg.data);
|
|
30813
|
-
} else if (msg.event === "result")
|
|
30814
|
-
|
|
30814
|
+
} else if (msg.event === "result") {
|
|
30815
|
+
final = {
|
|
30816
|
+
data: msg.data,
|
|
30817
|
+
note: msg.note,
|
|
30818
|
+
...msg.profiling === true ? { profiling: true } : {}
|
|
30819
|
+
};
|
|
30820
|
+
} else if (msg.event === "error") {
|
|
30815
30821
|
throw new ToolInvocationError(msg.error ?? "tool invocation failed", {
|
|
30816
30822
|
errorCode: msg.error_code,
|
|
30817
30823
|
errorKind: msg.error_kind
|
|
@@ -30858,7 +30864,11 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
30858
30864
|
if (!final) {
|
|
30859
30865
|
throw brokenStream(name, "the stream ended without a result", progress);
|
|
30860
30866
|
}
|
|
30861
|
-
return {
|
|
30867
|
+
return {
|
|
30868
|
+
data: final.data,
|
|
30869
|
+
note: final.note,
|
|
30870
|
+
...final.profiling ? { profiling: true } : {}
|
|
30871
|
+
};
|
|
30862
30872
|
}
|
|
30863
30873
|
function errorBodyMessage(body) {
|
|
30864
30874
|
if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
|
|
@@ -31031,7 +31041,8 @@ function createToolsClient(options = {}) {
|
|
|
31031
31041
|
return {
|
|
31032
31042
|
data: await settle2(streamed.data),
|
|
31033
31043
|
note: streamed.note,
|
|
31034
|
-
outputHint: meta3?.outputHint
|
|
31044
|
+
outputHint: meta3?.outputHint,
|
|
31045
|
+
...streamed.profiling ? { profiling: true } : {}
|
|
31035
31046
|
};
|
|
31036
31047
|
}
|
|
31037
31048
|
let json2;
|
|
@@ -31056,7 +31067,12 @@ function createToolsClient(options = {}) {
|
|
|
31056
31067
|
});
|
|
31057
31068
|
}
|
|
31058
31069
|
opts?.signal?.throwIfAborted();
|
|
31059
|
-
return {
|
|
31070
|
+
return {
|
|
31071
|
+
data: await settle2(json2.data),
|
|
31072
|
+
note: json2.note,
|
|
31073
|
+
outputHint: meta3?.outputHint,
|
|
31074
|
+
...json2.profiling === true ? { profiling: true } : {}
|
|
31075
|
+
};
|
|
31060
31076
|
}
|
|
31061
31077
|
return { fetchTools, fetchTool, callTool, baseUrl };
|
|
31062
31078
|
}
|
|
@@ -35578,7 +35594,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
35578
35594
|
var SESSION_ID2 = randomUUID5();
|
|
35579
35595
|
function readCliVersion() {
|
|
35580
35596
|
if (true) {
|
|
35581
|
-
return "0.30.2-next.
|
|
35597
|
+
return "0.30.2-next.15";
|
|
35582
35598
|
}
|
|
35583
35599
|
return "0.0.0";
|
|
35584
35600
|
}
|
package/dist/client.js
CHANGED
|
@@ -9059,6 +9059,7 @@ var FAILURE_CODES = {
|
|
|
9059
9059
|
REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
|
|
9060
9060
|
REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
|
|
9061
9061
|
REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
|
|
9062
|
+
REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
|
|
9062
9063
|
REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
|
|
9063
9064
|
REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
|
|
9064
9065
|
NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
|
|
@@ -10190,8 +10191,13 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
10190
10191
|
if (msg.event === "progress") {
|
|
10191
10192
|
progress++;
|
|
10192
10193
|
onProgress(msg.data);
|
|
10193
|
-
} else if (msg.event === "result")
|
|
10194
|
-
|
|
10194
|
+
} else if (msg.event === "result") {
|
|
10195
|
+
final = {
|
|
10196
|
+
data: msg.data,
|
|
10197
|
+
note: msg.note,
|
|
10198
|
+
...msg.profiling === true ? { profiling: true } : {}
|
|
10199
|
+
};
|
|
10200
|
+
} else if (msg.event === "error") {
|
|
10195
10201
|
throw new ToolInvocationError(msg.error ?? "tool invocation failed", {
|
|
10196
10202
|
errorCode: msg.error_code,
|
|
10197
10203
|
errorKind: msg.error_kind
|
|
@@ -10238,7 +10244,11 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
10238
10244
|
if (!final) {
|
|
10239
10245
|
throw brokenStream(name, "the stream ended without a result", progress);
|
|
10240
10246
|
}
|
|
10241
|
-
return {
|
|
10247
|
+
return {
|
|
10248
|
+
data: final.data,
|
|
10249
|
+
note: final.note,
|
|
10250
|
+
...final.profiling ? { profiling: true } : {}
|
|
10251
|
+
};
|
|
10242
10252
|
}
|
|
10243
10253
|
function errorBodyMessage(body) {
|
|
10244
10254
|
if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
|
|
@@ -10411,7 +10421,8 @@ function createToolsClient(options = {}) {
|
|
|
10411
10421
|
return {
|
|
10412
10422
|
data: await settle(streamed.data),
|
|
10413
10423
|
note: streamed.note,
|
|
10414
|
-
outputHint: meta?.outputHint
|
|
10424
|
+
outputHint: meta?.outputHint,
|
|
10425
|
+
...streamed.profiling ? { profiling: true } : {}
|
|
10415
10426
|
};
|
|
10416
10427
|
}
|
|
10417
10428
|
let json;
|
|
@@ -10436,7 +10447,12 @@ function createToolsClient(options = {}) {
|
|
|
10436
10447
|
});
|
|
10437
10448
|
}
|
|
10438
10449
|
opts?.signal?.throwIfAborted();
|
|
10439
|
-
return {
|
|
10450
|
+
return {
|
|
10451
|
+
data: await settle(json.data),
|
|
10452
|
+
note: json.note,
|
|
10453
|
+
outputHint: meta?.outputHint,
|
|
10454
|
+
...json.profiling === true ? { profiling: true } : {}
|
|
10455
|
+
};
|
|
10440
10456
|
}
|
|
10441
10457
|
return { fetchTools, fetchTool, callTool, baseUrl };
|
|
10442
10458
|
}
|
package/dist/installer.mjs
CHANGED
|
@@ -15962,6 +15962,7 @@ var FAILURE_CODES = {
|
|
|
15962
15962
|
REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
|
|
15963
15963
|
REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
|
|
15964
15964
|
REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
|
|
15965
|
+
REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
|
|
15965
15966
|
REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
|
|
15966
15967
|
REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
|
|
15967
15968
|
NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
|
|
@@ -16899,7 +16900,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
16899
16900
|
var SESSION_ID = randomUUID4();
|
|
16900
16901
|
function readCliVersion() {
|
|
16901
16902
|
if (true) {
|
|
16902
|
-
return "0.30.2-next.
|
|
16903
|
+
return "0.30.2-next.15";
|
|
16903
16904
|
}
|
|
16904
16905
|
return "0.0.0";
|
|
16905
16906
|
}
|
package/dist/mcp-server.mjs
CHANGED
|
@@ -25314,6 +25314,7 @@ var FAILURE_CODES = {
|
|
|
25314
25314
|
REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
|
|
25315
25315
|
REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
|
|
25316
25316
|
REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
|
|
25317
|
+
REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
|
|
25317
25318
|
REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
|
|
25318
25319
|
REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
|
|
25319
25320
|
NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
|
|
@@ -26486,8 +26487,13 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
26486
26487
|
if (msg.event === "progress") {
|
|
26487
26488
|
progress++;
|
|
26488
26489
|
onProgress(msg.data);
|
|
26489
|
-
} else if (msg.event === "result")
|
|
26490
|
-
|
|
26490
|
+
} else if (msg.event === "result") {
|
|
26491
|
+
final = {
|
|
26492
|
+
data: msg.data,
|
|
26493
|
+
note: msg.note,
|
|
26494
|
+
...msg.profiling === true ? { profiling: true } : {}
|
|
26495
|
+
};
|
|
26496
|
+
} else if (msg.event === "error") {
|
|
26491
26497
|
throw new ToolInvocationError(msg.error ?? "tool invocation failed", {
|
|
26492
26498
|
errorCode: msg.error_code,
|
|
26493
26499
|
errorKind: msg.error_kind
|
|
@@ -26534,7 +26540,11 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
26534
26540
|
if (!final) {
|
|
26535
26541
|
throw brokenStream(name, "the stream ended without a result", progress);
|
|
26536
26542
|
}
|
|
26537
|
-
return {
|
|
26543
|
+
return {
|
|
26544
|
+
data: final.data,
|
|
26545
|
+
note: final.note,
|
|
26546
|
+
...final.profiling ? { profiling: true } : {}
|
|
26547
|
+
};
|
|
26538
26548
|
}
|
|
26539
26549
|
function errorBodyMessage(body) {
|
|
26540
26550
|
if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
|
|
@@ -26707,7 +26717,8 @@ function createToolsClient(options = {}) {
|
|
|
26707
26717
|
return {
|
|
26708
26718
|
data: await settle2(streamed.data),
|
|
26709
26719
|
note: streamed.note,
|
|
26710
|
-
outputHint: meta2?.outputHint
|
|
26720
|
+
outputHint: meta2?.outputHint,
|
|
26721
|
+
...streamed.profiling ? { profiling: true } : {}
|
|
26711
26722
|
};
|
|
26712
26723
|
}
|
|
26713
26724
|
let json;
|
|
@@ -26732,7 +26743,12 @@ function createToolsClient(options = {}) {
|
|
|
26732
26743
|
});
|
|
26733
26744
|
}
|
|
26734
26745
|
opts?.signal?.throwIfAborted();
|
|
26735
|
-
return {
|
|
26746
|
+
return {
|
|
26747
|
+
data: await settle2(json.data),
|
|
26748
|
+
note: json.note,
|
|
26749
|
+
outputHint: meta2?.outputHint,
|
|
26750
|
+
...json.profiling === true ? { profiling: true } : {}
|
|
26751
|
+
};
|
|
26736
26752
|
}
|
|
26737
26753
|
return { fetchTools, fetchTool, callTool, baseUrl };
|
|
26738
26754
|
}
|
|
@@ -28540,6 +28556,7 @@ var AUTO_DESCRIBE_TOOLS = /* @__PURE__ */ new Set([
|
|
|
28540
28556
|
function autoDescribeEnabled(options) {
|
|
28541
28557
|
return !isFlagEnabled("disable-auto-describe", options);
|
|
28542
28558
|
}
|
|
28559
|
+
var PROFILING_CAPTURE_SKIPPED_NOTE = "Auto-screenshot and element tree skipped while a profiler is recording on this device. Call screenshot or describe if you need to see the screen.";
|
|
28543
28560
|
var AUTO_DESCRIBE_HEADER = "--- Elements after action (describe) ---";
|
|
28544
28561
|
function shouldAutoDescribe(toolName) {
|
|
28545
28562
|
return AUTO_DESCRIBE_TOOLS.has(normalizeToolName(toolName));
|
|
@@ -28692,8 +28709,8 @@ function createToolCaller(deps) {
|
|
|
28692
28709
|
return {
|
|
28693
28710
|
fetchTools: client.fetchTools,
|
|
28694
28711
|
async callTool(name, args) {
|
|
28695
|
-
const { data, note, outputHint } = await client.callTool(name, args);
|
|
28696
|
-
return { result: data, outputHint, note };
|
|
28712
|
+
const { data, note, outputHint, profiling } = await client.callTool(name, args);
|
|
28713
|
+
return { result: data, outputHint, note, ...profiling ? { profiling } : {} };
|
|
28697
28714
|
}
|
|
28698
28715
|
};
|
|
28699
28716
|
}
|
|
@@ -28857,7 +28874,7 @@ ${desc}` }];
|
|
|
28857
28874
|
args: params.arguments
|
|
28858
28875
|
});
|
|
28859
28876
|
try {
|
|
28860
|
-
const { result, outputHint, note } = await callTool(params.name, params.arguments);
|
|
28877
|
+
const { result, outputHint, note, profiling } = await callTool(params.name, params.arguments);
|
|
28861
28878
|
await spyLog({
|
|
28862
28879
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
28863
28880
|
event: "tool_result",
|
|
@@ -28890,6 +28907,11 @@ ${desc}` }];
|
|
|
28890
28907
|
text: "Auto-screenshot and element tree skipped: the input contains a {{secret:\u2026}} placeholder, and a capture of this screen could reveal the typed secret. The secret is already typed \u2014 do not send the typing step again, or the field will hold two copies of it. Submit or navigate away, then verify the resulting screen as usual. Only this call is covered: the next call is captured normally, and shows the secret if the field is still on screen. To cover the submit as well, put the typing and the submit in ONE `run-sequence` the next time you type a secret."
|
|
28891
28908
|
}
|
|
28892
28909
|
];
|
|
28910
|
+
} else if (udid && (wantScreenshot || wantTree) && profiling) {
|
|
28911
|
+
if (params.name !== "describe") {
|
|
28912
|
+
await awaitScreenSettled(udid, params.name);
|
|
28913
|
+
content = [...content, { type: "text", text: PROFILING_CAPTURE_SKIPPED_NOTE }];
|
|
28914
|
+
}
|
|
28893
28915
|
} else if (udid && (wantScreenshot || wantTree)) {
|
|
28894
28916
|
const screenSettled = await awaitScreenSettled(udid, params.name);
|
|
28895
28917
|
const screenshot = wantScreenshot ? captureScreenshotBlocks(udid) : Promise.resolve([]);
|
package/dist/tool-server.cjs
CHANGED
|
@@ -1584,6 +1584,7 @@ var init_failure_codes = __esm({
|
|
|
1584
1584
|
REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
|
|
1585
1585
|
REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
|
|
1586
1586
|
REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
|
|
1587
|
+
REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
|
|
1587
1588
|
REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
|
|
1588
1589
|
REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
|
|
1589
1590
|
NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
|
|
@@ -100944,7 +100945,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
100944
100945
|
var SESSION_ID = (0, import_node_crypto3.randomUUID)();
|
|
100945
100946
|
function readCliVersion() {
|
|
100946
100947
|
if (true) {
|
|
100947
|
-
return "0.30.2-next.
|
|
100948
|
+
return "0.30.2-next.15";
|
|
100948
100949
|
}
|
|
100949
100950
|
return "0.0.0";
|
|
100950
100951
|
}
|
|
@@ -122219,6 +122220,52 @@ function settleWithin(p, ms, signal) {
|
|
|
122219
122220
|
// ../tool-server/src/utils/simulator-client.ts
|
|
122220
122221
|
init_external_devices();
|
|
122221
122222
|
|
|
122223
|
+
// ../tool-server/src/utils/profiling-devices.ts
|
|
122224
|
+
var runs = /* @__PURE__ */ new Map();
|
|
122225
|
+
var servers = /* @__PURE__ */ new Map();
|
|
122226
|
+
function trackProfilingRun(deviceId, run2) {
|
|
122227
|
+
let set2 = runs.get(deviceId);
|
|
122228
|
+
if (!set2) {
|
|
122229
|
+
set2 = /* @__PURE__ */ new Set();
|
|
122230
|
+
runs.set(deviceId, set2);
|
|
122231
|
+
}
|
|
122232
|
+
set2.add(run2);
|
|
122233
|
+
syncCaptureOnDemand();
|
|
122234
|
+
}
|
|
122235
|
+
function isProfiling(deviceId) {
|
|
122236
|
+
syncCaptureOnDemand();
|
|
122237
|
+
return runs.has(deviceId);
|
|
122238
|
+
}
|
|
122239
|
+
function syncCaptureOnDemand() {
|
|
122240
|
+
for (const [deviceId, set2] of runs) {
|
|
122241
|
+
for (const run2 of set2) {
|
|
122242
|
+
if (!run2.profilingActive) set2.delete(run2);
|
|
122243
|
+
}
|
|
122244
|
+
if (set2.size === 0) runs.delete(deviceId);
|
|
122245
|
+
}
|
|
122246
|
+
for (const [deviceId, server] of servers) {
|
|
122247
|
+
const profiling = runs.has(deviceId);
|
|
122248
|
+
if (server.onDemand !== profiling) {
|
|
122249
|
+
server.onDemand = profiling;
|
|
122250
|
+
server.send(profiling);
|
|
122251
|
+
}
|
|
122252
|
+
}
|
|
122253
|
+
}
|
|
122254
|
+
function registerCaptureOnDemandSender(deviceId, endpoint, send) {
|
|
122255
|
+
const entry = { endpoint, send, onDemand: false };
|
|
122256
|
+
servers.set(deviceId, entry);
|
|
122257
|
+
syncCaptureOnDemand();
|
|
122258
|
+
return () => {
|
|
122259
|
+
if (servers.get(deviceId) !== entry) return;
|
|
122260
|
+
servers.delete(deviceId);
|
|
122261
|
+
if (entry.onDemand) entry.send(false);
|
|
122262
|
+
};
|
|
122263
|
+
}
|
|
122264
|
+
function captureOnDemandDropped(deviceId, endpoint) {
|
|
122265
|
+
const server = servers.get(deviceId);
|
|
122266
|
+
if (server?.endpoint === endpoint) server.onDemand = false;
|
|
122267
|
+
}
|
|
122268
|
+
|
|
122222
122269
|
// ../tool-server/src/utils/foldable.ts
|
|
122223
122270
|
var import_node_child_process13 = require("node:child_process");
|
|
122224
122271
|
var fs17 = __toESM(require("node:fs"));
|
|
@@ -122461,6 +122508,14 @@ var FIRST_FRAME_POLL_MS = 250;
|
|
|
122461
122508
|
var COMMAND_ACK_TIMEOUT_MS = 5e3;
|
|
122462
122509
|
var connections = /* @__PURE__ */ new Map();
|
|
122463
122510
|
var cmdId = 0;
|
|
122511
|
+
function pendingIdNamedBy(conn, message) {
|
|
122512
|
+
const named = message?.match(/unknown variant `([^`]+)`/)?.[1];
|
|
122513
|
+
if (named === void 0) return void 0;
|
|
122514
|
+
for (const [id, entry] of conn.pending) {
|
|
122515
|
+
if (entry.cmd === named) return id;
|
|
122516
|
+
}
|
|
122517
|
+
return void 0;
|
|
122518
|
+
}
|
|
122464
122519
|
function failAllPending(conn, makeError) {
|
|
122465
122520
|
const entries = [...conn.pending.values()];
|
|
122466
122521
|
conn.pending.clear();
|
|
@@ -122507,7 +122562,7 @@ function getOrCreateConnection(api) {
|
|
|
122507
122562
|
}
|
|
122508
122563
|
if (ack.status !== "ok" && ack.status !== "error") return;
|
|
122509
122564
|
if (ack.id != null && !conn.pending.has(ack.id)) return;
|
|
122510
|
-
const id = ack.id ?? conn.pending.keys().next().value;
|
|
122565
|
+
const id = ack.id ?? pendingIdNamedBy(conn, ack.message) ?? conn.pending.keys().next().value;
|
|
122511
122566
|
if (id == null) return;
|
|
122512
122567
|
const entry = conn.pending.get(id);
|
|
122513
122568
|
if (entry == null) return;
|
|
@@ -122536,6 +122591,7 @@ function getOrCreateConnection(api) {
|
|
|
122536
122591
|
ws.on("close", () => {
|
|
122537
122592
|
connections.delete(key2);
|
|
122538
122593
|
failAllPending(conn, (cmd) => transportError(cmd, key2, "the connection closed"));
|
|
122594
|
+
if (api.deviceId) captureOnDemandDropped(api.deviceId, key2);
|
|
122539
122595
|
});
|
|
122540
122596
|
connections.set(key2, conn);
|
|
122541
122597
|
return conn;
|
|
@@ -123211,6 +123267,19 @@ async function spawnSimulatorServerProcess(udid, subcommand) {
|
|
|
123211
123267
|
}, READY_TIMEOUT_MS);
|
|
123212
123268
|
});
|
|
123213
123269
|
}
|
|
123270
|
+
function withCaptureOnDemand(deviceId, instance) {
|
|
123271
|
+
const unregister = registerCaptureOnDemandSender(deviceId, instance.api.apiUrl, (enabled) => {
|
|
123272
|
+
sendCommand(instance.api, { cmd: "capture_on_demand", enabled }).catch(() => {
|
|
123273
|
+
});
|
|
123274
|
+
});
|
|
123275
|
+
return {
|
|
123276
|
+
...instance,
|
|
123277
|
+
dispose: async () => {
|
|
123278
|
+
unregister();
|
|
123279
|
+
await instance.dispose();
|
|
123280
|
+
}
|
|
123281
|
+
};
|
|
123282
|
+
}
|
|
123214
123283
|
var simulatorServerBlueprint = {
|
|
123215
123284
|
namespace: SIMULATOR_SERVER_NAMESPACE,
|
|
123216
123285
|
getURN(device) {
|
|
@@ -123255,7 +123324,7 @@ var simulatorServerBlueprint = {
|
|
|
123255
123324
|
}
|
|
123256
123325
|
const claim2 = externalClaimForAnyId(device.id);
|
|
123257
123326
|
if (claim2) {
|
|
123258
|
-
return buildAttachedInstance(device, claim2);
|
|
123327
|
+
return withCaptureOnDemand(device.id, await buildAttachedInstance(device, claim2));
|
|
123259
123328
|
}
|
|
123260
123329
|
if (device.platform === "ios-remote") {
|
|
123261
123330
|
return buildRemoteInstance(device);
|
|
@@ -123313,7 +123382,7 @@ var simulatorServerBlueprint = {
|
|
|
123313
123382
|
events
|
|
123314
123383
|
};
|
|
123315
123384
|
await attachFoldableDisplay(instance.api, device);
|
|
123316
|
-
return instance;
|
|
123385
|
+
return withCaptureOnDemand(device.id, instance);
|
|
123317
123386
|
}
|
|
123318
123387
|
};
|
|
123319
123388
|
|
|
@@ -130976,11 +131045,12 @@ function createHttpApp(registry2, options) {
|
|
|
130976
131045
|
const toolNote = takeToolNote(data);
|
|
130977
131046
|
if (toolNote) notes.push(toolNote);
|
|
130978
131047
|
const notePayload = notes.length > 0 ? { note: notes.join("\n\n") } : {};
|
|
131048
|
+
const profilingPayload = deviceArg && isProfiling(canonicalDeviceId(deviceArg) ?? deviceArg) ? { profiling: true } : {};
|
|
130979
131049
|
if (wantsStream) {
|
|
130980
|
-
writeLine({ event: "result", data, ...notePayload });
|
|
131050
|
+
writeLine({ event: "result", data, ...notePayload, ...profilingPayload });
|
|
130981
131051
|
res.end();
|
|
130982
131052
|
} else {
|
|
130983
|
-
res.json({ data, ...notePayload });
|
|
131053
|
+
res.json({ data, ...notePayload, ...profilingPayload });
|
|
130984
131054
|
}
|
|
130985
131055
|
} catch (err) {
|
|
130986
131056
|
const attribute = (message) => {
|
|
@@ -136761,6 +136831,7 @@ var reactProfilerSessionBlueprint = {
|
|
|
136761
136831
|
profileStartWallMs: null,
|
|
136762
136832
|
sessionId: null,
|
|
136763
136833
|
ownerToolServerPid: null,
|
|
136834
|
+
disposed: false,
|
|
136764
136835
|
disposeSession: () => events.emit("terminated")
|
|
136765
136836
|
};
|
|
136766
136837
|
await cdp.send("Profiler.enable").catch(warnOnError("Profiler.enable"));
|
|
@@ -136823,11 +136894,25 @@ var reactProfilerSessionBlueprint = {
|
|
|
136823
136894
|
);
|
|
136824
136895
|
};
|
|
136825
136896
|
cdp.events.on("disconnected", onDisconnected);
|
|
136897
|
+
const onCdpEvent = (method) => {
|
|
136898
|
+
if (method !== "Runtime.executionContextDestroyed" && method !== "Runtime.executionContextsCleared") {
|
|
136899
|
+
return;
|
|
136900
|
+
}
|
|
136901
|
+
if (state3.profilingActive) {
|
|
136902
|
+
state3.profilingActive = false;
|
|
136903
|
+
clearCachedProfilerPaths(state3.port, state3.deviceId);
|
|
136904
|
+
stopSamplerInNextRuntime(cdp);
|
|
136905
|
+
}
|
|
136906
|
+
events.emit("terminated");
|
|
136907
|
+
};
|
|
136908
|
+
cdp.events.on("event", onCdpEvent);
|
|
136826
136909
|
return {
|
|
136827
136910
|
api: state3,
|
|
136828
136911
|
dispose: async () => {
|
|
136912
|
+
state3.disposed = true;
|
|
136829
136913
|
cdp.events.off("scriptParsed", onScriptParsed);
|
|
136830
136914
|
cdp.events.off("disconnected", onDisconnected);
|
|
136915
|
+
cdp.events.off("event", onCdpEvent);
|
|
136831
136916
|
if (state3.profilingActive) {
|
|
136832
136917
|
state3.profilingActive = false;
|
|
136833
136918
|
await cdp.send("Runtime.evaluate", {
|
|
@@ -136842,6 +136927,20 @@ var reactProfilerSessionBlueprint = {
|
|
|
136842
136927
|
};
|
|
136843
136928
|
}
|
|
136844
136929
|
};
|
|
136930
|
+
function stopSamplerInNextRuntime(cdp) {
|
|
136931
|
+
const onEvent = (method) => {
|
|
136932
|
+
if (method !== "Runtime.executionContextCreated") return;
|
|
136933
|
+
disarm();
|
|
136934
|
+
void cdp.send("Profiler.stop").catch(() => {
|
|
136935
|
+
});
|
|
136936
|
+
};
|
|
136937
|
+
const disarm = () => {
|
|
136938
|
+
cdp.events.off("event", onEvent);
|
|
136939
|
+
cdp.events.off("disconnected", disarm);
|
|
136940
|
+
};
|
|
136941
|
+
cdp.events.on("event", onEvent);
|
|
136942
|
+
cdp.events.on("disconnected", disarm);
|
|
136943
|
+
}
|
|
136845
136944
|
var profilerPathsCache = /* @__PURE__ */ new Map();
|
|
136846
136945
|
function cacheKey(port, deviceId) {
|
|
136847
136946
|
return `${port}:${deviceId}`;
|
|
@@ -154859,6 +154958,96 @@ function classifyStaleness({
|
|
|
154859
154958
|
};
|
|
154860
154959
|
}
|
|
154861
154960
|
|
|
154961
|
+
// ../tool-server/src/utils/debugger/runtime-device.ts
|
|
154962
|
+
var import_node_crypto12 = require("node:crypto");
|
|
154963
|
+
var import_node_child_process38 = require("node:child_process");
|
|
154964
|
+
var import_node_util30 = require("node:util");
|
|
154965
|
+
init_adb();
|
|
154966
|
+
var execFileAsync30 = (0, import_node_util30.promisify)(import_node_child_process38.execFile);
|
|
154967
|
+
var LOG_READ_TIMEOUT_MS = 5e3;
|
|
154968
|
+
var RETRY_DELAY_MS = 300;
|
|
154969
|
+
async function findRuntimeDevice(cdp) {
|
|
154970
|
+
const marker = `argent-device-probe:${(0, import_node_crypto12.randomUUID)()}`;
|
|
154971
|
+
const logged = await cdp.evaluate(
|
|
154972
|
+
`(function () {
|
|
154973
|
+
if (typeof nativeLoggingHook !== "function") return false;
|
|
154974
|
+
nativeLoggingHook(${JSON.stringify(marker)}, 1);
|
|
154975
|
+
return true;
|
|
154976
|
+
})()`
|
|
154977
|
+
).catch(() => false);
|
|
154978
|
+
if (logged !== true) return void 0;
|
|
154979
|
+
const checks = [
|
|
154980
|
+
async () => firstFound((await androidSerials()).map((serial) => () => logcatHolds(serial, marker))),
|
|
154981
|
+
async () => firstFound((await bootedSimulators()).map((udid) => () => simulatorLogHolds(udid, marker)))
|
|
154982
|
+
];
|
|
154983
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
154984
|
+
if (attempt > 0) await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
|
|
154985
|
+
const found = await firstFound(checks);
|
|
154986
|
+
if (found !== void 0) return found;
|
|
154987
|
+
}
|
|
154988
|
+
return void 0;
|
|
154989
|
+
}
|
|
154990
|
+
function firstFound(checks) {
|
|
154991
|
+
return new Promise((resolve16) => {
|
|
154992
|
+
let left = checks.length;
|
|
154993
|
+
if (left === 0) resolve16(void 0);
|
|
154994
|
+
for (const check3 of checks) {
|
|
154995
|
+
void check3().then((id) => {
|
|
154996
|
+
if (id !== void 0) resolve16(id);
|
|
154997
|
+
else if (--left === 0) resolve16(void 0);
|
|
154998
|
+
});
|
|
154999
|
+
}
|
|
155000
|
+
});
|
|
155001
|
+
}
|
|
155002
|
+
async function androidSerials() {
|
|
155003
|
+
try {
|
|
155004
|
+
const { stdout } = await runAdb(["devices"], { timeoutMs: ADB_DEVICES_TIMEOUT_MS });
|
|
155005
|
+
return parseAdbDevices(stdout).filter((d) => d.state === "device").map((d) => d.serial);
|
|
155006
|
+
} catch {
|
|
155007
|
+
return [];
|
|
155008
|
+
}
|
|
155009
|
+
}
|
|
155010
|
+
async function bootedSimulators() {
|
|
155011
|
+
const simulators = await listIosSimulators();
|
|
155012
|
+
return simulators.filter((s) => s.state === "Booted").map((s) => s.udid);
|
|
155013
|
+
}
|
|
155014
|
+
async function logcatHolds(serial, marker) {
|
|
155015
|
+
try {
|
|
155016
|
+
const { stdout } = await runAdb(
|
|
155017
|
+
["-s", serial, "logcat", "-d", "-s", "ReactNativeJS", "-e", marker],
|
|
155018
|
+
{ timeoutMs: LOG_READ_TIMEOUT_MS }
|
|
155019
|
+
);
|
|
155020
|
+
return stdout.includes(marker) ? serial : void 0;
|
|
155021
|
+
} catch {
|
|
155022
|
+
return void 0;
|
|
155023
|
+
}
|
|
155024
|
+
}
|
|
155025
|
+
async function simulatorLogHolds(udid, marker) {
|
|
155026
|
+
try {
|
|
155027
|
+
const args = await simctlArgsForUdid(udid, [
|
|
155028
|
+
"spawn",
|
|
155029
|
+
udid,
|
|
155030
|
+
"log",
|
|
155031
|
+
"show",
|
|
155032
|
+
"--info",
|
|
155033
|
+
"--last",
|
|
155034
|
+
"1m",
|
|
155035
|
+
"--style",
|
|
155036
|
+
"compact",
|
|
155037
|
+
"--predicate",
|
|
155038
|
+
`eventMessage CONTAINS ${JSON.stringify(marker)} AND process != "log"`
|
|
155039
|
+
]);
|
|
155040
|
+
const { stdout } = await execFileAsync30("xcrun", args, {
|
|
155041
|
+
timeout: LOG_READ_TIMEOUT_MS,
|
|
155042
|
+
killSignal: SIMCTL_KILL_SIGNAL,
|
|
155043
|
+
encoding: "utf-8"
|
|
155044
|
+
});
|
|
155045
|
+
return stdout.includes(marker) ? udid : void 0;
|
|
155046
|
+
} catch {
|
|
155047
|
+
return void 0;
|
|
155048
|
+
}
|
|
155049
|
+
}
|
|
155050
|
+
|
|
154862
155051
|
// ../tool-server/src/utils/react-profiler/devtools-bootstrap.ts
|
|
154863
155052
|
function bootstrapFailureMessage(bootstrap) {
|
|
154864
155053
|
switch (bootstrap.reason) {
|
|
@@ -154881,6 +155070,7 @@ function bootstrapFailureMessage(bootstrap) {
|
|
|
154881
155070
|
// ../tool-server/src/tools/profiler/react/react-profiler-start.ts
|
|
154882
155071
|
var NO_DEVTOOLS_HOOK_ERROR = "React DevTools hook (__REACT_DEVTOOLS_GLOBAL_HOOK__) is not present in this app's JavaScript runtime. React profiling requires a development build with React DevTools enabled. Likely causes: (1) the app is a release/production build \u2014 DevTools is stripped to reduce bundle size; (2) you connected to the wrong JS runtime; (3) this isn't a React (Native) app. Fix: rebuild in debug/dev mode (e.g. `npx react-native run-ios` without --configuration Release; for Expo, run a dev client). Once the app is running with DevTools attached, call react-profiler-start again.";
|
|
154883
155072
|
var NO_RENDERERS_ATTACHED_ERROR = "React DevTools hook is present but no React renderer has registered yet. The hook is loaded but no fiber renderer has attached \u2014 typically because the app has not committed its first render, or the DevTools backend has not been bootstrapped on a bridgeless React Native dev build. Fix: ensure the app has rendered (interact with it once, then retry); if it stays empty, call react-profiler-start first \u2014 it will attempt to attach the DevTools backend automatically.";
|
|
155073
|
+
var UNKNOWN_DEVICE_NOTE = "Two or more devices share this Metro, and Argent could not tell which of them runs this app. So taps and swipes on that device still return a screenshot and an element tree, and the capture loads the app while the profiler records. To avoid this, run the app on its own Metro port.";
|
|
154884
155074
|
var zodSchema45 = external_exports.object({
|
|
154885
155075
|
port: metroPortField,
|
|
154886
155076
|
device_id: external_exports.string().describe(
|
|
@@ -155056,6 +155246,7 @@ Fails if the Hermes runtime is not reachable or the Metro CDP connection cannot
|
|
|
155056
155246
|
await cdp.send("Profiler.stop").catch(ignore);
|
|
155057
155247
|
api.profilingActive = false;
|
|
155058
155248
|
}
|
|
155249
|
+
const runtimeDevice = isLogicalKeyedDevice(api.deviceId) ? await findRuntimeDevice(cdp) : void 0;
|
|
155059
155250
|
const sessionId = crypto6.randomUUID();
|
|
155060
155251
|
const ownerPayload = {
|
|
155061
155252
|
sessionId,
|
|
@@ -155100,6 +155291,19 @@ Fails if the Hermes runtime is not reachable or the Metro CDP connection cannot
|
|
|
155100
155291
|
}
|
|
155101
155292
|
);
|
|
155102
155293
|
}
|
|
155294
|
+
if (api.disposed) {
|
|
155295
|
+
await cdp.evaluate(STOP_FOR_TAKEOVER_SCRIPT).catch(ignore);
|
|
155296
|
+
await cdp.send("Profiler.stop").catch(ignore);
|
|
155297
|
+
throw new FailureError(
|
|
155298
|
+
`The React profiler session for ${api.deviceId} was torn down while the profiler was starting, so nothing is recorded. One tool-server serves every agent using this argent install, so another agent may have run stop-all-simulator-servers. Call react-profiler-start again.`,
|
|
155299
|
+
{
|
|
155300
|
+
error_code: FAILURE_CODES.REACT_PROFILER_SESSION_TORN_DOWN,
|
|
155301
|
+
failure_stage: "react_profiler_start_session_torn_down",
|
|
155302
|
+
failure_area: "tool_server",
|
|
155303
|
+
error_kind: "not_found"
|
|
155304
|
+
}
|
|
155305
|
+
);
|
|
155306
|
+
}
|
|
155103
155307
|
const startedAtEpochMs = startResult.startedAtEpochMs ?? Date.now();
|
|
155104
155308
|
clearCachedProfilerPaths(api.port, api.deviceId);
|
|
155105
155309
|
api.sessionPaths = null;
|
|
@@ -155110,11 +155314,14 @@ Fails if the Hermes runtime is not reachable or the Metro CDP connection cannot
|
|
|
155110
155314
|
api.profileStartWallMs = startedAtEpochMs;
|
|
155111
155315
|
api.sessionId = sessionId;
|
|
155112
155316
|
api.ownerToolServerPid = process.pid;
|
|
155317
|
+
trackProfilingRun(api.deviceId, api);
|
|
155318
|
+
if (runtimeDevice) trackProfilingRun(runtimeDevice, api);
|
|
155113
155319
|
return {
|
|
155114
155320
|
started_at: new Date(startedAtEpochMs).toISOString(),
|
|
155115
155321
|
startedAtEpochMs,
|
|
155116
155322
|
hermes_version: api.hermesVersion,
|
|
155117
|
-
detected_architecture: api.detectedArchitecture
|
|
155323
|
+
detected_architecture: api.detectedArchitecture,
|
|
155324
|
+
...isLogicalKeyedDevice(api.deviceId) && !runtimeDevice ? { [RESULT_NOTE_KEY]: UNKNOWN_DEVICE_NOTE } : {}
|
|
155118
155325
|
};
|
|
155119
155326
|
}
|
|
155120
155327
|
};
|
|
@@ -155307,7 +155514,7 @@ Fails if no active profiling session exists or the CDP connection was lost durin
|
|
|
155307
155514
|
}
|
|
155308
155515
|
if (!api.profilingActive) {
|
|
155309
155516
|
throw new FailureError(
|
|
155310
|
-
"No active profiling run to stop.
|
|
155517
|
+
"No active profiling run to stop. Either the run ended without its data (a JS reload ends it: Metro's `r`, a red-box Reload, debugger-reload-metro), or Hermes CPU sampling was never started \u2014 typically because react-profiler-start failed before reaching the sampler (often on release builds without React DevTools). After a reload, call react-profiler-start again. Otherwise check the error react-profiler-start returned, address the underlying cause (rebuild in dev mode, reconnect the debugger, etc.), then call react-profiler-start again.",
|
|
155311
155518
|
{
|
|
155312
155519
|
error_code: FAILURE_CODES.REACT_PROFILER_NO_ACTIVE_SESSION,
|
|
155313
155520
|
failure_stage: "react_profiler_stop_inactive",
|
|
@@ -158171,8 +158378,8 @@ var import_util14 = require("util");
|
|
|
158171
158378
|
var DEFAULT_EXEC_TIMEOUT_MS = 6e4;
|
|
158172
158379
|
var DEFAULT_EXEC_MAX_BUFFER = 256 * 1024 * 1024;
|
|
158173
158380
|
async function execFileAsyncWithTimeout(file2, args, options = {}) {
|
|
158174
|
-
const
|
|
158175
|
-
const { stdout, stderr } = await
|
|
158381
|
+
const execFileAsync35 = (0, import_util14.promisify)(import_child_process2.execFile);
|
|
158382
|
+
const { stdout, stderr } = await execFileAsync35(file2, args, {
|
|
158176
158383
|
encoding: "utf-8",
|
|
158177
158384
|
...options,
|
|
158178
158385
|
// Applied after ...options so a caller cannot weaken the guards; maxBuffer
|
|
@@ -159704,7 +159911,7 @@ var STARTUP_TIMEOUT_MS = 1e4;
|
|
|
159704
159911
|
var DETECT_RUNNING_APP_TIMEOUT_MS = 1e4;
|
|
159705
159912
|
var NOTIFY_REGISTER_TIMEOUT_MS = 2e3;
|
|
159706
159913
|
var MAX_START_ATTEMPTS = 2;
|
|
159707
|
-
var
|
|
159914
|
+
var RETRY_DELAY_MS2 = 1200;
|
|
159708
159915
|
var COLD_START_SIGNATURE = "Cannot find process matching name:";
|
|
159709
159916
|
var STOP_GRACE_MS = 3e5;
|
|
159710
159917
|
var STOP_TERM_MS = 5e3;
|
|
@@ -160128,10 +160335,10 @@ async function startNativeProfilerIos(api, params) {
|
|
|
160128
160335
|
if (!isColdStart) throw err;
|
|
160129
160336
|
if (attempt >= MAX_START_ATTEMPTS) break;
|
|
160130
160337
|
process.stderr.write(
|
|
160131
|
-
`[native-profiler] xctrace could not find "${appProcess}" on attempt ${attempt}/${MAX_START_ATTEMPTS}; waiting ${
|
|
160338
|
+
`[native-profiler] xctrace could not find "${appProcess}" on attempt ${attempt}/${MAX_START_ATTEMPTS}; waiting ${RETRY_DELAY_MS2} ms for cold-start to settle, then retrying.
|
|
160132
160339
|
`
|
|
160133
160340
|
);
|
|
160134
|
-
await new Promise((r) => setTimeout(r,
|
|
160341
|
+
await new Promise((r) => setTimeout(r, RETRY_DELAY_MS2));
|
|
160135
160342
|
}
|
|
160136
160343
|
}
|
|
160137
160344
|
const totalMs = Date.now() - startMs;
|
|
@@ -161589,12 +161796,16 @@ Fails if no app is running on the device, or the profiler cannot attach to the p
|
|
|
161589
161796
|
const api = services.session;
|
|
161590
161797
|
const device = resolveDevice(params.device_id);
|
|
161591
161798
|
assertSupported("native-profiler-start", capability30, device);
|
|
161799
|
+
let started;
|
|
161592
161800
|
if (api.platform === "ios") {
|
|
161593
161801
|
await ensureDeps(["xcrun"]);
|
|
161594
|
-
|
|
161802
|
+
started = await startNativeProfilerIos(api, params);
|
|
161803
|
+
} else {
|
|
161804
|
+
await ensureDeps(["adb"]);
|
|
161805
|
+
started = await startNativeProfilerAndroid(api, params);
|
|
161595
161806
|
}
|
|
161596
|
-
|
|
161597
|
-
return
|
|
161807
|
+
trackProfilingRun(device.id, api);
|
|
161808
|
+
return started;
|
|
161598
161809
|
}
|
|
161599
161810
|
};
|
|
161600
161811
|
|
|
@@ -162221,7 +162432,7 @@ var WATERMARK_PNG_HEIGHT = 277;
|
|
|
162221
162432
|
var WATERMARK_PNG_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAA4QAAAEVCAYAAAC46yv0AAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nOydd7xkRbX916qGIcwQBAaQDEPOacgqIgoCgxJEQRiCCuJ7CCoIzwQYfoIYAJ8BFAUERYLwAEUBMcCoMAwZiUMSkJwGJMycWr8/ui709D23Y1Wf7tP7+/ncz3zm3HN27e7b4eyqXWsRhtEiksYBmCrp8wBWKzqffoLkqiRnFp2HYRiGYRiGYbTDPEUnYPQ/ksYD+LikzwFYvuh8+pTNAVhBaBiGYRiGYQwUVhAaYyJpMe/9YZIOA7B40fn0M977zQD8sug8jOFB0ju89zunHsc5dwHJGanHMQzDMAyjGKwgNEYhaSnv/aGSjiC5SNH5DAIkNy86B2O4kHQcye1Sj+O9XxnAh1OPYxiGYRhGMbDoBIz+QdKq3vvPk5wKYL4mp2cAXupBWkXwtg6ueY3kIiTfiJ6NYdQhaUVJDwBwPRjuDZLLkHy2B2MZhmEYhmEYvUbSBlmWnee9n+O9V5Of17Is+5GkVYrOOyaSnKQ9vPc3tvAc5P5Imlz04zCGgyzLju30ddrha/tTRT9mwzAMwzAMIzKStvHeX+arNLspnJVl2SmSli0675hImlfSVO/9P1u8OX5A0uFZlv0y56b5v4p+PEb5kUTv/f29LAi99zcU/bgNwzAMwzCMSIRC8KoWbwSfzrLsOEmLFZ13TCTNJ+lg7/0jLT4Pt0maKmmecP0n68/Jsuysoh+XUX4kvbvHxeDIhMd6RT92wzAMwzAMo0NCS+QU7/0NLd4A/lvS0cFyojRIWljS4d77x1t8Hq6TNEUS6+JslHPu3UU9LmN4yLLsrCIKwizLTir6sRuGYRiGYRhtImlcaIm8u8Ubv5mSDpc0f9G5x0TSklmWHee9f76dQrBBvHm89y/XXeMldSJIYxgtIWmC935WEQWh9/4JSfMW/RwYhmEYhhEXs50oKZImAPiYpCMBLNfCJbeS/C6Ac0lmabPrHZJW8t5/RtInSC7Q5HQP4Hckv0pyeqMTSc7x3t8MYJvawwAmA7iyu6wNY0w+DGBCQWMvBWAHAJcXNL5hGIZhFI6kpdDavXWrzCF5a8R4xrATWiKP9t4/001L5KAjad0sy8723s9u4Tl4PcuysyWt2c4YWZZ9pz6WpC+nekyG4b2/rqDVwZGfC4t+DgzDMAyjSCQdFfm7tXBbJ1shLAm1ZvIAmpnJC8BvSX6T5N96kF7PkLSxpGMk7UmyWZH7iqQznHMnOecebXcs59z1kurH36zdOIbRCpJWk7RVwWlMkTSR5NMF52EYhmEYRiSsIBxwJK3ivT9c0sEkm+37G2mJPI7kjF7k1yskbRNEcHZp4fSXJP0oFILdzMpcn3Ns8y7iGcaYeO8PaGGSIzXjAOwN4NSC8zAMwzAMwxhuJK3fQUvk6kXnHZMa5dTrWxXFCBYazVZQW8Z7/0RO2+jKseIbBlB9rfvWLVJS/9xU9PNhGIZhGEVhLaNG4dSshO3cwmrBy5J+5pz7lnPusZ4k2AOC0uHeko4BsFYLlzxI8hQApznnXouczg0A6tVINwPwYORxjOHmvQCWLzqJwEaSNrAN8IZhGIZRDlzRCRitEczkr5Z0LYBdUFW0HItnJB1PcsVKpXI4yVIUg5LGB0uMmZLOQvNi8DaS+5NcneQpJGMXgyA5qm3Ue29to0ZUvPcHFp1DLd77A4rOwTAMwzCMONgKYR8jyQHYWdJXJG3awiVPkDwZwPedc/9JnF7PkLQwgAPDiuDSLVwyjeSJAC4nqaZnd8cN9QdImrCMEQ1Ji0jateg8aiG5n6SjSb5RdC6GYRiGYXSHFYR9iKRxAD4i6QsA1mjhkpkkvw/gtBSrYEUhaUnv/ackHQ5g0RYumUbyWJJ/TJ1bDTegKtZTu9q+iaR5Sc7uYR5GefkogGYemr1mcQA7Abik6EQMwzAMw+gOaxntIyRNqGuJbFYM3hpaItdI1RJZBJJWzrLsFEkPkTwWjYtBj+pK4GTn3DY9LgZB8kUA99Ydnh/Aer3Mwygvkg4oOoc8+jUvwzAMwzDaw1YI+wBJS3jv/1vSYQAWa+GSXrZE9gxJ63nvj5K0N8lmr803JP3aOfcNkvf0JMExkHQ9yXpT+80BmBqj0RWS1pE0ueg8xmBnSUuTfKLoRAzDMAzD6BxbISwQSUsFG4SZYSWsUTEoVAvArcJK2GVlKQYlbe29v0zSrST3Q+OJipclnUpyUqVSmVp0MQgAzrlR+wi997aP0OiafhOTqWMeVD0JDcMwDMMYYGyFsAA6NJM/lmSpVpzaNJN/VtL/OudOdc49lzy59hilNErSlEaNrpA0j6SPFp1HIyQdBOB7RedhGIZhGEbnWEHYQySt770/UtI+JCtNTh9pifwayft6kmAPqFFO/XKLrXBPSvqxc+57zrkXU+fXIbcBeBVzC3+sKWlRki8UlJMx+OyE1lR1i2RdSRuXbbLKMAzDMIYJaxntAcFD8DJJt4SWyEbF4EhL5MqhJbIUxaCkcZKmSrpT0qUAmhWDD5A8guRKlUrluCDe0pcENdFb6g8D2KSAdIySIKmf20XfxDwJDcMwDGOwsYIwIZK2995Pa9NMfoVgJv94j9JMSo2Z/P1BObVefKWeETP5gVJOlTSqbRRVYRnDaBtJE1FdIYzJQ5HjAQBI7iNpvhSxDcMwDMNIjxWEkZHkJE3x3t8o6SoAWzW55JGwErZiWAl7vhd5pkbSwjWF4MkAlm9yyTSSu5LckOTZJOf0Is9Y5AnLSDJhGaNTPgpgXMyAQZl4esyYgcUBTEkQ1zAMwzCMHmB7CCNRYyb/RQCrt3DJiJn8j0m+nja73lFjJn8EgEVauOTqIJjzt9S5JcZWCI1oJPD4ewPABSQrKWwsQr4Xxo5rGIZhGIbR94yYyXvvH/Xeq4Wfm8NeumaiMgPFiJm89/4/LTwHWdhTuWnRecfEe/9k/WOVtELReRmDhaSNW/wsaefnghB7Me/9awniz5b09qKfO8MwDMNIjaSjIn+HPlv0Y7KW0Q6RtETwEHw4tEQu2+SSkZbIjUNLZNaLPFMjab0sy86WdC/JT2Nupc163pD0C5JrO+emkLyxV3n2iLx2PFslNNoihfcgyV+Ef58D8NvY8VHtNtk3QVzDMAzDMBJjBWGbSFo6y7ITJD3Uhpn8liU0kx9RTm3HTH6VfjGTTwFJM6g3ukLSOJIfiRz2aQBXjPyH5FmR4wMAJH0sRVzDMAzDMNJiewhbpAMz+YtIHk/yzl7k1yvaNJN/RtIP+tRMPgVmUG90ywcALBEzoKRfOedm1xz6HYAnASwVcxwAa0jaLG9ixDAMwzCM/sVWCJsgaYO6lshGxeDroSVyTefcXmUpBmuUU2+osdBoxBPBQmNSUE4dhmIQqLaM1q8AbyLJJl6MlkggJgPn3Nm1/yc5R9J5sccBzJPQMAzDMIwSMdIS6as02wz6UpZlp0hapui8YzJiJu+9v6vFTbEzg9VEsxXU0uK9vzdHWGbDovMy+h9JS3vvZ0feqJ47KSVpowTCMvLevyCp0T5iwzAMwxhoTFSm5EhiWAlr1Uz+6bAStmJJzeRntmgmf2swk199kMzkUzCGQb3tIzRaYX9EbuMnefYYx28GcFvMsQKLANg1QVzDMAzDMBJhBSHeaomUNF3SpWhuJv9wMJNfqYRm8kfXKKcu1+SSEeXUjcqknNoNeQb13nvbR2g0RdL+kUN6AL8c65djFYvdkqLt1TAMwzCMdAz13qYOzOTvJ3kSgJ+TnN307AFB0lLe+0OH0Ew+BXnCMrZCaDRE0paS1ooc9o8k/9Xg9+cAOAHxvwfeJ2n5JmMbxlxIWhzVbpS1vPcrAFiG5JKoKnnPD2BeAPMBeBnA8wBmSXoZwAvOubsB3AXgDpJPF/IADIT98isDWAPAqt775QBMJDkRwNtQ/RuOAzAewAuo7rmfg6oA3TMAnnHOPQrgAQAzUb3ner33j8SQtBCAVUd+vPerklwIwKKovh8XRPV+8UUAbwB4BcArkv7lnHsIwMOo/h1vL9P9cpkZyoJQ0gQAH5N0FJr7BwLALSS/B+DcMq2CSVrZe39EG8qpvyN5HMkZvchvQLkFwOuo3riMsLakhUm+VFBORp/jvT+AbNSd3j4j3oMNfv+k9/5KADtFHbjaebIvgG9GjtsTJB0s6UPdxiH5U5K/jpFTLZLmQ/WGew0Aa3jvJ6B6s70AyQVQvWGrz+U7JH8fO5dukLQOgPd477ciuZWk5Ud+1+p7YeQ86S0tL+/9MwBuCo/3cpL3Rc57QUn/122cYEN1aoycikLSEqj+DbckubmkjVDz3dfOZ1re3xLAHO/9nZJmOOeuB3ANyfujJF8QkiqSun4vkryK5Ldi5AQAkt4OYFvv/bYk3yVpjbrxWs2r/m/4mvd+hqTrnXN/BXAlyVdj5d0JkhbvVlhN0oqx8gks5L2/KnLMEWY553ZvdlLcO5A+R9IS3vv/JnkYGvsHjjCN5IkkL0udWy+RtL73/kiSe6P5pMAbkn7tnPs6yXt7kd+g473/B+oM6UluR/JPBaVk9DGSFpD0OHJu5LvgFZJLk3y5ydh7SYpetAC4l+Sag+i7mmXZSSSP7DaOpJ9UKpWDI8RZBcCOkt4NYGMAK6HN7R4kP0byZ93m0i2StvDe701yCqorSb3gPkmXO+fOIXlTt8EkbSDplghxflipVP6r2zi9RtKqAPaWtDOAyej91qNHJP3eOXcRqgXinB6P3xWS5pEUY8XsBudcV9tRJE0EsE/YrrBRhJxa4RUAV5C8GMDFRRSHkpaR9Fivxy2Q55xzizc7aShWCCWt4L3/nKSPk1ywxcueBPCqpE977z+dMr8es1DwCms2GTBL0o+dc991zj3Rk8xKgqQbcvwHNwNgBaGRx+6IWwxC0gXOuYbFYOBSVNvv3hZzfFRb8LcEMLRt5SSbiXGNSWjX2l/SVEmTI6bVcyQtAuATkg6StFbslfAWWI3kZyR9xns/neR3AVzQRbfPGs1PKReSFgSwr6T9JTXTWEjNCiQPlnQwgGezLDvfOXcayVsLzqvXrCPJkfTtXihpO0mHSdoJ1RbeXjIewJ6S9kT17/cT59wPSD7a4zyMOoalIPwjyVXbvGwpxDduHgSGzUw+Os656yUdVntMkgnLGLlIOjB2TOdcw3bREUi+lmXZ+SQPiZ1D8CQc2oIQzdWZRyFpgvf+yDb2c/ctkt7uvf+MpEMALFx0PoHJkn4F4HhJR3bY/dOK3kApCFY4nw7FV9MVhgJYnOShkg713v8jFPsXdVIkDSDjUd3f13LnlqStJX1d0rbJsmqPxUkeI+nILMvOcc59ieQwrdz1FaVXGZX0NgCTis5jAHgkKKeuOGRm8ikYpTQKs54wcpC0HIBtI4d9DMBfWj3ZOXdW5PEBACQ/HFYWhpWJQSilJSTtIek+ksdigIvBsMfuaEl3kzwK/VMM1rK6pEu995dJakVH4E2896VfIZT0tizLvilpJsn/QX8Wg/VsIel8SXeGlfXS398CWL+VkySt6r2/QtJ1iP99E4N5SB4g6d4sy74adD6MHjMMb5hNMWR7JdvkHpIHkVw1eAj+p+iESsD9AOpNRpcNN/+GUctBACoxA0o6q512OJJ/B3B3zBwCCwPYLUHcQaLpKmFQeT5f0oUAlu5BTskIe1Lvk3QC+rMQrGcXSbdJmtrqBSRLu0IYBE/+OxSCx6CqJDlorCnpLEkzwr7b0uK9b1gQquqtfbCkmwHs2KO0umFBkl8ORf27ik5m2BiGgtBWZsYmI7kxyVLZaBRNENKYnvMrey0abxK+rFu+EW2VVttFayF5Tuw8APMkRJOCUNJ7Jf0TQNeqpkUS9ulfHgSKlik6nzZZTNJZWZadpqoVVTNKuUIoaRNJ10v6PuLvKS6CDSVdk2XZeUE8pXSQHLMglLSspD9IOg3AoK24rSDpj2GVet6ikxkWSr+HMG9DPsmjAfyxgHQKRdLZANauOVQBsCGGe59PEiRdT3LHumOHSFqthcvnDVLyrbIQWnsvyzl3mBX/fcM7Eb+d/QaSnaz2nQXgeERerQSwnaQVSD4SOe5A4L0fsyCU9HFJP0TVm21gkbS7pJ9iwIuIIFSyjqQ9SD6Zd46kpYNITmmQVAFwjKTjUMJ7wtC6vp2kT5G8sOh8IpNbEKqqhPtbtGar1q9Uwv7Cd0j6IMlnik6o7JTuzZ9DnkLbbwbdy6YTsiy7juTadYc3hxWE0XHOPSWNUtx/n6T3tXJ9QiW+0wF0Lb1udI/3/sAE3oNnd3jdo977vwDYLmpC1S6UqQC+HjnuQEByrbzjWZZ9W9Lnep1PTCTN570/NQiOlIWtJf1D0o4k78n5fanaRVWV3/8VqpNTZWaipAuyLPtf59znSL5RdEKRWEnSoiRfGDkgafvQfl6WiYutw8r1TmO8J41IlLplNOzZqm9feQ7AzALSKZxg7DoX3ntTv4yIpHd476+U9IOicxmDgZawLwuSJpDcI3LYNwB07ClIMom4jKp2A8O6j3vUCmGWZV8nOejF4OKS/kCyTMXgCCtJ+qOkvNX70rSLStpU0g0ofzH4JiT/W9JfJA30Xt0aCGDdkf9I2kfS71CeYnCEVSRdK6lXXolDSakLQuTf/E4fRLPkSIwqCHP88owOkLS99/7Pkv4K4L1F5zMW3nsrCPuDvRB/X8dvu2yruQjArFjJ1LAygG0SxB0EVpY0/8h/JB1K8otFJtQtktaQdCOAMos+LBuKwhVrD5ZFYTS0+f4Vg91S2ClbSPqbpFL8LRHaRiW9R9LPMeAt6A2YGPZEtmshZ7RIqQvCvJtfSXliH8PCXQBeqju2Uolmy3pKEAXZ2Xv/d0lXYQBukEhaQdgHpBBbIdm2mEzd9a9I+k2sfGoJnoTDiAOwGgBI2lnS/xacT1dIWlfSXwCsVHQuPWDFUBS++f1YBoVRSR8N4j8LFJ1LgawsaZqkTYpOpFu89+uH1d5L0HuT+V4zUdIVkpYsOpEyUuo9hCRHqTo654a2ICTpvffTAbyn7lebA/i/AlIaSEL72wclfQnAxi1cclPYzN6qWe6LTc6lpF0B7NRivFrWlrSg2YsUh6SVJcVeMXsOwO+6DeKcO0vS/hHymQuSe0k6nOTLsWMPAGtKejwIrwzsJKyk9SRdA2CJonPpIZMknSdpe5JzMOAto5IOkHQGBvh1GJHFJV0p6T0kbyk6mU4huZ2k3TB4SqKdsqqqfpPbkWz1nspogdIWhGH1Jm/2J880fGgI6pdzFYRhH6EVhE1Q1eh2L0lfRE3ffgP+TvIbAH4Xo005jL9nGL8VQ9obACyJuWfz5wGwEYBp3eZjdIb3/mOMrCYj6VfOudcjhPozgAdRbfOMyQQAe6CqZjpsrOW935PkwHZiSFo+qBYOUzE4wru899+U9AVJsd8XPUPSFEk/gRWDtSwm6SpJ7yR5V9HJdEgryuVl410APgvg20UnUibK/MGwBoBF6449QvKJIpLpF5xz/6g/ZvsIGyPJSfqQqmapv0LzYnAayV2dc1uR/G23xWDN+HeEVp9mxeDI+JtL+kPO761ttCAkOZL7xY7bifdgHiQl6dwYsepJ0SY7CEg6mOReRefRKUFA5ioAyxedS1EEEaCjMKD7syRtGb47SrsI0AVLSLpcJfUqLCuSvi5pvaLzKBNl/nDIMwEf2nbRGkYJywCYLKlCMut5Nn2Mqoaoe4cVuVb2jkwjeSzJKB6XHY5/IsnLRg4456ZLOqT2JBOWKZTtAawQOea9iNj5ENpGv4iqgl1M3iVpEslhU3keWOGOMBl1Lga8VTIClPSNopPoBFW9Ey9CMXsGXwdws6TbnHMPA3gEwCt4S7xqAQALAljae78CyUkANgGwXI/zXEXSJaENMUanhZGe+SSdIWkLax2NQ2kLQu/95PquLJJDXxCSfMp7X98SthCAtQDcUUxW/YWkcQA+IukraM04/GqSXyY5avW1y/G/DKAVRa1pYfw/5fxu1GvehGWKI5H34FkxlZNJ3u+9/xuArWPFHAntvd8PwHGR4xqJ8N4fT3KHgoYXgLsk/dU5dweA+wE8BOAZAK8FEaR5UW1HXgjViZbVvPdrkNwG1UnhgVzRi4WkeSSdB+DtPRz2YUkXOucuA/A3krPbDRCEfHaUtBOAXdCbYnYr7/23ABzeg7H6mdkA/glgpqT7nXPPoapr8BqqojXjACwSCviVAawHoKh2+MkAPoQu7JaMtyhtQTjGTe9Q7x8cIewjrN8LsQWGvCCUNB7AxyUdheaz+kJV5v+rsSYaJM0HYP9QCDabIR0Z/2skG72u70R1RnZ8zbFVJS1O8tnuMjbaQdIikj4QOyyAX0aOCZJnSYpdEILkAZK+ajO6/Y+kbSV9odfDArg2eGJeTvKpRieHYuP58PMIgOveDFT9PN9O0lQAUwDMlyzrPsV7/0WSvVK/vorkKQCucM519f4OW3vOBHCmpEUBfFTSEWhtgrSbcQ+T9BeSSdSW+5hHJP3SOXcNqkX8K+1cLGk1ANtK+giAbdHD7WiSjpd0YZsdbnMAPNDl0IsCWKzLGLV4VCe8UvBCorj9j6R5vfeveu9V85NJWrjo3PoBSUfUPTfKsuwnRedVFJImSDrce/94/fOS85N57y9TRINUSePD+I+1MX7Lctne+2vr40jqW6/EsiLpky38fdv9idKenJPrwt77VxLkK0nvTpFzLLIsOynF407481yzH0kfbec5kLSQ9/7BHj6GN7IsO135ZvBdI2mxLMuO9d4/3wd/L3nvlWXZD1I81prHvKH3/o0ePJZ/SEpubh9WOw/0rX1PdvPzrBJacUmap+jXXs3P5ZK2C4J1sR7fclmWfc8n+v7I+5F0YKz823icR8V+3fX6MdRTVlGZDQDMX3fsHpL1HnzDihnUo3rTI+loSQ9LOhmN22pmS/oFyXWcc1NI3hxp/MMlzQzjL9PgdA/gApLrhvFntDFO3gqmtY32mBRfWt16DzaI+5KkS1PE9sPrSdgpswD8nuSXSH6I5MYkJ5KczzlH59xizX5ItiUU5KutcysleTSjuYDk6pVK5eBU+0tJPlepVI4nuYqkk1BdISgtoXg6E2lbZl8meTjJrUj+NeE4AACSc0j+nORaqvp5RmuTr2MxST9MFLtfmEZyS+fcLiSvidmxQfLRSqXyGZKTJJ0fK24jwn1c7D3vQ0dZC8I8Q3prF32Lm1Dd7F3LOsOygippiSzLjpP0iKQT0HjZ/42RQrBSqUwleXeE8RcP448Uoks1OH2kEF3LObdXJ9LYed6bkqwg7CGS1ka+0FU3/AfARZFjvolzLolFBMk9JC2UInaJeE3Sr0i+j+Rizrn3k/wGyQtJ3kzyGZJvpBhY0sYkD04Ru44nSO4ePtce6sF4IPl8pVL5PMktAdzeizEL4mBUJ8ZTcSfJySRP7XX7N8mXKpXKYSSnAEi1qrKbpD0SxS6SV0l+juQ7Y2kejAXJJyqVyodJ7om3RIRSsQbi73kfOkpZEPocFcVhNqSvJ6ho3Vp32KGq7lVaJC0ZCrGZJI/FaFuSWl6XdDrJVUMheF+E8SfWjf+2BqePFKJrh/Hv7WJoWyEsGO999NVBSb8hmfKL9koAjyaIOx5VIQBjNLPD584qlUplH5JXsWqI3hNU9e/9HtLfG9xMcjOSFyceJxeSN5KcLOnsIsZPiaRFJR2fcIj/I7l5jMnRbmDV0mkyqirL0ZF0YhB4Kwv/JrkNye/2sogneRHJrQE8nHIc7/1BKeMPA6UsCEnmzcTbCmENkvLsJ7boeSI9QNLyWZadIumhUIg1Wgl9RdKp4YbsEJL/ijD+klmWnVAz/iINTn+95oZwKsn7ux0fwEyMnkldVlKjFlUjEpLmIdnWHq5WcM4lvZkl6VX13YyOhtSTsAk3klw3fO78u6AcPgAg6X4wSeeFNsOuP1u7geTrzrkDSH4R6doPe473/hgAS6SILekMknu0KzqSCpIPknwHgFsShJ8E4FMJ4hbBP0luQfKmIgYneTvJ7QA8lnCMvazzpDtKVxBKmgBgzbrDbwC4rYB0+hbn3KiCUFKp9hFKWikUgveS/DQaS1e/HArBVSuVyuEkH48w/go1hejRqPotNRt/5XBDGO2Dk1VLgrwvgk1jjWE05P2IL/v+OIBrIscchXPuzESh3yFp2L3t3kTS90lu3WUnQIw8vph4iAudc/uRfC3xOC1BUiT/H8kjis4lBkE9+r8SxT7HOfeJNtUck0PyKZI7ojrxGRVJ/yOpCP/GmDwcWs8fKTIJkg+QfB+qqucpGI+qRYnRIaUrCFFte6zUHbuVZjZaT94K4ZY9zyIBklbJsuw0SfeFQrBeYKiWlySdSHKFUAg+EWH8dgrRWWH8FcP4SVYG8oRl8lqrjfikWA0L7cTJb8xI/hNAywJG7eC93zdF3EFD0omVSuXTqfYEtpHHLkg7SXQJyb172QLbKmEv3FFF59Et3vvPoOrLGJtrnHMfY0S/05iQfJLkTgBiCwcuCeCAyDF7yfMkd4w5wdwNJP9J8shU8b3370sVexgoY0E4ql3UBGVymYmqwW8tS0pasYhkYiBpnSzLzpZ0TxBFaOSz+Yyk40MhdgzJ5yOMP6muEG3ke/Vs3fjPdTt+I/L20NIM6pMjaXEAO8eO65xrSzWyG1j1hEsR9wBJ9ZN3Q0UoBo8pOg8AkPSZhOFvJblvPxaDI5D8tqTTi86jUyQtSDJFi+OTJPcpesKiGSTvJXlo7LiSPhfTlqGXkPx40Xs9czgNwJ9SBCb5PlMb7ZyBfJE3Ik890QRlRhNm+vJWCQeubVTS+qEQvJXkfmhcCD5F8phQiB1HsmvDTknrtlGIPh0KwUlh/K4L0RbJFZaxD8/k7Iv4htgzSPZSIfGXGK1KHIPlAGyXIO6gcLVzLnWLZktIWhVAKn/I50ju3i/7zhrhnPs0gBuLzqND9kJjobKOCEXFk7HjpoDkLxFfeXkSgAEQMK8AACAASURBVO0jx0yOpB+T/E3RedQT2rQ/h6qVVmyWAbBOgrhDQekKQuSrJ1pBmAPJUQWh935gCkJJG3nvz5d0SygEG602PELyCJIrkTyR5H8ijL9BXSHaaPwnQyG6UigEX+x2/HYILSP1+yIXA7BKL/MYNlK0izKR92CD8Z4FcEWK2EPsSfhMWHXpi/1Y3vtDASSZHCJ5CMkHUsSODcnXSe4N4NWic2kXSZ9MEPZykpcniJsMkp9B5H1q3vv9Y8brAf92zn2+6CTGguTNCT0K35MobukpVUEoaSJGm+nOAtBvS+b9wkAa1Et6p/f+Skk3oSpf3+hGZibJT5BcjeQpJLv+ope0lff+dzWFaKP30UMkP0VyxViFaBeY/UQPkbQRgA0jh50D4LzIMZuSsG10d0mN7F9KCcnPkny66DwAQJIj+ZFE4S8jeWGi2EkgeT/JrxWdRzsEgabY392eZN8WFWNB8l+SfhQ55m6D5NNM8mimtSTqGufct1PE9d5vlCLuMFCKglBSRdKHJV2Z8+sZ7LFx6gBxA0bLbW8sad4ikmmGpPd67/8i6S8A3tvk9LtJTiW5Jsmfxtj/IGlb7/3VkqahqhzZiPtJfozk6iR/1A+iRiRNWKaHJFr9uqKg9q3fAkhRwMyPaqvbMPG3Xq/yNmEbVFutYvMKyRSrVr3g2wDuLDqJNkjh63kpybsSxE2Oc+5kVNXlY7EAgB0ixkvJbQDOKTqJZpCcgfxtS93G3SB2zGFhoAtCSeMkTZV0h6TzkDMbb4IyYxP2z91Td3gBAH31hpK0vff+76Hgb+aRdQfJ/UmuS/IXMUQMJG0TCsE/oXk7wszQIrUWyZ+RnN3t+BExYZkeIWlcaD2LCslCjLRJzg6fsdEZNk9Ckl8qOodavPcpiglI+gEj2PcUAcnZJL9SdB6tImmP2DFJfj92zF5B8jFJUffPee+nxIyXCpIn9asabD0kU4ijrS1pXIK4pWcgC0JJ4yUdLmmmpLMw2nfwTUxQpjFjGNQX3jYqiZKmeO9vkHQVgC2aXHJrKAQ3IHl2jL05oRD9h6Rr0bwQHClE1yB5ep+q6d2I0SvCm0hqJIJjdMYUABMjx3wR1ZW6QnDOJWkbBbClpDE/w0vGdSSTKOx1Cslm3Q6d8HKqlrAecjGAW4tOohmSlkP81vR/A/hL5Jg9JbYSM8n3D4Da6KMAfl10Em1wIeKLy4wDYB63HdDvL+65kLSwpKMlPSzpZFRV6pphK4QNyDOoL1JYRpKTNEXSjZIuRfM9bn8nuSvJjUIh2NWHS00hOj0Uos2ei1tJ7kVy/ViFaCpYtbaoF3dYEA0mVIzOkHRggpi/irEHtlNCi08SddMBFG3oCJL/W3QOtQSboUkJ4v68X/ZIdkpQQzyx6DxaILpSr6RL+vm7rEX+AKBrFfEalkCff1dKOrfPupIawqrvcgqf277+O/UrA1EQSlouy7LvSnpM0gkAFm/x0qdIPpIytxLwj/oDRQjLSJpH0v6S7gqF4MZNLvkzye2dc1uRvKzbFomwD3UfSbeH8ZsZNE8j+X7n3IYkLxiUFo08g3rkeHcanSNpKSTYb+KcK3zfWaq9bySnDoEn4VOorjr1E0kU+ZxzZ6SIWwC/AfBs0Uk0wnsfvSB0zl0TO2avCYVR7FXOrSPHi4pz7pdF59Aukv6aIOyyCWKWnr4uCCWtkmXZKcHo+zMAJrQZIvqG1RJyO0ZLNK8WDLWTU7MP9J+SzgSwepNLpoVC8N0k/xhh/HnD+HdKOhfNPWymkdzVObcNyd93O36vyWuhNmGZ6OyPxl6UnXA/gL9HjtkJ5wJIsXKwDJoLRQ00kn4TQ9wqJt77LROEnUGy71stW4Hk65L6WqCD5DYJwl6XIGbPIRm1sPXeN9u6UiT3kbyt6CTaxTkXvSD03qcQySo9fVkQStooy7Jfh0Lw06gq0Y3Fa5J+DOCC+l+QHFSD2Z4R9rrdVH8YiVeNJC0g6TBJ94d9oKs1Oh1V+fLNQyEWoxAcJ+kQSfeE8Zv1nP+B5DvC+Jd1O36B5AnLNFsNNdoglfdgP6xCB5GQq1LELrsnoXOu31YHk7z3SV4SO2aROOf6dk9WsGyJ7SX7JMknIscsiqj3gCTXjRkvJpKuLjqHDkkxefT2BDFLT18VhEHN8TJJM0juhcb5vSzpVJKrViqVQwEslXOO7R9sgTxhmVT7CGsEge6TdCqA5Rudjqox7mbOuV1Jdv33lDSfpINDIfpjACs3ueRqkls453YkWYZZ0xmoetnVsoGkRpMuRotI2hzAWrHDoo9kxBN6Eu7Wq86EAvgPgD8XnUQtkuZD846ITrgiQcwiuQH92za6MRr78HbCvZHjFcntGC2k1g1rS4r9fEfBOddXYlVt8AiqfuHRIGktox3QF+qCkraXdLykrVo4/RlJP3DOneqcey5c74IJ9FxhkW/EbdThnLtemvszM/Y+QkkTAHxM0jEAlm5yugfwO5JfIXlzpPHHA/i4pM+juefWyPjHl22VmeR/vPd3AViv5vC8ANaHTaB0jff+QDL6/cJfSdaLARXJJaiKNcQ2lB8H4MMAfhg5bj9wQ7+1i6Lanh/bc/ZpjO44GWhIZlmW/YHkPkXnksP6CWKu4b1P0gXQa8J9TYZ497oTUJ3E7kdtimlFJ9AJJOW9vwfNdRvaYcmIsYaGwgrCIN+7s6SvSGrlhfAIye8C+Ilz7j91v1sHwEJ1xx4g2a+zev3GKGEZAFtIYgSxloUBHBoKscWanD5b0nnOuW+QrPdH7HT8QgvRfkTSdJLr1R2eDCsIu0LS/JI+HDtun5mYg+RrWZZdQPITsWOHdtvSFYSS+rG7ILq6KIDp/dDaHBvn3HWS+q4g9N6vmmACakkA28cOWiJWRP8VhM8Oqudn4FHELQit46kDet4yWiMiMqIm2exFMJPkESRXJ3kKyfpiEMixJhhDTdHIgeSjAB6rO7woGu/ra4ikJbIsOy5YhJyAxsXgG5J+QXLtSqUyNUYxmGNR0qgYnD0yvnNuSpmLQcCEZRKyO+Kvmr0G4KLIMbsmoSfhZEn1kxUDj3PulqJzyCGF3URZPzv7ctWTZOz9g0Zz+lGw5I6iE+gGSbH3rFpB2AE9KwglTQh7xx4IIh7N1CRvqTH6PoXk62OdmHcza4b0bRPFoF7SkqEQnEnyWDS+QX5d0ukkJ4VC8P52x8sZv9BCdEDIE5axgrBLEnkPXkwyppdWFEhOA5Dk/eK9n5oibsHcVXQC9XjvV4wd0zk3cCqHLXIbRu+97gea7YE34tN3+9Mk3V10Dl3yVOR4C0SONxQkLwjrbtBPRvM307RgNL5xq0bfJPMUMa39rQ1IdiUsI2mFYBHyUCgEF25w+itBEGiVSqVySFih7IqiC9EB4zZUV55qWTO09xodIGk5AO+OHbcfvAfHguS5ieLuJyn23rYi8ajahvQbExPEfDBBzMIh+SqAh4vOIwdTU+wx3vu3FZ1DPc65+g6vgcI5V2991i22QtgByQpCSUtnWXaCpIfDDXqjlZoRNcktR2T9W92HENQR66WAMwBlbV1JxaiCkGRTzx1JK4VC8J5gEdJoZmZWjTLs4TF63iUtX2QhOogEw976mXyHqmKd0RkHAIhtrP4kElk8ROJsVIud2CwFYIcEcYvi6T4UlAHJJRKELfNn6r+KTqCWMGlik3i9p16voh8YdJuQVyPHs4KwA6IXhJImhRv0B0keDWDBBqd7ABeQXC/s3coTN2nGhqiq09VyJ8nYMw5lZzpGt8SsLyn37ydplSzLTmvRK/IlSSeSXDEUgl1/eNUUovcWUYgOOmPssbW20Q6QREn7J4h7TvAJ7UtIPgwguqkwkMbLsUCeLDqBMYht8TEH8Vu/+gZJfVUQovr360sLhJIzoegEchj0grC+Y6lbXL/ag/Qz0VRGJW3ovf+spH1INpspf13S+c65r5G8r8uhR7WLSrJ20TYJdgR3Atig5vC8ADZCjZyxpHW9959v8e88YhHyPefcizHylLSK9/5oSQeRbPb6fUnSj5xzJzrnno8xfllwzk2vtxqRZAVhZ7wDwKqxgwZlw34XjbhK0rYJ4k6RtATJZxLE7jX9+hjGR443q5UtHgNMvxX2ixSdwJAyX9EJ5PBy0Ql0SZk/NwaGrgtCSdsENced2Vz/eJakn4cb9CirNN77yfXDmqBMZ0j6B8kN6g5vDmCapPW990dK+ijJZivLTwWLkO/nWIR0mts6oRBspxA92TnXd4IcfULepIkVhB2QyHsQki6OHnRwGAdgbwDfLzqRCMRuh4pFfWdNt/Tr44xFlO+yiPRjYTIM9OPrfEzRRcNolY4KwuAhOEXS/0hqRXjkSZInA/hRrJWiEUjm2VaUyky8VwSD+kNqj0na3Xv/Hkk7tXDT+zDJbwE4o5EqbDtI2kjSlyR9sIVC9HGS3wZwWqxCtMTcA2AW5t4PsZKkiSSfLiingUPSeEl7FJ1HGQlto2UoCPv1Zi12QRi77auvcM69Wt9VUTCx/35Ga1hBaJSSlgtCSW8DsAqAdSUdhaoZfDPekHSOc+7nqL6JVo38gTq/pHr7ijkAxknaJOZAQ0LeF/rWLVz3uqSfOefOBjAb1ddIt7ksFmxKdkLzfRKP1BSipb4piQVJ772fAWDbul9tCuCK3mc0sOyF/hQZKAMbS9qA5K1FJ9INkvpOUCYQW0Og7G1f/VYIlEmJd5Dot9cBUL3vMoyuaGeF8CBJ324z/jiSB0k6qM3rumEeSX/v4XgGMB/JQyUd2uNxHyD5TQBn96OKX78jaTrJbesOT4YVhC1TMvGTvsN7vz+AzxadR5f01bJSDbEFi8rewthvK3IpFH6NJpgegVFWWp4h9N7nef0ZRhHcTXJ/kmuQ/KkVg52Rt9fWhGVaR9LKqArKGIkgOVVSv92Il4XYn5ullnr33jdSTC8CWxUqhn5TmzWMKLRcEJK0G0WjaG4n+RGS65A8u58l+QcEs57oAu/9QTDZ99QsDmCnopMoKbELwn4rmGLTyNqoCGwitBjK7LVpDDEttYxKmhhmww2jCF4ieQCAS0j2a/vVwEHyIe/90wAm1hxeStIKJB8pKq9BQJKTNLXoPIaB0JZ7SdF5lJBZkeNNkDSB5KBL4I/FEkUnUEcK4bQMwMMJ4pYJ+240Skmrewjz2kWfAnBbxFwGibUBLFN37B5010qwMYDF6o7dCmAYFR/fDaDWWmJ+AL+zYjAJ0zF6BWYy7EuvGe8BsELRSQwJO0tamuSgmy/3Gyn8EZdF9buwdJBcvugc6ng2QcynnHOTEsQ1DKPPaakgzPP6k3RWpVL5fJKs+hxJX5D0jbpjv69UKkd0GtN7fz/qCkKS+5G8vdOYg4r3/jYA69UcGgdgA+R75xldEIRl5ioIvfeTAVxUUEoDgff+gBTeg0Yu86DqSfi9ohMpE5KeTfAaLm1BCGC5ohOoheSL3vs3EFfspuxtv4ZhjEFLewhJjlohdM4N8835qMee9xy1iqTFULX0qOUVAP/sNOYgI8n2tvUAScsAWKv+uO0XboykRUh+sOg8hokeK1UPCym6T9ZMELNwJFUArFR0HjnEXiVc2EScDGM4aVoQSiLyb8aHuSC8EaOlxDeS1Kkv0GSMFqe4iWTZfZ1yyVO/DKtWRgQkrZhl2Q8kPUByr5xTNpEU26OsTHwENpPea9aVtHHRSZQJ51z0vWLe+41ix+wT1kZ/vudjK14SVSEnwzCGjFZu+lbG6M3UTw6z6ATJFwDcW3d4fszd5tgOo4qdMVbJhoVRj91WrbpH0qQsy34q6V6Sn8LYvmGLAFi9h6kNFJIOLDqHYcR7f0DROZSMB2MHJLlh7Jh9Ql9ORkh6IEFY2xttGENIKwVhXivkMK8OAgAk5T0HHbWNStq0/ljeKtkQcTuA1+uOrSlpoSKSGXQkrZll2dmS7ib5MTTec/IsyS/DpLVzkbQGgM2LzmMYIflRSWU3P+8lKYqJDSQtnCBuoXjvtyo6hzFI8TcsZduvYRiNaVoQ5hnSkxz6gjByW6MV3TUEo/lb6w479Oksbb8iad1QCN5Bcj80FpF6WtLxJCeR/HqJpeO7IngPGsWwGIBdik6iRNyL+F5286KqwFsqSO5QdA55OOfuih3Tez9qX7lhGOWnaUE4hljK0BYrNUQRlpG0HIC31x1+DgnaeQYJE5bpHEkbhELw1lAIVhqc/hTJY0iuVKlUjiP5Yq/yHDQkzUNy36LzGGaCJ6ERgTDxFl24zHtfb2Mz0EhaH8CKRecxBjNiB+xGIM8wjMGlYUEoaR4A9XsChAQfQgPILRjd1rh2B+0yuYI9w+65Z8Iy7SNpS+/9ZZJuDoVgo/f3IySPILkSyRNJpjA5Lhs7YLT/qNFbdpRUP4FmdIikm2PHJLlbmVp7vfd7Fp1DA+4BMCtyzC0lzR85pmEYfU6zFcL1AIyvO3YfyRSGqAMFydcB3FZ3uO22xrwiZ8gFZUYwYZkWkbRNKAT/hmpLXSNzsQdDIbg6yVNIvtqjNAceE5PpC+YBYKu0kXDOXZ8g7OIASmHLEroC+rZNnKQHcFPksPMD2CJyTMMw+pxmBeGo1oExxFSGkhjCMnlFzpALyoxwN4CX6o6tLGnJIpLpR0IheLWka9F8b9VMkofUFIL1q9tGAyQtDtu/1hdY22hU/pQiqKRPpIhbADsDWLboJBpB8prYMft8VdQwjAQ0EpmA934yOfdigxUrb+Gcmy7N3dkpqeVVLEmUtEnOr27sNrdBh6T33t8EYNu6X20C4IreZ9Q/SNpe0tcltaJ2eQfJkwCcO6y+lpH4KMa26eiGh4KQj08QuzAkLSHpUaR5ztaWtJmJm3UPyXu9948CWC5y6PdIeifJv0aO21MkHVN0Di1wFYDjYwYkuaekI0jOiRm3l0jaSdJXI4Z83Dm3a8R4htFXNCwITVCmKd2uEK4G4G11xx4l+e/OUyoPkqaT3Lbu8GQMYUEoiQB2kfSVPJuSHG4l+Q0AFw77ftQYpFqVIvnzshWDAEDyGe/9bwHsniJ+8CS076IISLoyRVukpGMxwIqjknaRNAitk9MBPI/R9xLdsBSqHRGXRIzZU7z3+5HMm3DvCEn3x4plGP3ImC2jkhYEUC8/PBuj7QCGmbsBvFB3bIU2RA/yVhNtBTaQtxrdzgpsGZDkJE2RNEPSpQCaFYN/I7kryY1IXmDFYPdIWg/ARilCAzgnQdy+gOTPEsbeR9ICqeIPE865CxOF3k7SlESxkyJpHknfKDqPViA5R9LFseNKOip2zF4haWGSUVv8nXPXxoxnGP1Goz2Em2L0CuJtJkLxFuFmO29DdysrOLmCMiStIHyLvOdiKCSxQyH4IUl3hkKwWUEyjeSuzrmtSV5mhWA8vPcfSxT6jyRTGEv3C78H8K9EsRcBYO1bcbgaVauj6Eg6TVLMlate8XkA6xedRKs4585LEHYrSe9KELcXfBTAhMgxB7r92TCa0aggNEGZFsh7Tlq1RxhDNdMKwgDJhwA8VXd4SUnLF5BOT5A0TtJUSXdLOh/Amk0umUbyPc65bUhe1oschwlJ40jukyI2yZ+niNsvkMwk/SJVfBOXiQPJ2ZJ+kyj8273330kUOwmS1pT05aLzaJNrAETfaiLpe5Ia+dj2HWF19zORwz4E4I7IMQ2jloZb+HrBmAVhXlFjgjKjyXtOWjF2DR+yG9QfhgnK1JPneVm6ttFQCB4s6X5JZ6G6v7QRV5PcIhSC0VXmjDfZBcDEBHFfxADvz2kV59wZqH6upeB9ZZ4c6iXOuR+mik3yQEmHpoofE0kTJF2AqvXCwBAmX05LEHojAJ9MEDclU9H8+7MtJF1kXTdGYsYHrYjCGLMgNEGZlsl7Tia38IddF/kej/V7EoeaPE/GMhnUSxov6XBJD4Yv9EY3uB7A5SQnO+feSzKFh5hRQyrvQUnnkfxPitj9RGiJTdVq5VBtDTO6hOTNSNidIukUSdumih+DoPr9M1S/mwcO59yPAES3E5J0oqS1Y8dNgaSFJX09dtyE+2yNwSW2GFwFo2uCnpJbEEqaCGClusOzUBVRMWog+SiAx+sOLwZg1SaX5rXk2gpsHZ2uwPY7YSb68LAieDKAZRqcPlIIbuqcm0LSVpF7gKSlAOyQIrZzrtTtorWQPCNVbEkHFj2rWhZInpIw/LySLpG0ccIxOkYSvfcnA/hQ0bl0CsmnJKXYSzhe0q8lFXqz2gre+1MAtCrq1yr3ArDJV6OeFF7OzeqGpIy1Qpjnb3aj+ZiNSdv2E9aS2zJ5H8SbSGq0/7VvCTOYR0t6OBSCSzc4fbakX5BcOxSCN/cqTwMAsB+AeRPEvWfIVncvxGg15lisDmAQrAEGgfMA3JMw/iKS/iBpnYRjtE0oBr9P8tNF59ItzrmvoaoGH5t1JV0gKcXnYRQkHUDygNhxSf7A2kWNHFIUhBsmiNkyuTfVecWKCcqMTZ4yaLO2RhOUaQ2STwN4pO7wIoi8RyA1kpbIsuy4UAiegOoq8li8EQrBdSqVylSSKW/SjDGQNDVFXJI/TRG3XyH5qqRfp4ofPAmNLiGZkYzeblfHEpL+IundicdpidCy/2uS/1V0LjEgOTO0vabg/d77M/tRZEbSdpJ+nCD0LABnJohrDD7Rt3x475N0JLVKbkGY15Jnq1cNGVUsN2prlDQ/gPpZ0gzm8TgWea+9gdhHKGnJUAjOJHksgEUbnP66pNNJTgqF4H29ytOYG0mbAVgvQeg5AM5NELevCeIySSD5keCba3TPrwDclniMxcNKYaFCM5JWk/R3DHCbaB7OueNRLWSiE/w/L5A0X4r4nSDpncGHMXpO4fv4pdhxjVLwZOyAJHeTtETsuK0yqiAM+zHybrZthXBspmP0BtONGrRXbITRrWh3kHwlemYloJMV2KKRtHyWZadIeigUggs3OP0VSaeSXKVSqRwS9qUaBeK9TyImA+AKktHl4fud8B5ONeG1MIDdEsUeKsIq4RE9GGpeST/03v9e0oo9GO9Ngi3B4ZJuRppJn0Ih+W+SxyUcYjdJV0pqtO+9J0jaU9Lv0fj7tVNedM6dkCCuUQ6eSBBzPknJFJ+bkbdCuAqAxeuOPUEylcHwwEPyRQD1qznzY+wvG2vJbY88YZm+LAglrRQKwXvDnpQFGpz+cigEV61UKoeTrBcnMgpA0vwkP5widtm9BxtB8sxUsc2TMB4k/wSgV56mO0i6Pcuy41Mb2EtykvaSdEvYv933Iild8H2k9c17Z3ged044xphImj/LspOCV2+j79iOIfltks+kiG2UgscSxf1QlmXfKWK/bl5BaHYTHTBGQZfbNmqCMm0zA+2twPYcSatkWXaapPtCIdjIx+olSSeSXCEUgilmmozO2Q1AipvTZwH8NkHcQeEXSLMRHwC2k7RCothDB8lPoeqV2QsWIvkVSQ9lWfYtSVFtHyQtIelTkm4Pe1n7StQmBSRnkzwQaQRmRpgo6XLv/SWSJiUcZy4k7SLpdpJHAkilMPwwgO8lim2UAJLPA0jS7UPys5JmSPqEpEbbjKIyT/0B7/1kcu73WF7LnjE3zrnpkvarPRYKv1EbnU1Qpj1Ivui9vw/AGjWHR/Zh3lJMVlUkreO9P1rS3iRHvZ/qeEbSD5xzJzvnzG+yT0m12iTpbOfcGyliDwIkn/XeX4o0e7YcqobUqUVRhgKSj0o6UtJPejjswiSPknSU9/5WSZc7564F8DeSLe+JC6InGwF4h6T3StoeadSC+xqSN0r6mqSvJh7qA5Len2XZ+c6575G8KfYAYfL3A+E1maeCH3U4kp+wLTxGC9yB+DYnI6wn6XQAp3nvZwL4p6SXUN0f3PG+VufcyWMtQoy6gTVD+o5pSVhG0iKS6hUyXwNwZ6rEyoCk6STXqDu8GQoqCCWt770/UtI+JJuprj0l6UfOue8652yDeh8jaVlJ70kR2zl3Voq4gwTJn0lKIuIh6SBJ3zCJ+GicAWAnFLM/cwOSG0gCAO+9fxTATEkPo7rS/ppzbhaAcd778QAWIbksgEmSVkHjDo1h4psAtgfwzsTjjCO5r6R9vfe3kPwNgP9DVRuhIwNvVX0Pt/Hef0DS7gCWiplwg3F/6py7qhdjGYONpBkk35t4GKLqT7hq/WJdh5yLMfY/zlUQhs3W9T4YQrVlz2jMLai2Q9UqXa0taeE6lapNMbpV92aSKVs7Bp6wArtv7bGwAnt6L/OQtKGkL0jak83fnY+Q/C6A051zr/YiP6NrDgCQQlZ9BklTEQauRNVGJkV758oAtgFwbYLYQwdJSTowtHAWafPjUH29rFD7kRuKRUS6SWqFDGk+G5JBco6kD0majjTvuTw2DPeRXwXwkvf+Bkl3OOceQrUVcxaqvqQe1XvQRVBV314YwFLe+zVIri9pPQDz9PDvCwD3OOeO7OWAxuDinLtG0jFF5xGL+hXC9TB6o/V9JJ/tUT4DC8nXvfe3YW7BGAdgYwB/rjmWJyhj7aLNyVuB7ZmwjKRtVDWU36WF0x8ieTKA00i+ljo3Ix71bd+xGGYxmVpI+izLziL55RTxgyehFYSRIPmipD0kXYc0So6DwnOSziT52aITaReST0naTdK1AHptz7IwgO1Jbj9SwDejxwVgLS+R/KDZTBhtcB2AV5FI2KjX1K9U5bU4Wrtoi7QiLCPJBGU64xaM3iC/bmgrSYakbbz3l4Uv02bF4AMkDyG5GslTrBgcLCS9A3PvU43FGwDOSxB3IHHO/QyjRaKiQHIvSRNSxB5WSN5O8gNIJwjU73iS+4UVroGE5E0kd0f1s8gYjSe5H8m7i07EGBxIvirp0qLziMVcBaGpX3ZH3nOVUwCaoEwHhOKqXka7AmCDFONJ2t57//cWC8E7Se5PcnWSp5OckyInIy1hdSk6ki62Lou3IPkQ5u6aiMkEALsnij20kPwzyf0ADN1nW9iX+rui8+gWkn8gWrHE7wAAIABJREFUuQ+qra/GW4jkf5EszY290TvKpA0wV0E4RguerRC2Tt5z9eZzKmkpAMvX/T7Pw9DIYYzW2mhto5IoaUrY83AVgC2aXHJbKAQ3IHk2SfuiHVAkjSeZROzEOWftonWQPCNVbPMkTAPJC0juheFaZbrMOXdc0UnEguRFYaXQ9rQHSB5DcpQavGG0yJUA7ik6iRi8WRBKWhDA2nW/nw3AhBBa525UN0vXsqKkEVnavOLlxk5VuIaNvBXYvFXtdgmGxVMk3RiW/5vFvJnkXiQ3tEKwNOwJYKEEcR8DcHWCuIPObwA8nyj2tr30RRsmSF4c2kdfLjqXHnAFyQ+V7fuZ5KUkd0YX0vUlQSQ/T/JbRSdiDC4kM5JfKzqPGNSuEG6K0SIzt5G0maQWCXLneR48mwL5xYsJyrTFqOeqG2GZUAh+SNKdoRDcuMkl00ju6pzbOMyWm7x9SZB0YKK4Z9qEwWhIvibpV6nCe++TiAMZAMnfk9wKwINF55KQq0juTrKU+yZJ/inYYt1VdC4F8QbJqSRPKjoRoxT8CsD1RSfRLbUFoQnKRCDvORspBPN8CW2PZlvcAaDeLHY1SYu2E0TSvJKmSrpL0vkA1mxyyTSS73XObUPysnbGMvofSSsjkU+Xc+4XKeKWAedcsrZRkvtLqhdNMyIRhGY2R7VdqmxcQfIDZRcFI3kPyS0BDNt32vMkdyB5TtGJGOWApCe5Pwa8FfvNL0wTlIlD3nNWUwhuknOJPcctElZa6luYibAC2wxJ42oKwbMArN7kkqtJbhkKQWv7Kyne+wNRfR3F5lqSpdhbkAKSN6GqHpyClQC8K1FsAwDJp0nuSPIQAP8pOp8ISNKJJKcMS2cUyRdD8XsIhqMNeDrJTUn+uehEjHIRJlg+iap3+0DyZkGYt3oFE5TphFxhGUmrAJhYd/xJkv/qQU6lYYxV64Zto5LGSzpc0gOhEGy0v0gALie5mXPuvST/0U2+Rn8jiST3TRHbvAebQ/JnqWKnUo013oKkgrLyZAB/KTqfLniB5Acrlcoxw9biXfM33BDp1H+LRpJOIrk1yQeKTsYoJ0FT4otF59EpDgAkTUR1RrWWWaiKpBhtQPJRAI/XHV4MwN45p1vB3SYtWnuMHJ8QCsH7JJ0MYNkGoT2qheCmzrkpJG3ldjjYDsDKCeK+AuDCBHHLxrkAkrTmkdxDUgqhIKMOkv8k+e5gTfFY0fm0yR/CqtFQ2w6QnOmcezfJjwB4tOh8InIHyW0rlcrnSdZ7GRtGVEh+k+RhSOS1m5KRFcK8G+oZwzZTFpFRhZ6kg+uPkbyxN+mUirznbK7Xr6RFJX1F0sOhEHx7zjUjzJF0Nsm1QyGYJwpklJTQLhodSeeTnJUidpkg+ZykSxKFHw8giZWIMZqw0nQOydVIHgWg3703HyD5QefcjiRntnB+irbyvoPkr0muSfJ/ADxTdD5dMIvkkSQ3JvnXopMxhgeS/0tyF4xeHOprHAB47zev/4WkgVfMKYoxVpdWyDlmK4Ttcx9Gy9UvJ+ntkhbPsuw4SQ9KOh7VldmxmC3pFyTXqVQq+9ter+FD0sIkd0sR27wHW8c5l6xt1DwJew/JV0l+m+RKYaa833x2HyV5NMl1SP5fG9ctEDmPOZHjRYPkKyRPILkyyaMxWCuGL0r6BslJJL9jq4JGEZC8guS6kk5D1cKv73FAvnS/c85Wrzqn1UJvRtIsSkiwehj1vEn6iaSHSB4LoJHq6GuSfkBy1UqlMpXkvcmSNfqdjwBYMEHcBwFclyBuWbkaQKp9Pe+QtEai2EYDSL4cZsrXJLmDpLNR3YpSBAJwDck9Q5HzrXZVRL33sQvCvhfiCX/Db4XnbHdUVWX7tXPsAZJfILlipVL5Esmni07IGG5IPl+pVD5JcnVJP8Jon/K+YsR3MK9ldFlJ1m7TGYu0cM4LqBoop86ldEjK84baucllr0g63Tl3knPu3ynyMgaLVN6DJM+geVS2DEllWXY2yeNSxPfe7wvgyyliG81h1dj9SgBXSvokgO299zuS3AGNBb665TVUlX7/gOr+8G67QKJOHjnn+r4gHIHkHAAXA7hY0lIAdpe0B6p2PfMWmNoLkn7jnDsTwHX2uWv0IyQfAvApSZ8FMMV7vwvJ7QAsV2xmczOPpEmSlqj/Rdh7ZaRj0eCBZ6TlZf3/9u497rap3h/45zOW+/1+i3IvFKESInfRjUicUs4ph+LXRamcdHS6na6KFN1QEt2UiIhsl5DcU1RILiHkujf2Nr+f3x9z7s5j7TUva625nvXsvT/v1+t5sdca8zvGWs+a65ljjjG+QzoxpfQZdwRtNknrS5pjqnwLAoD3HuxTSunbkj4KoNN2bJIHSPqY18SPX7Gdw1nFDyStCuClEfESkhsBWBfAeuh/euZ0AH+S9OeU0s3It3O6mGSbna5VWowFzAUjhL2QvB/A8QCOl7Q4gG0iYgeSWwHYBMASI6z+SQBXk/wVgF8B+F1Kyee1zRWKWQk/Kn5m74G8CYANI2IDkqsg/55ZCfmNliXxfwN3o2+fpH0lnTZZFZpNkoclHZtSOpbkP8fdGDMza6bIfL4C8q2algWwEPILo4WRd/4eKf47HcCDJEee2TQiLkSelbgVJN9F8vi24k0FkhLyTv0mANaOiLVIroX8Inf54meRmjBPIl+zeK+kuwDclVK6AfkexH/2jR2z0VggIl5KzhfJs2z+8CDJLwE4LqX02LgbY2Zm/SnWfz0A4OZxt2WCtqd3/aPleGNXTA/+c/HTk6TFkHfsgf9bXvMogIyk/2abjckCJEcxbcpssj0g6WsppaP9R8XMzNoiaTFJba93vKPleHOFYhrv7Omy3RnDzWxMFpD0OwB/GHdDzAaVUvo9gG+nlJ4cd1vMzGyeswnaX996R8vxzMwGtkCn03nfuBthZmZmNkX1ysQ+jMdJPtRyTDOzgU1a9hozMzObWiTtJ+n9bcYk+eYWtnmYMiTt2nLIUe27aWY2EHcIzczM5l/PANi85Zg7A5gnOoSSFpW0Xcsxr2oznpnZsNK4G2BmZmZjc1fbASW9tu2YY7QH2t+U/rdtxjMzG5Y7hGZmZvOvO0cQcydJbW/TMBaS3jmCsJePIKaZ2cDcITQzM5t/3Qvgny3HTBHxrpZjTjpJmwLYpuWwj2AemU5rZvMOdwjNzMzmUyQF4MoRxD1U0gptx51Mkv53BDF/WWzgbmY2ZbhDaGZmNh8jecUIwi4ZEZ8fQdxJIelVANrOLoqU0o/bjmlmNix3CM3MzOZvI1nTRvJtkl49itijJGl5Sd8aQegZAM4dQVwzs6G4Q2hmZjZ/uxTAgyOIS0mnSFpnBLFHQlJH0okAnjOC8OeQnDGCuGZmQ3GH0MzMbD5Gcpakn4wo/LKSfi3peSOK36qIOBrA60YRm+QJo4hrZjYsdwjNzMzmcymlH4ww/HMlXSBpvRHWMRRJnSzLvkzy3SOq4gaSF44otpnZUNwhNDMzs4sB3DLC+OtKukLSLiOsYyCSlpL0M5LvGVUdJL84qthmZsNyh9DMzGw+RzJIfnbE1Swv6ZdZln1B0uIjrqsRSbtJugnAa0ZYzZ0ATh9hfDOzobhDaGZmZgBwKoC/jbgOkny/pJslvVlSZ8T19SRpk4g4Q9I5ANYYZV0kP0hy1ijrMDMbBsfdADMzM5saJL1N0smTWOVtJI8BcBrJUWQ6/RdJCwLYXdI7ALwak3MNdFFKaYdJqMfMbGDuEJqZmRkAQBIlXQhg+0mueiaAC0ieC+ACAH8iqWGDSloNwA4RsRPJ3QGsOGzMPjxDclOSN01inWZmfXOH0MzMzP5F0vqSbgCwyBib8SiA6yT9OaV0O4D7AUwH8HDx3+nIO5GLA1gAwNIAVgawckSsTnIjABsDWGkcjQcASR/rdDr/M676zcyacofQzMzMnkXSIZKOG3c75mIXkNyVZIy7IWZmddwhNDMzszlkWXYCyYPG3Y650P3FVNF7x90QM7Mm3CE0MzOzOUhaqFhP+Ipxt2UuMoPkziQvH3dDzMya8rYTZmZmNgeSM0m+BsAV427LXGImyb3dGTSzuY07hGZmZtYTyUdJ7gzgonG3ZYrLSL6lyJJqZjZXcYfQzMzMSpGcTvK1AM4cd1umqMdJ7kXyR+NuiJnZINwhNDMzs0pFp3BPku8F8My42zOF3EpyK5LuLJvZXMtJZczMzKwxSTtK+i6A1cbdljE7m+T+JB8Zd0PMzIbhEUIzMzNrjOSFJDeUdCyA+XGfvftJvo3k69wZNLN5gUcIzczMbCCStis2sN9o3G2ZBCHpGyml/yL58LgbY2bWFncIzczMbGCSEoD9JB0FYL1xt2cEZkk6PaX0OZI3jbsxZmZtc4fQzMzMhiZpAQBvlnQIgJeOuz0teELSiSmlo0n+bdyNMTMbFXcIzczMrFWSNo+Ig0nuA2CpcbenDzMBnEfydABnkpw+7gaZmY2aO4RmZmY2EpIWBrB9ROxB8nUAVh13m3r4u6SLU0oXAjjD6wPNbH7jDqGZmZmNnCQC2BDAlhGxNcktAayPyb0WeQzALZJuSildBuBSkrdOYv1mZlOOO4RmZmY2FpIWQ94pfD6A9SNiXZIrAlgZwEoAVgSwcMNwTwF4EMD9AO6X9ACA+1NKdwH4E4CbSd7d9mswM5vbuUNoZmZmU1YxsrhM8c8lACyIfP/DR4vHHif5zDjaZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm8yKOuwFmZmZTlSQC2ADASyJifQDrkVwOwFIAOkWxJwA8IumOlNLtAK4FcC3JGWNptJmZWR/cITQzAyBp6Yg4YrKqSyk9AuDR4udWADeSfHqS6rcKkhYC8OqI2JfkdgBWGiDMMwB+S/JMAGeQvK3NNpqZTUWSdouIV1aVSSkdQ/LeyWqTmZlZI5JWjwiN8WdmRFyTZdknJK077vdjfiTpOVmWfTEiHmr5dxsRcYGkvSSlcb9OM7NRybLsM3XfiZI2GXc77dn8h8nMbGpYEMBmJI+U9OeImCZpi3E3an4gaZUsy74h6XaShwFYruUqCGBHST+WdIOkPVuOb2ZmNjB3CM3Mph4CeKWky7MsO17S0uNu0LxIUkfSeyXdQvJAAAtNQrUvlHRGRJwjac1JqM/MzKzSAuNugJmZlUokD5b0SkmvInnnuBs0r5C0hqRTAWzToPijAC6RdE1K6c8A7gIwA8AjABYFsBiAVQCsGREbk3wpgI1RvU5/N0k3Sno7yR8N9WLMzMyG4A6hmdnUt4Gk8yRtRfLhcTdmbidpZ0mno3pq6AxJP0opnQTgMpJZn3WsCuC1kt4GYKuSYktK+mGWZZ9PKX2IpPqpw8zMrA2eMmpmNnd4QUR8bdyNmNtJerOks1HeGZwu6bMk1+x0OgeQvLjfziAAkLyX5DdSSluT3BTATwH07PCRPDwiTpTU6fW8mZnZKLlDaGY2lyC5r6Sy0SarIelASaegfK3gOSQ36nQ6Hyb5QFv1krw+pfQGktsDuKWkzAERcUJbdZqZmTXlKaNmZn2QdEJK6SdDhOgAWAbAupK2BLAL8gyjTes/DMDlQ9Q/X5L0JknHo/e6vpkk30dypCOwJC+WtHlEHE/yrT2ef4ekv5L89CjbYWY2KimlWyVdUFPs8UlpjJmZWT+a7kNYdMjarHflLMtO6mNPu6ckLd5mG+Z1kraMiKdL3s+HJW09hjZ9pKQ9z0hqkujGzMzMzMzaMq4O4YT6/7tpp1DSjqNow7xI0goRcVfJe/mQpM3H2Lb/KmnXHZKWGFe7zMxs/uI1hGZmU8MnAFzfsOzao2zIvETStwGs3uOpp0nuSfKayW7TbCQ/LenkHk89LyKOmOz2mJnZ/MlrCM3MpgCSkvQ1Sd9oUHzlkTdoHiBpL0mv6/UcyUNIXtJnvIWQ7y+4MYAVI2LZlNIjAG4FcPEgiWhSSocWU0TX6WrfYZJOIHlXvzHNzMz64Q6hmdnUcXGTQhGx0qgbMreTtLikY0ue/hnJb/cRa/OIeI+k1yJPCAQAIAnpXztJZBFxNsn/Jnlj1/GvALBhV9j7SZ5JcrqkQyT9suv5RSLiEAAfbtpOMzOzQbhDaGY2ddzRsJz3q6v3LgCr9Xj8cZIHNwkg6bmSjpX0erJXctJn6QB4vaTdJR1O8pgJcY4FsGlX7K8BOBMASJ4XEb8GsMPEMiQPlPQxkk81aW+D17M0gHWLn1UBLB4RSwKYmVJ6AsA/AfwVwE0k72+jTuufpOci/7ysW/x+FkkpPQbgXgA3ALhhkL0xi9iLA3gxgBcCWC4ilgbwVDHS/QiAGwHcSPKZFl5KP+1aEMBaANYD8BwAy0bEoshf+wwATwB4EPm2LbeQfGwy21enWPO7GfLZA8tFxGIppUcBPAzgfgBXkbxnktu0FP7vfF8NwGIRsRSAWSmlx5Gf73cgP9/vm8y2jYqkBQBshHzGxfMALBERiwNQ8Rn/J4DbAdxM8u/ja2m5Yj/aFyL/DlglIpYpzoGHi58bAPyBZLRZrzuEZmZTBMmZETEDwGI1RR/u9aCk/dG7EzTR3SRPHaR9ZST9P9S3+dskH2yz3or2LC7pA72eI/m/TTo7kvaV9E0A/SZ3WVDSlyUtQPKLktaUtGl3oZTS+V3t+pKkHbqKLYe8k3hOn20A8K+L7FdHxE4kd5C0QXeZ2R3dCSOdAICI+IekX6SUzgDwK5JP91Hv2gDeWFNsJskvNY3Zo453AliqqgiALw7RcfoPACvWFDua5Kyu49YFsFfFMT1ft6QVALyr+Nz96/dU8vt5MMuyn6aUjiV5U00bZx+/i6RDJe0MYJGa+DMi4hKSJwA4e9D3sKY9BLBFRLyK5G6SNkPXNWnZZxMAIuJPks5OKZ0F4NJhLo4lrQfgDRVFnib55ZJjXyXpIEmvQtf72uOc+lvR5q+Q/NOg7S1TdIZ2j4idi/O9e1ZC1fn+QNf5PvBNKEnbAdiipthJJP8xaB1d9S0L4I2S9i62cnrWd3bFa75N0gUppVMBXEZyzg9a/20hgA/WFPt+r6UAktYrZqLsjQnLQnp9lgA8GhHTSB4P4Pw22m5mZhh/ltGiDZ2IyBq04d97HZ9l2ccavIYnizvHbbV5wwZ13lXc9ZwUkv6zIqtoXce16ftY9/OMpFdIem+P52Z2/w6K3/093WWzLOt7b0RJS0r6QETc2cLrUETcLek/iw5mk/qXj4hZDT7H69RHK43f5DzZbMD4i0f5NiWzf64rOfZ1Ncc91lU+SXp/RDw+wO8lsiz7btGZLHsta0fEr4f43f+lmPLcCkmUtGdEXNfSZ1MRcaOkfSQNlChR0h418R/pccwLI+I3A7Y3i4ifSlp1+Hc0H52UdFhE/K2l9/MeSe9ser53y7LsMw3OzU1aeN3PzbLsuIiY0cJr/qOk/Yf9O1V8j9e99m27jlk6y7KvR4PvzJKfP3THHISzjJqZTR2rodn38lW9HkwpfQdA3Z3yRQDs2We7SkXEPnVlJJ06ilGGivreXvL4N0nOqDo2y7JPkjyqhWZ0JB0nqddo0W+7p7yRzCSd312QZN2d9meRtI2kGyV9HsAa/TW51HMkfV3SDb1GHbqRfAjAbxrEHXT7lFei2Xky6H6OrwSwUFUBST8bMPbEGItLOlvSF9D/SDQAkOT+kq4uRrm64+8h6QYA2w/RzHUlTcuybOhzQtKLiraegXzaalteJOkHkqZJqpshMTTla36vBrDVgCESgD2K82n3IduyVRHniwCeO0ysCVZTnuDs95Je2FLM1khaSNKRkm4heQiARVsIu4Gk70r6naSXtRCvEUkvkfR7kv+JwWdtbijp11mWfXzQmyKAO4RmZlNJ95TBXv4M4I+9niD5VwDT6gJI2q+/ZpUj+aa6Miml77ZVXx3l0+16/kFPKX2r5ti3kfxITRUPSDqG5F4ktyS5S9GBvLtH2U0AzDG6QnKOjl/Rvl5JhTZoetda0hGSLgKwZpPyA9hA0pUqydw6Eckz68pExEAdwojYrkm5Qe+aR8QudWVSSkN1CIuL2nMA7DZMnMLzJF0oabkJ8Q+S9BMM1tHs1iH5MUkDJzhSnvH3KuTr7EZlG0nXSOrrJko/siz7X0nHAVi4hXArSjqz5KZRLUmHS7oEo9uG6PmSrpDU2g3EYUlaQ9Ilkj6BdjqC3TaV9BtJH1A+/XNkJO0saRrauXHXIfnRiGiSpbwndwjNzKaAYirVIXXlSH6zar0AyZMaVLejpKEzlUraGMALaopdTbJnB3ZEdi15/DqSt5YdJOl5xYVeRRF9keRanU7nvSTPIHklyV+R/DjJF0g6pWEbe3YIAdzc47FF0WCbEUkfkvRpjD7h0JKSfqx8q4wqtR1CktsPctFFcruGRbcZMP7ONUX+SvKGfuNOFBFfATD0NK8J1oiIrwKApLcoT1rU6jWepE9I6ntkT9Kekn6ACWvsRmgVST+X1Nbo+L9I+gDJtrP+LiDpO01G3rvacpikz2H05/sSkn6ofF3gWEnaqLipMLIOf2EBSZ+PiG8OO4W0jKTNi5HyxduMS/Ltkg4d5Fh3CM3Mpob3AXhpTZm/AfhqTZkzADxaU2YB1Cf9qBURtaODJCdtdBAAJPUcdZJ0ds1xX0f5aMp0kvt0Op0PkJzeqwDJ6SmltwH4aU0T/wng6pLnbi95fOmqgJJeWXQGJ8uCxUXic8oKkLwdwO9r4qyIPCtjY8rXyzWdxrYi6m9YdMdfHXNuEdJdZtjRwYOKKWKtIvkmSQcoT4Y0iuu7BYqRmcYkbSDpe5jczMgrSfqp8iQrrVC+HvizbcXrsnjNzajutmxddAYnywLFlNzWO9lNSVqvmP2wymTVSfLtEfHNEYReUtKP0c7o/RwkfVoDrE91llEzszEq5vwf1uBiYxbJA0g+WVWI5Iwsy35Qd8FZTBut61xWIlm3fnAmgNOGqWMAPdf1pJQuLzugGFEpG1l8huQbyqZ5TkRSxVS9nQAsWVLswor1lGWp9EsvHIqR5ePQvANwi6RLU0q3IO+cZgBWjojnkNwU+fvXJJnEKpK+gorsjJLOJPmimjg7Ik+j3tQrAfQz6rcNeo+8lqkbHRx2uuiSkk7o8bgAXC3p3JTSHQBmId++4MUkd0V99mAAoKSyGQKPSDovpXQNgAcAPANgxYhYh+QeyLd6aGJ3SauT7DVF+lmKz+ZJqM9APFsG4FJJv0sp3Y78xtaCyN+HFUi+EPnvf5mqIIXNAewPoMmMiTqLFZ3aXufYY8ozh96IfFsQAVg+IjYnuQuApjMxtpe0FcnS76nZivOuaQf7T8X5fjPy8/0Z5FsZrDbhfK9cL1tYqRh1fm3DelsjaRlJZ6E+6+9E10m6KKV0K4CHkE/xXbU4n14FYNkmQUj+u/K1iq11wCV9Cb2n9WcALpZ0SUrpXuR/D5aLiPVJ7oR8O40mloyIdwM4opUGm5nNTzTJWUYlLSLp9RFxRZOsdCpJlFIS++UNYoakNYdo/+YN6hg68UafbVqx4ve2fMkxKSL+VHFc7TTeblmWHVMR7x1Vx0aP7JnF1Nyy17xNw0x0P1KDrJ6SVs6y7NMRMbPh+VA6hVDSSxrE+EVdmybKsuwr/WTgy7Lse33G/35NzH9UTSNTfZbRXj+XStq8IubCko6MXL+xZ0j6iKTS6ZrKM52+IyKeaPg7f0uT91L12Ttn/zyZZdln1WAae/G9eXBEPNwg7mUtt3Piz0PKt/EoXUsoaVFJh0fD7JFZln2lQVubfLcrIs5Qj0RDPeKtlGXZJ6M+q+7s333dLJbWs4xmWXZyH7+X8+piK1+/e1BEPNQw5kw1zFisBllGe/w8k2XZCZIqRz8l7RYRdzWMeUfT99fMzCZo2iGMiOsj4odD/PwiIn4XEU82rG+6pNqpmd0i4o8N/igPvB4my7LPNYhftbdX6yS9oqQt/6w45tUVr+EiDbAGTdKrKt6T51Uct0TJMaVJI5pskZFl2Yn9vo7i4qP2QrbqIlYSG1zAPK4+0ttHxO/7uNBSRPytj9ecIuIfNa/32zUx+uoQZln2jaoOZlfsj/b52p+uGPnuFX/3yNW1+fgm8SLi7AZt/IcGSAKjfNuHB2tiZ5Jq12gN0CG8sZ8pecWNv9r3NSL+0CDWkQ1+P98d4HzfJRrcBMqyrNfo9rO02SGUtGPD38lTkt7bz+uWtEZETGsY/xo1yOA5QIfw8WJGSdM2rx49ticqeY8H2tbHzGy+1keHcDJ/pjW5y1vyeg5vEH+gxBjFhf5fa2I/KKnJVKTWSNqrpC3Xlh0TEb8qOWaWpKZTdLrb8YKSmJVTF8s+g5qQPbJH+3/Y4MJgoHT0WZYd2+AzVLbucXaMrzZo39ZN2iNppcj1dR41HQmXtFmDWJVT5vrsEJ7R5wXswtHH3pKSPtQ09mwNRkgVEb9r0NZFo8Gok6TajK4VdRzcIH7tyE6fHcK/VJ2PZbIs+1aD2CGpMoFUk9/PoB2BLMu+1KCNc2yo3iNOKx3C4u/MVQ3a9IykPQZ5zZIWjIjzG55P+zaI10+HcJbqk3P1quP1DdvbeFYR4KQyZmZT0QySb0wpbUfyLwPGOAX5epEqGw/Y6dkCNVsbSDqd5MwBYg+jbN3eHBtLA/kdYpTvhfcLkrV37Ev0XJ8v6Vc1x/Va1/IwydIRTtQknEG+L2XtRVwvKaVjGxRbq2qqU0qpNtsomu9HWLV+8KGK45pedNWtH5wO4IKGseo8QPLtVRmDu5F8Wnm2zibuBPDlfhuVUjqxQbEVGpTZDPVr06Y1WZtb4dQqx7O0AAAdg0lEQVQGZfruvFWYRfLfas7HnlJKRzcoRgClMwgAgGTd+Q7kycf6llI6pkGx1ZUnXpoMO6I+0RpIHkZyoOUJJGeR3Bv1CbAwzIyakro/TvLSAQ79OYDSjNmzRcSa/QR1Uhkzs6lnMUmnRsTBJL8H4Hsk6zp3z0Lyvog4FzVJACJiPwBH9hM7IvYhqwc2JnPvwQlKs4SWPP5alHQwSH59iHb07CCllOoufp/f47G6P/yP1zyfAKwLoO8bCyRvzbLsCwCWqilXNS1vGvLkIKUXssozw368rj0RsV3Z547kp5Vvzt3ruG2R3yCp1GC06ry6pE5NkfwSyYf7PS6lNE3SB+rKSfpeSunpAZr2G+Q3EaoGDJok5Fi3rgDJnzRtVMnxj0c+Hbyq09faLAVJp6WUakdHeyH5x8inhNbdgOu51nlCGx6v++4FsD5K9qqtQvKOLMs+h5qkPSRHsf/fHCLiwAav9XIAtWsvq5B8THkysN+gOmHVJpJeTvLKYeor3AtgoEQ1JJVl2U9I1s0AqPwsdXOH0MxsaloI+X6BOwI4UtJhJH/eTwCSJ9VNcSO5r6SPNh2pUJ6Aom7LiltIXtW4oe0p6zT3fG0R8cqSC45HUL5XYBO9ti2YibxzVCoiXtrdHkmVF6CS7qu7aJL0KUlv6mc0arZOp3N4v8dMRHJmlmXnkqyabvVySYuXbekxIdZ2JU/9BXk2254dQpK1I4SSFqubujroKEQPGYBBN5BudKHfcGR2DiSfjDwhRdVm50tJ6lRkywWAeyVVvkaSvx6kjbMpTw5SebOiTSmlnp+vpiRdRXKoDiHyjkRdPZ+UtDfJaN66XKfT6Xua8SgU52NdRlORfO8g32vdSF5RZOeunBYa+VZLQ3cISX6V5CA3bAAAKaWrpNqX7Q6hmdk8Zh1JP8uy7AsppSNqLsQmOhvAP1Cd+nwd5FNAm/6R2xpA5ZShyd57cIKyDkXPtPcky6YjXdbHezwHSTv0ePhykk9UHUfyZd2PpZSmVR2TUrqzwYXBGyUtIentJGsvKNuWUvp5zfqbhQC8AsB5ZQUkrSxpg5LnpqWU7o2IW9B738H1Ja1M8v6KNmyLPDV9mVnIz6c2XEuyaoprlQcblMkA3DhgfKB+H1Mi3/ag9BwppoIOc1Olic0wedexd5Ac5j1FSunPDc7V0mywRYwm5/ueks6V9B8k7+mnjVPITgDqRiJ/S3KgEdteUkrH1a0TJPka5HsGD6uvm7s9/KmuAMmq77M5eA2hmdncgSQPj4jGd6lJzpJUu84mImoXy08oW7f3YADoK9V/i2aUPD5Hh7BIeNMz2QrJ3w7aAEmLAtiuR8zKi2NJywB4edfDMwHUjaI0XdO2m6Tbsiz7uqQt+s1COKRzkL+WUhFRt46wdP1gSuliAJB0ccmxRM06woiomy56ySBTPHuRNPDnC+U3PSb6K8mnhqijlWmxoyRpBUlN1ri2Vd+0FsL8o4UYFzYst4ukW4sstls2yZA5lRTTvCuRPL3lai9H/frLdSU12RO0yoMAbhoyRhufpWeZqz4gZmbjJulLJF8y5M/LSO5K8gDlm4rf1rR+ku+RdGDT8iml2o2ZSb5JDVLfF9PE9q4pdhHJgZKYtOC+ksd7pYhfDeWbOw8zirYPeq+Xqxst2Rtzjg78om4kieS1AJpOz12U5H9KulLS3UV6+oMkvajJ739QJB8FUNZZm12mskMYEdtVPH0xUD2aGhGVHUKSlQllWpwuipTSA4MeW0wDrBsiGrbjOkxncqQkLS3pEEnXo0HCkRbd2UKMupHXWsUoZe3m9YVFSB4o6fLifD9F0sGSNpY0pWcIknxJg2JtjdjPrlOSmsRs0rYqd7UwzXXoz1K3Kf2BMDObalJKd5O8psWQ3ynu3r6muONdmWUOACR9VtJPSdZOHyP5+yJNfNXF0yoAtkf9aNO2KEmYMqG+cU0XBYCyLRBWl7RAV2KesoykANB3FsHZJL2rx8MPAriu5rj9ux8jWbnn3YRy75J0BYDG+/kBWI3k/hPqnR75XltXpZSuQp4BcuCOS482nimpqtP1YknLl3WAK9YP3kby7uL/SzudJEtHHCStVpNtVwAGWpNXYuDPV0N1iYbqjH2EUNLSyBPTrAdg7YhYi+RmkjbGGK5dU0pNpupOCpKHFKPM/STMWZXkWyS9pfj39Ii4tut8b33UaQi9EmxN9AjKv+8HllK6tsGU3BdguCmfU+azNJE7hGZmY1bc9f+5pEsknYV8PVWVZSPiSADvbRj/ZEmVd9OLbKOVHcKIeFNNApMnAJzRpE0jch/yKXXdWS8XQL5NxsSMnVUvpHYz614k7SVpjnWAki5IKZUmeJC0laTuDst1yKda1iJ5jaSjJH26vxY/y+IAtiW5bXFBFBFxnaTzU0rnIV8DOWuI+D9Hng2w7H1PyKfazpF5UtIqknqtDXzWNFGSVesIN5a0DMleW5DsXNEuALim5VHvgdenNjTM7wmo366mFcWNsDUBbABgw4h4PskNAKwnacWJZRtkmxy1Yd/T1pC8XtJHJH1+iDCLA9iG5DbF+a4e5/tkbxsEIN9vUzX7MQK4vo1kMr3i1hWIiDWGrGMs72sdTxk1M5siSD5C8vUA7mhQ9q2Smi4aPw0108BIvqEqXjHC9oaqGJLOqEucMkrFBUJZ4ofuDnHp6FdErNdv3ZIWLbtAq9tuoldHjuRR/VzwkPxfkh9G/XTCphKAzUkeIWmapPuyLPuCpNrtBEradxeAa6vKVKwjrF0/OFvFOsKEPCFSr3onbbro/E7SJpL+KyJ+I2m6pNsknS3pcyTfDmArACvWxZnfkfwCyfejvfOdADYj+WFJFxXn+9GS+v4ubMHyqL5BA0mjSo7VJG6TfTjnOu4QmplNIST/SfK/GxRdFsBrGsZ8WFLdRe0yAHaveH4H1FyojWnvwWeRdFmvxyOiO2HLAyi5609y137rjYhvAlir5OnSDekl7Ye8wzPRL0me1W8bSH6W5KvRx5rUPixH8v2Sbi4uFKum3Ja1r3LaZdk6wibrB2frdx2hJJLcqapdANwhHJKknSPiYknXS/oU8o5fZUZNq0byaJKvwgB7jDawLMn3Fef7MZrE7T1QkhW6S6+R/jbUrr9l9b6rcy13CM3Mpp7TATxWV6hJJrbZUkon1pUpOidldb2p5vC7AFzUtD2jklLq2SEkuVvXv59BeXKGLSRt1bROSR8h+eaSp/8yYY1b93EvkPT1roenk/x/TevuRvJcki8sYtwyaJwKCxQXitcPMHpQtw5vfUlzTMeqWD94B8nurIAXo2TUpGQd4SYAqqan/YXkHyqetwqSVoyIsyWdj3wNcltulNR2lsm5DsnzSb6I5CEAbh5BFR2S75Z0g6S6dX1tabKcbeA9/GrMRJ4pu8o8udzOHUIzsymmWKt1aYNym/cR9kLUZ8p7Ta+RH0kLkdyz6kBJ3+MAGyGPwEXovf3EekVCin8heW5ZEEknSlquqiJJnSzLvizpkxXFeo7WSVpT0pnoSm5D8lCSt/Y6pimST5E8juSGJLeW9AnkmUjbXLu2tqTfSNqwj3bdCOCvNcWetYejpFXRe01gz60AmO+zWLZH1+aSukcfKqeLNhhZtxKSVpd0OYBXDxnqKQB/kPR9kh8g+fKU0iZlN3/mNySfJvk1khuR3ErSxwH8Fu2e72tKukzSi1qMWaZJUqNemZzbsBTq+0Zl2xvN1dwhNDObgiTd0aDY+k3jkQxJ36kptiiAPXo8vjPyKaqlpsJ0UQAg+XhZ6vCI6M7k+R2UX3w8v1g7t2mvJ4u1UBeQfE9Nk+a4eCiSyFyBrt+fpONJnlwTrzGSInl5p9P575TSFiRXJrmvpK8C+B2GT5SxoqTT+ljLiqITXKrHOsLtysp2rx+cUMe0kkMWQtdejzWZT5FScodwAJIWKc7DftacPgrgF5I+Q/JAktuTfC7JxVJKL+x0Om8m+UUOsU/ovKw436/odDpHpZReTnIl5lsKHYf8htCwyUxWKM73UU/1rV2HTrLy79EQauNKGts6+VFyh9DMbGpqspfYMv0ETCmdjJokBL2mjTbYjP4qkqOYnjiQlNL3ez1O8u2SFp/w7/skfbMi1IskXR0RlxXr5o7MsuzYiLhK+T5o2zVozg6SXixpSUnbRsSPi3WO3dt3/CylNPBU0SZIPkTyB51O59CU0stILklyS+Z7W/4AwD0DhN04Io5oWjil1Nc6wn7WD06oo3T7iYnrCCUtiuoN6+8DcGXF81YiIj6KfDpuncckfYHkZiSXTym9ptPpHEHyWySnkWxjz7b5UrEe/YedTuf/FTeEliL58mIK6OkAek5lr7FRkeF6lP6J+lHCxjdD+9RkWuwg35NTnjuEZmZT0xINyizYYwpcKZK3A7ikptjOE1O+S1qkyHxaFXdKjA5OcDZ671G1LIADJz6QUjqqpOy/igDYulg394libV6vLTzKUvUvI+k6SY8VGTD3QlcGvWIq3D4kR70dwbMUU82uJHlsp9PZN6W0OslNiyln9/UR592Smu6Jdhmq9+FbTdIGE2JvV1LuTpJl00+nodk6wm1QkdhE0llTZBr0XEX5fpJ1I+cAcCnJDTqdzuEkr5vsz//8pjjff0vyK51OZ7+U0hokN5H0P2iWXXN2nENHOUpY3ACoW97w/Ik391q0WV2BlFL3uuV5gjuEZmZT06oNymToc3E9ybrkMgsAeOOEf++K6vUaM5EnwZkySGYkj+71XLF/1zITyj5Ccl8Mty7kepKlCXkqBMmjUkr7c7g9/lpD8vpOp3MUyTVJfhDNppkti+qRtonxn5H0i5piOwD5hvEoGQmo2F4CJO9D+TrCl0taEAAiYpeqRni66MD2RP1enn8guSvJv09Gg6w3kjd2Op2PkVyL+TYWTf6eLI05MyO3qpiBUaWDrunfLdXbJJlY7V6FcyN3CM3MpiCSdZvTA8CDA9xV/wlqMphOnDbaILvoL0g+1GcbJsNJ6D21Z4WI+J+JD5D8HfOtBwZ5HReS3AHAuQCm93HcbSR3IvnxqTgKVYwmfL54bU2SPLy4aey6aaOSZk8b3a4iRmmHsIgxreSpxQBsDgAkq9YPPo48EZP1KSJ2qCtD8kMkm3yuKsMMebwVivP96GJEvsn3WOPzfRAppd/VlWnwt6kvkpZHTZIp5B3mG9qsd6pwh9DMbIqRtCWA5zQo2nha32wkp0v6YU2xrSU9V9JiJF9bE2+qTRcFAJCcwXyj9l7PHTqh0zH7sStIbgGgbvRqtulFRtCdST5McjrJzzY47sHiYvhFJIfapkPSARHxw6ofSWsOUwfJ30jqOdo6UUR0r4msch7yzJFltpPUGWT94Gw1HcZtJa0CoDRjoqRzSY4qtf08jeQGNUUeB3D+sPVERJNZFPMMSfs3ON/XGaYOkldK+nxduT7P90GcV1eA5N7FOuC27IM88VSVS+bV74V5ci8NM7O5lSQWa7ialP39IHWklE6S9I6KIgSwL/K1dVVrGR8EcM4gbZgkpwI4GMDWXY8nSd+V9HKSd81+kORtyLfe2DEi3krydZgzcc8dkr6fUjqW5P1dz32y6HAfhTx9+WwzAZxD8nsAzu6+oJD0PAArdMWaXpeoJyLWJvnGqjLIR4TvqClTKaX0c0kfqSm2YNN4JJ+IiAtRvh3BsgA2q1g/eDfrt+aYhnwd4RyjSJK2Yb49RekIk6eLDmXFmufvbGOKNMnJ2hdvqlgLz57O38uZKNnqpqnifP9YTbHG5/sgSN4UEbcDWLui2LIADgPwqWHrk7SYpP9q0K6zhq1rqvIIoZnZ1HIkgJ2aFEwpXTBIBSQvR82m5ZL2k1Q5JUfS6SSHTWU+MszTsB+AfESi22qSzpY0x/pIkhd2Op23kVyR5OpFZr6tSK6RUlqr0+l8pEdncHZ9RxfHbEVyz+LYZVJKe5L8SY/O4Csk3STp6ok/KKY1Vkkp3VVXJiIafZZqNPkdP9pPQJJ120+8FUDPje+r1g9OiF+1jvAVEbFrxeEzMbVvdEx1daM2Q0+RLtaXvmbYOHOZukQrU/Z8HwQbbMEj6UPFZ2EoEXE4gNVrij0FoGcG63mBO4RmZlOApIWzLDumyPjWxFPI7wYPpMEf2xcD2LuqwFTZe7AKyVtJHlLy9MaSLpyYVbXr2GdI3lNk5ruCZKM07SQfL8r/rDi251opSdtJOgddo7CSTiN5aoOqateyMN93sHv0sV+1IzEppapMrb2chYqOAclDK+qq7RAClesIlyH55opDLyI58gveediDNc+vJ2mpmjKlJDEivgSg8f6X84gm5/s+klYesp4X1BUY4HwfxLdRn+RmSUk/7SfbdjdJu5Os3UqjuAE6FdfLt8IdQjOzMZL0AkmHS/oLyXejYaIESSeTfGSIqk9B+VYJTfyRZO3C/6mA5CmSvlzy9OaSLpO00WS2SdJBks4HsGTXU7enlN7VMMw1qE+Es4Skb0vq9N1IAJIWkvShBkWv6iduMYI36AbjjTqETTuO3Uh6uuhw6rYwWCQiGk2L71asLf0yybq9UWcb6dTGSXYDgH/UlFlM0olDnO8LjuJ8HwTJv0s6oUHRl0k6fZBtKIoZGj9A/RK6WSmlT/Qbf27iNYRmZn2QdFBE7DZkmIUBLA9g5SKzWb8eTSl9cpgGkPx7RJyH8nVcdcdP+dHBiVJK74+IVUn2mga7vqSrJL0PwDc5wo2wJa0i6ThJe/V4+v4iFX+jjj7JLMuy0ytGQGd7XTE99j+KtXNN27qqpO8A2LSm6E0kb24adzaSZxYJlPpxL8k/Nyw7DSXrCCsEgJ/32SaboLi5VbktAcn3ZFn2TErpI02TdBQ3z75Gcvs+mjPq5CeThmRkWXYa6/d43F3SuZIOYB/bekhaWdLJ6L3P6kS3kBxo/Xq/UkqflPRvqF+X+tpiuv2+JGtHUiUlAEcUayVr+0KSjpmkUVEzMxsnSatHhOaGH0n7t/Sa9xqwDZmkuvUWU46khYpsfFWv7XJJW4yg7kUlHRYRD5XU+4ikuo5Xr7jrRMTTDX9vM7IsO0HS9mXZ+SQtL2m3LMtOiIgnGn4e3zrge/KCfj97WZad1k8dEXFzn3VcMchrmfCaXtfg/XrnMHVErqqOXw4Z/2cNXkNpNkZJe/bxft8m6YOSNiou0rtjLS/pjcV5+8wA31WXSKqcWippjwav9+Bh3tOintrv25pkX5C0ZkQ81fC1P5ll2Tck7VA2pVLScpJelWXZ1yLi8Ybn+9ur2phl2WcaxNikj/dt7z5+3zOzLDupmI4/x+hwcUPuoIi4qY+YN5d9X/aI32kQ7+ymr72inoUa1NPXTAePEJqZzUUkfTKldEpL4c5Cvt6n3zVmFzZdTzeVkJwpab+IeIhk2QXelpKujIgLmG9u/yuSA0+tLTrOb5V0KICyNPl/J/l6ktf1G5/kbVmWfZHkEQ2KL0ryIEkHAcgi4i7kU06FPGPfCiqS7JCNB9UuBfC9fttd1HFLRPwJDdYoztbvNFBJ00jWroma0CZPFx3eWcgz267ZoOzakj4L4LMAno6IBwDcj3zj8VWUbw8yjG0k3R0RfwSwGMnvk/zSkDHHhuQdWZZ9juRHGxRfhOSBkg5Efr7fjfz7fvb5vrykZYq4TZtwBYCT+2/54Ej+OMuyL5D8QIPiC5I8QNIBAGZGxG3I91UkgNUHWF/5aJEcbNg9M6c8ryE0M5s7BMkjOp1OkwuBRooOUpPkJd3HzVXTRScimXU6nXeSPAjVG67vJOkcSfdkWXa8pDepQTY7SQtLeqmkD0XEhZL+JulTKO8MXk3ypSSvHuT1AEBK6SgAl/d5WAf5BfvmAF4CYB0Ac2RcrXEXyf1IDpw1UlK/iZH66hCmlKb1Gd8dwiEVyZiaroOdaGHkmR43R57Uqq3pnisA2BbASyJi4GQ2U0Wxlu3SPg/rAHgenn2+d2+pU+fvJPclmfV53NBSSh+S1O+Np4UAbID89W4OoN/O4BMk96jb/mde4Q6hmdnUdzvJnUh+pu3AKaWT+jzkcQA/bbsdk43kN0huifrMfSuRPLhIWnBPRDwSEVdHxC8j4odZlp0W+RS7XxfT36YX6xE/A2AHlP+dzSQdQ3Lbftb5lLyWWcz3TKxdO9OiO0nuTPKeYYKklPpZr3c/arZL6eFi5CMiTdxMsmyrCusDyXMlfXPE1dyOfMRqvlKc768HcO0kVnt3cb7Xbn0xCiQjpfQ2SV+ZpCrvJ7kLyWmTVN/YuUNoZjZ13UvygyQ3InnRKCooFuA3vrCQ9BOS00fRlslG8gaSmxfZXZtmbF0a+d3mXQG8keS+AF4PYHvkmyg3ye53A8ktO53Oe9uaikTyIZLbYHI66xeQ3KKlztMVyDt6tSRd3G/CH1bvR9gd36ODLUopvbNIUjIK5zHf4/NbI4o/pZF8uEjc86NJqO6i4nz/4yTUVYpkdDqdd5PcH6PdB/Hi4u/CfHWzwR1CM7Op5SkAZxVTc9Yk+XmST42yQpKNRwnnhr0H+0EyI/kVkmuT/G/U76E2jBtIvoXkS0axZQfJx1NKbyhGC29rOz7yrUbeXNw5v6+NgCRDUqMkC4NuI6Hy/Qi74w+8r6fNiWSWUvoPkh9Cvo6rDX8jeQDJ3Ug+gHyj8Dtaij1XIflESmkfkq8G8JcRVHELybeS3HHYWQxtIvk9khtIOgVAm9NX/07y30luP+zMh7mRO4RmZuPxJPILmcslnULywyR3ILlsSul1JH9AcuYkteX7AJrU9Tf0uYZrblHccf9E0Qn/dwAXomLj9D48AeBHxQXspiRP5RBJapogeVYxqnwAgAsw3EXTkwB+QXJvki9inpSj1W05+uiIDfTZa7iO8B5Mwt5q8xuSIvk5khtJOhGDdQwDwK+Lzsn6JL8z+zNI8imSewKYMh2WyUbynOLcfBuA8zHc+f4UgHNI7lN8h5zS9vneBpL3djqdt5LcUPlehf8cItzVJA8ubgqePBVf72ToZ28eM7N5VpHyvN+kGoN4guSsSainMUmrSboLNTcJJX2q0+kcOUnNGrsiw+H2EbEdyS0ArA+gLv34owBulHRDSul85FlKRzrCW6dIhrNTRLyY5IsBbIj8s75IV9EZyDtGf5B0c0rpSuTTQ2eMuH1Nz71HBrlYk7QAgCVris0i+US/sXvUtSCAJWqKzWDDvfdK6li2pshQr0XSEqjZ0J3kwwPGXgrAnhGxTXFOrYNnn1PTkY/S3yrp8pTSFQAuJ1k5RVDScgAOkbQHgPXwf7/vWQD+KunqlNKlAH7WPbo9Gb+zop6FANRtnt5GPavi2ef7Rqg+3/9YnO+/Rf59NdRobrFFQ3dd3R5ji8lpivd2+4jYtvhcrYs8QVH3FP7HAdwu6Y8ppcuQv95WR1dHfX6Oqh53CM3M5nOS3iXpq3XlSD6fzTcFn+dIIvKLjFUBLFX8ZMg7gY8CeIBz0XYcxUXU0shfw2OjHrk066XoQCyB/GZZK2tqJS2JPGvpI/5c5yac74H8fJ9SNyZHodhWYxEATwN4qq3Pl5mZ2TwnIi5ssMltv2nOzczMzMzMbCqTtFpEPFPXIZT0b+Nuq5mZmbXPSWXMzOZvb0b9VgkPAjhjEtpiZmZmk8wdQjOz+ZSkBSUd2KDct8edGMXMzMzMzMxaJOmjDdYOZpLWHndbzczMzMzMrCFJqUi33+u5RbMs+1jk6jqE3qzbzMxsHuZtJ8zM5kGS1pR0C4CbAdwp6V4AGcnVAbwCwHJNwpB8KclrRtlWMzMzMzMza5GkNRuM/tX9OJGMmZnZPM5JZczMrJdHSL573I0wMzOz0XKH0MzMuonkQSTvHndDzMzMbLTcITQzs4lE8lCSPxx3Q8zMzGz03CE0M7PZHiS5H8mvjbshZmZmNjncITQzs6ckfYvkhiR/MO7GmJmZ2eTxthNmZvMgSYsC2A3AGhHxXABLkVwawEIAMkkzAPw1pXQtgItIPjrG5pqZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmc2X/j9B0/+uMB3y2gAAAABJRU5ErkJggg==";
|
|
162222
162433
|
|
|
162223
162434
|
// ../tool-server/src/tools/screen-recording/watermark.ts
|
|
162224
|
-
var
|
|
162435
|
+
var execFileAsync31 = (0, import_util15.promisify)(import_child_process6.execFile);
|
|
162225
162436
|
var OUTPUT_FPS = 30;
|
|
162226
162437
|
var FFMPEG_FALLBACK_PATHS = [
|
|
162227
162438
|
"/opt/homebrew/bin/ffmpeg",
|
|
@@ -162238,7 +162449,7 @@ var MASK_DARK_MAX_LUMA = 90;
|
|
|
162238
162449
|
var MASK_LIGHT_MIN_LUMA = 165;
|
|
162239
162450
|
async function resolveBinary(name, fallbacks) {
|
|
162240
162451
|
try {
|
|
162241
|
-
await
|
|
162452
|
+
await execFileAsync31("/bin/sh", ["-c", `command -v ${name}`], { timeout: 2e3 });
|
|
162242
162453
|
return name;
|
|
162243
162454
|
} catch {
|
|
162244
162455
|
}
|
|
@@ -165049,7 +165260,7 @@ Returns { stopped } - the URNs of the services that were actually live and got s
|
|
|
165049
165260
|
|
|
165050
165261
|
// ../tool-server/src/tools/simulator/stop-metro.ts
|
|
165051
165262
|
init_zod();
|
|
165052
|
-
var
|
|
165263
|
+
var import_node_child_process39 = require("node:child_process");
|
|
165053
165264
|
function parseNetstatListeningPids(netstatOutput, port) {
|
|
165054
165265
|
const pids = /* @__PURE__ */ new Set();
|
|
165055
165266
|
for (const line of netstatOutput.split(/\r?\n/)) {
|
|
@@ -165065,7 +165276,7 @@ function parseNetstatListeningPids(netstatOutput, port) {
|
|
|
165065
165276
|
}
|
|
165066
165277
|
function listeningPids(port) {
|
|
165067
165278
|
if (process.platform === "win32") {
|
|
165068
|
-
const output3 = (0,
|
|
165279
|
+
const output3 = (0, import_node_child_process39.execFileSync)("netstat", ["-ano"], {
|
|
165069
165280
|
encoding: "utf-8",
|
|
165070
165281
|
timeout: 5e3,
|
|
165071
165282
|
// `netstat -ano` dumps every socket on the host; overflowing Node's
|
|
@@ -165074,7 +165285,7 @@ function listeningPids(port) {
|
|
|
165074
165285
|
});
|
|
165075
165286
|
return parseNetstatListeningPids(output3, port);
|
|
165076
165287
|
}
|
|
165077
|
-
const output2 = (0,
|
|
165288
|
+
const output2 = (0, import_node_child_process39.execFileSync)("lsof", ["-ti", `tcp:${port}`, "-sTCP:LISTEN"], {
|
|
165078
165289
|
encoding: "utf-8",
|
|
165079
165290
|
timeout: 5e3
|
|
165080
165291
|
}).trim();
|
|
@@ -170831,7 +171042,7 @@ var import_node_url4 = require("node:url");
|
|
|
170831
171042
|
init_src2();
|
|
170832
171043
|
|
|
170833
171044
|
// ../tool-server/src/tools/flows/script/flow-script-executor.ts
|
|
170834
|
-
var
|
|
171045
|
+
var import_node_child_process40 = require("node:child_process");
|
|
170835
171046
|
var fs59 = __toESM(require("node:fs"));
|
|
170836
171047
|
var os17 = __toESM(require("node:os"));
|
|
170837
171048
|
var path45 = __toESM(require("node:path"));
|
|
@@ -171216,7 +171427,7 @@ var FlowScriptExecutor = class {
|
|
|
171216
171427
|
detached: process.platform !== "win32",
|
|
171217
171428
|
windowsHide: process.platform === "win32"
|
|
171218
171429
|
};
|
|
171219
|
-
child = (0,
|
|
171430
|
+
child = (0, import_node_child_process40.fork)(scriptPath, [], forkOptions);
|
|
171220
171431
|
} catch (err) {
|
|
171221
171432
|
return emptyResult(
|
|
171222
171433
|
{ kind: "spawn", message: `Could not start the script process: ${errorMessage(err)}` },
|
|
@@ -171660,7 +171871,7 @@ async function stopProcessTree(child, graceMs) {
|
|
|
171660
171871
|
if (process.platform === "win32") {
|
|
171661
171872
|
if (hasExited(child)) return;
|
|
171662
171873
|
tryKill(() => {
|
|
171663
|
-
const killer = (0,
|
|
171874
|
+
const killer = (0, import_node_child_process40.spawn)("taskkill", ["/pid", String(pid), "/t", "/f"], {
|
|
171664
171875
|
windowsHide: true,
|
|
171665
171876
|
stdio: "ignore"
|
|
171666
171877
|
});
|
|
@@ -172366,7 +172577,7 @@ init_src2();
|
|
|
172366
172577
|
init_device_info();
|
|
172367
172578
|
|
|
172368
172579
|
// ../tool-server/src/tools/flows/flow-visual.ts
|
|
172369
|
-
var
|
|
172580
|
+
var import_node_crypto13 = require("node:crypto");
|
|
172370
172581
|
var fs63 = __toESM(require("node:fs/promises"));
|
|
172371
172582
|
var os18 = __toESM(require("node:os"));
|
|
172372
172583
|
var path48 = __toESM(require("node:path"));
|
|
@@ -172382,7 +172593,7 @@ init_src2();
|
|
|
172382
172593
|
// ../tool-server/src/tools/screenshot-diff/screenshot-diff-ocr.ts
|
|
172383
172594
|
var import_child_process8 = require("child_process");
|
|
172384
172595
|
var import_util16 = require("util");
|
|
172385
|
-
var
|
|
172596
|
+
var execFileAsync32 = (0, import_util16.promisify)(import_child_process8.execFile);
|
|
172386
172597
|
var OCR_TIMEOUT_MS = 1e4;
|
|
172387
172598
|
var OCR_MAX_BUFFER_BYTES = 32 * 1024 * 1024;
|
|
172388
172599
|
var TESSERACT_BINARY = "tesseract";
|
|
@@ -172427,7 +172638,7 @@ async function extractOcrTextBlocks(imagePath) {
|
|
|
172427
172638
|
}
|
|
172428
172639
|
}
|
|
172429
172640
|
async function recognizeTsv(imagePath) {
|
|
172430
|
-
const { stdout } = await
|
|
172641
|
+
const { stdout } = await execFileAsync32(
|
|
172431
172642
|
TESSERACT_BINARY,
|
|
172432
172643
|
[
|
|
172433
172644
|
imagePath,
|
|
@@ -174537,7 +174748,7 @@ async function runSnapshot(env, opts) {
|
|
|
174537
174748
|
});
|
|
174538
174749
|
const captureWarned = shot.warning !== void 0 ? { warning: shot.warning } : {};
|
|
174539
174750
|
const { w, h } = await pngDimensions(shot.image.hostPath);
|
|
174540
|
-
const cropSuffix = opts.cropOn === void 0 ? "" : `-crop-${(0,
|
|
174751
|
+
const cropSuffix = opts.cropOn === void 0 ? "" : `-crop-${(0, import_node_crypto13.createHash)("sha256").update(cropIdentity(opts.cropOn)).digest("hex").slice(0, 8)}`;
|
|
174541
174752
|
const snapshotKey = `${opts.name}__${authoringPlatform(env.device.platform)}-${w}x${h}${cropSuffix}`;
|
|
174542
174753
|
const key2 = `${snapshotKey}.png`;
|
|
174543
174754
|
const baselinePath = opts.clientFlowPath === void 0 ? path48.join(baselineDir(opts.flowsDir, opts.flowName), key2) : clientBaselinePath(opts.clientFlowPath, opts.flowName, key2);
|
|
@@ -174709,11 +174920,11 @@ async function runSnapshot(env, opts) {
|
|
|
174709
174920
|
}
|
|
174710
174921
|
|
|
174711
174922
|
// ../tool-server/src/utils/status-bar.ts
|
|
174712
|
-
var
|
|
174713
|
-
var
|
|
174923
|
+
var import_node_child_process41 = require("node:child_process");
|
|
174924
|
+
var import_node_util31 = require("node:util");
|
|
174714
174925
|
init_adb();
|
|
174715
174926
|
init_device_info();
|
|
174716
|
-
var
|
|
174927
|
+
var execFileAsync33 = (0, import_node_util31.promisify)(import_node_child_process41.execFile);
|
|
174717
174928
|
var DEMO_BROADCAST = "am broadcast -a com.android.systemui.demo";
|
|
174718
174929
|
var IOS_STATUS_BAR_OVERRIDE = [
|
|
174719
174930
|
"override",
|
|
@@ -174737,7 +174948,7 @@ async function pinStatusBar(device, signal) {
|
|
|
174737
174948
|
if (isIosPhysicalDevice(device)) return false;
|
|
174738
174949
|
try {
|
|
174739
174950
|
if (device.platform === "ios") {
|
|
174740
|
-
await
|
|
174951
|
+
await execFileAsync33(
|
|
174741
174952
|
"xcrun",
|
|
174742
174953
|
await simctlArgsForUdid(device.id, ["status_bar", device.id, ...IOS_STATUS_BAR_OVERRIDE])
|
|
174743
174954
|
);
|
|
@@ -174773,7 +174984,7 @@ async function pinStatusBar(device, signal) {
|
|
|
174773
174984
|
async function restoreStatusBar(device) {
|
|
174774
174985
|
try {
|
|
174775
174986
|
if (device.platform === "ios") {
|
|
174776
|
-
await
|
|
174987
|
+
await execFileAsync33(
|
|
174777
174988
|
"xcrun",
|
|
174778
174989
|
await simctlArgsForUdid(device.id, ["status_bar", device.id, "clear"])
|
|
174779
174990
|
);
|
|
@@ -176382,7 +176593,7 @@ init_zod();
|
|
|
176382
176593
|
// ../tool-server/src/utils/workspace-reader.ts
|
|
176383
176594
|
var import_promises19 = require("node:fs/promises");
|
|
176384
176595
|
var import_node_path29 = require("node:path");
|
|
176385
|
-
var
|
|
176596
|
+
var import_node_child_process42 = require("node:child_process");
|
|
176386
176597
|
var import_dotenv2 = __toESM(require_dist());
|
|
176387
176598
|
async function exists2(path54) {
|
|
176388
176599
|
try {
|
|
@@ -176426,7 +176637,7 @@ async function listDir(path54) {
|
|
|
176426
176637
|
var COMMAND_TIMEOUT_MS = 3e3;
|
|
176427
176638
|
function runVersionCommand(cmd, args, cwd) {
|
|
176428
176639
|
return new Promise((resolve16) => {
|
|
176429
|
-
const child = (0,
|
|
176640
|
+
const child = (0, import_node_child_process42.execFile)(cmd, args, { cwd, timeout: COMMAND_TIMEOUT_MS }, (err, stdout) => {
|
|
176430
176641
|
if (err) {
|
|
176431
176642
|
resolve16(null);
|
|
176432
176643
|
return;
|
|
@@ -176716,7 +176927,7 @@ Fails if the workspacePath is not an absolute path or the directory cannot be ac
|
|
|
176716
176927
|
};
|
|
176717
176928
|
|
|
176718
176929
|
// ../tool-server/src/tools/system/update-argent.ts
|
|
176719
|
-
var
|
|
176930
|
+
var import_node_child_process43 = require("node:child_process");
|
|
176720
176931
|
var fs66 = __toESM(require("node:fs"));
|
|
176721
176932
|
var path50 = __toESM(require("node:path"));
|
|
176722
176933
|
init_zod();
|
|
@@ -176851,7 +177062,7 @@ var updateArgentTool = {
|
|
|
176851
177062
|
if (spawnRoot) updateArgs.push("--project-root", spawnRoot);
|
|
176852
177063
|
const cmd = cliEntry ? process.execPath : "argent";
|
|
176853
177064
|
const args = cliEntry ? [cliEntry, ...updateArgs] : updateArgs;
|
|
176854
|
-
const child = (0,
|
|
177065
|
+
const child = (0, import_node_child_process43.spawn)(cmd, args, {
|
|
176855
177066
|
detached: true,
|
|
176856
177067
|
stdio: "ignore",
|
|
176857
177068
|
env: { ...process.env, ARGENT_UPDATE_TRIGGER: "mcp_update" }
|
|
@@ -176903,7 +177114,7 @@ var dismissUpdateTool = {
|
|
|
176903
177114
|
};
|
|
176904
177115
|
|
|
176905
177116
|
// ../tool-server/src/tools/screenshot-diff/index.ts
|
|
176906
|
-
var
|
|
177117
|
+
var import_node_crypto14 = __toESM(require("node:crypto"));
|
|
176907
177118
|
var import_promises20 = __toESM(require("fs/promises"));
|
|
176908
177119
|
var import_node_os15 = __toESM(require("node:os"));
|
|
176909
177120
|
var import_path8 = __toESM(require("path"));
|
|
@@ -177050,7 +177261,7 @@ async function resolveOutputDir(params, options) {
|
|
|
177050
177261
|
const dir = import_path8.default.join(
|
|
177051
177262
|
import_node_os15.default.tmpdir(),
|
|
177052
177263
|
"argent-screenshot-diff",
|
|
177053
|
-
|
|
177264
|
+
import_node_crypto14.default.randomBytes(6).toString("hex")
|
|
177054
177265
|
);
|
|
177055
177266
|
await import_promises20.default.mkdir(dir, { recursive: true });
|
|
177056
177267
|
return dir;
|
|
@@ -177148,7 +177359,7 @@ function requireIosDeviceRunner(services) {
|
|
|
177148
177359
|
}
|
|
177149
177360
|
async function captureIosDeviceLiveInput(params) {
|
|
177150
177361
|
const png = await captureRunnerScreenshotPng(params.runner, RUNNER_COMMAND_TIMEOUT_MS);
|
|
177151
|
-
const suffix =
|
|
177362
|
+
const suffix = import_node_crypto14.default.randomBytes(4).toString("hex");
|
|
177152
177363
|
const destination = import_path8.default.join(params.outputDir, `${params.name}-${suffix}.live.png`);
|
|
177153
177364
|
await import_promises20.default.mkdir(params.outputDir, { recursive: true });
|
|
177154
177365
|
await import_promises20.default.writeFile(destination, png);
|
|
@@ -177166,7 +177377,7 @@ async function captureHarmonyLiveInput(params) {
|
|
|
177166
177377
|
}
|
|
177167
177378
|
await ensureDep("hdc");
|
|
177168
177379
|
const captured = await captureHarmonyScreenshotPng({ connectKey: params.connectKey, scale: 1 });
|
|
177169
|
-
const suffix =
|
|
177380
|
+
const suffix = import_node_crypto14.default.randomBytes(4).toString("hex");
|
|
177170
177381
|
const destination = import_path8.default.join(params.outputDir, `${params.name}-${suffix}.live.png`);
|
|
177171
177382
|
try {
|
|
177172
177383
|
await import_promises20.default.mkdir(params.outputDir, { recursive: true });
|
|
@@ -177202,7 +177413,7 @@ async function captureLiveInput(params) {
|
|
|
177202
177413
|
params.peekFor?.(params.device)
|
|
177203
177414
|
);
|
|
177204
177415
|
}
|
|
177205
|
-
const suffix =
|
|
177416
|
+
const suffix = import_node_crypto14.default.randomBytes(4).toString("hex");
|
|
177206
177417
|
const destination = import_path8.default.join(params.outputDir, `${params.name}-${suffix}.live.png`);
|
|
177207
177418
|
await import_promises20.default.mkdir(params.outputDir, { recursive: true });
|
|
177208
177419
|
await import_promises20.default.copyFile(capture.path, destination);
|
|
@@ -177921,13 +178132,13 @@ function probeArgentToolServer(host, port, timeoutMs = 500) {
|
|
|
177921
178132
|
|
|
177922
178133
|
// ../tool-server/src/utils/simulator-watcher.ts
|
|
177923
178134
|
var fs68 = __toESM(require("node:fs"));
|
|
177924
|
-
var
|
|
177925
|
-
var
|
|
178135
|
+
var import_node_child_process44 = require("node:child_process");
|
|
178136
|
+
var import_node_util32 = require("node:util");
|
|
177926
178137
|
init_external_devices();
|
|
177927
|
-
var
|
|
178138
|
+
var execFileAsync34 = (0, import_node_util32.promisify)(import_node_child_process44.execFile);
|
|
177928
178139
|
var POLL_INTERVAL_MS2 = 1e4;
|
|
177929
178140
|
async function getBootedUdidsInSet(deviceSet) {
|
|
177930
|
-
const { stdout } = await
|
|
178141
|
+
const { stdout } = await execFileAsync34("xcrun", [
|
|
177931
178142
|
...simctlPrefix(deviceSet),
|
|
177932
178143
|
"list",
|
|
177933
178144
|
"devices",
|
|
@@ -178046,7 +178257,7 @@ function startSimulatorWatcher(registry2) {
|
|
|
178046
178257
|
}
|
|
178047
178258
|
|
|
178048
178259
|
// ../tool-server/src/utils/preview-window.ts
|
|
178049
|
-
var
|
|
178260
|
+
var import_node_child_process45 = require("node:child_process");
|
|
178050
178261
|
var fs69 = __toESM(require("node:fs"));
|
|
178051
178262
|
var os20 = __toESM(require("node:os"));
|
|
178052
178263
|
var path52 = __toESM(require("node:path"));
|
|
@@ -178078,10 +178289,10 @@ function ensureLensAppBundle(electronBin) {
|
|
|
178078
178289
|
fs69.copyFileSync(path52.join(realContents, "Info.plist"), plist);
|
|
178079
178290
|
const setPlist = (entry, value) => {
|
|
178080
178291
|
try {
|
|
178081
|
-
(0,
|
|
178292
|
+
(0, import_node_child_process45.execFileSync)("/usr/libexec/PlistBuddy", ["-c", `Set :${entry} ${value}`, plist]);
|
|
178082
178293
|
} catch {
|
|
178083
178294
|
try {
|
|
178084
|
-
(0,
|
|
178295
|
+
(0, import_node_child_process45.execFileSync)("/usr/libexec/PlistBuddy", ["-c", `Add :${entry} string ${value}`, plist]);
|
|
178085
178296
|
} catch {
|
|
178086
178297
|
}
|
|
178087
178298
|
}
|
|
@@ -178140,7 +178351,7 @@ function createPreviewWindowManager(opts = {}) {
|
|
|
178140
178351
|
const wrapperBin = ensureLensAppBundle(electronBin);
|
|
178141
178352
|
const launchBin = wrapperBin ?? electronBin;
|
|
178142
178353
|
const launchArgs = wrapperBin ? ["--no-sandbox", mainScript] : [mainScript];
|
|
178143
|
-
const next = (0,
|
|
178354
|
+
const next = (0, import_node_child_process45.spawn)(launchBin, launchArgs, {
|
|
178144
178355
|
// Strips ELECTRON_RUN_AS_NODE, which an Electron-based MCP host leaves in
|
|
178145
178356
|
// our env, so the child boots as a GUI app instead of bare Node.
|
|
178146
178357
|
env: electronGuiChildEnv({ ARGENT_PREVIEW_URL: url2 }),
|
package/package.json
CHANGED
|
@@ -57,6 +57,7 @@ You do not need to derive `app_process` manually; just make sure the app is laun
|
|
|
57
57
|
|
|
58
58
|
Call `native-profiler-start` with `device_id` (iOS UDID or Android serial). The tool auto-detects the running app and saves the trace to `/tmp/argent-profiler-cwd/` with a timestamped filename.
|
|
59
59
|
Let the user interact with the app or drive interaction via simulator tools (see `argent-device-interact` skill).
|
|
60
|
+
While a profiler records, interaction tools return no automatic screenshot or element tree, so the capture does not load the app. Call `screenshot` or `describe` when you need to see the screen; interaction tools still wait for the screen to settle before they return, so add no wait of your own; on an Android emulator each screenshot during a profile takes one frame in about 100 ms and does not wake the screen capture; on a physical Android device it takes about 150–200 ms and briefly wakes the device screen capture, so take them sparingly there.
|
|
60
61
|
|
|
61
62
|
### Step 2: Stop and export
|
|
62
63
|
|
|
@@ -88,6 +88,8 @@ Mind the react-native and ios-native profiler selection mentioned above when sta
|
|
|
88
88
|
- if session is marked as "stale", you may overtake it without prompting the user for allowance
|
|
89
89
|
- if session is NOT "stale" - before taking action and terminating the other session, **stop and ask user what you should do**, explaining the situation.
|
|
90
90
|
|
|
91
|
+
While a profiler records, interaction tools return no automatic screenshot or element tree, so the capture does not load the app. Call `screenshot` or `describe` when you need to see the screen; interaction tools still wait for the screen to settle before they return, so add no wait of your own; on an Android emulator each screenshot during a profile takes one frame in about 100 ms and does not wake the screen capture; on a physical Android device it takes about 150–200 ms and briefly wakes the device screen capture, so take them sparingly there.
|
|
92
|
+
|
|
91
93
|
#### Annotate every interaction
|
|
92
94
|
|
|
93
95
|
After each `gesture-tap` or `gesture-swipe` call, record an annotation using the returned `timestampMs`. Compute `offsetMs = timestampMs - startedAtEpochMs`. Do this for _every_ interaction, including back-navigation swipes, not just the primary action. Pass all collected annotations to `react-profiler-analyze` in Step 3.
|