@dimina-kit/devtools 0.3.2-dev.20260601115343 → 0.3.2-dev.20260610082053

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 (184) hide show
  1. package/README.md +49 -59
  2. package/dist/main/api.d.ts +1 -2
  3. package/dist/main/api.js +5 -1
  4. package/dist/main/app/app.d.ts +15 -5
  5. package/dist/main/app/app.js +242 -122
  6. package/dist/main/app/bootstrap.d.ts +16 -0
  7. package/dist/main/app/bootstrap.js +20 -0
  8. package/dist/main/app/launch.d.ts +8 -4
  9. package/dist/main/app/launch.js +9 -4
  10. package/dist/main/index.bundle.js +5812 -1729
  11. package/dist/main/index.js +9 -1
  12. package/dist/main/ipc/app.d.ts +1 -1
  13. package/dist/main/ipc/bridge-router.d.ts +61 -0
  14. package/dist/main/ipc/bridge-router.js +1300 -0
  15. package/dist/main/ipc/panels.d.ts +1 -1
  16. package/dist/main/ipc/panels.js +6 -2
  17. package/dist/main/ipc/popover.d.ts +1 -1
  18. package/dist/main/ipc/project-fs.d.ts +1 -1
  19. package/dist/main/ipc/projects.d.ts +1 -1
  20. package/dist/main/ipc/session.d.ts +1 -1
  21. package/dist/main/ipc/settings.d.ts +1 -1
  22. package/dist/main/ipc/simulator-module.d.ts +6 -0
  23. package/dist/main/ipc/simulator-module.js +9 -1
  24. package/dist/main/ipc/simulator.d.ts +2 -2
  25. package/dist/main/ipc/simulator.js +49 -5
  26. package/dist/main/ipc/toolbar.d.ts +1 -1
  27. package/dist/main/ipc/views.d.ts +1 -1
  28. package/dist/main/ipc/views.js +40 -2
  29. package/dist/main/runtime/devtools-backend.d.ts +17 -0
  30. package/dist/main/runtime/devtools-backend.js +49 -0
  31. package/dist/main/runtime/miniapp-runtime.d.ts +39 -0
  32. package/dist/main/runtime/miniapp-runtime.js +17 -0
  33. package/dist/main/services/automation/exec.d.ts +27 -2
  34. package/dist/main/services/automation/exec.js +37 -3
  35. package/dist/main/services/automation/handlers/app.js +127 -11
  36. package/dist/main/services/automation/handlers/page.js +36 -19
  37. package/dist/main/services/automation/index.js +40 -13
  38. package/dist/main/services/automation/wait-active-page.d.ts +56 -0
  39. package/dist/main/services/automation/wait-active-page.js +71 -0
  40. package/dist/main/services/console-forward/index.d.ts +36 -0
  41. package/dist/main/services/console-forward/index.js +81 -0
  42. package/dist/main/services/dimina-resource-server.d.ts +7 -0
  43. package/dist/main/services/dimina-resource-server.js +99 -0
  44. package/dist/main/services/elements-forward/index.d.ts +66 -0
  45. package/dist/main/services/elements-forward/index.js +583 -0
  46. package/dist/main/services/layout/index.d.ts +22 -0
  47. package/dist/main/services/layout/index.js +25 -0
  48. package/dist/main/services/mcp/index.d.ts +1 -0
  49. package/dist/main/services/mcp/index.js +3 -0
  50. package/dist/main/services/mcp/server.d.ts +1 -1
  51. package/dist/main/services/mcp/server.js +1 -1
  52. package/dist/main/services/mcp/target-manager.d.ts +35 -0
  53. package/dist/main/services/mcp/target-manager.js +63 -1
  54. package/dist/main/services/mcp/tools/context-tools.js +15 -1
  55. package/dist/main/services/module.d.ts +1 -1
  56. package/dist/main/services/network-forward/index.d.ts +190 -0
  57. package/dist/main/services/network-forward/index.js +765 -0
  58. package/dist/main/services/notifications/renderer-notifier.d.ts +11 -0
  59. package/dist/main/services/notifications/renderer-notifier.js +7 -1
  60. package/dist/main/services/render-inspect/index.d.ts +41 -0
  61. package/dist/main/services/render-inspect/index.js +88 -0
  62. package/dist/main/services/safe-area/index.d.ts +17 -0
  63. package/dist/main/services/safe-area/index.js +59 -0
  64. package/dist/main/services/service-host-pool/pool.d.ts +197 -0
  65. package/dist/main/services/service-host-pool/pool.js +364 -0
  66. package/dist/main/services/simulator/custom-apis.d.ts +34 -0
  67. package/dist/main/services/simulator/custom-apis.js +22 -0
  68. package/dist/main/services/simulator-appdata/index.d.ts +35 -0
  69. package/dist/main/services/simulator-appdata/index.js +71 -0
  70. package/dist/main/services/simulator-current-page/index.d.ts +24 -0
  71. package/dist/main/services/simulator-current-page/index.js +19 -0
  72. package/dist/main/services/simulator-storage/index.d.ts +37 -2
  73. package/dist/main/services/simulator-storage/index.js +209 -32
  74. package/dist/main/services/simulator-storage/service-storage-ops.d.ts +40 -0
  75. package/dist/main/services/simulator-storage/service-storage-ops.js +67 -0
  76. package/dist/main/services/simulator-temp-files/index.d.ts +1 -1
  77. package/dist/main/services/simulator-temp-files/index.js +1 -1
  78. package/dist/main/services/simulator-wxml/index.d.ts +29 -0
  79. package/dist/main/services/simulator-wxml/index.js +28 -0
  80. package/dist/main/services/toolbar/toolbar-store.d.ts +3 -3
  81. package/dist/main/services/toolbar/toolbar-store.js +1 -18
  82. package/dist/main/services/views/devtools-tabs.d.ts +47 -0
  83. package/dist/main/services/views/devtools-tabs.js +95 -0
  84. package/dist/main/services/views/view-manager.d.ts +125 -0
  85. package/dist/main/services/views/view-manager.js +839 -4
  86. package/dist/main/services/workbench-context.d.ts +67 -7
  87. package/dist/main/services/workbench-context.js +6 -1
  88. package/dist/main/services/workspace/workspace-service.js +7 -13
  89. package/dist/main/utils/ipc-registry.d.ts +1 -1
  90. package/dist/main/utils/ipc-registry.js +21 -4
  91. package/dist/main/utils/paths.d.ts +15 -0
  92. package/dist/main/utils/paths.js +19 -0
  93. package/dist/main/utils/sender-policy.d.ts +9 -3
  94. package/dist/main/utils/sender-policy.js +18 -4
  95. package/dist/main/utils/theme.d.ts +1 -1
  96. package/dist/main/utils/theme.js +1 -1
  97. package/dist/main/windows/main-window/create.d.ts +0 -6
  98. package/dist/main/windows/main-window/create.js +11 -59
  99. package/dist/main/windows/main-window/events.d.ts +1 -1
  100. package/dist/main/windows/main-window/events.js +1 -1
  101. package/dist/main/windows/service-host-window/create.d.ts +52 -0
  102. package/dist/main/windows/service-host-window/create.js +112 -0
  103. package/dist/native-host/common/common.js +368 -0
  104. package/dist/native-host/container/pageFrame.css +1 -0
  105. package/dist/native-host/render/render.js +9334 -0
  106. package/dist/native-host/service/service.js +6 -0
  107. package/dist/preload/index.d.ts +2 -0
  108. package/dist/preload/index.js +6 -0
  109. package/dist/preload/instrumentation/app-data.d.ts +18 -20
  110. package/dist/preload/instrumentation/app-data.js +23 -160
  111. package/dist/preload/instrumentation/wxml-extract.d.ts +1 -1
  112. package/dist/preload/instrumentation/wxml-extract.js +1 -1
  113. package/dist/preload/runtime/bridge.d.ts +3 -8
  114. package/dist/preload/runtime/bridge.js +2 -32
  115. package/dist/preload/runtime/custom-apis.js +20 -17
  116. package/dist/preload/runtime/host-toolbar-advertiser.d.ts +27 -0
  117. package/dist/preload/runtime/host-toolbar-advertiser.js +55 -0
  118. package/dist/preload/runtime/main-api-runner.d.ts +9 -0
  119. package/dist/preload/runtime/main-api-runner.js +85 -0
  120. package/dist/preload/runtime/native-host.d.ts +43 -0
  121. package/dist/preload/runtime/native-host.js +83 -0
  122. package/dist/preload/shared/expose.d.ts +10 -5
  123. package/dist/preload/shared/expose.js +30 -12
  124. package/dist/preload/shared/sid-registry.d.ts +11 -0
  125. package/dist/preload/shared/sid-registry.js +38 -0
  126. package/dist/preload/windows/host-toolbar.cjs +161 -0
  127. package/dist/preload/windows/host-toolbar.cjs.map +7 -0
  128. package/dist/preload/windows/host-toolbar.d.ts +2 -0
  129. package/dist/preload/windows/host-toolbar.js +12 -0
  130. package/dist/preload/windows/main.cjs +1935 -0
  131. package/dist/preload/windows/main.cjs.map +4 -4
  132. package/dist/preload/windows/simulator.cjs +925 -0
  133. package/dist/preload/windows/simulator.cjs.map +7 -0
  134. package/dist/preload/windows/simulator.js +244 -574
  135. package/dist/render-host/pageFrame.html +29 -0
  136. package/dist/render-host/preload.cjs +154 -0
  137. package/dist/render-host/render-inspect.js +295 -0
  138. package/dist/renderer/assets/index-CcJKzatF.js +50 -0
  139. package/dist/renderer/assets/{input-CCYS8Ave.js → input-QGx6FFX1.js} +2 -2
  140. package/dist/renderer/assets/ipc-transport-BT4QYQqu.css +1 -0
  141. package/dist/renderer/assets/{ipc-transport-Bn4KXvhu.js → ipc-transport-DvZvwK-Z.js} +2 -2
  142. package/dist/renderer/assets/{popover-CH4rwpdt.js → popover-BOH1If1J.js} +2 -2
  143. package/dist/renderer/assets/select-C7JQ8G5N.js +2 -0
  144. package/dist/renderer/assets/{settings-CMTB-t0x.js → settings-DpAbTJyF.js} +2 -2
  145. package/dist/renderer/assets/{settings-api-Csdngf9Z.js → settings-api-RD2IZF53.js} +2 -2
  146. package/dist/renderer/assets/{workbenchSettings-CODFCzOg.js → workbenchSettings-CNJX4Qna.js} +2 -2
  147. package/dist/renderer/entries/main/index.html +5 -5
  148. package/dist/renderer/entries/popover/index.html +5 -5
  149. package/dist/renderer/entries/settings/index.html +5 -5
  150. package/dist/renderer/entries/workbench-settings/index.html +4 -4
  151. package/dist/service-host/preload.cjs +254 -0
  152. package/dist/service-host/service.html +10 -0
  153. package/dist/service-host/sourcemap-rewrite.cjs +58 -0
  154. package/dist/service-host/sync-api-patch.js +20 -0
  155. package/dist/service-host/sync-impls/menu-button.js +16 -0
  156. package/dist/service-host/sync-impls/storage.js +50 -0
  157. package/dist/service-host/sync-impls/system-info.js +54 -0
  158. package/dist/shared/appdata-accumulator.d.ts +95 -0
  159. package/dist/shared/appdata-accumulator.js +213 -0
  160. package/dist/shared/bridge-channels.d.ts +364 -0
  161. package/dist/shared/bridge-channels.js +54 -0
  162. package/dist/shared/ipc-channels.d.ts +84 -1
  163. package/dist/shared/ipc-channels.js +90 -10
  164. package/dist/shared/ipc-schemas.d.ts +59 -2
  165. package/dist/shared/ipc-schemas.js +64 -3
  166. package/dist/shared/open-in-editor.d.ts +71 -0
  167. package/dist/shared/open-in-editor.js +138 -0
  168. package/dist/shared/simulator-api-metadata.d.ts +21 -0
  169. package/dist/shared/simulator-api-metadata.js +23 -0
  170. package/dist/shared/types.d.ts +2 -39
  171. package/dist/simulator/assets/device-shell-DsdcNEkt.css +1 -0
  172. package/dist/simulator/assets/device-shell-vwYSOVrh.js +2 -0
  173. package/dist/simulator/assets/jsx-runtime-P6ZegaOf.js +2 -0
  174. package/dist/simulator/assets/simulator-DddliUL5.js +10 -0
  175. package/dist/simulator/assets/simulator-mini-app-BDNu5n26.js +2 -0
  176. package/dist/simulator/device-shell/menu-button-geometry.js +8 -0
  177. package/dist/simulator/simulator.html +2 -112
  178. package/package.json +8 -9
  179. package/dist/main/utils/disposable.d.ts +0 -18
  180. package/dist/main/utils/disposable.js +0 -67
  181. package/dist/renderer/assets/index-BDMxXUfn.js +0 -50
  182. package/dist/renderer/assets/ipc-transport-Cu7tubyg.css +0 -1
  183. package/dist/renderer/assets/select-Ct4-sijm.js +0 -2
  184. package/dist/simulator/assets/simulator-B4e3c6_O.js +0 -9
