@leadbay/mcp 0.23.5 → 0.23.6
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/CHANGELOG.md +6 -0
- package/dist/bin.js +159 -19
- package/dist/http-server.js +157 -19
- package/dist/installer-electron.js +226 -71
- package/dist/installer-gui.js +225 -70
- package/package.json +1 -1
|
@@ -1074,6 +1074,16 @@ import { randomUUID } from "crypto";
|
|
|
1074
1074
|
import { resolve as resolvePath } from "path";
|
|
1075
1075
|
import { fileURLToPath } from "url";
|
|
1076
1076
|
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
1077
|
+
async function detectLocale() {
|
|
1078
|
+
try {
|
|
1079
|
+
return await inferRegionViaStargate({ staging: false }) === "fr" ? "fr" : "en";
|
|
1080
|
+
} catch {
|
|
1081
|
+
return "en";
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
function parseLocale(raw) {
|
|
1085
|
+
return raw === "fr" ? "fr" : "en";
|
|
1086
|
+
}
|
|
1077
1087
|
async function isLeadbayConfigured(client) {
|
|
1078
1088
|
if (client.id === "claude-code") {
|
|
1079
1089
|
return await isLeadbayConfiguredInClaudeCode();
|
|
@@ -1204,23 +1214,25 @@ async function install(body) {
|
|
|
1204
1214
|
cleanupSessions();
|
|
1205
1215
|
const session = body.sessionId ? sessions.get(body.sessionId) : void 0;
|
|
1206
1216
|
const clientIds = body.clientIds ?? [];
|
|
1207
|
-
if (!session) return { ok: false, output:
|
|
1208
|
-
if (!clientIds.length) return { ok: false, output:
|
|
1217
|
+
if (!session) return { ok: false, output: MESSAGES.en.server.loginExpired };
|
|
1218
|
+
if (!clientIds.length) return { ok: false, output: MESSAGES.en.server.selectAtLeastOne };
|
|
1219
|
+
const locale = session.region === "fr" ? "fr" : "en";
|
|
1220
|
+
const s = MESSAGES[locale].server;
|
|
1209
1221
|
const detected = await detectClients();
|
|
1210
1222
|
const selected = detected.filter((client) => clientIds.includes(client.id));
|
|
1211
|
-
if (!selected.length) return { ok: false, output:
|
|
1223
|
+
if (!selected.length) return { ok: false, output: s.noSelectedDetected };
|
|
1212
1224
|
const includeWrite = body.includeWrite !== false;
|
|
1213
1225
|
const telemetryEnabled = body.telemetryEnabled !== false;
|
|
1214
1226
|
const results = [];
|
|
1215
1227
|
for (const client of selected) results.push(await installInto(client, session, includeWrite, telemetryEnabled));
|
|
1216
1228
|
const output = [
|
|
1217
|
-
|
|
1218
|
-
|
|
1229
|
+
s.loggedInBackend(session.region),
|
|
1230
|
+
s.settingsLine(includeWrite, telemetryEnabled),
|
|
1219
1231
|
"",
|
|
1220
|
-
|
|
1232
|
+
s.installSummaryHeader,
|
|
1221
1233
|
...results.map((result) => `${result.ok ? "OK" : "ERROR"} ${result.label}: ${result.message}`),
|
|
1222
1234
|
"",
|
|
1223
|
-
|
|
1235
|
+
s.restartClients
|
|
1224
1236
|
].join("\n");
|
|
1225
1237
|
return { ok: results.some((result) => result.ok), output: sanitizeOutput(output), results };
|
|
1226
1238
|
}
|
|
@@ -1235,6 +1247,8 @@ async function streamInstall(url, res, onDone) {
|
|
|
1235
1247
|
const clientIds = (url.searchParams.get("clients") ?? "").split(",").filter(Boolean);
|
|
1236
1248
|
const includeWrite = url.searchParams.get("write") !== "0";
|
|
1237
1249
|
const telemetryEnabled = url.searchParams.get("telemetry") !== "0";
|
|
1250
|
+
const locale = parseLocale(url.searchParams.get("locale"));
|
|
1251
|
+
const s = MESSAGES[locale].server;
|
|
1238
1252
|
const emit = (level, message) => sendSse(res, { level, message: sanitizeOutput(message) });
|
|
1239
1253
|
const abort = (msg) => {
|
|
1240
1254
|
emit("done", msg);
|
|
@@ -1246,29 +1260,29 @@ async function streamInstall(url, res, onDone) {
|
|
|
1246
1260
|
onDone?.();
|
|
1247
1261
|
};
|
|
1248
1262
|
if (!session) {
|
|
1249
|
-
emit("error",
|
|
1250
|
-
abort(
|
|
1263
|
+
emit("error", s.loginExpired);
|
|
1264
|
+
abort(s.installStopped);
|
|
1251
1265
|
return;
|
|
1252
1266
|
}
|
|
1253
1267
|
if (!clientIds.length) {
|
|
1254
|
-
emit("error",
|
|
1255
|
-
abort(
|
|
1268
|
+
emit("error", s.selectAtLeastOne);
|
|
1269
|
+
abort(s.installStopped);
|
|
1256
1270
|
return;
|
|
1257
1271
|
}
|
|
1258
|
-
emit("info",
|
|
1259
|
-
emit("info",
|
|
1260
|
-
emit("info",
|
|
1272
|
+
emit("info", s.connectedTo(session.accountLabel));
|
|
1273
|
+
emit("info", s.toolFlags(includeWrite, telemetryEnabled));
|
|
1274
|
+
emit("info", s.refreshingDetection);
|
|
1261
1275
|
const detected = await detectClients();
|
|
1262
1276
|
const selected = detected.filter((client) => clientIds.includes(client.id));
|
|
1263
1277
|
const selectedHasOnlyManualSetup = selected.length > 0 && selected.every(isManualSetupClient);
|
|
1264
1278
|
if (!selected.length) {
|
|
1265
|
-
emit("error",
|
|
1266
|
-
abort(
|
|
1279
|
+
emit("error", s.noSelectedDetected);
|
|
1280
|
+
abort(s.installStopped);
|
|
1267
1281
|
return;
|
|
1268
1282
|
}
|
|
1269
1283
|
let okCount = 0;
|
|
1270
1284
|
for (const client of selected) {
|
|
1271
|
-
emit("active", isManualSetupClient(client) ?
|
|
1285
|
+
emit("active", isManualSetupClient(client) ? s.preparingManual(client.label) : s.installing(client.label));
|
|
1272
1286
|
const result = await installInto(client, session, includeWrite, telemetryEnabled);
|
|
1273
1287
|
if (result.ok) {
|
|
1274
1288
|
okCount += 1;
|
|
@@ -1277,8 +1291,8 @@ async function streamInstall(url, res, onDone) {
|
|
|
1277
1291
|
emit("error", `${result.label}: ${result.message}`);
|
|
1278
1292
|
}
|
|
1279
1293
|
}
|
|
1280
|
-
const summary = selectedHasOnlyManualSetup ?
|
|
1281
|
-
const closing = selectedHasOnlyManualSetup ?
|
|
1294
|
+
const summary = selectedHasOnlyManualSetup ? s.manualReady : s.installedSummary(okCount, selected.length);
|
|
1295
|
+
const closing = selectedHasOnlyManualSetup ? s.followManual : s.restartClients;
|
|
1282
1296
|
emit(okCount > 0 ? "success" : "error", summary);
|
|
1283
1297
|
if (okCount > 0) {
|
|
1284
1298
|
finish(closing);
|
|
@@ -1293,6 +1307,8 @@ async function streamUninstall(url, res, onDone) {
|
|
|
1293
1307
|
connection: "keep-alive"
|
|
1294
1308
|
});
|
|
1295
1309
|
const clientIds = (url.searchParams.get("clients") ?? "").split(",").filter(Boolean);
|
|
1310
|
+
const locale = parseLocale(url.searchParams.get("locale"));
|
|
1311
|
+
const s = MESSAGES[locale].server;
|
|
1296
1312
|
const emit = (level, message) => sendSse(res, { level, message });
|
|
1297
1313
|
const abort = (msg) => {
|
|
1298
1314
|
emit("done", msg);
|
|
@@ -1304,20 +1320,20 @@ async function streamUninstall(url, res, onDone) {
|
|
|
1304
1320
|
onDone?.();
|
|
1305
1321
|
};
|
|
1306
1322
|
if (!clientIds.length) {
|
|
1307
|
-
emit("error",
|
|
1308
|
-
abort(
|
|
1323
|
+
emit("error", s.selectAtLeastOne);
|
|
1324
|
+
abort(s.uninstallStopped);
|
|
1309
1325
|
return;
|
|
1310
1326
|
}
|
|
1311
1327
|
const detected = await detectClients();
|
|
1312
1328
|
const selected = detected.filter((c) => clientIds.includes(c.id));
|
|
1313
1329
|
if (!selected.length) {
|
|
1314
|
-
emit("error",
|
|
1315
|
-
abort(
|
|
1330
|
+
emit("error", s.noSelectedDetected);
|
|
1331
|
+
abort(s.uninstallStopped);
|
|
1316
1332
|
return;
|
|
1317
1333
|
}
|
|
1318
1334
|
let okCount = 0;
|
|
1319
1335
|
for (const client of selected) {
|
|
1320
|
-
emit("active",
|
|
1336
|
+
emit("active", s.removing(client.label));
|
|
1321
1337
|
let res2;
|
|
1322
1338
|
if (client.id === "claude-code") {
|
|
1323
1339
|
res2 = await uninstallFromClaudeCode();
|
|
@@ -1335,16 +1351,17 @@ async function streamUninstall(url, res, onDone) {
|
|
|
1335
1351
|
emit("error", `${client.label}: ${res2.message}`);
|
|
1336
1352
|
}
|
|
1337
1353
|
}
|
|
1338
|
-
emit(okCount > 0 ? "success" : "error",
|
|
1339
|
-
finish(
|
|
1354
|
+
emit(okCount > 0 ? "success" : "error", s.removedSummary(okCount, selected.length));
|
|
1355
|
+
finish(s.completeRemoval);
|
|
1340
1356
|
}
|
|
1341
|
-
function pageUninstallHtml() {
|
|
1357
|
+
function pageUninstallHtml(locale = "en") {
|
|
1358
|
+
const ui = MESSAGES[locale].uninstaller;
|
|
1342
1359
|
return `<!doctype html>
|
|
1343
|
-
<html lang="
|
|
1360
|
+
<html lang="${locale}">
|
|
1344
1361
|
<head>
|
|
1345
1362
|
<meta charset="utf-8" />
|
|
1346
1363
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
1347
|
-
<title
|
|
1364
|
+
<title>${ui.docTitle}</title>
|
|
1348
1365
|
<style>
|
|
1349
1366
|
:root { color-scheme: light; --bg:#fff; --card:#fff; --strong:#1d2228; --muted:#9aa0ab; --line:#e7e9ee; --accent:#0d0f0e; --danger:#d14343; --ok:#16a34a; --warn:#b06a00; }
|
|
1350
1367
|
* { box-sizing:border-box; }
|
|
@@ -1396,8 +1413,8 @@ function pageUninstallHtml() {
|
|
|
1396
1413
|
<main>
|
|
1397
1414
|
<div class="steps"><div class="dot active" id="dot-1"></div><div class="dot" id="dot-2"></div></div>
|
|
1398
1415
|
<div class="card">
|
|
1399
|
-
<h1 id="title"
|
|
1400
|
-
<p class="sub" id="sub"
|
|
1416
|
+
<h1 id="title">${ui.steps[1].title}</h1>
|
|
1417
|
+
<p class="sub" id="sub">${ui.steps[1].sub}</p>
|
|
1401
1418
|
|
|
1402
1419
|
<section id="step-1">
|
|
1403
1420
|
<div class="spinner" id="spinner"></div>
|
|
@@ -1415,19 +1432,18 @@ function pageUninstallHtml() {
|
|
|
1415
1432
|
</section>
|
|
1416
1433
|
|
|
1417
1434
|
<div class="actions">
|
|
1418
|
-
<button id="back" class="ghost hidden"
|
|
1419
|
-
<button id="refresh"
|
|
1420
|
-
<button class="danger" id="next"
|
|
1435
|
+
<button id="back" class="ghost hidden">${ui.btnBack}</button>
|
|
1436
|
+
<button id="refresh">${ui.btnRefresh}</button>
|
|
1437
|
+
<button class="danger" id="next">${ui.btnRemove}</button>
|
|
1421
1438
|
</div>
|
|
1422
1439
|
</div>
|
|
1423
1440
|
<p class="version">v${VERSION}</p>
|
|
1424
1441
|
</main>
|
|
1425
1442
|
<script>
|
|
1443
|
+
const LOCALE = "${locale}";
|
|
1444
|
+
const T = ${JSON.stringify(ui)};
|
|
1426
1445
|
const $ = (id) => document.getElementById(id);
|
|
1427
|
-
const STEPS =
|
|
1428
|
-
1: { title: "Remove Leadbay MCP", sub: "Select the agents to remove Leadbay MCP from." },
|
|
1429
|
-
2: { title: "Removing", sub: "Keep this window open until it's done." },
|
|
1430
|
-
};
|
|
1446
|
+
const STEPS = T.steps;
|
|
1431
1447
|
const CHECK = "M20 33 l8 8 l16 -18";
|
|
1432
1448
|
const CROSS = "M22 22 l20 20 M42 22 l-20 20";
|
|
1433
1449
|
let step = 1;
|
|
@@ -1439,18 +1455,18 @@ function pageUninstallHtml() {
|
|
|
1439
1455
|
function showResult(ok, msg) {
|
|
1440
1456
|
$("sub").classList.add("hidden");
|
|
1441
1457
|
$("result-msg").textContent = msg;
|
|
1442
|
-
$("result-note").textContent = ok ?
|
|
1458
|
+
$("result-note").textContent = ok ? T.closeWindow : "";
|
|
1443
1459
|
$("ring-mark").setAttribute("d", ok ? CHECK : CROSS);
|
|
1444
1460
|
const ring = $("ring"); ring.classList.remove("ok", "err"); void ring.getBoundingClientRect();
|
|
1445
1461
|
ring.classList.add(ok ? "ok" : "err");
|
|
1446
1462
|
$("result").classList.toggle("err", !ok);
|
|
1447
1463
|
$("result").classList.remove("hidden");
|
|
1448
|
-
$("title").textContent = ok ?
|
|
1464
|
+
$("title").textContent = ok ? T.allSet : T.somethingWrong;
|
|
1449
1465
|
["next", "back", "refresh"].forEach((id) => $(id).classList.add("hidden"));
|
|
1450
1466
|
}
|
|
1451
|
-
function renderAgents() { $("spinner").classList.add("hidden"); const root = $("agents"); if (!clients.length) { root.innerHTML = '<div class="sub">
|
|
1452
|
-
async function refresh() { $("spinner").classList.remove("hidden"); $("agents").innerHTML = ""; const res = await fetch("/api/status"); const data = await res.json(); clients = (data.clients || []).filter((c) => c.configured); renderAgents(); if (!clients.length) say(
|
|
1453
|
-
async function doUninstall() { const selected = [...document.querySelectorAll("[data-client]:checked")].map((el) => el.dataset.client); if (!selected.length) return say(
|
|
1467
|
+
function renderAgents() { $("spinner").classList.add("hidden"); const root = $("agents"); if (!clients.length) { root.innerHTML = '<div class="sub">' + esc(T.noInstallDetected) + '</div>'; return; } root.innerHTML = clients.map((c) => '<label class="agent"><input type="checkbox" data-client="' + esc(c.id) + '" checked /><span><strong>' + esc(c.label) + '</strong><span class="detail">' + esc(c.detail) + '</span></span></label>').join(""); }
|
|
1468
|
+
async function refresh() { $("spinner").classList.remove("hidden"); $("agents").innerHTML = ""; const res = await fetch("/api/status"); const data = await res.json(); clients = (data.clients || []).filter((c) => c.configured); renderAgents(); if (!clients.length) say(T.noInstallDetected); }
|
|
1469
|
+
async function doUninstall() { const selected = [...document.querySelectorAll("[data-client]:checked")].map((el) => el.dataset.client); if (!selected.length) return say(T.selectAtLeastOne, true); setStep(2); let okCount = 0, lastError = ""; const params = new URLSearchParams({ clients: selected.join(","), locale: LOCALE }); const events = new EventSource("/api/uninstall-stream?" + params.toString()); events.onmessage = (event) => { const data = JSON.parse(event.data); if (data.level === "error") lastError = data.message; if (data.level === "success") okCount += 1; if (data.level === "done") { events.close(); const ok = okCount > 0 && !lastError; showResult(ok, ok ? T.successRemoved : (lastError || T.noneRemoved)); } else { say(data.message, data.level === "error"); } }; events.onerror = () => { events.close(); showResult(false, T.streamDisconnected); }; }
|
|
1454
1470
|
$("back").addEventListener("click", () => setStep(1));
|
|
1455
1471
|
$("refresh").addEventListener("click", refresh);
|
|
1456
1472
|
$("next").addEventListener("click", doUninstall);
|
|
@@ -1459,13 +1475,14 @@ function pageUninstallHtml() {
|
|
|
1459
1475
|
</body>
|
|
1460
1476
|
</html>`;
|
|
1461
1477
|
}
|
|
1462
|
-
function pageHtml() {
|
|
1478
|
+
function pageHtml(locale = "en") {
|
|
1479
|
+
const ui = MESSAGES[locale].installer;
|
|
1463
1480
|
return `<!doctype html>
|
|
1464
|
-
<html lang="
|
|
1481
|
+
<html lang="${locale}">
|
|
1465
1482
|
<head>
|
|
1466
1483
|
<meta charset="utf-8" />
|
|
1467
1484
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
1468
|
-
<title
|
|
1485
|
+
<title>${ui.docTitle}</title>
|
|
1469
1486
|
<style>
|
|
1470
1487
|
:root { color-scheme: light; --bg:#fff; --card:#fff; --strong:#1d2228; --muted:#9aa0ab; --line:#e7e9ee; --accent:#0d0f0e; --cancel-line:#f0c8b8; --danger:#d14343; --ok:#16a34a; --warn:#b06a00; }
|
|
1471
1488
|
* { box-sizing:border-box; }
|
|
@@ -1521,8 +1538,8 @@ function pageHtml() {
|
|
|
1521
1538
|
<main>
|
|
1522
1539
|
<div class="steps"><div class="dot active" id="dot-1"></div><div class="dot" id="dot-2"></div><div class="dot" id="dot-3"></div></div>
|
|
1523
1540
|
<div class="card">
|
|
1524
|
-
<h1 id="title"
|
|
1525
|
-
<p class="sub" id="sub"
|
|
1541
|
+
<h1 id="title">${ui.steps[1].title}</h1>
|
|
1542
|
+
<p class="sub" id="sub">${ui.steps[1].sub}</p>
|
|
1526
1543
|
|
|
1527
1544
|
<section id="step-2" class="hidden">
|
|
1528
1545
|
<div class="spinner" id="spinner"></div>
|
|
@@ -1540,20 +1557,18 @@ function pageHtml() {
|
|
|
1540
1557
|
</section>
|
|
1541
1558
|
|
|
1542
1559
|
<div class="actions">
|
|
1543
|
-
<button id="back" class="cancel hidden"
|
|
1544
|
-
<button id="refresh" class="ghost hidden"
|
|
1545
|
-
<button class="primary" id="next"
|
|
1560
|
+
<button id="back" class="cancel hidden">${ui.btnBack}</button>
|
|
1561
|
+
<button id="refresh" class="ghost hidden">${ui.btnRefresh}</button>
|
|
1562
|
+
<button class="primary" id="next">${ui.btnSignIn}</button>
|
|
1546
1563
|
</div>
|
|
1547
1564
|
</div>
|
|
1548
1565
|
<p class="version">v${VERSION}</p>
|
|
1549
1566
|
</main>
|
|
1550
1567
|
<script>
|
|
1568
|
+
const LOCALE = "${locale}";
|
|
1569
|
+
const T = ${JSON.stringify(ui)};
|
|
1551
1570
|
const $ = (id) => document.getElementById(id);
|
|
1552
|
-
const STEPS =
|
|
1553
|
-
1: { title: "Connect Leadbay", sub: "Sign in to install Leadbay across your AI agents." },
|
|
1554
|
-
2: { title: "Choose your agents", sub: "Pick where to install Leadbay." },
|
|
1555
|
-
3: { title: "Installing", sub: "Keep this window open until it's done." },
|
|
1556
|
-
};
|
|
1571
|
+
const STEPS = T.steps;
|
|
1557
1572
|
const CHECK = "M20 33 l8 8 l16 -18";
|
|
1558
1573
|
const CROSS = "M22 22 l20 20 M42 22 l-20 20";
|
|
1559
1574
|
let step = 1;
|
|
@@ -1571,30 +1586,30 @@ function pageHtml() {
|
|
|
1571
1586
|
$("back").classList.toggle("hidden", step !== 2);
|
|
1572
1587
|
$("refresh").classList.toggle("hidden", step !== 2);
|
|
1573
1588
|
$("next").classList.toggle("hidden", step === 3);
|
|
1574
|
-
$("next").textContent = step === 2 ?
|
|
1589
|
+
$("next").textContent = step === 2 ? T.btnInstall : T.btnSignIn;
|
|
1575
1590
|
}
|
|
1576
1591
|
// Final completion state: animated green check / red cross + message.
|
|
1577
1592
|
function showResult(ok, msg) {
|
|
1578
1593
|
$("sub").classList.add("hidden");
|
|
1579
1594
|
$("result-msg").textContent = msg;
|
|
1580
|
-
$("result-note").textContent = ok ?
|
|
1595
|
+
$("result-note").textContent = ok ? T.closeWindow : "";
|
|
1581
1596
|
$("ring-mark").setAttribute("d", ok ? CHECK : CROSS);
|
|
1582
1597
|
const ring = $("ring"); ring.classList.remove("ok", "err"); void ring.getBoundingClientRect();
|
|
1583
1598
|
ring.classList.add(ok ? "ok" : "err");
|
|
1584
1599
|
$("result").classList.toggle("err", !ok);
|
|
1585
1600
|
$("result").classList.remove("hidden");
|
|
1586
|
-
$("title").textContent = ok ?
|
|
1601
|
+
$("title").textContent = ok ? T.allSet : T.somethingWrong;
|
|
1587
1602
|
["next", "back", "refresh"].forEach((id) => $(id).classList.add("hidden"));
|
|
1588
1603
|
}
|
|
1589
|
-
function renderAgents() { $("spinner").classList.add("hidden"); const root = $("agents"); if (!clients.length) { root.innerHTML = '<div class="sub">
|
|
1590
|
-
async function refresh() { $("spinner").classList.remove("hidden"); $("agents").innerHTML = ""; const res = await fetch("/api/status"); const data = await res.json(); clients = data.clients || []; renderAgents(); if (!clients.length) say(
|
|
1591
|
-
async function doLogin() { $("next").disabled = true; say(
|
|
1604
|
+
function renderAgents() { $("spinner").classList.add("hidden"); const root = $("agents"); if (!clients.length) { root.innerHTML = '<div class="sub">' + esc(T.noClientsDetected) + '</div>'; return; } root.innerHTML = clients.map((client) => { const manual = client.id === "chatgpt-desktop"; const badgeText = manual ? T.badgeManual : client.configured ? T.badgeUpdate : T.badgeInstall; const badgeClass = manual ? "badge-update" : client.configured ? "badge-update" : "badge-install"; return '<label class="agent"><input type="checkbox" data-client="' + esc(client.id) + '" checked /><span><strong>' + esc(client.label) + ' <span class="badge-pill ' + badgeClass + '">' + esc(badgeText) + '</span></strong><span class="detail">' + esc(client.detail) + '</span></span></label>'; }).join(""); }
|
|
1605
|
+
async function refresh() { $("spinner").classList.remove("hidden"); $("agents").innerHTML = ""; const res = await fetch("/api/status"); const data = await res.json(); clients = data.clients || []; renderAgents(); if (!clients.length) say(T.noAgentsDetected); }
|
|
1606
|
+
async function doLogin() { $("next").disabled = true; say(T.openingSignIn); try { const res = await fetch("/api/oauth-login", { method:"POST" }); const data = await res.json(); if (!data.ok) return say(data.error || T.oauthFailed, true); sessionId = data.sessionId; setStep(2); await refresh(); } finally { $("next").disabled = false; } }
|
|
1592
1607
|
async function install() {
|
|
1593
1608
|
const selected = [...document.querySelectorAll("[data-client]:checked")].map((el) => el.dataset.client);
|
|
1594
|
-
if (!selected.length) return say(
|
|
1609
|
+
if (!selected.length) return say(T.selectAtLeastOne, true);
|
|
1595
1610
|
setStep(3);
|
|
1596
1611
|
let okCount = 0, lastError = "";
|
|
1597
|
-
const params = new URLSearchParams({ sessionId, clients: selected.join(","), write: "1", telemetry: "1" });
|
|
1612
|
+
const params = new URLSearchParams({ sessionId, clients: selected.join(","), write: "1", telemetry: "1", locale: LOCALE });
|
|
1598
1613
|
const events = new EventSource("/api/install-stream?" + params.toString());
|
|
1599
1614
|
events.onmessage = (event) => {
|
|
1600
1615
|
const data = JSON.parse(event.data);
|
|
@@ -1603,12 +1618,12 @@ function pageHtml() {
|
|
|
1603
1618
|
if (data.level === "done") {
|
|
1604
1619
|
events.close();
|
|
1605
1620
|
const ok = okCount > 0 && !lastError;
|
|
1606
|
-
showResult(ok, ok ?
|
|
1621
|
+
showResult(ok, ok ? T.successInstalled : (lastError || T.noneInstalled));
|
|
1607
1622
|
} else {
|
|
1608
1623
|
say(data.message, data.level === "error");
|
|
1609
1624
|
}
|
|
1610
1625
|
};
|
|
1611
|
-
events.onerror = () => { events.close(); showResult(false,
|
|
1626
|
+
events.onerror = () => { events.close(); showResult(false, T.streamDisconnected); };
|
|
1612
1627
|
}
|
|
1613
1628
|
$("back").addEventListener("click", () => setStep(1));
|
|
1614
1629
|
$("refresh").addEventListener("click", refresh);
|
|
@@ -1663,7 +1678,7 @@ function makeGuiServer(options, pageContent, extraRoutes, logLabel) {
|
|
|
1663
1678
|
}
|
|
1664
1679
|
try {
|
|
1665
1680
|
if (req.method === "GET" && req.url === "/") {
|
|
1666
|
-
const raw = pageContent();
|
|
1681
|
+
const raw = await pageContent();
|
|
1667
1682
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "content-length": Buffer.byteLength(raw) });
|
|
1668
1683
|
res.end(raw);
|
|
1669
1684
|
return;
|
|
@@ -1690,7 +1705,7 @@ function makeGuiServer(options, pageContent, extraRoutes, logLabel) {
|
|
|
1690
1705
|
});
|
|
1691
1706
|
}
|
|
1692
1707
|
function startInstallerGui(options = {}) {
|
|
1693
|
-
return makeGuiServer(options, pageHtml, async (req, res, onDone) => {
|
|
1708
|
+
return makeGuiServer(options, async () => pageHtml(await detectLocale()), async (req, res, onDone) => {
|
|
1694
1709
|
if (req.method === "GET" && req.url === "/api/status") {
|
|
1695
1710
|
sendJson(res, 200, { os: formatInstallOsLabel(), hostedMcpUrl: HOSTED_MCP_URL, clients: await clientsWithConfiguredStatus() });
|
|
1696
1711
|
return true;
|
|
@@ -1711,7 +1726,7 @@ function startInstallerGui(options = {}) {
|
|
|
1711
1726
|
}, "installer");
|
|
1712
1727
|
}
|
|
1713
1728
|
function startUninstallerGui(options = {}) {
|
|
1714
|
-
return makeGuiServer(options, pageUninstallHtml, async (req, res, onDone) => {
|
|
1729
|
+
return makeGuiServer(options, async () => pageUninstallHtml(await detectLocale()), async (req, res, onDone) => {
|
|
1715
1730
|
if (req.method === "GET" && req.url === "/api/status") {
|
|
1716
1731
|
sendJson(res, 200, { os: formatInstallOsLabel(), clients: await clientsWithConfiguredStatus() });
|
|
1717
1732
|
return true;
|
|
@@ -1723,7 +1738,7 @@ function startUninstallerGui(options = {}) {
|
|
|
1723
1738
|
return false;
|
|
1724
1739
|
}, "uninstaller");
|
|
1725
1740
|
}
|
|
1726
|
-
var VERSION, PORT, sessions, OAUTH_BASE_URLS, LOCAL_BIN_PATH;
|
|
1741
|
+
var VERSION, MESSAGES, PORT, sessions, OAUTH_BASE_URLS, LOCAL_BIN_PATH;
|
|
1727
1742
|
var init_installer_gui = __esm({
|
|
1728
1743
|
"installer/installer-gui.ts"() {
|
|
1729
1744
|
"use strict";
|
|
@@ -1733,7 +1748,147 @@ var init_installer_gui = __esm({
|
|
|
1733
1748
|
init_install_dxt();
|
|
1734
1749
|
init_install_shared();
|
|
1735
1750
|
init_oauth();
|
|
1736
|
-
VERSION = true ? "0.23.
|
|
1751
|
+
VERSION = true ? "0.23.6" : "0.0.0-dev";
|
|
1752
|
+
MESSAGES = {
|
|
1753
|
+
en: {
|
|
1754
|
+
installer: {
|
|
1755
|
+
docTitle: "Leadbay MCP installer",
|
|
1756
|
+
steps: {
|
|
1757
|
+
1: { title: "Connect Leadbay", sub: "Sign in to install Leadbay across your AI agents." },
|
|
1758
|
+
2: { title: "Choose your agents", sub: "Pick where to install Leadbay." },
|
|
1759
|
+
3: { title: "Installing", sub: "Keep this window open until it's done." }
|
|
1760
|
+
},
|
|
1761
|
+
btnSignIn: "Sign in with Leadbay",
|
|
1762
|
+
btnInstall: "Install",
|
|
1763
|
+
btnBack: "Back",
|
|
1764
|
+
btnRefresh: "Refresh",
|
|
1765
|
+
noClientsDetected: "No supported MCP client detected on this machine.",
|
|
1766
|
+
noAgentsDetected: "No supported agents detected.",
|
|
1767
|
+
selectAtLeastOne: "Select at least one agent.",
|
|
1768
|
+
openingSignIn: "Opening Leadbay sign-in in your browser...",
|
|
1769
|
+
oauthFailed: "OAuth login failed.",
|
|
1770
|
+
successInstalled: "MCP successfully installed",
|
|
1771
|
+
noneInstalled: "No agents were installed.",
|
|
1772
|
+
streamDisconnected: "Install stream disconnected.",
|
|
1773
|
+
closeWindow: "You can close this window.",
|
|
1774
|
+
allSet: "All set",
|
|
1775
|
+
somethingWrong: "Something went wrong",
|
|
1776
|
+
badgeManual: "manual",
|
|
1777
|
+
badgeUpdate: "update",
|
|
1778
|
+
badgeInstall: "install"
|
|
1779
|
+
},
|
|
1780
|
+
uninstaller: {
|
|
1781
|
+
docTitle: "Leadbay MCP uninstaller",
|
|
1782
|
+
steps: {
|
|
1783
|
+
1: { title: "Remove Leadbay MCP", sub: "Select the agents to remove Leadbay MCP from." },
|
|
1784
|
+
2: { title: "Removing", sub: "Keep this window open until it's done." }
|
|
1785
|
+
},
|
|
1786
|
+
btnRemove: "Remove selected",
|
|
1787
|
+
btnBack: "Back",
|
|
1788
|
+
btnRefresh: "Refresh",
|
|
1789
|
+
noInstallDetected: "No Leadbay MCP installation detected on this machine.",
|
|
1790
|
+
selectAtLeastOne: "Select at least one agent.",
|
|
1791
|
+
successRemoved: "MCP successfully removed",
|
|
1792
|
+
noneRemoved: "No agents were removed.",
|
|
1793
|
+
streamDisconnected: "Uninstall stream disconnected.",
|
|
1794
|
+
closeWindow: "You can close this window.",
|
|
1795
|
+
allSet: "All set",
|
|
1796
|
+
somethingWrong: "Something went wrong"
|
|
1797
|
+
},
|
|
1798
|
+
server: {
|
|
1799
|
+
loginExpired: "Login expired. Go back and sign in again.",
|
|
1800
|
+
selectAtLeastOne: "Select at least one agent.",
|
|
1801
|
+
noSelectedDetected: "No selected agents were detected on this machine.",
|
|
1802
|
+
installStopped: "Install stopped.",
|
|
1803
|
+
uninstallStopped: "Uninstall stopped.",
|
|
1804
|
+
connectedTo: (label) => `Connected to ${label}.`,
|
|
1805
|
+
toolFlags: (write, telemetry) => `Write tools ${write ? "enabled" : "disabled"}; telemetry ${telemetry ? "enabled" : "disabled"}.`,
|
|
1806
|
+
refreshingDetection: "Refreshing installed-agent detection...",
|
|
1807
|
+
installing: (label) => `Installing ${label}...`,
|
|
1808
|
+
preparingManual: (label) => `Preparing ${label} manual setup...`,
|
|
1809
|
+
removing: (label) => `Removing from ${label}...`,
|
|
1810
|
+
installedSummary: (ok, total) => `${ok}/${total} agent(s) installed, updated, or prepared.`,
|
|
1811
|
+
manualReady: "Manual ChatGPT setup instructions ready.",
|
|
1812
|
+
removedSummary: (ok, total) => `${ok}/${total} agent(s) removed.`,
|
|
1813
|
+
restartClients: "Restart your MCP client(s) to pick up the new server.",
|
|
1814
|
+
followManual: "Follow the manual setup instructions shown above.",
|
|
1815
|
+
completeRemoval: "Restart your MCP client(s) to complete the removal.",
|
|
1816
|
+
loggedInBackend: (region) => `Logged in to ${region.toUpperCase()} backend.`,
|
|
1817
|
+
settingsLine: (write, telemetry) => `Settings: write tools ${write ? "on" : "off"}, telemetry ${telemetry ? "on" : "off"}.`,
|
|
1818
|
+
installSummaryHeader: "Install summary:",
|
|
1819
|
+
noAgentsRemoved: "No agents were removed."
|
|
1820
|
+
}
|
|
1821
|
+
},
|
|
1822
|
+
fr: {
|
|
1823
|
+
installer: {
|
|
1824
|
+
docTitle: "Installateur Leadbay MCP",
|
|
1825
|
+
steps: {
|
|
1826
|
+
1: { title: "Connectez Leadbay", sub: "Connectez-vous pour installer Leadbay sur vos agents IA." },
|
|
1827
|
+
2: { title: "Choisissez vos agents", sub: "Choisissez o\xF9 installer Leadbay." },
|
|
1828
|
+
3: { title: "Installation en cours", sub: "Gardez cette fen\xEAtre ouverte jusqu'\xE0 la fin." }
|
|
1829
|
+
},
|
|
1830
|
+
btnSignIn: "Se connecter avec Leadbay",
|
|
1831
|
+
btnInstall: "Installer",
|
|
1832
|
+
btnBack: "Retour",
|
|
1833
|
+
btnRefresh: "Actualiser",
|
|
1834
|
+
noClientsDetected: "Aucun client MCP compatible d\xE9tect\xE9 sur cette machine.",
|
|
1835
|
+
noAgentsDetected: "Aucun agent compatible d\xE9tect\xE9.",
|
|
1836
|
+
selectAtLeastOne: "S\xE9lectionnez au moins un agent.",
|
|
1837
|
+
openingSignIn: "Ouverture de la connexion Leadbay dans votre navigateur...",
|
|
1838
|
+
oauthFailed: "\xC9chec de la connexion OAuth.",
|
|
1839
|
+
successInstalled: "MCP install\xE9 avec succ\xE8s",
|
|
1840
|
+
noneInstalled: "Aucun agent n'a \xE9t\xE9 install\xE9.",
|
|
1841
|
+
streamDisconnected: "Flux d'installation interrompu.",
|
|
1842
|
+
closeWindow: "Vous pouvez fermer cette fen\xEAtre.",
|
|
1843
|
+
allSet: "Termin\xE9",
|
|
1844
|
+
somethingWrong: "Une erreur est survenue",
|
|
1845
|
+
badgeManual: "manuel",
|
|
1846
|
+
badgeUpdate: "mettre \xE0 jour",
|
|
1847
|
+
badgeInstall: "installer"
|
|
1848
|
+
},
|
|
1849
|
+
uninstaller: {
|
|
1850
|
+
docTitle: "D\xE9sinstallateur Leadbay MCP",
|
|
1851
|
+
steps: {
|
|
1852
|
+
1: { title: "Supprimer Leadbay MCP", sub: "S\xE9lectionnez les agents desquels supprimer Leadbay MCP." },
|
|
1853
|
+
2: { title: "Suppression en cours", sub: "Gardez cette fen\xEAtre ouverte jusqu'\xE0 la fin." }
|
|
1854
|
+
},
|
|
1855
|
+
btnRemove: "Supprimer la s\xE9lection",
|
|
1856
|
+
btnBack: "Retour",
|
|
1857
|
+
btnRefresh: "Actualiser",
|
|
1858
|
+
noInstallDetected: "Aucune installation Leadbay MCP d\xE9tect\xE9e sur cette machine.",
|
|
1859
|
+
selectAtLeastOne: "S\xE9lectionnez au moins un agent.",
|
|
1860
|
+
successRemoved: "MCP supprim\xE9 avec succ\xE8s",
|
|
1861
|
+
noneRemoved: "Aucun agent n'a \xE9t\xE9 supprim\xE9.",
|
|
1862
|
+
streamDisconnected: "Flux de d\xE9sinstallation interrompu.",
|
|
1863
|
+
closeWindow: "Vous pouvez fermer cette fen\xEAtre.",
|
|
1864
|
+
allSet: "Termin\xE9",
|
|
1865
|
+
somethingWrong: "Une erreur est survenue"
|
|
1866
|
+
},
|
|
1867
|
+
server: {
|
|
1868
|
+
loginExpired: "Session expir\xE9e. Revenez en arri\xE8re et reconnectez-vous.",
|
|
1869
|
+
selectAtLeastOne: "S\xE9lectionnez au moins un agent.",
|
|
1870
|
+
noSelectedDetected: "Aucun des agents s\xE9lectionn\xE9s n'a \xE9t\xE9 d\xE9tect\xE9 sur cette machine.",
|
|
1871
|
+
installStopped: "Installation arr\xEAt\xE9e.",
|
|
1872
|
+
uninstallStopped: "D\xE9sinstallation arr\xEAt\xE9e.",
|
|
1873
|
+
connectedTo: (label) => `Connect\xE9 \xE0 ${label}.`,
|
|
1874
|
+
toolFlags: (write, telemetry) => `Outils d'\xE9criture ${write ? "activ\xE9s" : "d\xE9sactiv\xE9s"} ; t\xE9l\xE9m\xE9trie ${telemetry ? "activ\xE9e" : "d\xE9sactiv\xE9e"}.`,
|
|
1875
|
+
refreshingDetection: "Actualisation de la d\xE9tection des agents install\xE9s...",
|
|
1876
|
+
installing: (label) => `Installation de ${label}...`,
|
|
1877
|
+
preparingManual: (label) => `Pr\xE9paration de la configuration manuelle de ${label}...`,
|
|
1878
|
+
removing: (label) => `Suppression de ${label}...`,
|
|
1879
|
+
installedSummary: (ok, total) => `${ok}/${total} agent(s) install\xE9(s), mis \xE0 jour ou pr\xE9par\xE9(s).`,
|
|
1880
|
+
manualReady: "Instructions de configuration manuelle de ChatGPT pr\xEAtes.",
|
|
1881
|
+
removedSummary: (ok, total) => `${ok}/${total} agent(s) supprim\xE9(s).`,
|
|
1882
|
+
restartClients: "Red\xE9marrez votre/vos client(s) MCP pour charger le nouveau serveur.",
|
|
1883
|
+
followManual: "Suivez les instructions de configuration manuelle ci-dessus.",
|
|
1884
|
+
completeRemoval: "Red\xE9marrez votre/vos client(s) MCP pour terminer la suppression.",
|
|
1885
|
+
loggedInBackend: (region) => `Connect\xE9 au backend ${region.toUpperCase()}.`,
|
|
1886
|
+
settingsLine: (write, telemetry) => `Param\xE8tres : outils d'\xE9criture ${write ? "activ\xE9s" : "d\xE9sactiv\xE9s"}, t\xE9l\xE9m\xE9trie ${telemetry ? "activ\xE9e" : "d\xE9sactiv\xE9e"}.`,
|
|
1887
|
+
installSummaryHeader: "R\xE9capitulatif de l'installation :",
|
|
1888
|
+
noAgentsRemoved: "Aucun agent n'a \xE9t\xE9 supprim\xE9."
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
};
|
|
1737
1892
|
PORT = Number(process.env.LEADBAY_INSTALLER_PORT ?? 0);
|
|
1738
1893
|
sessions = /* @__PURE__ */ new Map();
|
|
1739
1894
|
OAUTH_BASE_URLS = {
|