@dimina-kit/devtools 0.3.2-dev.20260611063505 → 0.4.0-dev.20260612025610

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 (91) hide show
  1. package/README.md +56 -41
  2. package/dist/main/api.d.ts +4 -2
  3. package/dist/main/api.js +5 -1
  4. package/dist/main/app/app.d.ts +1 -5
  5. package/dist/main/app/app.js +25 -30
  6. package/dist/main/app/launch.d.ts +4 -4
  7. package/dist/main/app/launch.js +5 -17
  8. package/dist/main/index.bundle.js +535 -593
  9. package/dist/main/ipc/app.d.ts +1 -1
  10. package/dist/main/ipc/app.js +0 -7
  11. package/dist/main/ipc/index.d.ts +0 -2
  12. package/dist/main/ipc/index.js +0 -2
  13. package/dist/main/ipc/settings.d.ts +1 -1
  14. package/dist/main/ipc/settings.js +1 -13
  15. package/dist/main/ipc/simulator-module.d.ts +3 -3
  16. package/dist/main/ipc/simulator-module.js +3 -7
  17. package/dist/main/ipc/simulator.js +1 -12
  18. package/dist/main/menu/index.d.ts +2 -2
  19. package/dist/main/menu/index.js +4 -2
  20. package/dist/main/runtime/miniapp-runtime.d.ts +206 -28
  21. package/dist/main/runtime/miniapp-runtime.js +6 -11
  22. package/dist/main/services/layout/index.d.ts +0 -11
  23. package/dist/main/services/layout/index.js +0 -23
  24. package/dist/main/services/notifications/renderer-notifier.d.ts +0 -6
  25. package/dist/main/services/notifications/renderer-notifier.js +1 -10
  26. package/dist/main/services/service-host-pool/pool.d.ts +5 -4
  27. package/dist/main/services/views/host-toolbar-port-channel.d.ts +103 -0
  28. package/dist/main/services/views/host-toolbar-port-channel.js +248 -0
  29. package/dist/main/services/views/host-toolbar-session-runtime.d.ts +35 -0
  30. package/dist/main/services/views/host-toolbar-session-runtime.js +55 -0
  31. package/dist/main/services/views/view-manager.d.ts +80 -39
  32. package/dist/main/services/views/view-manager.js +153 -182
  33. package/dist/main/services/workbench-context.d.ts +13 -26
  34. package/dist/main/services/workbench-context.js +5 -14
  35. package/dist/main/services/workspace/workspace-service.d.ts +3 -7
  36. package/dist/main/services/workspace/workspace-service.js +34 -13
  37. package/dist/main/utils/paths.d.ts +11 -2
  38. package/dist/main/utils/paths.js +11 -2
  39. package/dist/main/windows/settings-window/index.d.ts +33 -0
  40. package/dist/main/windows/settings-window/index.js +59 -0
  41. package/dist/preload/index.d.ts +15 -0
  42. package/dist/preload/index.js +15 -0
  43. package/dist/preload/runtime/host-toolbar-port.d.ts +49 -0
  44. package/dist/preload/runtime/host-toolbar-port.js +151 -0
  45. package/dist/preload/runtime/host-toolbar-runtime.d.ts +41 -0
  46. package/dist/preload/runtime/host-toolbar-runtime.js +49 -0
  47. package/dist/preload/windows/{host-toolbar.cjs → host-toolbar-runtime.cjs} +103 -3
  48. package/dist/preload/windows/host-toolbar-runtime.cjs.map +7 -0
  49. package/dist/preload/windows/host-toolbar-runtime.d.ts +2 -0
  50. package/dist/preload/windows/host-toolbar-runtime.js +13 -0
  51. package/dist/preload/windows/simulator.cjs +0 -2
  52. package/dist/preload/windows/simulator.cjs.map +2 -2
  53. package/dist/preload/windows/simulator.js +0 -2
  54. package/dist/renderer/assets/constants-DI382mTP.js +2 -0
  55. package/dist/renderer/assets/index-DLzjz1wv.js +50 -0
  56. package/dist/renderer/assets/{input-CFHmbOgz.js → input-6fpCXV-n.js} +2 -2
  57. package/dist/renderer/assets/ipc-transport-Bs8Sf1B2.css +1 -0
  58. package/dist/renderer/assets/{ipc-transport-BkKKww3u.js → ipc-transport-D22e4dv7.js} +6 -6
  59. package/dist/renderer/assets/popover-CdGdKkkc.js +2 -0
  60. package/dist/renderer/assets/select-X0sbjwdP.js +2 -0
  61. package/dist/renderer/assets/{settings-Cl4IcWnG.js → settings-CS4jYaCw.js} +2 -2
  62. package/dist/renderer/assets/settings-api-CCWTAao_.js +2 -0
  63. package/dist/renderer/assets/workbenchSettings-Bpzaj3bm.js +8 -0
  64. package/dist/renderer/entries/main/index.html +7 -6
  65. package/dist/renderer/entries/popover/index.html +6 -6
  66. package/dist/renderer/entries/settings/index.html +5 -5
  67. package/dist/renderer/entries/workbench-settings/index.html +5 -5
  68. package/dist/shared/constants.d.ts +18 -0
  69. package/dist/shared/constants.js +18 -0
  70. package/dist/shared/ipc-channels.d.ts +10 -23
  71. package/dist/shared/ipc-channels.js +13 -34
  72. package/dist/shared/ipc-schemas.d.ts +0 -12
  73. package/dist/shared/ipc-schemas.js +0 -12
  74. package/dist/shared/types.d.ts +60 -76
  75. package/package.json +6 -6
  76. package/dist/main/ipc/panels.d.ts +0 -4
  77. package/dist/main/ipc/panels.js +0 -46
  78. package/dist/main/ipc/toolbar.d.ts +0 -4
  79. package/dist/main/ipc/toolbar.js +0 -21
  80. package/dist/main/services/toolbar/toolbar-store.d.ts +0 -23
  81. package/dist/main/services/toolbar/toolbar-store.js +0 -40
  82. package/dist/preload/windows/host-toolbar.cjs.map +0 -7
  83. package/dist/preload/windows/host-toolbar.d.ts +0 -2
  84. package/dist/preload/windows/host-toolbar.js +0 -12
  85. package/dist/renderer/assets/constants-CLAQX6VZ.js +0 -2
  86. package/dist/renderer/assets/index-CZQOpCvg.js +0 -50
  87. package/dist/renderer/assets/ipc-transport-Bv_BVu4T.css +0 -1
  88. package/dist/renderer/assets/popover-h1M7n3tt.js +0 -2
  89. package/dist/renderer/assets/select-kj0n1oYf.js +0 -2
  90. package/dist/renderer/assets/settings-api-CCwo2eOi.js +0 -2
  91. package/dist/renderer/assets/workbenchSettings-BzlpQnve.js +0 -8
@@ -10,6 +10,8 @@ import { app as app2, protocol } from "electron";
10
10
  // src/shared/constants.ts
11
11
  var DEFAULT_CDP_PORT = 9222;
12
12
  var DEFAULT_SCENE = 1001;
13
+ var HEADER_H = 40;
14
+ var HOST_TOOLBAR_RUNTIME_MARKER = "--dimina-host-toolbar";
13
15
 
14
16
  // src/main/services/settings/index.ts
15
17
  import { app, nativeTheme } from "electron";