@@ -1,4 +1,4 @@
1
1
  import type { WorkbenchContext } from '../services/workbench-context.js';
2
- import type { Disposable } from '../utils/disposable.js';
2
+ import type { Disposable } from '@dimina-kit/electron-deck/main';
3
3
  export declare function registerPanelsIpc(ctx: Pick<WorkbenchContext, 'panels' | 'views' | 'workspace' | 'senderPolicy'>): Disposable;
4
4
  //# sourceMappingURL=panels.d.ts.map
@@ -1,4 +1,4 @@
1
- import { PanelChannel } from '../../shared/ipc-channels.js';
1
+ import { PanelChannel, WorkbenchRuntimeChannel } from '../../shared/ipc-channels.js';
2
2
  import { PanelEvalSchema, PanelSelectSchema, } from '../../shared/ipc-schemas.js';
3
3
  import { validate } from '../utils/ipc-schema.js';
4
4
  import { IpcRegistry } from '../utils/ipc-registry.js';
@@ -37,6 +37,10 @@ export function registerPanelsIpc(ctx) {
37
37
  if (ctx.views.hasSimulatorView() && !ctx.views.isSimulatorAdded()) {
38
38
  ctx.views.showSimulator(ctx.views.getLastSimWidth());
39
39
  }
40
- });
40
+ })
41
+ // Renderer reads this once to pick panel data sources: native-host is the
42
+ // sole runtime, so WXML + AppData always come from the main process (the
43
+ // page/service logic live in separate webContents).
44
+ .handle(WorkbenchRuntimeChannel.GetNativeHost, () => true);
41
45
  }
