@rainbow-robotics/muscat-plugin-kit 0.1.2-dev.40 → 0.1.2-dev.42
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/cli/src/build.mjs +69 -29
- package/cli/src/devUi.mjs +9 -5
- package/cli/src/python.mjs +35 -48
- package/cli/src/templates-embedded.mjs +3 -0
- package/package.json +2 -2
package/cli/src/build.mjs
CHANGED
|
@@ -22,7 +22,7 @@ import { assertManifest, manifestRuntime } from "./manifest.mjs";
|
|
|
22
22
|
// In node mode, use the current process.
|
|
23
23
|
function findJsRuntime() {
|
|
24
24
|
if (typeof Bun === "undefined") return { bin: process.execPath, isBun: false };
|
|
25
|
-
for (const c of ["bun", "node", "
|
|
25
|
+
for (const c of ["bun", "node", "nodejs"]) {
|
|
26
26
|
if (hasBin(c)) return { bin: c, isBun: c === "bun" };
|
|
27
27
|
}
|
|
28
28
|
return null;
|
|
@@ -75,27 +75,33 @@ function isMainBranch() {
|
|
|
75
75
|
// rclpy: arch-agnostic (pure Python) → dist/ros2_ws/install/ (built once)
|
|
76
76
|
// rclcpp: arch-specific C++ binaries → dist/ros2_ws/install-{arch}/ per arch
|
|
77
77
|
export async function exportRos2Build(root, archs = ["amd64", "arm64"]) {
|
|
78
|
-
if (manifestRuntime(root) !== "ros2") return;
|
|
78
|
+
if (manifestRuntime(root) !== "ros2") return [];
|
|
79
79
|
const { assertDockerReady, ensureImage, colconBuild, ROS2_DEV_IMAGE, ARCH_DOCKER_PLATFORM } = await import("./ros2.mjs");
|
|
80
80
|
try {
|
|
81
81
|
assertDockerReady();
|
|
82
82
|
} catch (e) {
|
|
83
83
|
log.warn(`ros2 build skipped: ${e.message}`);
|
|
84
|
-
return;
|
|
84
|
+
return [];
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
const manifest = JSON.parse(readFileSync(resolve(root, "manifest.json"), "utf8"));
|
|
88
88
|
const rosClient = manifest.runtime?.rosClient;
|
|
89
89
|
|
|
90
|
+
const skipped = [];
|
|
90
91
|
if (rosClient === "rclcpp") {
|
|
91
92
|
// C++ ROS2: compile per arch so each robot picks the right install-{arch}/
|
|
92
93
|
for (const arch of archs) {
|
|
93
94
|
const dockerPlatform = ARCH_DOCKER_PLATFORM[arch];
|
|
94
|
-
if (!dockerPlatform) { log.warn(`unknown arch '${arch}' — skipped`); continue; }
|
|
95
|
+
if (!dockerPlatform) { log.warn(`unknown arch '${arch}' — skipped`); skipped.push(arch); continue; }
|
|
95
96
|
const archImage = `${ROS2_DEV_IMAGE}-${arch}`;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
try {
|
|
98
|
+
await ensureImage(archImage, { platform: dockerPlatform });
|
|
99
|
+
colconBuild(root, { symlink: false, arch });
|
|
100
|
+
log.ok(`dist/ros2_ws/install-${arch}/ ready`);
|
|
101
|
+
} catch {
|
|
102
|
+
log.warn(`${arch} ros2 build skipped — QEMU not available`);
|
|
103
|
+
skipped.push(arch);
|
|
104
|
+
}
|
|
99
105
|
}
|
|
100
106
|
} else {
|
|
101
107
|
// rclpy / pure Python: arch-agnostic, build once
|
|
@@ -103,6 +109,7 @@ export async function exportRos2Build(root, archs = ["amd64", "arm64"]) {
|
|
|
103
109
|
colconBuild(root, { symlink: false });
|
|
104
110
|
log.ok("dist/ros2_ws/install/ ready");
|
|
105
111
|
}
|
|
112
|
+
return skipped;
|
|
106
113
|
}
|
|
107
114
|
|
|
108
115
|
// For cpp plugins, compile cpp/ inside the Ubuntu container (Release) per arch
|
|
@@ -110,13 +117,13 @@ export async function exportRos2Build(root, archs = ["amd64", "arm64"]) {
|
|
|
110
117
|
// robot-compatible executables. rb-runtime prefers dist/{arch}/ and falls back
|
|
111
118
|
// to dist/{entry} (legacy). Skipped (with a warning) if Docker is unavailable.
|
|
112
119
|
export async function exportCppBuild(root, distDir, archs = ["amd64", "arm64"]) {
|
|
113
|
-
if (manifestRuntime(root) !== "cpp") return;
|
|
120
|
+
if (manifestRuntime(root) !== "cpp") return [];
|
|
114
121
|
const { assertDockerReady, ensureImage, cmakeBuild, CPP_DEV_IMAGE, ARCH_DOCKER_PLATFORM } = await import("./cpp.mjs");
|
|
115
122
|
try {
|
|
116
123
|
assertDockerReady();
|
|
117
124
|
} catch (e) {
|
|
118
125
|
log.warn(`cpp build skipped: ${e.message}`);
|
|
119
|
-
return;
|
|
126
|
+
return [];
|
|
120
127
|
}
|
|
121
128
|
|
|
122
129
|
const entry = JSON.parse(readFileSync(resolve(root, "manifest.json"), "utf8")).runtime?.entry;
|
|
@@ -125,26 +132,31 @@ export async function exportCppBuild(root, distDir, archs = ["amd64", "arm64"])
|
|
|
125
132
|
return;
|
|
126
133
|
}
|
|
127
134
|
|
|
135
|
+
const skipped = [];
|
|
128
136
|
for (const arch of archs) {
|
|
129
|
-
// python과 동일하게 arch별 이미지를 빌드해야 --platform 불일치를 피할 수 있다.
|
|
130
137
|
const dockerPlatform = ARCH_DOCKER_PLATFORM[arch];
|
|
131
|
-
if (!dockerPlatform) { log.warn(`unknown arch '${arch}' — skipped`); continue; }
|
|
138
|
+
if (!dockerPlatform) { log.warn(`unknown arch '${arch}' — skipped`); skipped.push(arch); continue; }
|
|
132
139
|
const archImage = `${CPP_DEV_IMAGE}-${arch}`;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
140
|
+
try {
|
|
141
|
+
await ensureImage(archImage, { platform: dockerPlatform });
|
|
142
|
+
cmakeBuild(root, { buildType: "Release", arch });
|
|
143
|
+
const built = resolve(root, `cpp/build-${arch}`, entry);
|
|
144
|
+
if (existsSync(built)) {
|
|
145
|
+
const archDir = resolve(distDir, arch);
|
|
146
|
+
mkdirSync(archDir, { recursive: true });
|
|
147
|
+
const dest = resolve(archDir, entry);
|
|
148
|
+
copyFileSync(built, dest);
|
|
149
|
+
chmodSync(dest, 0o755);
|
|
150
|
+
log.ok(`cpp binary → dist/${arch}/${entry}`);
|
|
151
|
+
} else {
|
|
152
|
+
log.warn(`cpp binary not found at cpp/build-${arch}/${entry}`);
|
|
153
|
+
}
|
|
154
|
+
} catch {
|
|
155
|
+
log.warn(`${arch} cpp build skipped — QEMU not available`);
|
|
156
|
+
skipped.push(arch);
|
|
146
157
|
}
|
|
147
158
|
}
|
|
159
|
+
return skipped;
|
|
148
160
|
}
|
|
149
161
|
|
|
150
162
|
const PRERELEASE_RE = /\.(dev|a|b|rc|alpha|beta)\d*/i;
|
|
@@ -245,10 +257,22 @@ export async function buildPlugin({ root, minify = false } = {}) {
|
|
|
245
257
|
mkdirSync(distDir, { recursive: true });
|
|
246
258
|
|
|
247
259
|
const manifest = JSON.parse(readFileSync(resolve(pluginRoot, "manifest.json"), "utf8"));
|
|
248
|
-
const contributesUi = (manifest.contributes ?? []).some((c) => c.ui);
|
|
249
260
|
const uiDir = resolve(pluginRoot, "ui");
|
|
261
|
+
const declaredUiEntries = [...new Set(
|
|
262
|
+
(manifest.contributes ?? []).map((c) => c.ui).filter(Boolean)
|
|
263
|
+
)];
|
|
264
|
+
// Validate each declared UI entry has a matching source file
|
|
265
|
+
for (const entry of declaredUiEntries) {
|
|
266
|
+
const exists = [".tsx", ".ts", ".jsx", ".js"].some(
|
|
267
|
+
(ext) => existsSync(resolve(uiDir, entry + ext))
|
|
268
|
+
);
|
|
269
|
+
if (!exists)
|
|
270
|
+
throw new Error(
|
|
271
|
+
`contributes declares ui "${entry}" but ui/${entry}.tsx (or .ts/.jsx/.js) does not exist.`
|
|
272
|
+
);
|
|
273
|
+
}
|
|
250
274
|
const hasUiFiles = existsSync(uiDir) && readdirSync(uiDir).some((f) => /\.[tj]sx?$/.test(f));
|
|
251
|
-
if (
|
|
275
|
+
if (declaredUiEntries.length > 0 || hasUiFiles) {
|
|
252
276
|
runViteBuild(pluginRoot, { mode: minify ? "production" : "development" });
|
|
253
277
|
}
|
|
254
278
|
|
|
@@ -422,6 +446,8 @@ export async function runBuild(args) {
|
|
|
422
446
|
|
|
423
447
|
const { pluginRoot, distDir } = await buildPlugin({ root, minify: true });
|
|
424
448
|
|
|
449
|
+
const skippedArches = { wheels: [], ros2: [], cpp: [] };
|
|
450
|
+
|
|
425
451
|
// python / rclpy: lock + wheel vendor in Ubuntu 24.04 container
|
|
426
452
|
if (!noLock) {
|
|
427
453
|
const manifest = JSON.parse(readFileSync(resolve(root, "manifest.json"), "utf8")).runtime ?? {};
|
|
@@ -431,15 +457,29 @@ export async function runBuild(args) {
|
|
|
431
457
|
if (needsLock) {
|
|
432
458
|
const { lockAndVendor } = await import("./python.mjs");
|
|
433
459
|
try {
|
|
434
|
-
await lockAndVendor(pluginRoot, archs);
|
|
460
|
+
skippedArches.wheels = await lockAndVendor(pluginRoot, archs);
|
|
435
461
|
} catch (e) {
|
|
436
462
|
log.warn(`python lock/vendor skipped: ${e.message}`);
|
|
463
|
+
skippedArches.wheels = archs;
|
|
437
464
|
}
|
|
438
465
|
}
|
|
439
466
|
}
|
|
440
467
|
|
|
441
|
-
await exportRos2Build(root, archs);
|
|
442
|
-
await exportCppBuild(root, distDir, archs);
|
|
468
|
+
skippedArches.ros2 = await exportRos2Build(root, archs) ?? [];
|
|
469
|
+
skippedArches.cpp = await exportCppBuild(root, distDir, archs) ?? [];
|
|
443
470
|
calcInstalledSize(pluginRoot);
|
|
444
471
|
if (!noZip) packZip(pluginRoot);
|
|
472
|
+
|
|
473
|
+
// Build summary
|
|
474
|
+
const allSkipped = [...new Set([...skippedArches.wheels, ...skippedArches.ros2, ...skippedArches.cpp])];
|
|
475
|
+
if (allSkipped.length > 0) {
|
|
476
|
+
const line = "─".repeat(58);
|
|
477
|
+
console.log(`\n${line}`);
|
|
478
|
+
log.warn(`Cross-arch builds skipped (QEMU not available): ${allSkipped.join(", ")}`);
|
|
479
|
+
if (skippedArches.wheels.length) log.warn(` wheels: ${skippedArches.wheels.join(", ")}`);
|
|
480
|
+
if (skippedArches.ros2.length) log.warn(` ros2: ${skippedArches.ros2.join(", ")}`);
|
|
481
|
+
if (skippedArches.cpp.length) log.warn(` cpp: ${skippedArches.cpp.join(", ")}`);
|
|
482
|
+
log.warn(` Enable: docker run --privileged --rm tonistiigi/binfmt --install all`);
|
|
483
|
+
console.log(line);
|
|
484
|
+
}
|
|
445
485
|
}
|
package/cli/src/devUi.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { copyFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
8
|
import { dirname, resolve } from "node:path";
|
|
9
9
|
import { SANDBOX_HTML } from "./build.mjs";
|
|
10
|
-
import { checkKitUpdate, findPluginRoot, hasBin, kitRoot, log } from "./util.mjs";
|
|
10
|
+
import { checkKitUpdate, findPluginRoot, hasBin, kitRoot, log, parseArgs, prompt } from "./util.mjs";
|
|
11
11
|
|
|
12
12
|
const PREVIEW_PKG = "@rainbow-robotics/preview-host";
|
|
13
13
|
const CACHE_DIR = resolve(homedir(), ".muscat-pk");
|
|
@@ -79,7 +79,7 @@ function findViteBin(pluginRoot) {
|
|
|
79
79
|
|
|
80
80
|
// Spawn vite build --watch as a background process.
|
|
81
81
|
// Returns the child process, or null if vite/node not available.
|
|
82
|
-
function spawnViteWatch(pluginRoot, node) {
|
|
82
|
+
function spawnViteWatch(pluginRoot, node, { robotIp = "" } = {}) {
|
|
83
83
|
const viteBin = findViteBin(pluginRoot);
|
|
84
84
|
if (!node || !viteBin || !existsSync(viteBin)) return null;
|
|
85
85
|
|
|
@@ -87,6 +87,7 @@ function spawnViteWatch(pluginRoot, node) {
|
|
|
87
87
|
return spawn(node, [viteBin, "build", "--watch", "--mode", "development", "--outDir", DEV_OUT], {
|
|
88
88
|
cwd: pluginRoot,
|
|
89
89
|
stdio: "inherit",
|
|
90
|
+
env: { ...process.env, ...(robotIp ? { VITE_RRS_PY_HOST: robotIp } : {}) },
|
|
90
91
|
});
|
|
91
92
|
}
|
|
92
93
|
|
|
@@ -105,15 +106,18 @@ function waitForInitialBuild(distDir, timeoutMs = 30_000) {
|
|
|
105
106
|
}
|
|
106
107
|
|
|
107
108
|
export async function runDevUi(args = []) {
|
|
108
|
-
const
|
|
109
|
-
const port =
|
|
109
|
+
const parsed = parseArgs(args);
|
|
110
|
+
const port = parsed.port ?? "4180";
|
|
111
|
+
const robotIp = parsed["robot-ip"] ?? await prompt(" Robot IP (Enter to skip): ");
|
|
110
112
|
|
|
111
113
|
await checkKitUpdate();
|
|
112
114
|
const pluginRoot = findPluginRoot();
|
|
113
115
|
const outDir = stageDevAssets(pluginRoot);
|
|
114
116
|
|
|
117
|
+
if (robotIp) log.info(`MUSCAT_API_ORIGIN → http://${robotIp}:*`);
|
|
118
|
+
|
|
115
119
|
const node = findNodeBin();
|
|
116
|
-
const viteProc = spawnViteWatch(pluginRoot, node);
|
|
120
|
+
const viteProc = spawnViteWatch(pluginRoot, node, { robotIp });
|
|
117
121
|
|
|
118
122
|
if (viteProc) {
|
|
119
123
|
log.step("waiting for initial vite build…");
|
package/cli/src/python.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Used by dev:back (hot-reload) and build (lock + wheel vendor).
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
|
-
import { dirname } from "node:path";
|
|
5
|
+
import { dirname, resolve } from "node:path";
|
|
6
6
|
import { hasBin, log, pruneMuskatImages, resolveDockerfile } from "./util.mjs";
|
|
7
7
|
|
|
8
8
|
export const PYTHON_DEV_IMAGE = "muscat-pk-python-dev";
|
|
@@ -27,22 +27,30 @@ export async function ensureImage(image = PYTHON_DEV_IMAGE, { platform = null }
|
|
|
27
27
|
pruneMuskatImages();
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
const
|
|
33
|
-
amd64:
|
|
34
|
-
|
|
30
|
+
// pip --platform does NOT auto-expand manylinux tags (unlike sys_tags()) — exact match only.
|
|
31
|
+
// Specifying all common glibc milestones ensures packages built for any Ubuntu era are found.
|
|
32
|
+
const PIP_PLATFORM = {
|
|
33
|
+
amd64: [
|
|
34
|
+
"manylinux_2_5_x86_64",
|
|
35
|
+
"manylinux_2_17_x86_64",
|
|
36
|
+
"manylinux_2_27_x86_64",
|
|
37
|
+
"manylinux_2_28_x86_64",
|
|
38
|
+
"manylinux_2_34_x86_64",
|
|
39
|
+
"manylinux_2_39_x86_64",
|
|
40
|
+
"linux_x86_64",
|
|
41
|
+
],
|
|
42
|
+
arm64: [
|
|
43
|
+
"manylinux_2_17_aarch64",
|
|
44
|
+
"manylinux_2_27_aarch64",
|
|
45
|
+
"manylinux_2_28_aarch64",
|
|
46
|
+
"manylinux_2_34_aarch64",
|
|
47
|
+
"manylinux_2_39_aarch64",
|
|
48
|
+
"linux_aarch64",
|
|
49
|
+
],
|
|
35
50
|
};
|
|
36
51
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
* 1. uv pip compile requirements.txt → dist/requirements.lock (arch 무관, 1회)
|
|
40
|
-
* 2. archs별 pip download --platform <manylinux_tag> → dist/wheels/ (네이티브 휠 벤더링)
|
|
41
|
-
*
|
|
42
|
-
* none-any 휠은 pip이 두 번째 arch에서 자동 skip → 중복 없음.
|
|
43
|
-
* requirements.txt 없으면 조용히 건너뜀.
|
|
44
|
-
*/
|
|
45
|
-
export async function lockAndVendor(pluginRoot, archs = ["x86_64", "aarch64"]) {
|
|
52
|
+
export async function lockAndVendor(pluginRoot, archs = ["amd64", "arm64"]) {
|
|
53
|
+
// ponytail: pip --platform used intentionally (not QEMU) — downloads wheels without running target arch code.
|
|
46
54
|
const reqTxt = resolve(pluginRoot, "requirements.txt");
|
|
47
55
|
if (!existsSync(reqTxt)) {
|
|
48
56
|
log.warn("requirements.txt not found — lock/vendor skipped");
|
|
@@ -66,45 +74,28 @@ export async function lockAndVendor(pluginRoot, archs = ["x86_64", "aarch64"]) {
|
|
|
66
74
|
if (lockResult.status !== 0) throw new Error("lock generation failed (uv pip compile)");
|
|
67
75
|
log.ok("dist/requirements.lock ready");
|
|
68
76
|
|
|
69
|
-
// arch별 휠 벤더링 — QEMU 불필요 (download only, --platform 고정)
|
|
70
|
-
// 한 arch가 실패해도 나머지 arch는 계속 시도한다.
|
|
71
77
|
const failed = [];
|
|
72
78
|
for (const arch of archs) {
|
|
73
|
-
const
|
|
74
|
-
if (!
|
|
75
|
-
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
// arch별 이미지 빌드 (--platform 지정) → pip이 glibc+arch 자동 감지 → 올바른 휠 선택.
|
|
79
|
-
const archImage = `${PYTHON_DEV_IMAGE}-${arch}`;
|
|
80
|
-
await ensureImage(archImage, { platform: dockerPlatform });
|
|
81
|
-
|
|
82
|
-
log.step(`vendoring wheels for ${arch} (${dockerPlatform})…`);
|
|
83
|
-
// 패키지별 개별 download로 private/미공개 패키지 실패 시에도 나머지 계속 진행.
|
|
84
|
-
const script = [
|
|
85
|
-
`set -e`,
|
|
86
|
-
`cd /plugin`,
|
|
87
|
-
`mkdir -p dist/wheels`,
|
|
88
|
-
`pkgs=$(grep -v '^#' dist/requirements.lock | grep -v '^[[:space:]]' | grep -v '^$')`,
|
|
89
|
-
`SKIP=""`,
|
|
90
|
-
`for pkg in $pkgs; do`,
|
|
91
|
-
` pip3 download "$pkg" --no-deps --only-binary=:all: -d dist/wheels -q 2>&1 || SKIP="$SKIP $pkg"`,
|
|
92
|
-
`done`,
|
|
93
|
-
`[ -z "$SKIP" ] || echo "WARN: no wheel found (package not on PyPI or missing binary wheel):$SKIP"`,
|
|
94
|
-
].join("\n");
|
|
79
|
+
const pipPlatforms = PIP_PLATFORM[arch];
|
|
80
|
+
if (!pipPlatforms) { log.warn(`unknown arch '${arch}' — skipped`); continue; }
|
|
81
|
+
log.step(`vendoring wheels for ${arch}…`);
|
|
95
82
|
const r = spawnSync(
|
|
96
83
|
"docker",
|
|
97
84
|
[
|
|
98
85
|
"run", "--rm",
|
|
99
|
-
"
|
|
86
|
+
"-e", "PIP_ROOT_USER_ACTION=ignore",
|
|
100
87
|
"-v", `${pluginRoot}:/plugin`,
|
|
101
|
-
|
|
102
|
-
|
|
88
|
+
"-w", "/plugin",
|
|
89
|
+
PYTHON_DEV_IMAGE,
|
|
90
|
+
"bash", "-c",
|
|
91
|
+
"mkdir -p dist/wheels && pip3 download -r dist/requirements.lock --no-deps --only-binary=:all: -d dist/wheels -q " +
|
|
92
|
+
"--python-version 312 --implementation cp --abi cp312 " +
|
|
93
|
+
pipPlatforms.map((p) => `--platform ${p}`).join(" "),
|
|
103
94
|
],
|
|
104
95
|
{ stdio: "inherit" },
|
|
105
96
|
);
|
|
106
97
|
if (r.status !== 0) {
|
|
107
|
-
log.warn(`wheel vendoring failed for ${arch}
|
|
98
|
+
log.warn(`wheel vendoring failed for ${arch}`);
|
|
108
99
|
failed.push(arch);
|
|
109
100
|
} else {
|
|
110
101
|
log.ok(`dist/wheels/ ready (${arch})`);
|
|
@@ -114,9 +105,5 @@ export async function lockAndVendor(pluginRoot, archs = ["x86_64", "aarch64"]) {
|
|
|
114
105
|
if (failed.length === archs.length) {
|
|
115
106
|
throw new Error(`wheel vendoring failed for all archs: ${failed.join(", ")}`);
|
|
116
107
|
}
|
|
117
|
-
|
|
118
|
-
log.warn(`wheel vendoring partial — failed: ${failed.join(", ")}, ok: ${archs.filter((a) => !failed.includes(a)).join(", ")}`);
|
|
119
|
-
} else {
|
|
120
|
-
log.ok(`dist/wheels/ ready (${archs.join(", ")})`);
|
|
121
|
-
}
|
|
108
|
+
return failed;
|
|
122
109
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// AUTO-GENERATED by cli/bundle-templates.mjs — do not edit.
|
|
2
|
+
// ponytail: generated at publish time; not tracked in git.
|
|
3
|
+
export const TEMPLATES = {"common/README.md":"IyBfX1BMVUdJTl9OQU1FX18KCkEgTXVzY2F0IHBsdWdpbiBwcm9qZWN0LiBCdWlsZCwgZGV2ZWxvcCwgYW5kIHNoaXAgd2l0aCBgbXVzY2F0LXBrYCBDTEkuCgojIyBRdWljayBzdGFydAoKYGBgYmFzaAptdXNjYXQtcGsgZGV2ICAgICAgICAjIFVJIHByZXZpZXcgKyBiYWNrZW5kIHRvZ2V0aGVyCm11c2NhdC1wayBkZXY6dWkgICAgICMgVUkgcHJldmlldyBvbmx5Cm11c2NhdC1wayBkZXY6YmFjayAgICMgYmFja2VuZCBvbmx5IChQeXRob24gd2F0Y2hmaWxlcyAvIFJPUzIgRG9ja2VyKQptdXNjYXQtcGsgYnVpbGQgICAgICAjIGJ1aWxkICsgZGlzdHJpYnV0YWJsZSBaSVAKYGBgCgotLS0KCiMjIFByb2plY3Qgc3RydWN0dXJlCgpgYGAKX19QTFVHSU5fRElSX18vCuKUnOKUgCB1aS8K4pSCICAg4pSU4pSAIGNvbnRlbnQudHN4ICAgICAgIyBwbHVnaW4gVUkgZW50cnkgcG9pbnQK4pSc4pSAIHB5LwrilIIgICDilJTilIAgbWFpbi5weSAgICAgICAgICAjIFB5dGhvbiBiYWNrZW5kIGVudHJ5IHBvaW50CuKUnOKUgCBhc3NldHMvCuKUgiAgIOKUlOKUgCBpY29uLnN2ZyAgICAgICAgICMgaWNvbiByZWZlcmVuY2VkIGZyb20gbWFuaWZlc3QK4pSc4pSAIG1hbmlmZXN0Lmpzb24gICAgICAgICMgbWV0YWRhdGEsIGNvbnRyaWJ1dGlvbiBwb2ludHMsIHJ1bnRpbWUgY29uZmlnCuKUnOKUgCBSRUFETUUubWQgICAgICAgICAgICAjIHRoaXMgZmlsZSAoY29waWVkIHRvIGRpc3QvIG9uIGJ1aWxkKQrilJTilIAgcmVxdWlyZW1lbnRzLnR4dCAgICAgIyBQeXRob24gZGVwcyAoYXV0by1waW5uZWQgdG8gbGF0ZXN0IG9uIGJ1aWxkKQpgYGAKCj4gUk9TMiBwbHVnaW5zIGFkZGl0aW9uYWxseSBpbmNsdWRlIGEgYHJvczJfd3MvYCBkaXJlY3RvcnkuCgotLS0KCiMjIEZyb250ZW5kIChgdWkvY29udGVudC50c3hgKQoKIyMjIHVzZVJiKCkgaG9vawoKQWNjZXNzIHRoZSBjb21tdW5pY2F0aW9uIEFQSSBiZXR3ZWVuIHRoZSBwbHVnaW4gbW9kdWxlIGFuZCBVSSBmcm9tIGFueSBwbHVnaW4gY29tcG9uZW50LgoKYGBgdHN4CmltcG9ydCB7IHVzZVJiIH0gZnJvbSAiQHJhaW5ib3ctcm9ib3RpY3MvcGx1Z2luLXVpL3NkayI7CgpmdW5jdGlvbiBBcHAoKSB7CiAgY29uc3QgcmIgPSB1c2VSYigpOwp9CmBgYAoKIyMjIHJiIEFQSQoKfCBNZXRob2QgfCBEZXNjcmlwdGlvbiB8CnwtLS18LS0tfAp8IGByYi5wdWIodG9waWMsIHBheWxvYWQpYCB8IFB1Ymxpc2ggYSBtZXNzYWdlIHRvIGEgdG9waWMgfAp8IGByYi5zdWIodG9waWMsIGhhbmRsZXIpYCB8IFN1YnNjcmliZSB0byBhIHRvcGljIOKAlCByZXR1cm5zIGB7IHVuZGVjbGFyZSgpIH1gIHwKfCBgcmIuYWN0aW9uKHRvcGljLCBwYXlsb2FkPylgIHwgU2VuZCBhIHJlcXVlc3QgYW5kIGF3YWl0IGEgcmVwbHkgfAp8IGByYi5zZXJ2ZSh0b3BpYywgaGFuZGxlcilgIHwgSGFuZGxlIGluY29taW5nIHJlcXVlc3RzIGZyb20gdGhlIGJhY2tlbmQgfAp8IGByYi50b2FzdChtZXNzYWdlLCB0eXBlPylgIHwgSG9zdCB0b2FzdCBub3RpZmljYXRpb24gKGAiaW5mbyIgwrcgInN1Y2Nlc3MiIMK3ICJ3YXJuaW5nIiDCtyAiZXJyb3IiYCkgfAoKQWxsIG1ldGhvZHMgc3VwcG9ydCBHZW5lcmljIFR5cGVzOgoKYGBgdHN4CmNvbnN0IHN0YXR1cyA9IGF3YWl0IHJiLmFjdGlvbjx7IG9rOiBib29sZWFuIH0sIHsgaWQ6IG51bWJlciB9PigKICAiZ2V0LXN0YXR1cyIsCiAgeyBpZDogMSB9LAopOwoKY29uc3Qgc3ViID0gYXdhaXQgcmIuc3ViPHsgdmFsdWU6IG51bWJlciB9Pigic2Vuc29yL2RhdGEiLCAoZGF0YSkgPT4gewogIGNvbnNvbGUubG9nKGRhdGEudmFsdWUpOwp9KTsKc3ViLnVuZGVjbGFyZSgpOyAvLyBjbGVhbnVwCmBgYAoKIyMjIFRvcGljIG5hbWVzcGFjZQoKVG9waWNzIGFyZSBhdXRvbWF0aWNhbGx5IG5hbWVzcGFjZWQgYnkgcGx1Z2luIElEIHRvIHByZXZlbnQgY29sbGlzaW9ucyBhY3Jvc3MgcGx1Z2lucy4KCmBgYAoic2Vuc29yL2RhdGEiICAg4oaSICBwbHVnaW4ve3BsdWdpbklkfS9zZW5zb3IvZGF0YSAgIChhdXRvLW5hbWVzcGFjZWQpCiIvYnJvYWRjYXN0L3giICDihpIgIGJyb2FkY2FzdC94ICAgICAgICAgICAgICAgICAgICAobGVhZGluZyAvID0gYWJzb2x1dGUpCmBgYAoKIyMjIFVJIGNvbXBvbmVudHMKCkltcG9ydCBNdXNjYXQgY29tcG9uZW50cyBmcm9tIGBAcmFpbmJvdy1yb2JvdGljcy9wbHVnaW4tdWkvcmVhY3RgLiBUaGUgcGx1Z2luIGVtaXRzCmByYi0qYCB0YWdzOyB0aGUgaG9zdCByZW5kZXJzIHRoZSBhY3R1YWwgY29tcG9uZW50cy4KCmBgYHRzeAppbXBvcnQgeyBjb25uZWN0IH0gZnJvbSAiQHJhaW5ib3ctcm9ib3RpY3MvcGx1Z2luLXVpL2Nvbm5lY3QiOwppbXBvcnQgeyBCdXR0b24sIFNsaWRlciwgVGV4dCwgU3dpdGNoIH0gZnJvbSAiQHJhaW5ib3ctcm9ib3RpY3MvcGx1Z2luLXVpL3JlYWN0IjsKaW1wb3J0IHsgdXNlUmIgfSBmcm9tICJAcmFpbmJvdy1yb2JvdGljcy9wbHVnaW4tdWkvc2RrIjsKCmZ1bmN0aW9uIEFwcCgpIHsKICBjb25zdCByYiA9IHVzZVJiKCk7CiAgcmV0dXJuIDxCdXR0b24gbGFiZWw9IlJ1biIgb25QcmVzcz17KCkgPT4gcmIuYWN0aW9uKCJydW4iKX0gLz47Cn0KCmNvbm5lY3QoQXBwKTsKYGBgCgotLS0KCiMjIEJhY2tlbmQgKGBweS9tYWluLnB5YCkKClRoZSBiYWNrZW5kIGNvbW11bmljYXRlcyB3aXRoIHRoZSBmcm9udGVuZCB1c2luZyBgcmFpbmJvdy5yYl9zZGsuUkJQbHVnaW5DYWxsYC4KYG11c2NhdC1wayBkZXZgIHN0YXJ0cyB0aGUgU29ja2V0LklPIGJyaWRnZSBpbiBEb2NrZXIgKHB1Ymxpc2hlZCBvbiBwb3J0IDEwMDAwKSBhbmQKcnVucyB0aGUgYmFja2VuZCBjb250YWluZXIgc2hhcmluZyBpdHMgbmV0d29yaywgc28gdGhlIFNESyBjb25uZWN0cyBhdCBsb2NhbGhvc3Q6MTAwMDAuCmBweS9tYWluLnB5YCBzaG91bGQgY29udGFpbiBwbHVnaW4gbG9naWMgb25seSBhbmQgbXVzdCBub3Qgc3RhcnQgaXRzIG93biBzZXJ2ZXIuCgojIyMgUHl0aG9uIHBsdWdpbgoKYGBgcHl0aG9uCmltcG9ydCB0aW1lCmZyb20gcmFpbmJvdy5yYl9zZGsgaW1wb3J0IFJCQW1yU0RLLCBSQk1hbmlwdWxhdGVTREssIFJCUGx1Z2luQ2FsbAoKcGx1Z2luID0gUkJQbHVnaW5DYWxsKCkKCgpwbHVnaW4ucHVibGlzaCgic3RhdGUiLCB7InJlYWR5IjogVHJ1ZX0pCgoKQHBsdWdpbi5zdWJzY3JpYmUoImV2ZW50IikKZGVmIG9uX3VpX2V2ZW50KHBheWxvYWQ9Tm9uZSk6CiAgICBwcmludChwYXlsb2FkKQoKCkBwbHVnaW4uc2VydmUoInRvb2wvZWNobyIpCmRlZiBlY2hvKHBheWxvYWQ9Tm9uZSk6CiAgICByZXR1cm4geyJlY2hvIjogcGF5bG9hZH0KCgpkZWYgY2FsbF9mcm9udGVuZCgpOgogICAgcmVzID0gcGx1Z2luLmNhbGwoInRvb2wvcGluZyIsIHBheWxvYWQ9eyJoZWxsbyI6ICJwbHVnaW4ifSkKICAgIHByaW50KHJlcykKCgpkZWYgbW92ZV9qX2V4YW1wbGUoKToKICAgIGFtciA9IFJCQW1yU0RLKCkKICAgIG1hbmlwdWxhdGUgPSBSQk1hbmlwdWxhdGVTREsoKQogICAgcmV0dXJuIG1hbmlwdWxhdGUubW92ZS5jYWxsX21vdmVfaigKICAgICAgICByb2JvdF9tb2RlbD0iQzUwMDkyMCIsCiAgICAgICAgdGFyZ2V0PXsidGFyX3ZhbHVlcyI6IFswLCAwLCAwLCAwLCAwLCAwXSwgInRhcl9mcmFtZSI6IDAsICJ0YXJfdW5pdCI6IDB9LAogICAgKQoKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICB3aGlsZSBUcnVlOgogICAgICAgIHRpbWUuc2xlZXAoMSkKYGBgCgojIyMgUk9TMiBwbHVnaW4KClRoZSBub2RlIGlzIGxhdW5jaGVkIHdpdGggYC0tcm9zLWFyZ3MgLXIgX19uczo9L3tzbHVnfWAgYXV0b21hdGljYWxseSBieSBgZGV2OmJhY2tgLgoKYGBgcHl0aG9uCiMgcm9zMl93cy9zcmMvX19QTFVHSU5fU0xVR19fL19fUExVR0lOX1NMVUdfXy9ub2RlLnB5CmltcG9ydCByY2xweQpmcm9tIHJjbHB5Lm5vZGUgaW1wb3J0IE5vZGUKZnJvbSBzdGRfbXNncy5tc2cgaW1wb3J0IEZsb2F0MzIKCmNsYXNzIF9fUExVR0lOX0NMQVNTX19Ob2RlKE5vZGUpOgogICAgZGVmIF9faW5pdF9fKHNlbGYpOgogICAgICAgIHN1cGVyKCkuX19pbml0X18oIl9fUExVR0lOX1NMVUdfX19ub2RlIikKICAgICAgICAjIHJlbGF0aXZlIHRvcGljIG5hbWUg4oCUIF9fbnMgcHJlZml4IGFwcGxpZWQgYXV0b21hdGljYWxseQogICAgICAgIHNlbGYucHViID0gc2VsZi5jcmVhdGVfcHVibGlzaGVyKEZsb2F0MzIsICJzZW5zb3JfZGF0YSIsIDEwKQogICAgICAgIHNlbGYuY3JlYXRlX3RpbWVyKDEuMCwgc2VsZi50aW1lcl9jYikKCiAgICBkZWYgdGltZXJfY2Ioc2VsZik6CiAgICAgICAgc2VsZi5wdWIucHVibGlzaChGbG9hdDMyKGRhdGE9NDIuMCkpCmBgYAoKLS0tCgojIyBtYW5pZmVzdC5qc29uCgpgYGBqc29uYwp7CiAgLy8gdW5pcXVlIHBsdWdpbiBJRCDigJQgcmV2ZXJzZS1kb21haW4gZm9ybWF0IHJlY29tbWVuZGVkCiAgImlkIjogImNvbS5leGFtcGxlLm15LXBsdWdpbiIsCiAgIm5hbWUiOiAiTXkgUGx1Z2luIiwKICAidmVyc2lvbiI6ICIxLjAuMCIsCgogIC8vIG1pbmltdW0gTXVzY2F0IHZlcnNpb24gcmVxdWlyZWQgdG8gbG9hZCB0aGlzIHBsdWdpbgogICJtaW5NdXNjYXRWZXJzaW9uIjogIjEuMC4wIiwKCiAgLy8gcGx1Z2luIGF1dGhvciAoZW1wdHkgc3RyaW5nIGlzIGZpbmUpCiAgImF1dGhvciI6ICJZb3VyIE5hbWUiLAoKICAvLyBkaXNwbGF5ZWQgaW4gdGhlIE11c2NhdCBwbHVnaW4gc3RvcmUgLyBpbmZvIHBhbmVsCiAgLy8gc3RyaW5nIG9yIHsgZW4gKHJlcXVpcmVkKSwga28sIGphLCB6aCwgdmksIHRoLCBlcyB9CiAgImRlc2NyaXB0aW9uIjogeyAiZW4iOiAiUGx1Z2luIGRlc2NyaXB0aW9uIiwgImtvIjogIu2UjOufrOq3uOyduCDshKTrqoUiIH0sCgogIC8vIFNWRyBzdHJpbmcgKHNpbmdsZSBmaWxlKSBvciBQTkcvSlBHIHNpemUgbWFwIChhbGwgdGhyZWUgc2l6ZXMgcmVxdWlyZWQpCiAgImljb25zIjogImFzc2V0cy9pY29uLnN2ZyIsCiAgLy8gImljb25zIjogeyAiMTYiOiAiYXNzZXRzL2ljb24tMTYucG5nIiwgIjQ4IjogImFzc2V0cy9pY29uLTQ4LnBuZyIsICIxMjgiOiAiYXNzZXRzL2ljb24tMTI4LnBuZyIgfSwKCiAgLy8gdGFyZ2V0TW9kZWxzIGFuZC9vciB0YXJnZXRDYXRlZ29yeXMg4oCUIGF0IGxlYXN0IG9uZSBpcyByZXF1aXJlZAogIC8vICJhbGwiID0gZXZlcnkgdGFyZ2V0LCBvciBsaXN0IHNwZWNpZmljIHZhbHVlcwogICJ0YXJnZXRNb2RlbHMiOiAiYWxsIiwKICAvLyAidGFyZ2V0TW9kZWxzIjogWyJDNTAwOTIwIiwgIkM1MDA5MzAiXSwKICAidGFyZ2V0Q2F0ZWdvcnlzIjogImFsbCIsCiAgLy8gInRhcmdldENhdGVnb3J5cyI6IFsibWFuaXB1bGF0ZSIsICJhbXIiLCAicmJ5MSIsICJ2aXNpb24iXSwKCiAgImNvbnRyaWJ1dGVzIjogWwogICAgLy8gcHJvZ3JhbS5jb21tYW5kIOKAlCBhZGRzIGEgc3RlcCBub2RlIHRvIHRoZSBwcm9ncmFtIHRyZWUKICAgIHsKICAgICAgInBvaW50IjogInByb2dyYW0uY29tbWFuZCIsCiAgICAgICJpY29uIjogImFzc2V0cy9pY29uLnN2ZyIsCiAgICAgICJsYWJlbCI6IHsgImtvIjogIuuCtCDtlIzrn6zqt7jsnbgiLCAiZW4iOiAiTXkgUGx1Z2luIiB9LAogICAgICAidWkiOiAicHJvZ3JhbS9jb250ZW50IiwgICAvLyBtdXN0IGJlIHVuaXF1ZSBhY3Jvc3MgYWxsIGNvbnRyaWJ1dGlvbnMKICAgICAgImNvbW1hbmRJbmZvIjogewogICAgICAgICJuYW1lIjogIk15IFBsdWdpbiIsCiAgICAgICAgImljb24iOiAiYXNzZXRzL2ljb24uc3ZnIiwKICAgICAgICAiZnVuY05hbWUiOiAicGx1Z2luLnJ1biIsCiAgICAgICAgImFyZ3MiOiB7fQogICAgICB9CiAgICB9LAogICAgLy8gdG9vbGJhciDigJQgYWRkcyBhIGJ1dHRvbiB0byB0aGUgdG9wIHRvb2xiYXIgKHJlcXVpcmVkKQogICAgewogICAgICAicG9pbnQiOiAidG9vbGJhciIsCiAgICAgICJpY29uIjogImFzc2V0cy9pY29uLnN2ZyIsCiAgICAgICJsYWJlbCI6IHsgImtvIjogIuuCtCDtlIzrn6zqt7jsnbgiLCAiZW4iOiAiTXkgUGx1Z2luIiB9LAogICAgICAidWkiOiAiY29udGVudCIsICAgICAgICAgICAvLyBtdXN0IGJlIHVuaXF1ZSBhY3Jvc3MgYWxsIGNvbnRyaWJ1dGlvbnMKICAgICAgIm9wZW5zIjogInBvcG92ZXIiCiAgICB9LAogICAgLy8gbW92ZS5ybmIg4oCUIGFkZHMgYSBwYW5lbCB0byB0aGUgTW92ZSBzY3JlZW4gcmlnaHQtc2lkZSBhcmVhCiAgICB7CiAgICAgICJwb2ludCI6ICJtb3ZlLnJuYiIsCiAgICAgICJpY29uIjogImFzc2V0cy9pY29uLnN2ZyIsCiAgICAgICJsYWJlbCI6IHsgImtvIjogIuuCtCDtlIzrn6zqt7jsnbgiLCAiZW4iOiAiTXkgUGx1Z2luIiB9LAogICAgICAidWkiOiAibW92ZS9jb250ZW50IiAgICAgICAvLyBtdXN0IGJlIHVuaXF1ZSBhY3Jvc3MgYWxsIGNvbnRyaWJ1dGlvbnMKICAgIH0KICBdLAoKICAvLyBydW50aW1lIOKAlCBvbmUgb2Y6CiAgLy8gICB7ICJ0eXBlIjogIm5vbmUiIH0KICAvLyAgIHsgInR5cGUiOiAicHl0aG9uIiwgImVudHJ5IjogIm1haW4ucHkiIH0KICAvLyAgIHsgInR5cGUiOiAiY3BwIiwgImVudHJ5IjogIjxleGVjdXRhYmxlIG5hbWU+IiB9CiAgLy8gICB7ICJ0eXBlIjogInJvczIiLCAicm9zQ2xpZW50IjogInJjbHB5IiB8ICJyY2xjcHAiLCAicGFja2FnZSI6ICIuLi4iLCAibGF1bmNoIjogIi4uLl9ub2RlIiB9CiAgInJ1bnRpbWUiOiB7ICJ0eXBlIjogInB5dGhvbiIsICJlbnRyeSI6ICJtYWluLnB5IiB9Cn0KYGBgCgoqKkJhY2tlbmQgdHlwZXM6KioKCnwgdHlwZSB8IHNvdXJjZSBkaXIgfCBidWlsZCAvIHJ1biB8IGVudHJ5IHwKfC0tLXwtLS18LS0tfC0tLXwKfCBgcHl0aG9uYCB8IGBweS9gIHwgcGlwICsgcnVuIGluIERvY2tlciB8IGBtYWluLnB5YCB8CnwgYGNwcGAgfCBgY3BwL2AgfCBDTWFrZSBpbiBEb2NrZXIgfCBidWlsdCBleGVjdXRhYmxlIG5hbWUgfAp8IGByb3MyYCAocmNscHkpIHwgYHJvczJfd3MvYCB8IGNvbGNvbiAoYW1lbnRfcHl0aG9uKSBpbiBEb2NrZXIgfCDigJQgfAp8IGByb3MyYCAocmNsY3BwKSB8IGByb3MyX3dzL2AgfCBjb2xjb24gKGFtZW50X2NtYWtlKSBpbiBEb2NrZXIgfCDigJQgfAoKPiBFdmVyeSBiYWNrIGVuZCBydW5zIGluIGEgRG9ja2VyIGNvbnRhaW5lciBtYXRjaGluZyB0aGUgcm9ib3QgKFVidW50dSAyNC4wNCArIFB5dGhvbiAzLjEyKSwgc28gZGV2IGJlaGF2ZXMgbGlrZSBwcm9kdWN0aW9uIGFuZCBjb21waWxlZCBiaW5hcmllcyBhcmUgQUJJLWNvbXBhdGlibGUuICoqRG9ja2VyIGlzIHJlcXVpcmVkKiogZm9yIGFsbCBiYWNrZW5kIHR5cGVzIChvbmx5IGEgZnJvbnRlbmQtb25seSBgbm9uZWAgcGx1Z2luIHNraXBzIGl0KS4gTm8gbG9jYWwgUHl0aG9uL3Rvb2xjaGFpbiBzZXR1cCBpcyBuZWVkZWQuCgoqKkNvbnRyaWJ1dGlvbiBwb2ludHM6KioKCnwgcG9pbnQgfCBXaGVyZSBpdCBhcHBlYXJzIHwgYGNvbW1hbmRJbmZvYCByZXF1aXJlZCB8CnwtLS18LS0tfDotLS06fAp8IGB0b29sYmFyYCB8IFRvcCB0b29sYmFyIGJ1dHRvbiAobXVzdCBoYXZlIGF0IGxlYXN0IG9uZSkgfCDigJQgfAp8IGBwcm9ncmFtLmNvbW1hbmRgIHwgUHJvZ3JhbSB0cmVlIHN0ZXAgbm9kZSB8IOKckyB8CnwgYG1vdmUucm5iYCB8IE1vdmUgc2NyZWVuIHJpZ2h0LXNpZGUgcGFuZWwgfCDigJQgfAoKKipgY29tbWFuZEluZm9gIGZpZWxkcyoqIChmb3IgYHByb2dyYW0uY29tbWFuZGApOgoKfCBmaWVsZCB8IHR5cGUgfCBkZXNjcmlwdGlvbiB8CnwtLS18LS0tfC0tLXwKfCBgbmFtZWAgfCBgc3RyaW5nYCB8IERpc3BsYXkgbmFtZSBvZiB0aGUgc3RlcCBub2RlIHwKfCBgaWNvbmAgfCBgc3RyaW5nYCB8IEljb24gcGF0aCB8CnwgYGljb25DbGFzc05hbWVgIHwgYHN0cmluZz9gIHwgT3B0aW9uYWwgQ1NTIGNsYXNzIGZvciB0aGUgaWNvbiB8CnwgYGZ1bmNOYW1lYCB8IGBzdHJpbmc/YCB8IEJhY2tlbmQgZnVuY3Rpb24gbmFtZSB0byBjYWxsIHwKfCBgYXJnc2AgfCBgUmVjb3JkPHN0cmluZywgYW55Pj9gIHwgRGVmYXVsdCBhcmd1bWVudHMgfAp8IGBkaXNhYmxlZGAgfCBgYm9vbGVhbj9gIHwgV2hldGhlciB0aGUgbm9kZSBpcyBkaXNhYmxlZCB8CnwgYGFsbG93Q2hpbGRyZW5gIHwgYHN0cmluZ1tdP2AgfCBBbGxvd2VkIGNoaWxkIGNvbW1hbmRzIHwKfCBgYWxsb3dQYXJlbnRzYCB8IGBzdHJpbmdbXT9gIHwgQWxsb3dlZCBwYXJlbnQgY29tbWFuZHMgfAp8IGBub3RBbGxvd0NoaWxkcmVuYCB8IGBzdHJpbmdbXT9gIHwgRGlzYWxsb3dlZCBjaGlsZCBjb21tYW5kcyB8CnwgYHN5bmNHcm91cElkYCB8IGBib29sZWFuP2AgfCBTeW5jIGdyb3VwIElEIGFjcm9zcyBjaGlsZHJlbiB8CnwgYGRpc2FibGVDb3B5YCB8IGBib29sZWFuP2AgfCBQcmV2ZW50IGNvcHkgfAp8IGBkaXNhYmxlRGVsZXRlYCB8IGBib29sZWFuP2AgfCBQcmV2ZW50IGRlbGV0ZSB8CnwgYHJlcXVpcmVDaGlsZHJlbmAgfCBgYm9vbGVhbj9gIHwgV2hldGhlciBhIGNoaWxkIGNvbW1hbmQgaXMgcmVxdWlyZWQgfAp8IGByZXF1aXJlUGFyZW50YCB8IGBib29sZWFuP2AgfCBXaGV0aGVyIGEgcGFyZW50IGNvbW1hbmQgaXMgcmVxdWlyZWQgfAp8IGBjaGlsZHJlbkNvbW1hbmRgIHwgYHN0cmluZz9gIHwgRGVmYXVsdCBjb21tYW5kIHR5cGUgZm9yIGNoaWxkcmVuIHwKCioqVmFsaWRhdGlvbiBydWxlczoqKgotIGBpZGAsIGBuYW1lYCwgYHZlcnNpb25gLCBgbWluTXVzY2F0VmVyc2lvbmAg4oCUIHJlcXVpcmVkIG5vbi1lbXB0eSBzdHJpbmdzCi0gYGF1dGhvcmAg4oCUIHJlcXVpcmVkIG5vbi1lbXB0eSBzdHJpbmcKLSBgZGVzY3JpcHRpb25gIOKAlCByZXF1aXJlZCAoYHN0cmluZ2Agb3IgYHsgZW4gKHJlcXVpcmVkKSwga28/LCBqYT8sIHpoPywgdmk/LCB0aD8sIGVzPyB9YCkKLSBgaWNvbnNgIOKAlCBTVkc6IHNpbmdsZSBzdHJpbmcgcGF0aCBlbmRpbmcgaW4gYC5zdmdgOyBQTkcvSlBHOiBvYmplY3Qgd2l0aCBgIjE2ImAsIGAiNDgiYCwgYCIxMjgiYCBhbGwgcHJlc2VudAotIGB0YXJnZXRNb2RlbHNgIOKAlCBgImFsbCJgIG9yIGEgbm9uLWVtcHR5IGFycmF5IG9mIHJvYm90IG1vZGVsIElEIHN0cmluZ3MgKGF0IGxlYXN0IG9uZSBvZiBgdGFyZ2V0TW9kZWxzYCAvIGB0YXJnZXRDYXRlZ29yeXNgIHJlcXVpcmVkKQotIGB0YXJnZXRDYXRlZ29yeXNgIOKAlCBgImFsbCJgIG9yIGEgbm9uLWVtcHR5IGFycmF5IG9mIGAibWFuaXB1bGF0ZSIgfCAiYW1yIiB8ICJyYnkxIiB8ICJ2aXNpb24iYCAoYXQgbGVhc3Qgb25lIG9mIGB0YXJnZXRNb2RlbHNgIC8gYHRhcmdldENhdGVnb3J5c2AgcmVxdWlyZWQpCi0gYGNvbnRyaWJ1dGVzYCDigJQgcmVxdWlyZWQgYXJyYXk7IG11c3QgY29udGFpbiBhdCBsZWFzdCBvbmUgYHRvb2xiYXJgIGVudHJ5Ci0gYHVpYCDigJQgZWFjaCBjb250cmlidXRpb24gbXVzdCBoYXZlIGEgdW5pcXVlIHZhbHVlCi0gYGNvbW1hbmRJbmZvYCDigJQgcmVxdWlyZWQgd2hlbiBgcG9pbnRgIGlzIGAicHJvZ3JhbS5jb21tYW5kImAKCmBtdXNjYXQtcGsgYnVpbGRgIHRocm93cyBvbiBhbnkgdmFsaWRhdGlvbiBlcnJvci4gYG11c2NhdC1wayBkZXZgIHByaW50cyB3YXJuaW5ncy4KCi0tLQoKIyMgTG9jYWxpemVkIGRvY3VtZW50YXRpb24KCllvdSBjYW4gc2hpcCBwZXItbGFuZ3VhZ2UgUkVBRE1FIGZpbGVzIGFsb25nc2lkZSB0aGUgbWFpbiBgUkVBRE1FLm1kYC4gUGxhY2UgdGhlbSBpbiB0aGUgcHJvamVjdCByb290OgoKYGBgClJFQURNRS5tZCAgICAgICAgIyBkZWZhdWx0IC8gRW5nbGlzaCBmYWxsYmFjawpSRUFETUUua28ubWQgICAgICMgS29yZWFuClJFQURNRS5lbi5tZCAgICAgIyBleHBsaWNpdCBFbmdsaXNoIChvcHRpb25hbCkKUkVBRE1FLmphLm1kICAgICAjIEphcGFuZXNlCmBgYAoKQWxsIGBSRUFETUUqLm1kYCBmaWxlcyBmb3VuZCBhdCB0aGUgcHJvamVjdCByb290IGFyZSBhdXRvbWF0aWNhbGx5IGNvcGllZCB0byBgZGlzdC9gIG9uCmBtdXNjYXQtcGsgYnVpbGRgLiBNdXNjYXQgZGlzcGxheXMgdGhlIGZpbGUgbWF0Y2hpbmcgdGhlIHVzZXIncyBsb2NhbGUsCmZhbGxpbmcgYmFjayB0byBgUkVBRE1FLm1kYCBpZiBub25lIG1hdGNoZXMuCgotLS0KCiMjIEluc3RhbGxpbmcgUHl0aG9uIGRlcGVuZGVuY2llcwoKQWRkIGFueSBwYWNrYWdlIHdpdGggYW4gb3B0aW9uYWwgdmVyc2lvbiBwaW4gdG8gYHJlcXVpcmVtZW50cy50eHRgOgoKYGBgCnJhaW5ib3ctcmItc2RrCnJhaW5ib3ctcmItZmxhdC1idWZmZXJzCm51bXB5PT0xLjI2LjQKb3BlbmN2LXB5dGhvbgpgYGAKClJ1biBgbXVzY2F0LXBrIGRldmAgb3IgYG11c2NhdC1wayBkZXY6YmFja2Ag4oCUIGRlcGVuZGVuY2llcyBhcmUgaW5zdGFsbGVkIGF1dG9tYXRpY2FsbHkgaW5zaWRlIHRoZSBkZXYgY29udGFpbmVyIChgcGlwIGluc3RhbGwgLXIgcmVxdWlyZW1lbnRzLnR4dGApIG9uIGV2ZXJ5IHN0YXJ0dXAuIE5vIGxvY2FsIFB5dGhvbiBvciB2ZW52IG5lZWRlZC4KCj4gYG11c2NhdC1wayBidWlsZGAgb25seSAqKnBpbnMqKiB2ZXJzaW9ucyBpbiBgcmVxdWlyZW1lbnRzLnR4dGAg4oCUIGl0IGRvZXMgbm90IHJ1biBgcGlwIGluc3RhbGxgICh0aGUgcm9ib3QgaW5zdGFsbHMgdGhlbSBhdCBsb2FkIHRpbWUpLgoKLS0tCgojIyBTd2l0Y2hpbmcgYmFja2VuZCB0eXBlCgpgYGBiYXNoCm11c2NhdC1wayB0eXBlIGNoYW5nZSAgICAgICAgICAgICAgICAgIyBpbnRlcmFjdGl2ZQptdXNjYXQtcGsgdHlwZSBjaGFuZ2UgLS10byBjcHAgICAgICAgICMg4oaSIEMrKwptdXNjYXQtcGsgdHlwZSBjaGFuZ2UgLS10byByb3MyICAgICAgICMg4oaSIFJPUzIgKHJjbHB5IC8gUHl0aG9uKQptdXNjYXQtcGsgdHlwZSBjaGFuZ2UgLS10byByb3MyLWNwcCAgICMg4oaSIFJPUzIgKHJjbGNwcCAvIEMrKykKbXVzY2F0LXBrIHR5cGUgY2hhbmdlIC0tdG8gcHl0aG9uICAgICAjIOKGkiBQeXRob24KYGBgCgo+IEV4aXN0aW5nIGJhY2tlbmQgZGlycyAoYHJvczJfd3MvYCwgYGNwcC9gKSBhcmUgbm90IGRlbGV0ZWQgd2hlbiBzd2l0Y2hpbmcgYXdheS4gUmVtb3ZlIHRoZW0gbWFudWFsbHkgaWYgbm8gbG9uZ2VyIG5lZWRlZC4KCi0tLQoKIyMgU2hpcHBpbmcKCmBgYGJhc2gKbXVzY2F0LXBrIGJ1aWxkICAgICAgICAgICAgIyBidWlsZCArIFpJUAptdXNjYXQtcGsgYnVpbGQgLS1uby16aXAgICAjIGJ1aWxkIG9ubHksIG5vIFpJUApgYGAKCi0gQnVpbGRzIGB1aS9jb250ZW50LnRzeGAg4oaSIGBkaXN0L2NvbnRlbnQuanNgIChtaW5pZmllZCkKLSBQaW5zIGByZXF1aXJlbWVudHMudHh0YCB0byBsYXRlc3QgdmVyc2lvbnMgKHN0YWJsZS1vbmx5IG9uIGBtYWluYCBicmFuY2gpCi0gQ29waWVzIGBhc3NldHMvYCwgYG1hbmlmZXN0Lmpzb25gLCBgUkVBRE1FKi5tZGAsIGBweS9gLCBhbmQgYHJlcXVpcmVtZW50cy50eHRgIGludG8gYGRpc3QvYAotIFJPUzI6IHJ1bnMgYGNvbGNvbiBidWlsZGAgaW5zaWRlIHRoZSBKYXp6eSBjb250YWluZXI7IGluY2x1ZGVzIGByb3MyX3dzL2luc3RhbGwvYAotIE91dHB1dDogYF9fUExVR0lOX0RJUl9fLXt2ZXJzaW9ufS56aXBgCgpaSVAgbGF5b3V0OgoKYGBgCl9fUExVR0lOX0RJUl9fLTEuMC4wLnppcArilJzilIAgZGlzdC8K4pSCICAg4pSc4pSAIGNvbnRlbnQuanMgICAgICAgICMgYnVpbHQgVUkK4pSCICAg4pSc4pSAIG1hbmlmZXN0Lmpzb24K4pSCICAg4pSc4pSAIGFzc2V0cy8K4pSCICAg4pSc4pSAIFJFQURNRS5tZArilIIgICDilJzilIAgUkVBRE1FLmtvLm1kICAgICAgIyBpZiBwcmVzZW50CuKUgiAgIOKUnOKUgCBtYWluLnB5ICAgICAgICAgICAjIGZyb20gcHkvCuKUgiAgIOKUlOKUgCByZXF1aXJlbWVudHMudHh0ICAjIHBpbm5lZArilJTilIAgcm9zMl93cy9pbnN0YWxsLyAgICAgICMgUk9TMiBvbmx5CmBgYAoKLS0tCgojIyBBbGwgY29tbWFuZHMKCmBgYGJhc2gKbXVzY2F0LXBrIGRldiAgICAgICAgIyBVSSArIGJhY2tlbmQKbXVzY2F0LXBrIGRldjp1aSAgICAgIyBVSSBwcmV2aWV3IG9ubHkgKHByZXZpZXctaG9zdCkKbXVzY2F0LXBrIGRldjpiYWNrICAgIyBiYWNrZW5kIG9ubHkgKFB5dGhvbjogd2F0Y2hmaWxlcyAvIFJPUzI6IERvY2tlcikKbXVzY2F0LXBrIGJ1aWxkICAgICAgIyBidWlsZCDihpIgZGlzdC8gKyBkaXN0cmlidXRhYmxlIFpJUCAoLS1uby16aXAgdG8gc2tpcCkKYGBgCgpgYGBiYXNoCm11c2NhdC1wayB0eXBlIGNoYW5nZSAgICAjIHN3aXRjaCBiYWNrZW5kIHR5cGUKbXVzY2F0LXBrIHNkayBsaXN0ICAgICAgICMgc2hvdyBjdXJyZW50IFB5dGhvbiBTREsgdmVyc2lvbgptdXNjYXQtcGsgc2RrIHVwZGF0ZSAgICAgIyB1cGRhdGUgUHl0aG9uIFNESyB0byBsYXRlc3QKbXVzY2F0LXBrIHVwZGF0ZSAgICAgICAgICMgdXBkYXRlIG11c2NhdC1wbHVnaW4ta2l0IGl0c2VsZgptdXNjYXQtcGsgdW5pbnN0YWxsICAgICAgIyByZW1vdmUgbXVzY2F0LXBrIGl0c2VsZgpgYGAK","common/assets/icon.svg":"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjFlbSIgaGVpZ2h0PSIxZW0iIGZpbGw9Im5vbmUiPgogIDxwYXRoIGZpbGw9ImN1cnJlbnRDb2xvciIgZD0iTTE2IDNhMTMgMTMgMCAxIDAgMCAyNiAxMyAxMyAwIDAgMCAwLTI2Wm0wIDRhMyAzIDAgMCAxIDMgM3YyLjE4YTMgMyAwIDAgMSAwIDUuNjRWMjBhMyAzIDAgMSAxLTYgMHYtMi4xOGEzIDMgMCAwIDEgMC01LjY0VjEwYTMgMyAwIDAgMSAzLTNaIi8+Cjwvc3ZnPgo=","common/manifest.json":"ewogICJpZCI6ICJfX1BMVUdJTl9JRF9fIiwKICAibmFtZSI6ICJfX1BMVUdJTl9OQU1FX18iLAogICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAibWluTXVzY2F0VmVyc2lvbiI6ICIxLjAuMCIsCiAgImF1dGhvciI6ICJfX1BMVUdJTl9BVVRIT1JfXyIsCiAgImVtYWlsIjogIl9fUExVR0lOX0VNQUlMX18iLAogICJkZXNjcmlwdGlvbiI6IHsKICAgICJrbyI6ICIiLAogICAgImVuIjogIiIKICB9LAogICJpY29ucyI6ICJhc3NldHMvaWNvbi5zdmciLAogICJ0YXJnZXRNb2RlbHMiOiAiYWxsIiwKICAidGFyZ2V0Q2F0ZWdvcnlzIjogImFsbCIsCiAgImNvbnRyaWJ1dGVzIjogWwogICAgewogICAgICAicG9pbnQiOiAidG9vbGJhciIsCiAgICAgICJpY29uIjogImFzc2V0cy9pY29uLnN2ZyIsCiAgICAgICJsYWJlbCI6IHsgImtvIjogIl9fUExVR0lOX05BTUVfXyIsICJlbiI6ICJfX1BMVUdJTl9OQU1FX18iIH0sCiAgICAgICJ1aSI6ICJjb250ZW50IiwKICAgICAgIm9wZW5zIjogInBvcG92ZXIiCiAgICB9CiAgXSwKICAicnVudGltZSI6IHsgInR5cGUiOiAiX19SVU5USU1FX1RZUEVfXyIsICJlbnRyeSI6ICJtYWluLnB5IiB9Cn0K","common/package.json":"ewogICJuYW1lIjogIl9fUExVR0lOX0lEX18iLAogICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAicHJpdmF0ZSI6IHRydWUsCiAgInR5cGUiOiAibW9kdWxlIiwKICAiZGVwZW5kZW5jaWVzIjogewogICAgIkByYWluYm93LXJvYm90aWNzL3BsdWdpbi11aSI6ICJfX1JCX1ZFUlNJT05fXyIKICB9LAogICJkZXZEZXBlbmRlbmNpZXMiOiB7CiAgICAiQHJhaW5ib3ctcm9ib3RpY3MvbXVzY2F0LXBsdWdpbi1raXQiOiAiX19SQl9WRVJTSU9OX18iLAogICAgIkByYWluYm93LXJvYm90aWNzL3ByZXZpZXctaG9zdCI6ICJfX1JCX1ZFUlNJT05fXyIsCiAgICAiQHZpdGVqcy9wbHVnaW4tcmVhY3QiOiAiXjQuMC4wIiwKICAgICJ0eXBlc2NyaXB0IjogIl41LjguMCIsCiAgICAidml0ZSI6ICJeNi4wLjAiCiAgfQp9Cg==","common/py/main.py":"IiIiCk11c2NhdCBwbHVnaW4gYmFja2VuZCDigJQgX19QTFVHSU5fTkFNRV9fCgpSdW4gd2l0aDoKICBtdXNjYXQtcGsgZGV2OmJhY2sKICBweXRob24gbWFpbi5weQoKVGhpcyB0ZW1wbGF0ZSB1c2VzIHRoZSBoaWdoLWxldmVsIFJhaW5ib3cgUHl0aG9uIFNESyBpbnN0ZWFkIG9mIHdpcmluZyB0aGUKdHJhbnNwb3J0IGxheWVyIGRpcmVjdGx5LgoiIiIKCmltcG9ydCB0aW1lCmZyb20gdHlwaW5nIGltcG9ydCBBbnkKCmZyb20gcmFpbmJvdy5yYl9zZGsgaW1wb3J0IFJCTWFuaXB1bGF0ZVNESywgUkJQbHVnaW5DYWxsCgoKUExVR0lOX05BTUUgPSAiX19QTFVHSU5fTkFNRV9fIgoKcGx1Z2luID0gUkJQbHVnaW5DYWxsKCkKCgpAcGx1Z2luLnN1YnNjcmliZSgiZXZlbnQiKQpkZWYgb25fdWlfZXZlbnQocGF5bG9hZDogZGljdFtzdHIsIEFueV0gfCBOb25lID0gTm9uZSk6CiAgICAiIiJIYW5kbGUgbWVzc2FnZXMgcHVibGlzaGVkIGZyb20gdGhlIHBsdWdpbiBVSSB3aXRoIHJiLnB1YigiZXZlbnQiLCAuLi4pLiIiIgogICAgcHJpbnQoZiJbe1BMVUdJTl9OQU1FfV0gZXZlbnQ6IiwgcGF5bG9hZCkKCgpAcGx1Z2luLnNlcnZlKCJncmlwIikKZGVmIGdyaXAocGF5bG9hZDogZGljdFtzdHIsIEFueV0gfCBOb25lID0gTm9uZSk6CiAgICAiIiJIYW5kbGUgdGhlIGRlZmF1bHQgVUkgYnV0dG9uOiByYi5hY3Rpb24oImdyaXAiLCB7IHdpZHRoIH0pLiIiIgogICAgd2lkdGggPSAocGF5bG9hZCBvciB7fSkuZ2V0KCJ3aWR0aCIsIDIwKQogICAgcHJpbnQoZiJbe1BMVUdJTl9OQU1FfV0gZ3JpcCByZXF1ZXN0ZWQ6IHdpZHRoPXt3aWR0aH0iKQoKICAgIHBsdWdpbi5wdWJsaXNoKCJzdGF0ZSIsIHsicmVhZHkiOiBUcnVlLCAibGFzdF9ncmlwX3dpZHRoIjogd2lkdGh9KQogICAgcmV0dXJuIHsib2siOiBUcnVlLCAid2lkdGgiOiB3aWR0aH0KCgpAcGx1Z2luLnNlcnZlKCJ0b29sL2VjaG8iKQpkZWYgZWNobyhwYXlsb2FkOiBkaWN0W3N0ciwgQW55XSB8IE5vbmUgPSBOb25lKToKICAgICIiIlNtYWxsIHF1ZXJ5IGV4YW1wbGUgY2FsbGFibGUgZnJvbSB0aGUgVUkgd2l0aCByYi5hY3Rpb24oInRvb2wvZWNobyIsIC4uLikuIiIiCiAgICByZXR1cm4geyJlY2hvIjogcGF5bG9hZCwgInBsdWdpbiI6IFBMVUdJTl9OQU1FfQoKCmRlZiBwaW5nX3VpX2V4YW1wbGUoKToKICAgICIiIgogICAgRXhhbXBsZTogY2FsbCBhIHF1ZXJ5YWJsZSBzZXJ2ZWQgYnkgdGhlIFVJLgoKICAgIEluIHRoZSBmcm9udGVuZCwgcmVnaXN0ZXI6CiAgICAgIHJiLnNlcnZlKCJ0b29sL3BpbmciLCBhc3luYyAocGF5bG9hZCkgPT4gKHsgcG9uZzogcGF5bG9hZCB9KSkKICAgICIiIgogICAgcmVzID0gcGx1Z2luLmNhbGwoInRvb2wvcGluZyIsIHBheWxvYWQ9eyJoZWxsbyI6ICJwbHVnaW4ifSkKICAgIHByaW50KGYiW3tQTFVHSU5fTkFNRX1dIHBpbmcgcmVzcG9uc2U6IiwgcmVzKQogICAgcmV0dXJuIHJlcwoKCmRlZiBtb3ZlX2pfZXhhbXBsZSgpOgogICAgIiIiCiAgICBFeGFtcGxlOiB1c2Ugb3RoZXIgcm9ib3QgU0RLcyBmcm9tIHRoZSBzYW1lIGJhY2tlbmQuCgogICAgVGhpcyBmdW5jdGlvbiBpcyBub3QgY2FsbGVkIGF1dG9tYXRpY2FsbHkuIEFkZCBzYWZldHkgY2hlY2tzIGFuZCBjYWxsIGl0CiAgICBmcm9tIHlvdXIgb3duIGhhbmRsZXIgd2hlbiB0aGUgcm9ib3QgaXMgcmVhZHkuCiAgICAiIiIKICAgIG1hbmlwdWxhdGUgPSBSQk1hbmlwdWxhdGVTREsoKQoKICAgIHJldHVybiBtYW5pcHVsYXRlLm1vdmUuY2FsbF9tb3ZlX2ooCiAgICAgICAgcm9ib3RfbW9kZWw9IkM1MDA5MjAiLAogICAgICAgIHRhcmdldD17CiAgICAgICAgICAgICJ0YXJfdmFsdWVzIjogWzAsIDAsIDAsIDAsIDAsIDBdLAogICAgICAgICAgICAidGFyX2ZyYW1lIjogMCwKICAgICAgICAgICAgInRhcl91bml0IjogMCwKICAgICAgICB9LAogICAgKQoKCmRlZiBtYWluKCk6CiAgICBwbHVnaW4ucHVibGlzaCgic3RhdGUiLCB7InJlYWR5IjogVHJ1ZSwgInBsdWdpbiI6IFBMVUdJTl9OQU1FfSkKICAgIHByaW50KGYiW3tQTFVHSU5fTkFNRX1dIGJhY2tlbmQgcmVhZHkiKQoKICAgIHRyeToKICAgICAgICB3aGlsZSBUcnVlOgogICAgICAgICAgICB0aW1lLnNsZWVwKDEpCiAgICBleGNlcHQgS2V5Ym9hcmRJbnRlcnJ1cHQ6CiAgICAgICAgcHJpbnQoZiJbe1BMVUdJTl9OQU1FfV0gc3RvcHBlZCIpCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIG1haW4oKQo=","common/requirements.txt":"cmFpbmJvdy1yYi1zZGs9PTAuMC45LmRldjQzCnJhaW5ib3ctcmItZmxhdC1idWZmZXJzPT0wLjAuOS5kZXY0MwpyYWluYm93LXJiLXplbm9oPT0wLjAuOS5kZXY0MwpyZXF1ZXN0cz09Mi4zNC4yCg==","common/tsconfig.json":"ewogICJjb21waWxlck9wdGlvbnMiOiB7CiAgICAidGFyZ2V0IjogIkVTTmV4dCIsCiAgICAibW9kdWxlIjogIkVTTmV4dCIsCiAgICAibW9kdWxlUmVzb2x1dGlvbiI6ICJidW5kbGVyIiwKICAgICJqc3giOiAicmVhY3QtanN4IiwKICAgICJzdHJpY3QiOiB0cnVlLAogICAgInNraXBMaWJDaGVjayI6IHRydWUsCiAgICAibm9FbWl0IjogdHJ1ZSwKICAgICJsaWIiOiBbIkRPTSIsICJET00uSXRlcmFibGUiLCAiRVNOZXh0Il0KICB9LAogICJpbmNsdWRlIjogWyJ1aSJdCn0K","common/ui/content.tsx":"aW1wb3J0IHsgdXNlU3RhdGUgfSBmcm9tICJyZWFjdCI7CmltcG9ydCB7IGNvbm5lY3QgfSBmcm9tICJAcmFpbmJvdy1yb2JvdGljcy9wbHVnaW4tdWkvY29ubmVjdCI7CmltcG9ydCB7IFNsaWRlciwgQnV0dG9uLCBUZXh0LCBTd2l0Y2ggfSBmcm9tICJAcmFpbmJvdy1yb2JvdGljcy9wbHVnaW4tdWkvcmVhY3QiOwppbXBvcnQgeyB1c2VSYiB9IGZyb20gIkByYWluYm93LXJvYm90aWNzL3BsdWdpbi11aS9zZGsiOwoKZnVuY3Rpb24gQXBwKCkgewogIGNvbnN0IHJiID0gdXNlUmIoKTsKICBjb25zdCBbd2lkdGgsIHNldFdpZHRoXSA9IHVzZVN0YXRlKDIwKTsKICBjb25zdCBbb3Blbiwgc2V0T3Blbl0gPSB1c2VTdGF0ZShmYWxzZSk7CgogIHJldHVybiAoCiAgICA8PgogICAgICA8VGV4dD5fX1BMVUdJTl9OQU1FX18gd2lkdGg6IHt3aWR0aH08L1RleHQ+CiAgICAgIDxTbGlkZXIKICAgICAgICB2YWx1ZT17d2lkdGh9CiAgICAgICAgbWluPXswfQogICAgICAgIG1heD17MTAwfQogICAgICAgIG9uQ2hhbmdlPXsoZXZlbnQ6IHsgZGV0YWlsPzogbnVtYmVyIH0pID0+IHNldFdpZHRoKGV2ZW50LmRldGFpbCA/PyAwKX0KICAgICAgLz4KICAgICAgPEJ1dHRvbiBsYWJlbD0iR3JpcCIgb25QcmVzcz17KCkgPT4gcmIuYWN0aW9uKCJncmlwIiwgeyB3aWR0aCB9KX0gLz4KICAgICAgPFN3aXRjaAogICAgICAgIGNoZWNrZWQ9e29wZW59CiAgICAgICAgb25DaGFuZ2U9eyhldmVudDogeyBkZXRhaWw/OiBib29sZWFuIH0pID0+IHsKICAgICAgICAgIGNvbnN0IG5leHQgPSBldmVudC5kZXRhaWwgPz8gZmFsc2U7CiAgICAgICAgICBzZXRPcGVuKG5leHQpOwogICAgICAgICAgcmIudG9hc3QobmV4dCA/ICJvcGVuZWQiIDogImNsb3NlZCIsICJpbmZvIik7CiAgICAgICAgfX0KICAgICAgLz4KICAgIDwvPgogICk7Cn0KCmNvbm5lY3QoQXBwKTsK","common/vite.config.ts":"aW1wb3J0IHsgcmVhZGRpclN5bmMgfSBmcm9tICJmcyI7CmltcG9ydCB7IGJhc2VuYW1lLCBleHRuYW1lLCByZXNvbHZlIH0gZnJvbSAicGF0aCI7CmltcG9ydCByZWFjdCBmcm9tICJAdml0ZWpzL3BsdWdpbi1yZWFjdCI7CmltcG9ydCB7IGRlZmluZUNvbmZpZyB9IGZyb20gInZpdGUiOwoKLy8gUGx1Z2luIFVJIGFuZCBSZWFjdCBhcmUgcHJvdmlkZWQgYnkgTXVzY2F0L3ByZXZpZXctaG9zdCB2aWEgaW1wb3J0IG1hcC4KLy8gVGhleSBtdXN0IE5PVCBiZSBidW5kbGVkIGludG8gdGhlIHBsdWdpbiBaSVAuCmNvbnN0IEhPU1RfUFJPVklERURfRVhURVJOQUxTID0gWwogIC9eQHJhaW5ib3ctcm9ib3RpY3NcL3BsdWdpbi11aShcL3wkKS8sCiAgL15yZWFjdChcL3wkKS8sCiAgL15yZWFjdC1kb20oXC98JCkvLApdOwoKLy8gQWxsIHRvcC1sZXZlbCAudHN4Ly50cyBmaWxlcyBpbiB1aS8gYmVjb21lIHNlcGFyYXRlIGVudHJ5IHBvaW50cy4KLy8gU3ViZGlyZWN0b3JpZXMgKGNvbXBvbmVudHMvLCBob29rcy8sIGV0Yy4pIGFyZSBpbXBvcnRlZCBieSBlbnRyaWVzIGFuZCBidW5kbGVkIGluLgpjb25zdCB1aUVudHJpZXMgPSBPYmplY3QuZnJvbUVudHJpZXMoCiAgcmVhZGRpclN5bmMoInVpIikKICAgIC5maWx0ZXIoKGYpID0+IC9cLih0c3g/fGpzeD8pJC8udGVzdChmKSkKICAgIC5tYXAoKGYpID0+IFtiYXNlbmFtZShmLCBleHRuYW1lKGYpKSwgcmVzb2x2ZSgidWkiLCBmKV0pLAopOwoKZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHsKICBwbHVnaW5zOiBbcmVhY3QoKV0sCiAgYnVpbGQ6IHsKICAgIG91dERpcjogImRpc3QiLAogICAgZW1wdHlPdXREaXI6IGZhbHNlLAogICAgcm9sbHVwT3B0aW9uczogewogICAgICBpbnB1dDogdWlFbnRyaWVzLAogICAgICBleHRlcm5hbDogSE9TVF9QUk9WSURFRF9FWFRFUk5BTFMsCiAgICAgIG91dHB1dDogewogICAgICAgIGZvcm1hdDogImVzIiwKICAgICAgICBlbnRyeUZpbGVOYW1lczogIltuYW1lXS5qcyIsCiAgICAgICAgY2h1bmtGaWxlTmFtZXM6ICJjaHVua3MvW25hbWVdLVtoYXNoXS5qcyIsCiAgICAgICAgYXNzZXRGaWxlTmFtZXM6ICJhc3NldHMvW25hbWVdLVtoYXNoXVtleHRuYW1lXSIsCiAgICAgIH0sCiAgICB9LAogIH0sCn0pOwo=","cpp/cpp/CMakeLists.txt":"Y21ha2VfbWluaW11bV9yZXF1aXJlZChWRVJTSU9OIDMuMTYpCnByb2plY3QoX19QTFVHSU5fU0xVR19fIENYWCkKCnNldChDTUFLRV9DWFhfU1RBTkRBUkQgMTcpCnNldChDTUFLRV9DWFhfU1RBTkRBUkRfUkVRVUlSRUQgT04pCgojIFRoZSBleGVjdXRhYmxlIG5hbWUgbXVzdCBtYXRjaCBydW50aW1lLmVudHJ5IGluIG1hbmlmZXN0Lmpzb24uCmFkZF9leGVjdXRhYmxlKF9fUExVR0lOX1NMVUdfXyBtYWluLmNwcCkKCiMgVE9ETyhjcHAtc2RrKTogbGluayB0aGUgcmFpbmJvdyBjcHAgU0RLIGR5bmFtaWNhbGx5ICh0aGUgcm9ib3QgcHJvdmlkZXMgdGhlCiMgLnNvIGF0IHJ1bnRpbWUg4oCUIGRvIE5PVCBidW5kbGUvc3RhdGljLWxpbmsgaXQpLiBPbmNlIHRoZSBTREsgc2hpcHMgYW4gYXB0CiMgcGFja2FnZSB3aXRoIENNYWtlIGNvbmZpZywgZW5hYmxlOgojICAgZmluZF9wYWNrYWdlKHJhaW5ib3dfY3BwX3NkayBSRVFVSVJFRCkKIyAgIHRhcmdldF9saW5rX2xpYnJhcmllcyhfX1BMVUdJTl9TTFVHX18gUFJJVkFURSByYWluYm93OjpjcHBfc2RrKQo=","cpp/cpp/main.cpp":"Ly8gX19QTFVHSU5fTkFNRV9fIOKAlCBDKysgcGx1Z2luIGJhY2sgZW5kLgovLwovLyBUaGUgQysrIHBsdWdpbiBTREsgaXMgbm90IGF2YWlsYWJsZSB5ZXQsIHNvIHRoaXMgaXMgYSBidWlsZC9ydW4gc2tlbGV0b24uCi8vIE9uY2UgdGhlIFNESyBsYW5kcywgY29ubmVjdCB0byB0aGUgcGx1Z2luIGdhdGV3YXkgaGVyZSAodGhlIGhvc3QgZXhwb3NlcyBpdAovLyBhdCB0aGUgUkJfUExVR0lOX0dBVEVXQVkgLyBSQl9QTFVHSU5fSUQgZW52aXJvbm1lbnQgdmFyaWFibGVzKSBhbmQgd2lyZSB1cAovLyBwdWIgLyBzdWIgLyBzZXJ2ZSwgbWlycm9yaW5nIHRoZSBQeXRob24gcmFpbmJvdy5yYl9zZGsuUkJQbHVnaW5DYWxsIEFQSS4KCiNpbmNsdWRlIDxjaHJvbm8+CiNpbmNsdWRlIDxjc3RkbGliPgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDx0aHJlYWQ+CgppbnQgbWFpbigpIHsKICBjb25zdCBjaGFyKiBwbHVnaW5faWQgPSBzdGQ6OmdldGVudigiUkJfUExVR0lOX0lEIik7CiAgc3RkOjpjb3V0IDw8ICJbX19QTFVHSU5fTkFNRV9fXSBiYWNrZW5kIHJlYWR5IgogICAgICAgICAgICA8PCAocGx1Z2luX2lkID8gc3RkOjpzdHJpbmcoIiAoaWQ9IikgKyBwbHVnaW5faWQgKyAiKSIgOiAiIikKICAgICAgICAgICAgPDwgc3RkOjplbmRsOwoKICAvLyBUT0RPOiBjb25uZWN0IHRvIHRoZSBwbHVnaW4gZ2F0ZXdheSBhbmQgcmVnaXN0ZXIgaGFuZGxlcnMgb25jZSB0aGUKICAvLyAgICAgICBDKysgU0RLIGlzIGF2YWlsYWJsZS4gRm9yIG5vdywganVzdCBrZWVwIHRoZSBwcm9jZXNzIGFsaXZlLgogIHdoaWxlICh0cnVlKSB7CiAgICBzdGQ6OnRoaXNfdGhyZWFkOjpzbGVlcF9mb3Ioc3RkOjpjaHJvbm86OnNlY29uZHMoMSkpOwogIH0KICByZXR1cm4gMDsKfQo=","ros2/ros2_ws/src/__PLUGIN_SLUG__/__PLUGIN_SLUG__/__init__.py":"","ros2/ros2_ws/src/__PLUGIN_SLUG__/__PLUGIN_SLUG__/node.py":"aW1wb3J0IHJjbHB5CmZyb20gcmNscHkubm9kZSBpbXBvcnQgTm9kZQpmcm9tIHJhaW5ib3cucmJfc2RrIGltcG9ydCBSQk1hbmlwdWxhdGVTREsgICMgUHlQSTogcmFpbmJvdy1yYi1zZGsKCgpzZGsgPSBSQk1hbmlwdWxhdGVTREsoKQoKCmNsYXNzIF9fUExVR0lOX0NMQVNTX19Ob2RlKE5vZGUpOgogICAgZGVmIF9faW5pdF9fKHNlbGYpOgogICAgICAgIHN1cGVyKCkuX19pbml0X18oIl9fUExVR0lOX1NMVUdfX19ub2RlIikKICAgICAgICBzZWxmLmdldF9sb2dnZXIoKS5pbmZvKCJfX1BMVUdJTl9OQU1FX18gbm9kZSBzdGFydGVkIikKICAgICAgICAjIHNkayBpcyBhdmFpbGFibGUgaGVyZSDigJQgdXNlIGl0IGFsb25nc2lkZSBST1MyIHRvcGljcyBhcyBuZWVkZWQKCgpkZWYgbWFpbihhcmdzPU5vbmUpOgogICAgcmNscHkuaW5pdChhcmdzPWFyZ3MpCiAgICBub2RlID0gX19QTFVHSU5fQ0xBU1NfX05vZGUoKQogICAgcmNscHkuc3Bpbihub2RlKQogICAgbm9kZS5kZXN0cm95X25vZGUoKQogICAgcmNscHkuc2h1dGRvd24oKQoKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICBtYWluKCkK","ros2/ros2_ws/src/__PLUGIN_SLUG__/package.xml":"PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxwYWNrYWdlIGZvcm1hdD0iMyI+CiAgPG5hbWU+X19QTFVHSU5fU0xVR19fPC9uYW1lPgogIDx2ZXJzaW9uPjAuMC4xPC92ZXJzaW9uPgogIDxkZXNjcmlwdGlvbj5fX1BMVUdJTl9OQU1FX18gUk9TMiBub2RlPC9kZXNjcmlwdGlvbj4KICA8bWFpbnRhaW5lciBlbWFpbD0idG9kb0BleGFtcGxlLmNvbSI+bWFpbnRhaW5lcjwvbWFpbnRhaW5lcj4KICA8bGljZW5zZT5Qcm9wcmlldGFyeTwvbGljZW5zZT4KICA8ZGVwZW5kPnJjbHB5PC9kZXBlbmQ+CiAgPGV4cG9ydD48YnVpbGRfdHlwZT5hbWVudF9weXRob248L2J1aWxkX3R5cGU+PC9leHBvcnQ+CjwvcGFja2FnZT4K","ros2/ros2_ws/src/__PLUGIN_SLUG__/resource/__PLUGIN_SLUG__":"","ros2/ros2_ws/src/__PLUGIN_SLUG__/setup.py":"ZnJvbSBzZXR1cHRvb2xzIGltcG9ydCBzZXR1cAoKcGFja2FnZV9uYW1lID0gIl9fUExVR0lOX1NMVUdfXyIKCnNldHVwKAogICAgbmFtZT1wYWNrYWdlX25hbWUsCiAgICB2ZXJzaW9uPSIwLjAuMSIsCiAgICBwYWNrYWdlcz1bcGFja2FnZV9uYW1lXSwKICAgIGRhdGFfZmlsZXM9WwogICAgICAgICgic2hhcmUvYW1lbnRfaW5kZXgvcmVzb3VyY2VfaW5kZXgvcGFja2FnZXMiLCBbInJlc291cmNlLyIgKyBwYWNrYWdlX25hbWVdKSwKICAgICAgICAoInNoYXJlLyIgKyBwYWNrYWdlX25hbWUsIFsicGFja2FnZS54bWwiXSksCiAgICBdLAogICAgaW5zdGFsbF9yZXF1aXJlcz1bInNldHVwdG9vbHMiXSwKICAgIHppcF9zYWZlPVRydWUsCiAgICBlbnRyeV9wb2ludHM9ewogICAgICAgICJjb25zb2xlX3NjcmlwdHMiOiBbIl9fUExVR0lOX1NMVUdfX19ub2RlID0gX19QTFVHSU5fU0xVR19fLm5vZGU6bWFpbiJdLAogICAgfSwKKQo=","ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/CMakeLists.txt":"Y21ha2VfbWluaW11bV9yZXF1aXJlZChWRVJTSU9OIDMuMTYpCnByb2plY3QoX19QTFVHSU5fU0xVR19fKQoKaWYoTk9UIENNQUtFX0NYWF9TVEFOREFSRCkKICBzZXQoQ01BS0VfQ1hYX1NUQU5EQVJEIDE3KQplbmRpZigpCgpmaW5kX3BhY2thZ2UoYW1lbnRfY21ha2UgUkVRVUlSRUQpCmZpbmRfcGFja2FnZShyY2xjcHAgUkVRVUlSRUQpCgphZGRfZXhlY3V0YWJsZShfX1BMVUdJTl9TTFVHX19fbm9kZSBzcmMvbm9kZS5jcHApCmFtZW50X3RhcmdldF9kZXBlbmRlbmNpZXMoX19QTFVHSU5fU0xVR19fX25vZGUgcmNsY3BwKQoKaW5zdGFsbChUQVJHRVRTIF9fUExVR0lOX1NMVUdfX19ub2RlCiAgREVTVElOQVRJT04gbGliLyR7UFJPSkVDVF9OQU1FfSkKCmFtZW50X3BhY2thZ2UoKQo=","ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/package.xml":"PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxwYWNrYWdlIGZvcm1hdD0iMyI+CiAgPG5hbWU+X19QTFVHSU5fU0xVR19fPC9uYW1lPgogIDx2ZXJzaW9uPjAuMC4xPC92ZXJzaW9uPgogIDxkZXNjcmlwdGlvbj5fX1BMVUdJTl9OQU1FX18gUk9TMiBub2RlIChyY2xjcHApPC9kZXNjcmlwdGlvbj4KICA8bWFpbnRhaW5lciBlbWFpbD0idG9kb0BleGFtcGxlLmNvbSI+bWFpbnRhaW5lcjwvbWFpbnRhaW5lcj4KICA8bGljZW5zZT5Qcm9wcmlldGFyeTwvbGljZW5zZT4KICA8YnVpbGR0b29sX2RlcGVuZD5hbWVudF9jbWFrZTwvYnVpbGR0b29sX2RlcGVuZD4KICA8ZGVwZW5kPnJjbGNwcDwvZGVwZW5kPgogIDxleHBvcnQ+PGJ1aWxkX3R5cGU+YW1lbnRfY21ha2U8L2J1aWxkX3R5cGU+PC9leHBvcnQ+CjwvcGFja2FnZT4K","ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/src/node.cpp":"Ly8gX19QTFVHSU5fTkFNRV9fIOKAlCBST1MyIG5vZGUgKHJjbGNwcCkuCi8vCi8vIFRoZSBub2RlIGlzIGxhdW5jaGVkIHdpdGggYC0tcm9zLWFyZ3MgLXIgX19uczo9L3tzbHVnfWAgYXV0b21hdGljYWxseSBieQovLyBkZXY6YmFjay4gUk9TMiB0b3BpY3MgYXJlIGJyaWRnZWQgdG8gdGhlIHBsdWdpbiBjb21tdW5pY2F0aW9uIGxheWVyLCBzbyBhCi8vIHBsYWluIHJjbGNwcCBub2RlIGlzIGFsbCB5b3UgbmVlZCDigJQgcmVsYXRpdmUgdG9waWMgbmFtZXMgZ2V0IHRoZSBuYW1lc3BhY2UKLy8gcHJlZml4IGFwcGxpZWQgYXV0b21hdGljYWxseS4KI2luY2x1ZGUgInJjbGNwcC9yY2xjcHAuaHBwIgoKY2xhc3MgX19QTFVHSU5fQ0xBU1NfX05vZGUgOiBwdWJsaWMgcmNsY3BwOjpOb2RlIHsKcHVibGljOgogIF9fUExVR0lOX0NMQVNTX19Ob2RlKCkgOiBOb2RlKCJfX1BMVUdJTl9TTFVHX19fbm9kZSIpIHsKICAgIFJDTENQUF9JTkZPKHRoaXMtPmdldF9sb2dnZXIoKSwgIl9fUExVR0lOX05BTUVfXyBub2RlIHN0YXJ0ZWQiKTsKICAgIC8vIGNyZWF0ZSBwdWJsaXNoZXJzIC8gc3Vic2NyaWJlcnMgLyBzZXJ2aWNlcyBoZXJlCiAgfQp9OwoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIqKiBhcmd2KSB7CiAgcmNsY3BwOjppbml0KGFyZ2MsIGFyZ3YpOwogIHJjbGNwcDo6c3BpbihzdGQ6Om1ha2Vfc2hhcmVkPF9fUExVR0lOX0NMQVNTX19Ob2RlPigpKTsKICByY2xjcHA6OnNodXRkb3duKCk7CiAgcmV0dXJuIDA7Cn0K","docker/Dockerfile.bridge":"IyBTb2NrZXQuSU8gYnJpZGdlIGNvbnRhaW5lciDigJQgdGhlIGZyb250ZW5kIChwcmV2aWV3LWhvc3QpIGFuZCB0aGUgYmFja2VuZAojIGNvbnRhaW5lciByZW5kZXp2b3VzIGhlcmUgZHVyaW5nIGBtdXNjYXQtcGsgZGV2YC4KIyAgIC0gZnJvbnRlbmQgKGhvc3QpICDihpIgcHVibGlzaGVkIHBvcnQgbG9jYWxob3N0OjEwMDAwCiMgICAtIGJhY2tlbmQgY29udGFpbmVyIOKGkiBzaGFyZXMgdGhpcyBjb250YWluZXIncyBuZXRucyAoLS1uZXR3b3JrIGNvbnRhaW5lcjopLAojICAgICAgICAgICAgICAgICAgICAgICAgIHNvIGl0IHJlYWNoZXMgdGhlIGJyaWRnZSBhdCBsb2NhbGhvc3Q6MTAwMDAgdG9vCiMgQnVpbGQgY29udGV4dCBpcyB0aGUgYGNsaS9gIGRpciBzbyBpdCBjYW4gY29weSBzcmMvc29ja2V0QnJpZGdlLm1qcy4KRlJPTSBub2RlOjIwLXNsaW0KTEFCRUwgY29tLnJhaW5ib3ctcm9ib3RpY3MubXVzY2F0LXBrPSJ0cnVlIgoKV09SS0RJUiAvYnJpZGdlCkNPUFkgZG9ja2VyL2JyaWRnZS1wYWNrYWdlLmpzb24gcGFja2FnZS5qc29uClJVTiBucG0gaW5zdGFsbCAtLW9taXQ9ZGV2IC0tbm8tYXVkaXQgLS1uby1mdW5kCgpDT1BZIHNyYy9zb2NrZXRCcmlkZ2UubWpzIC4vc29ja2V0QnJpZGdlLm1qcwoKRVhQT1NFIDEwMDAwCkNNRCBbIm5vZGUiLCAic29ja2V0QnJpZGdlLm1qcyJdCg==","docker/Dockerfile.cpp":"IyBEZXYvYnVpbGQgY29udGFpbmVyIGZvciB0aGUgcHVyZSBDKysgcGx1Z2luIGJhY2sgZW5kLgojIE1hdGNoZXMgdGhlIE11c2NhdCByb2JvdCBiYWNrZW5kIE9TIChVYnVudHUgMjQuMDQpIHNvIHRoZSBjb21waWxlZCBiaW5hcnkKIyBpcyBBQkktY29tcGF0aWJsZSB3aXRoIHRoZSByb2JvdC4gVXNlZCBieSBgbXVzY2F0LXBrIGRldjpiYWNrYCBhbmQgYGJ1aWxkYAojIOKAlCBOT1Qgc2hpcHBlZCBpbiB0aGUgcGx1Z2luIFpJUC4KRlJPTSB1YnVudHU6MjQuMDQKTEFCRUwgY29tLnJhaW5ib3ctcm9ib3RpY3MubXVzY2F0LXBrPSJ0cnVlIgoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSAtLW5vLWluc3RhbGwtcmVjb21tZW5kcyBcCiAgICAgIGJ1aWxkLWVzc2VudGlhbCBcCiAgICAgIGNtYWtlIFwKICAgICYmIHJtIC1yZiAvdmFyL2xpYi9hcHQvbGlzdHMvKgoKIyBUT0RPKGNwcC1zZGspOiBpbnN0YWxsIHRoZSByYWluYm93IGNwcCBTREsgKGRldiBwYWNrYWdlKSBoZXJlLCBwaW5uZWQgdG8gdGhlCiMgcm9ib3QncyB2ZXJzaW9uLCBzbyBwbHVnaW5zIGJ1aWxkL2xpbmsgYWdhaW5zdCB0aGUgc2FtZSBTREsgYXMgcHJvZHVjdGlvbi4KIyBQbGFuOiBhcHQgcGFja2FnZSArIGR5bmFtaWMgbGluayAodGhlIHJvYm90IHByb3ZpZGVzIHRoZSAuc28gYXQgcnVudGltZTsKIyB3ZSBkbyBOT1QgYnVuZGxlIGl0IGludG8gdGhlIHBsdWdpbiBiaW5hcnkpLiBlLmcuOgojICAgUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSByYWluYm93LWNwcC1zZGstZGV2PTxyb2JvdC12ZXJzaW9uPiBcCiMgICAgICAgJiYgcm0gLXJmIC92YXIvbGliL2FwdC9saXN0cy8qCgpXT1JLRElSIC9wbHVnaW4KCkNNRCBbImJhc2giXQo=","docker/Dockerfile.dev":"IyBEZXYtb25seSBjb250YWluZXIgZm9yIHRoZSBST1MyIHBsdWdpbiBiYWNrIGVuZC4KIyBNYXRjaGVzIHRoZSBNdXNjYXQgcm9ib3QgYmFja2VuZDogUk9TMiBKYXp6eSArIFB5dGhvbiAzLjEyIChVYnVudHUgMjQuMDQpLgojIFVzZWQgYnkgYG11c2NhdC1wayBkZXY6YmFja2Ag4oCUIE5PVCBzaGlwcGVkIGluIHRoZSBwbHVnaW4gWklQLgpGUk9NIHJvczpqYXp6eS1yb3MtYmFzZQpMQUJFTCBjb20ucmFpbmJvdy1yb2JvdGljcy5tdXNjYXQtcGs9InRydWUiCgpSVU4gYXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCBpbnN0YWxsIC15IC0tbm8taW5zdGFsbC1yZWNvbW1lbmRzIFwKICAgICAgcHl0aG9uMy1waXAgXAogICAgICBweXRob24zLWNvbGNvbi1jb21tb24tZXh0ZW5zaW9ucyBcCiAgICAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCldPUktESVIgL3BsdWdpbgoKQ01EIFsiYmFzaCJdCg==","docker/Dockerfile.python":"IyBEZXYvYnVpbGQgY29udGFpbmVyIGZvciB0aGUgUHl0aG9uIHBsdWdpbiBiYWNrIGVuZC4KIyBNYXRjaGVzIHRoZSBNdXNjYXQgcm9ib3QgYmFja2VuZDogVWJ1bnR1IDI0LjA0ICsgUHl0aG9uIDMuMTIuCiMgVXNlZCBieSBgbXVzY2F0LXBrIGRldjpiYWNrYCAoaG90LXJlbG9hZCkgYW5kIGBtdXNjYXQtcGsgYnVpbGRgIChsb2NrICsgd2hlZWwgdmVuZG9yKS4KIyBOT1Qgc2hpcHBlZCBpbiB0aGUgcGx1Z2luIFpJUCDigJQgdGhlIHJvYm90IGluc3RhbGxzIGRlcHMgZnJvbSBkaXN0L3doZWVscy8gb2ZmbGluZS4KRlJPTSB1YnVudHU6MjQuMDQKTEFCRUwgY29tLnJhaW5ib3ctcm9ib3RpY3MubXVzY2F0LXBrPSJ0cnVlIgoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSAtLW5vLWluc3RhbGwtcmVjb21tZW5kcyBcCiAgICAgIHB5dGhvbjMgXAogICAgICBweXRob24zLXBpcCBcCiAgICAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyogXAogICAgJiYgcGlwMyBpbnN0YWxsIHV2PT0wLjguMTggLS1icmVhay1zeXN0ZW0tcGFja2FnZXMKCiMgVE9ETyhjcHAtc2RrKTogdGhlIFB5dGhvbiBTREsgaXMgYSBweWJpbmQgd3JhcHBlciBvdmVyIHRoZSBjcHAgU0RLLCBzbyB0aGUKIyBjcHAgU0RLIHNoYXJlZCBsaWIgbXVzdCBiZSBwcmVzZW50IGZvciB0aGUgcHl0aG9uIG1vZHVsZSB0byBsb2FkLiBJbnN0YWxsIHRoZQojIHJhaW5ib3cgY3BwIFNESyAoYXB0LCBwaW5uZWQgdG8gdGhlIHJvYm90J3MgdmVyc2lvbikgaGVyZSBvbmNlIGl0IGV4aXN0cy4KCldPUktESVIgL3BsdWdpbgoKQ01EIFsiYmFzaCJdCg==","docker/bridge-package.json":"ewogICJuYW1lIjogIm11c2NhdC1way1icmlkZ2UiLAogICJwcml2YXRlIjogdHJ1ZSwKICAidHlwZSI6ICJtb2R1bGUiLAogICJkZXBlbmRlbmNpZXMiOiB7CiAgICAic29ja2V0LmlvIjogIl40LjguMSIKICB9Cn0K"};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rainbow-robotics/muscat-plugin-kit",
|
|
3
|
-
"version": "0.1.2-dev.
|
|
3
|
+
"version": "0.1.2-dev.42",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20"
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@types/react-dom": "^19.0.4"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@rainbow-robotics/preview-host": "0.1.2-dev.
|
|
34
|
+
"@rainbow-robotics/preview-host": "0.1.2-dev.42",
|
|
35
35
|
"socket.io": "^4.8.1"
|
|
36
36
|
},
|
|
37
37
|
"optionalDependencies": {
|