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.
Files changed (69) hide show
  1. package/bin/ensure-electron.js +47 -0
  2. package/bin/linux-sandbox.js +27 -18
  3. package/bin/postinstall.js +55 -33
  4. package/out/main/index.js +194 -417
  5. package/out/renderer/assets/{_basePickBy-C411r4Fr.js → _basePickBy-C7yOlBwG.js} +1 -1
  6. package/out/renderer/assets/{_baseUniq-Bt63j3mu.js → _baseUniq-BxWDXUxR.js} +1 -1
  7. package/out/renderer/assets/{agent-details-page-DujEqAzR.js → agent-details-page-DGusXpiv.js} +1 -1
  8. package/out/renderer/assets/{agent-hub-page-C3kMnXTf.js → agent-hub-page-BEy-xjst.js} +1 -1
  9. package/out/renderer/assets/{agents-page-NEQ4hFtm.js → agents-page-VfOUQ-yP.js} +2 -2
  10. package/out/renderer/assets/{architectureDiagram-IEHRJDOE-BqpmUfyo.js → architectureDiagram-IEHRJDOE-358ZDLa0.js} +1 -1
  11. package/out/renderer/assets/{blockDiagram-JOT3LUYC-CnQwEPXO.js → blockDiagram-JOT3LUYC-tzEHVS4j.js} +1 -1
  12. package/out/renderer/assets/{c4Diagram-VJAJSXHY-Dk_OmMLJ.js → c4Diagram-VJAJSXHY-D3tP-CCo.js} +1 -1
  13. package/out/renderer/assets/channel-D37fF6my.js +1 -0
  14. package/out/renderer/assets/{chunk-4BMEZGHF-BdRWhpmN.js → chunk-4BMEZGHF-BKUSTR_S.js} +1 -1
  15. package/out/renderer/assets/{chunk-A2AXSNBT-yHqgRYdq.js → chunk-A2AXSNBT-DvXPJSTp.js} +1 -1
  16. package/out/renderer/assets/{chunk-AEK57VVT-BanBKJ_s.js → chunk-AEK57VVT-iJyV8fDW.js} +1 -1
  17. package/out/renderer/assets/{chunk-D6G4REZN-CuQN5RTN.js → chunk-D6G4REZN-B3DDJ3MU.js} +1 -1
  18. package/out/renderer/assets/{chunk-RZ5BOZE2-C8fBZeNu.js → chunk-RZ5BOZE2-Dbn_07ZJ.js} +1 -1
  19. package/out/renderer/assets/{chunk-XZIHB7SX-6KNcbSfo.js → chunk-XZIHB7SX-ChdMxZnm.js} +1 -1
  20. package/out/renderer/assets/classDiagram-GIVACNV2-CcnNtrPC.js +1 -0
  21. package/out/renderer/assets/classDiagram-v2-COTLJTTW-CcnNtrPC.js +1 -0
  22. package/out/renderer/assets/clone-DPqLvbSr.js +1 -0
  23. package/out/renderer/assets/{compact-pagination-Ovp_kll1.js → compact-pagination-duvMYksr.js} +1 -1
  24. package/out/renderer/assets/{dagre-OKDRZEBW-DzfvIYmf.js → dagre-OKDRZEBW-BuSM1V0w.js} +1 -1
  25. package/out/renderer/assets/{diagram-SSKATNLV-Bpyw0frR.js → diagram-SSKATNLV-39xt9Mcn.js} +1 -1
  26. package/out/renderer/assets/{diagram-VNBRO52H-r7KETc_A.js → diagram-VNBRO52H-Bgyt_DWD.js} +1 -1
  27. package/out/renderer/assets/{erDiagram-Q7BY3M3F-BBPxCrm9.js → erDiagram-Q7BY3M3F-DNfsSD46.js} +1 -1
  28. package/out/renderer/assets/{flowDiagram-4HSFHLVR-Bqfojzvn.js → flowDiagram-4HSFHLVR-DbS8UHwN.js} +1 -1
  29. package/out/renderer/assets/{ganttDiagram-APWFNJXF-Cd7hVnw4.js → ganttDiagram-APWFNJXF-Dxdp2V-6.js} +1 -1
  30. package/out/renderer/assets/{gitGraphDiagram-7IBYFJ6S-Dxoexd6b.js → gitGraphDiagram-7IBYFJ6S-BLrXJPe3.js} +1 -1
  31. package/out/renderer/assets/{graph-DoZ-YflA.js → graph-Cgkq5xQ7.js} +1 -1
  32. package/out/renderer/assets/{icon-DaedMBiD.css → icon-HSrrv8O-.css} +1 -1
  33. package/out/renderer/assets/{index-s958Ss2_.js → index-C4RcIL0i.js} +1 -1
  34. package/out/renderer/assets/{index-DXDWG455.js → index-CLwRuOtJ.js} +47 -47
  35. package/out/renderer/assets/{index-Bvsuxozx.js → index-lEoaSpWQ.js} +1 -1
  36. package/out/renderer/assets/{infoDiagram-PH2N3AL5-B6Q2kq6y.js → infoDiagram-PH2N3AL5-DR6So_J8.js} +1 -1
  37. package/out/renderer/assets/{installer-poO56j69.js → installer-Ck14_4Oh.js} +1 -1
  38. package/out/renderer/assets/{journeyDiagram-U35MCT3I-YvFhqi_4.js → journeyDiagram-U35MCT3I-DubpieGX.js} +1 -1
  39. package/out/renderer/assets/{kanban-definition-NDS4AKOZ-hUPw4d6Q.js → kanban-definition-NDS4AKOZ-BtwsU2Rg.js} +1 -1
  40. package/out/renderer/assets/{layout-DL79cPuU.js → layout-BDeRPl4h.js} +1 -1
  41. package/out/renderer/assets/{legacy-agents-page-Bc9_mRrf.js → legacy-agents-page-ZyBMetf1.js} +1 -1
  42. package/out/renderer/assets/{mermaid.core-DY-qM3jW.js → mermaid.core-d-O-_a6F.js} +5 -5
  43. package/out/renderer/assets/{mindmap-definition-ALO5MXBD-BIr3BZFI.js → mindmap-definition-ALO5MXBD-BCZdiKEB.js} +1 -1
  44. package/out/renderer/assets/{page-header-zecAylNs.js → page-header-D-uc8qqA.js} +1 -1
  45. package/out/renderer/assets/{parseISO-DLnRjbkm.js → parseISO-PdZfrqAM.js} +1 -1
  46. package/out/renderer/assets/{pieDiagram-IB7DONF6-DEfXQAHX.js → pieDiagram-IB7DONF6-Bd2e7gHe.js} +1 -1
  47. package/out/renderer/assets/{quadrantDiagram-7GDLP6J5-DTbs_0uW.js → quadrantDiagram-7GDLP6J5-oypZsih9.js} +1 -1
  48. package/out/renderer/assets/{radar-MK3ICKWK-YpweuwYm.js → radar-MK3ICKWK-c4YagPOX.js} +1 -1
  49. package/out/renderer/assets/{radient-auth-buttons--VhWRhuh.js → radient-auth-buttons-BUlY7XDi.js} +1 -1
  50. package/out/renderer/assets/{requirementDiagram-KVF5MWMF-DV8bmMki.js → requirementDiagram-KVF5MWMF-7UoAwEus.js} +1 -1
  51. package/out/renderer/assets/{sankeyDiagram-QLVOVGJD-BpZDUCJV.js → sankeyDiagram-QLVOVGJD-JStPMuRd.js} +1 -1
  52. package/out/renderer/assets/{schedules-page-Co1Ixrkk.js → schedules-page-IjBtVuIo.js} +1 -1
  53. package/out/renderer/assets/{sequenceDiagram-X6HHIX6F-B4x4_BhD.js → sequenceDiagram-X6HHIX6F-Lene9gQ-.js} +1 -1
  54. package/out/renderer/assets/{settings-page-yvoJPfPs.js → settings-page-BqJRfztd.js} +1 -1
  55. package/out/renderer/assets/{square-pen-CdJTC74b.js → square-pen-CQEKS3JT.js} +1 -1
  56. package/out/renderer/assets/{stateDiagram-DGXRK772-DHIWQgsa.js → stateDiagram-DGXRK772-umC2tGUK.js} +1 -1
  57. package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-Cp1tcztr.js +1 -0
  58. package/out/renderer/assets/{timeline-definition-BDJGKUSR-rcUcUcdw.js → timeline-definition-BDJGKUSR-h2KfXqek.js} +1 -1
  59. package/out/renderer/assets/{use-agent-like-mutation-_CPevTyx.js → use-agent-like-mutation-BanZ02f7.js} +1 -1
  60. package/out/renderer/assets/{xychartDiagram-VJFVF3MP-CiY7ytjm.js → xychartDiagram-VJFVF3MP-BOH5ZQcH.js} +1 -1
  61. package/out/renderer/index.html +3 -3
  62. package/out/renderer/installer.html +3 -3
  63. package/package.json +69 -58
  64. package/out/renderer/assets/channel-QDS9FjQE.js +0 -1
  65. package/out/renderer/assets/classDiagram-GIVACNV2-CsOBNtuH.js +0 -1
  66. package/out/renderer/assets/classDiagram-v2-COTLJTTW-CsOBNtuH.js +0 -1
  67. package/out/renderer/assets/clone-BmqcgcfO.js +0 -1
  68. package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-CQi1jyLr.js +0 -1
  69. /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 require$$1 = require("path");
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 require$$0 = require("fs");
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 = require$$1.join(__dirname, "../../resources/icon.png");
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 = mainExports.config({
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 = bytes instanceof Uint8Array ? bytes : bytes instanceof ArrayBuffer ? new Uint8Array(bytes) : null;
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(version2) {
4076
+ setNotificationContract(version) {
4345
4077
  this.contractGeneration++;
4346
- this.applyNotificationContract(version2);
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(version2) {
4356
- this.notificationContract = typeof version2 === "number" && Number.isFinite(version2) && version2 > 0 ? version2 : 0;
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, version2) {
4399
+ function installedBundleSealBlock(appBundlePath, detail, version) {
4653
4400
  return {
4654
4401
  code: "installed-bundle-not-sealed",
4655
- message: version2 ? `This install of Local Operator can't be updated in place, so the update to version ${version2} 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.",
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(path$1) {
4428
+ function canonicalPath(path2) {
4682
4429
  try {
4683
- return fs.realpathSync(path$1);
4430
+ return fs.realpathSync(path2);
4684
4431
  } catch {
4685
4432
  try {
4686
- return path.join(fs.realpathSync(path.dirname(path$1)), path.basename(path$1));
4433
+ return path$1.join(fs.realpathSync(path$1.dirname(path2)), path$1.basename(path2));
4687
4434
  } catch {
4688
- return path$1;
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 path$1 = canonicalPath(candidate);
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 (!path$1.endsWith(".pyc")) return false;
4701
- const segments = path$1.split(separator);
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) => path$1.startsWith(`${dir}${separator}`));
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(version2) {
4819
- return version2 ? ` to version ${version2}` : "";
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 version2 = input.version ?? null;
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(version2)} isn't listed in the release metadata, so it wasn't installed.`,
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(version2)} doesn't match the published release, so it wasn't installed.`,
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(version2)} doesn't match the published release, so it wasn't installed.`,
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(version2)}, so it wasn't installed.`,
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 version2 = match[1].trim();
5590
- return version2.length > 0 ? version2 : null;
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(version2) {
5607
- return version2 ? ` to version ${version2}` : "";
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, version2) {
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: version2 ?? null,
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(version2) {
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, version2);
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, version2);
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 version2 = match[1].trim();
6681
+ const version = match[1].trim();
6935
6682
  logger.info(
6936
- `Backend version from pip: ${version2}`,
6683
+ `Backend version from pip: ${version}`,
6937
6684
  LogFileType.UPDATE_SERVICE
6938
6685
  );
6939
- return version2;
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 version2 = await this.getInstalledBackendVersion();
7267
- if (version2 && version2 !== "Unknown") {
7268
- last = version2;
7269
- if (target2 == null || version2 === target2) return version2;
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
- features: {
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
- return electron.dialog.showOpenDialog(mainWindow, options);
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 result = await electron.dialog.showOpenDialog(mainWindow, {
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 result = await electron.dialog.showOpenDialog(mainWindow, {
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 {