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

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.
@@ -751,7 +751,7 @@ function registerProjectFsIpc(ctx) {
751
751
  }
752
752
 
753
753
  // src/main/app/app.ts
754
- import { app as app14, BrowserWindow as BrowserWindow7, nativeImage, session as session2 } from "electron";
754
+ import { app as app14, BrowserWindow as BrowserWindow7, nativeImage, session as session3 } from "electron";
755
755
  import fs11 from "fs";
756
756
  import path20 from "path";
757
757
 
@@ -808,28 +808,9 @@ function installThemeBackgroundSync() {
808
808
  }
809
809
 
810
810
  // src/main/windows/main-window/create.ts
811
- import { app as app3, BrowserWindow as BrowserWindow2, View, session } from "electron";
811
+ import { app as app3, BrowserWindow as BrowserWindow2, View } from "electron";
812
812
  import path5 from "path";
813
813
 
814
- // src/main/services/simulator/referer.ts
815
- var DEFAULT_VERSION = "develop";
816
- var cachedRefererUrl = null;
817
- function buildServicewechatPageFrameReferer(appId, version = DEFAULT_VERSION) {
818
- return `https://servicewechat.com/${appId}/${version}/page-frame.html`;
819
- }
820
- function setSimulatorServicewechatReferer(appId, version) {
821
- cachedRefererUrl = buildServicewechatPageFrameReferer(
822
- appId,
823
- version && version.length > 0 ? version : DEFAULT_VERSION
824
- );
825
- }
826
- function clearSimulatorServicewechatReferer() {
827
- cachedRefererUrl = null;
828
- }
829
- function getSimulatorServicewechatReferer() {
830
- return cachedRefererUrl;
831
- }
832
-
833
814
  // src/main/windows/navigation-hardening.ts
834
815
  import { shell } from "electron";
835
816
  import path4 from "path";
@@ -866,28 +847,7 @@ function applyNavigationHardening(wc, rendererDir2) {
866
847
  }
867
848
 
868
849
  // src/main/windows/main-window/create.ts