@@ -314,8 +316,6 @@ var SimulatorChannel = {
314
316
  // mini-app sees the selected device without a relaunch.
315
317
  SetDeviceInfo: "simulator:set-device-info",
316
318
  Detach: "simulator:detach",
317
- Resize: "simulator:resize",
318
- SetVisible: "simulator:setVisible",
319
319
  Console: "simulator:console",
320
320
  // Main → renderer push of the visible top-of-stack page route whenever the
321
321
  // mini-app navigates (navigateTo / switchTab / back). Payload: the page path
@@ -332,7 +332,6 @@ var ServiceHostChannel = {
332
332
  HostEnvUpdate: "service-host:host-env:update"
333
333
  };
334
334
  var SimulatorCustomApiChannel = {
335
- List: "simulator:custom-apis:list",
336
335
  Invoke: "simulator:custom-apis:invoke"
337
336
  };
338
337
  var SimulatorCustomApiBridgeChannel = {
@@ -352,9 +351,6 @@ var SimulatorElementChannel = {
352
351
  Inspect: "simulator:element:inspect",
353
352
  Clear: "simulator:element:clear"
354
353
  };
355
- var WorkbenchRuntimeChannel = {
356
- GetNativeHost: "workbench:runtime:native-host"
357
- };
358
354
  var SimulatorWxmlChannel = {
359
355
  GetSnapshot: "simulator:wxml:snapshot",
360
356
  Event: "simulator:wxml:event"
@@ -369,7 +365,6 @@ var WorkbenchSettingsChannel = {
369
365
  SetTheme: "workbenchSettings:setTheme",
370
366
  GetCdpStatus: "workbenchSettings:getCdpStatus",
371
367
  GetMcpStatus: "workbenchSettings:getMcpStatus",
372
- SetVisible: "workbenchSettings:setVisible",
373
368
  Init: "workbenchSettings:init"
374
369
  };
375
370
  var ProjectChannel = {
@@ -416,12 +411,6 @@ var ProjectsChannel = {
416
411
  var DialogChannel = {
417
412
  OpenDirectory: "dialog:openDirectory"
418
413
  };
419
- var PanelChannel = {
420
- List: "panel:list",
421
- Eval: "panel:eval",
422
- Select: "panel:select",
423
- SelectSimulator: "panel:selectSimulator"
424
- };
425
414
  var ViewChannel = {
426
415
  /** Update the simulator DevTools view's bounds (or hide if w/h = 0). */
427
416
  SimulatorDevtoolsBounds: "view:simulator:devtools-bounds",
@@ -437,6 +426,16 @@ var ViewChannel = {
437
426
  * `{ axis: 'block', extent }`. fire-and-forget (send), NOT invoke.
438
427
  */
439
428
  HostToolbarAdvertiseHeight: "view:host-toolbar:advertise-height",
429
+ /**
430
+ * main → host-toolbar WCV renderer: per-load MessagePort handshake for the
431
+ * gated narrow channel. On every toolbar `did-finish-load` main creates a
432
+ * `MessageChannelMain` and transfers port2 here
433
+ * (`wc.postMessage(HostToolbarPort, null, [port2])`); the session-resident
434
+ * toolbar runtime preload receives it via `event.ports[0]` and bridges it to
435
+ * the page as `window.diminaHostToolbar`. Envelope both directions:
436
+ * `{ channel: string, payload: unknown }`.
437
+ */
438
+ HostToolbarPort: "view:host-toolbar:port",
440
439
  /**
441
440
  * main → main-window renderer: push the reserved host-toolbar height so the
442
441
  * renderer placeholder div resizes (closing the dynamic-height loop).
@@ -450,19 +449,11 @@ var PopoverChannel = {
450
449
  Closed: "popover:closed",
451
450
  Init: "popover:init"
452
451
  };
453
- var ToolbarChannel = {
454
- GetActions: "toolbar:getActions",
455
- ActionsChanged: "toolbar:actionsChanged",
456
- /** Invoke a toolbar action by id: `invoke(Invoke, actionId)`. */
457
- Invoke: "toolbar:invoke"
458
- };
459
452
  var WindowChannel = {
460
453
  NavigateBack: "window:navigateBack"
461
454
  };
462
455
  var AppChannel = {
463
- GetPreloadPath: "app:getPreloadPath",
464
- GetBranding: "app:getBranding",
465
- GetHeaderHeight: "app:getHeaderHeight"
456
+ GetBranding: "app:getBranding"
466
457
  };
467
458
  var AutomationChannel = {
468
459
  GetPort: "automation:port"
@@ -471,9 +462,7 @@ var SettingsChannel = {
471
462
  SetVisible: "settings:setVisible",
472
463
  ConfigChanged: "settings:configChanged",
473
464
  ProjectSettingsChanged: "settings:projectSettingsChanged",
474
- Init: "settings:init",
475
- Closed: "settings:closed",
476
- Changed: "settings:changed"
465
+ Init: "settings:init"
477
466
  };
478
467
  var UpdateChannel = {
479
468
  Check: "updates:check",
@@ -751,9 +740,9 @@ function registerProjectFsIpc(ctx) {
751
740
  }
752
741
 
753
742
  // src/main/app/app.ts
754
- import { app as app14, BrowserWindow as BrowserWindow7, nativeImage, session as session3 } from "electron";
755
- import fs11 from "fs";
756
- import path20 from "path";
743
+ import { app as app14, BrowserWindow as BrowserWindow8, nativeImage, session as session4 } from "electron";
744
+ import fs10 from "fs";
745
+ import path21 from "path";
757
746
 
758
747
  // src/main/utils/paths.ts
759
748
  import fs3 from "fs";
@@ -780,9 +769,9 @@ function cjsSiblingPreloadPath(preloadPath) {
780
769
  return preloadPath.endsWith(".js") ? preloadPath.slice(0, -".js".length) + ".cjs" : preloadPath;
781
770
  }
782
771
  var mainPreloadPath = path3.join(devtoolsPackageRoot, "dist/preload/windows/main.cjs");
783
- var hostToolbarPreloadPath = path3.join(
772
+ var hostToolbarRuntimePreloadPath = path3.join(
784
773
  devtoolsPackageRoot,
785
- "dist/preload/windows/host-toolbar.cjs"
774
+ "dist/preload/windows/host-toolbar-runtime.cjs"
786
775
  );
787
776
  var simulatorDir = path3.join(devtoolsPackageRoot, "dist/simulator");
788
777
 
@@ -980,21 +969,12 @@ function createRendererNotifier(ctx) {
980
969
  windowNavigateBack() {
981
970
  sendToMain(WindowChannel.NavigateBack);
982
971
  },
983
- settingsClosed() {
984
- sendToMain(SettingsChannel.Closed);
985
- },
986
- settingsChanged(config) {
987
- sendToMain(SettingsChannel.Changed, config);
988
- },
989
972
  popoverClosed() {
990
973
  sendToMain(PopoverChannel.Closed);
991
974
  },
992
975
  popoverRelaunch(config) {
993
976
  sendToMain(PopoverChannel.Relaunch, config);
994
977
  },
995
- toolbarActionsChanged() {
996
- sendToMain(ToolbarChannel.ActionsChanged);
997
- },
998
978
  hostToolbarHeightChanged(height) {
999
979
  sendToMain(ViewChannel.HostToolbarHeightChanged, height);
1000
980
  },
@@ -1531,22 +1511,6 @@ function installElementsForward(deps) {
1531
1511
  }
1532
1512
 
1533
1513
  // src/main/services/layout/index.ts
1534
- var SPLITTER_W = 4;
1535
- function getRightX(simWidth) {
1536
- return simWidth + SPLITTER_W;
1537
- }
1538
- function computeRightPanelBounds(contentWidth, contentHeight, simWidth, headerHeight) {
1539
- const x = getRightX(simWidth);
1540
- return {
1541
- x,
1542
- y: headerHeight,
1543
- width: Math.max(1, contentWidth - x),
1544
- height: Math.max(1, contentHeight - headerHeight)
1545
- };
1546
- }
1547
- function computeSimulatorBounds(contentWidth, contentHeight, simWidth, headerHeight) {
1548
- return computeRightPanelBounds(contentWidth, contentHeight, simWidth, headerHeight);
1549
- }
1550
1514
  function computeNativeSimulatorViewParams(rect, zoomPercent) {
1551
1515
  const zoomFactor = zoomPercent / 100;
1552
1516
  return {
@@ -1664,6 +1628,159 @@ function configureMiniappSession(partition) {
1664
1628
  return sess;
1665
1629
  }
1666
1630
 
1631
+ // src/main/services/views/host-toolbar-session-runtime.ts
1632
+ import { session as session2 } from "electron";
1633
+ var refCount = 0;
1634
+ var registrationId = null;
1635
+ function acquireHostToolbarSessionRuntime() {
1636
+ if (refCount === 0) {
1637
+ registrationId = session2.defaultSession.registerPreloadScript({
1638
+ type: "frame",
1639
+ filePath: hostToolbarRuntimePreloadPath
1640
+ });
1641
+ }
1642
+ refCount++;
1643
+ }
1644
+ function releaseHostToolbarSessionRuntime() {
1645
+ if (refCount === 0) return;
1646
+ refCount--;
1647
+ if (refCount === 0 && registrationId !== null) {
1648
+ session2.defaultSession.unregisterPreloadScript(registrationId);
1649
+ registrationId = null;
1650
+ }
1651
+ }
1652
+
1653
+ // src/main/services/views/host-toolbar-port-channel.ts
1654
+ import { MessageChannelMain } from "electron";
1655
+ function createHostToolbarPortChannel(opts) {
1656
+ let activePort = null;
1657
+ let activeWc = null;
1658
+ let state = "absent";
1659
+ let generation = 0;
1660
+ const handlers2 = [];
1661
+ const readyHandlers = [];
1662
+ function dispatch(data) {
1663
+ if (typeof data !== "object" || data === null) return;
1664
+ const { channel, payload } = data;
1665
+ if (typeof channel !== "string") return;
1666
+ for (const entry of [...handlers2]) {
1667
+ if (entry.channel === channel) entry.handler(payload);
1668
+ }
1669
+ }
1670
+ function dropActivePort(close, next) {
1671
+ const port = activePort;
1672
+ activePort = null;
1673
+ activeWc = null;
1674
+ if (state !== "disposed") state = next;
1675
+ if (close && port) {
1676
+ try {
1677
+ port.close();
1678
+ } catch {
1679
+ }
1680
+ }
1681
+ }
1682
+ function invokeReadyHandler(handler) {
1683
+ try {
1684
+ handler();
1685
+ } catch (err) {
1686
+ console.error("[host-toolbar] onReady handler threw:", err);
1687
+ }
1688
+ }
1689
+ function fireReadyHandlers() {
1690
+ for (const entry of [...readyHandlers]) {
1691
+ if (readyHandlers.includes(entry)) invokeReadyHandler(entry.handler);
1692
+ }
1693
+ }
1694
+ function handshake(wc) {
1695
+ if (state === "disposed") return;
1696
+ if (!opts.isCurrent(wc)) return;
1697
+ dropActivePort(true, "awaitingHandshake");
1698
+ const { port1, port2 } = new MessageChannelMain();
1699
+ port1.on("message", (event) => {
1700
+ dispatch(event.data);
1701
+ });
1702
+ port1.on("close", () => {
1703
+ if (activePort === port1) dropActivePort(false, "absent");
1704
+ });
1705
+ wc.postMessage(ViewChannel.HostToolbarPort, null, [port2]);
1706
+ port1.start();
1707
+ activePort = port1;
1708
+ activeWc = wc;
1709
+ state = "ready";
1710
+ generation++;
1711
+ fireReadyHandlers();
1712
+ }
1713
+ return {
1714
+ attach(wc) {
1715
+ wc.on("did-finish-load", () => handshake(wc));
1716
+ wc.on(
1717
+ "did-start-navigation",
1718
+ (details, _url, isInPlace, isMainFramePositional) => {
1719
+ if (activeWc !== wc) return;
1720
+ const isSameDocument = typeof details?.isSameDocument === "boolean" ? details.isSameDocument : isInPlace;
1721
+ const isMainFrame = typeof details?.isMainFrame === "boolean" ? details.isMainFrame : isMainFramePositional;
1722
+ if (isSameDocument || !isMainFrame) return;
1723
+ dropActivePort(true, "awaitingHandshake");
1724
+ }
1725
+ );
1726
+ wc.on("destroyed", () => {
1727
+ if (activeWc === wc) dropActivePort(true, "absent");
1728
+ });
1729
+ },
1730
+ invalidate() {
1731
+ dropActivePort(true, "awaitingHandshake");
1732
+ },
1733
+ onMessage(channel, handler) {
1734
+ if (typeof channel !== "string" || channel === "") {
1735
+ throw new TypeError(
1736
+ "hostToolbar.onMessage: channel must be a non-empty string"
1737
+ );
1738
+ }
1739
+ const entry = { channel, handler };
1740
+ handlers2.push(entry);
1741
+ return {
1742
+ dispose() {
1743
+ const i = handlers2.indexOf(entry);
1744
+ if (i >= 0) handlers2.splice(i, 1);
1745
+ }
1746
+ };
1747
+ },
1748
+ onReady(handler) {
1749
+ if (state === "disposed") {
1750
+ return { dispose() {
1751
+ } };
1752
+ }
1753
+ const entry = { handler };
1754
+ readyHandlers.push(entry);
1755
+ if (state === "ready") {
1756
+ const scheduledGeneration = generation;
1757
+ queueMicrotask(() => {
1758
+ if (state !== "ready" || generation !== scheduledGeneration || !activePort) return;
1759
+ if (!readyHandlers.includes(entry)) return;
1760
+ invokeReadyHandler(entry.handler);
1761
+ });
1762
+ }
1763
+ return {
1764
+ dispose() {
1765
+ const i = readyHandlers.indexOf(entry);
1766
+ if (i >= 0) readyHandlers.splice(i, 1);
1767
+ }
1768
+ };
1769
+ },
1770
+ send(channel, payload) {
1771
+ if (!activePort) return false;
1772
+ activePort.postMessage({ channel, payload });
1773
+ return true;
1774
+ },
1775
+ dispose() {
1776
+ dropActivePort(true, "absent");
1777
+ state = "disposed";
1778
+ handlers2.length = 0;
1779
+ readyHandlers.length = 0;
1780
+ }
1781
+ };
1782
+ }
1783
+
1667
1784
  // src/shared/simulator-route.ts
1668
1785
  function decodePageSpec(value) {
1669
1786
  const qIdx = value.indexOf("?");
@@ -1701,7 +1818,6 @@ function parseRoute(url) {
1701
1818
 
1702
1819
  // src/main/services/views/view-manager.ts
1703
1820
  function createViewManager(ctx) {
1704
- const headerHeight = ctx.headerHeight ?? 40;
1705
1821
  const safeArea = createSafeAreaController({ connections: ctx.connections });
1706
1822
  let simulatorView = null;
1707
1823
  let simulatorViewAdded = false;
@@ -1713,7 +1829,6 @@ function createViewManager(ctx) {
1713
1829
  let settingsView = null;
1714
1830
  let settingsViewAdded = false;
1715
1831
  let popoverView = null;
1716
- let lastSimWidth = 375;
1717
1832
  let simulatorWebContentsId = null;
1718
1833
  let nativeDevtoolsSourceWc = null;
1719
1834
  let unsubscribeNativeRenderEvents = null;
@@ -1724,6 +1839,11 @@ function createViewManager(ctx) {
1724
1839
  let hostToolbarView = null;
1725
1840
  let hostToolbarPreloadOverride = null;
1726
1841
  let hostToolbarViewAdded = false;
1842
+ let hostToolbarRuntimeAcquired = false;
1843
+ let hostToolbarHeightMode = "auto";
1844
+ const hostToolbarPort = createHostToolbarPortChannel({
1845
+ isCurrent: (wc) => liveHostToolbarWebContents() === wc
1846
+ });
1727
1847
  function destroyViewInternal(view) {
1728
1848
  if (!view) return;
1729
1849
  if (!ctx.windows.mainWindow.isDestroyed()) {
@@ -1739,17 +1859,6 @@ function createViewManager(ctx) {
1739
1859
  } catch {
1740
1860
  }
1741
1861
  }
1742
- function applySimulatorBounds(simWidth) {
1743
- if (!simulatorView || ctx.windows.mainWindow.isDestroyed()) return;
1744
- if (simulatorBoundsOverride) {
1745
- simulatorView.setBounds(simulatorBoundsOverride);
1746
- return;
1747
- }
1748
- const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
1749
- simulatorView.setBounds(
1750
- computeSimulatorBounds(w, h, simWidth, headerHeight)
1751
- );
1752
- }
1753
1862
  function isHidden(b) {
1754
1863
  return b.width <= 0 || b.height <= 0;
1755
1864
  }
@@ -1773,8 +1882,13 @@ function createViewManager(ctx) {
1773
1882
  }
1774
1883
  simulatorView.setBounds(bounds);
1775
1884
  }
1885
+ function liveHostToolbarWebContents() {
1886
+ const wc = hostToolbarView?.webContents;
1887
+ if (!wc || wc.isDestroyed()) return null;
1888
+ return wc;
1889
+ }
1776
1890
  function ensureHostToolbarView() {
1777
- if (hostToolbarView && !hostToolbarView.webContents.isDestroyed()) {
1891
+ if (hostToolbarView && liveHostToolbarWebContents()) {
1778
1892
  return hostToolbarView;
1779
1893
  }
1780
1894
  if (hostToolbarView && hostToolbarViewAdded) {
@@ -1784,21 +1898,22 @@ function createViewManager(ctx) {
1784
1898
  }
1785
1899
  hostToolbarViewAdded = false;
1786
1900
  }
1787
- const view = new WebContentsView2({
1788
- webPreferences: {
1789
- nodeIntegration: false,
1790
- contextIsolation: true,
1791
- sandbox: false,
1792
- // Default: the reverse size-advertiser preload that measures the host
1793
- // content's intrinsic height and posts it on the advertise channel so
1794
- // main reserves exactly that strip height (dynamic height via
1795
- // ViewAnchor). When the host-shell supplies its own toolbar preload
1796
- // (workbench config.toolbar.preloadPath), use that instead — the host
1797
- // owns the bridge and may install the advertiser itself.
1798
- preload: hostToolbarPreloadOverride ?? hostToolbarPreloadPath
1799
- }
1800
- });
1901
+ if (!hostToolbarRuntimeAcquired) {
1902
+ acquireHostToolbarSessionRuntime();
1903
+ hostToolbarRuntimeAcquired = true;
1904
+ }
1905
+ const webPreferences = {
1906
+ nodeIntegration: false,
1907
+ contextIsolation: true,
1908
+ sandbox: false,
1909
+ additionalArguments: [HOST_TOOLBAR_RUNTIME_MARKER]
1910
+ };
1911
+ if (hostToolbarPreloadOverride !== null) {
1912
+ webPreferences.preload = hostToolbarPreloadOverride;
1913
+ }
1914
+ const view = new WebContentsView2({ webPreferences });
1801
1915
  hostToolbarView = view;
1916
+ hostToolbarPort.attach(view.webContents);
1802
1917
  try {
1803
1918
  view.setBackgroundColor("#121212");
1804
1919
  } catch {
@@ -1812,7 +1927,7 @@ function createViewManager(ctx) {
1812
1927
  function setHostToolbarBounds(bounds) {
1813
1928
  if (ctx.windows.mainWindow.isDestroyed()) return;
1814
1929
  if (isHidden(bounds)) {
1815
- if (hostToolbarView && hostToolbarViewAdded && !hostToolbarView.webContents.isDestroyed()) {
1930
+ if (hostToolbarView && hostToolbarViewAdded && liveHostToolbarWebContents()) {
1816
1931
  try {
1817
1932
  ctx.windows.mainWindow.contentView.removeChildView(hostToolbarView);
1818
1933
  } catch {
@@ -1829,6 +1944,7 @@ function createViewManager(ctx) {
1829
1944
  view.setBounds(bounds);
1830
1945
  }
1831
1946
  function setHostToolbarHeight(extent) {
1947
+ if (hostToolbarHeightMode !== "auto") return;
1832
1948
  ctx.notify.hostToolbarHeightChanged(extent);
1833
1949
  }
1834
1950
  function hideHostToolbar() {
@@ -1844,33 +1960,53 @@ function createViewManager(ctx) {
1844
1960
  const hostToolbar = {
1845
1961
  async loadURL(url) {
1846
1962
  const view = ensureHostToolbarView();
1963
+ hostToolbarPort.invalidate();
1847
1964
  await view.webContents.loadURL(url);
1848
1965
  },
1849
1966
  async loadFile(filePath) {
1850
1967
  const view = ensureHostToolbarView();
1968
+ hostToolbarPort.invalidate();
1851
1969
  await view.webContents.loadFile(filePath);
1852
1970
  },
1853
1971
  get webContents() {
1854
- if (!hostToolbarView) return null;
1855
- if (hostToolbarView.webContents.isDestroyed()) return null;
1856
- return hostToolbarView.webContents;
1972
+ return liveHostToolbarWebContents();
1857
1973
  },
1858
1974
  hide() {
1859
1975
  hideHostToolbar();
1860
1976
  },
1861
1977
  setPreloadPath(path22) {
1862
1978
  hostToolbarPreloadOverride = path22;
1979
+ },
1980
+ setHeightMode(mode) {
1981
+ if (mode !== "auto" && !(Number.isFinite(mode.fixed) && mode.fixed >= 0)) {
1982
+ throw new TypeError(
1983
+ `hostToolbar.setHeightMode: fixed height must be a finite, non-negative number (got ${mode.fixed})`
1984
+ );
1985
+ }
1986
+ hostToolbarHeightMode = mode;
1987
+ if (mode !== "auto") {
1988
+ ctx.notify.hostToolbarHeightChanged(mode.fixed);
1989
+ }
1990
+ },
1991
+ onMessage(channel, handler) {
1992
+ return hostToolbarPort.onMessage(channel, handler);
1993
+ },
1994
+ onReady(handler) {
1995
+ return hostToolbarPort.onReady(handler);
1996
+ },
1997
+ send(channel, payload) {
1998
+ return hostToolbarPort.send(channel, payload);
1863
1999
  }
1864
2000
  };
1865
2001
  function applySettingsBounds() {
1866
2002
  if (!settingsView || ctx.windows.mainWindow.isDestroyed()) return;
1867
2003
  const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
1868
- settingsView.setBounds(computeSettingsBounds(w, h, headerHeight));
2004
+ settingsView.setBounds(computeSettingsBounds(w, h, HEADER_H));
1869
2005
  }
1870
2006
  function applyPopoverBounds() {
1871
2007
  if (!popoverView || ctx.windows.mainWindow.isDestroyed()) return;
1872
2008
  const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
1873
- popoverView.setBounds(computePopoverBounds(w, h, headerHeight));
2009
+ popoverView.setBounds(computePopoverBounds(w, h, HEADER_H));
1874
2010
  }
1875
2011
  function clearNativeDevtoolsRetry() {
1876
2012
  nativeDevtoolsRetryToken++;
@@ -2031,71 +2167,10 @@ function createViewManager(ctx) {
2031
2167
  if (event.kind !== "activePage" && event.kind !== "domReady") return;
2032
2168
  followNativeDevtoolsServiceHost(event.appId);
2033
2169
  }
2034
- function attachSimulator(simWcId, simWidth) {
2035
- const sim = webContents.fromId(simWcId);
2036
- if (!sim) {
2037
- console.error("[workbench] attachSimulator \u2014 simWc not found for id", simWcId);
2038
- return;
2039
- }
2040
- lastSimWidth = simWidth;
2041
- simulatorWebContentsId = simWcId;
2042
- if (simulatorView) {
2043
- hideSimulator();
2044
- try {
2045
- if (!simulatorView.webContents.isDestroyed()) {
2046
- simulatorView.webContents.close();
2047
- }
2048
- } catch {
2049
- }
2050
- simulatorView = null;
2051
- }
2052
- simulatorView = new WebContentsView2();
2053
- sim.setDevToolsWebContents(simulatorView.webContents);
2054
- sim.openDevTools({ mode: "detach", activate: false });
2055
- const devtoolsWc = simulatorView.webContents;
2056
- customizeDevtoolsTabs(devtoolsWc);
2057
- devtoolsWc.once("dom-ready", () => {
2058
- devtoolsWc.executeJavaScript(`
2059
- (function() {
2060
- try { localStorage.setItem('panel-selectedTab', '"console"') } catch {}
2061
- let tries = 0
2062
- const timer = setInterval(() => {
2063
- tries++
2064
- try {
2065
- const UI = globalThis.UI
2066
- const vm = UI && UI.ViewManager && typeof UI.ViewManager.instance === 'function'
2067
- ? UI.ViewManager.instance()
2068
- : null
2069
- if (vm && typeof vm.showView === 'function') {
2070
- vm.showView('console')
2071
- clearInterval(timer)
2072
- return
2073
- }
2074
- } catch {}
2075
- if (tries > 80) clearInterval(timer)
2076
- }, 50)
2077
- })()
2078
- `).catch(() => {
2079
- });
2080
- });
2081
- if (getDefaultTab(ctx) === "simulator") {
2082
- if (simulatorBoundsOverride) {
2083
- if (!isHidden(simulatorBoundsOverride)) {
2084
- ctx.windows.mainWindow.contentView.addChildView(simulatorView);
2085
- simulatorViewAdded = true;
2086
- simulatorView.setBounds(simulatorBoundsOverride);
2087
- }
2088
- } else {
2089
- ctx.windows.mainWindow.contentView.addChildView(simulatorView);
2090
- simulatorViewAdded = true;
2091
- applySimulatorBounds(simWidth);
2092
- }
2093
- }
2094
- }
2095
- function attachNativeSimulatorDevtoolsHost(simWidth) {
2170
+ function attachNativeSimulatorDevtoolsHost() {
2096
2171
  stopFollowingNativeServiceHost();
2097
2172
  if (simulatorView) {
2098
- hideSimulator();
2173
+ removeSimulatorDevtoolsView();
2099
2174
  try {
2100
2175
  if (!simulatorView.webContents.isDestroyed()) {
2101
2176
  simulatorView.webContents.close();
@@ -2145,18 +2220,10 @@ function createViewManager(ctx) {
2145
2220
  `).catch(() => {
2146
2221
  });
2147
2222
  });
2148
- if (getDefaultTab(ctx) === "simulator") {
2149
- if (simulatorBoundsOverride) {
2150
- if (!isHidden(simulatorBoundsOverride)) {
2151
- ctx.windows.mainWindow.contentView.addChildView(simulatorView);
2152
- simulatorViewAdded = true;
2153
- simulatorView.setBounds(simulatorBoundsOverride);
2154
- }
2155
- } else {
2156
- ctx.windows.mainWindow.contentView.addChildView(simulatorView);
2157
- simulatorViewAdded = true;
2158
- applySimulatorBounds(simWidth);
2159
- }
2223
+ if (simulatorBoundsOverride && !isHidden(simulatorBoundsOverride)) {
2224
+ ctx.windows.mainWindow.contentView.addChildView(simulatorView);
2225
+ simulatorViewAdded = true;
2226
+ simulatorView.setBounds(simulatorBoundsOverride);
2160
2227
  }
2161
2228
  if (ctx.bridge?.isNativeHost()) {
2162
2229
  unsubscribeNativeRenderEvents = ctx.bridge.onRenderEvent(onNativeRenderEvent);
@@ -2188,12 +2255,11 @@ function createViewManager(ctx) {
2188
2255
  ipcMain2.on(SimulatorCustomApiBridgeChannel.Request, handler);
2189
2256
  ctx.connections.acquire(simWc).own(detachNativeCustomApiBridge);
2190
2257
  }
2191
- function attachNativeSimulator(simulatorUrl, simWidth) {
2258
+ function attachNativeSimulator(simulatorUrl, _simWidth) {
2192
2259
  if (!ctx.preloadPath) {
2193
2260
  console.error("[workbench] attachNativeSimulator \u2014 preloadPath unset; cannot mount native simulator");
2194
2261
  return;
2195
2262
  }
2196
- lastSimWidth = simWidth;
2197
2263
  if (nativeSimulatorView) {
2198
2264
  detachNativeCustomApiBridge();
2199
2265
  if (nativeSimulatorViewAdded) {
@@ -2285,7 +2351,7 @@ function createViewManager(ctx) {
2285
2351
  if (lastRendererRect) {
2286
2352
  setNativeSimulatorViewBounds(lastRendererRect);
2287
2353
  }
2288
- attachNativeSimulatorDevtoolsHost(simWidth);
2354
+ attachNativeSimulatorDevtoolsHost();
2289
2355
  }
2290
2356
  function detachSimulator() {
2291
2357
  stopFollowingNativeServiceHost();
@@ -2324,21 +2390,12 @@ function createViewManager(ctx) {
2324
2390
  simulatorBoundsOverride = null;
2325
2391
  lastRendererRect = null;
2326
2392
  }
2327
- function showSimulator(simWidth) {
2328
- lastSimWidth = simWidth;
2329
- if (!simulatorView) return;
2330
- if (!simulatorViewAdded) {
2331
- ctx.windows.mainWindow.contentView.addChildView(simulatorView);
2332
- simulatorViewAdded = true;
2333
- }
2334
- applySimulatorBounds(simWidth);
2335
- }
2336
- function hideSimulator() {
2393
+ function removeSimulatorDevtoolsView() {
2337
2394
  if (simulatorView && simulatorViewAdded) {
2338
2395
  try {
2339
2396
  ctx.windows.mainWindow.contentView.removeChildView(simulatorView);
2340
2397
  } catch (e) {
2341
- console.error("[workbench] hideSimulator error", e);
2398
+ console.error("[workbench] removeSimulatorDevtoolsView error", e);
2342
2399
  }
2343
2400
  simulatorViewAdded = false;
2344
2401
  }
@@ -2403,8 +2460,6 @@ function createViewManager(ctx) {
2403
2460
  }
2404
2461
  }
2405
2462
  function repositionAll() {
2406
- if (simulatorView && simulatorViewAdded)
2407
- applySimulatorBounds(lastSimWidth);
2408
2463
  if (settingsView && settingsViewAdded)
2409
2464
  applySettingsBounds();
2410
2465
  if (popoverView)
@@ -2412,9 +2467,14 @@ function createViewManager(ctx) {
2412
2467
  }
2413
2468
  function disposeAll() {
2414
2469
  detachSimulator();
2470
+ hostToolbarPort.dispose();
2415
2471
  destroyViewInternal(hostToolbarView);
2416
2472
  hostToolbarView = null;
2417
2473
  hostToolbarViewAdded = false;
2474
+ if (hostToolbarRuntimeAcquired) {
2475
+ releaseHostToolbarSessionRuntime();
2476
+ hostToolbarRuntimeAcquired = false;
2477
+ }
2418
2478
  safeArea.dispose();
2419
2479
  }
2420
2480
  function setNativeSimulatorViewBounds(params) {
@@ -2451,27 +2511,13 @@ function createViewManager(ctx) {
2451
2511
  } catch {
2452
2512
  }
2453
2513
  }
2454
- function resize(simWidth) {
2455
- lastSimWidth = simWidth;
2456
- if (simulatorViewAdded) applySimulatorBounds(simWidth);
2514
+ function resize(_simWidth) {
2457
2515
  if (settingsViewAdded) applySettingsBounds();
2458
2516
  }
2459
- function setVisible(visible, simWidth) {
2460
- lastSimWidth = simWidth;
2461
- if (!simulatorView) return;
2462
- if (visible && !simulatorViewAdded) {
2463
- showSimulator(simWidth);
2464
- } else if (!visible) {
2465
- hideSimulator();
2466
- }
2467
- }
2468
2517
  return {
2469
- attachSimulator,
2470
2518
  attachNativeSimulator,
2471
2519
  detachSimulator,
2472
2520
  reapplySafeArea: (device) => safeArea.reapplyAll(device),
2473
- showSimulator,
2474
- hideSimulator,
2475
2521
  showSettings,
2476
2522
  hideSettings,
2477
2523
  showPopover,
@@ -2484,9 +2530,6 @@ function createViewManager(ctx) {
2484
2530
  const wc = webContents.fromId(simulatorWebContentsId);
2485
2531
  return wc && !wc.isDestroyed() ? wc : null;
2486
2532
  },
2487
- getLastSimWidth: () => lastSimWidth,
2488
- isSimulatorAdded: () => simulatorViewAdded,
2489
- hasSimulatorView: () => simulatorView !== null,
2490
2533
  getSettingsWebContents: () => {
2491
2534
  if (!settingsView) return null;
2492
2535
  if (settingsView.webContents.isDestroyed()) return null;
@@ -2502,14 +2545,9 @@ function createViewManager(ctx) {
2502
2545
  if (popoverView.webContents.isDestroyed()) return null;
2503
2546
  return popoverView.webContents.id;
2504
2547
  },
2505
- getHostToolbarWebContentsId: () => {
2506
- if (!hostToolbarView) return null;
2507
- if (hostToolbarView.webContents.isDestroyed()) return null;
2508
- return hostToolbarView.webContents.id;
2509
- },
2548
+ getHostToolbarWebContentsId: () => liveHostToolbarWebContents()?.id ?? null,
2510
2549
  setNativeSimulatorViewBounds,
2511
2550
  resize,
2512
- setVisible,
2513
2551
  setSimulatorDevtoolsBounds,
2514
2552
  setHostToolbarBounds,
2515
2553
  setHostToolbarHeight,
@@ -2543,13 +2581,82 @@ function createWindowService(mainWindow) {
2543
2581
  };
2544
2582
  }
2545
2583
 
2584
+ // src/main/windows/settings-window/create.ts
2585
+ import { BrowserWindow as BrowserWindow3 } from "electron";
2586
+ import path8 from "path";
2587
+ async function createSettingsWindow(parent, rendererDir2) {
2588
+ const win = new BrowserWindow3({
2589
+ width: 420,
2590
+ height: 560,
2591
+ minWidth: 380,
2592
+ minHeight: 480,
2593
+ parent: parent ?? void 0,
2594
+ title: "\u5F00\u53D1\u5DE5\u5177\u8BBE\u7F6E",
2595
+ backgroundColor: themeBg(),
2596
+ webPreferences: {
2597
+ nodeIntegration: false,
2598
+ contextIsolation: true,
2599
+ sandbox: false,
2600
+ preload: mainPreloadPath
2601
+ }
2602
+ });
2603
+ applyNavigationHardening(win.webContents, rendererDir2);
2604
+ await win.loadFile(path8.join(rendererDir2, "entries/workbench-settings/index.html"));
2605
+ return win;
2606
+ }
2607
+
2608
+ // src/main/windows/settings-window/events.ts
2609
+ function wireSettingsWindowEvents(win, onClosed) {
2610
+ win.on("closed", () => {
2611
+ onClosed();
2612
+ });
2613
+ }
2614
+
2615
+ // src/main/windows/settings-window/index.ts
2616
+ var inFlightCreations = /* @__PURE__ */ new WeakMap();
2617
+ async function getOrCreateSettingsWindow(deps) {
2618
+ const existing = deps.windows.settingsWindow;
2619
+ if (existing && !existing.isDestroyed()) return existing;
2620
+ const inFlight = inFlightCreations.get(deps.windows);
2621
+ if (inFlight) return inFlight;
2622
+ const creation = (async () => {
2623
+ const win = await createSettingsWindow(deps.windows.mainWindow, deps.rendererDir);
2624
+ deps.windows.setSettingsWindow(win);
2625
+ wireSettingsWindowEvents(win, () => {
2626
+ if (deps.windows.settingsWindow === win) {
2627
+ deps.windows.setSettingsWindow(null);
2628
+ }
2629
+ });
2630
+ return win;
2631
+ })();
2632
+ inFlightCreations.set(deps.windows, creation);
2633
+ try {
2634
+ return await creation;
2635
+ } finally {
2636
+ if (inFlightCreations.get(deps.windows) === creation) {
2637
+ inFlightCreations.delete(deps.windows);
2638
+ }
2639
+ }
2640
+ }
2641
+ async function openSettingsWindow(deps) {
2642
+ const win = await getOrCreateSettingsWindow(deps);
2643
+ win.show();
2644
+ win.focus();
2645
+ deps.notify.workbenchSettingsInit(win, {
2646
+ settings: loadWorkbenchSettings()
2647
+ });
2648
+ }
2649
+
2650
+ // src/main/services/workspace/workspace-service.ts
2651
+ import { z as z2 } from "zod";
2652
+
2546
2653
  // src/main/services/projects/project-repository.ts
2547
2654
  import { app as app5 } from "electron";
2548
- import path8 from "path";
2655
+ import path9 from "path";
2549
2656
  import fs4 from "fs";
2550
2657
  var log2 = createLogger("projects");
2551
2658
  function getProjectsFile() {
2552
- return path8.join(app5.getPath("userData"), "dimina-projects.json");
2659
+ return path9.join(app5.getPath("userData"), "dimina-projects.json");
2553
2660
  }
2554
2661
  function load() {
2555
2662
  try {
@@ -2571,13 +2678,13 @@ function validateProjectDir(dirPath) {
2571
2678
  if (!fs4.existsSync(dirPath)) {
2572
2679
  return `\u5C0F\u7A0B\u5E8F\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${dirPath}`;
2573
2680
  }
2574
- if (!fs4.existsSync(path8.join(dirPath, "app.json"))) {
2575
- const configPath = path8.join(dirPath, "project.config.json");
2681
+ if (!fs4.existsSync(path9.join(dirPath, "app.json"))) {
2682
+ const configPath = path9.join(dirPath, "project.config.json");
2576
2683
  if (fs4.existsSync(configPath)) {
2577
2684
  try {
2578
2685
  const cfg = JSON.parse(fs4.readFileSync(configPath, "utf-8"));
2579
2686
  if (cfg.miniprogramRoot) {
2580
- const resolvedRoot = path8.resolve(dirPath, cfg.miniprogramRoot);
2687
+ const resolvedRoot = path9.resolve(dirPath, cfg.miniprogramRoot);
2581
2688
  return `\u8BE5\u76EE\u5F55\u7F3A\u5C11 app.json\uFF0Cproject.config.json \u4E2D\u6307\u5B9A\u4E86 miniprogramRoot: "${cfg.miniprogramRoot}"\uFF0C\u8BF7\u5BFC\u5165 ${resolvedRoot}`;
2582
2689
  }
2583
2690
  } catch (err) {
@@ -2590,9 +2697,9 @@ function validateProjectDir(dirPath) {
2590
2697
  }
2591
2698
  function addProject(dirPath) {
2592
2699
  const projects = load();
2593
- let name = path8.basename(dirPath);
2700
+ let name = path9.basename(dirPath);
2594
2701
  try {
2595
- const configPath = path8.join(dirPath, "project.config.json");
2702
+ const configPath = path9.join(dirPath, "project.config.json");
2596
2703
  if (fs4.existsSync(configPath)) {
2597
2704
  const cfg = JSON.parse(fs4.readFileSync(configPath, "utf-8"));
2598
2705
  if (cfg.projectname) name = cfg.projectname;
@@ -2631,7 +2738,7 @@ function getCompileConfig(dirPath) {
2631
2738
  };
2632
2739
  }
2633
2740
  function getProjectPages(dirPath) {
2634
- const appJsonPath = path8.join(dirPath, "app.json");
2741
+ const appJsonPath = path9.join(dirPath, "app.json");
2635
2742
  try {
2636
2743
  const appJson = JSON.parse(
2637
2744
  fs4.readFileSync(appJsonPath, "utf-8")
@@ -2657,7 +2764,7 @@ function getProjectSettings(projectPath) {
2657
2764
  return { uploadWithSourceMap: false };
2658
2765
  }
2659
2766
  try {
2660
- const configPath = path8.join(projectPath, "project.config.json");
2767
+ const configPath = path9.join(projectPath, "project.config.json");
2661
2768
  const config = JSON.parse(fs4.readFileSync(configPath, "utf-8"));
2662
2769
  return {
2663
2770
  uploadWithSourceMap: !!config.setting?.uploadWithSourceMap
@@ -2668,7 +2775,7 @@ function getProjectSettings(projectPath) {
2668
2775
  }
2669
2776
  function updateProjectSettings(projectPath, patch) {
2670
2777
  if (!projectPath) return;
2671
- const configPath = path8.join(projectPath, "project.config.json");
2778
+ const configPath = path9.join(projectPath, "project.config.json");
2672
2779
  let config = {};
2673
2780
  try {
2674
2781
  config = JSON.parse(fs4.readFileSync(configPath, "utf-8"));
@@ -2711,6 +2818,7 @@ function getSimulatorServicewechatReferer() {
2711
2818
  }
2712
2819
 
2713
2820
  // src/main/services/workspace/workspace-service.ts
2821
+ var SessionAppInfoSchema = z2.looseObject({ appId: z2.string() });
2714
2822
  function createWorkspaceService(ctx) {
2715
2823
  let currentSession = null;
2716
2824
  let currentProjectPath = "";
@@ -2727,11 +2835,11 @@ function createWorkspaceService(ctx) {
2727
2835
  }
2728
2836
  async function disposeSession() {
2729
2837
  if (!currentSession) return;
2730
- const session4 = currentSession;
2838
+ const session5 = currentSession;
2731
2839
  currentSession = null;
2732
2840
  try {
2733
2841
  await Promise.race([
2734
- session4.close(),
2842
+ session5.close(),
2735
2843
  new Promise(
2736
2844
  (_, reject) => setTimeout(() => reject(new Error("session close timed out")), 5e3)
2737
2845
  )
@@ -2740,8 +2848,8 @@ function createWorkspaceService(ctx) {
2740
2848
  console.error("[workspace] session close failed:", err);
2741
2849
  }
2742
2850
  }
2743
- function applyRefererFromSession(session4) {
2744
- const appInfo = session4.appInfo;
2851
+ function applyRefererFromSession(session5) {
2852
+ const appInfo = session5.appInfo;
2745
2853
  if (appInfo && typeof appInfo.appId === "string" && appInfo.appId.length > 0) {
2746
2854
  setSimulatorServicewechatReferer(
2747
2855
  appInfo.appId,
@@ -2762,26 +2870,20 @@ function createWorkspaceService(ctx) {
2762
2870
  },
2763
2871
  validateProjectDir: async (dirPath) => provider.validateProjectDir ? provider.validateProjectDir(dirPath) : null,
2764
2872
  async openProject(projectPath) {
2873
+ clearSimulatorServicewechatReferer();
2874
+ await disposeSession();
2875
+ currentProjectPath = "";
2876
+ lastClosedProjectPath = "";
2765
2877
  const dirError = provider.validateProjectDir ? await provider.validateProjectDir(projectPath) : null;
2766
2878
  if (dirError) {
2767
2879
  sendStatus("error", dirError);
2768
2880
  return { success: false, error: dirError };
2769
2881
  }
2770
- const gate = ctx.beforeOpenProject ? await ctx.beforeOpenProject(projectPath) : void 0;
2771
- if (gate && !gate.allow) {
2772
- const message = gate.userMessage ?? gate.reason;
2773
- sendStatus("error", message);
2774
- return { success: false, error: message };
2775
- }
2776
- clearSimulatorServicewechatReferer();
2777
- await disposeSession();
2778
- currentProjectPath = "";
2779
- lastClosedProjectPath = "";
2780
2882
  sendStatus("compiling", "\u6B63\u5728\u7F16\u8BD1...");
2781
2883
  const { compile } = loadWorkbenchSettings();
2782
- let session4;
2884
+ let session5;
2783
2885
  try {
2784
- session4 = await ctx.adapter.openProject({
2886
+ session5 = await ctx.adapter.openProject({
2785
2887
  projectPath,
2786
2888
  sourcemap: true,
2787
2889
  watch: compile.watch,
@@ -2793,17 +2895,30 @@ function createWorkspaceService(ctx) {
2793
2895
  sendStatus("error", String(err));
2794
2896
  return { success: false, error: String(err) };
2795
2897
  }
2796
- currentSession = session4;
2898
+ if (!SessionAppInfoSchema.safeParse(session5.appInfo).success) {
2899
+ try {
2900
+ await session5.close();
2901
+ } catch (closeErr) {
2902
+ console.warn(
2903
+ "[workspace] closing appId-less adapter session failed (non-fatal):",
2904
+ closeErr
2905
+ );
2906
+ }
2907
+ const error = "adapter returned session.appInfo without a string appId \u2014 the CompilationAdapter must supply appInfo.appId";
2908
+ sendStatus("error", error);
2909
+ return { success: false, error };
2910
+ }
2911
+ currentSession = session5;
2797
2912
  currentProjectPath = projectPath;
2798
2913
  bestEffort("updateLastOpened", () => {
2799
2914
  if (provider.updateLastOpened) provider.updateLastOpened(projectPath);
2800
2915
  });
2801
- bestEffort("sendStatus", () => sendStatus("ready", gate?.statusMessage ?? "\u7F16\u8BD1\u5B8C\u6210"));
2802
- bestEffort("applyReferer", () => applyRefererFromSession(session4));
2916
+ bestEffort("sendStatus", () => sendStatus("ready", "\u7F16\u8BD1\u5B8C\u6210"));
2917
+ bestEffort("applyReferer", () => applyRefererFromSession(session5));
2803
2918
  return {
2804
2919
  success: true,
2805
- port: session4.port,
2806
- appInfo: session4.appInfo
2920
+ port: session5.port,
2921
+ appInfo: session5.appInfo
2807
2922
  };
2808
2923
  },
2809
2924
  async closeProject() {
@@ -2856,16 +2971,16 @@ function createWorkspaceService(ctx) {
2856
2971
  // src/main/services/projects/thumbnail.ts
2857
2972
  import { createHash } from "crypto";
2858
2973
  import fs5 from "fs";
2859
- import path9 from "path";
2974
+ import path10 from "path";
2860
2975
  import { app as app6 } from "electron";
2861
2976
  function getThumbnailDir() {
2862
- return path9.join(app6.getPath("userData"), "thumbnails");
2977
+ return path10.join(app6.getPath("userData"), "thumbnails");
2863
2978
  }
2864
2979
  function hashProjectPath(projectPath) {
2865
2980
  return createHash("sha256").update(projectPath).digest("hex").slice(0, 16);
2866
2981
  }
2867
2982
  function getThumbnailPath(projectPath) {
2868
- return path9.join(getThumbnailDir(), `${hashProjectPath(projectPath)}.png`);
2983
+ return path10.join(getThumbnailDir(), `${hashProjectPath(projectPath)}.png`);
2869
2984
  }
2870
2985
  var DATA_URL_PNG_PREFIX = "data:image/png;base64,";
2871
2986
  function saveThumbnailFromDataUrl(projectPath, imageDataUrl) {
@@ -2899,41 +3014,6 @@ function createLocalProjectsProvider() {
2899
3014
  };
2900
3015
  }
2901
3016
 
2902
- // src/main/services/toolbar/toolbar-store.ts
2903
- function toPublicAction(action) {
2904
- const projected = {
2905
- id: action.id,
2906
- label: action.label
2907
- };
2908
- if (action.kind) projected.kind = action.kind;
2909
- if (action.placement) projected.placement = action.placement;
2910
- if (action.icon) projected.icon = action.icon;
2911
- if (action.displayInitial) projected.displayInitial = action.displayInitial;
2912
- if (action.avatarUrl) projected.avatarUrl = action.avatarUrl;
2913
- return projected;
2914
- }
2915
- function createToolbarStore() {
2916
- let actions = [];
2917
- return {
2918
- set(next) {
2919
- const seen = /* @__PURE__ */ new Set();
2920
- for (const action of next) {
2921
- if (seen.has(action.id)) {
2922
- throw new Error(`Duplicate toolbar action id "${action.id}"`);
2923
- }
2924
- seen.add(action.id);
2925
- }
2926
- actions = next.slice();
2927
- },
2928
- list() {
2929
- return actions.map(toPublicAction);
2930
- },
2931
- getHandler(id) {
2932
- return actions.find((a) => a.id === id)?.handler;
2933
- }
2934
- };
2935
- }
2936
-
2937
3017
  // src/main/services/projects/templates.ts
2938
3018
  function resolveTemplates(builtin, injected, mode) {
2939
3019
  let kept;
@@ -2961,51 +3041,41 @@ function sanitizeTemplates(templates) {
2961
3041
  }
2962
3042
 
2963
3043
  // src/main/services/projects/builtin-templates.ts
2964
- import path10 from "node:path";
2965
- var TEMPLATES_DIR = path10.join(devtoolsPackageRoot, "templates");
3044
+ import path11 from "node:path";
3045
+ var TEMPLATES_DIR = path11.join(devtoolsPackageRoot, "templates");
2966
3046
  var BUILTIN_TEMPLATES = [
2967
3047
  {
2968
3048
  id: "blank",
2969
3049
  name: "Blank",
2970
3050
  description: "\u6700\u5C0F\u9AA8\u67B6\uFF1Aapp.* + \u4E00\u4E2A index \u9875\u9762",
2971
- source: { type: "directory", path: path10.join(TEMPLATES_DIR, "blank") }
3051
+ source: { type: "directory", path: path11.join(TEMPLATES_DIR, "blank") }
2972
3052
  },
2973
3053
  {
2974
3054
  id: "taro-todo",
2975
3055
  name: "Taro Todo",
2976
3056
  description: "Taro \u7F16\u8BD1\u4EA7\u7269\u7684 Todo \u793A\u4F8B",
2977
- source: { type: "directory", path: path10.join(TEMPLATES_DIR, "taro-todo") }
3057
+ source: { type: "directory", path: path11.join(TEMPLATES_DIR, "taro-todo") }
2978
3058
  }
2979
3059
  ];
2980
3060
 
2981
3061
  // src/main/services/workbench-context.ts
2982
- function hasBuiltinPanel(ctx, panelId) {
2983
- return ctx.panels.includes(panelId);
2984
- }
2985
- function getDefaultTab(ctx) {
2986
- if (hasBuiltinPanel(ctx, "console")) return "simulator";
2987
- if (ctx.panels.length > 0) return ctx.panels[0];
2988
- return "simulator";
2989
- }
2990
3062
  function createWorkbenchContext(opts) {
2991
3063
  const ctx = {
2992
3064
  adapter: opts.adapter ?? defaultAdapter,
2993
3065
  preloadPath: opts.preloadPath,
2994
3066
  rendererDir: opts.rendererDir,
2995
- panels: opts.panels ?? ["wxml", "console", "appdata", "storage"],
2996
3067
  apiNamespaces: opts.apiNamespaces ?? [],
2997
3068
  appName: opts.appName ?? "Dimina DevTools",
2998
- headerHeight: opts.headerHeight ?? 40,
2999
3069
  brandingProvider: opts.brandingProvider
3000
3070
  };
3001
3071
  ctx.registry = new DisposableRegistry3();
3002
3072
  ctx.connections = createConnectionRegistry();
3003
3073
  ctx.trustedWindowSenderIds = /* @__PURE__ */ new Map();
3004
3074
  ctx.simulatorApis = createSimulatorApiRegistry();
3005
- ctx.toolbar = createToolbarStore();
3006
3075
  ctx.windows = createWindowService(opts.mainWindow);
3007
3076
  ctx.views = createViewManager(ctx);
3008
3077
  ctx.notify = createRendererNotifier(ctx);
3078
+ ctx.openSettings = () => openSettingsWindow(ctx);
3009
3079
  ctx.projectsProvider = opts.projectsProvider ?? createLocalProjectsProvider();
3010
3080
  ctx.projectTemplates = resolveTemplates(
3011
3081
  BUILTIN_TEMPLATES,
@@ -3028,7 +3098,7 @@ function installAppMenu(ctx) {
3028
3098
  {
3029
3099
  label: "\u5F00\u53D1\u5DE5\u5177\u8BBE\u7F6E",
3030
3100
  click: () => {
3031
- void openSettingsWindow(ctx).catch(() => {
3101
+ void ctx.openSettings().catch(() => {
3032
3102
  });
3033
3103
  }
3034
3104
  },
@@ -3096,130 +3166,119 @@ function installAppMenu(ctx) {
3096
3166
  }
3097
3167
 
3098
3168
  // src/main/ipc/app.ts
3099
- import fs6 from "fs";
3100
3169
  function registerAppIpc(ctx) {
3101
- return new IpcRegistry(ctx.senderPolicy).handle(AppChannel.GetPreloadPath, () => {
3102
- return `file://${fs6.realpathSync(ctx.preloadPath)}`;
3103
- }).handle(AppChannel.GetBranding, async () => {
3170
+ return new IpcRegistry(ctx.senderPolicy).handle(AppChannel.GetBranding, async () => {
3104
3171
  if (ctx.brandingProvider) return ctx.brandingProvider();
3105
3172
  return { appName: ctx.appName };
3106
- }).handle(AppChannel.GetHeaderHeight, () => {
3107
- return ctx.headerHeight;
3108
3173
  });
3109
3174
  }
3110
3175
 
3111
3176
  // src/shared/ipc-schemas.ts
3112
- import { z as z2 } from "zod";
3113
- var AbsolutePath = z2.string().min(1).refine(
3177
+ import { z as z3 } from "zod";
3178
+ var AbsolutePath = z3.string().min(1).refine(
3114
3179
  (p) => p.startsWith("/") || /^[a-zA-Z]:\\/.test(p) || /^[a-zA-Z]:\//.test(p),
3115
3180
  "must be an absolute path"
3116
3181
  );
3117
- var PanelEvalSchema = z2.tuple([z2.string().min(1).max(5e4)]);
3118
- var ProjectsAddSchema = z2.tuple([AbsolutePath]);
3119
- var ProjectOpenSchema = z2.tuple([AbsolutePath]);
3120
- var CompileConfigShape = z2.looseObject({
3121
- startPage: z2.string().optional(),
3122
- scene: z2.number().optional(),
3123
- queryParams: z2.array(z2.looseObject({ key: z2.string(), value: z2.string() })).optional()
3182
+ var ProjectsAddSchema = z3.tuple([AbsolutePath]);
3183
+ var ProjectOpenSchema = z3.tuple([AbsolutePath]);
3184
+ var CompileConfigShape = z3.looseObject({
3185
+ startPage: z3.string().optional(),
3186
+ scene: z3.number().optional(),
3187
+ queryParams: z3.array(z3.looseObject({ key: z3.string(), value: z3.string() })).optional()
3124
3188
  });
3125
- var ProjectSaveCompileConfigSchema = z2.tuple([
3189
+ var ProjectSaveCompileConfigSchema = z3.tuple([
3126
3190
  AbsolutePath,
3127
3191
  CompileConfigShape
3128
3192
  ]);
3129
- var PopoverShowSchema = z2.tuple([z2.looseObject({})]);
3130
- var SimWidth = z2.number().int().min(100).max(2e3);
3131
- var SimulatorAttachNativeSchema = z2.tuple([
3132
- z2.string().url().refine((u) => u.startsWith("http://") || u.startsWith("https://"), {
3193
+ var PopoverShowSchema = z3.tuple([z3.looseObject({})]);
3194
+ var SimWidth = z3.number().int().min(100).max(2e3);
3195
+ var SimulatorAttachNativeSchema = z3.tuple([
3196
+ z3.string().url().refine((u) => u.startsWith("http://") || u.startsWith("https://"), {
3133
3197
  message: "simulator URL must be http(s)"
3134
3198
  }),
3135
3199
  SimWidth
3136
3200
  ]);
3137
- var SimulatorResizeSchema = z2.tuple([SimWidth]);
3138
- var SimulatorSetNativeBoundsSchema = z2.tuple([
3139
- z2.object({
3140
- x: z2.number().finite(),
3141
- y: z2.number().finite(),
3142
- width: z2.number().finite(),
3143
- height: z2.number().finite(),
3144
- zoom: z2.number().finite().positive()
3201
+ var SimulatorSetNativeBoundsSchema = z3.tuple([
3202
+ z3.object({
3203
+ x: z3.number().finite(),
3204
+ y: z3.number().finite(),
3205
+ width: z3.number().finite(),
3206
+ height: z3.number().finite(),
3207
+ zoom: z3.number().finite().positive()
3145
3208
  })
3146
3209
  ]);
3147
- var SimulatorSetDeviceInfoSchema = z2.tuple([
3148
- z2.object({
3149
- brand: z2.string().max(64),
3150
- model: z2.string().max(64),
3151
- system: z2.string().max(64),
3152
- platform: z2.string().max(32),
3153
- pixelRatio: z2.number().finite().positive(),
3154
- screenWidth: z2.number().int().min(100).max(4e3),
3155
- screenHeight: z2.number().int().min(100).max(4e3),
3156
- statusBarHeight: z2.number().finite().min(0).max(400),
3157
- safeAreaBottom: z2.number().finite().min(0).max(400),
3158
- notchType: z2.enum(["none", "notch", "dynamic-island"]),
3159
- safeAreaInsets: z2.object({
3160
- top: z2.number().finite().min(0).max(400),
3161
- right: z2.number().finite().min(0).max(400),
3162
- bottom: z2.number().finite().min(0).max(400),
3163
- left: z2.number().finite().min(0).max(400)
3210
+ var SimulatorSetDeviceInfoSchema = z3.tuple([
3211
+ z3.object({
3212
+ brand: z3.string().max(64),
3213
+ model: z3.string().max(64),
3214
+ system: z3.string().max(64),
3215
+ platform: z3.string().max(32),
3216
+ pixelRatio: z3.number().finite().positive(),
3217
+ screenWidth: z3.number().int().min(100).max(4e3),
3218
+ screenHeight: z3.number().int().min(100).max(4e3),
3219
+ statusBarHeight: z3.number().finite().min(0).max(400),
3220
+ safeAreaBottom: z3.number().finite().min(0).max(400),
3221
+ notchType: z3.enum(["none", "notch", "dynamic-island"]),
3222
+ safeAreaInsets: z3.object({
3223
+ top: z3.number().finite().min(0).max(400),
3224
+ right: z3.number().finite().min(0).max(400),
3225
+ bottom: z3.number().finite().min(0).max(400),
3226
+ left: z3.number().finite().min(0).max(400)
3164
3227
  })
3165
3228
  })
3166
3229
  ]);
3167
- var NonNegInt = z2.number().int().min(0).max(1e5);
3168
- var ViewBoundsSchema = z2.tuple([
3169
- z2.object({
3230
+ var NonNegInt = z3.number().int().min(0).max(1e5);
3231
+ var ViewBoundsSchema = z3.tuple([
3232
+ z3.object({
3170
3233
  x: NonNegInt,
3171
3234
  y: NonNegInt,
3172
3235
  width: NonNegInt,
3173
3236
  height: NonNegInt
3174
3237
  })
3175
3238
  ]);
3176
- var HostToolbarAdvertiseHeightSchema = z2.tuple([
3177
- z2.object({
3178
- axis: z2.literal("block"),
3239
+ var HostToolbarAdvertiseHeightSchema = z3.tuple([
3240
+ z3.object({
3241
+ axis: z3.literal("block"),
3179
3242
  extent: NonNegInt
3180
3243
  })
3181
3244
  ]);
3182
- var SimulatorSetVisibleSchema = z2.tuple([z2.boolean(), SimWidth]);
3183
- var SimulatorCustomApiInvokeSchema = z2.tuple([
3184
- z2.string().min(1).max(256),
3185
- z2.unknown()
3245
+ var SimulatorCustomApiInvokeSchema = z3.tuple([
3246
+ z3.string().min(1).max(256),
3247
+ z3.unknown()
3186
3248
  ]);
3187
- var ToolbarInvokeSchema = z2.tuple([z2.string().min(1).max(256)]);
3188
- var ProjectGetPagesSchema = z2.tuple([AbsolutePath]);
3189
- var ProjectGetCompileConfigSchema = z2.tuple([AbsolutePath]);
3190
- var ProjectsRemoveSchema = z2.tuple([AbsolutePath]);
3191
- var WorkbenchSettingsSaveSchema = z2.tuple([
3192
- z2.looseObject({
3193
- cdp: z2.looseObject({
3194
- enabled: z2.boolean(),
3195
- port: z2.number().int().min(0).max(65535)
3249
+ var ProjectGetPagesSchema = z3.tuple([AbsolutePath]);
3250
+ var ProjectGetCompileConfigSchema = z3.tuple([AbsolutePath]);
3251
+ var ProjectsRemoveSchema = z3.tuple([AbsolutePath]);
3252
+ var WorkbenchSettingsSaveSchema = z3.tuple([
3253
+ z3.looseObject({
3254
+ cdp: z3.looseObject({
3255
+ enabled: z3.boolean(),
3256
+ port: z3.number().int().min(0).max(65535)
3196
3257
  }),
3197
- mcp: z2.looseObject({
3198
- enabled: z2.boolean(),
3199
- port: z2.number().int().min(0).max(65535)
3258
+ mcp: z3.looseObject({
3259
+ enabled: z3.boolean(),
3260
+ port: z3.number().int().min(0).max(65535)
3200
3261
  }),
3201
- compile: z2.looseObject({
3202
- watch: z2.boolean()
3262
+ compile: z3.looseObject({
3263
+ watch: z3.boolean()
3203
3264
  }),
3204
- theme: z2.enum(["system", "light", "dark"]),
3205
- lastCreateBaseDir: z2.union([z2.string(), z2.null()])
3265
+ theme: z3.enum(["system", "light", "dark"]),
3266
+ lastCreateBaseDir: z3.union([z3.string(), z3.null()])
3206
3267
  })
3207
3268
  ]);
3208
- var WorkbenchSettingsSetThemeSchema = z2.tuple([
3209
- z2.enum(["system", "light", "dark"])
3269
+ var WorkbenchSettingsSetThemeSchema = z3.tuple([
3270
+ z3.enum(["system", "light", "dark"])
3210
3271
  ]);
3211
- var WorkbenchSettingsSetVisibleSchema = z2.tuple([z2.boolean()]);
3212
- var SettingsSetVisibleSchema = z2.tuple([z2.boolean()]);
3213
- var SettingsConfigChangedSchema = z2.tuple([CompileConfigShape]);
3214
- var PopoverRelaunchSchema = z2.tuple([CompileConfigShape]);
3215
- var SettingsProjectSettingsChangedSchema = z2.tuple([
3216
- z2.looseObject({
3217
- uploadWithSourceMap: z2.boolean().optional()
3272
+ var SettingsSetVisibleSchema = z3.tuple([z3.boolean()]);
3273
+ var SettingsConfigChangedSchema = z3.tuple([CompileConfigShape]);
3274
+ var PopoverRelaunchSchema = z3.tuple([CompileConfigShape]);
3275
+ var SettingsProjectSettingsChangedSchema = z3.tuple([
3276
+ z3.looseObject({
3277
+ uploadWithSourceMap: z3.boolean().optional()
3218
3278
  })
3219
3279
  ]);
3220
- var PanelSelectSchema = z2.tuple([z2.string().min(1).max(200)]);
3221
- var ProjectCaptureThumbnailSchema = z2.tuple([AbsolutePath]);
3222
- var ProjectGetThumbnailSchema = z2.tuple([AbsolutePath]);
3280
+ var ProjectCaptureThumbnailSchema = z3.tuple([AbsolutePath]);
3281
+ var ProjectGetThumbnailSchema = z3.tuple([AbsolutePath]);
3223
3282
 
3224
3283
  // src/shared/bridge-channels.ts
3225
3284
  var BRIDGE_CHANNELS = {
@@ -3296,9 +3355,6 @@ function registerSimulatorIpc(ctx) {
3296
3355
  ctx.views.attachNativeSimulator(simulatorUrl, simWidth);
3297
3356
  }).handle(SimulatorChannel.Detach, () => {
3298
3357
  ctx.views.detachSimulator();
3299
- }).handle(SimulatorChannel.Resize, (_, ...args) => {
3300
- const [simWidth] = validate(SimulatorChannel.Resize, SimulatorResizeSchema, args);
3301
- ctx.views.resize(simWidth);
3302
3358
  }).handle(SimulatorChannel.SetNativeBounds, (_, ...args) => {
3303
3359
  const [p] = validate(SimulatorChannel.SetNativeBounds, SimulatorSetNativeBoundsSchema, args);
3304
3360
  ctx.views.setNativeSimulatorViewBounds(p);
@@ -3310,48 +3366,12 @@ function registerSimulatorIpc(ctx) {
3310
3366
  if (serviceWc && !serviceWc.isDestroyed()) {
3311
3367
  serviceWc.send(ServiceHostChannel.HostEnvUpdate, deviceInfoToHostEnv(device));
3312
3368
  }
3313
- }).handle(SimulatorChannel.SetVisible, (_, ...args) => {
3314
- const [visible, simWidth] = validate(SimulatorChannel.SetVisible, SimulatorSetVisibleSchema, args);
3315
- ctx.views.setVisible(visible, simWidth);
3316
- }).handle(SimulatorCustomApiChannel.List, () => {
3317
- return ctx.simulatorApis.list();
3318
3369
  }).handle(SimulatorCustomApiChannel.Invoke, (_, ...args) => {
3319
3370
  const [name, params] = validate(SimulatorCustomApiChannel.Invoke, SimulatorCustomApiInvokeSchema, args);
3320
3371
  return ctx.simulatorApis.invoke(name, params);
3321
3372
  });
3322
3373
  }
3323
3374
 
3324
- // src/main/ipc/panels.ts
3325
- var BUILTIN_PANELS = [
3326
- { id: "wxml", label: "WXML" },
3327
- { id: "appdata", label: "AppData" },
3328
- { id: "storage", label: "Storage" }
3329
- ];
3330
- function registerPanelsIpc(ctx) {
3331
- return new IpcRegistry(ctx.senderPolicy).handle(PanelChannel.List, () => {
3332
- return BUILTIN_PANELS.filter((p) => ctx.panels.includes(p.id));
3333
- }).handle(PanelChannel.Eval, async (_event, ...args) => {
3334
- const [expression] = validate(PanelChannel.Eval, PanelEvalSchema, args);
3335
- if (!ctx.workspace.hasActiveSession()) return void 0;
3336
- const sim = ctx.views.getSimulatorWebContents();
3337
- if (!sim) return void 0;
3338
- try {
3339
- return await sim.executeJavaScript(expression);
3340
- } catch {
3341
- return void 0;
3342
- }
3343
- }).handle(PanelChannel.Select, (_event, ...args) => {
3344
- validate(PanelChannel.Select, PanelSelectSchema, args);
3345
- if (ctx.views.hasSimulatorView() && ctx.views.isSimulatorAdded()) {
3346
- ctx.views.hideSimulator();
3347
- }
3348
- }).handle(PanelChannel.SelectSimulator, () => {
3349
- if (ctx.views.hasSimulatorView() && !ctx.views.isSimulatorAdded()) {
3350
- ctx.views.showSimulator(ctx.views.getLastSimWidth());
3351
- }
3352
- }).handle(WorkbenchRuntimeChannel.GetNativeHost, () => true);
3353
- }
3354
-
3355
3375
  // src/main/ipc/popover.ts
3356
3376
  function registerPopoverIpc(ctx) {
3357
3377
  return new IpcRegistry(ctx.senderPolicy).handle(PopoverChannel.Show, (_event, ...args) => {
@@ -3371,11 +3391,11 @@ var popoverModule = {
3371
3391
 
3372
3392
  // src/main/ipc/projects.ts
3373
3393
  import { app as app7, dialog } from "electron";
3374
- import path12 from "path";
3394
+ import path13 from "path";
3375
3395
 
3376
3396
  // src/main/services/projects/create-project-service.ts
3377
- import fs7 from "node:fs";
3378
- import path11 from "node:path";
3397
+ import fs6 from "node:fs";
3398
+ import path12 from "node:path";
3379
3399
  var DEFAULT_TEMPLATE_ID = "blank";
3380
3400
  async function createProject(input, ctx) {
3381
3401
  const name = (input.name ?? "").trim();
@@ -3386,12 +3406,12 @@ async function createProject(input, ctx) {
3386
3406
  if (!target || typeof target !== "string") {
3387
3407
  throw new Error("Project path is required");
3388
3408
  }
3389
- if (fs7.existsSync(target)) {
3390
- const stat = fs7.statSync(target);
3409
+ if (fs6.existsSync(target)) {
3410
+ const stat = fs6.statSync(target);
3391
3411
  if (!stat.isDirectory()) {
3392
3412
  throw new Error(`Project path exists and is not a directory: ${target}`);
3393
3413
  }
3394
- const entries = fs7.readdirSync(target);
3414
+ const entries = fs6.readdirSync(target);
3395
3415
  if (entries.length > 0) {
3396
3416
  throw new Error(
3397
3417
  `Project path is not empty (refusing to overwrite): ${target}`
@@ -3408,31 +3428,31 @@ async function createProject(input, ctx) {
3408
3428
  `Template '${templateId}' has neither a source directory nor a generate function`
3409
3429
  );
3410
3430
  }
3411
- fs7.mkdirSync(target, { recursive: true });
3431
+ fs6.mkdirSync(target, { recursive: true });
3412
3432
  if (template.generate) {
3413
3433
  await template.generate(target, { name });
3414
3434
  } else if (template.source) {
3415
- if (!fs7.existsSync(template.source.path)) {
3435
+ if (!fs6.existsSync(template.source.path)) {
3416
3436
  throw new Error(
3417
3437
  `Template source missing on disk: ${template.source.path}`
3418
3438
  );
3419
3439
  }
3420
- fs7.cpSync(template.source.path, target, {
3440
+ fs6.cpSync(template.source.path, target, {
3421
3441
  recursive: true,
3422
3442
  force: true
3423
3443
  });
3424
3444
  }
3425
- const cfgPath = path11.join(target, "project.config.json");
3445
+ const cfgPath = path12.join(target, "project.config.json");
3426
3446
  let cfg = {};
3427
- if (fs7.existsSync(cfgPath)) {
3447
+ if (fs6.existsSync(cfgPath)) {
3428
3448
  try {
3429
- cfg = JSON.parse(fs7.readFileSync(cfgPath, "utf-8"));
3449
+ cfg = JSON.parse(fs6.readFileSync(cfgPath, "utf-8"));
3430
3450
  } catch {
3431
3451
  cfg = {};
3432
3452
  }
3433
3453
  }
3434
3454
  cfg.projectname = name;
3435
- fs7.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
3455
+ fs6.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
3436
3456
  const created = await ctx.projectsProvider.addProject(target);
3437
3457
  return created;
3438
3458
  }
@@ -3508,7 +3528,7 @@ function registerProjectsIpc(ctx) {
3508
3528
  }
3509
3529
  try {
3510
3530
  const settings = loadWorkbenchSettings();
3511
- const newBase = path12.dirname(input.path);
3531
+ const newBase = path13.dirname(input.path);
3512
3532
  if (newBase && settings.lastCreateBaseDir !== newBase) {
3513
3533
  saveWorkbenchSettings({ ...settings, lastCreateBaseDir: newBase });
3514
3534
  }
@@ -3636,17 +3656,6 @@ function registerSettingsIpc(ctx) {
3636
3656
  activePort: runtime.port,
3637
3657
  error: runtime.error
3638
3658
  };
3639
- }).handle(WorkbenchSettingsChannel.SetVisible, async (_, ...args) => {
3640
- const [visible] = validate(
3641
- WorkbenchSettingsChannel.SetVisible,
3642
- WorkbenchSettingsSetVisibleSchema,
3643
- args
3644
- );
3645
- if (visible) {
3646
- await openSettingsWindow(ctx);
3647
- } else {
3648
- ctx.windows.closeSettingsWindow();
3649
- }
3650
3659
  }).handle(SettingsChannel.SetVisible, async (_, ...args) => {
3651
3660
  const [visible] = validate(SettingsChannel.SetVisible, SettingsSetVisibleSchema, args);
3652
3661
  if (visible) {
@@ -3659,7 +3668,6 @@ function registerSettingsIpc(ctx) {
3659
3668
  });
3660
3669
  } else {
3661
3670
  ctx.views.hideSettings();
3662
- ctx.notify.settingsClosed();
3663
3671
  }
3664
3672
  }).on(SettingsChannel.ConfigChanged, async (_, ...args) => {
3665
3673
  const [config] = validate(
@@ -3671,7 +3679,6 @@ function registerSettingsIpc(ctx) {
3671
3679
  if (projectPath) {
3672
3680
  await ctx.workspace.saveCompileConfig(projectPath, config);
3673
3681
  }
3674
- ctx.notify.settingsChanged(config);
3675
3682
  }).on(SettingsChannel.ProjectSettingsChanged, (_, ...args) => {
3676
3683
  const [patch] = validate(
3677
3684
  SettingsChannel.ProjectSettingsChanged,
@@ -3688,26 +3695,12 @@ var settingsModule = {
3688
3695
  setup: (ctx) => registerSettingsIpc(ctx)
3689
3696
  };
3690
3697
 
3691
- // src/main/ipc/toolbar.ts
3692
- function registerToolbarIpc(ctx) {
3693
- return new IpcRegistry(ctx.senderPolicy).handle(ToolbarChannel.GetActions, () => {
3694
- return ctx.toolbar.list();
3695
- }).handle(ToolbarChannel.Invoke, async (_, ...args) => {
3696
- const [id] = validate(ToolbarChannel.Invoke, ToolbarInvokeSchema, args);
3697
- const handler = ctx.toolbar.getHandler(id);
3698
- if (!handler) {
3699
- throw new Error(`Toolbar action "${id}" is not registered`);
3700
- }
3701
- await handler();
3702
- });
3703
- }
3704
-
3705
3698
  // src/main/ipc/simulator-module.ts
3706
3699
  import { DisposableRegistry as DisposableRegistry6 } from "@dimina-kit/electron-deck/main";
3707
3700
 
3708
3701
  // src/main/ipc/bridge-router.ts
3709
3702
  import { app as app11, ipcMain as ipcMain3, protocol as protocol2, session as electronSession, webContents as webContents2 } from "electron";
3710
- import path15 from "node:path";
3703
+ import path16 from "node:path";
3711
3704
  import { pathToFileURL as pathToFileURL3 } from "node:url";
3712
3705
 
3713
3706
  // src/shared/simulator-api-metadata.ts
@@ -3721,8 +3714,8 @@ import { createDebugTap } from "@dimina-kit/electron-deck/main";
3721
3714
 
3722
3715
  // src/main/services/dimina-resource-server.ts
3723
3716
  import http from "node:http";
3724
- import fs8 from "node:fs";
3725
- import path13 from "node:path";
3717
+ import fs7 from "node:fs";
3718
+ import path14 from "node:path";
3726
3719
  var MIME_TYPES = {
3727
3720
  ".css": "text/css; charset=utf-8",
3728
3721
  ".html": "text/html; charset=utf-8",
@@ -3738,7 +3731,7 @@ var MIME_TYPES = {
3738
3731
  ".wasm": "application/wasm"
3739
3732
  };
3740
3733
  async function startDiminaResourceServer(rootDir) {
3741
- const root = path13.resolve(rootDir);
3734
+ const root = path14.resolve(rootDir);
3742
3735
  const server = http.createServer((req, res) => {
3743
3736
  void handleRequest(root, req, res);
3744
3737
  });
@@ -3779,14 +3772,14 @@ async function handleRequest(root, req, res) {
3779
3772
  return;
3780
3773
  }
3781
3774
  try {
3782
- const stat = await fs8.promises.stat(filePath);
3775
+ const stat = await fs7.promises.stat(filePath);
3783
3776
  if (!stat.isFile()) {
3784
3777
  res.writeHead(404);
3785
3778
  res.end("Not Found");
3786
3779
  return;
3787
3780
  }
3788
3781
  res.writeHead(200, {
3789
- "content-type": MIME_TYPES[path13.extname(filePath)] ?? "application/octet-stream",
3782
+ "content-type": MIME_TYPES[path14.extname(filePath)] ?? "application/octet-stream",
3790
3783
  "content-length": stat.size,
3791
3784
  "cache-control": "no-store"
3792
3785
  });
@@ -3794,7 +3787,7 @@ async function handleRequest(root, req, res) {
3794
3787
  res.end();
3795
3788
  return;
3796
3789
  }
3797
- fs8.createReadStream(filePath).pipe(res);
3790
+ fs7.createReadStream(filePath).pipe(res);
3798
3791
  } catch {
3799
3792
  res.writeHead(404);
3800
3793
  res.end("Not Found");
@@ -3802,8 +3795,8 @@ async function handleRequest(root, req, res) {
3802
3795
  }
3803
3796
  function resolveContainedPath(root, pathname) {
3804
3797
  const relative = pathname.replace(/^\/+/, "") || "index.html";
3805
- const resolved = path13.resolve(root, relative);
3806
- if (resolved !== root && !resolved.startsWith(root + path13.sep)) return null;
3798
+ const resolved = path14.resolve(root, relative);
3799
+ if (resolved !== root && !resolved.startsWith(root + path14.sep)) return null;
3807
3800
  return resolved;
3808
3801
  }
3809
3802
  function setCorsHeaders(res) {
@@ -3814,16 +3807,16 @@ function setCorsHeaders(res) {
3814
3807
  }
3815
3808
 
3816
3809
  // src/main/windows/service-host-window/create.ts
3817
- import { app as app9, BrowserWindow as BrowserWindow3 } from "electron";
3818
- import path14 from "node:path";
3810
+ import { app as app9, BrowserWindow as BrowserWindow4 } from "electron";
3811
+ import path15 from "node:path";
3819
3812
  import { pathToFileURL as pathToFileURL2 } from "node:url";
3820
3813
  var SERVICE_HOST_PARTITION = SHARED_MINIAPP_PARTITION;
3821
- var serviceHostPreloadPath = path14.join(devtoolsPackageRoot, "dist/service-host/preload.cjs");
3822
- var serviceHostHtmlPath = path14.join(devtoolsPackageRoot, "dist/service-host/service.html");
3814
+ var serviceHostPreloadPath = path15.join(devtoolsPackageRoot, "dist/service-host/preload.cjs");
3815
+ var serviceHostHtmlPath = path15.join(devtoolsPackageRoot, "dist/service-host/service.html");
3823
3816
  function constructServiceHostWindow(opts = {}) {
3824
3817
  const partition = opts.partition ?? SERVICE_HOST_PARTITION;
3825
3818
  configureMiniappSession(partition);
3826
- return new BrowserWindow3({
3819
+ return new BrowserWindow4({
3827
3820
  width: 980,
3828
3821
  height: 720,
3829
3822
  show: false,
@@ -3894,7 +3887,7 @@ function createServiceHostWindow(opts) {
3894
3887
  }
3895
3888
 
3896
3889
  // src/main/services/service-host-pool/pool.ts
3897
- import { BrowserWindow as BrowserWindow4 } from "electron";
3890
+ import { BrowserWindow as BrowserWindow5 } from "electron";
3898
3891
  var BLANK_URL = "about:blank";
3899
3892
  var HARD_MAX_POOL_SIZE = 4;
3900
3893
  var RESET_STORAGES = [
@@ -4091,7 +4084,7 @@ var ServiceHostPool = class {
4091
4084
  }
4092
4085
  }
4093
4086
  createWindow(spec) {
4094
- return new BrowserWindow4({
4087
+ return new BrowserWindow5({
4095
4088
  show: false,
4096
4089
  width: spec.size?.width,
4097
4090
  height: spec.size?.height,
@@ -4804,8 +4797,8 @@ function installBridgeRouter(ctx) {
4804
4797
  const onNativeHostQuery = (event) => {
4805
4798
  const reply = {
4806
4799
  enabled: true,
4807
- renderHostHtmlUrl: pathToFileURL3(path15.join(devtoolsPackageRoot, "dist/render-host/pageFrame.html")).toString(),
4808
- renderPreloadUrl: pathToFileURL3(path15.join(devtoolsPackageRoot, "dist/render-host/preload.cjs")).toString(),
4800
+ renderHostHtmlUrl: pathToFileURL3(path16.join(devtoolsPackageRoot, "dist/render-host/pageFrame.html")).toString(),
4801
+ renderPreloadUrl: pathToFileURL3(path16.join(devtoolsPackageRoot, "dist/render-host/preload.cjs")).toString(),
4809
4802
  device: currentDevice ?? void 0
4810
4803
  };
4811
4804
  event.returnValue = reply;
@@ -5055,14 +5048,14 @@ async function handleSpawn(state, ctx, event, opts) {
5055
5048
  const appSessionId = bridgeId;
5056
5049
  const simulatorWc = resolveSimulatorWebContents(ctx, opts.simulatorWcId, event.sender);
5057
5050
  const pagePath = normalizePagePath(opts.pagePath || "pages/index/index");
5058
- const pkgRoot = path15.resolve(opts.pkgRoot || process.cwd());
5051
+ const pkgRoot = path16.resolve(opts.pkgRoot || process.cwd());
5059
5052
  const root = opts.root || "main";
5060
5053
  let resourceServer = null;
5061
5054
  let resourceBaseUrl;
5062
5055
  if (opts.resourceBaseUrl) {
5063
5056
  resourceBaseUrl = opts.resourceBaseUrl.endsWith("/") ? opts.resourceBaseUrl : `${opts.resourceBaseUrl}/`;
5064
5057
  } else {
5065
- resourceServer = await startDiminaResourceServer(path15.resolve(pkgRoot, root));
5058
+ resourceServer = await startDiminaResourceServer(path16.resolve(pkgRoot, root));
5066
5059
  resourceBaseUrl = resourceServer.baseUrl;
5067
5060
  }
5068
5061
  const selectedDevice = ctx.bridge?.getDevice?.() ?? null;
@@ -5841,8 +5834,6 @@ var simulatorModule = {
5841
5834
  setup: (ctx) => {
5842
5835
  const reg = new DisposableRegistry6();
5843
5836
  reg.add(registerSimulatorIpc(ctx));
5844
- reg.add(registerPanelsIpc(ctx));
5845
- reg.add(registerToolbarIpc(ctx));
5846
5837
  reg.add(registerViewsIpc(ctx));
5847
5838
  installBridgeRouter(ctx);
5848
5839
  return reg;
@@ -6684,7 +6675,7 @@ function getClient(kind) {
6684
6675
  }
6685
6676
 
6686
6677
  // src/main/services/mcp/tool-registry.ts
6687
- import { z as z3 } from "zod";
6678
+ import { z as z4 } from "zod";
6688
6679
  function registerCommonTargetTools(server, kind) {
6689
6680
  const descriptions = kind === "simulator" ? {
6690
6681
  screenshot: "Take a screenshot of the simulator webview",
@@ -6705,9 +6696,9 @@ function registerCommonTargetTools(server, kind) {
6705
6696
  return { content: [{ type: "image", data, mimeType: "image/png" }] };
6706
6697
  });
6707
6698
  server.tool(`${kind}_console_logs`, descriptions.consoleLogs, {
6708
- limit: z3.number().optional().default(50).describe("Maximum number of log entries"),
6709
- level: z3.enum(["error", "warning", "warn", "info", "log", "debug"]).optional().describe("Only return entries with this level"),
6710
- sinceTimestamp: z3.string().optional().describe("ISO timestamp; only return entries at or after this time")
6699
+ limit: z4.number().optional().default(50).describe("Maximum number of log entries"),
6700
+ level: z4.enum(["error", "warning", "warn", "info", "log", "debug"]).optional().describe("Only return entries with this level"),
6701
+ sinceTimestamp: z4.string().optional().describe("ISO timestamp; only return entries at or after this time")
6711
6702
  }, async ({ limit, level, sinceTimestamp }) => {
6712
6703
  getClient(kind);
6713
6704
  let entries = getTargetState(kind).consoleLogs;
@@ -6722,7 +6713,7 @@ function registerCommonTargetTools(server, kind) {
6722
6713
  });
6723
6714
  if (kind !== "workbench") {
6724
6715
  server.tool(`${kind}_evaluate`, descriptions.evaluate, {
6725
- expression: z3.string().describe("JavaScript expression to evaluate")
6716
+ expression: z4.string().describe("JavaScript expression to evaluate")
6726
6717
  }, async ({ expression }) => {
6727
6718
  const c = getClient(kind);
6728
6719
  const result = await c.Runtime.evaluate({ expression, returnByValue: true, awaitPromise: true });
@@ -6735,15 +6726,15 @@ ${JSON.stringify(result.exceptionDetails, null, 2)}` }], isError: true };
6735
6726
  });
6736
6727
  }
6737
6728
  server.tool(`${kind}_get_dom`, descriptions.getDom, {
6738
- depth: z3.number().optional().default(3).describe("Maximum depth")
6729
+ depth: z4.number().optional().default(3).describe("Maximum depth")
6739
6730
  }, async ({ depth }) => {
6740
6731
  const c = getClient(kind);
6741
6732
  const { root } = await c.DOM.getDocument({ depth });
6742
6733
  return { content: [{ type: "text", text: JSON.stringify(root, null, 2) }] };
6743
6734
  });
6744
6735
  server.tool(`${kind}_network_log`, descriptions.networkLog, {
6745
- limit: z3.number().optional().default(20).describe("Maximum number of entries"),
6746
- minStatus: z3.number().optional().describe("Only return entries with status >= minStatus (status 0 = failed before response is included when minStatus >= 400)")
6736
+ limit: z4.number().optional().default(20).describe("Maximum number of entries"),
6737
+ minStatus: z4.number().optional().describe("Only return entries with status >= minStatus (status 0 = failed before response is included when minStatus >= 400)")
6747
6738
  }, async ({ limit, minStatus }) => {
6748
6739
  getClient(kind);
6749
6740
  let entries = getTargetState(kind).networkRequests;
@@ -6998,11 +6989,11 @@ function registerContextTools(server) {
6998
6989
  }
6999
6990
 
7000
6991
  // src/main/services/mcp/tools/simulator-tools.ts
7001
- import { z as z4 } from "zod";
6992
+ import { z as z5 } from "zod";
7002
6993
  function registerSimulatorTools(server) {
7003
6994
  server.tool("simulator_navigate", "Navigate the simulator to a URL, or reload the current page", {
7004
- url: z4.string().optional().describe("URL to navigate to"),
7005
- reload: z4.boolean().optional().describe("If true, reload current page instead of navigating")
6995
+ url: z5.string().optional().describe("URL to navigate to"),
6996
+ reload: z5.boolean().optional().describe("If true, reload current page instead of navigating")
7006
6997
  }, async ({ url, reload }) => {
7007
6998
  const c = getClient("simulator");
7008
6999
  if (reload) {
@@ -7017,15 +7008,15 @@ function registerSimulatorTools(server) {
7017
7008
  return { content: [{ type: "text", text: "Error: either url or reload is required" }], isError: true };
7018
7009
  });
7019
7010
  server.tool("simulator_input", "Dispatch input to the simulator. `tap_coord` requires x and y. `tap_selector` requires selector and optional nth. `type` requires selector and text. `scroll` requires x, y, deltaX, and deltaY. `key` is best-effort for common keys such as Enter, Escape, Tab, Arrow* and Space.", {
7020
- action: z4.enum(["tap_coord", "tap_selector", "type", "scroll", "key"]).describe("Input action to dispatch"),
7021
- x: z4.number().optional().describe("Viewport x coordinate for `tap_coord` or `scroll`"),
7022
- y: z4.number().optional().describe("Viewport y coordinate for `tap_coord` or `scroll`"),
7023
- selector: z4.string().optional().describe("CSS selector for `tap_selector` or `type`"),
7024
- nth: z4.number().int().optional().describe("Zero-based index when selector matches multiple elements; defaults to 0"),
7025
- text: z4.string().optional().describe("Text to insert for `type`"),
7026
- key: z4.string().optional().describe("Best-effort keyboard key name for `key`; common keys such as Enter, Escape, Tab, Arrow* and Space work best"),
7027
- deltaX: z4.number().optional().describe("Horizontal wheel delta for `scroll`"),
7028
- deltaY: z4.number().optional().describe("Vertical wheel delta for `scroll`")
7011
+ action: z5.enum(["tap_coord", "tap_selector", "type", "scroll", "key"]).describe("Input action to dispatch"),
7012
+ x: z5.number().optional().describe("Viewport x coordinate for `tap_coord` or `scroll`"),
7013
+ y: z5.number().optional().describe("Viewport y coordinate for `tap_coord` or `scroll`"),
7014
+ selector: z5.string().optional().describe("CSS selector for `tap_selector` or `type`"),
7015
+ nth: z5.number().int().optional().describe("Zero-based index when selector matches multiple elements; defaults to 0"),
7016
+ text: z5.string().optional().describe("Text to insert for `type`"),
7017
+ key: z5.string().optional().describe("Best-effort keyboard key name for `key`; common keys such as Enter, Escape, Tab, Arrow* and Space work best"),
7018
+ deltaX: z5.number().optional().describe("Horizontal wheel delta for `scroll`"),
7019
+ deltaY: z5.number().optional().describe("Vertical wheel delta for `scroll`")
7029
7020
  }, async ({ action, x, y, selector, nth, text, key, deltaX, deltaY }) => {
7030
7021
  const c = getClient("simulator");
7031
7022
  const err = (msg) => ({ content: [{ type: "text", text: `Error: ${msg}` }], isError: true });
@@ -7936,10 +7927,10 @@ function setupSimulatorCurrentPage(host, options) {
7936
7927
 
7937
7928
  // src/main/services/render-inspect/index.ts
7938
7929
  import { readFileSync } from "node:fs";
7939
- import path16 from "node:path";
7930
+ import path17 from "node:path";
7940
7931
  var DEFAULT_SOURCE_PATH = "dist/render-host/render-inspect.js";
7941
7932
  function createRenderInspector(options = {}) {
7942
- const loadSource = options.loadSource ?? (() => readFileSync(path16.join(devtoolsPackageRoot, DEFAULT_SOURCE_PATH), "utf8"));
7933
+ const loadSource = options.loadSource ?? (() => readFileSync(path17.join(devtoolsPackageRoot, DEFAULT_SOURCE_PATH), "utf8"));
7943
7934
  let cachedSource = null;
7944
7935
  const injected = /* @__PURE__ */ new Set();
7945
7936
  function source() {
@@ -8025,14 +8016,14 @@ function revokeAllTempFiles(store) {
8025
8016
 
8026
8017
  // src/shared/vpath.ts
8027
8018
  import os from "node:os";
8028
- import path17 from "node:path";
8019
+ import path18 from "node:path";
8029
8020
  var DIFILE_PREFIX = "difile://";
8030
8021
  function sandboxBase() {
8031
8022
  const env = typeof process !== "undefined" && process.env && process.env.DIMINA_HOME || "";
8032
8023
  if (env) {
8033
- return path17.join(env, "files");
8024
+ return path18.join(env, "files");
8034
8025
  }
8035
- return path17.join(os.homedir(), ".dimina", "files");
8026
+ return path18.join(os.homedir(), ".dimina", "files");
8036
8027
  }
8037
8028
  function resolveVPath(url) {
8038
8029
  if (typeof url !== "string") return null;
@@ -8066,15 +8057,15 @@ function resolveVPath(url) {
8066
8057
  return { kind, writable };
8067
8058
  }
8068
8059
  const base = sandboxBase();
8069
- const joined = path17.join(base, decoded);
8070
- const normalized = path17.normalize(joined);
8071
- if (normalized !== base && !normalized.startsWith(base + path17.sep)) return null;
8060
+ const joined = path18.join(base, decoded);
8061
+ const normalized = path18.normalize(joined);
8062
+ if (normalized !== base && !normalized.startsWith(base + path18.sep)) return null;
8072
8063
  return { kind, writable, realPath: normalized };
8073
8064
  }
8074
8065
 
8075
8066
  // src/main/services/simulator-temp-files/disk.ts
8076
- import fs9 from "node:fs/promises";
8077
- import path18 from "node:path";
8067
+ import fs8 from "node:fs/promises";
8068
+ import path19 from "node:path";
8078
8069
  var EXT_MIME = {
8079
8070
  ".txt": "text/plain",
8080
8071
  ".log": "text/plain",
@@ -8139,7 +8130,7 @@ function sniffMime(head) {
8139
8130
  return null;
8140
8131
  }
8141
8132
  function extMime(realPath) {
8142
- const ext = path18.extname(realPath).toLowerCase();
8133
+ const ext = path19.extname(realPath).toLowerCase();
8143
8134
  if (!ext) return null;
8144
8135
  return EXT_MIME[ext] ?? null;
8145
8136
  }
@@ -8154,7 +8145,7 @@ function etagOf(mtimeMs, size) {
8154
8145
  return `W/"${Math.floor(mtimeMs)}-${size}"`;
8155
8146
  }
8156
8147
  async function readDiskFile(realPath, opts) {
8157
- const handle = await fs9.open(realPath, "r");
8148
+ const handle = await fs8.open(realPath, "r");
8158
8149
  try {
8159
8150
  const st = await handle.stat();
8160
8151
  const totalSize = st.size;
@@ -8209,15 +8200,15 @@ async function readDiskFile(realPath, opts) {
8209
8200
  }
8210
8201
  async function writeDiskFile(realPath, bytes) {
8211
8202
  const buf = Buffer.isBuffer(bytes) ? bytes : Buffer.from(new Uint8Array(bytes));
8212
- await fs9.mkdir(path18.dirname(realPath), { recursive: true });
8213
- await fs9.writeFile(realPath, buf);
8203
+ await fs8.mkdir(path19.dirname(realPath), { recursive: true });
8204
+ await fs8.writeFile(realPath, buf);
8214
8205
  }
8215
8206
  async function readDiskDir(realPath) {
8216
- const entries = await fs9.readdir(realPath);
8207
+ const entries = await fs8.readdir(realPath);
8217
8208
  return entries;
8218
8209
  }
8219
8210
  async function statDiskFile(realPath) {
8220
- const st = await fs9.stat(realPath);
8211
+ const st = await fs8.stat(realPath);
8221
8212
  return {
8222
8213
  size: st.size,
8223
8214
  mtime: Math.floor(st.mtimeMs),
@@ -8350,29 +8341,29 @@ async function handleDifileRequest(ctx, req) {
8350
8341
  }
8351
8342
 
8352
8343
  // src/main/services/simulator-temp-files/fs-channels.ts
8353
- import fs10 from "node:fs/promises";
8354
- import path19 from "node:path";
8344
+ import fs9 from "node:fs/promises";
8345
+ import path20 from "node:path";
8355
8346
  async function enforceSandbox(realPath) {
8356
8347
  if (typeof realPath !== "string" || realPath.length === 0) {
8357
8348
  throw new Error("sandbox: realPath must be a non-empty string");
8358
8349
  }
8359
8350
  const base = sandboxBase();
8360
- const baseReal = await fs10.realpath(base).catch(() => base);
8361
- const normalized = path19.normalize(realPath);
8362
- if (normalized !== base && !normalized.startsWith(base + path19.sep)) {
8351
+ const baseReal = await fs9.realpath(base).catch(() => base);
8352
+ const normalized = path20.normalize(realPath);
8353
+ if (normalized !== base && !normalized.startsWith(base + path20.sep)) {
8363
8354
  throw new Error("sandbox: realPath escapes the user-data base");
8364
8355
  }
8365
8356
  let probe = normalized;
8366
- while (probe !== path19.parse(probe).root) {
8357
+ while (probe !== path20.parse(probe).root) {
8367
8358
  try {
8368
- const resolved = await fs10.realpath(probe);
8369
- if (resolved !== baseReal && !resolved.startsWith(baseReal + path19.sep)) {
8359
+ const resolved = await fs9.realpath(probe);
8360
+ if (resolved !== baseReal && !resolved.startsWith(baseReal + path20.sep)) {
8370
8361
  throw new Error("sandbox: realPath escapes the user-data base via symlink");
8371
8362
  }
8372
8363
  break;
8373
8364
  } catch (err) {
8374
8365
  if (err.code === "ENOENT") {
8375
- probe = path19.dirname(probe);
8366
+ probe = path20.dirname(probe);
8376
8367
  continue;
8377
8368
  }
8378
8369
  throw err;
@@ -8405,12 +8396,12 @@ async function handleFsReaddir(req) {
8405
8396
  }
8406
8397
  async function handleFsUnlink(req) {
8407
8398
  const safe = await enforceSandbox(req.realPath);
8408
- await fs10.unlink(safe);
8399
+ await fs9.unlink(safe);
8409
8400
  return { ok: true };
8410
8401
  }
8411
8402
  async function handleFsMkdir(req) {
8412
8403
  const safe = await enforceSandbox(req.realPath);
8413
- await fs10.mkdir(safe, { recursive: !!req.recursive });
8404
+ await fs9.mkdir(safe, { recursive: !!req.recursive });
8414
8405
  return { ok: true };
8415
8406
  }
8416
8407
 
@@ -8545,7 +8536,7 @@ function setupSimulatorTempFiles(simSession) {
8545
8536
  }
8546
8537
 
8547
8538
  // src/main/services/views/simulator-session-policy.ts
8548
- import { session as session2 } from "electron";
8539
+ import { session as session3 } from "electron";
8549
8540
  import { toDisposable as toDisposable7 } from "@dimina-kit/electron-deck/main";
8550
8541
  function applySimulatorWebRequestPolicy(simulatorSession) {
8551
8542
  simulatorSession.webRequest.onBeforeSendHeaders((details, callback) => {
@@ -8577,7 +8568,7 @@ function setupSimulatorSessionPolicy() {
8577
8568
  configured.add(sess);
8578
8569
  applySimulatorWebRequestPolicy(sess);
8579
8570
  }
8580
- install(session2.fromPartition(SHARED_MINIAPP_PARTITION));
8571
+ install(session3.fromPartition(SHARED_MINIAPP_PARTITION));
8581
8572
  const unregister = registerMiniappSessionConfigurator((sess) => install(sess));
8582
8573
  return toDisposable7(() => {
8583
8574
  unregister();
@@ -8756,7 +8747,7 @@ async function disposeContext(ctx) {
8756
8747
  function createConfiguredMainWindow(config, rendererDir2) {
8757
8748
  const mainWindow = createMainWindow({
8758
8749
  title: config.appName ?? "Dimina DevTools",
8759
- indexHtml: path20.join(rendererDir2, "entries/main/index.html"),
8750
+ indexHtml: path21.join(rendererDir2, "entries/main/index.html"),
8760
8751
  width: config.window?.width,
8761
8752
  height: config.window?.height,
8762
8753
  minWidth: config.window?.minWidth,
@@ -8774,10 +8765,8 @@ function createContext(config, mainWindow, rendererDir2) {
8774
8765
  adapter: config.adapter,
8775
8766
  preloadPath: config.preloadPath ?? defaultPreloadPath,
8776
8767
  rendererDir: rendererDir2,
8777
- panels: config.panels,
8778
8768
  appName: config.appName,
8779
8769
  apiNamespaces: config.apiNamespaces,
8780
- headerHeight: config.headerHeight,
8781
8770
  brandingProvider: config.brandingProvider,
8782
8771
  // The host-supplied ProjectsProvider / template types in `shared/types`
8783
8772
  // are structurally compatible with the main-process equivalents —
@@ -8796,13 +8785,21 @@ function registerBuiltinModules(config, context) {
8796
8785
  });
8797
8786
  }
8798
8787
  function toMenuContext(context) {
8799
- const menuContext = { ...context };
8800
- delete menuContext.registry;
8801
- delete menuContext.senderPolicy;
8802
- delete menuContext.trustedWindowSenderIds;
8803
- delete menuContext.simulatorApis;
8804
- delete menuContext.toolbar;
8805
- return menuContext;
8788
+ return {
8789
+ appName: context.appName,
8790
+ workspace: {
8791
+ hasActiveSession: () => context.workspace.hasActiveSession(),
8792
+ getProjectPath: () => context.workspace.getProjectPath(),
8793
+ openProject: (projectPath) => context.workspace.openProject(projectPath),
8794
+ closeProject: () => context.workspace.closeProject(),
8795
+ getSession: () => context.workspace.getSession()
8796
+ },
8797
+ openSettings: () => context.openSettings(),
8798
+ notify: {
8799
+ projectStatus: (payload) => context.notify.projectStatus(payload),
8800
+ windowNavigateBack: () => context.notify.windowNavigateBack()
8801
+ }
8802
+ };
8806
8803
  }
8807
8804
  function installMenu(config, mainWindow, context) {
8808
8805
  if (config.menuBuilder) {
@@ -8856,10 +8853,10 @@ function enableDevRendererAutoReload(rendererDir2) {
8856
8853
  });
8857
8854
  }
8858
8855
  let reloadTimer = null;
8859
- const watcher = fs11.watch(rendererDir2, { recursive: true }, () => {
8856
+ const watcher = fs10.watch(rendererDir2, { recursive: true }, () => {
8860
8857
  if (reloadTimer) clearTimeout(reloadTimer);
8861
8858
  reloadTimer = setTimeout(() => {
8862
- for (const win of BrowserWindow7.getAllWindows()) {
8859
+ for (const win of BrowserWindow8.getAllWindows()) {
8863
8860
  win.webContents.reload();
8864
8861
  }
8865
8862
  }, 300);
@@ -8893,7 +8890,7 @@ async function createDevtoolsRuntime(config = {}) {
8893
8890
  context.registry.add(setupSimulatorSessionPolicy());
8894
8891
  context.registry.add(installThemeBackgroundSync());
8895
8892
  registerBuiltinModules(config, context);
8896
- const simSession = session3.fromPartition(SHARED_MINIAPP_PARTITION);
8893
+ const simSession = session4.fromPartition(SHARED_MINIAPP_PARTITION);
8897
8894
  context.registry.add(setupSimulatorTempFiles(simSession));
8898
8895
  installMenu(config, mainWindow, context);
8899
8896
  const hostIpc = new IpcRegistry(context.senderPolicy);
@@ -8907,17 +8904,8 @@ async function createDevtoolsRuntime(config = {}) {
8907
8904
  // teardown, so a single dispose leaves no dead entry behind.
8908
8905
  registerTrustedWindow: (win) => context.registry.add(registerTrustedWindow(context, win)),
8909
8906
  registerSimulatorApi: (name, handler) => context.registry.add(toDisposable8(context.simulatorApis.register(name, handler))),
8910
- toolbar: {
8911
- set: (actions) => {
8912
- context.toolbar.set(actions);
8913
- context.notify.toolbarActionsChanged();
8914
- }
8915
- },
8916
8907
  dispose: () => disposeContext(context)
8917
8908
  };
8918
- if (config.onBeforeOpenProject) {
8919
- context.beforeOpenProject = (projectPath) => config.onBeforeOpenProject({ projectPath, instance });
8920
- }
8921
8909
  if (config.onSetup) {
8922
8910
  await config.onSetup(instance);
8923
8911
  }
@@ -8936,8 +8924,8 @@ async function createDevtoolsRuntime(config = {}) {
8936
8924
  const mcp = setupMcp();
8937
8925
  if (mcp) context.registry.add(mcp);
8938
8926
  const getActiveAppId = () => {
8939
- const session4 = context.workspace.getSession();
8940
- const appInfo = session4?.appInfo;
8927
+ const session5 = context.workspace.getSession();
8928
+ const appInfo = session5?.appInfo;
8941
8929
  return appInfo?.appId ?? null;
8942
8930
  };
8943
8931
  if (context.bridge?.isNativeHost()) {
@@ -9086,56 +9074,10 @@ function createDevtoolsBackend(config = {}) {
9086
9074
  };
9087
9075
  }
9088
9076
 
9089
- // src/main/windows/settings-window/create.ts
9090
- import { BrowserWindow as BrowserWindow8 } from "electron";
9091
- import path21 from "path";
9092
- async function createSettingsWindow(parent, rendererDir2) {
9093
- const win = new BrowserWindow8({
9094
- width: 420,
9095
- height: 560,
9096
- minWidth: 380,
9097
- minHeight: 480,
9098
- parent: parent ?? void 0,
9099
- title: "\u5F00\u53D1\u5DE5\u5177\u8BBE\u7F6E",
9100
- backgroundColor: themeBg(),
9101
- webPreferences: {
9102
- nodeIntegration: false,
9103
- contextIsolation: true,
9104
- sandbox: false,
9105
- preload: mainPreloadPath
9106
- }
9107
- });
9108
- applyNavigationHardening(win.webContents, rendererDir2);
9109
- await win.loadFile(path21.join(rendererDir2, "entries/workbench-settings/index.html"));
9110
- return win;
9111
- }
9112
-
9113
- // src/main/windows/settings-window/events.ts
9114
- function wireSettingsWindowEvents(win, onClosed) {
9115
- win.on("closed", () => {
9116
- onClosed();
9117
- });
9118
- }
9119
-
9120
9077
  // src/main/app/launch.ts
9121
9078
  function launch(config = {}) {
9122
9079
  return frameworkElectronDeck({ backend: createDevtoolsBackend(config) });
9123
9080
  }
9124
- async function openSettingsWindow(ctx) {
9125
- let win = ctx.windows.settingsWindow;
9126
- if (!win || win.isDestroyed()) {
9127
- win = await createSettingsWindow(ctx.windows.mainWindow, ctx.rendererDir);
9128
- ctx.windows.setSettingsWindow(win);
9129
- wireSettingsWindowEvents(win, () => {
9130
- ctx.windows.setSettingsWindow(null);
9131
- });
9132
- }
9133
- win.show();
9134
- win.focus();
9135
- ctx.notify.workbenchSettingsInit(win, {
9136
- settings: loadWorkbenchSettings()
9137
- });
9138
- }
9139
9081
 
9140
9082
  // src/main/index.ts
9141
9083
  launch().catch((err) => {