@trops/dash-core 0.1.833 → 0.1.834

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.
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var require$$0$2 = require('electron');
4
- var require$$1$2 = require('path');
5
4
  var require$$0$3 = require('fs');
5
+ var require$$1$2 = require('path');
6
6
  var require$$0$4 = require('crypto');
7
7
  var require$$2$1 = require('os');
8
8
  var require$$3$1 = require('adm-zip');
@@ -1320,7 +1320,7 @@ var secureStoreController$1 = {
1320
1320
  decryptString,
1321
1321
  };
1322
1322
 
1323
- const path$t = require$$1$2;
1323
+ const path$r = require$$1$2;
1324
1324
  const {
1325
1325
  readFileSync,
1326
1326
  writeFileSync: writeFileSync$3,
@@ -1338,7 +1338,7 @@ const {
1338
1338
  function ensureDirectoryExistence$1(filePath) {
1339
1339
  try {
1340
1340
  // isDirectory
1341
- var dirname = path$t.dirname(filePath);
1341
+ var dirname = path$r.dirname(filePath);
1342
1342
  // check if the directory exists...return true
1343
1343
  // if not, we can pass in the dirname as the filepath
1344
1344
  // and check each directory recursively.
@@ -1453,7 +1453,7 @@ function removeFilesFromDirectory(directory, excludeFiles = []) {
1453
1453
 
1454
1454
  for (const file of files) {
1455
1455
  if (!excludeFiles.includes(file)) {
1456
- unlinkSync(path$t.join(directory, file), (err) => {
1456
+ unlinkSync(path$r.join(directory, file), (err) => {
1457
1457
  if (err) throw err;
1458
1458
  });
1459
1459
  }
@@ -1470,6 +1470,269 @@ var file = {
1470
1470
  checkDirectory: checkDirectory$1,
1471
1471
  };
1472
1472
 
1473
+ var profileStore$2 = {exports: {}};
1474
+
1475
+ /**
1476
+ * profileStore.js
1477
+ *
1478
+ * The list of profiles for an app and which one is active, kept in
1479
+ * <userData>/Dashboard/<appId>/profiles.json:
1480
+ *
1481
+ * { activeProfileId, profiles: [{ id, name, createdAt }] }
1482
+ *
1483
+ * Until a second profile is created the file doesn't exist and the app
1484
+ * has one profile, Default, whose data stays in Dashboard/<appId>/ exactly
1485
+ * as before profiles existed. Other profiles live in
1486
+ * Dashboard/<appId>/profiles/<id>/.
1487
+ */
1488
+
1489
+ const { app: app$c } = require$$0$2;
1490
+ const path$q = require$$1$2;
1491
+ const fs$m = require$$0$3;
1492
+
1493
+ const appName$2 = "Dashboard";
1494
+ const storeFilename = "profiles.json";
1495
+ const profilesDirname = "profiles";
1496
+
1497
+ const DEFAULT_PROFILE_ID = "default";
1498
+ const DEFAULT_PROFILE_NAME = "Default";
1499
+
1500
+ // Ids we create are "p-<base36>"; only these are ever used in a path.
1501
+ const PROFILE_ID_PATTERN = /^[a-z0-9-]{1,64}$/;
1502
+
1503
+ const cache$3 = new Map();
1504
+
1505
+ function getAppRootDir(appId) {
1506
+ if (!appId || typeof appId !== "string") {
1507
+ throw new Error("profileStore: appId is required");
1508
+ }
1509
+ return path$q.join(app$c.getPath("userData"), appName$2, appId);
1510
+ }
1511
+
1512
+ function getStorePath(appId) {
1513
+ return path$q.join(getAppRootDir(appId), storeFilename);
1514
+ }
1515
+
1516
+ function defaultStore() {
1517
+ return {
1518
+ activeProfileId: DEFAULT_PROFILE_ID,
1519
+ profiles: [{ id: DEFAULT_PROFILE_ID, name: DEFAULT_PROFILE_NAME }],
1520
+ };
1521
+ }
1522
+
1523
+ // A missing or unreadable file means "Default only" — never an error, so
1524
+ // a damaged profiles.json can't hide the user's dashboards.
1525
+ function normalize$1(raw) {
1526
+ const base = defaultStore();
1527
+ if (!raw || !Array.isArray(raw.profiles)) return base;
1528
+ const profiles = raw.profiles.filter(
1529
+ (p) =>
1530
+ p &&
1531
+ typeof p.id === "string" &&
1532
+ PROFILE_ID_PATTERN.test(p.id) &&
1533
+ p.id !== DEFAULT_PROFILE_ID,
1534
+ );
1535
+ const defaultEntry = raw.profiles.find(
1536
+ (p) => p && p.id === DEFAULT_PROFILE_ID,
1537
+ );
1538
+ const all = [{ ...base.profiles[0], ...defaultEntry }, ...profiles];
1539
+ const activeProfileId = all.some((p) => p.id === raw.activeProfileId)
1540
+ ? raw.activeProfileId
1541
+ : DEFAULT_PROFILE_ID;
1542
+ return { activeProfileId, profiles: all };
1543
+ }
1544
+
1545
+ function readStore(appId) {
1546
+ if (cache$3.has(appId)) return cache$3.get(appId);
1547
+ let raw = null;
1548
+ try {
1549
+ raw = JSON.parse(fs$m.readFileSync(getStorePath(appId), "utf8"));
1550
+ } catch (e) {
1551
+ raw = null;
1552
+ }
1553
+ const store = normalize$1(raw);
1554
+ cache$3.set(appId, store);
1555
+ return store;
1556
+ }
1557
+
1558
+ function writeStore(appId, store) {
1559
+ const file = getStorePath(appId);
1560
+ fs$m.mkdirSync(path$q.dirname(file), { recursive: true });
1561
+ fs$m.writeFileSync(file, JSON.stringify(store, null, 2));
1562
+ cache$3.set(appId, store);
1563
+ return store;
1564
+ }
1565
+
1566
+ function sameName(a, b) {
1567
+ return a.trim().toLowerCase() === b.trim().toLowerCase();
1568
+ }
1569
+
1570
+ function cleanName(name) {
1571
+ const trimmed = typeof name === "string" ? name.trim() : "";
1572
+ if (!trimmed) throw new Error("A profile needs a name");
1573
+ if (trimmed.length > 60)
1574
+ throw new Error("Profile names are 60 characters or fewer");
1575
+ return trimmed;
1576
+ }
1577
+
1578
+ function findProfile(store, profileId) {
1579
+ const profile = store.profiles.find((p) => p.id === profileId);
1580
+ if (!profile) throw new Error(`No profile with id ${profileId}`);
1581
+ return profile;
1582
+ }
1583
+
1584
+ function newProfileId(store) {
1585
+ let id;
1586
+ do {
1587
+ id = `p-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`;
1588
+ } while (store.profiles.some((p) => p.id === id));
1589
+ return id;
1590
+ }
1591
+
1592
+ /**
1593
+ * The folder holding a profile's per-profile files. Default keeps the
1594
+ * app folder itself.
1595
+ */
1596
+ function getProfileDir(appId, profileId) {
1597
+ if (profileId === DEFAULT_PROFILE_ID) return getAppRootDir(appId);
1598
+ if (!PROFILE_ID_PATTERN.test(profileId || "")) {
1599
+ throw new Error(`Invalid profile id: ${profileId}`);
1600
+ }
1601
+ return path$q.join(getAppRootDir(appId), profilesDirname, profileId);
1602
+ }
1603
+
1604
+ const profileStore$1 = {
1605
+ list(appId) {
1606
+ return readStore(appId).profiles.map((p) => ({ ...p }));
1607
+ },
1608
+
1609
+ getActiveProfileId(appId) {
1610
+ return readStore(appId).activeProfileId;
1611
+ },
1612
+
1613
+ getActive(appId) {
1614
+ const store = readStore(appId);
1615
+ return { ...findProfile(store, store.activeProfileId) };
1616
+ },
1617
+
1618
+ create(appId, name) {
1619
+ const store = readStore(appId);
1620
+ const clean = cleanName(name);
1621
+ if (store.profiles.some((p) => sameName(p.name, clean))) {
1622
+ throw new Error(`A profile named "${clean}" already exists`);
1623
+ }
1624
+ const profile = {
1625
+ id: newProfileId(store),
1626
+ name: clean,
1627
+ createdAt: new Date().toISOString(),
1628
+ };
1629
+ writeStore(appId, {
1630
+ ...store,
1631
+ profiles: [...store.profiles, profile],
1632
+ });
1633
+ fs$m.mkdirSync(getProfileDir(appId, profile.id), { recursive: true });
1634
+ return { ...profile };
1635
+ },
1636
+
1637
+ rename(appId, profileId, name) {
1638
+ const store = readStore(appId);
1639
+ findProfile(store, profileId);
1640
+ const clean = cleanName(name);
1641
+ if (
1642
+ store.profiles.some((p) => p.id !== profileId && sameName(p.name, clean))
1643
+ ) {
1644
+ throw new Error(`A profile named "${clean}" already exists`);
1645
+ }
1646
+ const profiles = store.profiles.map((p) =>
1647
+ p.id === profileId ? { ...p, name: clean } : p,
1648
+ );
1649
+ writeStore(appId, { ...store, profiles });
1650
+ return { ...profiles.find((p) => p.id === profileId) };
1651
+ },
1652
+
1653
+ /**
1654
+ * Removes a profile and its folder. Default and the active profile
1655
+ * can't be deleted.
1656
+ */
1657
+ remove(appId, profileId) {
1658
+ const store = readStore(appId);
1659
+ findProfile(store, profileId);
1660
+ if (profileId === DEFAULT_PROFILE_ID) {
1661
+ throw new Error("The Default profile can't be deleted");
1662
+ }
1663
+ if (profileId === store.activeProfileId) {
1664
+ throw new Error("Switch to another profile before deleting this one");
1665
+ }
1666
+ writeStore(appId, {
1667
+ ...store,
1668
+ profiles: store.profiles.filter((p) => p.id !== profileId),
1669
+ });
1670
+ fs$m.rmSync(getProfileDir(appId, profileId), {
1671
+ recursive: true,
1672
+ force: true,
1673
+ });
1674
+ return { success: true };
1675
+ },
1676
+
1677
+ setActive(appId, profileId) {
1678
+ const store = readStore(appId);
1679
+ findProfile(store, profileId);
1680
+ writeStore(appId, { ...store, activeProfileId: profileId });
1681
+ return { ...findProfile(store, profileId) };
1682
+ },
1683
+
1684
+ getProfileDir,
1685
+ getAppRootDir,
1686
+
1687
+ // Tests only: forget what was read so the next call reads the disk.
1688
+ _resetCache() {
1689
+ cache$3.clear();
1690
+ },
1691
+ };
1692
+
1693
+ profileStore$2.exports = profileStore$1;
1694
+ profileStore$2.exports.DEFAULT_PROFILE_ID = DEFAULT_PROFILE_ID;
1695
+ profileStore$2.exports.DEFAULT_PROFILE_NAME = DEFAULT_PROFILE_NAME;
1696
+
1697
+ var profileStoreExports = profileStore$2.exports;
1698
+
1699
+ /**
1700
+ * profilePaths.js
1701
+ *
1702
+ * Where the active profile's files live. Controllers for per-profile data
1703
+ * (dashboards, folders, themes, layouts, ratings) build their paths here
1704
+ * instead of joining userData/Dashboard/<appId> themselves, so switching
1705
+ * profile switches every one of them together.
1706
+ *
1707
+ * Shared data (providers, settings, widget data, installed widgets) is
1708
+ * not per profile and keeps its own paths.
1709
+ */
1710
+
1711
+ const path$p = require$$1$2;
1712
+ const profileStore = profileStoreExports;
1713
+
1714
+ /**
1715
+ * @param {string} appId
1716
+ * @param {string} [profileId] defaults to the active profile
1717
+ * @returns {string} the profile's data folder
1718
+ */
1719
+ function getProfileDataDir$1(appId, profileId) {
1720
+ const id = profileId || profileStore.getActiveProfileId(appId);
1721
+ return profileStore.getProfileDir(appId, id);
1722
+ }
1723
+
1724
+ /**
1725
+ * @param {string} appId
1726
+ * @param {string} filename e.g. "workspaces.json"
1727
+ * @param {string} [profileId] defaults to the active profile
1728
+ * @returns {string} the file's path inside the profile's folder
1729
+ */
1730
+ function getProfileFilePath$6(appId, filename, profileId) {
1731
+ return path$p.join(getProfileDataDir$1(appId, profileId), filename);
1732
+ }
1733
+
1734
+ var profilePaths = { getProfileDataDir: getProfileDataDir$1, getProfileFilePath: getProfileFilePath$6 };
1735
+
1473
1736
  /**
1474
1737
  * workspaceEvents.js
1475
1738
  *
@@ -1502,14 +1765,12 @@ function emitWorkspaceDeleted$1(workspaceId) {
1502
1765
 
1503
1766
  var workspaceEvents = { onWorkspaceDeleted: onWorkspaceDeleted$1, emitWorkspaceDeleted: emitWorkspaceDeleted$1 };
1504
1767
 
1505
- const { app: app$g } = require$$0$2;
1506
- const path$s = require$$1$2;
1507
1768
  const { writeFileSync: writeFileSync$2 } = require$$0$3;
1508
1769
  const { getFileContents: getFileContents$7 } = file;
1770
+ const { getProfileFilePath: getProfileFilePath$5 } = profilePaths;
1509
1771
  const { emitWorkspaceDeleted } = workspaceEvents;
1510
1772
 
1511
1773
  const configFilename$5 = "workspaces.json";
1512
- const appName$7 = "Dashboard";
1513
1774
 
1514
1775
  const workspaceController$3 = {
1515
1776
  /**
@@ -1551,12 +1812,7 @@ const workspaceController$3 = {
1551
1812
  saveWorkspaceForApplication: (win, appId, workspaceObject) => {
1552
1813
  try {
1553
1814
  // filename to the pages file (live pages)
1554
- const filename = path$s.join(
1555
- app$g.getPath("userData"),
1556
- appName$7,
1557
- appId,
1558
- configFilename$5,
1559
- );
1815
+ const filename = getProfileFilePath$5(appId, configFilename$5);
1560
1816
  const workspacesArray = getFileContents$7(filename);
1561
1817
 
1562
1818
  // lets check to see if we already have this one!
@@ -1600,12 +1856,7 @@ const workspaceController$3 = {
1600
1856
  saveMenuItemsForApplication: (win, appId, menuItems) => {
1601
1857
  try {
1602
1858
  // filename to the workspaces file
1603
- const filename = path$s.join(
1604
- app$g.getPath("userData"),
1605
- appName$7,
1606
- appId,
1607
- configFilename$5,
1608
- );
1859
+ const filename = getProfileFilePath$5(appId, configFilename$5);
1609
1860
  const workspacesArray = getFileContents$7(filename);
1610
1861
 
1611
1862
  // Update menu items for workspaces
@@ -1649,12 +1900,7 @@ const workspaceController$3 = {
1649
1900
  */
1650
1901
  deleteWorkspaceForApplication: (win, appId, workspaceId) => {
1651
1902
  try {
1652
- const filename = path$s.join(
1653
- app$g.getPath("userData"),
1654
- appName$7,
1655
- appId,
1656
- configFilename$5,
1657
- );
1903
+ const filename = getProfileFilePath$5(appId, configFilename$5);
1658
1904
  const workspacesArray = getFileContents$7(filename);
1659
1905
 
1660
1906
  const filtered = workspacesArray.filter(
@@ -1688,12 +1934,7 @@ const workspaceController$3 = {
1688
1934
 
1689
1935
  listWorkspacesForApplication: (win, appId) => {
1690
1936
  try {
1691
- const filename = path$s.join(
1692
- app$g.getPath("userData"),
1693
- appName$7,
1694
- appId,
1695
- configFilename$5,
1696
- );
1937
+ const filename = getProfileFilePath$5(appId, configFilename$5);
1697
1938
 
1698
1939
  const workspacesArray = getFileContents$7(filename);
1699
1940
  console.log(
@@ -1716,12 +1957,7 @@ const workspaceController$3 = {
1716
1957
 
1717
1958
  listMenuItemsForApplication: (win, appId) => {
1718
1959
  try {
1719
- const filename = path$s.join(
1720
- app$g.getPath("userData"),
1721
- appName$7,
1722
- appId,
1723
- configFilename$5,
1724
- );
1960
+ const filename = getProfileFilePath$5(appId, configFilename$5);
1725
1961
  const workspacesArray = getFileContents$7(filename);
1726
1962
 
1727
1963
  // Extract unique menu items from workspaces
@@ -1760,13 +1996,11 @@ const workspaceController$3 = {
1760
1996
 
1761
1997
  var workspaceController_1 = workspaceController$3;
1762
1998
 
1763
- const { app: app$f } = require$$0$2;
1764
- const path$r = require$$1$2;
1765
1999
  const { writeFileSync: writeFileSync$1 } = require$$0$3;
1766
2000
  const { getFileContents: getFileContents$6 } = file;
2001
+ const { getProfileFilePath: getProfileFilePath$4 } = profilePaths;
1767
2002
 
1768
2003
  const configFilename$4 = "themes.json";
1769
- const appName$6 = "Dashboard";
1770
2004
 
1771
2005
  const themeController$5 = {
1772
2006
  /**
@@ -1781,12 +2015,7 @@ const themeController$5 = {
1781
2015
  saveThemeForApplication: (win, appId, name, obj) => {
1782
2016
  try {
1783
2017
  // filename to the pages file (live pages)
1784
- const filename = path$r.join(
1785
- app$f.getPath("userData"),
1786
- appName$6,
1787
- appId,
1788
- configFilename$4,
1789
- );
2018
+ const filename = getProfileFilePath$4(appId, configFilename$4);
1790
2019
  const data = getFileContents$6(filename, {});
1791
2020
 
1792
2021
  // Add/update the theme based on the name
@@ -1827,12 +2056,7 @@ const themeController$5 = {
1827
2056
  */
1828
2057
  listThemesForApplication: (win, appId) => {
1829
2058
  try {
1830
- const filename = path$r.join(
1831
- app$f.getPath("userData"),
1832
- appName$6,
1833
- appId,
1834
- configFilename$4,
1835
- );
2059
+ const filename = getProfileFilePath$4(appId, configFilename$4);
1836
2060
 
1837
2061
  const data = getFileContents$6(filename, {});
1838
2062
 
@@ -1869,12 +2093,7 @@ const themeController$5 = {
1869
2093
  */
1870
2094
  deleteThemeForApplication: (win, appId, themeKey) => {
1871
2095
  try {
1872
- const filename = path$r.join(
1873
- app$f.getPath("userData"),
1874
- appName$6,
1875
- appId,
1876
- configFilename$4,
1877
- );
2096
+ const filename = getProfileFilePath$4(appId, configFilename$4);
1878
2097
  const data = getFileContents$6(filename, {});
1879
2098
 
1880
2099
  if (themeKey in data) {
@@ -1946,9 +2165,9 @@ var themeController_1 = themeController$5;
1946
2165
  * `/data/`.
1947
2166
  */
1948
2167
 
1949
- const path$q = require$$1$2;
2168
+ const path$o = require$$1$2;
1950
2169
  const fs$l = require$$0$3;
1951
- const { app: app$e } = require$$0$2;
2170
+ const { app: app$b } = require$$0$2;
1952
2171
 
1953
2172
  const APP_NAME = "Dashboard";
1954
2173
 
@@ -1957,10 +2176,10 @@ const APP_NAME = "Dashboard";
1957
2176
  * @returns {string[]} ordered allowed roots for that category
1958
2177
  */
1959
2178
  function getAllowedRoots$2(category) {
1960
- const userData = app$e.getPath("userData");
2179
+ const userData = app$b.getPath("userData");
1961
2180
  switch (category) {
1962
2181
  case "data": {
1963
- const def = path$q.join(userData, APP_NAME, "data");
2182
+ const def = path$o.join(userData, APP_NAME, "data");
1964
2183
  // The user can configure a custom data directory in
1965
2184
  // Settings → General → Data Directory. If set, that
1966
2185
  // location is ALSO an allowed root. We don't replace the
@@ -1970,13 +2189,13 @@ function getAllowedRoots$2(category) {
1970
2189
  return override ? [def, override] : [def];
1971
2190
  }
1972
2191
  case "themes":
1973
- return [path$q.join(userData, APP_NAME, "themes")];
2192
+ return [path$o.join(userData, APP_NAME, "themes")];
1974
2193
  case "widgets":
1975
- return [path$q.join(userData, "widgets")];
2194
+ return [path$o.join(userData, "widgets")];
1976
2195
  case "plugins":
1977
- return [path$q.join(userData, "plugins")];
2196
+ return [path$o.join(userData, "plugins")];
1978
2197
  case "downloads":
1979
- return [app$e.getPath("downloads")];
2198
+ return [app$b.getPath("downloads")];
1980
2199
  default:
1981
2200
  throw new Error("safePath: unknown allowed-roots category: " + category);
1982
2201
  }
@@ -1991,8 +2210,8 @@ function getAllowedRoots$2(category) {
1991
2210
  */
1992
2211
  function readDataDirectoryFromSettings() {
1993
2212
  try {
1994
- const settingsPath = path$q.join(
1995
- app$e.getPath("userData"),
2213
+ const settingsPath = path$o.join(
2214
+ app$b.getPath("userData"),
1996
2215
  APP_NAME,
1997
2216
  "settings.json",
1998
2217
  );
@@ -2023,7 +2242,7 @@ function safePath$4(requested, allowedRoots) {
2023
2242
  throw new Error("safePath: allowedRoots must be a non-empty array");
2024
2243
  }
2025
2244
 
2026
- const resolved = path$q.resolve(requested);
2245
+ const resolved = path$o.resolve(requested);
2027
2246
 
2028
2247
  // Real-path through symlinks. If the file doesn't exist yet (a
2029
2248
  // create-new operation), real-path the parent so a symlink in the
@@ -2033,8 +2252,8 @@ function safePath$4(requested, allowedRoots) {
2033
2252
  real = fs$l.realpathSync(resolved);
2034
2253
  } catch (_e) {
2035
2254
  try {
2036
- const parent = fs$l.realpathSync(path$q.dirname(resolved));
2037
- real = path$q.join(parent, path$q.basename(resolved));
2255
+ const parent = fs$l.realpathSync(path$o.dirname(resolved));
2256
+ real = path$o.join(parent, path$o.basename(resolved));
2038
2257
  } catch (_e2) {
2039
2258
  // Parent doesn't exist either. Use the resolved-but-not-
2040
2259
  // real path; the caller's mkdirSync will happen inside the
@@ -2053,7 +2272,7 @@ function safePath$4(requested, allowedRoots) {
2053
2272
  }
2054
2273
  // Exact match OR strictly-inside (with separator to prevent
2055
2274
  // /data-evil/ matching /data/).
2056
- if (real === realRoot || real.startsWith(realRoot + path$q.sep)) {
2275
+ if (real === realRoot || real.startsWith(realRoot + path$o.sep)) {
2057
2276
  return real;
2058
2277
  }
2059
2278
  }
@@ -2176,8 +2395,8 @@ var fsGrantAttribution = { dataFileOwner, dropMisattributedFsPaths: dropMisattri
2176
2395
  */
2177
2396
 
2178
2397
  const fs$k = require$$0$3;
2179
- const path$p = require$$1$2;
2180
- const { app: app$d } = require$$0$2;
2398
+ const path$n = require$$1$2;
2399
+ const { app: app$a } = require$$0$2;
2181
2400
  const { dropMisattributedFsPaths } = fsGrantAttribution;
2182
2401
 
2183
2402
  const FILE_NAME = "widgetMcpGrants.json";
@@ -2189,7 +2408,7 @@ const FS_CLEANUP_MARK = "widgetMcpGrants.fs-attribution-cleaned";
2189
2408
  let _cache$1 = null;
2190
2409
 
2191
2410
  function grantsFilePath() {
2192
- return path$p.join(app$d.getPath("userData"), FILE_NAME);
2411
+ return path$n.join(app$a.getPath("userData"), FILE_NAME);
2193
2412
  }
2194
2413
 
2195
2414
  function loadFromDisk() {
@@ -2212,7 +2431,7 @@ function loadFromDisk() {
2212
2431
  * failed save leaves the mark unwritten, so the next load tries again.
2213
2432
  */
2214
2433
  function cleanMisattributedOnce(parsed) {
2215
- const mark = path$p.join(path$p.dirname(grantsFilePath()), FS_CLEANUP_MARK);
2434
+ const mark = path$n.join(path$n.dirname(grantsFilePath()), FS_CLEANUP_MARK);
2216
2435
  if (fs$k.existsSync(mark)) return parsed;
2217
2436
  const { grants, removed } = dropMisattributedFsPaths(parsed);
2218
2437
  try {
@@ -2236,7 +2455,7 @@ function writeToDisk(data) {
2236
2455
  const tmp = p + ".tmp";
2237
2456
  // Ensure parent dir exists (userData should already, but be defensive
2238
2457
  // for first-launch / freshly-cleared profile cases).
2239
- fs$k.mkdirSync(path$p.dirname(p), { recursive: true });
2458
+ fs$k.mkdirSync(path$n.dirname(p), { recursive: true });
2240
2459
  fs$k.writeFileSync(tmp, JSON.stringify(data, null, 2), "utf8");
2241
2460
  fs$k.renameSync(tmp, p);
2242
2461
  }
@@ -2998,7 +3217,7 @@ function commonjsRequire(path) {
2998
3217
  */
2999
3218
 
3000
3219
  const fs$j = require$$0$3;
3001
- const path$o = require$$1$2;
3220
+ const path$m = require$$1$2;
3002
3221
  const { builtinModules } = require$$2;
3003
3222
 
3004
3223
  // Provided by the host app via MODULE_MAP in widgetBundleLoader.js — never
@@ -3034,7 +3253,7 @@ const CODE = /\.(?:js|jsx|ts|tsx|mjs|cjs)$/;
3034
3253
  function sourceFiles(dir, rel = "") {
3035
3254
  let entries;
3036
3255
  try {
3037
- entries = fs$j.readdirSync(path$o.join(dir, rel), { withFileTypes: true });
3256
+ entries = fs$j.readdirSync(path$m.join(dir, rel), { withFileTypes: true });
3038
3257
  } catch (_e) {
3039
3258
  return [];
3040
3259
  }
@@ -3106,7 +3325,7 @@ const VALID_NAME = /^(?:@[a-z0-9~-][a-z0-9._~-]*\/)?[a-z0-9~-][a-z0-9._~-]*$/i;
3106
3325
  function findLibraryImports(dir) {
3107
3326
  const found = new Set();
3108
3327
  for (const rel of sourceFiles(dir)) {
3109
- const source = fs$j.readFileSync(path$o.join(dir, rel), "utf8");
3328
+ const source = fs$j.readFileSync(path$m.join(dir, rel), "utf8");
3110
3329
  const code = codeMask(source);
3111
3330
  for (const re of IMPORTS) {
3112
3331
  re.lastIndex = 0;
@@ -3129,7 +3348,7 @@ function findLibraryImports(dir) {
3129
3348
  /** The version of a library installed in one of `paths` (node_modules). */
3130
3349
  function installedVersion(name, paths) {
3131
3350
  for (const p of paths || []) {
3132
- const file = path$o.join(p, ...name.split("/"), "package.json");
3351
+ const file = path$m.join(p, ...name.split("/"), "package.json");
3133
3352
  try {
3134
3353
  const v = JSON.parse(fs$j.readFileSync(file, "utf8")).version;
3135
3354
  if (typeof v === "string" && v) return v;
@@ -3149,7 +3368,7 @@ function libraryDependencies(dir, paths) {
3149
3368
  let listed = {};
3150
3369
  try {
3151
3370
  const pkg = JSON.parse(
3152
- fs$j.readFileSync(path$o.join(dir, "package.json"), "utf8"),
3371
+ fs$j.readFileSync(path$m.join(dir, "package.json"), "utf8"),
3153
3372
  );
3154
3373
  if (pkg && pkg.dependencies && typeof pkg.dependencies === "object") {
3155
3374
  listed = pkg.dependencies;
@@ -3686,7 +3905,7 @@ function requireWidgetLibraries () {
3686
3905
  */
3687
3906
 
3688
3907
  const fs$i = require$$0$3;
3689
- const path$n = require$$1$2;
3908
+ const path$l = require$$1$2;
3690
3909
 
3691
3910
  // Provided by the host app via MODULE_MAP in widgetBundleLoader.js — never
3692
3911
  // bundled (utils/libraryImports.js).
@@ -3705,13 +3924,13 @@ const {
3705
3924
  */
3706
3925
  function hostLibraryPaths(dir = __dirname) {
3707
3926
  const out = [];
3708
- let at = path$n.resolve(dir);
3927
+ let at = path$l.resolve(dir);
3709
3928
  for (;;) {
3710
- if (path$n.basename(at) !== "node_modules") {
3711
- const candidate = path$n.join(at, "node_modules");
3929
+ if (path$l.basename(at) !== "node_modules") {
3930
+ const candidate = path$l.join(at, "node_modules");
3712
3931
  if (fs$i.existsSync(candidate)) out.push(candidate);
3713
3932
  }
3714
- const up = path$n.dirname(at);
3933
+ const up = path$l.dirname(at);
3715
3934
  if (up === at) break;
3716
3935
  at = up;
3717
3936
  }
@@ -3722,8 +3941,8 @@ function hostLibraryPaths(dir = __dirname) {
3722
3941
  function copyDir(from, to) {
3723
3942
  fs$i.mkdirSync(to, { recursive: true });
3724
3943
  for (const name of fs$i.readdirSync(from)) {
3725
- const src = path$n.join(from, name);
3726
- const dest = path$n.join(to, name);
3944
+ const src = path$l.join(from, name);
3945
+ const dest = path$l.join(to, name);
3727
3946
  if (fs$i.statSync(src).isDirectory()) copyDir(src, dest);
3728
3947
  else fs$i.writeFileSync(dest, fs$i.readFileSync(src));
3729
3948
  }
@@ -3736,10 +3955,10 @@ function copyDir(from, to) {
3736
3955
  */
3737
3956
  function mirrorLibrary(spec, fromPaths, toDir) {
3738
3957
  const name = packageNameOf(spec);
3739
- const dest = path$n.join(toDir, ...name.split("/"));
3958
+ const dest = path$l.join(toDir, ...name.split("/"));
3740
3959
  if (fs$i.existsSync(dest)) return true;
3741
3960
  for (const from of fromPaths) {
3742
- const src = path$n.join(from, ...name.split("/"));
3961
+ const src = path$l.join(from, ...name.split("/"));
3743
3962
  if (fs$i.existsSync(src)) {
3744
3963
  copyDir(src, dest);
3745
3964
  return true;
@@ -3778,19 +3997,19 @@ function appFolder() {
3778
3997
  */
3779
3998
  function libraryResolution(dir = __dirname) {
3780
3999
  const paths = libraryPaths(dir);
3781
- const inAsar = paths.filter((p) => p.includes(`.asar${path$n.sep}`));
4000
+ const inAsar = paths.filter((p) => p.includes(`.asar${path$l.sep}`));
3782
4001
  if (!inAsar.length) return { nodePaths: paths, plugins: [] };
3783
4002
  let cache;
3784
4003
  try {
3785
4004
  const { app } = require("electron");
3786
- cache = path$n.join(
4005
+ cache = path$l.join(
3787
4006
  app.getPath("userData"),
3788
4007
  "widget-build-libraries",
3789
4008
  app.getVersion(),
3790
4009
  "node_modules",
3791
4010
  );
3792
4011
  } catch (_e) {
3793
- cache = path$n.join(
4012
+ cache = path$l.join(
3794
4013
  require$$2$1.tmpdir(),
3795
4014
  "dash-widget-build-libraries",
3796
4015
  "node_modules",
@@ -3818,13 +4037,13 @@ function libraryResolution(dir = __dirname) {
3818
4037
  /** A file in esbuild's error, short: "widgets/A.js", else its name. */
3819
4038
  function shortFile(file) {
3820
4039
  const f = String(file || "")
3821
- .split(path$n.sep)
4040
+ .split(path$l.sep)
3822
4041
  .join("/");
3823
4042
  return f.includes("/widgets/")
3824
4043
  ? `widgets/${f.split("/widgets/").pop()}`
3825
4044
  : f.startsWith("widgets/")
3826
4045
  ? f
3827
- : path$n.basename(f);
4046
+ : path$l.basename(f);
3828
4047
  }
3829
4048
 
3830
4049
  /**
@@ -3838,7 +4057,7 @@ function friendlyCompileError(error) {
3838
4057
  const loc = e.location || {};
3839
4058
  const missing = /^Could not resolve "(.+)"/.exec(e.text || "");
3840
4059
  if (missing && /^[./]/.test(missing[1])) {
3841
- return `${path$n.basename(String(loc.file || "a file"))} imports "${missing[1]}", which isn't in the package.`;
4060
+ return `${path$l.basename(String(loc.file || "a file"))} imports "${missing[1]}", which isn't in the package.`;
3842
4061
  }
3843
4062
  if (missing) {
3844
4063
  return `This widget needs the library "${packageNameOf(missing[1])}", which this app doesn't include.`;
@@ -3885,7 +4104,7 @@ function getEsbuildDiagnostics() {
3885
4104
 
3886
4105
  try {
3887
4106
  const pkgJsonPath = require.resolve("esbuild/package.json");
3888
- diagnostics.esbuildPackageDir = path$n.dirname(pkgJsonPath);
4107
+ diagnostics.esbuildPackageDir = path$l.dirname(pkgJsonPath);
3889
4108
  diagnostics.esbuildVersion = commonjsRequire(pkgJsonPath).version;
3890
4109
  } catch (err) {
3891
4110
  diagnostics.esbuildResolveError = err.message;
@@ -3895,13 +4114,13 @@ function getEsbuildDiagnostics() {
3895
4114
  const archPkgJson = require.resolve(
3896
4115
  `${diagnostics.archPackage}/package.json`,
3897
4116
  );
3898
- const archDir = path$n.dirname(archPkgJson);
4117
+ const archDir = path$l.dirname(archPkgJson);
3899
4118
  // esbuild's native binary on macOS/Linux is bin/esbuild;
3900
4119
  // on Windows it's esbuild.exe at the package root.
3901
4120
  const candidate =
3902
4121
  process.platform === "win32"
3903
- ? path$n.join(archDir, "esbuild.exe")
3904
- : path$n.join(archDir, "bin", "esbuild");
4122
+ ? path$l.join(archDir, "esbuild.exe")
4123
+ : path$l.join(archDir, "bin", "esbuild");
3905
4124
  diagnostics.nativeBinaryPath = candidate;
3906
4125
  diagnostics.nativeBinaryExists = fs$i.existsSync(candidate);
3907
4126
  } catch (err) {
@@ -3949,19 +4168,19 @@ async function healthCheck() {
3949
4168
  * @returns {string|null} Path to the widgets/ directory, or null
3950
4169
  */
3951
4170
  function findWidgetsDir$2(widgetPath) {
3952
- const direct = path$n.join(widgetPath, "widgets");
4171
+ const direct = path$l.join(widgetPath, "widgets");
3953
4172
  if (fs$i.existsSync(direct)) {
3954
4173
  return direct;
3955
4174
  }
3956
4175
 
3957
4176
  // Check configs/widgets/ (packageZip.js nests .dash.js files here)
3958
- const configsWidgets = path$n.join(widgetPath, "configs", "widgets");
4177
+ const configsWidgets = path$l.join(widgetPath, "configs", "widgets");
3959
4178
  if (fs$i.existsSync(configsWidgets)) {
3960
4179
  return configsWidgets;
3961
4180
  }
3962
4181
 
3963
4182
  // Check configs/ directory (used by packageZip.js for distributed widgets)
3964
- const configs = path$n.join(widgetPath, "configs");
4183
+ const configs = path$l.join(widgetPath, "configs");
3965
4184
  if (fs$i.existsSync(configs)) {
3966
4185
  return configs;
3967
4186
  }
@@ -3978,7 +4197,7 @@ function findWidgetsDir$2(widgetPath) {
3978
4197
  );
3979
4198
 
3980
4199
  for (const subdir of subdirs) {
3981
- const nested = path$n.join(widgetPath, subdir.name, "widgets");
4200
+ const nested = path$l.join(widgetPath, subdir.name, "widgets");
3982
4201
  if (fs$i.existsSync(nested)) {
3983
4202
  console.log(`[WidgetCompiler] Found nested widgets/ at ${nested}`);
3984
4203
  return nested;
@@ -4038,15 +4257,15 @@ async function compileWidget$1(
4038
4257
  // since widgetsDir may be nested (e.g., ./weather-widget/widgets/).
4039
4258
  // Built elsewhere (outDir), the entry imports the sources by full path.
4040
4259
  const relWidgetsDir = outDir
4041
- ? path$n.resolve(widgetsDir).split(path$n.sep).join("/")
4042
- : "./" + path$n.relative(widgetPath, widgetsDir).split(path$n.sep).join("/");
4260
+ ? path$l.resolve(widgetsDir).split(path$l.sep).join("/")
4261
+ : "./" + path$l.relative(widgetPath, widgetsDir).split(path$l.sep).join("/");
4043
4262
  const imports = [];
4044
4263
  const exportParts = [];
4045
4264
 
4046
4265
  for (const dashFile of dashFiles) {
4047
4266
  const componentName = dashFile.replace(".dash.js", "");
4048
4267
  const componentFile = `${componentName}.js`;
4049
- const componentFilePath = path$n.join(widgetsDir, componentFile);
4268
+ const componentFilePath = path$l.join(widgetsDir, componentFile);
4050
4269
  const hasComponent = fs$i.existsSync(componentFilePath);
4051
4270
 
4052
4271
  // Import the config (always)
@@ -4079,9 +4298,9 @@ async function compileWidget$1(
4079
4298
  const entryContent = [...imports, "", ...exportParts, ""].join("\n");
4080
4299
 
4081
4300
  // Write temporary entry file in the widget root (or beside the build)
4082
- const distDir = outDir || path$n.join(widgetPath, "dist");
4083
- const entryPath = path$n.join(outDir || widgetPath, "__compile_entry.js");
4084
- const outPath = path$n.join(distDir, "index.cjs.js");
4301
+ const distDir = outDir || path$l.join(widgetPath, "dist");
4302
+ const entryPath = path$l.join(outDir || widgetPath, "__compile_entry.js");
4303
+ const outPath = path$l.join(distDir, "index.cjs.js");
4085
4304
  // The package's own libraries (package.json dependencies), downloaded
4086
4305
  // into a temp folder for this build (consolidation Phase 1a-3).
4087
4306
  let own = null;
@@ -10721,7 +10940,7 @@ var dashConfigParser = { parseDashConfig: parseDashConfig$3, DashConfigParseErro
10721
10940
  */
10722
10941
 
10723
10942
  const fs$h = require$$0$3;
10724
- const path$m = require$$1$2;
10943
+ const path$k = require$$1$2;
10725
10944
  const { findWidgetsDir: findWidgetsDir$1 } = widgetCompiler$1;
10726
10945
  const { parseDashConfig: parseDashConfig$2 } = dashConfigParser;
10727
10946
 
@@ -10762,9 +10981,9 @@ class DynamicWidgetLoader {
10762
10981
  );
10763
10982
 
10764
10983
  const widgetsDir =
10765
- findWidgetsDir$1(widgetPath) || path$m.join(widgetPath, "widgets");
10766
- const componentPath = path$m.join(widgetsDir, `${componentName}.js`);
10767
- const configPath = path$m.join(widgetsDir, `${componentName}.dash.js`);
10984
+ findWidgetsDir$1(widgetPath) || path$k.join(widgetPath, "widgets");
10985
+ const componentPath = path$k.join(widgetsDir, `${componentName}.js`);
10986
+ const configPath = path$k.join(widgetsDir, `${componentName}.dash.js`);
10768
10987
 
10769
10988
  if (!fs$h.existsSync(componentPath)) {
10770
10989
  throw new Error(`Component file not found: ${componentPath}`);
@@ -11600,9 +11819,9 @@ var registryDownload = {
11600
11819
  */
11601
11820
 
11602
11821
  const fs$g = require$$0$3;
11603
- const path$l = require$$1$2;
11822
+ const path$j = require$$1$2;
11604
11823
  const os$4 = require$$2$1;
11605
- const { app: app$c } = require$$0$2;
11824
+ const { app: app$9 } = require$$0$2;
11606
11825
 
11607
11826
  // Cache: widgetId → permissions | null. Populated lazily on first
11608
11827
  // lookup; invalidated when a widget is installed/uninstalled (the
@@ -11617,7 +11836,7 @@ function expandHome(p) {
11617
11836
  if (typeof p !== "string" || !p) return p;
11618
11837
  if (p === "~") return os$4.homedir();
11619
11838
  if (p.startsWith("~/") || p.startsWith("~\\")) {
11620
- return path$l.join(os$4.homedir(), p.slice(2));
11839
+ return path$j.join(os$4.homedir(), p.slice(2));
11621
11840
  }
11622
11841
  return p;
11623
11842
  }
@@ -11727,10 +11946,10 @@ function dottedComponentIdToPackageId(widgetId) {
11727
11946
  function resolveWidgetPackagePath(widgetId) {
11728
11947
  const packageId = dottedComponentIdToPackageId(widgetId);
11729
11948
  if (typeof packageId !== "string" || !packageId) return null;
11730
- const widgetsRoot = path$l.join(app$c.getPath("userData"), "widgets");
11949
+ const widgetsRoot = path$j.join(app$9.getPath("userData"), "widgets");
11731
11950
  // Split scope from name for "@scope/name" form.
11732
11951
  const parts = packageId.startsWith("@") ? packageId.split("/") : [packageId];
11733
- return path$l.join(widgetsRoot, ...parts, "package.json");
11952
+ return path$j.join(widgetsRoot, ...parts, "package.json");
11734
11953
  }
11735
11954
 
11736
11955
  /**
@@ -11822,7 +12041,7 @@ var widgetPermissions = {
11822
12041
  */
11823
12042
 
11824
12043
  const fs$f = require$$0$3;
11825
- const path$k = require$$1$2;
12044
+ const path$i = require$$1$2;
11826
12045
 
11827
12046
  const SOURCE_EXTENSIONS = new Set([
11828
12047
  ".js",
@@ -11880,13 +12099,13 @@ function readSourceFiles(dir) {
11880
12099
  return;
11881
12100
  }
11882
12101
  for (const entry of entries) {
11883
- const abs = path$k.join(current, entry.name);
11884
- const rel = relBase ? path$k.join(relBase, entry.name) : entry.name;
12102
+ const abs = path$i.join(current, entry.name);
12103
+ const rel = relBase ? path$i.join(relBase, entry.name) : entry.name;
11885
12104
  if (entry.isDirectory()) {
11886
12105
  if (skipDirs.has(entry.name)) continue;
11887
12106
  walk(abs, rel);
11888
12107
  } else if (entry.isFile()) {
11889
- const ext = path$k.extname(entry.name).toLowerCase();
12108
+ const ext = path$i.extname(entry.name).toLowerCase();
11890
12109
  if (!SOURCE_EXTENSIONS.has(ext)) continue;
11891
12110
  if (result.length >= SCAN_FILE_LIMIT) return;
11892
12111
  try {
@@ -11912,7 +12131,7 @@ function scanForMcpUsage(input) {
11912
12131
  let fileList = [];
11913
12132
  if (input.files && typeof input.files === "object") {
11914
12133
  for (const [relPath, source] of Object.entries(input.files)) {
11915
- const ext = path$k.extname(relPath).toLowerCase();
12134
+ const ext = path$i.extname(relPath).toLowerCase();
11916
12135
  if (!SOURCE_EXTENSIONS.has(ext)) continue;
11917
12136
  if (typeof source !== "string") continue;
11918
12137
  fileList.push({ relPath, source });
@@ -12025,7 +12244,7 @@ var manifestScanner = {
12025
12244
  */
12026
12245
 
12027
12246
  const fs$e = require$$0$3;
12028
- const path$j = require$$1$2;
12247
+ const path$h = require$$1$2;
12029
12248
  const { safePath: safePath$3 } = safePath_1;
12030
12249
 
12031
12250
  const NAME_RE = /^@?[a-z0-9][a-z0-9.-]*(\/[a-z0-9][a-z0-9.-]*)?$/i;
@@ -12046,8 +12265,8 @@ function loadWidgetManifest(folderPath) {
12046
12265
  return { ok: false, error: `folder does not exist: ${folderPath}` };
12047
12266
  }
12048
12267
 
12049
- const dashJsonPath = path$j.join(folderPath, "dash.json");
12050
- const packageJsonPath = path$j.join(folderPath, "package.json");
12268
+ const dashJsonPath = path$h.join(folderPath, "dash.json");
12269
+ const packageJsonPath = path$h.join(folderPath, "package.json");
12051
12270
 
12052
12271
  let raw;
12053
12272
  let source;
@@ -12118,7 +12337,7 @@ function loadWidgetManifest(folderPath) {
12118
12337
 
12119
12338
  // entry: optional with sensible default. Validate when present.
12120
12339
  let entry = typeof raw.entry === "string" ? raw.entry : "widgets";
12121
- if (path$j.isAbsolute(entry) || entry.split(/[/\\]/).includes("..")) {
12340
+ if (path$h.isAbsolute(entry) || entry.split(/[/\\]/).includes("..")) {
12122
12341
  return {
12123
12342
  ok: false,
12124
12343
  error: "manifest.entry must be relative and must not contain `..`",
@@ -12129,15 +12348,15 @@ function loadWidgetManifest(folderPath) {
12129
12348
  // folder root after realpath. If the entry doesn't yet exist on
12130
12349
  // disk (common during validate-only flows), fall back to a plain
12131
12350
  // resolve-and-prefix check.
12132
- const candidate = path$j.join(folderPath, entry);
12351
+ const candidate = path$h.join(folderPath, entry);
12133
12352
  if (fs$e.existsSync(candidate)) {
12134
12353
  safePath$3(candidate, [folderPath]);
12135
12354
  } else {
12136
- const resolved = path$j.resolve(candidate);
12137
- const rootResolved = path$j.resolve(folderPath);
12355
+ const resolved = path$h.resolve(candidate);
12356
+ const rootResolved = path$h.resolve(folderPath);
12138
12357
  if (
12139
12358
  resolved !== rootResolved &&
12140
- !resolved.startsWith(rootResolved + path$j.sep)
12359
+ !resolved.startsWith(rootResolved + path$h.sep)
12141
12360
  ) {
12142
12361
  return {
12143
12362
  ok: false,
@@ -12216,7 +12435,7 @@ function walkSourceContainment(rootPath) {
12216
12435
  const stat = fs$e.lstatSync(current);
12217
12436
  if (stat.isDirectory()) {
12218
12437
  for (const entry of fs$e.readdirSync(current)) {
12219
- stack.push(path$j.join(current, entry));
12438
+ stack.push(path$h.join(current, entry));
12220
12439
  }
12221
12440
  }
12222
12441
  // Symlinks: lstat gives us the symlink-itself; safePath above
@@ -19853,9 +20072,9 @@ function requireTransform () {
19853
20072
  return transform;
19854
20073
  }
19855
20074
 
19856
- const { app: app$b } = require$$0$2;
20075
+ const { app: app$8 } = require$$0$2;
19857
20076
  var fs$d = require$$0$3;
19858
- const path$i = require$$1$2;
20077
+ const path$g = require$$1$2;
19859
20078
  const events$5 = events$8;
19860
20079
  const { getFileContents: getFileContents$5, writeToFile: writeToFile$2 } = file;
19861
20080
  const { safePath: safePath$2, getAllowedRoots: getAllowedRoots$1 } = safePath_1;
@@ -19872,9 +20091,9 @@ const { readEnforceFlag: readEnforceFlag$2, readJitFlag: readJitFlag$2 } = secur
19872
20091
  // domain-neutral name is a separate slice).
19873
20092
  function _loadFlags$1() {
19874
20093
  try {
19875
- const settingsPath = path$i.join(
19876
- app$b.getPath("userData"),
19877
- appName$5,
20094
+ const settingsPath = path$g.join(
20095
+ app$8.getPath("userData"),
20096
+ appName$1,
19878
20097
  "settings.json",
19879
20098
  );
19880
20099
  if (!fs$d.existsSync(settingsPath)) return null;
@@ -19943,7 +20162,7 @@ async function _runNetworkGate$1(win, action, widgetId, args, errorEvent, token)
19943
20162
  const ObjectsToCsv = require$$9$2;
19944
20163
  const Transform = requireTransform();
19945
20164
  const https$4 = require$$0$7;
19946
- const appName$5 = "Dashboard";
20165
+ const appName$1 = "Dashboard";
19947
20166
 
19948
20167
  const dataController$1 = {
19949
20168
  /**
@@ -19959,9 +20178,9 @@ const dataController$1 = {
19959
20178
  // Validate the renderer-supplied filename is contained within
19960
20179
  // the data directory. path.join doesn't reject `..` segments;
19961
20180
  // safePath does.
19962
- const candidate = path$i.join(
19963
- app$b.getPath("userData"),
19964
- appName$5,
20181
+ const candidate = path$g.join(
20182
+ app$8.getPath("userData"),
20183
+ appName$1,
19965
20184
  appId,
19966
20185
  "data",
19967
20186
  toFilename,
@@ -20320,9 +20539,9 @@ const dataController$1 = {
20320
20539
  if (data) {
20321
20540
  // Validate filename is contained within the data directory.
20322
20541
  // path.join doesn't reject `..` segments; safePath does.
20323
- const candidate = path$i.join(
20324
- app$b.getPath("userData"),
20325
- appName$5,
20542
+ const candidate = path$g.join(
20543
+ app$8.getPath("userData"),
20544
+ appName$1,
20326
20545
  "data",
20327
20546
  filename,
20328
20547
  );
@@ -20429,9 +20648,9 @@ const dataController$1 = {
20429
20648
  try {
20430
20649
  if (filename) {
20431
20650
  // filename to the pages file (live pages)
20432
- const fromFilename = path$i.join(
20433
- app$b.getPath("userData"),
20434
- appName$5,
20651
+ const fromFilename = path$g.join(
20652
+ app$8.getPath("userData"),
20653
+ appName$1,
20435
20654
  "data",
20436
20655
  filename,
20437
20656
  );
@@ -20667,14 +20886,14 @@ var migrations = {
20667
20886
  * settingsController
20668
20887
  */
20669
20888
 
20670
- const { app: app$a } = require$$0$2;
20671
- const path$h = require$$1$2;
20889
+ const { app: app$7 } = require$$0$2;
20890
+ const path$f = require$$1$2;
20672
20891
  const fs$c = require$$0$3;
20673
20892
  const { getFileContents: getFileContents$4, writeToFile: writeToFile$1 } = file;
20674
20893
  const { migrateSettings, CURRENT_SCHEMA_VERSION: CURRENT_SCHEMA_VERSION$2 } = migrations;
20675
20894
 
20676
20895
  const configFilename$3 = "settings.json";
20677
- const appName$4 = "Dashboard";
20896
+ const appName = "Dashboard";
20678
20897
 
20679
20898
  // Helper function to recursively copy directory
20680
20899
  function copyDirectory(source, destination) {
@@ -20684,8 +20903,8 @@ function copyDirectory(source, destination) {
20684
20903
 
20685
20904
  const files = fs$c.readdirSync(source);
20686
20905
  for (const file of files) {
20687
- const srcPath = path$h.join(source, file);
20688
- const destPath = path$h.join(destination, file);
20906
+ const srcPath = path$f.join(source, file);
20907
+ const destPath = path$f.join(destination, file);
20689
20908
  const stat = fs$c.lstatSync(srcPath);
20690
20909
 
20691
20910
  // Skip symlinks to prevent following links to sensitive files
@@ -20713,9 +20932,9 @@ const settingsController$4 = {
20713
20932
  try {
20714
20933
  if (data) {
20715
20934
  // <appId>/settings.json
20716
- const filename = path$h.join(
20717
- app$a.getPath("userData"),
20718
- appName$4,
20935
+ const filename = path$f.join(
20936
+ app$7.getPath("userData"),
20937
+ appName,
20719
20938
  configFilename$3,
20720
20939
  );
20721
20940
  // Always stamp the current schema version on every save so the
@@ -20757,9 +20976,9 @@ const settingsController$4 = {
20757
20976
  getSettingsForApplication: (win) => {
20758
20977
  try {
20759
20978
  // <appId>/settings.json
20760
- const filename = path$h.join(
20761
- app$a.getPath("userData"),
20762
- appName$4,
20979
+ const filename = path$f.join(
20980
+ app$7.getPath("userData"),
20981
+ appName,
20763
20982
  configFilename$3,
20764
20983
  );
20765
20984
  // make sure the file exists...
@@ -20805,15 +21024,15 @@ const settingsController$4 = {
20805
21024
  */
20806
21025
  getDataDirectory: (win) => {
20807
21026
  try {
20808
- const settingsPath = path$h.join(
20809
- app$a.getPath("userData"),
20810
- appName$4,
21027
+ const settingsPath = path$f.join(
21028
+ app$7.getPath("userData"),
21029
+ appName,
20811
21030
  configFilename$3,
20812
21031
  );
20813
21032
  const settings = getFileContents$4(settingsPath, {});
20814
21033
  const userDataDir =
20815
21034
  settings.userDataDirectory ||
20816
- path$h.join(app$a.getPath("userData"), appName$4);
21035
+ path$f.join(app$7.getPath("userData"), appName);
20817
21036
 
20818
21037
  console.log("[settingsController] Data directory retrieved successfully");
20819
21038
  // Return the data for ipcMain.handle() - modern promise-based approach
@@ -20850,9 +21069,9 @@ const settingsController$4 = {
20850
21069
  }
20851
21070
 
20852
21071
  // Update settings
20853
- const settingsPath = path$h.join(
20854
- app$a.getPath("userData"),
20855
- appName$4,
21072
+ const settingsPath = path$f.join(
21073
+ app$7.getPath("userData"),
21074
+ appName,
20856
21075
  configFilename$3,
20857
21076
  );
20858
21077
  const settings = getFileContents$4(settingsPath, {});
@@ -20884,20 +21103,20 @@ const settingsController$4 = {
20884
21103
  migrateDataDirectory: (win, oldPath, newPath) => {
20885
21104
  try {
20886
21105
  // Resolve paths to prevent traversal
20887
- const resolvedOldPath = path$h.resolve(oldPath);
20888
- const resolvedNewPath = path$h.resolve(newPath);
21106
+ const resolvedOldPath = path$f.resolve(oldPath);
21107
+ const resolvedNewPath = path$f.resolve(newPath);
20889
21108
 
20890
21109
  // Validate oldPath is the current configured data directory
20891
- const settingsCheckPath = path$h.join(
20892
- app$a.getPath("userData"),
20893
- appName$4,
21110
+ const settingsCheckPath = path$f.join(
21111
+ app$7.getPath("userData"),
21112
+ appName,
20894
21113
  configFilename$3,
20895
21114
  );
20896
21115
  const currentSettings = getFileContents$4(settingsCheckPath, {});
20897
21116
  const currentDataDir =
20898
21117
  currentSettings.userDataDirectory ||
20899
- path$h.join(app$a.getPath("userData"), appName$4);
20900
- if (resolvedOldPath !== path$h.resolve(currentDataDir)) {
21118
+ path$f.join(app$7.getPath("userData"), appName);
21119
+ if (resolvedOldPath !== path$f.resolve(currentDataDir)) {
20901
21120
  throw new Error("Source path must be the current data directory");
20902
21121
  }
20903
21122
 
@@ -20933,9 +21152,9 @@ const settingsController$4 = {
20933
21152
  copyDirectory(resolvedOldPath, resolvedNewPath);
20934
21153
 
20935
21154
  // Update settings to use new path
20936
- const settingsPath = path$h.join(
20937
- app$a.getPath("userData"),
20938
- appName$4,
21155
+ const settingsPath = path$f.join(
21156
+ app$7.getPath("userData"),
21157
+ appName,
20939
21158
  configFilename$3,
20940
21159
  );
20941
21160
  const settings = getFileContents$4(settingsPath, {});
@@ -21831,13 +22050,11 @@ function requireProviderController () {
21831
22050
  return providerController_1;
21832
22051
  }
21833
22052
 
21834
- const { app: app$9 } = require$$0$2;
21835
- const path$g = require$$1$2;
21836
22053
  const events$4 = events$8;
21837
22054
  const { getFileContents: getFileContents$3 } = file;
22055
+ const { getProfileFilePath: getProfileFilePath$3 } = profilePaths;
21838
22056
 
21839
22057
  const configFilename$2 = "layouts.json";
21840
- const appName$3 = "Dashboard";
21841
22058
 
21842
22059
  const layoutController$1 = {
21843
22060
  /**
@@ -21848,12 +22065,7 @@ const layoutController$1 = {
21848
22065
  */
21849
22066
  listLayoutsForApplication: (win, appId) => {
21850
22067
  try {
21851
- const filename = path$g.join(
21852
- app$9.getPath("userData"),
21853
- appName$3,
21854
- appId,
21855
- configFilename$2,
21856
- );
22068
+ const filename = getProfileFilePath$3(appId, configFilename$2);
21857
22069
  const layoutsArray = getFileContents$3(filename);
21858
22070
  win.webContents.send(events$4.LAYOUT_LIST_COMPLETE, {
21859
22071
  layouts: layoutsArray,
@@ -58106,7 +58318,7 @@ const {
58106
58318
  const {
58107
58319
  StreamableHTTPClientTransport,
58108
58320
  } = streamableHttp$1;
58109
- const path$f = require$$1$2;
58321
+ const path$e = require$$1$2;
58110
58322
  const fs$b = require$$0$3;
58111
58323
  const os$3 = require$$2$1;
58112
58324
  const responseCache$2 = responseCache_1;
@@ -58124,7 +58336,7 @@ const {
58124
58336
  isBuiltinTransport,
58125
58337
  createBuiltinTransport,
58126
58338
  } = builtinServers;
58127
- const { app: app$8 } = require$$0$2;
58339
+ const { app: app$6 } = require$$0$2;
58128
58340
 
58129
58341
  /**
58130
58342
  * Load the user's settings.json (or null on absence/parse error). The
@@ -58133,8 +58345,8 @@ const { app: app$8 } = require$$0$2;
58133
58345
  */
58134
58346
  function loadSettingsForFlags() {
58135
58347
  try {
58136
- const settingsPath = path$f.join(
58137
- app$8.getPath("userData"),
58348
+ const settingsPath = path$e.join(
58349
+ app$6.getPath("userData"),
58138
58350
  "Dashboard",
58139
58351
  "settings.json",
58140
58352
  );
@@ -58885,7 +59097,7 @@ const mcpController$3 = {
58885
59097
  }
58886
59098
 
58887
59099
  // Interpolate {{MCP_DIR}} in args to resolve local MCP server scripts
58888
- const mcpDir = path$f.join(__dirname, "..", "mcp");
59100
+ const mcpDir = path$e.join(__dirname, "..", "mcp");
58889
59101
  for (let i = 0; i < args.length; i++) {
58890
59102
  if (
58891
59103
  typeof args[i] === "string" &&
@@ -59468,7 +59680,7 @@ const mcpController$3 = {
59468
59680
  */
59469
59681
  getCatalog: (win) => {
59470
59682
  try {
59471
- const catalogPath = path$f.join(
59683
+ const catalogPath = path$e.join(
59472
59684
  __dirname,
59473
59685
  "..",
59474
59686
  "mcp",
@@ -59509,7 +59721,7 @@ const mcpController$3 = {
59509
59721
  */
59510
59722
  getKnownExternalCatalog: () => {
59511
59723
  try {
59512
- const catalogPath = path$f.join(
59724
+ const catalogPath = path$e.join(
59513
59725
  __dirname,
59514
59726
  "..",
59515
59727
  "mcp",
@@ -59614,7 +59826,7 @@ const mcpController$3 = {
59614
59826
  }
59615
59827
 
59616
59828
  // Interpolate {{MCP_DIR}} in authCommand args (same as startServer)
59617
- const mcpDir = path$f.join(__dirname, "..", "mcp");
59829
+ const mcpDir = path$e.join(__dirname, "..", "mcp");
59618
59830
  const resolvedArgs = (authCommand.args || []).map((arg) =>
59619
59831
  typeof arg === "string" && arg.includes("{{MCP_DIR}}")
59620
59832
  ? arg.replace(/\{\{MCP_DIR\}\}/g, mcpDir)
@@ -59786,7 +59998,7 @@ var isNewerVersion_1 = { isNewerVersion: isNewerVersion$1 };
59786
59998
  * - Support two-level browsing: packages (bundles) and widgets within packages
59787
59999
  */
59788
60000
 
59789
- const path$e = require$$1$2;
60001
+ const path$d = require$$1$2;
59790
60002
  const fs$a = require$$0$3;
59791
60003
  const os$2 = require$$2$1;
59792
60004
  const { toPackageId } = packageId;
@@ -59817,7 +60029,7 @@ function getCacheKey() {
59817
60029
  * Get the local test registry path for dev mode
59818
60030
  */
59819
60031
  function getTestRegistryPath() {
59820
- return path$e.join(__dirname, "..", "registry", "test-registry-index.json");
60032
+ return path$d.join(__dirname, "..", "registry", "test-registry-index.json");
59821
60033
  }
59822
60034
 
59823
60035
  /**
@@ -60441,7 +60653,7 @@ async function fetchPackageSource(packageName, componentName = null) {
60441
60653
 
60442
60654
  const zip = new AdmZip(buffer);
60443
60655
  const safeName = (pkg.name || "pkg").replace(/[^a-zA-Z0-9-_]/g, "_");
60444
- const tempDir = path$e.join(
60656
+ const tempDir = path$d.join(
60445
60657
  os$2.tmpdir(),
60446
60658
  `dash-registry-preview-${safeName}-${Date.now()}`,
60447
60659
  );
@@ -60450,7 +60662,7 @@ async function fetchPackageSource(packageName, componentName = null) {
60450
60662
  validateZipEntries(zip, tempDir);
60451
60663
  zip.extractAllTo(tempDir, true);
60452
60664
 
60453
- const widgetsDir = path$e.join(tempDir, "widgets");
60665
+ const widgetsDir = path$d.join(tempDir, "widgets");
60454
60666
  let componentCode = "";
60455
60667
  let configCode = "";
60456
60668
  let widgetName = null;
@@ -60478,7 +60690,7 @@ async function fetchPackageSource(packageName, componentName = null) {
60478
60690
  if (!configFile) configFile = dashFiles[0];
60479
60691
 
60480
60692
  if (configFile) {
60481
- configCode = fs$a.readFileSync(path$e.join(widgetsDir, configFile), "utf8");
60693
+ configCode = fs$a.readFileSync(path$d.join(widgetsDir, configFile), "utf8");
60482
60694
  widgetName = configFile.replace(/\.dash\.js$/, "");
60483
60695
  }
60484
60696
 
@@ -60493,7 +60705,7 @@ async function fetchPackageSource(packageName, componentName = null) {
60493
60705
 
60494
60706
  if (componentFile) {
60495
60707
  componentCode = fs$a.readFileSync(
60496
- path$e.join(widgetsDir, componentFile),
60708
+ path$d.join(widgetsDir, componentFile),
60497
60709
  "utf8",
60498
60710
  );
60499
60711
  if (!widgetName) widgetName = componentFile.replace(/\.js$/, "");
@@ -60501,13 +60713,13 @@ async function fetchPackageSource(packageName, componentName = null) {
60501
60713
  }
60502
60714
 
60503
60715
  let bundleSource = null;
60504
- const bundlePath = path$e.join(tempDir, "dist", "index.cjs.js");
60716
+ const bundlePath = path$d.join(tempDir, "dist", "index.cjs.js");
60505
60717
  if (fs$a.existsSync(bundlePath)) {
60506
60718
  bundleSource = fs$a.readFileSync(bundlePath, "utf8");
60507
60719
  }
60508
60720
 
60509
60721
  let dashMeta = {};
60510
- const dashPath = path$e.join(tempDir, "dash.json");
60722
+ const dashPath = path$d.join(tempDir, "dash.json");
60511
60723
  if (fs$a.existsSync(dashPath)) {
60512
60724
  try {
60513
60725
  dashMeta = JSON.parse(fs$a.readFileSync(dashPath, "utf8"));
@@ -60629,7 +60841,7 @@ async function fetchPackageManifest(packageName) {
60629
60841
 
60630
60842
  const zip = new AdmZip(buffer);
60631
60843
  const safeName = (pkg.name || "pkg").replace(/[^a-zA-Z0-9-_]/g, "_");
60632
- const tempDir = path$e.join(
60844
+ const tempDir = path$d.join(
60633
60845
  os$2.tmpdir(),
60634
60846
  `dash-registry-manifest-${safeName}-${Date.now()}`,
60635
60847
  );
@@ -60698,7 +60910,7 @@ var registryController$3 = {
60698
60910
  var fs$9 = require$$0$3;
60699
60911
  var JSONStream = require$$4$1;
60700
60912
  const algoliasearch$1 = require$$2$4;
60701
- const path$d = require$$3$3;
60913
+ const path$c = require$$3$3;
60702
60914
  const { ensureDirectoryExistence, checkDirectory } = file;
60703
60915
 
60704
60916
  let AlgoliaIndex$1 = class AlgoliaIndex {
@@ -60805,7 +61017,7 @@ let AlgoliaIndex$1 = class AlgoliaIndex {
60805
61017
  if (err) reject(err);
60806
61018
  if (files) {
60807
61019
  files.forEach((file) => {
60808
- fs$9.unlinkSync(path$d.join(directoryPath, file));
61020
+ fs$9.unlinkSync(path$c.join(directoryPath, file));
60809
61021
  });
60810
61022
  resolve();
60811
61023
  }
@@ -60828,7 +61040,7 @@ let AlgoliaIndex$1 = class AlgoliaIndex {
60828
61040
  let results = [];
60829
61041
  for (const fileIndex in files) {
60830
61042
  // for each file lets read the file and then push to algolia
60831
- const pathToBatch = path$d.join(batchFilepath, files[fileIndex]);
61043
+ const pathToBatch = path$c.join(batchFilepath, files[fileIndex]);
60832
61044
  const fileContents = await this.readFile(pathToBatch);
60833
61045
  if (fileContents) {
60834
61046
  if ("data" in fileContents && "filepath" in fileContents) {
@@ -61367,24 +61579,21 @@ function upsertMenuItem$1(items, menuItem) {
61367
61579
 
61368
61580
  var upsertMenuItem_1 = { upsertMenuItem: upsertMenuItem$1 };
61369
61581
 
61370
- const { app: app$7 } = require$$0$2;
61371
- const path$c = require$$1$2;
61582
+ const path$b = require$$1$2;
61372
61583
  const { writeFileSync } = require$$0$3;
61373
61584
  const { getFileContents: getFileContents$2 } = file;
61585
+ const {
61586
+ getProfileFilePath: getProfileFilePath$2,
61587
+ getProfileDataDir,
61588
+ } = profilePaths;
61374
61589
  const { upsertMenuItem } = upsertMenuItem_1;
61375
61590
 
61376
61591
  const configFilename$1 = "menuItems.json";
61377
- const appName$2 = "Dashboard";
61378
61592
 
61379
61593
  const menuItemsController$1 = {
61380
61594
  saveMenuItemForApplication: (win, appId, menuItem) => {
61381
61595
  try {
61382
- const filename = path$c.join(
61383
- app$7.getPath("userData"),
61384
- appName$2,
61385
- appId,
61386
- configFilename$1,
61387
- );
61596
+ const filename = getProfileFilePath$2(appId, configFilename$1);
61388
61597
  const raw = getFileContents$2(filename) || [];
61389
61598
  const deduped = upsertMenuItem(raw, menuItem);
61390
61599
  writeFileSync(filename, JSON.stringify(deduped, null, 2));
@@ -61398,12 +61607,7 @@ const menuItemsController$1 = {
61398
61607
 
61399
61608
  listMenuItemsForApplication: (win, appId) => {
61400
61609
  try {
61401
- const filename = path$c.join(
61402
- app$7.getPath("userData"),
61403
- appName$2,
61404
- appId,
61405
- configFilename$1,
61406
- );
61610
+ const filename = getProfileFilePath$2(appId, configFilename$1);
61407
61611
  const menuItemsArray = getFileContents$2(filename);
61408
61612
  const filtered = menuItemsArray.filter((mi) => mi !== null);
61409
61613
  // Return the data for ipcMain.handle() - modern promise-based approach
@@ -61425,10 +61629,10 @@ const menuItemsController$1 = {
61425
61629
  // a missing menuId would read as folder 1), as the confirm says.
61426
61630
  deleteMenuItemForApplication: (win, appId, menuItemId) => {
61427
61631
  try {
61428
- const dir = path$c.join(app$7.getPath("userData"), appName$2, appId);
61632
+ const dir = getProfileDataDir(appId);
61429
61633
  return deleteMenuItemFromFiles(
61430
- path$c.join(dir, configFilename$1),
61431
- path$c.join(dir, "workspaces.json"),
61634
+ path$b.join(dir, configFilename$1),
61635
+ path$b.join(dir, "workspaces.json"),
61432
61636
  menuItemId,
61433
61637
  );
61434
61638
  } catch (e) {
@@ -63340,7 +63544,7 @@ streamableHttp.StreamableHTTPServerTransport = StreamableHTTPServerTransport$1;
63340
63544
  */
63341
63545
 
63342
63546
  const fs$7 = require$$0$3;
63343
- const path$b = require$$1$2;
63547
+ const path$a = require$$1$2;
63344
63548
  const forge = require$$2$5;
63345
63549
 
63346
63550
  /**
@@ -63349,8 +63553,8 @@ const forge = require$$2$5;
63349
63553
  * @returns {{ cert: string, key: string }} PEM-encoded certificate and private key
63350
63554
  */
63351
63555
  function getOrCreateCert$1(certsDir) {
63352
- const certPath = path$b.join(certsDir, "cert.pem");
63353
- const keyPath = path$b.join(certsDir, "key.pem");
63556
+ const certPath = path$a.join(certsDir, "cert.pem");
63557
+ const keyPath = path$a.join(certsDir, "key.pem");
63354
63558
 
63355
63559
  // Return existing cert if valid
63356
63560
  if (fs$7.existsSync(certPath) && fs$7.existsSync(keyPath)) {
@@ -74187,7 +74391,7 @@ var dashboardConfigUtils$1 = {
74187
74391
  * not exposed to the renderer.
74188
74392
  */
74189
74393
 
74190
- const { app: app$6, safeStorage: safeStorage$1 } = require$$0$2;
74394
+ const { app: app$5, safeStorage: safeStorage$1 } = require$$0$2;
74191
74395
  const os$1 = require$$2$1;
74192
74396
 
74193
74397
  const {
@@ -74487,7 +74691,7 @@ var publisherKeyController$1 = {
74487
74691
  */
74488
74692
 
74489
74693
  const fs$6 = require$$0$3;
74490
- const path$a = require$$1$2;
74694
+ const path$9 = require$$1$2;
74491
74695
  const { getStoredToken } = registryAuthController$1;
74492
74696
  const { signZipBuffer: signZipBuffer$1 } = publisherKeyController$1;
74493
74697
 
@@ -74549,7 +74753,7 @@ async function publishToRegistry$1(zipPath, manifest) {
74549
74753
  formData.append(
74550
74754
  "file",
74551
74755
  new Blob([zipBuffer], { type: "application/zip" }),
74552
- path$a.basename(zipPath),
74756
+ path$9.basename(zipPath),
74553
74757
  );
74554
74758
  formData.append("manifest", JSON.stringify(manifest));
74555
74759
  formData.append("signature", signing.signature);
@@ -74836,8 +75040,8 @@ function requireWidgetPublishManifest () {
74836
75040
  * Mirrors dashboardConfigController patterns for ZIP creation, manifest generation,
74837
75041
  * and registry interaction.
74838
75042
  */
74839
- const path$9 = require$$1$2;
74840
- const { app: app$5, dialog: dialog$2 } = require$$0$2;
75043
+ const path$8 = require$$1$2;
75044
+ const { app: app$4, dialog: dialog$2 } = require$$0$2;
74841
75045
  const AdmZip$2 = require$$3$1;
74842
75046
 
74843
75047
  const themeController$3 = themeController_1;
@@ -75367,7 +75571,7 @@ async function installThemeFromRegistry$1(win, appId, packageName) {
75367
75571
  // Validate entry path (security: prevent path traversal)
75368
75572
  if (
75369
75573
  themeEntry.entryName.includes("..") ||
75370
- path$9.isAbsolute(themeEntry.entryName)
75574
+ path$8.isAbsolute(themeEntry.entryName)
75371
75575
  ) {
75372
75576
  return {
75373
75577
  success: false,
@@ -75679,8 +75883,8 @@ var secretBox = { createSecretBox: createSecretBox$1, PREFIX };
75679
75883
  * the host and the store together.
75680
75884
  */
75681
75885
 
75682
- const path$8 = require$$1$2;
75683
- const { app: app$4, safeStorage } = require$$0$2;
75886
+ const path$7 = require$$1$2;
75887
+ const { app: app$3, safeStorage } = require$$0$2;
75684
75888
  const Store$1 = require$$0$5;
75685
75889
  const { createSecretBox } = secretBox;
75686
75890
 
@@ -75697,11 +75901,11 @@ function createElectronHost$1() {
75697
75901
  const budgetStore = new Store$1({ name: "dash-bot-budgets" });
75698
75902
  const memoryStore = new Store$1({ name: "dash-bot-memory" });
75699
75903
  const recentStore = new Store$1({ name: "dash-create-recent" });
75700
- const botsRoot = path$8.join(app$4.getPath("userData"), "bots");
75904
+ const botsRoot = path$7.join(app$3.getPath("userData"), "bots");
75701
75905
 
75702
75906
  return {
75703
75907
  // The saved audit log (US-003 AC5) — append-only JSON lines.
75704
- paths: { botsRoot, auditLog: path$8.join(botsRoot, "audit.log") },
75908
+ paths: { botsRoot, auditLog: path$7.join(botsRoot, "audit.log") },
75705
75909
  clock: { now: () => new Date().toISOString() },
75706
75910
  // Seals sensitive bot data at rest (run answers) with the OS keychain.
75707
75911
  // Falls back to plain text where the keychain isn't available.
@@ -75759,7 +75963,7 @@ var BotStore$2 = {exports: {}};
75759
75963
  */
75760
75964
 
75761
75965
  const fs$5 = require$$0$3;
75762
- const path$7 = require$$1$2;
75966
+ const path$6 = require$$1$2;
75763
75967
  const {
75764
75968
  newBotId,
75765
75969
  isValidBotId,
@@ -75850,7 +76054,7 @@ let BotStore$1 = class BotStore {
75850
76054
  if (!isValidBotId(id)) {
75851
76055
  throw new Error(`BotStore: invalid bot id "${id}"`);
75852
76056
  }
75853
- return path$7.join(this._botsRoot, id, "files");
76057
+ return path$6.join(this._botsRoot, id, "files");
75854
76058
  }
75855
76059
 
75856
76060
  /** @returns {object[]} all bot definitions */
@@ -75939,7 +76143,7 @@ let BotStore$1 = class BotStore {
75939
76143
  this._save(data);
75940
76144
 
75941
76145
  if (isValidBotId(id)) {
75942
- fs$5.rmSync(path$7.join(this._botsRoot, id), {
76146
+ fs$5.rmSync(path$6.join(this._botsRoot, id), {
75943
76147
  recursive: true,
75944
76148
  force: true,
75945
76149
  });
@@ -79159,7 +79363,7 @@ var PauseController_1 = PauseController$1;
79159
79363
  * Portable (NFR-006): the file path, fs and clock are injected; no Electron.
79160
79364
  */
79161
79365
 
79162
- const path$6 = require$$1$2;
79366
+ const path$5 = require$$1$2;
79163
79367
 
79164
79368
  const DEFAULT_MAX_BYTES = 2.5 * 1024 * 1024;
79165
79369
 
@@ -79297,7 +79501,7 @@ function createAuditLog$1({
79297
79501
  };
79298
79502
  let line = `${JSON.stringify(saved)}\n`;
79299
79503
  try {
79300
- fs.mkdirSync(path$6.dirname(file), { recursive: true });
79504
+ fs.mkdirSync(path$5.dirname(file), { recursive: true });
79301
79505
  // A torn last line (Dash quit mid-write) mustn't swallow this entry.
79302
79506
  if (!checkedEnd) {
79303
79507
  checkedEnd = true;
@@ -81127,7 +81331,7 @@ var placeWidget_1 = {
81127
81331
 
81128
81332
  const fs$3 = require$$0$3;
81129
81333
  const os = require$$2$1;
81130
- const path$5 = require$$1$2;
81334
+ const path$4 = require$$1$2;
81131
81335
 
81132
81336
  /** Registry sign-in state and the username that becomes the package scope. */
81133
81337
  async function registryIdentity$1() {
@@ -81154,8 +81358,8 @@ async function zipAndPublish$1(files, manifest) {
81154
81358
  const registryApiController = registryApiController$3;
81155
81359
  const zip = new AdmZip();
81156
81360
  for (const f of files) zip.addFile(f.name, Buffer.from(f.text, "utf8"));
81157
- const dir = fs$3.mkdtempSync(path$5.join(os.tmpdir(), "dash-bot-publish-"));
81158
- const zipPath = path$5.join(dir, `${manifest.name}-${manifest.version}.zip`);
81361
+ const dir = fs$3.mkdtempSync(path$4.join(os.tmpdir(), "dash-bot-publish-"));
81362
+ const zipPath = path$4.join(dir, `${manifest.name}-${manifest.version}.zip`);
81159
81363
  try {
81160
81364
  zip.writeZip(zipPath);
81161
81365
  const result = await registryApiController.publishToRegistry(
@@ -88219,7 +88423,7 @@ var teamDirectory = { summarizeTeams: summarizeTeams$1, summarizeLeads, resolveD
88219
88423
  * injected/portable modules; this file is the boundary.
88220
88424
  */
88221
88425
 
88222
- const path$4 = require$$1$2;
88426
+ const path$3 = require$$1$2;
88223
88427
  const { Cron } = require$$1$3;
88224
88428
  const { createElectronHost } = host;
88225
88429
  const BotStore = BotStoreExports;
@@ -90023,7 +90227,7 @@ const botController$1 = {
90023
90227
  toolName: req.toolName,
90024
90228
  args: req.input,
90025
90229
  },
90026
- { isWriteTool, pathArgKeys: PATH_ARG_KEYS, dirname: path$4.dirname },
90230
+ { isWriteTool, pathArgKeys: PATH_ARG_KEYS, dirname: path$3.dirname },
90027
90231
  );
90028
90232
  remembered = grantStore.setGrant(req.botId, next) === true;
90029
90233
  if (remembered) {
@@ -90454,7 +90658,7 @@ const botController$1 = {
90454
90658
  : undefined,
90455
90659
  // Sandbox dir for engines with native file/shell tools (claude-agent).
90456
90660
  workingDir: this._botsRoot
90457
- ? path$4.join(this._botsRoot, bot.id, "files")
90661
+ ? path$3.join(this._botsRoot, bot.id, "files")
90458
90662
  : undefined,
90459
90663
  };
90460
90664
  },
@@ -91942,13 +92146,14 @@ var botController_1 = botController$1;
91942
92146
  * applies event wiring. (Import is implemented in DASH-13.)
91943
92147
  */
91944
92148
 
91945
- const { app: app$3, dialog: dialog$1 } = require$$0$2;
91946
- const path$3 = require$$1$2;
92149
+ const { app: app$2, dialog: dialog$1 } = require$$0$2;
92150
+ const path$2 = require$$1$2;
91947
92151
  // The publish step reads each pinned widget's package.json for its
91948
92152
  // permissions (it never ran before: every dep came out unpinned).
91949
92153
  const fs$2 = require$$0$3;
91950
92154
  const AdmZip$1 = require$$3$1;
91951
92155
  const { getFileContents: getFileContents$1 } = file;
92156
+ const { getProfileFilePath: getProfileFilePath$1 } = profilePaths;
91952
92157
  const {
91953
92158
  validateDashboardConfig,
91954
92159
  applyDefaults,
@@ -91975,7 +92180,6 @@ const {
91975
92180
  const themeController$2 = themeController_1;
91976
92181
 
91977
92182
  const configFilename = "workspaces.json";
91978
- const appName$1 = "Dashboard";
91979
92183
 
91980
92184
  /**
91981
92185
  * Export a workspace as a .dashboard.json config inside a ZIP file.
@@ -91998,12 +92202,7 @@ async function exportDashboardConfig$1(
91998
92202
  ) {
91999
92203
  try {
92000
92204
  // 1. Read workspace from workspaces.json
92001
- const filename = path$3.join(
92002
- app$3.getPath("userData"),
92003
- appName$1,
92004
- appId,
92005
- configFilename,
92006
- );
92205
+ const filename = getProfileFilePath$1(appId, configFilename);
92007
92206
  const workspacesArray = getFileContents$1(filename);
92008
92207
  const workspace = workspacesArray.find(
92009
92208
  (w) => w.id === workspaceId || w.id === Number(workspaceId),
@@ -92122,8 +92321,8 @@ async function exportDashboardConfig$1(
92122
92321
 
92123
92322
  const { canceled, filePath } = await dialog$1.showSaveDialog(win, {
92124
92323
  title: "Export Dashboard as ZIP",
92125
- defaultPath: path$3.join(
92126
- app$3.getPath("desktop"),
92324
+ defaultPath: path$2.join(
92325
+ app$2.getPath("desktop"),
92127
92326
  `dashboard-${sanitizedName}.zip`,
92128
92327
  ),
92129
92328
  filters: [{ name: "ZIP Archive", extensions: ["zip"] }],
@@ -92190,7 +92389,7 @@ async function selectDashboardFile$1(win) {
92190
92389
 
92191
92390
  // Extract and validate
92192
92391
  const zip = new AdmZip$1(zipPath);
92193
- const tempDir = path$3.join(app$3.getPath("temp"), "dash-import");
92392
+ const tempDir = path$2.join(app$2.getPath("temp"), "dash-import");
92194
92393
  const { validateZipEntries } = widgetRegistryExports;
92195
92394
  validateZipEntries(zip, tempDir);
92196
92395
 
@@ -92300,7 +92499,7 @@ async function importDashboardConfig$1(
92300
92499
  const zip = new AdmZip$1(zipPath);
92301
92500
 
92302
92501
  // Validate ZIP entries for path traversal
92303
- const tempDir = path$3.join(app$3.getPath("temp"), "dash-import");
92502
+ const tempDir = path$2.join(app$2.getPath("temp"), "dash-import");
92304
92503
  const { validateZipEntries } = widgetRegistryExports;
92305
92504
  validateZipEntries(zip, tempDir);
92306
92505
 
@@ -92975,7 +93174,7 @@ async function downloadDashboardPackage(packageName, { purpose = null } = {}) {
92975
93174
  const zip = new AdmZip$1(zipBuffer);
92976
93175
 
92977
93176
  // 3. Validate ZIP entries
92978
- const tempDir = path$3.join(app$3.getPath("temp"), "dash-registry-import");
93177
+ const tempDir = path$2.join(app$2.getPath("temp"), "dash-registry-import");
92979
93178
  const { validateZipEntries } = widgetRegistryExports;
92980
93179
  validateZipEntries(zip, tempDir);
92981
93180
 
@@ -93152,12 +93351,7 @@ async function collectDashboardDependencies$1(
93152
93351
  ) {
93153
93352
  try {
93154
93353
  // 1. Read workspace
93155
- const filename = path$3.join(
93156
- app$3.getPath("userData"),
93157
- appName$1,
93158
- appId,
93159
- configFilename,
93160
- );
93354
+ const filename = getProfileFilePath$1(appId, configFilename);
93161
93355
  const workspacesArray = getFileContents$1(filename);
93162
93356
  const workspace = workspacesArray.find(
93163
93357
  (w) => w.id === workspaceId || w.id === Number(workspaceId),
@@ -93431,12 +93625,7 @@ async function prepareDashboardForPublish$1(
93431
93625
  const { resolveNextVersion } = requireWidgetPublishManifest();
93432
93626
 
93433
93627
  // 1. Read workspace
93434
- const filename = path$3.join(
93435
- app$3.getPath("userData"),
93436
- appName$1,
93437
- appId,
93438
- configFilename,
93439
- );
93628
+ const filename = getProfileFilePath$1(appId, configFilename);
93440
93629
  const workspacesArray = getFileContents$1(filename);
93441
93630
  const workspace = workspacesArray.find(
93442
93631
  (w) => w.id === workspaceId || w.id === Number(workspaceId),
@@ -93755,7 +93944,7 @@ async function prepareDashboardForPublish$1(
93755
93944
  );
93756
93945
  });
93757
93946
  if (!match || !match.path) continue;
93758
- const pkgJsonPath = path$3.join(match.path, "package.json");
93947
+ const pkgJsonPath = path$2.join(match.path, "package.json");
93759
93948
  if (!fs$2.existsSync(pkgJsonPath)) continue;
93760
93949
  try {
93761
93950
  const pkg = JSON.parse(fs$2.readFileSync(pkgJsonPath, "utf8"));
@@ -93799,8 +93988,8 @@ async function prepareDashboardForPublish$1(
93799
93988
  const sanitizedName = manifest.name;
93800
93989
  const { canceled, filePath } = await dialog$1.showSaveDialog(win, {
93801
93990
  title: "Save Dashboard Package for Registry",
93802
- defaultPath: path$3.join(
93803
- app$3.getPath("desktop"),
93991
+ defaultPath: path$2.join(
93992
+ app$2.getPath("desktop"),
93804
93993
  `dashboard-${sanitizedName}-v${manifest.version}.zip`,
93805
93994
  ),
93806
93995
  filters: [{ name: "ZIP Archive", extensions: ["zip"] }],
@@ -93969,12 +94158,7 @@ async function checkDashboardUpdatesForApp$1(appId) {
93969
94158
  const { fetchRegistryIndex } = registryController$3;
93970
94159
 
93971
94160
  try {
93972
- const filename = path$3.join(
93973
- app$3.getPath("userData"),
93974
- appName$1,
93975
- appId,
93976
- configFilename,
93977
- );
94161
+ const filename = getProfileFilePath$1(appId, configFilename);
93978
94162
  const workspaces = getFileContents$1(filename) || [];
93979
94163
 
93980
94164
  const index = await fetchRegistryIndex();
@@ -94040,12 +94224,7 @@ function getProviderSetupManifest$1(appId, requiredProviders = []) {
94040
94224
  */
94041
94225
  function getDashboardPublishPreview$1(appId, workspaceId, widgetRegistry = null) {
94042
94226
  try {
94043
- const filename = path$3.join(
94044
- app$3.getPath("userData"),
94045
- appName$1,
94046
- appId,
94047
- configFilename,
94048
- );
94227
+ const filename = getProfileFilePath$1(appId, configFilename);
94049
94228
  const workspacesArray = getFileContents$1(filename);
94050
94229
  const workspace = workspacesArray.find(
94051
94230
  (w) => w.id === workspaceId || w.id === Number(workspaceId),
@@ -94693,9 +94872,9 @@ var notificationController_1 = notificationController$2;
94693
94872
  * `consumers: Set` field, and re-gating sends would break that.
94694
94873
  */
94695
94874
 
94696
- const { app: app$2 } = require$$0$2;
94875
+ const { app: app$1 } = require$$0$2;
94697
94876
  const fs$1 = require$$0$3;
94698
- const path$2 = require$$1$2;
94877
+ const path$1 = require$$1$2;
94699
94878
  const WebSocket = require$$3$4;
94700
94879
  const {
94701
94880
  gateNetworkCall,
@@ -94705,8 +94884,8 @@ const { readEnforceFlag, readJitFlag } = securityFlags;
94705
94884
 
94706
94885
  function _loadFlags() {
94707
94886
  try {
94708
- const settingsPath = path$2.join(
94709
- app$2.getPath("userData"),
94887
+ const settingsPath = path$1.join(
94888
+ app$1.getPath("userData"),
94710
94889
  "Dashboard",
94711
94890
  "settings.json",
94712
94891
  );
@@ -96322,22 +96501,20 @@ var dashboardRatingsUtils = {
96322
96501
  * Runs in the Electron main process.
96323
96502
  */
96324
96503
 
96325
- const { app: app$1 } = require$$0$2;
96326
- const path$1 = require$$1$2;
96327
96504
  const { getFileContents, writeToFile } = file;
96328
96505
  const {
96329
96506
  validateAndBuildRating,
96330
96507
  enrichWithRatings,
96331
96508
  } = dashboardRatingsUtils;
96509
+ const { getProfileFilePath } = profilePaths;
96332
96510
 
96333
96511
  const ratingsFilename = "dashboard-ratings.json";
96334
- const appName = "Dashboard";
96335
96512
 
96336
96513
  /**
96337
96514
  * Get the ratings file path for an app.
96338
96515
  */
96339
96516
  function getRatingsPath(appId) {
96340
- return path$1.join(app$1.getPath("userData"), appName, appId, ratingsFilename);
96517
+ return getProfileFilePath(appId, ratingsFilename);
96341
96518
  }
96342
96519
 
96343
96520
  /**