42
46
  //# sourceMappingURL=panels.js.map
@@ -1,6 +1,6 @@
1
1
  import type { WorkbenchContext } from '../services/workbench-context.js';
2
2
  import type { WorkbenchModule } from '../services/module.js';
3
- import type { Disposable } from '../utils/disposable.js';
3
+ import type { Disposable } from '@dimina-kit/electron-deck/main';
4
4
  export declare function registerPopoverIpc(ctx: Pick<WorkbenchContext, 'views' | 'notify' | 'senderPolicy'>): Disposable;
5
5
  export declare const popoverModule: WorkbenchModule;
6
6
  //# sourceMappingURL=popover.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import type { WorkbenchContext } from '../services/workbench-context.js';
2
- import type { Disposable } from '../utils/disposable.js';
2
+ import type { Disposable } from '@dimina-kit/electron-deck/main';
3
3
  /**
4
4
  * Synchronous, string-level guard: reject empty root (ENOACTIVE), NUL bytes
5
5
  * and empty paths (EINVAL), and lexical `..` escapes (EACCES) by resolving
@@ -1,6 +1,6 @@
1
1
  import type { WorkbenchContext } from '../services/workbench-context.js';
2
2
  import type { WorkbenchModule } from '../services/module.js';
3
- import type { Disposable } from '../utils/disposable.js';
3
+ import type { Disposable } from '@dimina-kit/electron-deck/main';
4
4
  type ProjectsIpcCtx = Pick<WorkbenchContext, 'workspace' | 'windows' | 'senderPolicy' | 'projectsProvider' | 'projectTemplates' | 'customCreateProjectDialog'>;
5
5
  export declare function registerProjectsIpc(ctx: ProjectsIpcCtx): Disposable;
6
6
  export declare const projectsModule: WorkbenchModule;
@@ -1,6 +1,6 @@
1
1
  import type { WorkbenchContext } from '../services/workbench-context.js';
2
2
  import type { WorkbenchModule } from '../services/module.js';
3
- import type { Disposable } from '../utils/disposable.js';
3
+ import type { Disposable } from '@dimina-kit/electron-deck/main';
4
4
  export declare function registerSessionIpc(ctx: Pick<WorkbenchContext, 'workspace' | 'senderPolicy'>): Disposable;
5
5
  export declare const sessionModule: WorkbenchModule;
6
6
  //# sourceMappingURL=session.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import type { WorkbenchContext } from '../services/workbench-context.js';
2
- import type { Disposable } from '../utils/disposable.js';
2
+ import type { Disposable } from '@dimina-kit/electron-deck/main';
3
3
  import type { WorkbenchModule } from '../services/module.js';
4
4
  export declare function registerSettingsIpc(ctx: Pick<WorkbenchContext, 'views' | 'notify' | 'workspace' | 'rendererDir' | 'senderPolicy' | 'windows'>): Disposable;
5
5
  export declare const settingsModule: WorkbenchModule;
@@ -3,6 +3,12 @@ import type { WorkbenchModule } from '../services/module.js';
3
3
  * The 'simulator' built-in module fans out into three IPC registrars
4
4
  * (core simulator, panels, toolbar). Bundle them under a single module
5
5
  * so app.ts only sees one entry per BuiltinModuleId.
6
+ *
7
+ * Bridge router (native-host PAGE_OPEN / NAV_ACTION / TAB_ACTION etc.) hooks
8
+ * up unconditionally — the `__diminaNativeHost.enabled` flag in the simulator
9
+ * window decides whether to actually call dmb:* channels, but the main-side
10
+ * handlers must always be ready or `ipcRenderer.invoke('dmb:spawn')` fails
11
+ * with `No handler registered`.
6
12
  */
