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

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 (189) 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 +249 -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 +6071 -1863
  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 +1333 -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 +29 -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 +39 -17
  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/miniapp-partition.d.ts +80 -0
  85. package/dist/main/services/views/miniapp-partition.js +138 -0
  86. package/dist/main/services/views/simulator-session-policy.d.ts +28 -0
  87. package/dist/main/services/views/simulator-session-policy.js +82 -0
  88. package/dist/main/services/views/view-manager.d.ts +125 -0
  89. package/dist/main/services/views/view-manager.js +852 -4
  90. package/dist/main/services/workbench-context.d.ts +67 -7
  91. package/dist/main/services/workbench-context.js +6 -1
  92. package/dist/main/services/workspace/workspace-service.js +7 -13
  93. package/dist/main/utils/ipc-registry.d.ts +1 -1
  94. package/dist/main/utils/ipc-registry.js +21 -4
  95. package/dist/main/utils/paths.d.ts +15 -0
  96. package/dist/main/utils/paths.js +19 -0
  97. package/dist/main/utils/sender-policy.d.ts +9 -3
  98. package/dist/main/utils/sender-policy.js +18 -4
  99. package/dist/main/utils/theme.d.ts +1 -1
  100. package/dist/main/utils/theme.js +1 -1
  101. package/dist/main/windows/main-window/create.d.ts +0 -6
  102. package/dist/main/windows/main-window/create.js +6 -80
  103. package/dist/main/windows/main-window/events.d.ts +1 -1
  104. package/dist/main/windows/main-window/events.js +1 -1
  105. package/dist/main/windows/service-host-window/create.d.ts +67 -0
  106. package/dist/main/windows/service-host-window/create.js +138 -0
  107. package/dist/native-host/common/common.js +368 -0
  108. package/dist/native-host/container/pageFrame.css +1 -0
  109. package/dist/native-host/render/render.js +9334 -0
  110. package/dist/native-host/service/service.js +6 -0
  111. package/dist/preload/index.d.ts +2 -0
  112. package/dist/preload/index.js +6 -0
  113. package/dist/preload/instrumentation/app-data.d.ts +18 -20
  114. package/dist/preload/instrumentation/app-data.js +23 -160
  115. package/dist/preload/instrumentation/wxml-extract.d.ts +1 -1
  116. package/dist/preload/instrumentation/wxml-extract.js +1 -1
  117. package/dist/preload/runtime/bridge.d.ts +3 -8
  118. package/dist/preload/runtime/bridge.js +2 -32
  119. package/dist/preload/runtime/custom-apis.js +20 -17
  120. package/dist/preload/runtime/host-toolbar-advertiser.d.ts +27 -0
  121. package/dist/preload/runtime/host-toolbar-advertiser.js +55 -0
  122. package/dist/preload/runtime/main-api-runner.d.ts +9 -0
  123. package/dist/preload/runtime/main-api-runner.js +85 -0
  124. package/dist/preload/runtime/native-host.d.ts +43 -0
  125. package/dist/preload/runtime/native-host.js +83 -0
  126. package/dist/preload/shared/expose.d.ts +10 -5
  127. package/dist/preload/shared/expose.js +30 -12
  128. package/dist/preload/shared/sid-registry.d.ts +11 -0
  129. package/dist/preload/shared/sid-registry.js +38 -0
  130. package/dist/preload/windows/host-toolbar.cjs +161 -0
  131. package/dist/preload/windows/host-toolbar.cjs.map +7 -0
  132. package/dist/preload/windows/host-toolbar.d.ts +2 -0
  133. package/dist/preload/windows/host-toolbar.js +12 -0
  134. package/dist/preload/windows/main.cjs +1935 -0
  135. package/dist/preload/windows/main.cjs.map +4 -4
  136. package/dist/preload/windows/simulator.cjs +925 -0
  137. package/dist/preload/windows/simulator.cjs.map +7 -0
  138. package/dist/preload/windows/simulator.js +244 -574
  139. package/dist/render-host/pageFrame.html +29 -0
  140. package/dist/render-host/preload.cjs +154 -0
  141. package/dist/render-host/render-inspect.js +295 -0
  142. package/dist/renderer/assets/index-CcJKzatF.js +50 -0
  143. package/dist/renderer/assets/{input-CCYS8Ave.js → input-QGx6FFX1.js} +2 -2
  144. package/dist/renderer/assets/ipc-transport-BT4QYQqu.css +1 -0
  145. package/dist/renderer/assets/{ipc-transport-Bn4KXvhu.js → ipc-transport-DvZvwK-Z.js} +2 -2
  146. package/dist/renderer/assets/{popover-CH4rwpdt.js → popover-BOH1If1J.js} +2 -2
  147. package/dist/renderer/assets/select-C7JQ8G5N.js +2 -0
  148. package/dist/renderer/assets/{settings-CMTB-t0x.js → settings-DpAbTJyF.js} +2 -2
  149. package/dist/renderer/assets/{settings-api-Csdngf9Z.js → settings-api-RD2IZF53.js} +2 -2
  150. package/dist/renderer/assets/{workbenchSettings-CODFCzOg.js → workbenchSettings-CNJX4Qna.js} +2 -2
  151. package/dist/renderer/entries/main/index.html +5 -5
  152. package/dist/renderer/entries/popover/index.html +5 -5
  153. package/dist/renderer/entries/settings/index.html +5 -5
  154. package/dist/renderer/entries/workbench-settings/index.html +4 -4
  155. package/dist/service-host/preload.cjs +254 -0
  156. package/dist/service-host/service.html +10 -0
  157. package/dist/service-host/sourcemap-rewrite.cjs +58 -0
  158. package/dist/service-host/sync-api-patch.js +20 -0
  159. package/dist/service-host/sync-impls/menu-button-geometry.js +8 -0
  160. package/dist/service-host/sync-impls/menu-button.js +16 -0
  161. package/dist/service-host/sync-impls/storage.js +50 -0
  162. package/dist/service-host/sync-impls/system-info.js +54 -0
  163. package/dist/shared/appdata-accumulator.d.ts +95 -0
  164. package/dist/shared/appdata-accumulator.js +213 -0
  165. package/dist/shared/bridge-channels.d.ts +378 -0
  166. package/dist/shared/bridge-channels.js +81 -0
  167. package/dist/shared/ipc-channels.d.ts +84 -1
  168. package/dist/shared/ipc-channels.js +90 -10
  169. package/dist/shared/ipc-schemas.d.ts +59 -2
  170. package/dist/shared/ipc-schemas.js +64 -3
  171. package/dist/shared/open-in-editor.d.ts +71 -0
  172. package/dist/shared/open-in-editor.js +138 -0
  173. package/dist/shared/simulator-api-metadata.d.ts +21 -0
  174. package/dist/shared/simulator-api-metadata.js +23 -0
  175. package/dist/shared/types.d.ts +2 -39
  176. package/dist/simulator/assets/device-shell-DsdcNEkt.css +1 -0
  177. package/dist/simulator/assets/device-shell-fH2cI-3q.js +2 -0
  178. package/dist/simulator/assets/jsx-runtime-P6ZegaOf.js +2 -0
  179. package/dist/simulator/assets/simulator-DHylZf9Z.js +10 -0
  180. package/dist/simulator/assets/simulator-mini-app-BDNu5n26.js +2 -0
  181. package/dist/simulator/device-shell/menu-button-geometry.js +8 -0
  182. package/dist/simulator/simulator.html +2 -112
  183. package/package.json +12 -12
  184. package/dist/main/utils/disposable.d.ts +0 -18
  185. package/dist/main/utils/disposable.js +0 -67
  186. package/dist/renderer/assets/index-BDMxXUfn.js +0 -50
  187. package/dist/renderer/assets/ipc-transport-Cu7tubyg.css +0 -1
  188. package/dist/renderer/assets/select-Ct4-sijm.js +0 -2
  189. package/dist/simulator/assets/simulator-B4e3c6_O.js +0 -9
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Customize the embedded Chrome DevTools front-end's panel tab bar.
3
+ *
4
+ * The right-panel DevTools (a WebContents rendering `devtools://`, attached to the
5
+ * service-host via `setDevToolsWebContents` + `openDevTools`) shows ALL its panels
6
+ * by default. For the mini-app workflow only Elements / Console / Network are
7
+ * meaningful in the default tab bar — but we do NOT want to delete the rest: they
8
+ * stay reachable on demand via the command menu (Cmd+Shift+P → "Show Sources" …).
9
+ *
10
+ * ── How (registry, not DOM) ─────────────────────────────────────────────────
11
+ * The modern ESM DevTools front-end does NOT expose `UI.ViewManager` on
12
+ * `globalThis`, so the tab bar can't be driven through the view manager. Panels
13
+ * register themselves via `registerViewExtension({id, location:'panel', persistence})`
14
+ * into a module-level registry; the official mutators are `registerViewExtension`,
15
+ * `getRegisteredViewExtensions` and `maybeRemoveViewExtension`. We:
16
+ * 1. `import('./ui/legacy/legacy.js')` to reach those functions (the real export
17
+ * path on Electron 41 / Chromium ~138, verified at runtime);
18
+ * 2. whitelist-patch `registerViewExtension` so any future non-kept panel comes
19
+ * in with `persistence:'transient'` (hidden from the default bar);
20
+ * 3. for the already-registered non-kept panels, `maybeRemoveViewExtension(id)`
21
+ * then re-register a copy with `persistence:'transient'`.
22
+ * Transient views are not shown in the default tab bar but stay in the command
23
+ * menu — and because this is DevTools' own panel path, there is NO `>>` overflow
24
+ * or `×` close-button residue (which a DOM `display:none` hack leaves behind).
25
+ *
26
+ * ── Locale infobar ──────────────────────────────────────────────────────────
27
+ * The "DevTools is now available in 中文" banner is suppressed via the official
28
+ * host preference `disable-locale-info-bar` (a GLOBAL setting that lives in host
29
+ * preferences, NOT page localStorage), set through `InspectorFrontendHost.setPreference`.
30
+ *
31
+ * ── Degradation ─────────────────────────────────────────────────────────────
32
+ * If the ESM module can't be resolved, a bounded DOM `display:none` fallback hides
33
+ * the non-kept tabs (by visible name) so the bar still looks right. Everything is
34
+ * wrapped in try/catch in the injected realm and silently no-ops on any failure.
35
+ */
36
+ /**
37
+ * Canonical DevTools panel view ids kept in the DEFAULT tab bar (stable front-end
38
+ * ids, unchanged for many Chromium releases): `elements`, `console`, `network`.
39
+ */
40
+ export declare const DEVTOOLS_KEPT_VIEW_IDS: readonly string[];
41
+ /**
42
+ * Build the `executeJavaScript` source injected into the DevTools front-end
43
+ * WebContents. The kept ids + display names are carried as JSON data literals
44
+ * (never interpolated as bare code), same discipline as the other injectors.
45
+ */
46
+ export declare function buildCustomizeTabsScript(keptIds?: readonly string[]): string;
47
+ //# sourceMappingURL=devtools-tabs.d.ts.map
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Customize the embedded Chrome DevTools front-end's panel tab bar.
3
+ *
4
+ * The right-panel DevTools (a WebContents rendering `devtools://`, attached to the
5
+ * service-host via `setDevToolsWebContents` + `openDevTools`) shows ALL its panels
6
+ * by default. For the mini-app workflow only Elements / Console / Network are
7
+ * meaningful in the default tab bar — but we do NOT want to delete the rest: they
8
+ * stay reachable on demand via the command menu (Cmd+Shift+P → "Show Sources" …).
9
+ *
10
+ * ── How (registry, not DOM) ─────────────────────────────────────────────────
11
+ * The modern ESM DevTools front-end does NOT expose `UI.ViewManager` on
12
+ * `globalThis`, so the tab bar can't be driven through the view manager. Panels
13
+ * register themselves via `registerViewExtension({id, location:'panel', persistence})`
14
+ * into a module-level registry; the official mutators are `registerViewExtension`,
15
+ * `getRegisteredViewExtensions` and `maybeRemoveViewExtension`. We:
16
+ * 1. `import('./ui/legacy/legacy.js')` to reach those functions (the real export
17
+ * path on Electron 41 / Chromium ~138, verified at runtime);
18
+ * 2. whitelist-patch `registerViewExtension` so any future non-kept panel comes
19
+ * in with `persistence:'transient'` (hidden from the default bar);
20
+ * 3. for the already-registered non-kept panels, `maybeRemoveViewExtension(id)`
21
+ * then re-register a copy with `persistence:'transient'`.
22
+ * Transient views are not shown in the default tab bar but stay in the command
23
+ * menu — and because this is DevTools' own panel path, there is NO `>>` overflow
24
+ * or `×` close-button residue (which a DOM `display:none` hack leaves behind).
25
+ *
26
+ * ── Locale infobar ──────────────────────────────────────────────────────────
27
+ * The "DevTools is now available in 中文" banner is suppressed via the official
28
+ * host preference `disable-locale-info-bar` (a GLOBAL setting that lives in host
29
+ * preferences, NOT page localStorage), set through `InspectorFrontendHost.setPreference`.
30
+ *
31
+ * ── Degradation ─────────────────────────────────────────────────────────────
32
+ * If the ESM module can't be resolved, a bounded DOM `display:none` fallback hides
33
+ * the non-kept tabs (by visible name) so the bar still looks right. Everything is
34
+ * wrapped in try/catch in the injected realm and silently no-ops on any failure.
35
+ */
36
+ /**
37
+ * Canonical DevTools panel view ids kept in the DEFAULT tab bar (stable front-end
38
+ * ids, unchanged for many Chromium releases): `elements`, `console`, `network`.
39
+ */
40
+ export const DEVTOOLS_KEPT_VIEW_IDS = ['elements', 'console', 'network'];
41
+ /**
42
+ * Build the `executeJavaScript` source injected into the DevTools front-end
43
+ * WebContents. The kept ids + display names are carried as JSON data literals
44
+ * (never interpolated as bare code), same discipline as the other injectors.
45
+ */
46
+ export function buildCustomizeTabsScript(keptIds = DEVTOOLS_KEPT_VIEW_IDS) {
47
+ // Kept panels are matched by view id (registry path) and by visible NAME (DOM
48
+ // fallback path); the DevTools UI may be EN or ZH, so include both.
49
+ const NAME_MAP = {
50
+ elements: ['Elements', '元素'], console: ['Console', '控制台'], network: ['Network', '网络'],
51
+ };
52
+ const keepNames = keptIds.flatMap((id) => NAME_MAP[id] ?? [id]);
53
+ const keepIdsJson = JSON.stringify(JSON.stringify([...keptIds]));
54
+ const keepNamesJson = JSON.stringify(JSON.stringify(keepNames));
55
+ return `(function(){try{
56
+ var KEEPID = new Set(JSON.parse(${keepIdsJson}));
57
+ var KEEPNAME = new Set(JSON.parse(${keepNamesJson}));
58
+ // (1) Locale infobar — official host-preference suppression (NOT localStorage).
59
+ try { var IFH=globalThis.InspectorFrontendHost; if(IFH&&typeof IFH.setPreference==='function'){ IFH.setPreference('disable-locale-info-bar','true'); } }catch(_){}
60
+ function deepCollect(sel,cap){ var out=[],seen=0,stack=[document]; while(stack.length&&seen<(cap||40000)){ var root=stack.pop(); try{var m=root.querySelectorAll?root.querySelectorAll(sel):[];for(var i=0;i<m.length;i++)out.push(m[i]);}catch(_){} try{var all=root.querySelectorAll?root.querySelectorAll('*'):[];for(var j=0;j<all.length;j++){seen++;if(all[j].shadowRoot)stack.push(all[j].shadowRoot);}}catch(_){} } return out; }
61
+ function txt(el){ return ((el&&el.textContent)||'').replace(/\\s+/g,' ').trim(); }
62
+ var PATHS=['./ui/legacy/legacy.js','./ui/legacy/ViewManager.js','devtools://devtools/bundled/ui/legacy/legacy.js'];
63
+ (async function(){
64
+ var VM=null,maybeRemove=null,origReg=null,reg=null,getReg=null;
65
+ for(var i=0;i<PATHS.length;i++){ try{ var m=await import(PATHS[i]); if(!m)continue; var v=m.ViewManager||m;
66
+ var mr=(v&&typeof v.maybeRemoveViewExtension==='function')?v.maybeRemoveViewExtension.bind(v):(typeof m.maybeRemoveViewExtension==='function'?m.maybeRemoveViewExtension:null);
67
+ if(mr){ VM=v;maybeRemove=mr;
68
+ origReg=(v&&typeof v.registerViewExtension==='function')?v.registerViewExtension:m.registerViewExtension; reg=origReg;
69
+ getReg=(v&&typeof v.getRegisteredViewExtensions==='function')?v.getRegisteredViewExtensions.bind(v):(typeof m.getRegisteredViewExtensions==='function'?m.getRegisteredViewExtensions:null);
70
+ break; } }catch(_){} }
71
+ if(maybeRemove){
72
+ // (2) future non-kept panels register as transient
73
+ try{ if(origReg&&VM){ VM.registerViewExtension=function(r){ try{ if(r&&String(r.location)==='panel'&&!KEEPID.has(r.id)){ r.persistence='transient'; } }catch(_){} return origReg.apply(this,arguments); }; reg=VM.registerViewExtension; } }catch(_){}
74
+ // (3) already-registered non-kept panels -> remove + re-register transient
75
+ var exts=[]; try{ if(getReg) exts=getReg()||[]; }catch(_){}
76
+ var handled=false;
77
+ for(var e=0;e<exts.length;e++){ try{ var ex=exts[e]; var eid=ex&&ex.id; if(!eid||KEEPID.has(eid)) continue; if(String(ex.location)!=='panel') continue;
78
+ maybeRemove(eid);
79
+ var nr={}; try{ nr=Object.assign({},ex); }catch(_){ for(var k in ex){ try{nr[k]=ex[k];}catch(__){} } }
80
+ nr.persistence='transient';
81
+ try{ reg(nr); }catch(_){ try{ origReg(nr); }catch(__){} }
82
+ handled=true;
83
+ }catch(_){} }
84
+ // fallback: registrations not enumerable -> at least clear the bar by id
85
+ if(!handled){ var FALL=['timeline','resources','heap-profiler','sources','security','lighthouse','chrome-recorder','coverage','linear-memory-inspector','sensors','rendering','animations','autofill-view','medias','issues-pane']; for(var fr=0;fr<FALL.length;fr++){ try{ if(!KEEPID.has(FALL[fr])) maybeRemove(FALL[fr]); }catch(_){} } }
86
+ } else { domFallback(); }
87
+ })();
88
+ // DOM fallback: only if the ESM module couldn't be resolved at all.
89
+ function domFallback(){ var cachedBar=null;
90
+ function findBar(){ if(cachedBar&&cachedBar.isConnected)return cachedBar; cachedBar=null; var tabs=deepCollect('[role="tab"]'); var a=null; for(var i=0;i<tabs.length;i++){if(KEEPNAME.has(txt(tabs[i]))){a=tabs[i];break;}} if(!a)return null; var p=a.parentElement; while(p){try{if(p.querySelectorAll('[role="tab"]').length>1){cachedBar=p;return p;}}catch(_){} p=p.parentElement;} cachedBar=a.parentElement; return cachedBar; }
91
+ function apply(){ try{ var bar=findBar(); if(bar){ var bts=bar.querySelectorAll('[role="tab"]'); for(var b=0;b<bts.length;b++){var bt=bts[b]; if(KEEPNAME.has(txt(bt)))continue; try{if(bt.style)bt.style.display='none';}catch(_){}} try{var more=bar.querySelector('[aria-label*="More tabs"],.tabbed-pane-header-tabs-drop-down-container'); if(more&&more.style)more.style.display='none';}catch(_){} } }catch(_){} }
92
+ var tr=0,t=setInterval(function(){tr++;try{apply();}catch(_){}if(tr>120)clearInterval(t);},60); try{apply();}catch(_){} }
93
+ }catch(_){}})()`;
94
+ }
95
+ //# sourceMappingURL=devtools-tabs.js.map
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Per-project session partition for the native-host miniapp runtime (P0 debt).
3
+ *
4
+ * Historically every project's miniapp webContents — the simulator content
5
+ * WebContentsView, its nested render-host `<webview>` guests, AND the
6
+ * service-host window — shared ONE hard-coded `persist:simulator` Electron
7
+ * session. Cookies / localStorage / cache / IndexedDB written by project A were
8
+ * visible to (and clobbered by) project B; two projects open at once cross-
9
+ * contaminate and "clear storage" on one nukes the other.
10
+ *
11
+ * The fix derives a STABLE per-project partition from the project identity (the
12
+ * miniapp `appId`, which flows in via the simulator URL `?appId=` and the spawn
13
+ * path's `appId`). Same project → same partition (storage survives a relaunch);
14
+ * different projects → different partitions (no cross-contamination). The shape
15
+ * mirrors the IDE state of the art (WeChat's static partition, ByteDance's
16
+ * `persist:miniapp-<id>` dynamic partition).
17
+ *
18
+ * The protocol handlers (`difile://`, `dmb-resource`) and webRequest policies
19
+ * (referer / CORS) that the simulator runtime needs were installed once on the
20
+ * single `persist:simulator` session. With per-project partitions those have to
21
+ * be (re)applied to EACH project session the first time it is used. The setup
22
+ * sites register a partition-agnostic configurator here; `configureMiniappSession`
23
+ * runs every registered configurator exactly once per partition.
24
+ *
25
+ * Partition CLEANUP (reclaiming on-disk `persist:` data) is intentionally NOT
26
+ * done here — leaving the data on disk is the whole point of a `persist:`
27
+ * partition (cache/storage survives a relaunch). That is a separate concern.
28
+ */
29
+ import type { Session } from 'electron';
30
+ /** The legacy single-session partition. Still used by the pre-warm pool (which
31
+ * is intentionally NOT isolation-aware — see `serviceHostSpec`) and as the
32
+ * fallback when a project key cannot be derived. */
33
+ export declare const SHARED_MINIAPP_PARTITION = "persist:simulator";
34
+ /**
35
+ * Derive a stable, filesystem-safe partition key from a project `appId`.
36
+ *
37
+ * `appId` is the project identity (e.g. a `wxapp…` id). We pass through the
38
+ * characters Electron is happy to put in a session partition / on-disk folder
39
+ * name (`[A-Za-z0-9_-]`) verbatim so the common case is human-legible, and fold
40
+ * anything else into a short deterministic hash suffix so two appIds that differ
41
+ * only in stripped characters never collide. The same `appId` always yields the
42
+ * same key (so storage survives a relaunch); different `appId`s yield different
43
+ * keys.
44
+ */
45
+ export declare function miniappPartitionKey(appId: string): string;
46
+ /**
47
+ * The Electron session partition for a project. Returns the SHARED partition
48
+ * when `appId` is empty/unknown (so the runtime still has a session to load on,
49
+ * matching the legacy behavior) and a `persist:miniapp-<key>` partition
50
+ * otherwise.
51
+ */
52
+ export declare function miniappPartition(appId: string | null | undefined): string;
53
+ type SessionConfigurator = (sess: Session, partition: string) => void;
54
+ /**
55
+ * Register a configurator that runs against every miniapp partition session.
56
+ * Already-configured partitions are (re)configured immediately so registration
57
+ * order does not matter. Returns a disposer that unregisters the configurator
58
+ * (it does not undo work already applied to live sessions).
59
+ */
60
+ export declare function registerMiniappSessionConfigurator(fn: SessionConfigurator): () => void;
61
+ /**
62
+ * Ensure a partition's session has every registered configurator applied. Safe
63
+ * to call repeatedly per partition (idempotent — each partition is configured
64
+ * once). Call this before loading project content on `partition`.
65
+ *
66
+ * Returns `null` when there is nothing to configure (no configurator registered)
67
+ * so the partition derivation stays independent of any live Electron session —
68
+ * the partition is a constructor-time fact, not a side effect of touching the
69
+ * session API. Setup sites register configurators at app boot; in unit tests
70
+ * that mock `electron` without a `session` export this short-circuits cleanly.
71
+ */
72
+ export declare function configureMiniappSession(partition: string): Session | null;
73
+ /**
74
+ * Test-only: drop the configurator + configured-partition bookkeeping so each
75
+ * test starts from a clean slate. (Module-level state otherwise leaks across
76
+ * unit tests that mock `electron`.)
77
+ */
78
+ export declare function __resetMiniappSessionConfigForTests(): void;
79
+ export {};
80
+ //# sourceMappingURL=miniapp-partition.d.ts.map
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Per-project session partition for the native-host miniapp runtime (P0 debt).
3
+ *
4
+ * Historically every project's miniapp webContents — the simulator content
5
+ * WebContentsView, its nested render-host `<webview>` guests, AND the
6
+ * service-host window — shared ONE hard-coded `persist:simulator` Electron
7
+ * session. Cookies / localStorage / cache / IndexedDB written by project A were
8
+ * visible to (and clobbered by) project B; two projects open at once cross-
9
+ * contaminate and "clear storage" on one nukes the other.
10
+ *
11
+ * The fix derives a STABLE per-project partition from the project identity (the
12
+ * miniapp `appId`, which flows in via the simulator URL `?appId=` and the spawn
13
+ * path's `appId`). Same project → same partition (storage survives a relaunch);
14
+ * different projects → different partitions (no cross-contamination). The shape
15
+ * mirrors the IDE state of the art (WeChat's static partition, ByteDance's
16
+ * `persist:miniapp-<id>` dynamic partition).
17
+ *
18
+ * The protocol handlers (`difile://`, `dmb-resource`) and webRequest policies
19
+ * (referer / CORS) that the simulator runtime needs were installed once on the
20
+ * single `persist:simulator` session. With per-project partitions those have to
21
+ * be (re)applied to EACH project session the first time it is used. The setup
22
+ * sites register a partition-agnostic configurator here; `configureMiniappSession`
23
+ * runs every registered configurator exactly once per partition.
24
+ *
25
+ * Partition CLEANUP (reclaiming on-disk `persist:` data) is intentionally NOT
26
+ * done here — leaving the data on disk is the whole point of a `persist:`
27
+ * partition (cache/storage survives a relaunch). That is a separate concern.
28
+ */
29
+ import * as electron from 'electron';
30
+ /** The legacy single-session partition. Still used by the pre-warm pool (which
31
+ * is intentionally NOT isolation-aware — see `serviceHostSpec`) and as the
32
+ * fallback when a project key cannot be derived. */
33
+ export const SHARED_MINIAPP_PARTITION = 'persist:simulator';
34
+ const PARTITION_PREFIX = 'persist:miniapp-';
35
+ /**
36
+ * Derive a stable, filesystem-safe partition key from a project `appId`.
37
+ *
38
+ * `appId` is the project identity (e.g. a `wxapp…` id). We pass through the
39
+ * characters Electron is happy to put in a session partition / on-disk folder
40
+ * name (`[A-Za-z0-9_-]`) verbatim so the common case is human-legible, and fold
41
+ * anything else into a short deterministic hash suffix so two appIds that differ
42
+ * only in stripped characters never collide. The same `appId` always yields the
43
+ * same key (so storage survives a relaunch); different `appId`s yield different
44
+ * keys.
45
+ */
46
+ export function miniappPartitionKey(appId) {
47
+ const safe = appId.replace(/[^A-Za-z0-9_-]/g, '');
48
+ // Folding may have dropped distinguishing characters; if the input was not
49
+ // already fully safe, append a deterministic hash of the RAW appId so two
50
+ // distinct appIds can never alias onto the same key.
51
+ if (safe === appId && safe.length > 0)
52
+ return safe;
53
+ const hash = djb2(appId).toString(36);
54
+ return safe.length > 0 ? `${safe}-${hash}` : hash;
55
+ }
56
+ /**
57
+ * The Electron session partition for a project. Returns the SHARED partition
58
+ * when `appId` is empty/unknown (so the runtime still has a session to load on,
59
+ * matching the legacy behavior) and a `persist:miniapp-<key>` partition
60
+ * otherwise.
61
+ */
62
+ export function miniappPartition(appId) {
63
+ if (!appId)
64
+ return SHARED_MINIAPP_PARTITION;
65
+ return `${PARTITION_PREFIX}${miniappPartitionKey(appId)}`;
66
+ }
67
+ /** Small, stable string hash (djb2). Not cryptographic — only needs to be
68
+ * deterministic and collision-resistant enough to disambiguate appIds. */
69
+ function djb2(input) {
70
+ let h = 5381;
71
+ for (let i = 0; i < input.length; i++) {
72
+ h = ((h << 5) + h + input.charCodeAt(i)) >>> 0;
73
+ }
74
+ return h;
75
+ }
76
+ const configurators = new Set();
77
+ const configuredPartitions = new Set();
78
+ /**
79
+ * Register a configurator that runs against every miniapp partition session.
80
+ * Already-configured partitions are (re)configured immediately so registration
81
+ * order does not matter. Returns a disposer that unregisters the configurator
82
+ * (it does not undo work already applied to live sessions).
83
+ */
84
+ export function registerMiniappSessionConfigurator(fn) {
85
+ configurators.add(fn);
86
+ for (const partition of configuredPartitions) {
87
+ try {
88
+ fn(electron.session.fromPartition(partition), partition);
89
+ }
90
+ catch (err) {
91
+ console.warn('[miniapp-partition] configurator failed for', partition, err);
92
+ }
93
+ }
94
+ return () => {
95
+ configurators.delete(fn);
96
+ };
97
+ }
98
+ /**
99
+ * Ensure a partition's session has every registered configurator applied. Safe
100
+ * to call repeatedly per partition (idempotent — each partition is configured
101
+ * once). Call this before loading project content on `partition`.
102
+ *
103
+ * Returns `null` when there is nothing to configure (no configurator registered)
104
+ * so the partition derivation stays independent of any live Electron session —
105
+ * the partition is a constructor-time fact, not a side effect of touching the
106
+ * session API. Setup sites register configurators at app boot; in unit tests
107
+ * that mock `electron` without a `session` export this short-circuits cleanly.
108
+ */
109
+ export function configureMiniappSession(partition) {
110
+ // Record that this partition should be configured even if no configurator is
111
+ // registered YET — a later `registerMiniappSessionConfigurator` back-fills it.
112
+ const alreadyConfigured = configuredPartitions.has(partition);
113
+ configuredPartitions.add(partition);
114
+ if (configurators.size === 0)
115
+ return null;
116
+ const sess = electron.session.fromPartition(partition);
117
+ if (alreadyConfigured)
118
+ return sess;
119
+ for (const fn of configurators) {
120
+ try {
121
+ fn(sess, partition);
122
+ }
123
+ catch (err) {
124
+ console.warn('[miniapp-partition] configurator failed for', partition, err);
125
+ }
126
+ }
127
+ return sess;
128
+ }
129
+ /**
130
+ * Test-only: drop the configurator + configured-partition bookkeeping so each
131
+ * test starts from a clean slate. (Module-level state otherwise leaks across
132
+ * unit tests that mock `electron`.)
133
+ */
134
+ export function __resetMiniappSessionConfigForTests() {
135
+ configurators.clear();
136
+ configuredPartitions.clear();
137
+ }
138
+ //# sourceMappingURL=miniapp-partition.js.map
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Referer + CORS webRequest policy for the simulator runtime's sessions.
3
+ *
4
+ * The native render/service hosts fetch the compiled `<appId>/…` resources
5
+ * cross-origin and need a WeChat-style page-frame `Referer`; this installs that
6
+ * policy on the shared fallback session AND on every per-project
7
+ * `persist:miniapp-<key>` partition (current + future) via the partition
8
+ * configurator registry, so isolated projects load resources identically.
9
+ *
10
+ * TEARDOWN: a `webRequest` listener is per-session and there is exactly one
11
+ * slot per (session, event) — re-installing replaces, never stacks. But the
12
+ * configurator registration itself leaks if discarded: re-creating the
13
+ * WorkbenchApp in the same process would register a second configurator that
14
+ * keeps firing for every future partition. So this returns a {@link Disposable}
15
+ * that unregisters the configurator AND clears the listeners off every session
16
+ * it touched. Wire it into the context registry like any other module.
17
+ */
18
+ import { type Disposable } from '@dimina-kit/electron-deck/main';
19
+ /**
20
+ * Install the simulator referer/CORS policy on the shared fallback session and
21
+ * register a configurator so every per-project partition session gets it too.
22
+ * Returns a disposable that unregisters the configurator and clears the policy
23
+ * off every session it installed on — call its teardown when the owning
24
+ * context is disposed so re-creating the app never leaks a duplicate
25
+ * configurator/listener.
26
+ */
27
+ export declare function setupSimulatorSessionPolicy(): Disposable;
28
+ //# sourceMappingURL=simulator-session-policy.d.ts.map
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Referer + CORS webRequest policy for the simulator runtime's sessions.
3
+ *
4
+ * The native render/service hosts fetch the compiled `<appId>/…` resources
5
+ * cross-origin and need a WeChat-style page-frame `Referer`; this installs that
6
+ * policy on the shared fallback session AND on every per-project
7
+ * `persist:miniapp-<key>` partition (current + future) via the partition
8
+ * configurator registry, so isolated projects load resources identically.
9
+ *
10
+ * TEARDOWN: a `webRequest` listener is per-session and there is exactly one
11
+ * slot per (session, event) — re-installing replaces, never stacks. But the
12
+ * configurator registration itself leaks if discarded: re-creating the
13
+ * WorkbenchApp in the same process would register a second configurator that
14
+ * keeps firing for every future partition. So this returns a {@link Disposable}
15
+ * that unregisters the configurator AND clears the listeners off every session
16
+ * it touched. Wire it into the context registry like any other module.
17
+ */
18
+ import { session } from 'electron';
19
+ import { toDisposable } from '@dimina-kit/electron-deck/main';
20
+ import { getSimulatorServicewechatReferer } from '../simulator/referer.js';
21
+ import { registerMiniappSessionConfigurator, SHARED_MINIAPP_PARTITION, } from './miniapp-partition.js';
22
+ /** Apply the simulator runtime's referer + CORS webRequest policy to one
23
+ * session. Each session installs its own listeners (a webRequest listener is
24
+ * per-session), so this runs once per partition. */
25
+ function applySimulatorWebRequestPolicy(simulatorSession) {
26
+ simulatorSession.webRequest.onBeforeSendHeaders((details, callback) => {
27
+ const forcedReferer = getSimulatorServicewechatReferer();
28
+ if (forcedReferer) {
29
+ details.requestHeaders['Referer'] = forcedReferer;
30
+ }
31
+ callback({ requestHeaders: details.requestHeaders });
32
+ });
33
+ simulatorSession.webRequest.onHeadersReceived((details, callback) => {
34
+ const headers = details.responseHeaders ?? {};
35
+ // CORS for the native render/service hosts to fetch compiled app resources
36
+ // cross-origin. (The COOP/COEP cross-origin-isolation headers were only for
37
+ // the removed default-path SharedArrayBuffer sync Worker — dropped.)
38
+ headers['access-control-allow-origin'] = ['*'];
39
+ headers['access-control-allow-headers'] = ['*'];
40
+ headers['access-control-allow-methods'] = ['*'];
41
+ callback({ responseHeaders: headers });
42
+ });
43
+ }
44
+ /** Remove the policy listeners from a session (passing `null` clears the slot). */
45
+ function clearSimulatorWebRequestPolicy(simulatorSession) {
46
+ try {
47
+ simulatorSession.webRequest.onBeforeSendHeaders(null);
48
+ simulatorSession.webRequest.onHeadersReceived(null);
49
+ }
50
+ catch {
51
+ // Session already gone (app shutdown) — nothing to clear.
52
+ }
53
+ }
54
+ /**
55
+ * Install the simulator referer/CORS policy on the shared fallback session and
56
+ * register a configurator so every per-project partition session gets it too.
57
+ * Returns a disposable that unregisters the configurator and clears the policy
58
+ * off every session it installed on — call its teardown when the owning
59
+ * context is disposed so re-creating the app never leaks a duplicate
60
+ * configurator/listener.
61
+ */
62
+ export function setupSimulatorSessionPolicy() {
63
+ const configured = new Set();
64
+ function install(sess) {
65
+ if (configured.has(sess))
66
+ return;
67
+ configured.add(sess);
68
+ applySimulatorWebRequestPolicy(sess);
69
+ }
70
+ // Shared fallback session (pre-warm pool + unknown-appId path).
71
+ install(session.fromPartition(SHARED_MINIAPP_PARTITION));
72
+ // Every per-project miniapp partition session (current + future) gets the
73
+ // same referer/CORS policy so isolated projects load resources identically.
74
+ const unregister = registerMiniappSessionConfigurator((sess) => install(sess));
75
+ return toDisposable(() => {
76
+ unregister();
77
+ for (const sess of configured)
78
+ clearSimulatorWebRequestPolicy(sess);
79
+ configured.clear();
80
+ });
81
+ }
82
+ //# sourceMappingURL=simulator-session-policy.js.map
@@ -1,4 +1,5 @@
1
1
  import type { WebContents } from 'electron';
2
+ import type { NativeDeviceInfo } from '../../../shared/ipc-channels.js';
2
3
  import { type WorkbenchContext } from '../workbench-context.js';
3
4
  /**
4
5
  * Context surface used by the ViewManager. We only need a small slice of the
@@ -7,8 +8,41 @@ import { type WorkbenchContext } from '../workbench-context.js';
7
8
  export interface ViewManagerContext {
8
9
  windows: WorkbenchContext['windows'];
9
10
  rendererDir: string;
11
+ /**
12
+ * Per-webContents connection registry (foundation.md §4). The native-host
13
+ * simulator WebContentsView is acquired here so the registry tracks that
14
+ * trusted webContents and tears its per-wc resources (the custom-api bridge
15
+ * `ipcMain.on`) down deterministically on destroy — see P1 DoD #3. Required:
16
+ * `createWorkbenchContext` always supplies it.
17
+ */
18
+ connections: WorkbenchContext['connections'];
19
+ /**
20
+ * Absolute path to the simulator preload bundle. Only consumed by the
21
+ * native-host simulator WebContentsView (`attachNativeSimulator`); the
22
+ * default `<webview>` path gets its preload from the session-registered
23
+ * frame preload instead. Optional so partial test contexts compile.
24
+ */
25
+ preloadPath?: string;
10
26
  panels: string[];
11
27
  notify: WorkbenchContext['notify'];
28
+ bridge?: WorkbenchContext['bridge'];
29
+ /**
30
+ * Native-host network forwarder. `attachNativeSimulator` hands it the freshly
31
+ * created simulator WebContentsView (`attachSimulator`) so it can attach the
32
+ * CDP debugger, and the DevTools front-end host wc (`setDevtoolsHost`) so it can
33
+ * inject that WCV's Network.* events into the native Network tab (service-host
34
+ * console line is the fallback). Optional so partial test contexts compile.
35
+ */
36
+ networkForward?: WorkbenchContext['networkForward'];
37
+ /**
38
+ * Per-context registry of host-registered simulator custom APIs. The
39
+ * native-host simulator is a top-level WebContentsView with no embedder
40
+ * renderer, so `attachNativeSimulator` dispatches the simulator-side
41
+ * `__diminaCustomApis` bridge straight to this registry (the default
42
+ * `<webview>` path proxies through the trusted main renderer instead).
43
+ * Optional so partial test contexts compile.
44
+ */
45
+ simulatorApis?: WorkbenchContext['simulatorApis'];
12
46
  /**
13
47
  * Header bar height in px, used to position overlay views below the header.
14
48
  * Optional here so partial test contexts compile; `createWorkbenchContext`
@@ -36,6 +70,19 @@ export interface ViewManager {
36
70
  * tab; otherwise the view is created but not added yet).
37
71
  */
38
72
  attachSimulator(simWcId: number, simWidth: number): void;
73
+ /**
74
+ * NATIVE-HOST ONLY. Create the simulator itself as a top-level
75
+ * WebContentsView (not a renderer `<webview>` guest) loading `simulatorUrl`,
76
+ * position it in the simulator panel region, and treat its webContents as
77
+ * THE simulator webContents (so `getSimulatorWebContents` resolves it and the
78
+ * spawn/SIMULATOR_EVENTS pipeline flows through it). This is required because
79
+ * Electron force-disables the `<webview>` tag inside a webview guest, so the
80
+ * default `<webview>`-in-`<webview>` topology can never host DeviceShell's
81
+ * per-page render-host `<webview>`s. A top-level WebContentsView's webContents
82
+ * is NOT a guest and CAN host them. Then wires the DevTools/console view on
83
+ * top of it via `attachSimulator`. No-op (logs) when `preloadPath` is unset.
84
+ */
85
+ attachNativeSimulator(simulatorUrl: string, simWidth: number): void;
39
86
  /**
40
87
  * Destroy and null out the simulator view (e.g. on simulator detach).
41
88
  * Also destroys the cached settings view and hides the popover —
@@ -75,6 +122,35 @@ export interface ViewManager {
75
122
  getSettingsWebContentsId(): number | null;
76
123
  /** Return the webContents ID of the popover overlay if alive, else null. */
77
124
  getPopoverWebContentsId(): number | null;
125
+ /**
126
+ * Return the webContents ID of the host-toolbar overlay if alive, else null.
127
+ * The host-toolbar WCV is the one overlay whose OWN renderer drives an IPC
128
+ * channel back to main (the reverse size-advertiser), so the sender policy
129
+ * must trust its id — see `createWorkbenchSenderPolicy`.
130
+ */
131
+ getHostToolbarWebContentsId(): number | null;
132
+ /**
133
+ * NATIVE-HOST ONLY. Position the simulator content WebContentsView over the
134
+ * renderer-measured simulator panel REGION rect (the flex:1 placeholder slot,
135
+ * CSS px from the main window content top-left, which maps 1:1 to overlay
136
+ * setBounds DIP) and apply the device zoom. The WCV fills the region as a
137
+ * plain rectangle; DeviceShell draws + scrolls the phone inside. No-op in the
138
+ * default `<webview>` path (`nativeSimulatorView` is null). See
139
+ * `computeNativeSimulatorViewParams`.
140
+ */
141
+ setNativeSimulatorViewBounds(params: {
142
+ x: number;
143
+ y: number;
144
+ width: number;
145
+ height: number;
146
+ zoom: number;
147
+ }): void;
148
+ /**
149
+ * NATIVE-HOST ONLY. Re-push the selected device's CSS `env(safe-area-inset-*)`
150
+ * override to every attached render-host guest (on device change). New guests
151
+ * pick it up automatically when they attach (`did-attach-webview`).
152
+ */
153
+ reapplySafeArea(device: NativeDeviceInfo | null): void;
78
154
  /** Update lastSimWidth; reposition simulator + settings if they are added. */
79
155
  resize(simWidth: number): void;
80
156
  /** Show or hide the simulator overlay based on visibility flag. */
@@ -91,6 +167,55 @@ export interface ViewManager {
91
167
  width: number;
92
168
  height: number;
93
169
  }): void;
170
+ /**
171
+ * Apply a renderer-measured rectangle to the host-controllable toolbar
172
+ * WebContentsView (the strip above the devtools header). Forward anchor,
173
+ * mirroring `setSimulatorDevtoolsBounds`. `{ width: 0, height: 0 }` is
174
+ * treated as "hide" — the view is removed from the contentView but its
175
+ * WebContents (and the host's loaded content) stays alive. Lazily creates
176
+ * the view on the first non-empty rect.
177
+ */
178
+ setHostToolbarBounds(bounds: {
179
+ x: number;
180
+ y: number;
181
+ width: number;
182
+ height: number;
183
+ }): void;
184
+ /**
185
+ * Reverse size-advertiser sink: the toolbar WCV's own renderer advertises
186
+ * its intrinsic content height (block-axis extent); we store it and push it
187
+ * to the main-window renderer so the placeholder div resizes (closing the
188
+ * dynamic-height loop).
189
+ */
190
+ setHostToolbarHeight(extent: number): void;
191
+ /**
192
+ * Host-facing control surface for the toolbar WebContentsView. The downstream
193
+ * host loads its own content into it (`loadURL` / `loadFile`) and fully drives
194
+ * it. Lazily creates the underlying view on the first load call.
195
+ */
196
+ readonly hostToolbar: HostToolbarControl;
197
+ }
198
+ /**
199
+ * The control object the downstream host uses to own the toolbar
200
+ * WebContentsView. Lazily backed by the view-manager's `hostToolbarView`.
201
+ */
202
+ export interface HostToolbarControl {
203
+ /** Load a URL into the toolbar view (lazy-creates the view). */
204
+ loadURL(url: string): Promise<void>;
205
+ /** Load a local file into the toolbar view (lazy-creates the view). */
206
+ loadFile(path: string): Promise<void>;
207
+ /** The toolbar view's live WebContents, or null if not yet created/destroyed. */
208
+ readonly webContents: WebContents | null;
209
+ /** Remove the toolbar view from the contentView and reset it (kept alive). */
210
+ hide(): void;
211
+ /**
212
+ * Override the preload used when the toolbar view is first created. The
213
+ * host-shell (`launch(config)`) passes the host-controlled
214
+ * `toolbar.preloadPath` here; the host owns the bridge (it calls
215
+ * `exposeWorkbenchBridge()` itself). Must be set before the first
216
+ * `loadURL`/`loadFile`; `null` restores the built-in size-advertiser preload.
217
+ */
218
+ setPreloadPath(path: string | null): void;
94
219
  }
95
220
  /**
96
221
  * Build a ViewManager bound to the given context. The returned object is the