local-operator-ui 0.19.7 → 0.20.1
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/bin/ensure-electron.js +47 -0
- package/bin/linux-sandbox.js +27 -18
- package/bin/postinstall.js +55 -33
- package/out/main/index.js +194 -417
- package/out/renderer/assets/{_basePickBy-C411r4Fr.js → _basePickBy-C7yOlBwG.js} +1 -1
- package/out/renderer/assets/{_baseUniq-Bt63j3mu.js → _baseUniq-BxWDXUxR.js} +1 -1
- package/out/renderer/assets/{agent-details-page-DujEqAzR.js → agent-details-page-DGusXpiv.js} +1 -1
- package/out/renderer/assets/{agent-hub-page-C3kMnXTf.js → agent-hub-page-BEy-xjst.js} +1 -1
- package/out/renderer/assets/{agents-page-NEQ4hFtm.js → agents-page-VfOUQ-yP.js} +2 -2
- package/out/renderer/assets/{architectureDiagram-IEHRJDOE-BqpmUfyo.js → architectureDiagram-IEHRJDOE-358ZDLa0.js} +1 -1
- package/out/renderer/assets/{blockDiagram-JOT3LUYC-CnQwEPXO.js → blockDiagram-JOT3LUYC-tzEHVS4j.js} +1 -1
- package/out/renderer/assets/{c4Diagram-VJAJSXHY-Dk_OmMLJ.js → c4Diagram-VJAJSXHY-D3tP-CCo.js} +1 -1
- package/out/renderer/assets/channel-D37fF6my.js +1 -0
- package/out/renderer/assets/{chunk-4BMEZGHF-BdRWhpmN.js → chunk-4BMEZGHF-BKUSTR_S.js} +1 -1
- package/out/renderer/assets/{chunk-A2AXSNBT-yHqgRYdq.js → chunk-A2AXSNBT-DvXPJSTp.js} +1 -1
- package/out/renderer/assets/{chunk-AEK57VVT-BanBKJ_s.js → chunk-AEK57VVT-iJyV8fDW.js} +1 -1
- package/out/renderer/assets/{chunk-D6G4REZN-CuQN5RTN.js → chunk-D6G4REZN-B3DDJ3MU.js} +1 -1
- package/out/renderer/assets/{chunk-RZ5BOZE2-C8fBZeNu.js → chunk-RZ5BOZE2-Dbn_07ZJ.js} +1 -1
- package/out/renderer/assets/{chunk-XZIHB7SX-6KNcbSfo.js → chunk-XZIHB7SX-ChdMxZnm.js} +1 -1
- package/out/renderer/assets/classDiagram-GIVACNV2-CcnNtrPC.js +1 -0
- package/out/renderer/assets/classDiagram-v2-COTLJTTW-CcnNtrPC.js +1 -0
- package/out/renderer/assets/clone-DPqLvbSr.js +1 -0
- package/out/renderer/assets/{compact-pagination-Ovp_kll1.js → compact-pagination-duvMYksr.js} +1 -1
- package/out/renderer/assets/{dagre-OKDRZEBW-DzfvIYmf.js → dagre-OKDRZEBW-BuSM1V0w.js} +1 -1
- package/out/renderer/assets/{diagram-SSKATNLV-Bpyw0frR.js → diagram-SSKATNLV-39xt9Mcn.js} +1 -1
- package/out/renderer/assets/{diagram-VNBRO52H-r7KETc_A.js → diagram-VNBRO52H-Bgyt_DWD.js} +1 -1
- package/out/renderer/assets/{erDiagram-Q7BY3M3F-BBPxCrm9.js → erDiagram-Q7BY3M3F-DNfsSD46.js} +1 -1
- package/out/renderer/assets/{flowDiagram-4HSFHLVR-Bqfojzvn.js → flowDiagram-4HSFHLVR-DbS8UHwN.js} +1 -1
- package/out/renderer/assets/{ganttDiagram-APWFNJXF-Cd7hVnw4.js → ganttDiagram-APWFNJXF-Dxdp2V-6.js} +1 -1
- package/out/renderer/assets/{gitGraphDiagram-7IBYFJ6S-Dxoexd6b.js → gitGraphDiagram-7IBYFJ6S-BLrXJPe3.js} +1 -1
- package/out/renderer/assets/{graph-DoZ-YflA.js → graph-Cgkq5xQ7.js} +1 -1
- package/out/renderer/assets/{icon-DaedMBiD.css → icon-HSrrv8O-.css} +1 -1
- package/out/renderer/assets/{index-s958Ss2_.js → index-C4RcIL0i.js} +1 -1
- package/out/renderer/assets/{index-DXDWG455.js → index-CLwRuOtJ.js} +47 -47
- package/out/renderer/assets/{index-Bvsuxozx.js → index-lEoaSpWQ.js} +1 -1
- package/out/renderer/assets/{infoDiagram-PH2N3AL5-B6Q2kq6y.js → infoDiagram-PH2N3AL5-DR6So_J8.js} +1 -1
- package/out/renderer/assets/{installer-poO56j69.js → installer-Ck14_4Oh.js} +1 -1
- package/out/renderer/assets/{journeyDiagram-U35MCT3I-YvFhqi_4.js → journeyDiagram-U35MCT3I-DubpieGX.js} +1 -1
- package/out/renderer/assets/{kanban-definition-NDS4AKOZ-hUPw4d6Q.js → kanban-definition-NDS4AKOZ-BtwsU2Rg.js} +1 -1
- package/out/renderer/assets/{layout-DL79cPuU.js → layout-BDeRPl4h.js} +1 -1
- package/out/renderer/assets/{legacy-agents-page-Bc9_mRrf.js → legacy-agents-page-ZyBMetf1.js} +1 -1
- package/out/renderer/assets/{mermaid.core-DY-qM3jW.js → mermaid.core-d-O-_a6F.js} +5 -5
- package/out/renderer/assets/{mindmap-definition-ALO5MXBD-BIr3BZFI.js → mindmap-definition-ALO5MXBD-BCZdiKEB.js} +1 -1
- package/out/renderer/assets/{page-header-zecAylNs.js → page-header-D-uc8qqA.js} +1 -1
- package/out/renderer/assets/{parseISO-DLnRjbkm.js → parseISO-PdZfrqAM.js} +1 -1
- package/out/renderer/assets/{pieDiagram-IB7DONF6-DEfXQAHX.js → pieDiagram-IB7DONF6-Bd2e7gHe.js} +1 -1
- package/out/renderer/assets/{quadrantDiagram-7GDLP6J5-DTbs_0uW.js → quadrantDiagram-7GDLP6J5-oypZsih9.js} +1 -1
- package/out/renderer/assets/{radar-MK3ICKWK-YpweuwYm.js → radar-MK3ICKWK-c4YagPOX.js} +1 -1
- package/out/renderer/assets/{radient-auth-buttons--VhWRhuh.js → radient-auth-buttons-BUlY7XDi.js} +1 -1
- package/out/renderer/assets/{requirementDiagram-KVF5MWMF-DV8bmMki.js → requirementDiagram-KVF5MWMF-7UoAwEus.js} +1 -1
- package/out/renderer/assets/{sankeyDiagram-QLVOVGJD-BpZDUCJV.js → sankeyDiagram-QLVOVGJD-JStPMuRd.js} +1 -1
- package/out/renderer/assets/{schedules-page-Co1Ixrkk.js → schedules-page-IjBtVuIo.js} +1 -1
- package/out/renderer/assets/{sequenceDiagram-X6HHIX6F-B4x4_BhD.js → sequenceDiagram-X6HHIX6F-Lene9gQ-.js} +1 -1
- package/out/renderer/assets/{settings-page-yvoJPfPs.js → settings-page-BqJRfztd.js} +1 -1
- package/out/renderer/assets/{square-pen-CdJTC74b.js → square-pen-CQEKS3JT.js} +1 -1
- package/out/renderer/assets/{stateDiagram-DGXRK772-DHIWQgsa.js → stateDiagram-DGXRK772-umC2tGUK.js} +1 -1
- package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-Cp1tcztr.js +1 -0
- package/out/renderer/assets/{timeline-definition-BDJGKUSR-rcUcUcdw.js → timeline-definition-BDJGKUSR-h2KfXqek.js} +1 -1
- package/out/renderer/assets/{use-agent-like-mutation-_CPevTyx.js → use-agent-like-mutation-BanZ02f7.js} +1 -1
- package/out/renderer/assets/{xychartDiagram-VJFVF3MP-CiY7ytjm.js → xychartDiagram-VJFVF3MP-BOH5ZQcH.js} +1 -1
- package/out/renderer/index.html +3 -3
- package/out/renderer/installer.html +3 -3
- package/package.json +69 -58
- package/out/renderer/assets/channel-QDS9FjQE.js +0 -1
- package/out/renderer/assets/classDiagram-GIVACNV2-CsOBNtuH.js +0 -1
- package/out/renderer/assets/classDiagram-v2-COTLJTTW-CsOBNtuH.js +0 -1
- package/out/renderer/assets/clone-BmqcgcfO.js +0 -1
- package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-CQi1jyLr.js +0 -1
- /package/out/renderer/assets/{icon-DMNb6cX-.js → icon-RIkwUxL5.js} +0 -0
package/out/main/index.js
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const fs = require("node:fs");
|
|
3
|
-
const path = require("node:path");
|
|
3
|
+
const path$1 = require("node:path");
|
|
4
4
|
const node_url = require("node:url");
|
|
5
5
|
const utils = require("@electron-toolkit/utils");
|
|
6
6
|
const electron = require("electron");
|
|
7
7
|
const posthogNode = require("posthog-node");
|
|
8
|
-
const
|
|
8
|
+
const path = require("path");
|
|
9
9
|
const node_child_process = require("node:child_process");
|
|
10
10
|
const node_crypto = require("node:crypto");
|
|
11
11
|
const os = require("node:os");
|
|
12
12
|
const node_util = require("node:util");
|
|
13
13
|
const zod = require("zod");
|
|
14
|
-
const
|
|
15
|
-
const require$$2 = require("os");
|
|
16
|
-
const require$$3 = require("crypto");
|
|
14
|
+
const dotenv = require("dotenv");
|
|
17
15
|
const electronLog = require("electron-log");
|
|
18
16
|
const https = require("node:https");
|
|
19
17
|
const electronUpdater = require("electron-updater");
|
|
@@ -33,9 +31,9 @@ function _interopNamespaceDefault(e) {
|
|
|
33
31
|
n.default = e;
|
|
34
32
|
return Object.freeze(n);
|
|
35
33
|
}
|
|
36
|
-
const path__namespace = /* @__PURE__ */ _interopNamespaceDefault(path);
|
|
34
|
+
const path__namespace = /* @__PURE__ */ _interopNamespaceDefault(path$1);
|
|
37
35
|
const https__namespace = /* @__PURE__ */ _interopNamespaceDefault(https);
|
|
38
|
-
const icon =
|
|
36
|
+
const icon = path.join(__dirname, "../../resources/icon.png");
|
|
39
37
|
const id$1 = zod.z.string().min(1).max(128).regex(/^[a-zA-Z0-9_-]+$/);
|
|
40
38
|
const MAX_UPLOAD_BYTES = 16 * 1024 * 1024;
|
|
41
39
|
const MAX_DOWNLOAD_BYTES = 32 * 1024 * 1024;
|
|
@@ -1344,7 +1342,7 @@ function insideAppBundle(path2) {
|
|
|
1344
1342
|
return path2.split(PATH_SEPARATORS).some((segment) => segment.length > 4 && segment.endsWith(".app"));
|
|
1345
1343
|
}
|
|
1346
1344
|
function pythonBytecodeCacheDir(userDataDir) {
|
|
1347
|
-
return path.join(userDataDir, PYTHON_BYTECODE_CACHE_DIR_NAME);
|
|
1345
|
+
return path$1.join(userDataDir, PYTHON_BYTECODE_CACHE_DIR_NAME);
|
|
1348
1346
|
}
|
|
1349
1347
|
function withPythonBytecodeCache(env, userDataDir) {
|
|
1350
1348
|
const existing = env.PYTHONPYCACHEPREFIX?.trim();
|
|
@@ -1353,7 +1351,7 @@ function withPythonBytecodeCache(env, userDataDir) {
|
|
|
1353
1351
|
}
|
|
1354
1352
|
const BUNDLED_PYTHON_TREE_NAMES = ["python", "python_aarch64"];
|
|
1355
1353
|
function bundledPythonTreePaths(resourcesPath) {
|
|
1356
|
-
return BUNDLED_PYTHON_TREE_NAMES.map((name) => path.join(resourcesPath, name));
|
|
1354
|
+
return BUNDLED_PYTHON_TREE_NAMES.map((name) => path$1.join(resourcesPath, name));
|
|
1357
1355
|
}
|
|
1358
1356
|
const FIND = "/usr/bin/find";
|
|
1359
1357
|
const CHMOD = "/bin/chmod";
|
|
@@ -1426,279 +1424,6 @@ function applyAce(tree, selector, ace, failures) {
|
|
|
1426
1424
|
for (const byte of run.stdout) if (byte === 0) selected += 1;
|
|
1427
1425
|
return selected;
|
|
1428
1426
|
}
|
|
1429
|
-
var main = { exports: {} };
|
|
1430
|
-
const version = "16.5.0";
|
|
1431
|
-
const require$$4 = {
|
|
1432
|
-
version
|
|
1433
|
-
};
|
|
1434
|
-
var hasRequiredMain;
|
|
1435
|
-
function requireMain() {
|
|
1436
|
-
if (hasRequiredMain) return main.exports;
|
|
1437
|
-
hasRequiredMain = 1;
|
|
1438
|
-
const fs2 = require$$0;
|
|
1439
|
-
const path2 = require$$1;
|
|
1440
|
-
const os2 = require$$2;
|
|
1441
|
-
const crypto = require$$3;
|
|
1442
|
-
const packageJson = require$$4;
|
|
1443
|
-
const version2 = packageJson.version;
|
|
1444
|
-
const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
1445
|
-
function parse(src) {
|
|
1446
|
-
const obj = {};
|
|
1447
|
-
let lines = src.toString();
|
|
1448
|
-
lines = lines.replace(/\r\n?/mg, "\n");
|
|
1449
|
-
let match;
|
|
1450
|
-
while ((match = LINE.exec(lines)) != null) {
|
|
1451
|
-
const key = match[1];
|
|
1452
|
-
let value = match[2] || "";
|
|
1453
|
-
value = value.trim();
|
|
1454
|
-
const maybeQuote = value[0];
|
|
1455
|
-
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, "$2");
|
|
1456
|
-
if (maybeQuote === '"') {
|
|
1457
|
-
value = value.replace(/\\n/g, "\n");
|
|
1458
|
-
value = value.replace(/\\r/g, "\r");
|
|
1459
|
-
}
|
|
1460
|
-
obj[key] = value;
|
|
1461
|
-
}
|
|
1462
|
-
return obj;
|
|
1463
|
-
}
|
|
1464
|
-
function _parseVault(options) {
|
|
1465
|
-
const vaultPath = _vaultPath(options);
|
|
1466
|
-
const result = DotenvModule.configDotenv({ path: vaultPath });
|
|
1467
|
-
if (!result.parsed) {
|
|
1468
|
-
const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
|
|
1469
|
-
err.code = "MISSING_DATA";
|
|
1470
|
-
throw err;
|
|
1471
|
-
}
|
|
1472
|
-
const keys = _dotenvKey(options).split(",");
|
|
1473
|
-
const length = keys.length;
|
|
1474
|
-
let decrypted;
|
|
1475
|
-
for (let i = 0; i < length; i++) {
|
|
1476
|
-
try {
|
|
1477
|
-
const key = keys[i].trim();
|
|
1478
|
-
const attrs = _instructions(result, key);
|
|
1479
|
-
decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
|
|
1480
|
-
break;
|
|
1481
|
-
} catch (error) {
|
|
1482
|
-
if (i + 1 >= length) {
|
|
1483
|
-
throw error;
|
|
1484
|
-
}
|
|
1485
|
-
}
|
|
1486
|
-
}
|
|
1487
|
-
return DotenvModule.parse(decrypted);
|
|
1488
|
-
}
|
|
1489
|
-
function _warn(message) {
|
|
1490
|
-
console.log(`[dotenv@${version2}][WARN] ${message}`);
|
|
1491
|
-
}
|
|
1492
|
-
function _debug(message) {
|
|
1493
|
-
console.log(`[dotenv@${version2}][DEBUG] ${message}`);
|
|
1494
|
-
}
|
|
1495
|
-
function _dotenvKey(options) {
|
|
1496
|
-
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
|
|
1497
|
-
return options.DOTENV_KEY;
|
|
1498
|
-
}
|
|
1499
|
-
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
|
|
1500
|
-
return process.env.DOTENV_KEY;
|
|
1501
|
-
}
|
|
1502
|
-
return "";
|
|
1503
|
-
}
|
|
1504
|
-
function _instructions(result, dotenvKey) {
|
|
1505
|
-
let uri;
|
|
1506
|
-
try {
|
|
1507
|
-
uri = new URL(dotenvKey);
|
|
1508
|
-
} catch (error) {
|
|
1509
|
-
if (error.code === "ERR_INVALID_URL") {
|
|
1510
|
-
const err = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
|
|
1511
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
1512
|
-
throw err;
|
|
1513
|
-
}
|
|
1514
|
-
throw error;
|
|
1515
|
-
}
|
|
1516
|
-
const key = uri.password;
|
|
1517
|
-
if (!key) {
|
|
1518
|
-
const err = new Error("INVALID_DOTENV_KEY: Missing key part");
|
|
1519
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
1520
|
-
throw err;
|
|
1521
|
-
}
|
|
1522
|
-
const environment = uri.searchParams.get("environment");
|
|
1523
|
-
if (!environment) {
|
|
1524
|
-
const err = new Error("INVALID_DOTENV_KEY: Missing environment part");
|
|
1525
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
1526
|
-
throw err;
|
|
1527
|
-
}
|
|
1528
|
-
const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
|
|
1529
|
-
const ciphertext = result.parsed[environmentKey];
|
|
1530
|
-
if (!ciphertext) {
|
|
1531
|
-
const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
|
|
1532
|
-
err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
|
|
1533
|
-
throw err;
|
|
1534
|
-
}
|
|
1535
|
-
return { ciphertext, key };
|
|
1536
|
-
}
|
|
1537
|
-
function _vaultPath(options) {
|
|
1538
|
-
let possibleVaultPath = null;
|
|
1539
|
-
if (options && options.path && options.path.length > 0) {
|
|
1540
|
-
if (Array.isArray(options.path)) {
|
|
1541
|
-
for (const filepath of options.path) {
|
|
1542
|
-
if (fs2.existsSync(filepath)) {
|
|
1543
|
-
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
1544
|
-
}
|
|
1545
|
-
}
|
|
1546
|
-
} else {
|
|
1547
|
-
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
1548
|
-
}
|
|
1549
|
-
} else {
|
|
1550
|
-
possibleVaultPath = path2.resolve(process.cwd(), ".env.vault");
|
|
1551
|
-
}
|
|
1552
|
-
if (fs2.existsSync(possibleVaultPath)) {
|
|
1553
|
-
return possibleVaultPath;
|
|
1554
|
-
}
|
|
1555
|
-
return null;
|
|
1556
|
-
}
|
|
1557
|
-
function _resolveHome(envPath) {
|
|
1558
|
-
return envPath[0] === "~" ? path2.join(os2.homedir(), envPath.slice(1)) : envPath;
|
|
1559
|
-
}
|
|
1560
|
-
function _configVault(options) {
|
|
1561
|
-
const debug = Boolean(options && options.debug);
|
|
1562
|
-
if (debug) {
|
|
1563
|
-
_debug("Loading env from encrypted .env.vault");
|
|
1564
|
-
}
|
|
1565
|
-
const parsed = DotenvModule._parseVault(options);
|
|
1566
|
-
let processEnv = process.env;
|
|
1567
|
-
if (options && options.processEnv != null) {
|
|
1568
|
-
processEnv = options.processEnv;
|
|
1569
|
-
}
|
|
1570
|
-
DotenvModule.populate(processEnv, parsed, options);
|
|
1571
|
-
return { parsed };
|
|
1572
|
-
}
|
|
1573
|
-
function configDotenv(options) {
|
|
1574
|
-
const dotenvPath = path2.resolve(process.cwd(), ".env");
|
|
1575
|
-
let encoding = "utf8";
|
|
1576
|
-
const debug = Boolean(options && options.debug);
|
|
1577
|
-
if (options && options.encoding) {
|
|
1578
|
-
encoding = options.encoding;
|
|
1579
|
-
} else {
|
|
1580
|
-
if (debug) {
|
|
1581
|
-
_debug("No encoding is specified. UTF-8 is used by default");
|
|
1582
|
-
}
|
|
1583
|
-
}
|
|
1584
|
-
let optionPaths = [dotenvPath];
|
|
1585
|
-
if (options && options.path) {
|
|
1586
|
-
if (!Array.isArray(options.path)) {
|
|
1587
|
-
optionPaths = [_resolveHome(options.path)];
|
|
1588
|
-
} else {
|
|
1589
|
-
optionPaths = [];
|
|
1590
|
-
for (const filepath of options.path) {
|
|
1591
|
-
optionPaths.push(_resolveHome(filepath));
|
|
1592
|
-
}
|
|
1593
|
-
}
|
|
1594
|
-
}
|
|
1595
|
-
let lastError;
|
|
1596
|
-
const parsedAll = {};
|
|
1597
|
-
for (const path22 of optionPaths) {
|
|
1598
|
-
try {
|
|
1599
|
-
const parsed = DotenvModule.parse(fs2.readFileSync(path22, { encoding }));
|
|
1600
|
-
DotenvModule.populate(parsedAll, parsed, options);
|
|
1601
|
-
} catch (e) {
|
|
1602
|
-
if (debug) {
|
|
1603
|
-
_debug(`Failed to load ${path22} ${e.message}`);
|
|
1604
|
-
}
|
|
1605
|
-
lastError = e;
|
|
1606
|
-
}
|
|
1607
|
-
}
|
|
1608
|
-
let processEnv = process.env;
|
|
1609
|
-
if (options && options.processEnv != null) {
|
|
1610
|
-
processEnv = options.processEnv;
|
|
1611
|
-
}
|
|
1612
|
-
DotenvModule.populate(processEnv, parsedAll, options);
|
|
1613
|
-
if (lastError) {
|
|
1614
|
-
return { parsed: parsedAll, error: lastError };
|
|
1615
|
-
} else {
|
|
1616
|
-
return { parsed: parsedAll };
|
|
1617
|
-
}
|
|
1618
|
-
}
|
|
1619
|
-
function config(options) {
|
|
1620
|
-
if (_dotenvKey(options).length === 0) {
|
|
1621
|
-
return DotenvModule.configDotenv(options);
|
|
1622
|
-
}
|
|
1623
|
-
const vaultPath = _vaultPath(options);
|
|
1624
|
-
if (!vaultPath) {
|
|
1625
|
-
_warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
|
|
1626
|
-
return DotenvModule.configDotenv(options);
|
|
1627
|
-
}
|
|
1628
|
-
return DotenvModule._configVault(options);
|
|
1629
|
-
}
|
|
1630
|
-
function decrypt(encrypted, keyStr) {
|
|
1631
|
-
const key = Buffer.from(keyStr.slice(-64), "hex");
|
|
1632
|
-
let ciphertext = Buffer.from(encrypted, "base64");
|
|
1633
|
-
const nonce = ciphertext.subarray(0, 12);
|
|
1634
|
-
const authTag = ciphertext.subarray(-16);
|
|
1635
|
-
ciphertext = ciphertext.subarray(12, -16);
|
|
1636
|
-
try {
|
|
1637
|
-
const aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce);
|
|
1638
|
-
aesgcm.setAuthTag(authTag);
|
|
1639
|
-
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
|
|
1640
|
-
} catch (error) {
|
|
1641
|
-
const isRange = error instanceof RangeError;
|
|
1642
|
-
const invalidKeyLength = error.message === "Invalid key length";
|
|
1643
|
-
const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
|
|
1644
|
-
if (isRange || invalidKeyLength) {
|
|
1645
|
-
const err = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
|
|
1646
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
1647
|
-
throw err;
|
|
1648
|
-
} else if (decryptionFailed) {
|
|
1649
|
-
const err = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
|
|
1650
|
-
err.code = "DECRYPTION_FAILED";
|
|
1651
|
-
throw err;
|
|
1652
|
-
} else {
|
|
1653
|
-
throw error;
|
|
1654
|
-
}
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
function populate(processEnv, parsed, options = {}) {
|
|
1658
|
-
const debug = Boolean(options && options.debug);
|
|
1659
|
-
const override = Boolean(options && options.override);
|
|
1660
|
-
if (typeof parsed !== "object") {
|
|
1661
|
-
const err = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
|
|
1662
|
-
err.code = "OBJECT_REQUIRED";
|
|
1663
|
-
throw err;
|
|
1664
|
-
}
|
|
1665
|
-
for (const key of Object.keys(parsed)) {
|
|
1666
|
-
if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
|
|
1667
|
-
if (override === true) {
|
|
1668
|
-
processEnv[key] = parsed[key];
|
|
1669
|
-
}
|
|
1670
|
-
if (debug) {
|
|
1671
|
-
if (override === true) {
|
|
1672
|
-
_debug(`"${key}" is already defined and WAS overwritten`);
|
|
1673
|
-
} else {
|
|
1674
|
-
_debug(`"${key}" is already defined and was NOT overwritten`);
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
} else {
|
|
1678
|
-
processEnv[key] = parsed[key];
|
|
1679
|
-
}
|
|
1680
|
-
}
|
|
1681
|
-
}
|
|
1682
|
-
const DotenvModule = {
|
|
1683
|
-
configDotenv,
|
|
1684
|
-
_configVault,
|
|
1685
|
-
_parseVault,
|
|
1686
|
-
config,
|
|
1687
|
-
decrypt,
|
|
1688
|
-
parse,
|
|
1689
|
-
populate
|
|
1690
|
-
};
|
|
1691
|
-
main.exports.configDotenv = DotenvModule.configDotenv;
|
|
1692
|
-
main.exports._configVault = DotenvModule._configVault;
|
|
1693
|
-
main.exports._parseVault = DotenvModule._parseVault;
|
|
1694
|
-
main.exports.config = DotenvModule.config;
|
|
1695
|
-
main.exports.decrypt = DotenvModule.decrypt;
|
|
1696
|
-
main.exports.parse = DotenvModule.parse;
|
|
1697
|
-
main.exports.populate = DotenvModule.populate;
|
|
1698
|
-
main.exports = DotenvModule;
|
|
1699
|
-
return main.exports;
|
|
1700
|
-
}
|
|
1701
|
-
var mainExports = requireMain();
|
|
1702
1427
|
var LogFileType = /* @__PURE__ */ ((LogFileType2) => {
|
|
1703
1428
|
LogFileType2["INSTALLER"] = "backend-installer.log";
|
|
1704
1429
|
LogFileType2["BACKEND"] = "backend-service.log";
|
|
@@ -1715,9 +1440,9 @@ class Logger {
|
|
|
1715
1440
|
*/
|
|
1716
1441
|
constructor() {
|
|
1717
1442
|
if (process.platform === "win32") {
|
|
1718
|
-
this.logPath = path.join(electron.app.getPath("userData"), "logs");
|
|
1443
|
+
this.logPath = path$1.join(electron.app.getPath("userData"), "logs");
|
|
1719
1444
|
} else if (process.platform === "darwin") {
|
|
1720
|
-
this.logPath = path.join(
|
|
1445
|
+
this.logPath = path$1.join(
|
|
1721
1446
|
electron.app.getPath("home"),
|
|
1722
1447
|
"Library",
|
|
1723
1448
|
"Application Support",
|
|
@@ -1725,7 +1450,7 @@ class Logger {
|
|
|
1725
1450
|
"logs"
|
|
1726
1451
|
);
|
|
1727
1452
|
} else {
|
|
1728
|
-
this.logPath = path.join(
|
|
1453
|
+
this.logPath = path$1.join(
|
|
1729
1454
|
electron.app.getPath("home"),
|
|
1730
1455
|
".config",
|
|
1731
1456
|
"local-operator",
|
|
@@ -1738,7 +1463,7 @@ class Logger {
|
|
|
1738
1463
|
this.loggers = /* @__PURE__ */ new Map();
|
|
1739
1464
|
for (const logFileType of Object.values(LogFileType)) {
|
|
1740
1465
|
const logger2 = electronLog.create(`logger-${logFileType}`);
|
|
1741
|
-
logger2.transports.file.resolvePath = () => path.join(this.logPath, logFileType);
|
|
1466
|
+
logger2.transports.file.resolvePath = () => path$1.join(this.logPath, logFileType);
|
|
1742
1467
|
logger2.transports.file.level = "debug";
|
|
1743
1468
|
logger2.transports.file.format = "[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}] {text}";
|
|
1744
1469
|
logger2.transports.file.maxSize = 10 * 1024 * 1024;
|
|
@@ -1852,8 +1577,8 @@ class Logger {
|
|
|
1852
1577
|
}
|
|
1853
1578
|
}
|
|
1854
1579
|
const logger = Logger.getInstance();
|
|
1855
|
-
const envResult =
|
|
1856
|
-
path: path.join(process.cwd(), ".env"),
|
|
1580
|
+
const envResult = dotenv.config({
|
|
1581
|
+
path: path$1.join(process.cwd(), ".env"),
|
|
1857
1582
|
override: true
|
|
1858
1583
|
});
|
|
1859
1584
|
if (envResult.error) {
|
|
@@ -2042,9 +1767,9 @@ class BackendServiceManager {
|
|
|
2042
1767
|
);
|
|
2043
1768
|
}
|
|
2044
1769
|
if (process.platform === "win32") {
|
|
2045
|
-
this.venvPath = path.join(this.appDataPath, "local-operator-venv");
|
|
1770
|
+
this.venvPath = path$1.join(this.appDataPath, "local-operator-venv");
|
|
2046
1771
|
} else if (process.platform === "darwin") {
|
|
2047
|
-
this.venvPath = path.join(
|
|
1772
|
+
this.venvPath = path$1.join(
|
|
2048
1773
|
electron.app.getPath("home"),
|
|
2049
1774
|
"Library",
|
|
2050
1775
|
"Application Support",
|
|
@@ -2052,7 +1777,7 @@ class BackendServiceManager {
|
|
|
2052
1777
|
"local-operator-venv"
|
|
2053
1778
|
);
|
|
2054
1779
|
} else {
|
|
2055
|
-
this.venvPath = path.join(
|
|
1780
|
+
this.venvPath = path$1.join(
|
|
2056
1781
|
electron.app.getPath("home"),
|
|
2057
1782
|
".config",
|
|
2058
1783
|
"local-operator",
|
|
@@ -2135,10 +1860,10 @@ class BackendServiceManager {
|
|
|
2135
1860
|
async loadMacOSEnvironment() {
|
|
2136
1861
|
const home = os.homedir();
|
|
2137
1862
|
const possibleFiles = [
|
|
2138
|
-
path.join(home, ".zshrc"),
|
|
2139
|
-
path.join(home, ".bash_profile"),
|
|
2140
|
-
path.join(home, ".bashrc"),
|
|
2141
|
-
path.join(home, ".profile")
|
|
1863
|
+
path$1.join(home, ".zshrc"),
|
|
1864
|
+
path$1.join(home, ".bash_profile"),
|
|
1865
|
+
path$1.join(home, ".bashrc"),
|
|
1866
|
+
path$1.join(home, ".profile")
|
|
2142
1867
|
];
|
|
2143
1868
|
let shellConfigFile = null;
|
|
2144
1869
|
for (const file of possibleFiles) {
|
|
@@ -2185,9 +1910,9 @@ class BackendServiceManager {
|
|
|
2185
1910
|
async loadLinuxEnvironment() {
|
|
2186
1911
|
const home = os.homedir();
|
|
2187
1912
|
const possibleFiles = [
|
|
2188
|
-
path.join(home, ".bashrc"),
|
|
2189
|
-
path.join(home, ".zshrc"),
|
|
2190
|
-
path.join(home, ".profile")
|
|
1913
|
+
path$1.join(home, ".bashrc"),
|
|
1914
|
+
path$1.join(home, ".zshrc"),
|
|
1915
|
+
path$1.join(home, ".profile")
|
|
2191
1916
|
];
|
|
2192
1917
|
let shellConfigFile = null;
|
|
2193
1918
|
for (const file of possibleFiles) {
|
|
@@ -2243,9 +1968,9 @@ class BackendServiceManager {
|
|
|
2243
1968
|
}
|
|
2244
1969
|
}
|
|
2245
1970
|
const userProfile = process.env.USERPROFILE || os.homedir();
|
|
2246
|
-
const pyenvDir = path.join(userProfile, ".pyenv");
|
|
2247
|
-
const pyenvBinPath = path.join(pyenvDir, "pyenv-win", "bin");
|
|
2248
|
-
const pyenvShimsPath = path.join(pyenvDir, "pyenv-win", "shims");
|
|
1971
|
+
const pyenvDir = path$1.join(userProfile, ".pyenv");
|
|
1972
|
+
const pyenvBinPath = path$1.join(pyenvDir, "pyenv-win", "bin");
|
|
1973
|
+
const pyenvShimsPath = path$1.join(pyenvDir, "pyenv-win", "shims");
|
|
2249
1974
|
if (fs.existsSync(pyenvBinPath) && fs.existsSync(pyenvShimsPath)) {
|
|
2250
1975
|
logger.info(
|
|
2251
1976
|
`Found pyenv-win directories at ${pyenvBinPath} and ${pyenvShimsPath}`,
|
|
@@ -2258,7 +1983,7 @@ class BackendServiceManager {
|
|
|
2258
1983
|
if (!currentPath.includes(pyenvShimsPath)) {
|
|
2259
1984
|
this.shellEnv.PATH = `${pyenvShimsPath};${this.shellEnv.PATH}`;
|
|
2260
1985
|
}
|
|
2261
|
-
const pyenvWinPath = path.join(pyenvDir, "pyenv-win");
|
|
1986
|
+
const pyenvWinPath = path$1.join(pyenvDir, "pyenv-win");
|
|
2262
1987
|
this.shellEnv.PYENV = pyenvWinPath;
|
|
2263
1988
|
this.shellEnv.PYENV_HOME = pyenvWinPath;
|
|
2264
1989
|
logger.info(
|
|
@@ -2271,7 +1996,7 @@ class BackendServiceManager {
|
|
|
2271
1996
|
LogFileType.BACKEND
|
|
2272
1997
|
);
|
|
2273
1998
|
}
|
|
2274
|
-
const venvScriptsPath = path.join(this.venvPath, "Scripts");
|
|
1999
|
+
const venvScriptsPath = path$1.join(this.venvPath, "Scripts");
|
|
2275
2000
|
if (fs.existsSync(venvScriptsPath)) {
|
|
2276
2001
|
const currentPath = this.shellEnv.PATH || "";
|
|
2277
2002
|
if (!currentPath.includes(venvScriptsPath)) {
|
|
@@ -2460,7 +2185,7 @@ class BackendServiceManager {
|
|
|
2460
2185
|
let cmd;
|
|
2461
2186
|
let args;
|
|
2462
2187
|
if (process.platform === "win32") {
|
|
2463
|
-
const localOperatorExe = path.join(
|
|
2188
|
+
const localOperatorExe = path$1.join(
|
|
2464
2189
|
this.venvPath,
|
|
2465
2190
|
"Scripts",
|
|
2466
2191
|
"local-operator.exe"
|
|
@@ -2469,7 +2194,7 @@ class BackendServiceManager {
|
|
|
2469
2194
|
cmd = localOperatorExe;
|
|
2470
2195
|
args = ["serve", "--port", this.port.toString()];
|
|
2471
2196
|
} else {
|
|
2472
|
-
const pythonExe = path.join(this.venvPath, "Scripts", "python.exe");
|
|
2197
|
+
const pythonExe = path$1.join(this.venvPath, "Scripts", "python.exe");
|
|
2473
2198
|
if (fs.existsSync(pythonExe)) {
|
|
2474
2199
|
cmd = pythonExe;
|
|
2475
2200
|
args = [
|
|
@@ -2480,7 +2205,7 @@ class BackendServiceManager {
|
|
|
2480
2205
|
this.port.toString()
|
|
2481
2206
|
];
|
|
2482
2207
|
} else {
|
|
2483
|
-
const activateScript = path.join(
|
|
2208
|
+
const activateScript = path$1.join(
|
|
2484
2209
|
this.venvPath,
|
|
2485
2210
|
"Scripts",
|
|
2486
2211
|
"Activate.ps1"
|
|
@@ -2495,7 +2220,7 @@ class BackendServiceManager {
|
|
|
2495
2220
|
}
|
|
2496
2221
|
}
|
|
2497
2222
|
} else {
|
|
2498
|
-
const activateScript = path.join(this.venvPath, "bin", "activate");
|
|
2223
|
+
const activateScript = path$1.join(this.venvPath, "bin", "activate");
|
|
2499
2224
|
cmd = "bash";
|
|
2500
2225
|
args = [
|
|
2501
2226
|
"-c",
|
|
@@ -3565,9 +3290,9 @@ class BackendInstaller {
|
|
|
3565
3290
|
*/
|
|
3566
3291
|
constructor() {
|
|
3567
3292
|
if (process.platform === "win32") {
|
|
3568
|
-
this.venvPath = path.join(this.appDataPath, "local-operator-venv");
|
|
3293
|
+
this.venvPath = path$1.join(this.appDataPath, "local-operator-venv");
|
|
3569
3294
|
} else if (process.platform === "darwin") {
|
|
3570
|
-
this.venvPath = path.join(
|
|
3295
|
+
this.venvPath = path$1.join(
|
|
3571
3296
|
electron.app.getPath("home"),
|
|
3572
3297
|
"Library",
|
|
3573
3298
|
"Application Support",
|
|
@@ -3575,14 +3300,14 @@ class BackendInstaller {
|
|
|
3575
3300
|
"local-operator-venv"
|
|
3576
3301
|
);
|
|
3577
3302
|
} else {
|
|
3578
|
-
this.venvPath = path.join(
|
|
3303
|
+
this.venvPath = path$1.join(
|
|
3579
3304
|
electron.app.getPath("home"),
|
|
3580
3305
|
".config",
|
|
3581
3306
|
"local-operator",
|
|
3582
3307
|
"local-operator-venv"
|
|
3583
3308
|
);
|
|
3584
3309
|
}
|
|
3585
|
-
this.resourcesPath = process.env.NODE_ENV === "development" ? path.join(process.cwd(), "resources") : path.join(process.resourcesPath);
|
|
3310
|
+
this.resourcesPath = process.env.NODE_ENV === "development" ? path$1.join(process.cwd(), "resources") : path$1.join(process.resourcesPath);
|
|
3586
3311
|
if (electron.app.isPackaged) {
|
|
3587
3312
|
const seal = sealPythonInterpreterTrees(
|
|
3588
3313
|
bundledPythonTreePaths(process.resourcesPath)
|
|
@@ -3613,31 +3338,31 @@ class BackendInstaller {
|
|
|
3613
3338
|
const possibilities = [];
|
|
3614
3339
|
if (process.arch === "arm64") {
|
|
3615
3340
|
possibilities.push(
|
|
3616
|
-
path.join(process.resourcesPath, "python_aarch64", "bin", "python3"),
|
|
3341
|
+
path$1.join(process.resourcesPath, "python_aarch64", "bin", "python3"),
|
|
3617
3342
|
// Packaged app (aarch64)
|
|
3618
|
-
path.join(process.cwd(), "resources", "python_aarch64", "bin", "python3")
|
|
3343
|
+
path$1.join(process.cwd(), "resources", "python_aarch64", "bin", "python3")
|
|
3619
3344
|
// Development (aarch64)
|
|
3620
3345
|
);
|
|
3621
3346
|
} else if (process.arch === "x64") {
|
|
3622
3347
|
possibilities.push(
|
|
3623
|
-
path.join(process.resourcesPath, "python", "bin", "python3"),
|
|
3348
|
+
path$1.join(process.resourcesPath, "python", "bin", "python3"),
|
|
3624
3349
|
// Packaged app (x86_64)
|
|
3625
|
-
path.join(process.cwd(), "resources", "python", "bin", "python3")
|
|
3350
|
+
path$1.join(process.cwd(), "resources", "python", "bin", "python3")
|
|
3626
3351
|
// Development (x86_64)
|
|
3627
3352
|
);
|
|
3628
3353
|
}
|
|
3629
3354
|
if (process.platform === "win32") {
|
|
3630
3355
|
const userProfile = process.env.USERPROFILE || electron.app.getPath("home");
|
|
3631
|
-
const pyenvDir = path.join(userProfile, ".pyenv");
|
|
3356
|
+
const pyenvDir = path$1.join(userProfile, ".pyenv");
|
|
3632
3357
|
possibilities.push(
|
|
3633
3358
|
// In packaged app (Windows)
|
|
3634
|
-
path.join(process.resourcesPath, "python", "python.exe"),
|
|
3359
|
+
path$1.join(process.resourcesPath, "python", "python.exe"),
|
|
3635
3360
|
// In development (Windows)
|
|
3636
|
-
path.join(process.cwd(), "resources", "python", "python.exe"),
|
|
3361
|
+
path$1.join(process.cwd(), "resources", "python", "python.exe"),
|
|
3637
3362
|
// Check for pyenv-win Python
|
|
3638
|
-
path.join(pyenvDir, "pyenv-win", "versions", "3.12.0", "python.exe"),
|
|
3363
|
+
path$1.join(pyenvDir, "pyenv-win", "versions", "3.12.0", "python.exe"),
|
|
3639
3364
|
// Check for pyenv-win shims
|
|
3640
|
-
path.join(pyenvDir, "pyenv-win", "shims", "python.exe")
|
|
3365
|
+
path$1.join(pyenvDir, "pyenv-win", "shims", "python.exe")
|
|
3641
3366
|
);
|
|
3642
3367
|
}
|
|
3643
3368
|
for (const path2 of possibilities) {
|
|
@@ -3667,7 +3392,7 @@ class BackendInstaller {
|
|
|
3667
3392
|
}
|
|
3668
3393
|
let localOperatorPath;
|
|
3669
3394
|
if (process.platform === "win32") {
|
|
3670
|
-
localOperatorPath = path.join(
|
|
3395
|
+
localOperatorPath = path$1.join(
|
|
3671
3396
|
this.venvPath,
|
|
3672
3397
|
"Scripts",
|
|
3673
3398
|
"local-operator.exe"
|
|
@@ -3680,7 +3405,7 @@ class BackendInstaller {
|
|
|
3680
3405
|
return false;
|
|
3681
3406
|
}
|
|
3682
3407
|
} else {
|
|
3683
|
-
localOperatorPath = path.join(this.venvPath, "bin", "local-operator");
|
|
3408
|
+
localOperatorPath = path$1.join(this.venvPath, "bin", "local-operator");
|
|
3684
3409
|
if (!fs.existsSync(localOperatorPath)) {
|
|
3685
3410
|
logger.info(
|
|
3686
3411
|
`local-operator executable not found at ${localOperatorPath}`,
|
|
@@ -3729,18 +3454,18 @@ class BackendInstaller {
|
|
|
3729
3454
|
let args;
|
|
3730
3455
|
const tempDir = os.tmpdir();
|
|
3731
3456
|
if (process.platform === "win32") {
|
|
3732
|
-
scriptPath = path.join(tempDir, "install-backend-windows.ps1");
|
|
3457
|
+
scriptPath = path$1.join(tempDir, "install-backend-windows.ps1");
|
|
3733
3458
|
fs.writeFileSync(scriptPath, windowsInstallScript);
|
|
3734
3459
|
cmd = "powershell.exe";
|
|
3735
3460
|
args = ["-ExecutionPolicy", "Bypass", "-File", scriptPath];
|
|
3736
3461
|
} else if (process.platform === "darwin") {
|
|
3737
|
-
scriptPath = path.join(tempDir, "install-backend-macos.sh");
|
|
3462
|
+
scriptPath = path$1.join(tempDir, "install-backend-macos.sh");
|
|
3738
3463
|
fs.writeFileSync(scriptPath, macosInstallScript);
|
|
3739
3464
|
cmd = "bash";
|
|
3740
3465
|
args = [scriptPath];
|
|
3741
3466
|
fs.chmodSync(scriptPath, "755");
|
|
3742
3467
|
} else {
|
|
3743
|
-
scriptPath = path.join(tempDir, "install-backend-linux.sh");
|
|
3468
|
+
scriptPath = path$1.join(tempDir, "install-backend-linux.sh");
|
|
3744
3469
|
fs.writeFileSync(scriptPath, linuxInstallScript);
|
|
3745
3470
|
cmd = "bash";
|
|
3746
3471
|
args = [scriptPath];
|
|
@@ -3768,7 +3493,7 @@ class BackendInstaller {
|
|
|
3768
3493
|
moves with it. */
|
|
3769
3494
|
backgroundColor: "#16130e",
|
|
3770
3495
|
webPreferences: {
|
|
3771
|
-
preload: path.join(__dirname, "../preload/index.js"),
|
|
3496
|
+
preload: path$1.join(__dirname, "../preload/index.js"),
|
|
3772
3497
|
sandbox: false
|
|
3773
3498
|
}
|
|
3774
3499
|
});
|
|
@@ -3777,7 +3502,7 @@ class BackendInstaller {
|
|
|
3777
3502
|
`${process.env.ELECTRON_RENDERER_URL}/installer`
|
|
3778
3503
|
);
|
|
3779
3504
|
} else {
|
|
3780
|
-
progressWindow.loadFile(path.join(__dirname, "../renderer/installer.html"));
|
|
3505
|
+
progressWindow.loadFile(path$1.join(__dirname, "../renderer/installer.html"));
|
|
3781
3506
|
}
|
|
3782
3507
|
progressWindow.setMenuBarVisibility(false);
|
|
3783
3508
|
let installationCancelled = false;
|
|
@@ -3941,7 +3666,7 @@ class BackendInstaller {
|
|
|
3941
3666
|
"Backend installation completed successfully",
|
|
3942
3667
|
LogFileType.INSTALLER
|
|
3943
3668
|
);
|
|
3944
|
-
const localOperatorPath = process.platform === "win32" ? path.join(this.venvPath, "Scripts", "local-operator.exe") : path.join(this.venvPath, "bin", "local-operator");
|
|
3669
|
+
const localOperatorPath = process.platform === "win32" ? path$1.join(this.venvPath, "Scripts", "local-operator.exe") : path$1.join(this.venvPath, "bin", "local-operator");
|
|
3945
3670
|
if (!fs.existsSync(localOperatorPath)) {
|
|
3946
3671
|
logger.error(
|
|
3947
3672
|
`Installation verification failed: ${localOperatorPath} not found`,
|
|
@@ -3975,7 +3700,7 @@ class BackendInstaller {
|
|
|
3975
3700
|
}
|
|
3976
3701
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
3977
3702
|
if (process.platform === "win32") {
|
|
3978
|
-
const transcriptPath = path.join(
|
|
3703
|
+
const transcriptPath = path$1.join(
|
|
3979
3704
|
this.appDataPath,
|
|
3980
3705
|
"backend-install-shell.log"
|
|
3981
3706
|
);
|
|
@@ -4055,6 +3780,13 @@ function guardForegroundReceipts(window, send) {
|
|
|
4055
3780
|
return send(input);
|
|
4056
3781
|
};
|
|
4057
3782
|
}
|
|
3783
|
+
function relayedBytes(value) {
|
|
3784
|
+
if (value instanceof ArrayBuffer) return new Uint8Array(value);
|
|
3785
|
+
if (!(value instanceof Uint8Array)) return null;
|
|
3786
|
+
const { buffer, byteOffset, byteLength } = value;
|
|
3787
|
+
if (!(buffer instanceof ArrayBuffer)) return null;
|
|
3788
|
+
return new Uint8Array(buffer, byteOffset, byteLength);
|
|
3789
|
+
}
|
|
4058
3790
|
function registerDesktopIPC(window, expectedUrl, request, streams, media, notifier) {
|
|
4059
3791
|
const opened = /* @__PURE__ */ new Map();
|
|
4060
3792
|
function authorize(event) {
|
|
@@ -4091,7 +3823,7 @@ function registerDesktopIPC(window, expectedUrl, request, streams, media, notifi
|
|
|
4091
3823
|
if (media) {
|
|
4092
3824
|
electron.ipcMain.handle("desktop-media", (event, input, bytes) => {
|
|
4093
3825
|
authorize(event);
|
|
4094
|
-
const payload =
|
|
3826
|
+
const payload = relayedBytes(bytes);
|
|
4095
3827
|
return media(input, payload);
|
|
4096
3828
|
});
|
|
4097
3829
|
}
|
|
@@ -4341,9 +4073,9 @@ class DesktopNotifier {
|
|
|
4341
4073
|
* reading of the backend, so an older probe still in flight must not settle
|
|
4342
4074
|
* on top of it.
|
|
4343
4075
|
*/
|
|
4344
|
-
setNotificationContract(
|
|
4076
|
+
setNotificationContract(version) {
|
|
4345
4077
|
this.contractGeneration++;
|
|
4346
|
-
this.applyNotificationContract(
|
|
4078
|
+
this.applyNotificationContract(version);
|
|
4347
4079
|
this.contractAnswered = true;
|
|
4348
4080
|
}
|
|
4349
4081
|
/**
|
|
@@ -4352,8 +4084,8 @@ class DesktopNotifier {
|
|
|
4352
4084
|
* That invariant is the fix for R2-1, so a third caller that resets the
|
|
4353
4085
|
* value without answering re-opens it.
|
|
4354
4086
|
*/
|
|
4355
|
-
applyNotificationContract(
|
|
4356
|
-
this.notificationContract = typeof
|
|
4087
|
+
applyNotificationContract(version) {
|
|
4088
|
+
this.notificationContract = typeof version === "number" && Number.isFinite(version) && version > 0 ? version : 0;
|
|
4357
4089
|
}
|
|
4358
4090
|
/**
|
|
4359
4091
|
* Renderer heartbeat. Forwarded to the backend as the watch lease for the
|
|
@@ -4610,6 +4342,21 @@ class DesktopNotifier {
|
|
|
4610
4342
|
notification.show();
|
|
4611
4343
|
}
|
|
4612
4344
|
}
|
|
4345
|
+
const lastPickedDirectory = /* @__PURE__ */ new Map();
|
|
4346
|
+
function withRememberedDirectory(kind, options, fallbackDirectory) {
|
|
4347
|
+
if (options.defaultPath) return options;
|
|
4348
|
+
const remembered = lastPickedDirectory.get(kind);
|
|
4349
|
+
if (remembered && fs.existsSync(remembered)) {
|
|
4350
|
+
return { ...options, defaultPath: remembered };
|
|
4351
|
+
}
|
|
4352
|
+
if (remembered) lastPickedDirectory.delete(kind);
|
|
4353
|
+
return { ...options, defaultPath: fallbackDirectory };
|
|
4354
|
+
}
|
|
4355
|
+
function rememberPickedDirectory(kind, filePaths, directoryPicked = false) {
|
|
4356
|
+
const [first] = filePaths;
|
|
4357
|
+
if (!first) return;
|
|
4358
|
+
lastPickedDirectory.set(kind, directoryPicked ? first : path$1.dirname(first));
|
|
4359
|
+
}
|
|
4613
4360
|
const PENDING_INSTALL_MARKER_FILE = "pending-update-install.json";
|
|
4614
4361
|
const INSTALL_DISK_SLACK_BYTES = 256 * 1024 * 1024;
|
|
4615
4362
|
const DOWNLOAD_PAGE_URL = "https://local-operator.com/download";
|
|
@@ -4626,7 +4373,7 @@ const BAD_BUNDLE_MARKERS = [
|
|
|
4626
4373
|
"-67062"
|
|
4627
4374
|
];
|
|
4628
4375
|
function appBundleFromExecutable(execPath) {
|
|
4629
|
-
const marker = `${path.join("Contents", "MacOS")}/`;
|
|
4376
|
+
const marker = `${path$1.join("Contents", "MacOS")}/`;
|
|
4630
4377
|
const index = execPath.lastIndexOf(marker);
|
|
4631
4378
|
if (index <= 0) return null;
|
|
4632
4379
|
return execPath.slice(0, index - 1);
|
|
@@ -4649,10 +4396,10 @@ ${probe.stderr}`.trim();
|
|
|
4649
4396
|
detail: marker ? `${marker}: ${output || "no output"}` : `codesign --verify exited ${probe.exitCode}: ${output || "no output"}`
|
|
4650
4397
|
};
|
|
4651
4398
|
}
|
|
4652
|
-
function installedBundleSealBlock(appBundlePath, detail,
|
|
4399
|
+
function installedBundleSealBlock(appBundlePath, detail, version) {
|
|
4653
4400
|
return {
|
|
4654
4401
|
code: "installed-bundle-not-sealed",
|
|
4655
|
-
message:
|
|
4402
|
+
message: version ? `This install of Local Operator can't be updated in place, so the update to version ${version} was stopped before the app quit.` : "This install of Local Operator can't be updated in place, so the update was stopped before the app quit.",
|
|
4656
4403
|
remedy: {
|
|
4657
4404
|
text: "Quit Local Operator, then download a fresh copy and replace the app in Applications.",
|
|
4658
4405
|
url: DOWNLOAD_PAGE_URL
|
|
@@ -4678,29 +4425,29 @@ function parseSealViolations(output) {
|
|
|
4678
4425
|
}
|
|
4679
4426
|
return violations;
|
|
4680
4427
|
}
|
|
4681
|
-
function canonicalPath(
|
|
4428
|
+
function canonicalPath(path2) {
|
|
4682
4429
|
try {
|
|
4683
|
-
return fs.realpathSync(
|
|
4430
|
+
return fs.realpathSync(path2);
|
|
4684
4431
|
} catch {
|
|
4685
4432
|
try {
|
|
4686
|
-
return path.join(fs.realpathSync(path.dirname(
|
|
4433
|
+
return path$1.join(fs.realpathSync(path$1.dirname(path2)), path$1.basename(path2));
|
|
4687
4434
|
} catch {
|
|
4688
|
-
return
|
|
4435
|
+
return path2;
|
|
4689
4436
|
}
|
|
4690
4437
|
}
|
|
4691
4438
|
}
|
|
4692
4439
|
const BUNDLED_PYTHON_DIRS = ["python", "python_aarch64"];
|
|
4693
4440
|
function isPythonBytecodePath(bundlePath, candidate) {
|
|
4694
4441
|
const bundle = canonicalPath(bundlePath);
|
|
4695
|
-
const
|
|
4442
|
+
const path2 = canonicalPath(candidate);
|
|
4696
4443
|
const dirs = BUNDLED_PYTHON_DIRS.map(
|
|
4697
|
-
(name) => path.join(bundle, "Contents", "Resources", name)
|
|
4444
|
+
(name) => path$1.join(bundle, "Contents", "Resources", name)
|
|
4698
4445
|
);
|
|
4699
4446
|
const separator = "/";
|
|
4700
|
-
if (!
|
|
4701
|
-
const segments =
|
|
4447
|
+
if (!path2.endsWith(".pyc")) return false;
|
|
4448
|
+
const segments = path2.split(separator);
|
|
4702
4449
|
if (!segments.includes("__pycache__")) return false;
|
|
4703
|
-
return dirs.some((dir) =>
|
|
4450
|
+
return dirs.some((dir) => path2.startsWith(`${dir}${separator}`));
|
|
4704
4451
|
}
|
|
4705
4452
|
function planPythonBytecodeHeal(bundlePath, violations) {
|
|
4706
4453
|
const added = violations.filter((violation) => violation.kind === "added");
|
|
@@ -4766,8 +4513,8 @@ function healPythonBytecode(bundlePath, violations, remove = (path2) => fs.rmSyn
|
|
|
4766
4513
|
return { ...plan, removed };
|
|
4767
4514
|
}
|
|
4768
4515
|
function metadataBasenames(filePath, updatePath) {
|
|
4769
|
-
const names = [path.basename(filePath)];
|
|
4770
|
-
if (updatePath) names.push(path.basename(updatePath));
|
|
4516
|
+
const names = [path$1.basename(filePath)];
|
|
4517
|
+
if (updatePath) names.push(path$1.basename(updatePath));
|
|
4771
4518
|
return names;
|
|
4772
4519
|
}
|
|
4773
4520
|
function matchArtifactMetadata(filePath, files, updatePath) {
|
|
@@ -4779,7 +4526,7 @@ function matchArtifactMetadata(filePath, files, updatePath) {
|
|
|
4779
4526
|
url = decodeURIComponent(url);
|
|
4780
4527
|
} catch {
|
|
4781
4528
|
}
|
|
4782
|
-
if (path.basename(url) === name) return file;
|
|
4529
|
+
if (path$1.basename(url) === name) return file;
|
|
4783
4530
|
}
|
|
4784
4531
|
}
|
|
4785
4532
|
return null;
|
|
@@ -4796,7 +4543,7 @@ function measureDirectoryBytes(root) {
|
|
|
4796
4543
|
if (!stats.isDirectory()) return stats.size;
|
|
4797
4544
|
let total = 0;
|
|
4798
4545
|
for (const entry of fs.readdirSync(root)) {
|
|
4799
|
-
const child = path.join(root, entry);
|
|
4546
|
+
const child = path$1.join(root, entry);
|
|
4800
4547
|
let childStats;
|
|
4801
4548
|
try {
|
|
4802
4549
|
childStats = fs.lstatSync(child);
|
|
@@ -4815,18 +4562,18 @@ function measureDirectoryBytes(root) {
|
|
|
4815
4562
|
return null;
|
|
4816
4563
|
}
|
|
4817
4564
|
}
|
|
4818
|
-
function versionClause(
|
|
4819
|
-
return
|
|
4565
|
+
function versionClause(version) {
|
|
4566
|
+
return version ? ` to version ${version}` : "";
|
|
4820
4567
|
}
|
|
4821
4568
|
function verifyStagedArtifact(input) {
|
|
4822
|
-
const name = path.basename(input.filePath);
|
|
4823
|
-
const
|
|
4569
|
+
const name = path$1.basename(input.filePath);
|
|
4570
|
+
const version = input.version ?? null;
|
|
4824
4571
|
if (input.metadata == null) {
|
|
4825
4572
|
return {
|
|
4826
4573
|
ok: false,
|
|
4827
4574
|
block: {
|
|
4828
4575
|
code: "artifact-metadata-missing",
|
|
4829
|
-
message: `The downloaded update${versionClause(
|
|
4576
|
+
message: `The downloaded update${versionClause(version)} isn't listed in the release metadata, so it wasn't installed.`,
|
|
4830
4577
|
remedy: {
|
|
4831
4578
|
text: "Check for updates again to re-download the release."
|
|
4832
4579
|
},
|
|
@@ -4840,7 +4587,7 @@ function verifyStagedArtifact(input) {
|
|
|
4840
4587
|
ok: false,
|
|
4841
4588
|
block: {
|
|
4842
4589
|
code: "download-verification-failed",
|
|
4843
|
-
message: `The downloaded update${versionClause(
|
|
4590
|
+
message: `The downloaded update${versionClause(version)} doesn't match the published release, so it wasn't installed.`,
|
|
4844
4591
|
remedy: {
|
|
4845
4592
|
text: "Check for updates again to re-download the release."
|
|
4846
4593
|
},
|
|
@@ -4854,7 +4601,7 @@ function verifyStagedArtifact(input) {
|
|
|
4854
4601
|
ok: false,
|
|
4855
4602
|
block: {
|
|
4856
4603
|
code: "download-verification-failed",
|
|
4857
|
-
message: `The downloaded update${versionClause(
|
|
4604
|
+
message: `The downloaded update${versionClause(version)} doesn't match the published release, so it wasn't installed.`,
|
|
4858
4605
|
remedy: {
|
|
4859
4606
|
text: "Check for updates again to re-download the release."
|
|
4860
4607
|
},
|
|
@@ -4873,7 +4620,7 @@ function verifyStagedArtifact(input) {
|
|
|
4873
4620
|
ok: false,
|
|
4874
4621
|
block: {
|
|
4875
4622
|
code: "insufficient-disk-space",
|
|
4876
|
-
message: `There isn't enough free disk space to install the update${versionClause(
|
|
4623
|
+
message: `There isn't enough free disk space to install the update${versionClause(version)}, so it wasn't installed.`,
|
|
4877
4624
|
remedy: {
|
|
4878
4625
|
text: `Free up about ${formatGiB(needed - input.freeBytes)}, then check for updates again.`
|
|
4879
4626
|
},
|
|
@@ -4893,12 +4640,12 @@ function resolveStagedArtifactPath(input) {
|
|
|
4893
4640
|
const entries = input.listDir(input.pendingDir);
|
|
4894
4641
|
for (const name of input.candidateNames) {
|
|
4895
4642
|
const match = entries.find((entry) => entry === name);
|
|
4896
|
-
if (match) return path.join(input.pendingDir, match);
|
|
4643
|
+
if (match) return path$1.join(input.pendingDir, match);
|
|
4897
4644
|
}
|
|
4898
4645
|
return null;
|
|
4899
4646
|
}
|
|
4900
4647
|
function pendingInstallMarkerPath(dir) {
|
|
4901
|
-
return path.join(dir, PENDING_INSTALL_MARKER_FILE);
|
|
4648
|
+
return path$1.join(dir, PENDING_INSTALL_MARKER_FILE);
|
|
4902
4649
|
}
|
|
4903
4650
|
function writePendingInstallMarker(dir, marker) {
|
|
4904
4651
|
fs.mkdirSync(dir, { recursive: true });
|
|
@@ -4942,7 +4689,7 @@ function clearPendingInstallMarker(dir) {
|
|
|
4942
4689
|
}
|
|
4943
4690
|
const LAST_INSTALL_ATTEMPT_FILE = "last-update-install.json";
|
|
4944
4691
|
function lastInstallAttemptPath(dir) {
|
|
4945
|
-
return path.join(dir, LAST_INSTALL_ATTEMPT_FILE);
|
|
4692
|
+
return path$1.join(dir, LAST_INSTALL_ATTEMPT_FILE);
|
|
4946
4693
|
}
|
|
4947
4694
|
function readLastInstallAttempt(dir) {
|
|
4948
4695
|
const path2 = lastInstallAttemptPath(dir);
|
|
@@ -5029,7 +4776,7 @@ function shipItJobLabel(bundleId) {
|
|
|
5029
4776
|
return `${bundleId}.ShipIt`;
|
|
5030
4777
|
}
|
|
5031
4778
|
function shipItCacheDir(cacheRoot, bundleId) {
|
|
5032
|
-
return path.join(cacheRoot, shipItJobLabel(bundleId));
|
|
4779
|
+
return path$1.join(cacheRoot, shipItJobLabel(bundleId));
|
|
5033
4780
|
}
|
|
5034
4781
|
function watchdogSwapTarget(input) {
|
|
5035
4782
|
if (!input.target) return null;
|
|
@@ -5319,7 +5066,7 @@ function reapFailedInstall(input) {
|
|
|
5319
5066
|
if (!input.exists(cacheDir)) return result;
|
|
5320
5067
|
for (const entry of input.listDir(cacheDir)) {
|
|
5321
5068
|
if (!entry.startsWith("update.")) continue;
|
|
5322
|
-
const staging = path.join(cacheDir, entry);
|
|
5069
|
+
const staging = path$1.join(cacheDir, entry);
|
|
5323
5070
|
try {
|
|
5324
5071
|
input.removeDir(staging);
|
|
5325
5072
|
result.removedStaging.push(staging);
|
|
@@ -5352,14 +5099,14 @@ const LOCAL_OPERATOR_DIST_INFO = /^local[-_]operator[-_]/;
|
|
|
5352
5099
|
function resolveDistributionMarkers(prefix) {
|
|
5353
5100
|
const sitePackages = [];
|
|
5354
5101
|
try {
|
|
5355
|
-
for (const entry of fs.readdirSync(path.join(prefix, "lib"))) {
|
|
5102
|
+
for (const entry of fs.readdirSync(path$1.join(prefix, "lib"))) {
|
|
5356
5103
|
if (!PYTHON_LIB_DIR.test(entry)) continue;
|
|
5357
|
-
const candidate = path.join(prefix, "lib", entry, "site-packages");
|
|
5104
|
+
const candidate = path$1.join(prefix, "lib", entry, "site-packages");
|
|
5358
5105
|
if (fs.existsSync(candidate)) sitePackages.push(candidate);
|
|
5359
5106
|
}
|
|
5360
5107
|
} catch {
|
|
5361
5108
|
}
|
|
5362
|
-
const windowsSitePackages = path.join(prefix, "Lib", "site-packages");
|
|
5109
|
+
const windowsSitePackages = path$1.join(prefix, "Lib", "site-packages");
|
|
5363
5110
|
if (fs.existsSync(windowsSitePackages)) sitePackages.push(windowsSitePackages);
|
|
5364
5111
|
let installer = null;
|
|
5365
5112
|
let editable = false;
|
|
@@ -5373,15 +5120,15 @@ function resolveDistributionMarkers(prefix) {
|
|
|
5373
5120
|
for (const entry of entries) {
|
|
5374
5121
|
if (!LOCAL_OPERATOR_DIST_INFO.test(entry)) continue;
|
|
5375
5122
|
if (!entry.endsWith(".dist-info")) continue;
|
|
5376
|
-
const distInfo = path.join(dir, entry);
|
|
5123
|
+
const distInfo = path$1.join(dir, entry);
|
|
5377
5124
|
try {
|
|
5378
|
-
const installerText = fs.readFileSync(path.join(distInfo, "INSTALLER"), "utf8");
|
|
5125
|
+
const installerText = fs.readFileSync(path$1.join(distInfo, "INSTALLER"), "utf8");
|
|
5379
5126
|
installer = installerText.trim().toLowerCase() || installer;
|
|
5380
5127
|
} catch {
|
|
5381
5128
|
}
|
|
5382
5129
|
try {
|
|
5383
5130
|
const payload = JSON.parse(
|
|
5384
|
-
fs.readFileSync(path.join(distInfo, "direct_url.json"), "utf8")
|
|
5131
|
+
fs.readFileSync(path$1.join(distInfo, "direct_url.json"), "utf8")
|
|
5385
5132
|
);
|
|
5386
5133
|
if (payload.editable === true || payload.dir_info?.editable === true) {
|
|
5387
5134
|
editable = true;
|
|
@@ -5401,11 +5148,11 @@ function commandSearchDirs(env, home) {
|
|
|
5401
5148
|
if (trimmed.length === 0 || dirs.includes(trimmed)) return;
|
|
5402
5149
|
dirs.push(trimmed);
|
|
5403
5150
|
};
|
|
5404
|
-
for (const dir of (env.PATH ?? "").split(path.delimiter)) add(dir);
|
|
5151
|
+
for (const dir of (env.PATH ?? "").split(path$1.delimiter)) add(dir);
|
|
5405
5152
|
add(env.UV_TOOL_BIN_DIR);
|
|
5406
5153
|
add(env.XDG_BIN_HOME);
|
|
5407
|
-
if (env.XDG_DATA_HOME) add(path.join(env.XDG_DATA_HOME, "..", "bin"));
|
|
5408
|
-
add(path.join(home, ".local", "bin"));
|
|
5154
|
+
if (env.XDG_DATA_HOME) add(path$1.join(env.XDG_DATA_HOME, "..", "bin"));
|
|
5155
|
+
add(path$1.join(home, ".local", "bin"));
|
|
5409
5156
|
add("/opt/homebrew/bin");
|
|
5410
5157
|
add("/usr/local/bin");
|
|
5411
5158
|
add("/usr/bin");
|
|
@@ -5413,12 +5160,12 @@ function commandSearchDirs(env, home) {
|
|
|
5413
5160
|
return dirs;
|
|
5414
5161
|
}
|
|
5415
5162
|
function uvToolBinDirs(env, home, listDir, platform) {
|
|
5416
|
-
const root = env.UV_TOOL_DIR ?? (env.XDG_DATA_HOME ? path.join(env.XDG_DATA_HOME, "uv", "tools") : path.join(home, ".local", "share", "uv", "tools"));
|
|
5163
|
+
const root = env.UV_TOOL_DIR ?? (env.XDG_DATA_HOME ? path$1.join(env.XDG_DATA_HOME, "uv", "tools") : path$1.join(home, ".local", "share", "uv", "tools"));
|
|
5417
5164
|
const scriptDir = platform === "win32" ? "Scripts" : "bin";
|
|
5418
5165
|
const dirs = [];
|
|
5419
5166
|
try {
|
|
5420
5167
|
for (const entry of listDir(root)) {
|
|
5421
|
-
dirs.push(path.join(root, entry, scriptDir));
|
|
5168
|
+
dirs.push(path$1.join(root, entry, scriptDir));
|
|
5422
5169
|
}
|
|
5423
5170
|
} catch {
|
|
5424
5171
|
}
|
|
@@ -5437,10 +5184,10 @@ function windowsCommandExtensions(env) {
|
|
|
5437
5184
|
return extensions;
|
|
5438
5185
|
}
|
|
5439
5186
|
function commandCandidates(dir, name, env, platform) {
|
|
5440
|
-
const candidates = [path.join(dir, name)];
|
|
5187
|
+
const candidates = [path$1.join(dir, name)];
|
|
5441
5188
|
if (platform !== "win32") return candidates;
|
|
5442
5189
|
for (const extension of windowsCommandExtensions(env)) {
|
|
5443
|
-
candidates.push(path.join(dir, name + extension));
|
|
5190
|
+
candidates.push(path$1.join(dir, name + extension));
|
|
5444
5191
|
}
|
|
5445
5192
|
return candidates;
|
|
5446
5193
|
}
|
|
@@ -5486,15 +5233,15 @@ function readInstallIdentity(shimPath) {
|
|
|
5486
5233
|
shebang = null;
|
|
5487
5234
|
}
|
|
5488
5235
|
const executable = realPath ?? shimPath;
|
|
5489
|
-
const prefix = path.dirname(path.dirname(executable));
|
|
5236
|
+
const prefix = path$1.dirname(path$1.dirname(executable));
|
|
5490
5237
|
const existing = (candidate) => fs.existsSync(candidate) ? candidate : null;
|
|
5491
5238
|
const markers = resolveDistributionMarkers(prefix);
|
|
5492
5239
|
return {
|
|
5493
5240
|
path: shimPath,
|
|
5494
5241
|
realPath,
|
|
5495
5242
|
shebang,
|
|
5496
|
-
uvReceipt: existing(path.join(prefix, "uv-receipt.toml")),
|
|
5497
|
-
venvPrefix: fs.existsSync(path.join(prefix, "pyvenv.cfg")) ? prefix : null,
|
|
5243
|
+
uvReceipt: existing(path$1.join(prefix, "uv-receipt.toml")),
|
|
5244
|
+
venvPrefix: fs.existsSync(path$1.join(prefix, "pyvenv.cfg")) ? prefix : null,
|
|
5498
5245
|
installer: markers.installer,
|
|
5499
5246
|
editable: markers.editable
|
|
5500
5247
|
};
|
|
@@ -5586,8 +5333,8 @@ const PIP_SHOW_VERSION_REGEX = /^Version:\s*(.+)$/m;
|
|
|
5586
5333
|
function parsePipShowVersion(stdout) {
|
|
5587
5334
|
const match = stdout.match(PIP_SHOW_VERSION_REGEX);
|
|
5588
5335
|
if (!match) return null;
|
|
5589
|
-
const
|
|
5590
|
-
return
|
|
5336
|
+
const version = match[1].trim();
|
|
5337
|
+
return version.length > 0 ? version : null;
|
|
5591
5338
|
}
|
|
5592
5339
|
function didUpgradeLand(input) {
|
|
5593
5340
|
const { before, after, target: target2 } = input;
|
|
@@ -5603,8 +5350,8 @@ const BETA_VERSION_REGEX = /v\d+\.\d+\.\d+\.beta\.\d+/;
|
|
|
5603
5350
|
const BUNDLE_ID_REGEX = /^[\w.-]+$/;
|
|
5604
5351
|
const LAUNCHCTL_NOT_LOADED_REGEX = /could not find|no such process/i;
|
|
5605
5352
|
const SEAL_PROBE_TIMEOUT_MS = 45e3;
|
|
5606
|
-
function versionSuffix(
|
|
5607
|
-
return
|
|
5353
|
+
function versionSuffix(version) {
|
|
5354
|
+
return version ? ` to version ${version}` : "";
|
|
5608
5355
|
}
|
|
5609
5356
|
function runCommand(command, args, options = {}) {
|
|
5610
5357
|
return new Promise((resolve) => {
|
|
@@ -5781,14 +5528,14 @@ class UpdateService {
|
|
|
5781
5528
|
* forgets, and the whole point of these checks is that the user gets an
|
|
5782
5529
|
* explanation instead of an app that quits and never returns.
|
|
5783
5530
|
*/
|
|
5784
|
-
sendInstallBlock(block,
|
|
5531
|
+
sendInstallBlock(block, version) {
|
|
5785
5532
|
logger.error(
|
|
5786
5533
|
`Update refused (${block.code}): ${block.detail}`,
|
|
5787
5534
|
LogFileType.UPDATE_SERVICE
|
|
5788
5535
|
);
|
|
5789
5536
|
this.sendToRenderer("update-install-blocked", {
|
|
5790
5537
|
code: block.code,
|
|
5791
|
-
version:
|
|
5538
|
+
version: version ?? null,
|
|
5792
5539
|
message: block.message,
|
|
5793
5540
|
remedy: block.remedy,
|
|
5794
5541
|
detail: block.detail
|
|
@@ -5867,7 +5614,7 @@ class UpdateService {
|
|
|
5867
5614
|
if (!bundlePath) return null;
|
|
5868
5615
|
const value = readCommandOutput("/usr/bin/defaults", [
|
|
5869
5616
|
"read",
|
|
5870
|
-
path.join(bundlePath, "Contents", "Info.plist"),
|
|
5617
|
+
path$1.join(bundlePath, "Contents", "Info.plist"),
|
|
5871
5618
|
"CFBundleIdentifier"
|
|
5872
5619
|
]);
|
|
5873
5620
|
return value && BUNDLE_ID_REGEX.test(value) ? value : null;
|
|
@@ -5889,8 +5636,8 @@ class UpdateService {
|
|
|
5889
5636
|
shipItLog() {
|
|
5890
5637
|
const bundleId = this.bundleIdentifier();
|
|
5891
5638
|
if (!bundleId) return null;
|
|
5892
|
-
const candidate = path.join(
|
|
5893
|
-
shipItCacheDir(path.join(os.homedir(), "Library", "Caches"), bundleId),
|
|
5639
|
+
const candidate = path$1.join(
|
|
5640
|
+
shipItCacheDir(path$1.join(os.homedir(), "Library", "Caches"), bundleId),
|
|
5894
5641
|
"ShipIt_stderr.log"
|
|
5895
5642
|
);
|
|
5896
5643
|
return fs.existsSync(candidate) ? candidate : null;
|
|
@@ -5912,7 +5659,7 @@ class UpdateService {
|
|
|
5912
5659
|
try {
|
|
5913
5660
|
const result = reapFailedInstall({
|
|
5914
5661
|
bundleId: this.bundleIdentifier(),
|
|
5915
|
-
cacheRoot: path.join(os.homedir(), "Library", "Caches"),
|
|
5662
|
+
cacheRoot: path$1.join(os.homedir(), "Library", "Caches"),
|
|
5916
5663
|
removeJob: (label) => {
|
|
5917
5664
|
const result2 = node_child_process.spawnSync("/bin/launchctl", ["remove", label], {
|
|
5918
5665
|
encoding: "utf8",
|
|
@@ -6040,7 +5787,7 @@ class UpdateService {
|
|
|
6040
5787
|
* those files restores the seal (measured; see `healPythonBytecode`), where a
|
|
6041
5788
|
* bundle broken any other way still gets the reinstall refusal below.
|
|
6042
5789
|
*/
|
|
6043
|
-
async probeInstalledBundleSeal(
|
|
5790
|
+
async probeInstalledBundleSeal(version) {
|
|
6044
5791
|
if (process.platform !== "darwin" || !electron.app.isPackaged) return null;
|
|
6045
5792
|
const bundlePath = appBundleFromExecutable(process.execPath);
|
|
6046
5793
|
if (!bundlePath) {
|
|
@@ -6090,7 +5837,7 @@ class UpdateService {
|
|
|
6090
5837
|
`Installed bundle is not healable in place: ${heal.reason}`,
|
|
6091
5838
|
LogFileType.UPDATE_SERVICE
|
|
6092
5839
|
);
|
|
6093
|
-
return installedBundleSealBlock(bundlePath, seal.detail,
|
|
5840
|
+
return installedBundleSealBlock(bundlePath, seal.detail, version);
|
|
6094
5841
|
}
|
|
6095
5842
|
logger.info(
|
|
6096
5843
|
`Removed ${heal.removed.length} bytecode file(s) our own interpreter had written into the sealed bundle: ${heal.reason}. Paths:
|
|
@@ -6109,17 +5856,17 @@ ${heal.removed.join("\n")}`,
|
|
|
6109
5856
|
`Installed bundle still fails its seal check after healing: ${healed.detail}`,
|
|
6110
5857
|
LogFileType.UPDATE_SERVICE
|
|
6111
5858
|
);
|
|
6112
|
-
return installedBundleSealBlock(bundlePath, healed.detail,
|
|
5859
|
+
return installedBundleSealBlock(bundlePath, healed.detail, version);
|
|
6113
5860
|
}
|
|
6114
5861
|
/** File names the updater's metadata knows this update by. */
|
|
6115
5862
|
stagedArtifactCandidates(info) {
|
|
6116
5863
|
const names = /* @__PURE__ */ new Set();
|
|
6117
|
-
if (info?.path) names.add(path.basename(info.path));
|
|
5864
|
+
if (info?.path) names.add(path$1.basename(info.path));
|
|
6118
5865
|
for (const file of info?.files ?? []) {
|
|
6119
|
-
if (file.url) names.add(path.basename(decodeURIComponent(file.url)));
|
|
5866
|
+
if (file.url) names.add(path$1.basename(decodeURIComponent(file.url)));
|
|
6120
5867
|
}
|
|
6121
5868
|
if (this.downloadedArtifactPath) {
|
|
6122
|
-
names.add(path.basename(this.downloadedArtifactPath));
|
|
5869
|
+
names.add(path$1.basename(this.downloadedArtifactPath));
|
|
6123
5870
|
}
|
|
6124
5871
|
return [...names];
|
|
6125
5872
|
}
|
|
@@ -6268,7 +6015,7 @@ ${heal.removed.join("\n")}`,
|
|
|
6268
6015
|
if (!bundlePath) return null;
|
|
6269
6016
|
const plan = buildWatchdogPlan({
|
|
6270
6017
|
appBundlePath: bundlePath,
|
|
6271
|
-
executableName: path.basename(process.execPath),
|
|
6018
|
+
executableName: path$1.basename(process.execPath),
|
|
6272
6019
|
// The app's own pid, captured here - before the quit - because the
|
|
6273
6020
|
// watchdog cannot ask a name about its own ancestor (review R1).
|
|
6274
6021
|
appPid: process.pid,
|
|
@@ -6931,12 +6678,12 @@ ${heal.removed.join("\n")}`,
|
|
|
6931
6678
|
const { stdout } = await execAsync("pip show local-operator");
|
|
6932
6679
|
const match = stdout.match(VERSION_LINE_REGEX);
|
|
6933
6680
|
if (match) {
|
|
6934
|
-
const
|
|
6681
|
+
const version = match[1].trim();
|
|
6935
6682
|
logger.info(
|
|
6936
|
-
`Backend version from pip: ${
|
|
6683
|
+
`Backend version from pip: ${version}`,
|
|
6937
6684
|
LogFileType.UPDATE_SERVICE
|
|
6938
6685
|
);
|
|
6939
|
-
return
|
|
6686
|
+
return version;
|
|
6940
6687
|
}
|
|
6941
6688
|
} catch (pipError) {
|
|
6942
6689
|
logger.error(
|
|
@@ -7263,10 +7010,10 @@ ${heal.removed.join("\n")}`,
|
|
|
7263
7010
|
const deadline = Date.now() + timeoutMs;
|
|
7264
7011
|
let last = null;
|
|
7265
7012
|
while (Date.now() < deadline) {
|
|
7266
|
-
const
|
|
7267
|
-
if (
|
|
7268
|
-
last =
|
|
7269
|
-
if (target2 == null ||
|
|
7013
|
+
const version = await this.getInstalledBackendVersion();
|
|
7014
|
+
if (version && version !== "Unknown") {
|
|
7015
|
+
last = version;
|
|
7016
|
+
if (target2 == null || version === target2) return version;
|
|
7270
7017
|
}
|
|
7271
7018
|
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
7272
7019
|
}
|
|
@@ -7355,7 +7102,7 @@ ${heal.removed.join("\n")}`,
|
|
|
7355
7102
|
if (venvPath && electron.app.isPackaged) {
|
|
7356
7103
|
const venvBinDir = process.platform === "win32" ? "Scripts" : "bin";
|
|
7357
7104
|
const pythonName = process.platform === "win32" ? "python.exe" : "python3";
|
|
7358
|
-
pythonPath = path.join(venvPath, venvBinDir, pythonName);
|
|
7105
|
+
pythonPath = path$1.join(venvPath, venvBinDir, pythonName);
|
|
7359
7106
|
}
|
|
7360
7107
|
if (!pythonPath || !fs.existsSync(pythonPath)) {
|
|
7361
7108
|
logger.error(
|
|
@@ -7754,6 +7501,9 @@ const posthogClient = new posthogNode.PostHog(backendConfig.VITE_PUBLIC_POSTHOG_
|
|
|
7754
7501
|
host: backendConfig.VITE_PUBLIC_POSTHOG_HOST,
|
|
7755
7502
|
enableExceptionAutocapture: true
|
|
7756
7503
|
});
|
|
7504
|
+
function pickerFallbackDirectory() {
|
|
7505
|
+
return electron.app.getPath("home");
|
|
7506
|
+
}
|
|
7757
7507
|
function createApplicationMenu() {
|
|
7758
7508
|
const isDev = Boolean(process.env.ELECTRON_RENDERER_URL);
|
|
7759
7509
|
const zoomInHandler = () => {
|
|
@@ -7907,7 +7657,7 @@ function createWindow() {
|
|
|
7907
7657
|
title: "Local Operator",
|
|
7908
7658
|
icon,
|
|
7909
7659
|
webPreferences: {
|
|
7910
|
-
preload: path.join(__dirname, "../preload/index.js"),
|
|
7660
|
+
preload: path$1.join(__dirname, "../preload/index.js"),
|
|
7911
7661
|
sandbox: false,
|
|
7912
7662
|
// Only enable devTools when running with 'pnpm dev'
|
|
7913
7663
|
// Disable for 'pnpm start' and production builds
|
|
@@ -7978,7 +7728,7 @@ function createWindow() {
|
|
|
7978
7728
|
if (isTrustedAuthDomain) {
|
|
7979
7729
|
return {
|
|
7980
7730
|
action: "allow",
|
|
7981
|
-
|
|
7731
|
+
overrideBrowserWindowOptions: {
|
|
7982
7732
|
width: 800,
|
|
7983
7733
|
height: 700,
|
|
7984
7734
|
// Increased height for better visibility
|
|
@@ -8009,7 +7759,7 @@ function createWindow() {
|
|
|
8009
7759
|
if (utils.is.dev && process.env.ELECTRON_RENDERER_URL) {
|
|
8010
7760
|
mainWindow2.loadURL(process.env.ELECTRON_RENDERER_URL);
|
|
8011
7761
|
} else {
|
|
8012
|
-
mainWindow2.loadFile(path.join(__dirname, "../renderer/index.html"));
|
|
7762
|
+
mainWindow2.loadFile(path$1.join(__dirname, "../renderer/index.html"));
|
|
8013
7763
|
}
|
|
8014
7764
|
return mainWindow2;
|
|
8015
7765
|
}
|
|
@@ -8089,7 +7839,7 @@ electron.app.whenReady().then(async () => {
|
|
|
8089
7839
|
});
|
|
8090
7840
|
registerDesktopIPC(
|
|
8091
7841
|
() => mainWindow,
|
|
8092
|
-
process.env.ELECTRON_RENDERER_URL || node_url.pathToFileURL(path.join(__dirname, "../renderer/index.html")).href,
|
|
7842
|
+
process.env.ELECTRON_RENDERER_URL || node_url.pathToFileURL(path$1.join(__dirname, "../renderer/index.html")).href,
|
|
8093
7843
|
sendDesktop,
|
|
8094
7844
|
() => backendService.getStreamRelay(),
|
|
8095
7845
|
(input, bytes) => backendService.requestDesktopMedia(input, bytes),
|
|
@@ -8106,7 +7856,7 @@ electron.app.whenReady().then(async () => {
|
|
|
8106
7856
|
"read-file",
|
|
8107
7857
|
async (_, filePath, encoding = "utf-8") => {
|
|
8108
7858
|
try {
|
|
8109
|
-
const normalizedPath = filePath.startsWith("~/") ? path.join(electron.app.getPath("home"), filePath.slice(2)) : filePath;
|
|
7859
|
+
const normalizedPath = filePath.startsWith("~/") ? path$1.join(electron.app.getPath("home"), filePath.slice(2)) : filePath;
|
|
8110
7860
|
const data = fs.readFileSync(normalizedPath, encoding);
|
|
8111
7861
|
return { success: true, data };
|
|
8112
7862
|
} catch (error) {
|
|
@@ -8133,7 +7883,7 @@ electron.app.whenReady().then(async () => {
|
|
|
8133
7883
|
"save-file",
|
|
8134
7884
|
async (_, filePath, content, encoding = "utf-8") => {
|
|
8135
7885
|
try {
|
|
8136
|
-
const normalizedPath = filePath.startsWith("~/") ? path.join(electron.app.getPath("home"), filePath.slice(2)) : filePath;
|
|
7886
|
+
const normalizedPath = filePath.startsWith("~/") ? path$1.join(electron.app.getPath("home"), filePath.slice(2)) : filePath;
|
|
8137
7887
|
fs.writeFileSync(normalizedPath, content, encoding);
|
|
8138
7888
|
} catch (error) {
|
|
8139
7889
|
logger.error("Error saving file:", LogFileType.BACKEND, error);
|
|
@@ -8142,12 +7892,12 @@ electron.app.whenReady().then(async () => {
|
|
|
8142
7892
|
}
|
|
8143
7893
|
);
|
|
8144
7894
|
electron.ipcMain.handle("file-exists", async (_, filePath) => {
|
|
8145
|
-
const normalizedPath = filePath.startsWith("~/") ? path.join(electron.app.getPath("home"), filePath.slice(2)) : filePath;
|
|
7895
|
+
const normalizedPath = filePath.startsWith("~/") ? path$1.join(electron.app.getPath("home"), filePath.slice(2)) : filePath;
|
|
8146
7896
|
return fs.existsSync(normalizedPath);
|
|
8147
7897
|
});
|
|
8148
7898
|
electron.ipcMain.handle("directory-exists", async (_, dirPath) => {
|
|
8149
7899
|
const home = electron.app.getPath("home");
|
|
8150
|
-
const normalizedPath = dirPath === "~" ? home : dirPath.startsWith("~/") ? path.join(home, dirPath.slice(2)) : dirPath;
|
|
7900
|
+
const normalizedPath = dirPath === "~" ? home : dirPath.startsWith("~/") ? path$1.join(home, dirPath.slice(2)) : dirPath;
|
|
8151
7901
|
try {
|
|
8152
7902
|
return fs.statSync(normalizedPath, { throwIfNoEntry: false })?.isDirectory() ?? false;
|
|
8153
7903
|
} catch {
|
|
@@ -8162,7 +7912,16 @@ electron.app.whenReady().then(async () => {
|
|
|
8162
7912
|
);
|
|
8163
7913
|
return { canceled: true, filePaths: [] };
|
|
8164
7914
|
}
|
|
8165
|
-
|
|
7915
|
+
const result = await electron.dialog.showOpenDialog(
|
|
7916
|
+
mainWindow,
|
|
7917
|
+
withRememberedDirectory(
|
|
7918
|
+
"open-file",
|
|
7919
|
+
options,
|
|
7920
|
+
pickerFallbackDirectory()
|
|
7921
|
+
)
|
|
7922
|
+
);
|
|
7923
|
+
rememberPickedDirectory("open-file", result.filePaths);
|
|
7924
|
+
return result;
|
|
8166
7925
|
});
|
|
8167
7926
|
electron.ipcMain.handle("select-directory", async () => {
|
|
8168
7927
|
if (!mainWindow) {
|
|
@@ -8172,13 +7931,22 @@ electron.app.whenReady().then(async () => {
|
|
|
8172
7931
|
);
|
|
8173
7932
|
return void 0;
|
|
8174
7933
|
}
|
|
8175
|
-
const
|
|
7934
|
+
const directoryOptions = {
|
|
8176
7935
|
properties: ["openDirectory"],
|
|
8177
7936
|
title: "Select Working Directory",
|
|
8178
7937
|
// More appropriate title
|
|
8179
7938
|
buttonLabel: "Select Folder"
|
|
8180
7939
|
// Correct button label
|
|
8181
|
-
}
|
|
7940
|
+
};
|
|
7941
|
+
const result = await electron.dialog.showOpenDialog(
|
|
7942
|
+
mainWindow,
|
|
7943
|
+
withRememberedDirectory(
|
|
7944
|
+
"select-directory",
|
|
7945
|
+
directoryOptions,
|
|
7946
|
+
pickerFallbackDirectory()
|
|
7947
|
+
)
|
|
7948
|
+
);
|
|
7949
|
+
rememberPickedDirectory("select-directory", result.filePaths, true);
|
|
8182
7950
|
if (!result.canceled && result.filePaths.length > 0) {
|
|
8183
7951
|
return result.filePaths[0];
|
|
8184
7952
|
}
|
|
@@ -8192,11 +7960,20 @@ electron.app.whenReady().then(async () => {
|
|
|
8192
7960
|
);
|
|
8193
7961
|
return void 0;
|
|
8194
7962
|
}
|
|
8195
|
-
const
|
|
7963
|
+
const fileOptions = {
|
|
8196
7964
|
properties: ["openFile"],
|
|
8197
7965
|
title: "Select File",
|
|
8198
7966
|
buttonLabel: "Open"
|
|
8199
|
-
}
|
|
7967
|
+
};
|
|
7968
|
+
const result = await electron.dialog.showOpenDialog(
|
|
7969
|
+
mainWindow,
|
|
7970
|
+
withRememberedDirectory(
|
|
7971
|
+
"select-file",
|
|
7972
|
+
fileOptions,
|
|
7973
|
+
pickerFallbackDirectory()
|
|
7974
|
+
)
|
|
7975
|
+
);
|
|
7976
|
+
rememberPickedDirectory("select-file", result.filePaths);
|
|
8200
7977
|
if (!result.canceled && result.filePaths.length > 0) {
|
|
8201
7978
|
const filePath = result.filePaths[0];
|
|
8202
7979
|
try {
|