7
13
  export declare const simulatorModule: WorkbenchModule;
8
14
  //# sourceMappingURL=simulator-module.d.ts.map
@@ -1,12 +1,19 @@
1
- import { DisposableRegistry } from '../utils/disposable.js';
1
+ import { DisposableRegistry } from '@dimina-kit/electron-deck/main';
2
2
  import { registerSimulatorIpc } from './simulator.js';
3
3
  import { registerPanelsIpc } from './panels.js';
4
4
  import { registerToolbarIpc } from './toolbar.js';
5
+ import { installBridgeRouter } from './bridge-router.js';
5
6
  import { registerViewsIpc } from './views.js';
6
7
  /**
7
8
  * The 'simulator' built-in module fans out into three IPC registrars
8
9
  * (core simulator, panels, toolbar). Bundle them under a single module
9
10
  * so app.ts only sees one entry per BuiltinModuleId.
11
+ *
12
+ * Bridge router (native-host PAGE_OPEN / NAV_ACTION / TAB_ACTION etc.) hooks
13
+ * up unconditionally — the `__diminaNativeHost.enabled` flag in the simulator
14
+ * window decides whether to actually call dmb:* channels, but the main-side
15
+ * handlers must always be ready or `ipcRenderer.invoke('dmb:spawn')` fails
16
+ * with `No handler registered`.
10
17
  */