869
- var simulatorSessionConfigured = false;
870
- function configureSimulatorSession() {
871
- if (simulatorSessionConfigured) return;
872
- simulatorSessionConfigured = true;
873
- const simulatorSession = session.fromPartition("persist:simulator");
874
- simulatorSession.webRequest.onBeforeSendHeaders((details, callback) => {
875
- const forcedReferer = getSimulatorServicewechatReferer();
876
- if (forcedReferer) {
877
- details.requestHeaders["Referer"] = forcedReferer;
878
- }
879
- callback({ requestHeaders: details.requestHeaders });
880
- });
881
- simulatorSession.webRequest.onHeadersReceived((details, callback) => {
882
- const headers = details.responseHeaders ?? {};
883
- headers["access-control-allow-origin"] = ["*"];
884
- headers["access-control-allow-headers"] = ["*"];
885
- headers["access-control-allow-methods"] = ["*"];
886
- callback({ responseHeaders: headers });
887
- });
888
- }
889
850
  function createMainWindow(opts) {
890
- configureSimulatorSession();
891
851
  const mainWindow = new BrowserWindow2({
892
852
  width: opts.width ?? 1280,
893
853
  height: opts.height ?? 980,
@@ -1652,6 +1612,93 @@ function createSimulatorApiRegistry() {
1652
1612
  };
1653
1613
  }
1654
1614
 
1615
+ // src/main/services/views/miniapp-partition.ts
1616
+ import * as electron from "electron";
1617
+ var SHARED_MINIAPP_PARTITION = "persist:simulator";
1618
+ var PARTITION_PREFIX = "persist:miniapp-";
1619
+ function miniappPartitionKey(appId) {
1620
+ const safe = appId.replace(/[^A-Za-z0-9_-]/g, "");
1621
+ if (safe === appId && safe.length > 0) return safe;
1622
+ const hash = djb2(appId).toString(36);
1623
+ return safe.length > 0 ? `${safe}-${hash}` : hash;
1624
+ }
1625
+ function miniappPartition(appId) {
1626
+ if (!appId) return SHARED_MINIAPP_PARTITION;
1627
+ return `${PARTITION_PREFIX}${miniappPartitionKey(appId)}`;
1628
+ }
1629
+ function djb2(input) {
1630
+ let h = 5381;
1631
+ for (let i = 0; i < input.length; i++) {
1632
+ h = (h << 5) + h + input.charCodeAt(i) >>> 0;
1633
+ }
1634
+ return h;
1635
+ }
1636
+ var configurators = /* @__PURE__ */ new Set();
1637
+ var configuredPartitions = /* @__PURE__ */ new Set();
1638
+ function registerMiniappSessionConfigurator(fn) {
1639
+ configurators.add(fn);
1640
+ for (const partition of configuredPartitions) {
1641
+ try {
1642
+ fn(electron.session.fromPartition(partition), partition);
1643
+ } catch (err) {
1644
+ console.warn("[miniapp-partition] configurator failed for", partition, err);
1645
+ }
1646
+ }
1647
+ return () => {
1648
+ configurators.delete(fn);
1649
+ };
1650
+ }
1651
+ function configureMiniappSession(partition) {
1652
+ const alreadyConfigured = configuredPartitions.has(partition);
1653
+ configuredPartitions.add(partition);
1654
+ if (configurators.size === 0) return null;
1655
+ const sess = electron.session.fromPartition(partition);
1656
+ if (alreadyConfigured) return sess;
1657
+ for (const fn of configurators) {
1658
+ try {
1659
+ fn(sess, partition);
1660
+ } catch (err) {
1661
+ console.warn("[miniapp-partition] configurator failed for", partition, err);
1662
+ }
1663
+ }
1664
+ return sess;
1665
+ }
1666
+
1667
+ // src/shared/simulator-route.ts
1668
+ function decodePageSpec(value) {
1669
+ const qIdx = value.indexOf("?");
1670
+ if (qIdx < 0) return { pagePath: value, query: {} };
1671
+ const pagePath = value.slice(0, qIdx);
1672
+ const query = {};
1673
+ for (const pair of value.slice(qIdx + 1).split("&")) {
1674
+ if (!pair) continue;
1675
+ const eqIdx = pair.indexOf("=");
1676
+ const k = eqIdx >= 0 ? pair.slice(0, eqIdx) : pair;
1677
+ const v = eqIdx >= 0 ? pair.slice(eqIdx + 1) : "";
1678
+ if (k) query[decodeURIComponent(k)] = decodeURIComponent(v);
1679
+ }
1680
+ return { pagePath, query };
1681
+ }
1682
+ function parseLocationRoute(search) {
1683
+ const params = new URLSearchParams(search.startsWith("?") ? search.slice(1) : search);
1684
+ const appId = params.get("appId");
1685
+ const entryRaw = params.get("entry");
1686
+ if (!appId || !entryRaw) return null;
1687
+ const entry = decodePageSpec(entryRaw);
1688
+ const pageRaw = params.get("page");
1689
+ const current = pageRaw && pageRaw !== entryRaw ? decodePageSpec(pageRaw) : entry;
1690
+ return { appId, entry, current };
1691
+ }
1692
+ function parseRoute(url) {
1693
+ if (!url) return null;
1694
+ try {
1695
+ const u = new URL(url);
1696
+ return parseLocationRoute(u.search);
1697
+ } catch {
1698
+ return null;
1699
+ }
1700
+ }
1701
+
1655
1702
  // src/main/services/views/view-manager.ts
1656
1703
  function createViewManager(ctx) {
1657
1704
  const headerHeight = ctx.headerHeight ?? 40;
@@ -2164,6 +2211,9 @@ function createViewManager(ctx) {
2164
2211
  }
2165
2212
  nativeSimulatorView = null;
2166
2213
  }
2214
+ const route = parseRoute(simulatorUrl);
2215
+ const partition = miniappPartition(route?.appId);
2216
+ configureMiniappSession(partition);
2167
2217
  const view = new WebContentsView2({
2168
2218
  webPreferences: {
2169
2219
  nodeIntegration: false,
@@ -2171,7 +2221,7 @@ function createViewManager(ctx) {
2171
2221
  sandbox: false,
2172
2222
  webviewTag: true,
2173
2223
  preload: cjsSiblingPreloadPath(ctx.preloadPath),
2174
- partition: "persist:simulator"
2224
+ partition
2175
2225
  }
2176
2226
  });
2177
2227
  nativeSimulatorView = view;
@@ -2180,8 +2230,8 @@ function createViewManager(ctx) {
2180
2230
  attachNativeCustomApiBridge(simWc);
2181
2231
  simWc.on("will-attach-webview", (_event, webPreferences, params) => {
2182
2232
  ;
2183
- webPreferences.partition = "persist:simulator";
2184
- params.partition = "persist:simulator";
2233
+ webPreferences.partition = partition;
2234
+ params.partition = partition;
2185
2235
  webPreferences.contextIsolation = false;
2186
2236
  webPreferences.sandbox = false;
2187
2237
  });
@@ -2641,6 +2691,25 @@ var DEFAULT_COMPILE_CONFIG = {
2641
2691
  queryParams: []
2642
2692
  };
2643
2693
 
2694
+ // src/main/services/simulator/referer.ts
2695
+ var DEFAULT_VERSION = "develop";
2696
+ var cachedRefererUrl = null;
2697
+ function buildServicewechatPageFrameReferer(appId, version = DEFAULT_VERSION) {
2698
+ return `https://servicewechat.com/${appId}/${version}/page-frame.html`;
2699
+ }
2700
+ function setSimulatorServicewechatReferer(appId, version) {
2701
+ cachedRefererUrl = buildServicewechatPageFrameReferer(
2702
+ appId,
2703
+ version && version.length > 0 ? version : DEFAULT_VERSION
2704
+ );
2705
+ }
2706
+ function clearSimulatorServicewechatReferer() {
2707
+ cachedRefererUrl = null;
2708
+ }
2709
+ function getSimulatorServicewechatReferer() {
2710
+ return cachedRefererUrl;
2711
+ }
2712
+
2644
2713
  // src/main/services/workspace/workspace-service.ts
2645
2714
  function createWorkspaceService(ctx) {
2646
2715
  let currentSession = null;
@@ -2658,11 +2727,11 @@ function createWorkspaceService(ctx) {
2658
2727
  }
2659
2728
  async function disposeSession() {
2660
2729
  if (!currentSession) return;
2661
- const session3 = currentSession;
2730
+ const session4 = currentSession;
2662
2731
  currentSession = null;
2663
2732
  try {
2664
2733
  await Promise.race([
2665
- session3.close(),
2734
+ session4.close(),
2666
2735
  new Promise(
2667
2736
  (_, reject) => setTimeout(() => reject(new Error("session close timed out")), 5e3)
2668
2737
  )
@@ -2671,8 +2740,8 @@ function createWorkspaceService(ctx) {
2671
2740
  console.error("[workspace] session close failed:", err);
2672
2741
  }
2673
2742
  }
2674
- function applyRefererFromSession(session3) {
2675
- const appInfo = session3.appInfo;
2743
+ function applyRefererFromSession(session4) {
2744
+ const appInfo = session4.appInfo;
2676
2745
  if (appInfo && typeof appInfo.appId === "string" && appInfo.appId.length > 0) {
2677
2746
  setSimulatorServicewechatReferer(
2678
2747
  appInfo.appId,
@@ -2704,9 +2773,9 @@ function createWorkspaceService(ctx) {
2704
2773
  }
2705
2774
  sendStatus("compiling", "\u6B63\u5728\u7F16\u8BD1...");
2706
2775
  const { compile } = loadWorkbenchSettings();
2707
- let session3;
2776
+ let session4;
2708
2777
  try {
2709
- session3 = await ctx.adapter.openProject({
2778
+ session4 = await ctx.adapter.openProject({
2710
2779
  projectPath,
2711
2780
  sourcemap: true,
2712
2781
  watch: compile.watch,
@@ -2718,17 +2787,17 @@ function createWorkspaceService(ctx) {
2718
2787
  sendStatus("error", String(err));
2719
2788
  return { success: false, error: String(err) };
2720
2789
  }
2721
- currentSession = session3;
2790
+ currentSession = session4;
2722
2791
  currentProjectPath = projectPath;
2723
2792
  bestEffort("updateLastOpened", () => {
2724
2793
  if (provider.updateLastOpened) provider.updateLastOpened(projectPath);
2725
2794
  });
2726
2795
  bestEffort("sendStatus", () => sendStatus("ready", "\u7F16\u8BD1\u5B8C\u6210"));
2727
- bestEffort("applyReferer", () => applyRefererFromSession(session3));
2796
+ bestEffort("applyReferer", () => applyRefererFromSession(session4));
2728
2797
  return {
2729
2798
  success: true,
2730
- port: session3.port,
2731
- appInfo: session3.appInfo
2799
+ port: session4.port,
2800
+ appInfo: session4.appInfo
2732
2801
  };
2733
2802
  },
2734
2803
  async closeProject() {
@@ -3134,7 +3203,59 @@ var PanelSelectSchema = z2.tuple([z2.string().min(1).max(200)]);
3134
3203
  var ProjectCaptureThumbnailSchema = z2.tuple([AbsolutePath]);
3135
3204
  var ProjectGetThumbnailSchema = z2.tuple([AbsolutePath]);
3136
3205
 
3137
- // src/main/ipc/simulator.ts
3206
+ // src/shared/bridge-channels.ts
3207
+ var BRIDGE_CHANNELS = {
3208
+ SPAWN: "dmb:spawn",
3209
+ DISPOSE: "dmb:dispose",
3210
+ PAGE_OPEN: "dmb:page:open",
3211
+ PAGE_CLOSE: "dmb:page:close",
3212
+ PAGE_LIFECYCLE: "dmb:page:lifecycle",
3213
+ NAV_CALLBACK: "dmb:nav:callback",
3214
+ SERVICE_INVOKE: "dmb:service:invoke",
3215
+ SERVICE_PUBLISH: "dmb:service:publish",
3216
+ RENDER_INVOKE: "dmb:render:invoke",
3217
+ RENDER_PUBLISH: "dmb:render:publish",
3218
+ TO_SERVICE: "dmb:to-service",
3219
+ TO_RENDER: "dmb:to-render",
3220
+ SIMULATOR_API: "dmb:simulator-api",
3221
+ /** simulator → main: ack of an API_CALL request (carries success/fail args). */
3222
+ API_RESPONSE: "dmb:api:response",
3223
+ /**
3224
+ * simulator webview preload → main (sendSync): "is native-host mode on?".
3225
+ * The guest preload can't read the launch `process.env`, so it asks main
3226
+ * (which can) at install time. Reply is `e.returnValue = boolean`.
3227
+ */
3228
+ NATIVE_HOST_ENABLED: "dmb:native-host-enabled",
3229
+ /**
3230
+ * simulator (DeviceShell) → main: the visible top-of-stack page bridgeId.
3231
+ * Main has no z-order concept — the active page lives only in DeviceShell's
3232
+ * ShellState — so devtools panels / automation that must target "the current
3233
+ * page's render webContents" resolve it through this signal. Fire-and-forget.
3234
+ */
3235
+ ACTIVE_PAGE: "dmb:active-page",
3236
+ /**
3237
+ * simulator (DeviceShell) → main: the FULL ordered page stack (bottom→top)
3238
+ * whenever it changes. Main has no stack of its own (it only learns the
3239
+ * active bridgeId via ACTIVE_PAGE), so automation's `App.getPageStack` needs
3240
+ * this to report multi-page stacks. Fire-and-forget.
3241
+ */
3242
+ PAGE_STACK: "dmb:page-stack"
3243
+ };
3244
+ var SIMULATOR_EVENTS = {
3245
+ DOM_READY: "simulator:dom-ready",
3246
+ NAV_BAR: "simulator:navigation-bar",
3247
+ NAV_ACTION: "simulator:nav-action",
3248
+ TAB_ACTION: "simulator:tab-action",
3249
+ /** main → simulator: invoke a wx.* API on the simulator-resident MiniApp. */
3250
+ API_CALL: "simulator:api-call",
3251
+ /**
3252
+ * main → simulator: the renderer toolbar picked a different device. Carries a
3253
+ * NativeDeviceInfo; DeviceShell resizes the bezel + re-renders status bar /
3254
+ * notch. The race-free INITIAL device rides NativeHostConfig.device (read
3255
+ * synchronously at preload bridge-install); this event covers live changes.
3256
+ */
3257
+ DEVICE_CHANGE: "simulator:device-change"
3258
+ };
3138
3259
  function deviceInfoToHostEnv(d) {
3139
3260
  return {
3140
3261
  brand: d.brand,
@@ -3149,6 +3270,8 @@ function deviceInfoToHostEnv(d) {
3149
3270
  statusBarHeight: d.statusBarHeight
3150
3271
  };
3151
3272
  }
3273
+
3274
+ // src/main/ipc/simulator.ts
3152
3275
  function registerSimulatorIpc(ctx) {
3153
3276
  return new IpcRegistry(ctx.senderPolicy).handle(SimulatorChannel.AttachNative, (_, ...args) => {
3154
3277
  const [simulatorUrl, simWidth] = validate(SimulatorChannel.AttachNative, SimulatorAttachNativeSchema, args);
@@ -3569,60 +3692,6 @@ import { app as app11, ipcMain as ipcMain3, protocol as protocol2, session as el
3569
3692
  import path15 from "node:path";
3570
3693
  import { pathToFileURL as pathToFileURL3 } from "node:url";
3571
3694
 
3572
- // src/shared/bridge-channels.ts
3573
- var BRIDGE_CHANNELS = {
3574
- SPAWN: "dmb:spawn",
3575
- DISPOSE: "dmb:dispose",
3576
- PAGE_OPEN: "dmb:page:open",
3577
- PAGE_CLOSE: "dmb:page:close",
3578
- PAGE_LIFECYCLE: "dmb:page:lifecycle",
3579
- NAV_CALLBACK: "dmb:nav:callback",
3580
- SERVICE_INVOKE: "dmb:service:invoke",
3581
- SERVICE_PUBLISH: "dmb:service:publish",
3582
- RENDER_INVOKE: "dmb:render:invoke",
3583
- RENDER_PUBLISH: "dmb:render:publish",
3584
- TO_SERVICE: "dmb:to-service",
3585
- TO_RENDER: "dmb:to-render",
3586
- SIMULATOR_API: "dmb:simulator-api",
3587
- /** simulator → main: ack of an API_CALL request (carries success/fail args). */
3588
- API_RESPONSE: "dmb:api:response",
3589
- /**
3590
- * simulator webview preload → main (sendSync): "is native-host mode on?".
3591
- * The guest preload can't read the launch `process.env`, so it asks main
3592
- * (which can) at install time. Reply is `e.returnValue = boolean`.
3593
- */
3594
- NATIVE_HOST_ENABLED: "dmb:native-host-enabled",
3595
- /**
3596
- * simulator (DeviceShell) → main: the visible top-of-stack page bridgeId.
3597
- * Main has no z-order concept — the active page lives only in DeviceShell's
3598
- * ShellState — so devtools panels / automation that must target "the current
3599
- * page's render webContents" resolve it through this signal. Fire-and-forget.
3600
- */
3601
- ACTIVE_PAGE: "dmb:active-page",
3602
- /**
3603
- * simulator (DeviceShell) → main: the FULL ordered page stack (bottom→top)
3604
- * whenever it changes. Main has no stack of its own (it only learns the
3605
- * active bridgeId via ACTIVE_PAGE), so automation's `App.getPageStack` needs
3606
- * this to report multi-page stacks. Fire-and-forget.
3607
- */
3608
- PAGE_STACK: "dmb:page-stack"
3609
- };
3610
- var SIMULATOR_EVENTS = {
3611
- DOM_READY: "simulator:dom-ready",
3612
- NAV_BAR: "simulator:navigation-bar",
3613
- NAV_ACTION: "simulator:nav-action",
3614
- TAB_ACTION: "simulator:tab-action",
3615
- /** main → simulator: invoke a wx.* API on the simulator-resident MiniApp. */
3616
- API_CALL: "simulator:api-call",
3617
- /**
3618
- * main → simulator: the renderer toolbar picked a different device. Carries a
3619
- * NativeDeviceInfo; DeviceShell resizes the bezel + re-renders status bar /
3620
- * notch. The race-free INITIAL device rides NativeHostConfig.device (read
3621
- * synchronously at preload bridge-install); this event covers live changes.
3622
- */
3623
- DEVICE_CHANGE: "simulator:device-change"
3624
- };
3625
-
3626
3695
  // src/shared/simulator-api-metadata.ts
3627
3696
  var PERSISTENT_SIMULATOR_APIS = /* @__PURE__ */ new Set(["audioListen"]);
3628
3697
  function isPersistentSimulatorApi(name) {
@@ -3730,17 +3799,19 @@ function setCorsHeaders(res) {
3730
3799
  import { app as app9, BrowserWindow as BrowserWindow3 } from "electron";
3731
3800
  import path14 from "node:path";
3732
3801
  import { pathToFileURL as pathToFileURL2 } from "node:url";
3733
- var SERVICE_HOST_PARTITION = "persist:simulator";
3802
+ var SERVICE_HOST_PARTITION = SHARED_MINIAPP_PARTITION;
3734
3803
  var serviceHostPreloadPath = path14.join(devtoolsPackageRoot, "dist/service-host/preload.cjs");
3735
3804
  var serviceHostHtmlPath = path14.join(devtoolsPackageRoot, "dist/service-host/service.html");
3736
3805
  function constructServiceHostWindow(opts = {}) {
3806
+ const partition = opts.partition ?? SERVICE_HOST_PARTITION;
3807
+ configureMiniappSession(partition);
3737
3808
  return new BrowserWindow3({
3738
3809
  width: 980,
3739
3810
  height: 720,
3740
3811
  show: false,
3741
3812
  title: opts.appId ? `Dimina Service Host: ${opts.appId}` : "Dimina Service Host",
3742
3813
  webPreferences: {
3743
- partition: opts.partition ?? SERVICE_HOST_PARTITION,
3814
+ partition,
3744
3815
  nodeIntegration: false,
3745
3816
  contextIsolation: false,
3746
3817
  sandbox: false,
@@ -3784,9 +3855,12 @@ function navigateServiceHost(win, url) {
3784
3855
  }
3785
3856
  return loaded;
3786
3857
  }
3787
- function serviceHostSpec() {
3858
+ function serviceHostSpec(appId) {
3788
3859
  return {
3789
- partition: SERVICE_HOST_PARTITION,
3860
+ // Per-project partition when an appId is known (so this project's service
3861
+ // host shares storage ONLY with its own render side); the shared partition
3862
+ // for the pre-warm pool's default spec (no appId — see KNOWN BLOCKER below).
3863
+ partition: appId ? miniappPartition(appId) : SERVICE_HOST_PARTITION,
3790
3864
  preloadPath: serviceHostPreloadPath,
3791
3865
  size: { width: 980, height: 720 },
3792
3866
  contextIsolation: false,
@@ -3796,7 +3870,7 @@ function serviceHostSpec() {
3796
3870
  };
3797
3871
  }
3798
3872
  function createServiceHostWindow(opts) {
3799
- const win = constructServiceHostWindow({ appId: opts.appId });
3873
+ const win = constructServiceHostWindow({ appId: opts.appId, partition: miniappPartition(opts.appId) });
3800
3874
  void navigateServiceHost(win, buildServiceHostSpawnUrl(opts));
3801
3875
  return win;
3802
3876
  }
@@ -4973,7 +5047,11 @@ async function handleSpawn(state, ctx, event, opts) {
4973
5047
  resourceServer = await startDiminaResourceServer(path15.resolve(pkgRoot, root));
4974
5048
  resourceBaseUrl = resourceServer.baseUrl;
4975
5049
  }
4976
- const hostEnv = makeHostEnv(opts.hostEnvSnapshot);
5050
+ const selectedDevice = ctx.bridge?.getDevice?.() ?? null;
5051
+ const hostEnv = makeHostEnv({
5052
+ ...opts.hostEnvSnapshot,
5053
+ ...selectedDevice ? deviceInfoToHostEnv(selectedDevice) : {}
5054
+ });
4977
5055
  const appConfig = await loadAppConfig(
4978
5056
  resourceServer ? resourceServer.baseUrl : `${resourceBaseUrl}${appId}/${root}/`
4979
5057
  );
@@ -5639,7 +5717,7 @@ function installResourceProtocolHandlers(ctx, state) {
5639
5717
  const target = new URL(url.pathname.replace(/^\/+/, "") + url.search, ap.resourceBaseUrl);
5640
5718
  return fetch(target);
5641
5719
  };
5642
- const simulatorSession = electronSession.fromPartition("persist:simulator");
5720
+ const simulatorSession = electronSession.fromPartition(SHARED_MINIAPP_PARTITION);
5643
5721
  try {
5644
5722
  protocol2.unhandle("dmb-resource");
5645
5723
  } catch {
@@ -5650,7 +5728,18 @@ function installResourceProtocolHandlers(ctx, state) {
5650
5728
  }
5651
5729
  protocol2.handle("dmb-resource", handler);
5652
5730
  simulatorSession.protocol.handle("dmb-resource", handler);
5731
+ const perProjectSessions = /* @__PURE__ */ new Set();
5732
+ const unregisterConfigurator = registerMiniappSessionConfigurator((sess) => {
5733
+ if (perProjectSessions.has(sess)) return;
5734
+ perProjectSessions.add(sess);
5735
+ try {
5736
+ sess.protocol.unhandle("dmb-resource");
5737
+ } catch {
5738
+ }
5739
+ sess.protocol.handle("dmb-resource", handler);
5740
+ });
5653
5741
  ctx.registry.add(() => {
5742
+ unregisterConfigurator();
5654
5743
  try {
5655
5744
  protocol2.unhandle("dmb-resource");
5656
5745
  } catch {
@@ -5659,6 +5748,12 @@ function installResourceProtocolHandlers(ctx, state) {
5659
5748
  simulatorSession.protocol.unhandle("dmb-resource");
5660
5749
  } catch {
5661
5750
  }
5751
+ for (const sess of perProjectSessions) {
5752
+ try {
5753
+ sess.protocol.unhandle("dmb-resource");
5754
+ } catch {
5755
+ }
5756
+ }
5662
5757
  });
5663
5758
  }
5664
5759
  function makeHostEnv(snapshot) {
@@ -5787,32 +5882,6 @@ toolHandlers["Tool.close"] = async (ctx) => {
5787
5882
  return {};
5788
5883
  };
5789
5884
 
5790
- // src/shared/simulator-route.ts
5791
- function decodePageSpec(value) {
5792
- const qIdx = value.indexOf("?");
5793
- if (qIdx < 0) return { pagePath: value, query: {} };
5794
- const pagePath = value.slice(0, qIdx);
5795
- const query = {};
5796
- for (const pair of value.slice(qIdx + 1).split("&")) {
5797
- if (!pair) continue;
5798
- const eqIdx = pair.indexOf("=");
5799
- const k = eqIdx >= 0 ? pair.slice(0, eqIdx) : pair;
5800
- const v = eqIdx >= 0 ? pair.slice(eqIdx + 1) : "";
5801
- if (k) query[decodeURIComponent(k)] = decodeURIComponent(v);
5802
- }
5803
- return { pagePath, query };
5804
- }
5805
- function parseLocationRoute(search) {
5806
- const params = new URLSearchParams(search.startsWith("?") ? search.slice(1) : search);
5807
- const appId = params.get("appId");
5808
- const entryRaw = params.get("entry");
5809
- if (!appId || !entryRaw) return null;
5810
- const entry = decodePageSpec(entryRaw);
5811
- const pageRaw = params.get("page");
5812
- const current = pageRaw && pageRaw !== entryRaw ? decodePageSpec(pageRaw) : entry;
5813
- return { appId, entry, current };
5814
- }
5815
-
5816
5885
  // src/main/services/automation/wait-active-page.ts
5817
5886
  function waitForActivePage(bridge, opts) {
5818
5887
  const { since, timeoutMs, match, onTimeout } = opts;
@@ -8352,7 +8421,8 @@ function setupSimulatorTempFiles(simSession) {
8352
8421
  pendingWaiters.clear();
8353
8422
  for (const list of lists) for (const fn of list) fn();
8354
8423
  }
8355
- const simulatorOnlyPolicy = (sender) => !sender.isDestroyed() && sender.session === simSession;
8424
+ const trustedSessions = /* @__PURE__ */ new Set([simSession]);
8425
+ const simulatorOnlyPolicy = (sender) => !sender.isDestroyed() && trustedSessions.has(sender.session);
8356
8426
  const registry = new IpcRegistry(simulatorOnlyPolicy);
8357
8427
  registry.on("simulator:temp-file:write", (_event, payload) => {
8358
8428
  if (disposed) return;
@@ -8370,11 +8440,7 @@ function setupSimulatorTempFiles(simSession) {
8370
8440
  if (disposed) return;
8371
8441
  revokeAllTempFiles(store);
8372
8442
  });
8373
- try {
8374
- simSession.protocol.unhandle("difile");
8375
- } catch {
8376
- }
8377
- simSession.protocol.handle("difile", async (req) => {
8443
+ const difileHandler = async (req) => {
8378
8444
  const url = req.url;
8379
8445
  const headers = {};
8380
8446
  try {
@@ -8407,7 +8473,20 @@ function setupSimulatorTempFiles(simSession) {
8407
8473
  res = await handleDifileRequest(ctx, { url, headers });
8408
8474
  }
8409
8475
  return res;
8410
- });
8476
+ };
8477
+ const installedSessions = /* @__PURE__ */ new Set();
8478
+ function installOnSession(sess) {
8479
+ trustedSessions.add(sess);
8480
+ if (installedSessions.has(sess)) return;
8481
+ installedSessions.add(sess);
8482
+ try {
8483
+ sess.protocol.unhandle("difile");
8484
+ } catch {
8485
+ }
8486
+ sess.protocol.handle("difile", difileHandler);
8487
+ }
8488
+ installOnSession(simSession);
8489
+ const unregisterConfigurator = registerMiniappSessionConfigurator((sess) => installOnSession(sess));
8411
8490
  registry.handle(
8412
8491
  "simulator:fs:read",
8413
8492
  (_event, payload) => handleFsRead(payload)
@@ -8434,16 +8513,61 @@ function setupSimulatorTempFiles(simSession) {
8434
8513
  );
8435
8514
  return toDisposable6(async () => {
8436
8515
  disposed = true;
8516
+ unregisterConfigurator();
8437
8517
  drainAllWaiters();
8438
8518
  store.clear();
8439
- try {
8440
- simSession.protocol.unhandle("difile");
8441
- } catch {
8519
+ for (const sess of installedSessions) {
8520
+ try {
8521
+ sess.protocol.unhandle("difile");
8522
+ } catch {
8523
+ }
8442
8524
  }
8443
8525
  await registry.dispose();
8444
8526
  });
8445
8527
  }
8446
8528
 
8529
+ // src/main/services/views/simulator-session-policy.ts
8530
+ import { session as session2 } from "electron";
8531
+ import { toDisposable as toDisposable7 } from "@dimina-kit/electron-deck/main";
8532
+ function applySimulatorWebRequestPolicy(simulatorSession) {
8533
+ simulatorSession.webRequest.onBeforeSendHeaders((details, callback) => {
8534
+ const forcedReferer = getSimulatorServicewechatReferer();
8535
+ if (forcedReferer) {
8536
+ details.requestHeaders["Referer"] = forcedReferer;
8537
+ }
8538
+ callback({ requestHeaders: details.requestHeaders });
8539
+ });
8540
+ simulatorSession.webRequest.onHeadersReceived((details, callback) => {
8541
+ const headers = details.responseHeaders ?? {};
8542
+ headers["access-control-allow-origin"] = ["*"];
8543
+ headers["access-control-allow-headers"] = ["*"];
8544
+ headers["access-control-allow-methods"] = ["*"];
8545
+ callback({ responseHeaders: headers });
8546
+ });
8547
+ }
8548
+ function clearSimulatorWebRequestPolicy(simulatorSession) {
8549
+ try {
8550
+ simulatorSession.webRequest.onBeforeSendHeaders(null);
8551
+ simulatorSession.webRequest.onHeadersReceived(null);
8552
+ } catch {
8553
+ }
8554
+ }
8555
+ function setupSimulatorSessionPolicy() {
8556
+ const configured = /* @__PURE__ */ new Set();
8557
+ function install(sess) {
8558
+ if (configured.has(sess)) return;
8559
+ configured.add(sess);
8560
+ applySimulatorWebRequestPolicy(sess);
8561
+ }
8562
+ install(session2.fromPartition(SHARED_MINIAPP_PARTITION));
8563
+ const unregister = registerMiniappSessionConfigurator((sess) => install(sess));
8564
+ return toDisposable7(() => {
8565
+ unregister();
8566
+ for (const sess of configured) clearSimulatorWebRequestPolicy(sess);
8567
+ configured.clear();
8568
+ });
8569
+ }
8570
+
8447
8571
  // src/main/services/update/update-manager.ts
8448
8572
  import { app as app12, shell as shell3 } from "electron";
8449
8573
  var UpdateManager = class {
@@ -8546,7 +8670,7 @@ var UpdateManager = class {
8546
8670
  import { app as app13 } from "electron";
8547
8671
 
8548
8672
  // src/main/app/app.ts
8549
- import { toDisposable as toDisposable7 } from "@dimina-kit/electron-deck/main";
8673
+ import { toDisposable as toDisposable8 } from "@dimina-kit/electron-deck/main";
8550
8674
  var DEFAULT_MODULES = {
8551
8675
  projects: true,
8552
8676
  session: true,
@@ -8580,7 +8704,7 @@ function registerTrustedWindow(context, win) {
8580
8704
  else counts.set(senderId, count - 1);
8581
8705
  }
8582
8706
  win.once("closed", onClosed);
8583
- return toDisposable7(remove);
8707
+ return toDisposable8(remove);
8584
8708
  }
8585
8709
  function parseAutoArgs() {
8586
8710
  const argv = process.argv;
@@ -8710,7 +8834,7 @@ function wireAppWindowEvents(config, instance) {
8710
8834
  }
8711
8835
  function enableDevRendererAutoReload(rendererDir2) {
8712
8836
  if (app14.isPackaged) {
8713
- return toDisposable7(() => {
8837
+ return toDisposable8(() => {
8714
8838
  });
8715
8839
  }
8716
8840
  let reloadTimer = null;
@@ -8722,7 +8846,7 @@ function enableDevRendererAutoReload(rendererDir2) {
8722
8846
  }
8723
8847
  }, 300);
8724
8848
  });
8725
- return toDisposable7(() => {
8849
+ return toDisposable8(() => {
8726
8850
  if (reloadTimer) {
8727
8851
  clearTimeout(reloadTimer);
8728
8852
  reloadTimer = null;
@@ -8748,9 +8872,10 @@ async function createDevtoolsRuntime(config = {}) {
8748
8872
  context.connections.acquire(mainWindow.webContents);
8749
8873
  context.registry.add(registerAppIpc(context));
8750
8874
  context.registry.add(registerProjectFsIpc(context));
8875
+ context.registry.add(setupSimulatorSessionPolicy());
8751
8876
  context.registry.add(installThemeBackgroundSync());
8752
8877
  registerBuiltinModules(config, context);
8753
- const simSession = session2.fromPartition("persist:simulator");
8878
+ const simSession = session3.fromPartition(SHARED_MINIAPP_PARTITION);
8754
8879
  context.registry.add(setupSimulatorTempFiles(simSession));
8755
8880
  installMenu(config, mainWindow, context);
8756
8881
  const hostIpc = new IpcRegistry(context.senderPolicy);
@@ -8763,7 +8888,7 @@ async function createDevtoolsRuntime(config = {}) {
8763
8888
  // wrapper splices the registry entry out AND drives the underlying
8764
8889
  // teardown, so a single dispose leaves no dead entry behind.
8765
8890
  registerTrustedWindow: (win) => context.registry.add(registerTrustedWindow(context, win)),
8766
- registerSimulatorApi: (name, handler) => context.registry.add(toDisposable7(context.simulatorApis.register(name, handler))),
8891
+ registerSimulatorApi: (name, handler) => context.registry.add(toDisposable8(context.simulatorApis.register(name, handler))),
8767
8892
  toolbar: {
8768
8893
  set: (actions) => {
8769
8894
  context.toolbar.set(actions);
@@ -8790,8 +8915,8 @@ async function createDevtoolsRuntime(config = {}) {
8790
8915
  const mcp = setupMcp();
8791
8916
  if (mcp) context.registry.add(mcp);
8792
8917
  const getActiveAppId = () => {
8793
- const session3 = context.workspace.getSession();
8794
- const appInfo = session3?.appInfo;
8918
+ const session4 = context.workspace.getSession();
8919
+ const appInfo = session4?.appInfo;
8795
8920
  return appInfo?.appId ?? null;
8796
8921
  };
8797
8922
  if (context.bridge?.isNativeHost()) {