11
18
  export const simulatorModule = {
12
19
  setup: (ctx) => {
@@ -15,6 +22,7 @@ export const simulatorModule = {
15
22
  reg.add(registerPanelsIpc(ctx));
16
23
  reg.add(registerToolbarIpc(ctx));
17
24
  reg.add(registerViewsIpc(ctx));
25
+ installBridgeRouter(ctx);
18
26
  return reg;
19
27
  },
20
28
  };
@@ -1,4 +1,4 @@
1
1
  import type { WorkbenchContext } from '../services/workbench-context.js';
2
- import type { Disposable } from '../utils/disposable.js';
3
- export declare function registerSimulatorIpc(ctx: Pick<WorkbenchContext, 'views' | 'notify' | 'senderPolicy' | 'simulatorApis'>): Disposable;
2
+ import type { Disposable } from '@dimina-kit/electron-deck/main';
3
+ export declare function registerSimulatorIpc(ctx: Pick<WorkbenchContext, 'views' | 'notify' | 'senderPolicy' | 'simulatorApis' | 'bridge'>): Disposable;
4
4
  //# sourceMappingURL=simulator.d.ts.map
@@ -1,12 +1,33 @@
1
- import { SimulatorChannel, SimulatorCustomApiChannel } from '../../shared/ipc-channels.js';
2
- import { SimulatorAttachSchema, SimulatorCustomApiInvokeSchema, SimulatorResizeSchema, SimulatorSetVisibleSchema, } from '../../shared/ipc-schemas.js';
1
+ import { ServiceHostChannel, SimulatorChannel, SimulatorCustomApiChannel } from '../../shared/ipc-channels.js';
2
+ import { SimulatorAttachNativeSchema, SimulatorCustomApiInvokeSchema, SimulatorResizeSchema, SimulatorSetDeviceInfoSchema, SimulatorSetNativeBoundsSchema, SimulatorSetVisibleSchema, } from '../../shared/ipc-schemas.js';
3
3
  import { validate } from '../utils/ipc-schema.js';
4
4
  import { IpcRegistry } from '../utils/ipc-registry.js';
5
+ /**
6
+ * Map the renderer's logical device metrics onto the subset of a
7
+ * HostEnvSnapshot the service-host window's `getSystemInfoSync` consumes.
8
+ * `windowHeight` excludes the status bar (the page area); `windowWidth` has no
9
+ * horizontal chrome. Zoom is intentionally absent — it is a display scale, not
10
+ * a logical-size change.
11
+ */
12
+ function deviceInfoToHostEnv(d) {
13
+ return {
14
+ brand: d.brand,
15
+ model: d.model,
16
+ system: d.system,
17
+ platform: d.platform,
18
+ pixelRatio: d.pixelRatio,
19
+ screenWidth: d.screenWidth,
20
+ screenHeight: d.screenHeight,
21
+ windowWidth: d.screenWidth,
22
+ windowHeight: Math.max(0, d.screenHeight - d.statusBarHeight),
23
+ statusBarHeight: d.statusBarHeight,
24
+ };
25
+ }
5
26
  export function registerSimulatorIpc(ctx) {
6
27
  return new IpcRegistry(ctx.senderPolicy)
7
- .handle(SimulatorChannel.Attach, (_, ...args) => {
8
- const [simWcId, simWidth] = validate(SimulatorChannel.Attach, SimulatorAttachSchema, args);
9
- ctx.views.attachSimulator(simWcId, simWidth);
28
+ .handle(SimulatorChannel.AttachNative, (_, ...args) => {
29
+ const [simulatorUrl, simWidth] = validate(SimulatorChannel.AttachNative, SimulatorAttachNativeSchema, args);
30
+ ctx.views.attachNativeSimulator(simulatorUrl, simWidth);
10
31
  })
11
32
  .handle(SimulatorChannel.Detach, () => {
12
33
  ctx.views.detachSimulator();
@@ -14,6 +35,29 @@ export function registerSimulatorIpc(ctx) {
14
35
  .handle(SimulatorChannel.Resize, (_, ...args) => {
15
36
  const [simWidth] = validate(SimulatorChannel.Resize, SimulatorResizeSchema, args);
16
37
  ctx.views.resize(simWidth);
38
+ })
39
+ .handle(SimulatorChannel.SetNativeBounds, (_, ...args) => {
40
+ const [p] = validate(SimulatorChannel.SetNativeBounds, SimulatorSetNativeBoundsSchema, args);
41
+ ctx.views.setNativeSimulatorViewBounds(p);
42
+ })
43
+ .handle(SimulatorChannel.SetDeviceInfo, (_, ...args) => {
44
+ const [device] = validate(SimulatorChannel.SetDeviceInfo, SimulatorSetDeviceInfoSchema, args);
45
+ // Cache the selection (rides the next NATIVE_HOST_ENABLED reply for a
46
+ // race-free DeviceShell init) and push DEVICE_CHANGE to the live simulator
47
+ // WCV so the DeviceShell resizes the bezel + re-renders status bar / notch.
48
+ ctx.bridge?.setDevice(device);
49
+ // Re-push the CSS env(safe-area-inset-*) override to attached render-host
50
+ // guests so notch-aware page layout updates without a reload.
51
+ ctx.views.reapplySafeArea(device);
52
+ // Live-update the running service-host window's host-env snapshot so
53
+ // `wx.getSystemInfoSync()` reflects the selected device without a relaunch.
54
+ // The service-host preload mutates `__diminaSpawnContext` in place;
55
+ // `getSystemInfoSync` reads it fresh on each call. No service window yet
56
+ // (pre-spawn) → no-op.
57
+ const serviceWc = ctx.bridge?.getServiceWc();
58
+ if (serviceWc && !serviceWc.isDestroyed()) {
59
+ serviceWc.send(ServiceHostChannel.HostEnvUpdate, deviceInfoToHostEnv(device));
60
+ }
17
61
  })
18
62
  .handle(SimulatorChannel.SetVisible, (_, ...args) => {
19
63
  const [visible, simWidth] = validate(SimulatorChannel.SetVisible, SimulatorSetVisibleSchema, args);
@@ -1,4 +1,4 @@
1
1
  import type { WorkbenchContext } from '../services/workbench-context.js';
2
- import type { Disposable } from '../utils/disposable.js';
2
+ import type { Disposable } from '@dimina-kit/electron-deck/main';
3
3
  export declare function registerToolbarIpc(ctx: Pick<WorkbenchContext, 'toolbar' | 'senderPolicy'>): Disposable;
4
4
  //# sourceMappingURL=toolbar.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import type { WorkbenchContext } from '../services/workbench-context.js';
2
- import type { Disposable } from '../utils/disposable.js';
2
+ import type { Disposable } from '@dimina-kit/electron-deck/main';
3
3
  /**
4
4
  * Renderer-driven overlay bounds.
5
5
  *
@@ -1,5 +1,6 @@
1
+ import { ipcMain } from 'electron';
1
2
  import { ViewChannel } from '../../shared/ipc-channels.js';
2
- import { ViewBoundsSchema } from '../../shared/ipc-schemas.js';
3
+ import { ViewBoundsSchema, HostToolbarAdvertiseHeightSchema, } from '../../shared/ipc-schemas.js';
3
4
  import { validate } from '../utils/ipc-schema.js';
4
5
  import { IpcRegistry } from '../utils/ipc-registry.js';
5
6
  /**
@@ -18,10 +19,47 @@ import { IpcRegistry } from '../utils/ipc-registry.js';
18
19
  * subsequent re-shows skip the OpenSumi DI bootstrap.
19
20
  */
20
21
  export function registerViewsIpc(ctx) {
21
- return new IpcRegistry(ctx.senderPolicy)
22
+ const registry = new IpcRegistry(ctx.senderPolicy)
22
23
  .handle(ViewChannel.SimulatorDevtoolsBounds, (_event, ...args) => {
23
24
  const [bounds] = validate(ViewChannel.SimulatorDevtoolsBounds, ViewBoundsSchema, args);
24
25
  ctx.views.setSimulatorDevtoolsBounds(bounds);
26
+ })
27
+ // Host-controllable toolbar: forward anchor (the MAIN renderer measures the
28
+ // placeholder rect → toolbar WCV bounds). invoke, mirroring
29
+ // SimulatorDevtoolsBounds. Sender is the trusted main renderer.
30
+ .handle(ViewChannel.HostToolbarBounds, (_event, ...args) => {
31
+ const [bounds] = validate(ViewChannel.HostToolbarBounds, ViewBoundsSchema, args);
32
+ ctx.views.setHostToolbarBounds(bounds);
25
33
  });
34
+ // Reverse size-advertiser: the toolbar WCV's OWN renderer sends this, and the
35
+ // host loads ARBITRARY content into that WCV. We DELIBERATELY do NOT add the
36
+ // toolbar wc to the global sender policy — that would trust it for ALL ~72
37
+ // IpcRegistry channels (project-fs / session / settings / panels
38
+ // executeJavaScript / storage …), a large blast radius if the host content is
39
+ // ever compromised. Instead this is a RAW `ipcMain.on` gated on the EXACT
40
+ // current host-toolbar wc id — the same precise-sender-id trust model the
41
+ // simulator custom-api bridge uses (view-manager `attachNativeCustomApiBridge`).
42
+ // The host content can reach ONLY this one channel, carrying only a
43
+ // non-negative integer height.
44
+ const onAdvertiseHeight = (event, ...args) => {
45
+ if (event.sender.id !== ctx.views.getHostToolbarWebContentsId())
46
+ return;
47
+ let extent;
48
+ try {
49
+ ;
50
+ [{ extent }] = validate(ViewChannel.HostToolbarAdvertiseHeight, HostToolbarAdvertiseHeightSchema, args);
51
+ }
52
+ catch {
53
+ return; // malformed payload from the host's own content — drop it
54
+ }
55
+ ctx.views.setHostToolbarHeight(extent);
56
+ };
57
+ ipcMain.on(ViewChannel.HostToolbarAdvertiseHeight, onAdvertiseHeight);
58
+ return {
59
+ dispose() {
60
+ void registry.dispose();
61
+ ipcMain.removeListener(ViewChannel.HostToolbarAdvertiseHeight, onAdvertiseHeight);
62
+ },
63
+ };
26
64
  }
27
65
  //# sourceMappingURL=views.js.map
@@ -0,0 +1,17 @@
1
+ import type { RuntimeBackend } from '@dimina-kit/electron-deck';
2
+ import type { WorkbenchAppConfig } from '../../shared/types.js';
3
+ /**
4
+ * Adapts the devtools runtime into a {@link RuntimeBackend} the framework
5
+ * (`@dimina-kit/electron-deck`) orchestrates. The framework owns the process
6
+ * lifecycle gate (whenReady) + wire/trust primitives; the backend supplies the
7
+ * full devtools assembly — reusing the exact same `runDevtoolsBootstrap` / `createDevtoolsRuntime`
8
+ * assembly bodies (extracted from the former createWorkbenchApp), so the app is
9
+ * byte-identical to the pre-extraction behaviour (no behavioural re-creation).
10
+ *
11
+ * v2 scope: the backend owns window creation (the framework skips its own when a
12
+ * backend is present), so `assemble` ignores the framework `runtime` and builds
13
+ * the real devtools main window itself. Trust/frame unification and surfacing
14
+ * the runtime facade are deferred (see framework-extraction-v2.md §7).
15
+ */
16
+ export declare function createDevtoolsBackend(config?: WorkbenchAppConfig): RuntimeBackend;
17
+ //# sourceMappingURL=devtools-backend.d.ts.map
@@ -0,0 +1,49 @@
1
+ import { runDevtoolsBootstrap, createDevtoolsRuntime } from '../app/app.js';
2
+ import { registerAppLifecycle } from '../app/lifecycle.js';
3
+ /**
4
+ * Adapts the devtools runtime into a {@link RuntimeBackend} the framework
5
+ * (`@dimina-kit/electron-deck`) orchestrates. The framework owns the process
6
+ * lifecycle gate (whenReady) + wire/trust primitives; the backend supplies the
7
+ * full devtools assembly — reusing the exact same `runDevtoolsBootstrap` / `createDevtoolsRuntime`
8
+ * assembly bodies (extracted from the former createWorkbenchApp), so the app is
9
+ * byte-identical to the pre-extraction behaviour (no behavioural re-creation).
10
+ *
11
+ * v2 scope: the backend owns window creation (the framework skips its own when a
12
+ * backend is present), so `assemble` ignores the framework `runtime` and builds
13
+ * the real devtools main window itself. Trust/frame unification and surfacing
14
+ * the runtime facade are deferred (see framework-extraction-v2.md §7).
15
+ */
16
+ export function createDevtoolsBackend(config = {}) {
17
+ // Hoisted so `onShutdown` can reach the assembled context (assigned by `assemble`).
18
+ let instance = null;
19
+ return {
20
+ // The backend builds the devtools main window itself (framework skips its own).
21
+ // Its only construction-time needs are the host preload + `sandbox:false`
22
+ // (main-window/create.ts) and wrapping contentView in a `View` container.
23
+ // NOTE: `ownsWindows` is NOT structurally required — the framework's
24
+ // `mainWindowWebPreferences()` + `onMainWindowCreated()` hooks can supply both,
25
+ // and the project close→back lifecycle maps onto the Window facade's
26
+ // `onClose`/`newSession` (probe-validated). Retained for now; migrating to
27
+ // `runtime.windows.main` is the documented next step. (The `persist:simulator`
28
+ // partition is a fixed session used by child WCVs, not main-window state.)
29
+ ownsWindows: true,
30
+ // Pre-ready: app name / CDP port / CSP / privileged scheme — must run before
31
+ // the framework awaits app.whenReady().
32
+ beforeReady: () => {
33
+ runDevtoolsBootstrap(config);
34
+ },
35
+ // Setup (post-whenReady): app lifecycle (window-all-closed → quit) + the
36
+ // full devtools assembly.
37
+ assemble: async () => {
38
+ registerAppLifecycle();
39
+ instance = await createDevtoolsRuntime(config);
40
+ },
41
+ // Dispose the devtools context during the framework's deterministic shutdown
42
+ // (app.on('will-quit') → shutdown() → runShutdownCleanup(), awaited once).
43
+ // Without this, the compile session (a child process, torn down by
44
+ // closeProject) and the IPC registry would leak on exit. The framework awaits
45
+ // this hook, so teardown is no longer a best-effort before-quit reach-around.
46
+ onShutdown: () => instance?.dispose(),
47
+ };
48
+ }
49
+ //# sourceMappingURL=devtools-backend.js.map
@@ -0,0 +1,39 @@
1
+ /**
2
+ * MiniappRuntime — the stable, host-facing contract surface (foundation.md §3
3
+ * "MiniappRuntime 契约" layer, P4).
4
+ *
5
+ * `WorkbenchContext` is the rich internal main-process state: runtime kernel +
6
+ * host config + trust/infra plumbing, all mixed. Downstream hosts (qdmp, a
7
+ * re-skin of devtools that depends ONLY on devtools) don't consume that whole
8
+ * grab-bag — they drive the miniapp KERNEL: the view lifecycle (including the
9
+ * host-controllable toolbar at `views.hostToolbar`), the cross-wc bridge, the
10
+ * workspace, the custom-API registry, async storage, the appdata tap, the
11
+ * connection layer, and the main→renderer notifier.
12
+ *
13
+ * This module NAMES that kernel as an explicit, documented contract so the
14
+ * surface a host depends on is compiler-enforced and versionable, instead of
15
+ * "whatever fields of WorkbenchContext you happen to reach for". Config inputs
16
+ * (appName / panels / apiNamespaces / branding / project templates) are the
17
+ * host's INPUT, not part of the runtime it consumes; trust/infra
18
+ * (senderPolicy / trustedWindowSenderIds / registry / toolbar action-table)
19
+ * stay internal.
20
+ *
21
+ * Derived via `Pick<WorkbenchContext, …>` so the field TYPES never drift from
22
+ * the real implementation — `MiniappRuntime` is a view onto `WorkbenchContext`,
23
+ * and the conformance assertion below fails to compile the moment the context
24
+ * stops satisfying the contract.
25
+ *
26
+ * The host-controllable toolbar WebContentsView hangs off `views.hostToolbar`
27
+ * (a ViewManager concern), so it's reachable through the contract WITHOUT a 9th
28
+ * top-level member — `runtime.views.hostToolbar.loadURL(...)`.
29
+ */
30
+ import type { WorkbenchContext } from '../services/workbench-context.js';
31
+ /** The stable miniapp-kernel surface a downstream host (qdmp) consumes. */
32
+ export type MiniappRuntime = Pick<WorkbenchContext, 'views' | 'bridge' | 'workspace' | 'simulatorApis' | 'storageApi' | 'appData' | 'connections' | 'notify'>;
33
+ /**
34
+ * Project a full `WorkbenchContext` down to its `MiniappRuntime` view. Hosts
35
+ * call this to get a value typed to exactly the contract — no wider access to
36
+ * the context's internals leaks through.
37
+ */
38
+ export declare function asMiniappRuntime(ctx: WorkbenchContext): MiniappRuntime;
39
+ //# sourceMappingURL=miniapp-runtime.d.ts.map
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Project a full `WorkbenchContext` down to its `MiniappRuntime` view. Hosts
3
+ * call this to get a value typed to exactly the contract — no wider access to
4
+ * the context's internals leaks through.
5
+ */
6
+ export function asMiniappRuntime(ctx) {
7
+ return ctx;
8
+ }
9
+ /**
10
+ * Compile-time conformance guard: if `WorkbenchContext` ever stops structurally
11
+ * satisfying `MiniappRuntime` (a kernel field renamed / its type narrowed),
12
+ * THIS line fails `tsc`, catching the contract break at build time. The runtime
13
+ * value is unused.
14
+ */
15
+ const _conformance = (ctx) => ctx;
16
+ void _conformance;
17
+ //# sourceMappingURL=miniapp-runtime.js.map
@@ -1,10 +1,35 @@
1
+ import type { WebContents } from 'electron';
1
2
  import type { WorkbenchContext } from '../workbench-context.js';
2
3
  import type { ElementRef } from './shared.js';
3
4
  export declare function getSimulator(ctx: WorkbenchContext): Electron.WebContents | null;
4
5
  export declare function evalInSim<T = unknown>(ctx: WorkbenchContext, expression: string): Promise<T>;
5
- /** Build JS that locates an element by selector+index inside the active page iframe. */
6
+ /**
7
+ * Native-host: the active page's DOM lives directly in the visible render-host
8
+ * <webview> guest (no iframe), so element/page automation must run in that
9
+ * WebContents' main world. Returns null on the default dimina-fe arch, where the
10
+ * page lives inside an iframe of the simulator guest and automation goes through
11
+ * `evalInSim` + `inIframe` instead.
12
+ */
13
+ export declare function getActivePageWc(ctx: WorkbenchContext): WebContents | null;
14
+ /**
15
+ * Wrap guest code so `_doc` is the page document. Under native-host the render
16
+ * guest IS the page document — no iframe lookup (cf. `inIframe`, which digs into
17
+ * the simulator guest's last iframe). Mirrors `inIframe`'s `_doc` contract so the
18
+ * same handler `body` strings work in both arches unchanged.
19
+ */
20
+ export declare function wrapGuest(code: string): string;
21
+ /**
22
+ * Run page-level automation code against the right document for the current arch:
23
+ * - native-host with a live active render guest → run in that guest's main
24
+ * world via `wrapGuest` (the guest IS the page document).
25
+ * - otherwise (default dimina-fe, or native-host with no active guest yet) →
26
+ * fall back to `evalInSim(inIframe(code))` (the existing simulator-iframe path).
27
+ * The `code` is the same body either arch expects — it reads `_doc`.
28
+ */
29
+ export declare function evalInActivePage<T = unknown>(ctx: WorkbenchContext, code: string): Promise<T>;
30
+ /** Build JS that locates an element by selector+index inside the active page document. */
6
31
  export declare function buildElAccess(ref: ElementRef, varName?: string): string;
7
- /** Run `body` inside the active page iframe with `varName` bound to the element at `ref`. */
32
+ /** Run `body` inside the active page document with `varName` bound to the element at `ref`. */
8
33
  export declare function evalInElement<T = unknown>(ctx: WorkbenchContext, ref: ElementRef, body: string, varName?: string): Promise<T>;
9
34
  /** Wrap code to run inside the active page iframe (last iframe in the stack). */
10
35
  export declare function inIframe(code: string): string;
@@ -10,13 +10,47 @@ export async function evalInSim(ctx, expression) {
10
10
  throw new Error('Simulator not connected');
11
11
  return sim.executeJavaScript(expression);
12
12
  }
13
- /** Build JS that locates an element by selector+index inside the active page iframe. */
13
+ /**
14
+ * Native-host: the active page's DOM lives directly in the visible render-host
15
+ * <webview> guest (no iframe), so element/page automation must run in that
16
+ * WebContents' main world. Returns null on the default dimina-fe arch, where the
17
+ * page lives inside an iframe of the simulator guest and automation goes through
18
+ * `evalInSim` + `inIframe` instead.
19
+ */
20
+ export function getActivePageWc(ctx) {
21
+ return ctx.bridge?.isNativeHost() ? ctx.bridge.getActiveRenderWc() : null;
22
+ }
23
+ /**
24
+ * Wrap guest code so `_doc` is the page document. Under native-host the render
25
+ * guest IS the page document — no iframe lookup (cf. `inIframe`, which digs into
26
+ * the simulator guest's last iframe). Mirrors `inIframe`'s `_doc` contract so the
27
+ * same handler `body` strings work in both arches unchanged.
28
+ */
29
+ export function wrapGuest(code) {
30
+ return `(() => { const _doc = document; return (function(){ ${code} })() })()`;
31
+ }
32
+ /**
33
+ * Run page-level automation code against the right document for the current arch:
34
+ * - native-host with a live active render guest → run in that guest's main
35
+ * world via `wrapGuest` (the guest IS the page document).
36
+ * - otherwise (default dimina-fe, or native-host with no active guest yet) →
37
+ * fall back to `evalInSim(inIframe(code))` (the existing simulator-iframe path).
38
+ * The `code` is the same body either arch expects — it reads `_doc`.
39
+ */
40
+ export async function evalInActivePage(ctx, code) {
41
+ const renderWc = getActivePageWc(ctx);
42
+ if (renderWc) {
43
+ return renderWc.executeJavaScript(wrapGuest(code));
44
+ }
45
+ return evalInSim(ctx, inIframe(code));
46
+ }
47
+ /** Build JS that locates an element by selector+index inside the active page document. */
14
48
  export function buildElAccess(ref, varName = 'el') {
15
49
  return `const ${varName} = _doc.querySelectorAll(${JSON.stringify(ref.selector)})[${ref.index}]`;
16
50
  }
17
- /** Run `body` inside the active page iframe with `varName` bound to the element at `ref`. */
51
+ /** Run `body` inside the active page document with `varName` bound to the element at `ref`. */
18
52
  export function evalInElement(ctx, ref, body, varName = 'el') {
19
- return evalInSim(ctx, inIframe(`${buildElAccess(ref, varName)}\n${body}`));
53
+ return evalInActivePage(ctx, `${buildElAccess(ref, varName)}\n${body}`);
20
54
  }
21
55
  /** Wrap code to run inside the active page iframe (last iframe in the stack). */
22
56
  export function inIframe(code) {